Methodology
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 |
Overview
The subject is a Majeur implementation contract rather than a deployed application, which shaped the approach throughout. Reading Moloch in isolation describes what the code permits; it does not describe what a DAO built on it does, what its members experience, or which of its many optional modules anyone actually uses. Structural claims below are drawn from the verified Solidity and checked against at least one of the two live instances running on it.
Work began from two DAO addresses supplied as the research subject. Both resolved to 45-byte minimal proxies pointing at a common implementation, which relocated the analysis one level down to the shared logic and reframed the two DAOs as evidence rather than as subjects. The factory was then recovered from the initialisation transactions, and its getDAOCount established that 56 DAOs share this code — which is what justified treating the framework, rather than either instance, as the unit of analysis.
The source is verified on Etherscan and was additionally diffed against the project repository at HEAD. Because the two proved byte-identical, the repository's tooling could be used against the deployed code with confidence — forge inspect produced the storage layouts and the complete selector set for all five contracts, rather than either being reconstructed by hand. Every selector published in functions.md was then re-checked programmatically against that generated set, and every value in storage-layout.md was confirmed by reading raw storage slots from a live clone rather than by trusting the declaration order.
The repository also carries a README, an mdbook, and 33 audit reports. None of these were used as a source for behavioural claims. The skill governing this work is explicit that analysis is of code, and comments and prose describing intent are not evidence of it. Those materials are recorded as context and cited as artifacts; where this analysis describes what a function does, that description came from reading the function.
Thought Process
mindmap
root((Majeur Analysis))
Relocate the subject
Two DAO addresses supplied
Both are 45-byte clones
Resolve shared implementation
Recover factory from init tx
56 DAOs confirm framework scope
Establish source trust
Etherscan verified
Clone repo at HEAD
Diff deployed vs published
Byte-identical result
Repo tooling now usable
Derive structure mechanically
forge inspect storageLayout
forge inspect methods
136 selectors across 5 contracts
Cross-check every published selector
Confirm coverage both directions
Read the code
Proposal lifecycle first
Content-addressed intent model
Execution op semantics
Satellite token division
Badge seat mechanics
Futarchy and permit modules
Ground against live chain
Enumerate all 37 proposals
Decode executed payloads
Verify targets resolve to known contracts
Read packed storage slots raw
Decode badge bitmaps and cutlines
Enumerate permits and spends
Test the surprising claims
Passed proposals that expired
Queued proposals that never expire
Compute quorum arithmetic explicitly
Confirm against current block time
Assess risk
What a passing proposal reaches
What survives without a new vote
What a voter can know when voting
Configuration interactions
Publish
Six documents
Withhold detailed register
Independent verification pass
Verification Guide
Every quantitative claim in this analysis is reproducible from the commands below. Addresses are given in full so the commands can be pasted directly.
External Resources
- Etherscan — verified source code, compiler configuration, contract creation metadata
- Etherscan API v2 —
getsourcecodefor the source bundle,getcontractcreationfor deployment provenance,getLogsfor the event history behind every proposal, permit and execution figure cited - z0r0z/majeur — the project repository, cloned locally to diff against the deployed source and to run
forge inspectagainst the same code - Foundry —
castfor chain reads,forgefor storage layout and selector generation - zFi DAO interface — the front end through which both live DAOs are operated, used to identify the research subject
Commandline Tools
Tip
Commands below use cast from the Foundry Toolkit. To run the commands below, you must set the RPC URL environment variable:
Establish That the DAOs Are Clones
The starting point. A 92-character result — 45 bytes plus the 0x prefix — is a minimal proxy, and the implementation address sits in the middle of it.
# FETCH RUNTIME BYTECODE OF THE ZORG DAO — EXPECT A 45-BYTE MINIMAL PROXY
cast code 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E
# FETCH RUNTIME BYTECODE OF THE FWC DAO — EXPECT THE SAME IMPLEMENTATION
cast code 0xE7Aa6cA3a9Ca3fe92a425dFeaD24900B9BF49853
# CONFIRM THE IMPLEMENTATION IS A FULL CONTRACT, NOT ANOTHER PROXY
cast code 0x643A45B599D81be3f3A68F37EB3De55fF10673C1 | wc -c
Recover the Factory and Its DAO Registry
Summoner is not referenced by any public getter on the DAO, so it was recovered from the initialisation transaction and then confirmed by reading its registry.
# COUNT EVERY DAO SUMMONED FROM THE FACTORY
cast call 0x0000000000330B8df9E3bc5E553074DA58eE9138 "getDAOCount()(uint256)"
# CONFIRM THE ZORG DAO IS THE FIRST ENTRY IN THE REGISTRY
cast call 0x0000000000330B8df9E3bc5E553074DA58eE9138 "daos(uint256)(address)" 0
Confirm the Immutables Embedded in Bytecode
SUMMONER, sharesImpl, lootImpl and badgesImpl are immutables and therefore absent from storage. Each was confirmed by searching the deployed runtime bytecode, where each appears exactly once.
# EACH OF THE FOUR IMMUTABLES SHOULD APPEAR EXACTLY ONCE IN THE RUNTIME BYTECODE
cast code 0x643A45B599D81be3f3A68F37EB3De55fF10673C1 > moloch.hex
grep -o -i "0000000000330b8df9e3bc5e553074da58ee9138" moloch.hex | wc -l
grep -o -i "71E9b38d301b5A58cb998C1295045FE276Acf600" moloch.hex | wc -l
grep -o -i "6f1f2aF76a3aDD953277e9F369242697C87bc6A5" moloch.hex | wc -l
grep -o -i "47C175Ce83B6B931ccBedD5ce95e701984eD96d5" moloch.hex | wc -l
Read Governance Configuration
The configuration table in the contract analysis comes from these reads against both instances.
# GOVERNANCE PARAMETERS FOR THE ZORG DAO
cast call 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E "quorumBps()(uint16)"
cast call 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E "proposalTTL()(uint64)"
cast call 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E "timelockDelay()(uint64)"
cast call 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E "proposalThreshold()(uint96)"
cast call 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E "ragequittable()(bool)"
cast call 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E "config()(uint64)"
# THE SATELLITE CLONES BOUND TO THIS DAO
cast call 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E "shares()(address)"
cast call 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E "loot()(address)"
cast call 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E "badges()(address)"
Verify Packed Storage Slots
The storage layout was generated with forge inspect, then confirmed against live storage. Slots 2, 3 and 4 pack multiple variables and were decoded by hand from the raw words.
# SLOT 2 — proposalThreshold (low 12 bytes) | minYesVotesAbsolute (next 12)
cast storage 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E 2
# SLOT 3 — quorumAbsolute | proposalTTL | timelockDelay
cast storage 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E 3
# SLOT 4 — config | quorumBps | ragequittable | renderer
cast storage 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E 4
# SLOT 14 AND 21 — proposalIds LENGTH AND messages LENGTH
cast storage 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E 14
cast storage 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E 21
Enumerate Proposals and Their States
Both DAOs' full proposal histories were walked through the registry array. This is the source of every state, tally and timing figure cited.
# WALK THE PROPOSAL REGISTRY AND REPORT STATE PLUS TALLY FOR EACH ENTRY
DAO=0x5E58BA0e06ED0F5558f83bE732a4b899a674053E
N=$(cast call $DAO "getProposalCount()(uint256)")
for ((i=0; i<N; i++)); do
PID=$(cast call $DAO "proposalIds(uint256)(uint256)" $i | awk '{print $1}')
echo "index $i id $PID"
cast call $DAO "state(uint256)(uint8)" $PID
cast call $DAO "tallies(uint256)(uint96,uint96,uint96)" $PID
cast call $DAO "supplySnapshot(uint256)(uint256)" $PID
cast call $DAO "createdAt(uint256)(uint64)" $PID
cast call $DAO "queuedAt(uint256)(uint64)" $PID
done
Reproduce the Quorum Arithmetic
The claim that proposals expired despite passing is arithmetic over the values above. state() applies totalCast >= quorumBps × supplySnapshot / 10000 and forVotes > againstVotes.
# PROPOSAL AT REGISTRY INDEX 15 — TURNOUT AGAINST THE 10% REQUIREMENT
cast call 0x5E58BA0e06ED0F5558f83bE732a4b899a674053E "state(uint256)(uint8)" \
27074363409939138706291210971568393745107980601210147145343527035030422413634
# 71271799312169381608761 cast, against a requirement of
# 237279790097462170647646 × 1000 / 10000 = 23727979009746217064764
# quorum met, zero against votes, and the state reads 5 (Expired)
Decode Executed Proposal Payloads
The Executed event carries mode, target and value but not calldata. The calldata was recovered by decoding the execution transaction itself.
# TOPIC FOR THE Executed EVENT
cast keccak "Executed(uint256,address,uint8,address,uint256)"
# DECODE THE FULL INTENT FROM AN EXECUTION TRANSACTION
cast decode-calldata "executeByVotes(uint8,address,uint256,bytes,bytes32)" \
$(cast tx 0xf90b79da45a6d9062d4b83d0df35c33a7166b8ec72fc58365e503134d1f8dd80 input)
# IDENTIFY THE INNER SELECTOR REVEALED BY THAT DECODE
cast 4byte 0x56d3163d
# CONFIRM THE CALL LANDED — ZORGCONVICTION'S RENDERER MATCHES THE PAYLOAD
cast call 0x0000006D936bA3653b8854490E16E782cd32a9a8 "renderer()(address)"
cast call 0x0000006D936bA3653b8854490E16E782cd32a9a8 "dao()(address)"
Enumerate Permits and Their Remaining Counts
Permits are ERC-6909 balances on the DAO. Grants come from event logs; remaining counts come from the balance itself.
# PERMIT GRANT AND SPEND TOPICS
cast keccak "PermitSet(address,uint256,uint256)"
cast keccak "PermitSpent(uint256,address,uint8,address,uint256)"
# REMAINING EXECUTIONS HELD BY A PERMIT HOLDER
cast call 0xE7Aa6cA3a9Ca3fe92a425dFeaD24900B9BF49853 \
"balanceOf(address,uint256)(uint256)" \
0x006cd14f36f65ecbb29b2519ccbe63a0dc8549f2 \
26605949972002582115139889680824186016431470980784028459561712153469334030501
Decode the Badge Seat Board
The seat bitmap and cutline are packed and have no dedicated getter, so both were read from raw storage.
# occupied BITMAP — POPCOUNT GIVES SEATS TAKEN, OUT OF 256
cast storage 0x2809A7EB62D5a50e40153080F548c306Db01c221 4
# SLOT 261 — minSlot (LOW 2 BYTES) AND minBal (NEXT 12 BYTES)
cast storage 0x2809A7EB62D5a50e40153080F548c306Db01c221 261
Regenerate Storage Layouts and Selectors
Both were produced mechanically from the repository, whose source is byte-identical to the deployed contract.
# CLONE AND CONFIRM THE DEPLOYED SOURCE MATCHES THE REPOSITORY
git clone https://github.com/z0r0z/majeur.git
diff majeur/src/Moloch.sol ./verified-source/Moloch.sol
# GENERATE STORAGE LAYOUT AND SELECTOR SET FOR EACH CONTRACT
forge inspect src/Moloch.sol:Moloch storageLayout
forge inspect src/Moloch.sol:Shares storageLayout
forge inspect src/Moloch.sol:Badges storageLayout
forge inspect src/Moloch.sol:Moloch methods
Document Verification
The drafted documents were re-checked before publication in five independent passes, each with a narrow scope and each reading from primary sources rather than from the draft. Running them separately matters: a claim can be correctly formatted, non-redundant, neutral in tone, free of filler, and still be factually wrong, and a single reviewer holding all five concerns at once reliably drops the last one.
| DIMENSION | WHAT IT CHECKS | CHECKED AGAINST |
|---|---|---|
| Facts | Addresses, block heights, proposal counts, vote tallies, timestamps, compiler version, storage values, badge bitmaps, permit balances, and all 136 function selectors | Live chain state via cast, Etherscan API v2, forge inspect output regenerated from the verified source |
| Standards | Address display format, explorer links on every on-chain reference, table casing, section separators, icon semantics, glossary term wrapping, nav registration | CLAUDE.md, docs/glossary.md, mkdocs.yml |
| Redundancy | Duplicated tables and paragraphs across the six documents, and the same claim stated with different values in two places | The document set itself |
| Voice | Superlatives asserted without a verification clause, opinion adjectives, speculation about intent or users | CLAUDE.md writing standards |
| Filler | Rhetorical padding — meta-narration, telegraphed structure, formulaic emphasis | CLAUDE.md anti-patterns |
The selector check is mechanical rather than editorial. Every selector published in functions.md was extracted by pattern match and compared against the forge inspect methods output for the contract that declares it, in both directions — no published selector absent from the generated set, and no generated selector absent from the document.
Every disagreement the fact pass raised was re-derived from chain or source before any edit was made, on the assumption that the checker is as capable of being wrong as the draft. A claim was only changed where the contradicting value could be reproduced from a command in the Verification Guide above.
Token Cost Breakdown
| PHASE | DESCRIPTION | TOKENS |
|---|---|---|
| Phase 0 | Obtain the Contract | 45 tok |
| Phase 1 | Discovery & Understanding | 130 tok |
| Phase 2 | Deep Dive Analysis | 210 tok |
| Phase 3 | Risk & Trust Analysis | 145 tok |
| Phase 4 | Documentation Generation | 260 tok |
| Phase 5 | Document Verification | 865 tok |
| TOTAL | Complete Contract Analysis | 1.7 mtok |
Phase 5 exceeds every other phase and approaches the combined cost of Phases 0 through 4. Phase 5 costs more because fact-checking re-derives claims instead of re-reading the draft. Confirming this analysis meant walking both proposal registries again, re-reading packed storage slots, regenerating the full selector set and comparing it row by row against the published tables, and recomputing the quorum arithmetic behind the expired-proposal findings. Each is a fresh set of chain reads rather than a pass over text already in context.
Note: Token costs are estimates based on typical conversation lengths and complexity. Actual consumption may vary by ±10-15% depending on API responses, iterative refinement, and verification steps.