Introduction

You can define storage variables to store and retrieve data in your contract. Storage in Cairo contracts is implemented as a key-value store using a struct marked with the #[storage] attribute. Every contract must have exactly one storage definition, which serves as the contract’s persistent state on the blockchain and is kept between contract executions.

Storage space & pointers

The contract’s storage space consists of 22512^{251} storage slots, where each slot:
  • Can store a single felt252 value
  • Is initialized to 0
Storage variables are stored in storage slots using Starknet’s memory model abstraction called storage pointers. A storage pointer is a tuple (base_address, offset) where:
  • base_address is the address of the first slot where the variable is stored
  • offset is the distance from the base address where the variable is stored
To get the base address of a storage variable, you can use the selector! macro to derive it from the variable name (i.e., selector!("variable§_name")).

Example

mod Contract {
    #[storage]
    struct Storage {
        a: u128,
        b: u8,
        c: u256,
    }
}
The storage layout of this contract is:
  • Variable a (u128):
    • Base address: selector!(”a”)`
    • Uses lowest 128 bits of the slot at offset 0
    • Leaves 124 bits unused
  • Variable b (u8):
    • Base address: selector!("b")
    • Uses lowest 8 bits of the slot at offset 0
    • Leaves 244 bits unused
  • Variable c (u256):
    • Base address: selector!("c")
    • Too large for a single slot, uses two consecutive slots:
      • First slot: lower 128 bits at offset 0
      • Second slot: lower 128 bits at offset 1
    • Leaves 248 bits unused, 124 in each slot
For more complex data structures, see storing custom types.
Notice how many bits are left unused in each slot? This can make storage operations expensive. To optimize storage usage, you can pack multiple variables together. Learn more in storage optimization.