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 | 0x643A45B5...0673C1 (etherscan) |
| Network | Ethereum Mainnet |
| Analysis Date | 2026-08-18 |
Reading This Document
The address above is the Moloch implementation. It holds no governance state of its own — every DAO is a separate ERC-1167 clone with its own storage, and the implementation's slots are never written through the implementation address itself. The CURRENT VALUE column therefore reports a sampled live clone — the zOrg DAO at 0x5E58BA0e...74053E (etherscan), read at block height on the analysis date — so that the decoded layout can be checked against real data. Those values belong to that DAO and are not framework defaults; a second clone, FWC at 0xE7Aa6cA3...F49853 (etherscan), is cited where the two differ.
Four values do not appear in any storage table below because they are not in storage. SUMMONER, sharesImpl, badgesImpl and lootImpl are Solidity immutables, compiled into the implementation's runtime bytecode at its own deployment. Every clone reads the same four values, and no clone can change them. Each appears exactly once in the deployed runtime bytecode, which is how they were confirmed:
| IMMUTABLE | VALUE | VERIFIED |
|---|---|---|
SUMMONER |
0x00000000...eE9138 (etherscan) |
Present once in runtime bytecode |
sharesImpl |
0x71E9b38d...Acf600 (etherscan) |
Present once in runtime bytecode |
lootImpl |
0x6f1f2aF7...7bc6A5 (etherscan) |
Present once in runtime bytecode |
badgesImpl |
0x47C175Ce...eD96d5 (etherscan) |
Present once in runtime bytecode |
Because init() requires msg.sender == SUMMONER and both live DAOs were successfully initialised in transactions originating from 0x00000000...eE9138 (etherscan), the SUMMONER immutable resolves to that factory. No other address can call init on any clone of this implementation.
Variables
Moloch
Thirty-eight declared variables across thirty-two slots, 0 to 31. Slots 2, 3 and 4 are packed, and all three packings were confirmed by reading raw storage rather than by trusting the declaration order.
| SLOT | VARIABLE NAME | TYPE | CURRENT VALUE | PURPOSE |
|---|---|---|---|---|
| 0 | _orgName |
string |
"zOrg" |
Organisation display name, served to Shares, Loot and Badges |
| 1 | _orgSymbol |
string |
"ZORG" |
Organisation symbol, inherited by the satellite tokens |
| 2 (offset 0) | proposalThreshold |
uint96 |
1000000000000000000 |
Minimum votes required to open a proposal; 0 disables |
| 2 (offset 12) | minYesVotesAbsolute |
uint96 |
0 |
Absolute floor on FOR votes; 0 disables |
| 3 (offset 0) | quorumAbsolute |
uint96 |
0 |
Absolute turnout floor; 0 disables |
| 3 (offset 12) | proposalTTL |
uint64 |
86400 |
Seconds from creation until an unqueued proposal expires; 0 disables |
| 3 (offset 20) | timelockDelay |
uint64 |
86400 |
Seconds between queueing and execution; 0 disables |
| 4 (offset 0) | config |
uint64 |
0 |
Version salt mixed into every proposal id; incrementing it invalidates all pending ids |
| 4 (offset 8) | quorumBps |
uint16 |
1000 |
Turnout quorum as basis points of snapshot supply (10%) |
| 4 (offset 10) | ragequittable |
bool |
true |
Whether holders may exit with a pro-rata share of the treasury |
| 4 (offset 11) | renderer |
address |
0x00000000...D6E654 (etherscan) |
External metadata renderer for tokenURI and contractURI |
| 5 | shares |
contract Shares |
0x00a6bA94...2dCb12 (etherscan) |
This DAO's voting token clone |
| 6 | badges |
contract Badges |
0x2809A7EB...01c221 (etherscan) |
This DAO's soulbound badge clone |
| 7 | loot |
contract Loot |
0x62eC8675...359016 (etherscan) |
This DAO's non-voting economic token clone |
| 8 | executed |
mapping(uint256 => bool) |
mapping | Execution latch per proposal id; also set by cancelProposal as a tombstone |
| 9 | createdAt |
mapping(uint256 => uint64) |
mapping | Timestamp of first open or vote, the origin for TTL |
| 10 | snapshotBlock |
mapping(uint256 => uint48) |
mapping | Vote-weight snapshot block, fixed at block.number - 1 on open |
| 11 | supplySnapshot |
mapping(uint256 => uint256) |
mapping | Total share supply at the snapshot block, the quorum denominator |
| 12 | queuedAt |
mapping(uint256 => uint64) |
mapping | Timelock start; a non-zero value permanently disables TTL for that proposal |
| 13 | tallies |
mapping(uint256 => Tally) |
mapping | Packed FOR / AGAINST / ABSTAIN vote totals |
| 14 | proposalIds |
uint256[] |
length 22 |
Append-only registry of opened proposal ids |
| 15 | proposerOf |
mapping(uint256 => address) |
mapping | Address that opened each proposal; the only address permitted to cancel it |
| 16 | hasVoted |
mapping(uint256 => mapping(address => uint8)) |
mapping | Vote record, stored as support + 1 so that 0 means "not voted" |
| 17 | voteWeight |
mapping(uint256 => mapping(address => uint96)) |
mapping | Weight credited per voter, retained so cancelVote can subtract exactly what it added |
| 18 | isPermitReceipt |
mapping(uint256 => bool) |
mapping | Marks an ERC-6909 id as a permit rather than a vote receipt, which makes it non-transferable |
| 19 | allowance |
mapping(address => mapping(address => uint256)) |
mapping | Token spending allowances granted by governance, keyed token then spender |
| 20 | sales |
mapping(address => Sale) |
mapping | Per-payment-token share sale configuration |
| 21 | messages |
string[] |
length 116 |
Badge-gated on-chain chat log |
| 22 | _orgURI |
string |
empty | Contract-level metadata override; when empty the renderer is consulted |
| 23 | balanceOf |
mapping(address => mapping(uint256 => uint256)) |
mapping | ERC-6909 balances for vote receipts and permits |
| 24 | totalSupply |
mapping(uint256 => uint256) |
mapping | ERC-6909 supply per id; the futarchy payout denominator |
| 25 | receiptSupport |
mapping(uint256 => uint8) |
mapping | Decodes a receipt id back to the side it represents |
| 26 | receiptProposal |
mapping(uint256 => uint256) |
mapping | Decodes a receipt id back to its proposal |
| 27 | futarchy |
mapping(uint256 => FutarchyConfig) |
mapping | Per-proposal prediction market state |
| 28 | autoFutarchyParam |
uint256 |
10 |
Automatic futarchy earmark; 1–10000 is basis points of basis supply, above 10000 is an absolute amount |
| 29 | autoFutarchyCap |
uint256 |
5000000000000000000 |
Per-proposal ceiling on the automatic earmark (5e18) |
| 30 | rewardToken |
address |
0x00000000...000000 |
Governance-pinned futarchy reward token. Zero leaves the choice to the first funder in fundFutarchy, but resolves to address(1007) — newly minted loot — in the openProposal auto-earmark |
| 31 | isOperator |
mapping(address => mapping(address => bool)) |
mapping | ERC-6909 operator approvals |
The three packed slots decode as follows, read directly from the zOrg clone:
slot 2 0x0000000000000000000000000000000000000000000000000de0b6b3a7640000
proposalThreshold = 0x0de0b6b3a7640000 = 1e18
minYesVotesAbsolute = 0
slot 3 0x0000000000000000000151800000000000015180000000000000000000000000
quorumAbsolute = 0
proposalTTL = 0x15180 = 86400
timelockDelay = 0x15180 = 86400
slot 4 0x00000000000011c799980827f52d3137b4abd6e6540103e80000000000000000
config = 0
quorumBps = 0x03e8 = 1000
ragequittable = 0x01 = true
renderer = 0x000000000011C799980827F52d3137b4abD6E654
Both sampled clones happen to set proposalTTL equal to timelockDelay — 86,400 seconds on zOrg, 43,200 on FWC. Nothing in the implementation ties them together; the consequence of setting them that way is treated in the Contract Analysis.
Shares
Nine declared slots. This is the only satellite that carries voting machinery.
| SLOT | VARIABLE NAME | TYPE | CURRENT VALUE | PURPOSE |
|---|---|---|---|---|
| 0 | transfersLocked |
bool |
false |
When set, blocks transfers unless the DAO is sender or recipient |
| 1 | totalSupply |
uint256 |
7822066259197685009861991 |
Share supply, checkpointed on every mint and burn |
| 2 | balanceOf |
mapping(address => uint256) |
mapping | ERC-20 balances |
| 3 | allowance |
mapping(address => mapping(address => uint256)) |
mapping | ERC-20 allowances |
| 4 | DAO |
address payable |
0x5E58BA0e...74053E (etherscan) |
The owning Moloch clone; set once in init and never mutable afterwards |
| 5 | _delegates |
mapping(address => address) |
mapping | Primary delegate per holder; zero is interpreted as self |
| 6 | _checkpoints |
mapping(address => Checkpoint[]) |
mapping | Per-delegate vote history, binary-searched by getPastVotes |
| 7 | _totalSupplyCheckpoints |
Checkpoint[] |
array | Supply history, the source for getPastTotalSupply |
| 8 | _splits |
mapping(address => Split[]) |
mapping | Split delegation configuration, at most four entries per holder |
DAO guards every privileged entry point on this contract and is written exactly once, in init, behind a require(DAO == address(0)). There is no setter and no transfer path, so the binding between a Shares clone and its Moloch clone is permanent.
Loot
Five declared slots, identical in shape to the first five of Shares and carrying none of the voting machinery. Loot confers economic rights only.
| SLOT | VARIABLE NAME | TYPE | CURRENT VALUE | PURPOSE |
|---|---|---|---|---|
| 0 | transfersLocked |
bool |
false |
Transfer lock, same semantics as Shares |
| 1 | totalSupply |
uint256 |
2026458778534528890 |
Loot supply; counts toward ragequit but never toward votes |
| 2 | balanceOf |
mapping(address => uint256) |
mapping | ERC-20 balances |
| 3 | allowance |
mapping(address => mapping(address => uint256)) |
mapping | ERC-20 allowances |
| 4 | DAO |
address payable |
0x5E58BA0e...74053E (etherscan) |
Owning Moloch clone, written once in init |
Loot cannot be delegated, cannot be snapshotted, and contributes nothing to getPastTotalSupply, so issuing loot dilutes treasury claims without diluting voting power.
Badges
Eight declared entries occupying 262 slots, because seats is a fixed 256-element array of packed structs.
| SLOT | VARIABLE NAME | TYPE | CURRENT VALUE | PURPOSE |
|---|---|---|---|---|
| 0 | DAO |
address payable |
0x5E58BA0e...74053E (etherscan) |
Owning Moloch clone, written once in init |
| 1 | _ownerOf |
mapping(uint256 => address) |
mapping | Seat id (1–256) to holder |
| 2 | seatOf |
mapping(address => uint256) |
mapping | Holder to seat id; 0 means unseated |
| 3 | balanceOf |
mapping(address => uint256) |
mapping | ERC-721 balance, structurally capped at 1 per address |
| 4 | occupied |
uint256 |
0xffff...ffff (256 of 256 set) |
Bitmap of taken seats, one bit per slot |
| 5–260 | seats |
Seat[256] |
array | Cached holder and balance per seat, packed as address + uint96 |
| 261 (offset 0) | minSlot |
uint16 |
120 |
Index of the current cutline seat |
| 261 (offset 2) | minBal |
uint96 |
16693532759286299628 |
Share balance at the cutline (≈16.6935 ZORG) |
The zOrg board is full: occupied reads as all 256 bits set, and the cutline sits at roughly 16.69 shares held by the occupant of seat index 120. A newcomer joins only by strictly exceeding that balance, which evicts the cutline holder. The FWC board is partly filled, and its occupied word has a cleared bit where a seat was released when its holder's balance reached zero. That seat will be refilled by the next holder to acquire any non-zero balance, regardless of size, because free seats are granted without comparison — the two boards therefore demonstrate both allocation regimes at once.
Diagrams
graph TB
subgraph Immutable["Immutables — bytecode, not storage"]
I0["SUMMONER — 0x00000000...eE9138"]
I1["sharesImpl / lootImpl / badgesImpl"]
end
subgraph Config["Governance Config — Slots 2-4 packed"]
S2["Slot 2: proposalThreshold 1e18 | minYesVotesAbsolute 0"]
S3["Slot 3: quorumAbsolute 0 | proposalTTL 86400 | timelockDelay 86400"]
S4["Slot 4: config 0 | quorumBps 1000 | ragequittable true | renderer"]
end
subgraph Satellites["Satellite Clones — Slots 5-7"]
S5["Slot 5: shares"]
S6["Slot 6: badges"]
S7["Slot 7: loot"]
end
subgraph Proposals["Proposal State — Slots 8-17"]
S8["Slot 8: executed latch"]
S9["Slots 9-12: createdAt, snapshotBlock, supplySnapshot, queuedAt"]
S13["Slots 13-17: tallies, proposalIds, proposerOf, hasVoted, voteWeight"]
end
subgraph Modules["Module State — Slots 18-31"]
S18["Slots 18-20: permits, allowances, sales"]
S21["Slots 21-22: chat log, org URI"]
S23["Slots 23-27: ERC-6909 receipts and futarchy"]
S28["Slots 28-31: futarchy config, operators"]
end
Immutable --> Config --> Satellites --> Proposals --> Modules
style S3 fill:#ffe1e1
style S4 fill:#ffe1e1
style S8 fill:#fff4e1
graph LR
subgraph Moloch["Moloch clone — governance state"]
M["38 vars / 32 slots"]
end
subgraph Shares["Shares clone — 9 slots"]
SH["totalSupply + checkpoints + splits"]
end
subgraph Loot["Loot clone — 5 slots"]
LO["totalSupply only, no checkpoints"]
end
subgraph Badges["Badges clone — 262 slots"]
BA["seats[256] + occupied bitmap + cutline"]
end
Moloch -->|"DAO immutable binding"| Shares
Moloch --> Loot
Moloch --> Badges
Shares -->|"onSharesChanged"| Moloch
Moloch -->|"onSharesChanged"| Badges
style BA fill:#e1f0ff