Documentation Index
Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
Use this file to discover all available pages before exploring further.
StateRoot
32-byte Merkle Patricia Trie root hash representing global Ethereum state.
Overview
StateRoot represents the root hash of the Ethereum state trie. It uniquely identifies the entire global state at a given block - all account balances, nonces, contract code, and storage. Every block header includes a state root.
Type Definition
type StateRootType = Uint8Array & {
readonly __tag: "StateRoot";
readonly length: 32;
};
type StateRootLike = StateRootType | string | Uint8Array;
const SIZE = 32;
Usage
Create StateRoot
import * as StateRoot from './primitives/StateRoot/index.js';
// From hex string
const root = StateRoot.fromHex("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421");
// From Uint8Array
const bytes = new Uint8Array(32);
const root2 = StateRoot.from(bytes);
Convert to Hex
const hex = StateRoot.toHex(root);
// "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
Compare State Roots
const isEqual = StateRoot.equals(root1, root2);
API Reference
Constructors
| Function | Description |
|---|
from(bytes) | Create from Uint8Array |
fromHex(hex) | Create from hex string |
Methods
| Function | Description |
|---|
toHex(root) | Convert to hex string |
equals(a, b) | Check equality |
Constants
| Constant | Value | Description |
|---|
SIZE | 32 | State root size in bytes |
State Trie Structure
The Ethereum state is a Merkle Patricia Trie mapping addresses to account states:
State Root (32 bytes)
|
v
Merkle Patricia Trie
|
+-- Address A --> Account State A
| - nonce
| - balance
| - codeHash
| - storageRoot
|
+-- Address B --> Account State B
...
Every block header contains a state root:
type BlockHeader = {
parentHash: Hash;
stateRoot: StateRoot; // <-- This represents all state
transactionsRoot: Hash;
receiptsRoot: Hash;
// ...
};
Empty State Root
The empty state root (no accounts) has a known value:
// Empty trie root = keccak256(RLP(null))
const EMPTY_STATE_ROOT = StateRoot.fromHex(
"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
);
Use Cases
// Get block header (from trusted source)
const header = await provider.getBlock("latest");
// Get state proof
const proof = await provider.send("eth_getProof", [address, [], "latest"]);
// Verify proof against header's state root
const isValid = verifyStateProof(proof, header.stateRoot);
Track State Changes
// Compare state roots between blocks
const block1 = await provider.getBlock(1000000);
const block2 = await provider.getBlock(1000001);
const stateChanged = !StateRoot.equals(
StateRoot.fromHex(block1.stateRoot),
StateRoot.fromHex(block2.stateRoot)
);
Light Client Sync
// Light client stores only block headers
const headers = [header1, header2, ...];
// To verify any state claim, check proof against stateRoot
function verifyBalance(address: string, balance: bigint, proof: StateProof): boolean {
const header = findHeader(proof.blockNumber);
return verifyProof(proof, header.stateRoot);
}
Specification
Per the Yellow Paper, the state trie encodes mappings from addresses (160-bit identifiers) to account states. The state root is a 32-byte Keccak-256 hash of the root node of the state trie.
See Also