Custom Data Structures
Last updated
Was this helpful?
Last updated
Was this helpful?
The ink_storage
crate provides useful utilities and data structures to organize and manipulate the contract's storage. However, contract authors should know that they can also create their own custom data structures.
Any custom type wanting to be compatible with ink! storage must implement the trait, so it can be SCALE and . Additionally, the traits and are required as well. But don't worry, usually these traits can just be derived:
Even better: there is a macro , which derives all necessary traits for you. If there is no need to implement any special behavior, the above code example can be simplified further as follows:
Naturally, you can as well implement any required trait manually. Please directly refer to the relevant trait documentations for more information.
NOTE
Types with custom implementations of the ink! storage traits can still use this macro only for key calculation by disabling the derives: #[ink::storage_item(derive = false)].
Let's say you want a mapping where accessing a non-existent key should just return it's default value, akin to how mappings work in Solidity. Additionally, you want to know how many values there are in the mapping (its length). This could be implemented as a thin wrapper around the ink! Mapping
as follows:
CAUTION
Generic data types may substantially increase your contracts overall code size, making it more costly to store on-chain.
The #[ink::storage_item]
macro is responsible for storage key calculation of non- types. Without it, the key for non-Packed
fields will be zero. Using this macro is necessary if you don't plan to use a on a non-Packed
type.
It is possible to use generic data types in your storage, as long as any generic type satisfies the required storage trait bounds. In fact, we already witnessed this in the previous sections about the .
The reason for this is .