Skip to main content
Three different things get called “state” in a trading engine, and confusing them is how systems end up with answers that depend on who you ask. This page separates them and says which one is authoritative.

Three representations

Engine statemarkets · accounts · positions · books · clearinghouselives across blocks · a reconstruction
Block working setmarks · touched accounts · fills · staged outputlives for one block · a journal
Chain stateversioned key-value, Merkle-authenticatedthe authority
The failure this preventsAn engine whose in-memory view has drifted from what was committed keeps serving answers, and every one of them is wrong in a way that only shows up at settlement.
engine state must be derivable from the committed record, never the other way round
Engine state is what the kernel holds between blocks: market metadata, accounts, positions, order books, instrument state, clearinghouse state. It is the working representation — laid out for the access patterns matching and clearing actually have, not for storage. The block working set exists only while a block executes: the marks fixed at the start, which accounts and orders were touched, the fills produced, the outputs being assembled. It is a journal of what happened during this block. Chain state is the committed result: versioned key-value entries, authenticated by a Merkle structure, durable and replayable. It is what a node syncs, what a proof is against, and what an indexer reads. Chain state is the authority. The block working set is a journal used to build deterministic output — not a source of truth. Engine state is a reconstruction of chain state optimized for execution; it must be derivable from the committed record, never the other way round. Getting this backwards is a specific, recognizable failure: an engine whose in-memory view has drifted from what was committed will keep serving answers, and every one of them will be wrong in a way that only shows up at settlement.

Keys

Chain state is addressed by key. Trading state is grouped into named, explicitly versioned namespaces — for example the fee configuration, the perpetual index, the leverage tier table, the administrative role list. The version suffix is not decoration. When the shape of a configuration changes, it moves to a new version of its key, and the previous key is retained so that state written under the old schema can still be read during migration. A reader that hard-codes one version and never re-checks will silently read stale configuration after a migration; a reader that resolves the current key will not.
This is why configuration should be read from the chain rather than pinned in client code. The fee tier service reads the live fee configuration on every cycle for exactly this reason — a tier table baked into a client is a table that will eventually disagree with the one the network is applying.

Versions

Every committed block advances a version. State values are stored against the version at which they were written, which means the store is not just “the current state” but “the state at any version.” That property is what makes several things possible at once:
  • Proofs can be produced against a specific version rather than only against the present.
  • Replay can start from any version, not just genesis.
  • Reads can be historical — an indexer reconstructing a position’s history is asking for old versions, not scanning a log.
  • Pruning becomes a policy decision about how far back to keep, rather than a structural limitation.

What ends up committed

Kernel execution produces two things per block. Each transaction carries its own writes and events, bound to it. Effects that belong to no single user transaction — funding flows, insurance movements, block-level counters — go to a distinguished system channel. Between the two, nothing is lost. There is no execution effect inside the kernel that is absent from both a transaction’s output and the system channel. That completeness is what allows the committed record to be treated as the whole story rather than a summary of it, and it is the reason an event can be traced back to the transaction that caused it even when matching ran as a batch.

Where to go next

Storage and proofs

How committed state is physically stored, authenticated, and pruned.

State sync

How a node that has never seen the chain catches up to it.

IntentionKernel

Where engine state and the block working set live.

Indexer

Turning committed state into something queryable.