State Variables
A contract's state is defined by multiple values. For example, in a token contract, these include the total supply, user balances, outstanding approvals, accounts with minting permission, etc. Each of these persisting values is called a state variable.
One of the first design considerations for any smart contract is how it'll store its state. This is doubly true in Aztec due to there being both public and private state - the tradeoff space is large, so there's room for lots of decisions.
Choosing the right storage type
| Need | Use |
|---|---|
| Public value anyone can read/write | PublicMutable |
| Public value set once (contract name, decimals) | PublicImmutable |
| Public key-value mapping | Map<K, PublicMutable<V>> |
| Private collection per user (token balances) | Owned<PrivateSet<...>> |
| Single private value per user | Owned<PrivateMutable<...>> |
| Immutable private value per user | Owned<PrivateImmutable<...>> |
| Contract-wide private singleton (admin key) | SinglePrivateMutable |
| Public value readable in private execution | DelayedPublicMutable |
Prerequisites
- An Aztec contract project set up with
aztec-nrdependency - Understanding of Aztec's private and public state model
- Familiarity with Noir struct syntax
For storage concepts, see storage overview.
The Storage Struct
State variables are declared in Solidity by simply listing them inside of the contract, like so:
contract MyContract {
uint128 public my_public_state_variable;
}
In Aztec.nr, we define a struct that holds all state variables. This struct is called the storage struct, and it is identified by having the #[storage] macro applied to it.
use aztec::macros::aztec;
#[aztec]
contract MyContract {
use aztec::macros::storage;
#[storage]
struct Storage<Context> {
// state variables go here e.g, the admin of the contract
admin: PublicMutable<AztecAddress, Context>,
}
}
This struct must also have a generic type called C or Context - an unfortunate boilerplate parameter that provides execution mode information.
The #[storage] macro can only be used once, so all contract state must be in a single struct.