StateCell
A StateCell is the smallest state unit in the Nigo ledger. Rather than overwriting one global account object in place, Nigo represents state changes by spending and creating StateCells with distinct meanings.
The model combines the explicit input/output traceability of UTXO systems with EVM slot-based state execution on the same ledger state and commitment.
StateCell structure
A StateCell has four fields.
| Field | Format | Meaning |
|---|---|---|
id | Versioned binary StateCellId | Canonical key identifying the Cell in the ledger |
owner | 20-byte address | Owner or access principal for the Cell |
schemaHash | 32-byte hash | Structural hash identifying the value's shape and type |
value | Primitive value | The single primitive payload stored in the Cell |
Supported primitive types are:
UINT8, UINT64, UINT256, INT64, INT256,
ADDRESS, BOOL, BYTES4, BYTES32, BYTES, STRING
A StateCell does not store an entire general-purpose structure or array. Schema-backed composite state is decomposed into primitive leaves. EVM storage keeps each final 256-bit slot calculated by Solidity in one UINT256 StateCell.
StateCell ID V1
A StateCellId is a versioned binary protocol address, not a display name.
UINT8 formatVersion = 0x01
UINT8 domain
UINT8 subtype
BYTES body
The full ID is 3 to 255 bytes, and subtype 0 is unassigned. Its canonical hex representation includes every byte: version, domain, subtype, and body.
0x 01 | domain | subtype | body...
Human-readable IDs and metadata exposed through RPC are display projections. Transaction hashes, database keys, and state commitments use only the canonical binary ID.
Domains
| Domain | Code | Owned area |
|---|---|---|
GENERIC | 0x00 | Protocol-neutral IDs and Direct Cell outputs |
NATIVE_ASSET | 0x01 | Native Asset outputs—including NIGO—and supply state |
NATIVE_SYSTEM | 0x02 | Native Program identity, revisions, activation, and runtimes |
NATIVE_PROGRAM_STATE | 0x03 | Persistent state owned by Native Programs |
EVM | 0x04 | EVM storage slots, canonical nonces, and code references |
PROTOCOL | 0x05 | Chain-wide canonical configuration such as fees and consensus |
Registering a domain code and validating its business rules are separate concerns. nigo-state-cell preserves the canonical ID shape; the execution module that owns a domain validates meanings such as allowances, asset supply, EVM slots, and fee policy.
Three representative state patterns
Schema-backed state
General structures and arrays are decomposed into primitive leaves according to a schema.
AccountProfile
├── owner: ADDRESS -> StateCell A
├── enabled: BOOL -> StateCell B
└── limit: UINT256 -> StateCell C
Changing one field replaces only the changed leaf rather than storing the complete object again. A structured read batches the required leaves, validates the schema and completeness, and reconstructs the original value.
EVM storage
EVM storage does not use the schema-backed decomposer.
EvmStorageCellId(contractAddress, slot256)
-> UINT256 StateCell
The Solidity compiler and EVM calculate the final slot layout for structures, mappings, and arrays. Nigo does not decompose that slot back into logical fields, avoiding a duplicate definition of SLOAD and SSTORE semantics.
Native Assets
A Native Asset is represented as spendable outputs and supply state. NIGO does not have a separate ID namespace; it uses the zero asset ID in the NATIVE_ASSET domain. Per-asset controllers and Native Programs validate ownership, quantity conservation, mint/burn, or managed-transfer policy.
State lifecycle
The primary StateStore transitions are spend and create.
Even a logical value update spends the existing Cell and creates a replacement instead of mutating an internal object in place.
before
Cell ID X -> value 10
transition
spentIds: [X]
createdCells: [Cell ID X -> value 11]
after
Cell ID X -> value 11
If the same ID appears once in both the spent and created lists, the transition is a replacement. A new ID makes lineage between the previous and new outputs explicit.
applyBatch(spentIds, createdCells) atomically applies validated spends and creates as one state transition. It rejects creation of an already-active ID, spending a nonexistent or already-spent ID, and duplicate IDs within the batch.
Overlays and StateDelta
Transaction and block execution operate on BufferedStateStore overlays rather than immediately changing persistent storage.
Only a successful child overlay merges into its parent; failed execution is discarded. The final overlay result is normalized into a StateDelta ordered by canonical ID.
StateDelta
spentIds
createdCells
A Cell created and spent within the same overlay does not appear in the final delta. The state-commitment layer applies this delta to the previous root rather than rereading the entire active state.
Transaction lineage
A receipt records inputs read or consumed during execution, outputs created, and spent IDs. This allows state relationships to be classified as follows.
| Relationship | Meaning |
|---|---|
CREATING | A previously nonexistent StateCell was created by the transaction |
SPENDING | An existing StateCell was consumed and is no longer active |
MUTATING | EVM execution consumed a StateCell ID and recreated it as a replacement |
A Cell transaction records the relationship between declared inputs it consumes and outputs it creates. An EVM storage update can spend and replace the same slot ID and is therefore classified as a mutation.
StateCells and deterministic parallel execution
Explicit StateCell IDs form the unit for analyzing a transaction's read and write sets. Transactions that access only independent StateCells can execute against the same frozen state view. Conflicting transactions, or transactions whose access range cannot be proven completely, execute in canonical order.
Worker count and scheduling strategy are node-local optimizations. The final StateDelta, receipts, and state root must match the result of executing the same block sequentially.
Protocol limits
| Area | Current limit |
|---|---|
| StateCell ID | 255 bytes maximum |
| StateCell value | 16 MiB maximum |
| Schema depth | 64 maximum |
| Schema nodes | 4,096 maximum |
| Struct fields | 1,024 maximum |
| Array length | 100,000 maximum |
| Structured-state leaves | 100,000 maximum |
These limits protect consensus safety. A deployment profile may impose lower business or operational limits.
What StateCell does not imply
- Not every StateCell is a financial-asset UTXO.
- EVM account and storage semantics do not disappear; EVM state is persisted as StateCells.
owneralone does not determine every access right; domain-specific Core and VM rules also apply.- A human-readable friendly ID is not canonical identity.
- Implementing StateCell alone does not complete the entire storage lifecycle, pruning, or production approval.