Skip to content

Storage Layout

DISCLAIMER // NFA // DYOR

This analysis is based on observations of the contract behavior. We are not smart contract security experts. This document aims to explain what the contract appears to do based on the code. It should not be considered a comprehensive security audit or financial advice. Always verify critical information independently and consult with blockchain security professionals for important decisions.

⊙ generated by robots | curated by humans

METADATA
Contract Address 0x82eb1246...90cC37 (etherscan)
Network Ethereum Mainnet
Analysis Date 2026-06-02

Variables

All persistent state lives in slots 0–25. The contract's configuration is held in immutable/constant fields, which the compiler embeds in bytecode rather than storage — so the relay address, verifiers, denominations, asset id, and tree constants occupy no storage slot. The inherited ReentrancyGuardTransient lock uses EIP-1153 transient storage, which also consumes no persistent slot.

Values below were read on-chain at analysis date via cast storage.

SLOT VARIABLE NAME TYPE CURRENT VALUE PURPOSE
0 _pools mapping(bytes32 => Pool) 0x0 (base) Per-pool state, keyed by pid = keccak256(ASSET_ID, denomination). Members live at keccak-derived slots (see below)
1 totalBalance uint256 90000000000000 (9e13 wei) Aggregate escrowed ETH; the solvency gate for withdrawals
2 poolVerifiers mapping(bytes32 => IPoolRootVerifier) 0x0 (base) Pool → bound SP1 pool-root verifier (all 8 → 0x42Ab3d9d...2a3CCb (etherscan))
3 everKnownRoot mapping(bytes32 => mapping(bytes32 => bool)) 0x0 (base) Pool → root → was-ever-current flag
4 rootAccumulator mapping(bytes32 => bytes32) 0x0 (base) Pool → running SHA-256 of all historical roots (read by the SP1 verifier)
5 poolIds bytes32[] length 8 Enumerable list of the 8 pool ids
6 zeros[0] bytes32 0x0 Empty-subtree hash at level 0 (the zero leaf)
7 zeros[1] bytes32 0x2098f5fb...b64864 Poseidon(0,0) — canonical empty-subtree hash at level 1
8–24 zeros[2..18] bytes32 precomputed Empty-subtree hashes, each Poseidon(zeros[i-1], zeros[i-1])
25 zeros[19] bytes32 0x1830ee67...f72cca Empty-subtree hash at level 19 (top precomputed level)

Pool struct (value type of _pools)

Each pool's fields are laid out sequentially from its base slot keccak256(pid . 0):

OFFSET FIELD TYPE PURPOSE
+0 denomination uint256 Wei denomination; 0 means "pool does not exist"
+1 nextLeafIndex uint256 Count of deposited leaves (deposit-tree fill level)
+2 currentRoot bytes32 Latest deposit Merkle root
+3 verifierDenomIdx uint8 Index of this denom in the SP1 verifier's array (packed in the same slot)
+4 filledSubtrees mapping(uint256 => bytes32) Cached right-edge subtree hashes for incremental insertion
+5 burnNullifiers mapping(bytes32 => bool) Spent burn nullifiers (double-spend guard)
+6 commitments mapping(bytes32 => bool) Used deposit commitments (duplicate guard)

Storage notes

  • ◇ The mapping bases (slots 0, 2, 3, 4) read as zero — expected, since mapping contents hash to derived slots, not the base slot.
  • zeros[] is a 20-entry fixed array filling slots 6–25 contiguously; zeros[1] matching the well-known Poseidon(0,0) constant 0x2098f5fb… confirms the tree hash is Poseidon Hash, the same primitive used inside the withdrawal SNARK.
  • ☑ No storage slot holds an owner, admin, or pause flag — consistent with the role-free design.

Diagrams

graph TB
    subgraph Core["Core State — Slots 0-4"]
        S0["Slot 0: _pools mapping (base)"]
        S1["Slot 1: totalBalance — 9e13 wei"]
        S2["Slot 2: poolVerifiers mapping"]
        S3["Slot 3: everKnownRoot mapping"]
        S4["Slot 4: rootAccumulator mapping"]
    end

    subgraph List["Enumerable — Slot 5"]
        S5["Slot 5: poolIds[] — length 8"]
    end

    subgraph Zeros["Precomputed Empty-Subtree Hashes — Slots 6-25"]
        S6["Slot 6: zeros[0] = 0x0"]
        S7["Slot 7: zeros[1] = Poseidon(0,0)"]
        S25["Slot 25: zeros[19]"]
    end

    subgraph Derived["Hash-Derived (per pool)"]
        P["Pool struct: denomination, nextLeafIndex,<br/>currentRoot, verifierDenomIdx,<br/>filledSubtrees, burnNullifiers, commitments"]
    end

    Core --> List --> Zeros
    S0 -.->|"keccak256(pid . 0)"| Derived

    style S1 fill:#ffe1e1
    style S0 fill:#e1e8ff