Appearance
State APIs
This page documents the four state Hook APIs: the functions that read and write a hook's persistent key/value storage, both on the hook's own account and — with an explicit grant — on other accounts.
All function signatures on this page match the Hook API.
Return codes reference the shared error table in ../../glossary, and the values quoted below match the Hook API's error definitions.
The implementation uses WASM-facing wrappers and a state cache.
What Hook State is
Hook State is a persistent key/value store attached to an account. Each stored entry is addressed by a triple:
- Account — whose ledger the entry lives on. For
state/state_setthis is always the account the hook is installed on (hook_account). For the_foreignvariants you name the account explicitly. - Namespace — a 32-byte (
uint256) tag that partitions an account's state. Each hook runs with a current namespace (sfHookNamespace).state/state_setand the_foreignvariants with a zero-length namespace use that current namespace; otherwise you pass a 32-byte namespace. - Key — a 32-byte key. Keys shorter than 32 bytes are accepted and zero-padded on the left to 32 bytes: the key
"key"is stored as 29 zero bytes followed by the three ASCII bytes. A key must be 1..32 bytes; 0 bytes returnsTOO_SMALLand more than 32 returnsTOO_BIG.
Each entry is a HookState ledger object (ltHOOK_STATE) identified by its account, key, and namespace.
Value size
A state value may be up to the scaled state-data limit.
- The base limit is 256 bytes.
- An account may raise it with
sfHookStateScale(1..16); the limit is256 * scale, i.e. up to 4096 bytes at scale 16. Accounts withoutsfHookStateScaleuse scale 1 (256 bytes).
Writing more than the limit returns TOO_BIG. The scale is read from the account object at write time.
State entries cost reserve
Creating a new state entry consumes owner reserve. The first time an account is touched in a hook execution, the implementation computes how many reserve increments the account can still afford:
availableForReserves = (balance - accountReserve(ownerCount)) / feeIncrementEach new entry consumes scale reserve positions. If the account cannot afford the next entry the write fails with RESERVE_INSUFFICIENT (-38). Overwriting an existing entry does not consume additional reserve. Deleting an entry (see state_set below) frees it.
Namespaces
An account may hold at most 256 namespaces.
Creating a state entry in a brand-new namespace counts against this limit and returns TOO_MANY_NAMESPACES (-45) if exceeded. The new-namespace accounting is gated behind the fixXahauV1 amendment.
Two distinct "too many modifications" limits
There are two separate limits on how much state a single transaction may change, and they are enforced at different points:
- Per-execution cache limit — 256. A write is rejected with
TOO_MANY_STATE_MODIFICATIONS(-44) once 256 entries have been modified within the current hook's state cache. - Combined-chain write limit. When state is finally flushed to the ledger, modified entries are counted across the combined hook chains, and the transaction returns
tecHOOK_REJECTEDif the count exceeds the 256-entry limit. TheTOO_MANY_STATE_MODIFICATIONS(-44) error is raised by this same 256-entry limit. Treat 256 as the operative figure for both mechanisms above.
Index
| Function | Purpose |
|---|---|
state | Read state under the hook account's current namespace. |
state_set | Write (or delete) state under the hook account's current namespace. |
state_foreign | Read state from a specified account and namespace. |
state_foreign_set | Write state on another account's namespace (requires a grant). |
Related documents
- ../../README — documentation index.
- ../../overview — hook execution model and lifecycle.
- ../../glossary — full error-code and term reference.
- ../../macros —
SBUF,SVAR,UINT64_TO_BUF, and other helpers. - ../../best-practices — structuring state access and reserve budgets.
- control —
hook_account,accept/rollback, and namespaces context. - transaction — reading fields off the originating transaction.
- ledger-and-slot — slots and ledger info.
- utility —
util_keylet,util_accid, STO helpers. - ../../examples/state-counter — a persistent counter hook.
- ../../examples/foreign-state — cross-account state with grants.