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 0xb276f62d...1eac1c (etherscan)
Network Ethereum Mainnet
Analysis Date 2026-08-11
Snapshot Block 25733839

Variables

Slots are assigned in declaration order from the verified source and every value below was read directly with cast storage at block 25733839. Solady's Ownable and ReentrancyGuard use fixed high slots rather than sequential ones, which is why the sequential layout begins at slot 0 with the VRF coordinator rather than with the owner.

SLOT VARIABLE NAME TYPE CURRENT VALUE PURPOSE
0 s_vrfCoordinator IVRFCoordinatorV2Plus 0xd7f86b4b...20893a (etherscan) Chainlink Verifiable Random Function (VRF) coordinator; the only address permitted to call rawFulfillRandomWords. Owner-replaceable while quiescent.
1 vrfSubId uint256 0xbe3fb16e...0ffd33 Subscription that pays fulfilment gas.
2 vrfKeyHash bytes32 0x8077df51...2bd3d9 Chainlink gas lane.
3 callbackGasLimit / requestConfirmations uint32 / uint16 (packed) 900000 / 3 Gas budget for the callback; confirmation depth before fulfilment.
4 maxActivationsPerAcquisition uint256 6 Cap on staged listings drained or reserved per acquisition.
5 pendingAcquisitionCount uint256 0 Requests awaiting a VRF word.
6 unfulfilledVrfCount uint256 0 Outstanding callback liabilities against the subscription.
7 callbackObserved mapping(uint256 => bool) — Ensures each request releases its callback liability exactly once.
8 unsettledAcquisitionCount uint256 0 The exit gate. Non-zero blocks withdrawals, re-pricing and config changes.
9 selectionTimeoutBlocks uint256 30 Blocks a request has to receive its word before it is skipped.
10 maxAcquisitionsPerTx uint256 5 Cap on acquireBatch size.
11 lastIssuedSequence / nextSequenceToProcess / acquisitionsEnabled / withdrawOnly / whitelistEnabled uint64 / uint64 / bool / bool / bool (packed) 140481 / 140482 / true / false / true The settlement queue head and tail, plus the three mode flags. nextSequenceToProcess exceeding lastIssuedSequence means the queue is fully drained.
12 collectionWhitelisted mapping(address => bool) — Deposit whitelist. 47 collections observed active.
13 whitelistManager address 0x854352b2...5e17c3 (etherscan) FWAWhitelist; may edit the whitelist without being owner.
14 surchargeBps uint256 250 Purchaser premium over expected value. Lowered from 1000.
15 selectionSlippageBps uint256 1000 Default positive-drift tolerance snapshotted into each request.
16 settlementDiscountBps uint256 9000 Purchaser's ETH payout as a fraction of backing. Raised from 8500.
17 settlementWindow uint256 86400 Purchaser's exclusive resolution period, in seconds.
18 finalizeWindow uint256 604800 Delay before anyone may finalize, in seconds.
19 minBacking uint256 50000000000000000 Minimum deposit, 0.05 ETH. Raised from 0.01 ETH.
20 ownerAcquisitionFeeBps uint256 100 Protocol cut of each acquisition fee. Capped only at 10000.
21 ownerSettlementFeeBps uint256 100 Protocol cut of backing returned to a depositor. Hard-capped at 500.
22 retainedToProtocol bool true Whether the retained settlement penalty is protocol revenue or shared.
23 topListingShareBps uint256 100 Slice of each acquisition routed to the top-listing pot. Lowered from 500.
24 topThresholdBps uint256 1000 Margin by which a challenger must clear the incumbent top.
25 nextListingId uint256 149855 Monotonic id counter; 149,854 listings created to date.
26 listings mapping(uint256 => Listing) — The listing store.
27 stuckNFTRecipient mapping(uint256 => address) — Records who is owed an NFT whose delivery reverted.
28 stagingHead uint256 0 Oldest staged listing; 0 when the queue is empty.
29 stagingTail uint256 0 Newest staged listing.
30 stagingNext mapping(uint256 => uint256) — Forward links of the staging FIFO.
31 stagingPrev mapping(uint256 => uint256) — Backward links of the staging FIFO.
32 stagedCount uint256 0 Listings waiting outside the selection pool.
33 maxStagedListings uint256 0 Staging cap; 0 means unlimited.
34 reservedForSequence mapping(uint256 => uint64) — Binds a staged listing to the sequence that will activate it.
35 reservedStagedCount uint256 0 Staged listings currently reserved.
36 reservedListingsBySequence mapping(uint64 => uint256[]) — The exact activation batch committed per sequence.
37 slotToListing mapping(uint256 => uint256) — Reverse index from tree slot to listing id.
38 activeListingCount uint256 5770 Listings in the selection pool.
39 totalWeight uint256 72357566815035813943552 Sum of all active weights; must equal tree[1].
40 weightedBackingTotal uint256 5769999999999999999537847588424043513363 Sum of weight × value. Approximately activeListingCount × 1e36.
41 feeShareTotal uint256 5770 Sum of all active fee shares. Equals activeListingCount because each share is a flat 1.
42 accFeePerEV uint256 8026115607382734750819897645708918229739575285927178291 Dividend Accumulator, scaled by 1e36. Divided by SCALE this is 8.026115607 ETH of cumulative fees per unit share since deployment.
43 feeCredit mapping(address => uint256) — Withdrawable earnings. 348 addresses hold a non-zero balance totalling 39.895179240 ETH.
44 accruedOwnerFees uint256 0 Protocol fees awaiting payoutFees.
45 payoutAddress address 0x1C175b9F...373Bfe (etherscan) Splitter. Currently receives nothing because the token slice is 100%.
46 topListingId uint256 136185 The top-backed listing: a CryptoPunks 721 wrapper backed with 300 ETH.
47 topListingPot uint256 9365078075945921140 9.365078076 ETH accrued to the current top holder.
48 token address 0xa0Df17B5...20C845 (etherscan) FWAToken; derived from the rewards module at wiring, never set directly.
49 rewards / acceptBidAsTokensEnabled IFWARewards / bool (packed) 0x6a1a1C0C...92fc78 (etherscan) / true The rewards module and the switch allowing settlement in FWAToken.
50 acquisitionTokenSlice mapping(uint256 => uint256) — Per-request reward slice registered at request time.
51 protocolFeeToTokenBps uint256 10000 Share of protocol fees routed to the FWAToken buyback reserve. Raised from 0 to 8000 then 10000.
52 tree mapping(uint256 => uint256) — The depth-32 Segment Tree. Root at node 1; leaves from node 2³².
53 nextUnusedSlot uint256 9653 Next never-used tree slot.
54 freeSlotHead uint256 1318 Head of the LIFO free list of released slots.
55 nextFreeSlot mapping(uint256 => uint256) — Free-list links.
56 acquisitions mapping(uint256 => Acquisition) — Per-request purchaser, escrow, allocated listing and status.
57 acquisitionMeta mapping(uint256 => AcquisitionMeta) — Per-request sequence, deadline, snapshotted tolerances and cached word.
58 requestIdAtSequence mapping(uint64 => uint256) — Sequence-to-request index used by the ordered processor.
59 acquisitionRefundCredit mapping(address => uint256) — Pull refunds owed to purchasers.
60 acquisitionRefundCreditTotal uint256 0 Aggregate of the above.
61 acquisitionEscrowTotal uint256 0 Acquisition fees escrowed against unresolved requests.

Inherited Fixed Slots

SLOT SOURCE PURPOSE
0x8b78c6d8...000000 Solady Ownable Owner address. Stored at a constant slot rather than sequentially, which is why slot 0 is free for the coordinator.
Transient Solady ReentrancyGuard The nonReentrant mutex, held in Transient Storage and cleared at transaction end.

Struct Layouts

Listing occupies 11 sequential words per entry:

OFFSET FIELD TYPE NOTES
0 collection address The ERC-721 contract.
1 depositor address Who escrowed it and who receives the backing on a keep.
2 purchaser address Zero until allocated.
3 tokenId uint256
4 weight uint256 1e36 / value. Inversely proportional to backing.
5 value uint256 Backing ETH, escrowed for this listing alone.
6 feeShare uint256 Always 1. The struct comment describes this as √backing, but the deployed code assigns a literal 1 in both _createListing and updateBacking. The square-root weighting exists in the separate rewards module, not here.
7 feeDebt uint256 Dividend checkpoint, ceiled on entry.
8 slot uint256 Tree slot; 0 when not active.
9 allocatedAt uint64 Timestamp gating the settlement and finalize windows.
10 status ListingStatus None, Active, Allocated, Withdrawn, Settled, Staged.

Observed Status Distribution

Every listing id from 1 to 149,854 was read at block 25733839. The distribution reconciles exactly with nextListingId - 1 and with activeListingCount.

STATUS ENUM COUNT AGGREGATE BACKING
Active 1 5,770 1246.219052680 ETH
Allocated 2 56 3.788921919 ETH
Withdrawn 3 9,314 — (returned)
Settled 4 134,714 — (resolved)
Staged 5 0 0
Total 149,854

Diagrams

graph TB
    subgraph VRF["VRF Configuration — Slots 0-11"]
        S0["Slot 0: s_vrfCoordinator<br/>0xd7f86b4b...20893a"]
        S3["Slot 3: callbackGasLimit 900000<br/>requestConfirmations 3"]
        S8["Slot 8: unsettledAcquisitionCount — 0<br/>THE EXIT GATE"]
        S11["Slot 11: sequences 140481 / 140482<br/>enabled=true, withdrawOnly=false"]
    end

    subgraph Econ["Economic Parameters — Slots 14-24"]
        S14["Slot 14: surchargeBps — 250"]
        S16["Slot 16: settlementDiscountBps — 9000"]
        S19["Slot 19: minBacking — 0.05 ETH"]
        S20["Slot 20: ownerAcquisitionFeeBps — 100<br/>capped at 10000"]
        S21["Slot 21: ownerSettlementFeeBps — 100<br/>hard-capped at 500"]
        S23["Slot 23: topListingShareBps — 100"]
    end

    subgraph Pool["Pool Aggregates — Slots 38-42"]
        S38["Slot 38: activeListingCount — 5770"]
        S39["Slot 39: totalWeight<br/>7.2357e22 = tree root"]
        S40["Slot 40: weightedBackingTotal<br/>5.77e39 ≈ count x 1e36"]
        S41["Slot 41: feeShareTotal — 5770<br/>equals activeListingCount"]
        S42["Slot 42: accFeePerEV<br/>8.026 ETH per share cumulative"]
    end

    subgraph Liab["Liability Counters — Slots 44-61"]
        S44["Slot 44: accruedOwnerFees — 0"]
        S47["Slot 47: topListingPot — 9.365 ETH"]
        S60["Slot 60: acquisitionRefundCreditTotal — 0"]
        S61["Slot 61: acquisitionEscrowTotal — 0"]
    end

    subgraph Struct["Structures — Slots 26-37, 52-59"]
        S26["Slot 26: listings — 149,854 entries"]
        S52["Slot 52: tree — depth 32 segment tree"]
        S37["Slot 37: slotToListing — 5,770 occupied"]
        S30["Slots 28-36: staging FIFO — empty"]
    end

    VRF --> Econ --> Pool --> Liab --> Struct

    style S8 fill:#ffe1e1
    style S20 fill:#ffe1e1
    style S21 fill:#e1ffe1
    style S39 fill:#e8f0ff
    style S41 fill:#e8f0ff

The colouring marks the three slots that carry the most weight in the risk assessment. Slot 8 is the exit gate: while it is non-zero no depositor may withdraw or re-price, and no numeric config may change. Slot 20 is the unbounded side of the fee asymmetry — the owner may raise it to 10000 and capture the entire depositor fee stream. Slot 21 is the bounded side, hard-capped at 500, so the settlement cut cannot exceed 5% of backing.

graph LR
    subgraph Tree["Segment Tree — slot 52"]
        R["node 1<br/>root = totalWeight<br/>7.2357e22"]
        L2["node 2"]
        R2["node 3"]
        LEAF["leaves from node 2^32<br/>slot i maps to node 2^32 + i - 1"]
    end

    subgraph Slots["Slot Allocation"]
        NU["nextUnusedSlot — 9653"]
        FH["freeSlotHead — 1318<br/>LIFO free list"]
        OCC["5,770 occupied<br/>highest in use: 9651"]
    end

    R --> L2
    R --> R2
    L2 --> LEAF
    R2 --> LEAF
    LEAF --> OCC
    FH -.reuse.-> OCC
    NU -.extend.-> OCC

    style R fill:#e8f0ff

Selection walks the tree from the root, comparing a target drawn as randomWord mod totalWeight against the cumulative weight of each left subtree, descending 32 times to land on a leaf. Because the tree is a mapping rather than an array, capacity for 2³² concurrent listings costs nothing until a slot is actually touched — at the snapshot only 9,652 leaves have ever been used, and 5,770 are occupied.