#[storage_item]Expand description
Prepares the type to be fully compatible and usable with the storage.
It implements all necessary traits and calculates the storage key for types.
Packed types don’t have a storage key, but non-packed types (like Mapping, Lazy
etc.) require calculating the storage key during compilation.
Consider annotating structs and enums that are intended to be a part of the storage with this macro. If the type is packed then the usage of the macro is optional.
If the type is non-packed it is best to rely on automatic storage key
calculation via ink::storage_item.
The usage of KEY: StorageKey generic allows to propagate the parent’s storage key to
the type and offset the storage key of the type. It is helpful for non-packed types
that can be used several times in the contract. Each field should have a unique
storage key, so propagation of the parent’s storage key allows one to achieve it.
The macro should be called before derive macros because it can change the type.
All required traits can be:
- Derived manually via
#[derive(...)]. - Derived automatically via deriving of
scale::Decodeandscale::Encode. - Derived via this macro.
§Example
§Trait implementation
use ink_prelude::vec::Vec;
use ink::storage::{
Lazy,
Mapping,
};
use ink::storage::traits::{
StorageKey,
StorableHint,
};
use ink::storage::traits::Storable;
// Example of how to define a packed type.
#[ink::storage_item(packed)]
#[derive(Default, Debug)]
struct Packed {
s1: u128,
s2: Vec<u128>,
// Fails because `StorableHint` is only implemented for `Vec` where `T: Packed`.
// s3: Vec<NonPacked>,
}
// Example of how to define the packed type with generics.
#[ink::storage_item(packed)]
#[derive(Default, Debug)]
struct PackedGeneric<T: ink::storage::traits::Packed> {
s1: (u128, bool),
s2: Vec<T>,
s3: String,
}
// Example of how to define the non-packed type.
// Note: `packed` argument defaults to `false`, so it can be omitted for non-packed types,
// so the definition below is equivalent to `#[ink::storage_item(packed = false)]`.
#[ink::storage_item]
#[derive(Default, Debug)]
struct NonPacked {
s1: Mapping<u32, u128>,
s2: Lazy<u128>,
}
// Example of how to define the non-packed generic type.
#[ink::storage_item]
#[derive(Default, Debug)]
struct NonPackedGeneric<T>
where
T: Default + core::fmt::Debug,
T: ink::storage::traits::Packed,
{
s1: u32,
s2: T,
s3: Mapping<u128, T>,
}
// Example of how to define the non-packed generic type with manually derived storage traits.
#[ink::storage_item(derive = false)]
#[derive(Storable, StorableHint, StorageKey)]
#[cfg_attr(
feature = "std",
derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout)
)]
#[derive(Default, Debug)]
struct NonPackedGenericManual<T>
where
T: Default + core::fmt::Debug,
T: ink::storage::traits::Packed,
{
s1: u32,
s2: T,
s3: Mapping<u128, T>,
}
// Example of how to define a complex packed type.
#[ink::storage_item(packed)]
#[derive(Default, Debug)]
struct PackedComplex {
s1: u128,
s2: Vec<u128>,
s3: Vec<Packed>,
}
// Example of how to define a complex non-packed type.
#[ink::storage_item]
#[derive(Default, Debug)]
struct NonPackedComplex<KEY: StorageKey> {
s1: (String, u128, Packed),
s2: Mapping<u128, u128>,
s3: Lazy<u128>,
s4: Mapping<u128, Packed>,
s5: Lazy<NonPacked>,
s6: PackedGeneric<Packed>,
s7: NonPackedGeneric<Packed>,
// Fails because: the trait `ink::storage::traits::Packed` is not implemented for `NonPacked`
// s8: Mapping<u128, NonPacked>,
}§Header Arguments
The #[ink::storage_item] macro can be provided with an additional comma-separated
header argument:
-
packed: flagStorage items flagged as
packeduse “packed” layout .Usage Example:
use ink::storage::Mapping; #[ink::storage_item(packed)] struct PackedGeneric<T: ink::storage::traits::Packed> { s1: (u128, bool), s2: Vec<T>, s3: String, }Default value: not set. Note: The default behavior is to use “non-packed” layout, and automatically derive storage keys for each field.
-
derive: boolThe
deriveconfiguration parameter is used to enable/disable auto deriving of all required storage traits.Usage Example:
use ink::storage::Mapping; use ink::storage::traits::{ StorableHint, StorageKey, Storable, }; #[ink::storage_item(derive = false)] #[derive(StorableHint, Storable, StorageKey)] struct NonPackedGeneric<T: ink::storage::traits::Packed> { s1: u32, s2: Mapping<u128, T>, }Default value: true.