Step-Scoped State
Definition
A step is a discrete, sequential interval identified by a monotonically increasing u64. Rs defines the step contract — the interface between a cell and its runtime:
current_step() -> u64— returns the current step numberreset_step_state()— called by the runtime at the boundary between step N and step N+1
Rs enforces: step state is only accessed within cell context (RS401), and #[step] generates correct reset implementations.
Rs does not define: what triggers step transitions, how long a step lasts, or how steps relate to external events (blocks, time intervals, signals). The runtime provides the step driver.
Problem
Long-running systems accumulate state. A variable set in step N might still be non-zero in step N+1000 because someone forgot to clear it. This is a source of non-determinism and state leaks.
Solution
The #[step] attribute marks state that is automatically reset at step boundaries.
Syntax
static PENDING_TXS: =
new;
static VOTES_THIS_ROUND: AtomicU32 = new;
Semantics
The runtime calls StepState::reset() at the beginning of each step. This is injected by the cell infrastructure, not by user code.
On statics
// Compiler generates this trait impl for every #[step] static:
// At step boundary (generated by cell! macro):
On structs
When #[step] is placed on a struct (as used in cell! generated code for step_state blocks), it generates a StepReset impl that resets all fields:
// Generated:
Reset rules by field type:
| Type | Reset to |
|---|---|
BoundedVec<T, N> |
clear() |
BoundedMap<K, V, N> |
clear() |
Option<T> |
None |
AtomicU32 / AtomicU64 |
store(0) |
bool |
false |
| Integer types | 0 |
| Custom types | must implement StepReset |
Compile-Time Checks
In edition = "rs", accessing a #[step] variable outside of a step context is an error:
static COUNTER: AtomicU64 = new;
// OK: inside a cell function (has step context)
cell!
// ERROR: outside cell context
Implementation: ~300 lines (attribute handling + lint pass).
Error Reference
See errors/step.md for detailed description of RS401.