Skip to content

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 — getsourcecode for the source bundle, getcontractcreation for deployment provenance, getLogs for 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 inspect against the same code
  • Foundry — cast for chain reads, forge for 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:

export ETH_RPC_URL=https://eth.llamarpc.com

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.