Storage Derives
StorageRoot - Top-Level Contract Storage
Every contract has exactly oneStorageRoot:
.init(ctx)method to initialize storage- Accessible via
ctx.model()
Storage - Nested Structures
For structures nested within your storage root:- Same accessors as
StorageRootbut without.init() - Used for nested data structures
Store and Model
#[derive(Store)] - Generates only persistence methods (__set())
#[derive(Model)] - Generates only read/write accessor types (*Model, *WriteModel)
Most contracts only need StorageRoot and Storage.
Type Constraints
Supported Storage Types
Primitive types:u64,s64,bool,String
Integer- Arbitrary precision (256-bit)Decimal- Arbitrary precision with decimalsContractAddress- References to other contracts
- Enums and structs with
#[derive(Storage)]or#[derive(Wavey)] Option<T>where T is a supported typeMap<K, V>where K:ToString+FromString, V is a supported type
Not Directly Supported
Vec - UseMap<u64, T> as workaround:
- No
u32,u16,u8→ Useu64 - No
f64,f32→ UseDecimal
Working with Basic Fields
Working with Options
Working with Maps
Maps provide key-value storage:Map API
For read-only access (ViewContext):Map Initialization with Data
Nested Structures
Storage structures can be nested arbitrarily deep:Updating Nested Fields with Closures
Storage Key Scoping
Keys are scoped by path, preventing collisions:map_a and map_b are independent—they can have the same key without collision.
Gas Considerations
Storage operations consume gas: General guidance:- Storage writes are more expensive than reads
- Minimize storage writes
- Cache reads when accessing multiple times
- Use lazy evaluation (models load only what you access)
- Map iterations over many keys can be expensive