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 0x090D4613473dEE047c3f2706764f49e0821D256e (etherscan)
Network Ethereum Mainnet
Analysis Date 2026-03-19

Variables

This contract has a minimal storage footprint. The two key configuration values (token and merkleRoot) are declared immutable and are embedded directly in the contract bytecode — they do not occupy storage slots.

The only storage used is the packed bitmap for tracking claimed indices.

Immutable Variables (In Bytecode)

VARIABLE TYPE VALUE PURPOSE
token address 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984 UNI token address
merkleRoot bytes32 0xc8500f8e2fcf3c9a32880e1b973fb28acc88be35787a8abcf9981b2b65dbdeb5 Root hash of the eligibility Merkle tree

Storage Variables

SLOT VARIABLE NAME TYPE CURRENT VALUE (SAMPLE) PURPOSE
0 (base) claimedBitMap mapping(uint256 => uint256) N/A (mapping base) Packed bitmap tracking which indices have been claimed

The claimedBitMap is the contract's only storage mapping. Each key represents a "word" covering 256 indices:

  • Key 0 covers indices 0–255
  • Key 1 covers indices 256–511
  • Key N covers indices (N×256) through (N×256 + 255)

Each bit within the 256-bit word represents one index. A set bit (1) means claimed; unset (0) means unclaimed.

Verified Storage Values

The storage slot for claimedBitMap[0] (indices 0–255) is computed as:

keccak256(abi.encode(0, 0)) = 0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5

Current value at that slot:

0xfffff7fdffffbeffffffbfff7fffffbffffff7fffff7fffffdfffffffffffffe

This value is nearly all 1s, indicating that most indices in the 0–255 range have been claimed. The few zero bits correspond to unclaimed indices (e.g., index 0 — bit 0 is 0, confirmed by isClaimed(0) returning false).


Diagrams

graph TB
    subgraph Bytecode["Immutable Variables (In Bytecode)"]
        T["token: 0x1f9840a8...01F984<br/>(UNI)"]
        MR["merkleRoot: 0xc8500f8e...dbdeb5"]
    end

    subgraph Storage["Storage — Slot 0 (Mapping Base)"]
        BM["claimedBitMap<br/>mapping(uint256 => uint256)"]
    end

    subgraph BitPacking["Bit Packing Detail"]
        W0["Word 0: indices 0-255<br/>0xfffff7fd...fffffffe"]
        W1["Word 1: indices 256-511"]
        WN["Word N: indices N×256 to N×256+255"]
    end

    Bytecode -.->|"read at zero gas cost<br/>(embedded in code)"| Storage
    BM --> W0
    BM --> W1
    BM --> WN

    style T fill:#ff007a20,stroke:#ff007a
    style MR fill:#ff007a20,stroke:#ff007a
    style W0 fill:#ffe1e1

Bit Packing Visualization

Each uint256 word in the bitmap stores 256 claim statuses:

Word 0 (indices 0-255):
Bit:   255  254  253  ...  2   1   0
       ┌────┬────┬────┬───┬───┬───┬───┐
       │ 1  │ 1  │ 1  │...│ 1 │ 1 │ 0 │  ← Index 0 unclaimed
       └────┴────┴────┴───┴───┴───┴───┘

To check index I:
  Word index = I / 256
  Bit index  = I % 256
  Claimed?   = (claimedBitMap[wordIndex] >> bitIndex) & 1

This packing reduces storage from 1 slot per claim (at 20,000 gas for a cold SSTORE) to 1 slot per 256 claims, with only the first claim in each 256-index range paying the full cold storage cost.