aztec-nr - noir_aztec::state_vars
Module state_vars
Structs
- Mutable public values with private read access.
- A key-value container for state variables.
- Per-account state variable.
- Per-account immutable private state.
- Per-account mutable private state.
- Per-account aggregated private state.
- Immutable public values.
- Mutable public values.
- Contract-wide immutable private state.
- Contract-wide mutable private state.
- Private right to perform an action.
- Exported storage layout definition.
Traits
- A trait that defines the interface for Aztec state variables that have an owner. Unlike regular state variables, owned state variables need to be wrapped in
Ownedstate variable when placed in storage: - A container for contract state.
Storage for contract state.
Contracts store their state in state variables. In Solidity, a state variable is simply any value declared inside a contract, e.g.
contract Token { uint256 totalSupply; }, and they can be one of many kinds (primitive values, mappings, arrays, immutable, etc.).Due to Aztec contracts being able to store both public and private state, there are many more different types of state variables, each with their nuance and use cases. Understanding these is key to understanding how a contract works.
Declaration
All of a contract's state variables, both public and private, are declared in a single place: as members of a struct to which the
#[storage]macro is applied.Choosing a State Variable
The very first question to answer is whether the contents of the variable should be public (everyone in the network can see their contents, like Solidity state variables), or private (only some people know what is stored in them).
Public State Variables
Public state variables typically store their contents in the public storage tree, and can therefore only be written to by public contract functions.
PublicMutablePublicImmutableDelayedPublicMutablePrivate State Variables
Private state variables typically store their contents in the note and nullifier trees, and are therefore mainly interacted with from private contract functions.
PrivateMutablePrivateImmutablePrivateSetStorage Slots
Each state variable in a contract gets assigned a unique storage slot, which isolates the different variables so that reads and writes to one do not interfere with others.
Storage slot allocation is automatic and cannot be overridden. A state variable's storage slot can be queried via
crate::state_vars::StateVariable::get_storage_slot.The Context Parameter
All state variables take a generic
Contextparameter, which will be set to one ofPrivateContext,PublicContextorUtilityContextdepending on the contract function type. This leads to some unfortunate boilerplate when declaring contract storage.Different methods are available depending on the context, reflecting that certain actions can only be performed in some or other context. For example,
PublicMutable'sreadfunction is available under bothPublicContextandUtilityContext, but notPrivateContextsincePublicMutablecannot be read from private functions. Similarly,writeis only available inPublicContext.Packing for Efficient Access
Because all state variables are fully independent, when a contract reads or writes one of them all others are left untouched. This is good for isolation, but in some cases users may want to group variables together for more efficient access, for example to access multiple values in a single storage read or write.
The pattern to follow is to group related values in a
struct, just like in Solidity. How values are packed inside thisstructis governed by thecrate::protocol::traits::Packabletrait, which must be#[derive]'d or manually implemented - see thePackable's docs on how to do this.Note that private state variables and public ones that can be read from private (like
PublicImmutableandDelayedPublicMutable) benefit from packing multiple values in the samestructeven if there is no need for tight packing (e.g. if all values areFields), since they often work by reading the hash of the entire value. Many values in the samestructwill result in a single hash, and therefore a single read.