storage

Storage-related types and traits for Cairo contracts.This module implements the storage system for Starknet contracts, providing high-level abstractions for persistent data storage. It offers a type-safe interface for reading and writing to Starknet storage through the StoragePointerReadAccess and StoragePointerWriteAccess traits, along with useful storage-only collection types like Vec and Map.Vec: starknet::storage::vec::Vec Map: starknet::storage::map::Map # OverviewThe storage system in Starknet contracts is built on a key-value store where each storage slot is identified by a 251-bit address. The storage system allows interactions with storage using state variables, which are declared inside a Storage struct annotated with the #[storage] attribute. This ensures type-safe storage access and simplifies the process of reading and writing to storage. # Using the Storage SystemStorage is typically declared using the #[storage] attribute on a struct:

[storage]
struct Storage {
    balance: u256,
    users: Map<ContractAddress, User>,
    nested_data: Map<ContractAddress, Map<ContractAddress, u8>>,
    collection: Vec<u8>,
}

Any type that implements the Store trait (or it's optimized StorePacked variant) can be used in storage. This type can simply be derived using #[derive(Store)] - provided that all of the members of the type also implement Store.

[derive(Copy, Default, Drop, Store)]
struct User {
    name: felt252,
    age: u8,
}

Interaction with storage is made through a set of traits, depending on the type interacted with:StoragePointerReadAccess and StoragePointerWriteAccess allow for reading and writing storable types. - StorageMapReadAccess and StorageMapWriteAccess allow for reading and writing to storage Maps. - StoragePathEntry allows for accessing a specific entry in a Map, and can be combined with the StoragePointer traits to read and write in these entries. - VecTrait and MutableVecTrait allow for interacting with storage Vecs.VecTrait: starknet::storage::vec::VecTrait MutableVecTrait: starknet::storage::vec::MutableVecTrait StorageMapReadAccess: starknet::storage::map::StorageMapReadAccess StorageMapWriteAccess: starknet::storage::map::StorageMapWriteAccess StoragePathEntry: starknet::storage::map::StoragePathEntry ## Examples

fn use_storage(self: @ContractState) {
    let address = 'address'.try_into().unwrap();
    // Reading values
    let balance = self.balance.read();
    // For a `Map`, use the `entry` method to access values at specific keys:
    let user = self.users.entry(address).read();
    // Accessing nested `Map`s requires chaining `entry` calls:
    let nested = self.nested_data.entry(address).entry(address).read();
    // Accessing a specific index in a `Vec` requires using the `index` method:
    let element = self.collection[index];

    // Writing values
    self.balance.write(100);
    self.users.entry(address).write(Default::default());
    self.nested_data.entry(address).entry(address).write(10);
    self.collection[index].write(20);
}

Storage LifecycleWhen you access a storage variable, it goes through several transformations:FlattenedStorage: The starting point is your contract's storage struct. Each member is represented either as a StorageBase or another FlattenedStorage (for #[substorage(v0)] or #[flat] members).StorageBase: For simple variables, this holds the sn_keccak hash of the variable name, which becomes the storage address. For example:

#[storage]
struct Storage {
    balance: u128,  // Stored at sn_keccak('balance')
}

StoragePath: For complex types, a StoragePath represents an un-finalized path to aspecific entry in storage. For example, a StoragePath for a Map can be updated withspecific keys to point to a specific entry in the map.StoragePointer: The final form, pointing to the actual storage location. For multi-slotvalues (like structs), values are stored sequentially from this address. # Storage CollectionsCairo's memory collection types, like Felt252Dict and Array, can not be used in storage.Consequently, any type that contains these types can not be used in storage either.Instead, Cairo has two storage-only collection types: Map and Vec.Instead of storing these memory collections directly, you will need to reflect them intostorage using the Map and Vec types. # Address CalculationStorage addresses are calculated deterministically:For a single value variable, the address is the sn_keccak hash of the variable name's ASCIIencoding. sn_keccak is Starknet's version of the Keccak-256 hash function, with its outputtruncated to 250 bits.For variables composed of multiple values (tuples, structs, or enums), the base storageaddress is also the sn_keccak hash of the variable name's ASCII encoding. The storage layoutthen varies depending on the specific type. A struct will store its members as a sequence ofprimitive types, while an enum will store its variant index, followed by the members of thevariant.For variables within a storage node, the address is calculated using a chain of hashes thatrepresents the node structure. Given a member m within a storage variable variable_name,the path is computed as h(sn_keccak(variable_name), sn_keccak(m)), where h is the Pedersenhash. For nested storage nodes, this process repeats, creating a hash chain representing thepath to each leaf node. At the leaf node, the storage calculation follows the standard rules forthat variable type.For Map or Vec variables, the address is calculated relative to the storage baseaddress (the sn_keccak hash of the variable name) combined with the mapping keys or vectorindices.See their respective module documentation for more details.

Fully qualified path: core::starknet::storage

Structs

Traits

Impls