Explicit Storage Access in Cairo 1.x Makes State Mutations Auditable
Cairo 1.x makes state mutations auditable by declaring storage with #[storage] and forcing explicit self.storage.field.read() and .write() calls. This declarative model improves reviewability, serialization safety, and interface clarity.
23 Feb 2026, 05:35 UTC

The concrete problem is tracing where on-chain state changes. In a contract with many functions, implicit writes make it hard to prove a call is read-only or to audit which fields a function touches. Cairo 1.x answers this with a declarative storage model: state is declared once with #[storage], and every read or write is explicit via self.storage..read() and .write(). That makes mutations visible in code review and tooling.
Declarative storage with explicit access
Cairo 1.x contracts define persistent state as a #[storage] annotated struct. Fields are typically Map and Array types that map to StarkNet storage slots. Access is not field assignment; it is a method call on the storage proxy.
#[storage]
struct Storage {
balances: Map<ContractAddress, u256>,
total_supply: u256,
}
#[external]
fn deposit(ref self: ContractState, amount: u256) {
let caller = get_caller_address();
let current = self.storage.balances.entry(caller).read();
self.storage.balances.entry(caller).write(current + amount);
self.storage.total_supply.write(self.storage.total_supply.read() + amount);
}
#[view]
fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {
self.storage.balances.entry(account).read()
}
The read/write methods make data flow explicit. A reviewer can scan a function and see exactly which storage slots are touched, and static analysis can distinguish read-only paths from state-changing paths.
Serialization safety for on-chain data
Data that crosses the contract boundary or is stored must implement Serde and Drop for deterministic encoding to Sierra. Engineering practice is to derive these traits for storage structs, event payloads and calldata types.
#[derive(Drop, Serde)]
struct Transfer {
from: ContractAddress,
to: ContractAddress,
amount: u256,
}
Deriving Serde guarantees a stable, declaration-order encoding. Removing Serde/Drop or changing field order can break upgrade compatibility and on-chain state decoding because the compiler derives the layout from the struct definition.
Interface clarity with entry points
External entry points are marked #[external], read-only queries #[view], and constructors #[constructor]. This creates a clear interface boundary that tooling uses to generate ABI and to enforce read-only execution.
A practical check is to inspect the compiled JSON ABI after building the project. In the project root run:
scarb build
Required permissions are normal file system access in the project directory. Expected checks are the presence of target dir artifacts and an abi.json where #[view] functions are marked state_mutability: view and #[external] functions are marked external. The risk is that renaming or reordering storage members changes the derived layout; upgrades must preserve declaration order or use a migration strategy.
Trade-off and limitation
The explicit model improves auditability at the cost of verbosity. Every storage interaction is a method call, and storage layout is compiler derived. Changing field order, renaming storage members, or removing Serde/Drop can silently break state decoding for upgraded contracts. Gas metering and built-in primitives such as Pedersen and EC operations are version sensitive across Cairo and StarkNet releases.
A reproducible way to reason about resource usage is to write tests with #[available_gas] that perform storage reads and writes on a Map and assert expected state transitions using the testing harness. This keeps resource assumptions explicit without claiming a specific gas number.
Use #[storage] to declare state once, access it only via explicit read/write, derive Serde and Drop for all on-chain types, and mark entry points with #[external]/#[view]/#[constructor]. Then verify the ABI for read-only markers and keep storage declaration order stable across upgrades.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.