Opinionated DAO governance β members can always exit with their share of the treasury. Built-in futarchy, weighted delegation, and soulbound badges.
| Feature | Majeur | Governor (OZ) | Aragon OSx |
|---|---|---|---|
| Ragequit (exit with treasury share) | Yes | No | No |
| Futarchy (prediction markets on votes) | Yes | No | No |
| Split delegation (60% Alice, 40% Bob) | Yes | No | No |
| Fully on-chain metadata (SVG) | Yes | No | No |
| Single-contract deployment | Yes | Multi-contract | Plugin system |
| DUNA legal wrapper support | Yes | No | No |
Majeur is for DAOs that prioritize member protection. Ragequit means no one can be trapped β if you disagree with the majority, burn your shares and leave with your proportional treasury. Futarchy rewards voters who bet correctly on outcomes, not just those who show up. Split delegation lets you diversify representation instead of all-or-nothing.
All contracts are deployed at the same CREATE2 addresses across supported networks.
| Contract | Address | Description |
|---|---|---|
| Summoner | 0x0000000000330B8df9E3bc5E553074DA58eE9138 |
Factory for deploying new DAOs |
| Renderer | 0x000000000011C799980827F52d3137b4abD6E654 |
On-chain SVG metadata renderer |
| MolochViewHelper | 0x00000000006631040967E58e3430e4B77921a2db |
Batch read helper for dApps |
| Tribute | 0x000000000066524fcf78Dc1E41E9D525d9ea73D0 |
OTC escrow for tribute proposals |
| DAICO | 0x000000000033e92DB97B4B3beCD2c255126C60aC |
Token sale with tap mechanism |
Vote with shares β Split delegation β Futarchy markets β Ragequit exit
β β β β
Execute any 60% Alice Reward correct Leave with your
on-chain action 40% Bob predictions treasury share
| Token | Standard | Purpose |
|---|---|---|
| Shares | ERC-20 | Voting power + economic rights (delegatable) |
| Loot | ERC-20 | Economic rights only β no voting |
| Receipts | ERC-6909 | Vote receipts for futarchy payouts |
| Badges | ERC-721 | Soulbound NFTs for top 256 shareholders |
All tokens are deployed as separate contracts via minimal proxy clones. The DAO controls minting, burning, and transfer locks.
The defining feature of Moloch-style DAOs: members can always exit.
Burn your shares/loot β receive your proportional share of the treasury. Own 10% of shares? Claim 10% of every treasury token. This creates a floor price for membership and protects minorities from majority tyranny.
Limitation: You can only claim external tokens (ETH, USDC, etc.) β not the DAO's own shares, loot, or badges.
Skin-in-the-game governance through prediction markets:
- Anyone funds a reward pool for a proposal
- Vote YES, NO, or ABSTAIN β receive receipt tokens
- Proposal passes β YES voters split the pool; fails β NO voters win
- Burn your receipts to claim winnings
This shifts incentives from "vote with the crowd" to "vote for what you believe will actually succeed."
Distribute voting power across multiple delegates:
Traditional: 100% β Alice
Split: 60% β Alice, 40% β Bob, or any combination
Useful when you trust different people for different expertise, or want to hedge your representation.
Soulbound NFTs automatically minted for the top 256 shareholders. They update in real-time as balances change and gate access to member-only features like on-chain chat.
Unopened β Active β Succeeded β Queued (if timelock) β Executed
β Defeated
β Expired (TTL)
Pass conditions (all must be true):
- Quorum reached (absolute or percentage)
- FOR > AGAINST (ties fail)
- Minimum YES threshold met (if configured)
- Not expired
// Deploy via Summoner factory
Summoner summoner = new Summoner();
address[] memory holders = [alice, bob, charlie];
uint256[] memory shares = [100e18, 50e18, 50e18];
Moloch dao = summoner.summon(
"MyDAO", // name
"MYDAO", // symbol
"", // URI (metadata)
5000, // 50% quorum (basis points)
true, // ragequittable
address(0), // renderer (0 = default on-chain SVG)
bytes32(0), // salt (for deterministic addresses)
holders, // initial holders
shares, // initial shares
new Call[](0) // init calls (optional setup actions)
);// 1. Create proposal ID (anyone can compute this)
uint256 proposalId = dao.proposalId(
0, // op: 0=call, 1=delegatecall
target, // contract to call
value, // ETH to send
data, // calldata
nonce // unique nonce
);
// 2. Open and vote (auto-opens on first vote)
dao.castVote(proposalId, 1); // support: 0=AGAINST, 1=FOR, 2=ABSTAIN
// 3. Execute when passed
dao.executeByVotes(0, target, value, data, nonce);// Split delegation: 60% to alice, 40% to bob
address[] memory delegates = [alice, bob];
uint32[] memory bps = [6000, 4000]; // must sum to 10000
dao.shares().setSplitDelegation(delegates, bps);
// Clear split (return to single delegate)
dao.shares().clearSplitDelegation();// Fund a prediction market for a proposal
dao.fundFutarchy(
proposalId,
address(0), // 0 = ETH, or token address
1 ether // amount
);
// After resolution, claim winnings
uint256 receiptId = dao._receiptId(proposalId, 1); // 1=YES
dao.cashOutFutarchy(proposalId, myReceiptBalance);// DAO enables share sales (governance action)
dao.setSale(
address(0), // payment token (0=ETH, or ERC-20 address)
0.01 ether, // price per share (in payment token units)
1000e18, // cap (max shares that can be sold)
true, // mint new shares (false = transfer from DAO treasury)
true, // active (enable sales)
false // isLoot (false = shares, true = loot)
);
// Users can buy shares
dao.buyShares{value: 1 ether}(
address(0), // payment token (must match the sale config)
100e18, // shares to buy
1 ether // max payment willing to spend (slippage protection)
);
// Payment goes to DAO treasury, buyer receives shares/loot// Exit with proportional share of treasury
address[] memory tokens = [weth, usdc, dai];
dao.ragequit(
tokens, // tokens to claim
myShares, // shares to burn
myLoot // loot to burn
);DAOs can issue permits allowing specific addresses to execute actions without voting:
// DAO issues permit
dao.setPermit(op, target, value, data, nonce, alice, 1);
// Alice spends permit
dao.spendPermit(op, target, value, data, nonce);dao.setTimelockDelay(2 days); // Delay between queue and execute
dao.setProposalTTL(7 days); // Proposal expiry time// Only badge holders (top 256) can chat
dao.chat("Hello DAO members!");// Web3.js/Ethers.js
const shares = await dao.shares();
const totalSupply = await shares.totalSupply();
const myBalance = await shares.balanceOf(account);
const myVotes = await shares.getVotes(account);
// Check proposal state
const state = await dao.state(proposalId);
// States: 0=Unopened, 1=Active, 2=Queued, 3=Succeeded, 4=Defeated, 5=Expired, 6=Executed
// Get vote tally
const tally = await dao.tallies(proposalId);
console.log(`FOR: ${tally.forVotes}, AGAINST: ${tally.againstVotes}`);// Key events to watch
dao.on("Opened", (id, snapshot, supply) => {
console.log(`Proposal ${id} opened at block ${snapshot}`);
});
dao.on("Voted", (id, voter, support, weight) => {
console.log(`${voter} voted ${support} with ${weight} votes`);
});
dao.on("Executed", (id, executor, op, target, value) => {
console.log(`Proposal ${id} executed by ${executor}`);
});| Feature | Description |
|---|---|
| Snapshot voting | Block N-1 snapshot prevents vote buying after proposal opens |
| Flexible quorum | Absolute (e.g., 1000 votes) or percentage (e.g., 20%) |
| Timelocks | Configurable delay between passing and execution |
| Proposal TTL | Auto-expire stale proposals |
| Vote/proposal cancellation | Change your mind before execution |
| Feature | Description |
|---|---|
| Ragequit | Exit with proportional treasury share |
| Token sales | Built-in share/loot sales at configurable price |
| DAICO | External sale contract with tap mechanism (controlled fund release) |
| Tribute | OTC escrow for membership trades |
| Futarchy | Prediction markets reward correct voters |
| Feature | Description |
|---|---|
| Split delegation | Divide voting power across multiple delegates |
| ERC-6909 receipts | Gas-efficient multi-token for vote tracking |
| Clone pattern | ~80% deployment gas savings |
| Transient storage | EIP-1153 reentrancy guards |
| On-chain SVG | Fully decentralized metadata β no IPFS, no servers |
Majeur supports Wyoming's Decentralized Unincorporated Nonprofit Association (DUNA) β a legal entity that exists purely through smart contracts (Wyoming Statute 17-32-101).
| DUNA Benefit | How Majeur Implements It |
|---|---|
| Limited liability | On-chain legal covenant in metadata |
| Member registry | Top-256 badge system |
| Governance records | All votes stored permanently on-chain |
| Exit rights | Ragequit (legal self-help remedy) |
| No admin burden | No filings, meetings, or formalities |
A DUNA lets your DAO sign real-world agreements, own property, and shield members from personal liability β without incorporating.
Summoner (Factory)
βββ Deploys via CREATE2 + minimal proxy clones
β
βββ Moloch (Main DAO Contract)
β βββ Governance logic (proposals, voting, execution)
β βββ ERC-6909 receipts (multi-token vote receipts)
β βββ Futarchy markets
β βββ Ragequit mechanism
β βββ Token sales
β
βββ Shares (Separate ERC-20 + ERC-20Votes Clone)
β βββ Voting power tokens
β βββ Transferable/Lockable (DAO-controlled)
β βββ Single delegation or split delegation
β βββ Checkpoint-based vote tracking
β
βββ Loot (Separate ERC-20 Clone)
β βββ Non-voting economic tokens
β βββ Transferable/Lockable (DAO-controlled)
β
βββ Badges (Separate ERC-721 Clone)
βββ Soulbound (non-transferable) NFTs
βββ Automatically minted for top 256 shareholders
βββ Auto-updated as balances change
Renderer (Singleton)
βββ On-chain SVG generation
βββ DUNA covenant display
βββ DAO contract metadata
βββ Proposal cards
βββ Vote receipt cards
βββ Permit cards
βββ Badge cards
Simple escrow for "tribute proposals" β trade external assets for DAO membership:
// 1. Proposer locks tribute (e.g., 10 ETH for 1000 shares)
tribute.proposeTribute{value: 10 ether}(
dao, // target DAO
address(0), // tribTkn (ETH)
0, // tribAmt (use msg.value for ETH)
sharesToken, // forTkn (what proposer wants)
1000e18 // forAmt (how much)
);
// 2. DAO votes to accept, then claims (executes the swap)
// DAO receives tribute, proposer receives shares
dao.executeByVotes(...); // calls tribute.claimTribute(proposer, tribTkn)Key functions:
proposeTribute()- Lock assets and create offercancelTribute()- Proposer withdraws (before DAO claims)claimTribute()- DAO accepts and executes swapgetActiveDaoTributes()- View all pending tributes for a DAO
Inspired by Vitalik's DAICO concept β controlled fundraising with investor protection:
// 1. DAO configures a sale
dao.executeByVotes(...); // calls DAICO.setSaleWithTap(...)
// 2. Users buy shares/loot
daico.buy(dao, address(0), 1 ether, minShares); // exact-in
daico.buyExactOut(dao, address(0), 1000e18, maxPay); // exact-out
// 3. Ops team claims vested funds via tap
daico.claimTap(dao); // anyone can trigger, funds go to opsSale Features:
- Fixed-price OTC sales (tribAmt:forAmt ratio)
- Optional deadline expiry
- Optional LP integration with ZAMM (auto-adds liquidity)
- Drift protection prevents buyer underflow when spot > OTC price
Tap Mechanism:
ratePerSec- Funds release rate (smallest units/second)ops- Beneficiary address (can be updated by DAO)- Rate changes are non-retroactive (prevents gaming)
- Dynamically caps to min(owed, allowance, balance) β respects ragequits
Summon Helpers:
// Deploy DAO with pre-configured DAICO sale
daico.summonDAICO(summonConfig, "MyDAO", "DAO", ..., daicoConfig);
daico.summonDAICOWithTap(..., tapConfig); // includes tapGas-efficient view contract for dApp frontends:
// Fetch full state for multiple DAOs in one call
DAOLens[] memory daos = helper.getDAOsFullState(
0, // daoStart
10, // daoCount
0, // proposalStart
5, // proposalCount
0, // messageStart
10, // messageCount
tokens // treasury tokens to check
);
// User portfolio: find all DAOs where user is a member
UserMemberView[] memory myDaos = helper.getUserDAOs(
user, 0, 100, tokens
);
// DAICO scanner: find all DAOs with active sales
DAICOView[] memory sales = helper.scanDAICOs(0, 100, tribTokens);Returned Data:
DAOLens- Full DAO state (meta, config, supplies, members, proposals, messages, treasury)MemberView- Account balances, seat ID, voting power, delegation splitsProposalView- Tallies, state, voters, futarchy configSaleView- Active DAICO sale terms, remaining supply, LP configTapView- Tap config, claimable amount, treasury balance
| Function | Purpose | Who Can Call |
|---|---|---|
summon() |
Deploy new DAO | Anyone |
castVote() |
Vote on proposal | Share holders |
executeByVotes() |
Execute passed proposal | Anyone |
ragequit() |
Exit with treasury share | Share/Loot holders |
delegate() |
Delegate voting power | Share holders |
setSplitDelegation() |
Split delegation | Share holders |
buyShares() |
Purchase shares during sale | Anyone (if sale active) |
fundFutarchy() |
Add to prediction market | Anyone |
cashOutFutarchy() |
Claim futarchy rewards | Receipt holders |
chat() |
Post in member chat | Badge holders |
| Function | Purpose |
|---|---|
setSale() |
Enable built-in token sales |
setPermit() |
Issue execution permits |
setAllowance() |
Set treasury spending allowance |
setTimelockDelay() |
Set execution delay |
setQuorumBps() |
Set quorum percentage |
setRagequittable() |
Enable/disable ragequit |
setTransfersLocked() |
Lock/unlock share/loot transfers |
setAutoFutarchy() |
Configure auto-funded futarchy |
bumpConfig() |
Invalidate old proposals |
| Function | Purpose | Who Can Call |
|---|---|---|
proposeTribute() |
Lock assets, create offer | Anyone |
cancelTribute() |
Withdraw locked tribute | Original proposer |
claimTribute() |
Accept and execute swap | DAO (via proposal) |
getActiveDaoTributes() |
View pending tributes | Anyone (view) |
| Function | Purpose | Who Can Call |
|---|---|---|
setSale() |
Configure token sale | DAO |
setSaleWithTap() |
Sale + tap in one call | DAO |
setLPConfig() |
Configure LP auto-add | DAO |
setTapOps() |
Update tap beneficiary | DAO |
setTapRate() |
Adjust tap rate | DAO |
buy() |
Exact-in purchase | Anyone |
buyExactOut() |
Exact-out purchase | Anyone |
claimTap() |
Release vested funds | Anyone (funds go to ops) |
quoteBuy() |
Preview exact-in | Anyone (view) |
quotePayExactOut() |
Preview exact-out | Anyone (view) |
DAO Members β Vote, delegate (even split across multiple people), buy shares, ragequit, chat with top holders.
Proposal Creators β Submit proposals, fund futarchy markets, set timelocks, cancel before votes are cast.
Developers β Monitor events, build delegation UIs, create futarchy dashboards, display on-chain SVGs. Use MolochViewHelper for efficient batch reads.
// β Wrong - will revert if not sorted
address[] memory tokens = [dai, weth, usdc];
dao.ragequit(tokens, shares, loot);
// β
Correct - tokens sorted by address
address[] memory tokens = [dai, usdc, weth]; // sorted ascending
dao.ragequit(tokens, shares, loot);// Check proposal state before voting
if (dao.state(proposalId) == ProposalState.Active) {
dao.castVote(proposalId, 1);
}// β Wrong - doesn't sum to 10000
uint32[] memory bps = [6000, 3000]; // 90% total
// β
Correct - must sum to exactly 10000
uint32[] memory bps = [6000, 4000]; // 100% total# Install Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup
# Build
forge build
# Run all tests
forge test
# Run with verbosity
forge test -vvv
# Run specific test file
forge test --match-path test/Moloch.t.sol
# Run specific test
forge test --match-test test_Ragequit
# Gas snapshot
forge snapshot| File | Coverage |
|---|---|
Moloch.t.sol |
Core governance: voting, delegation, execution, ragequit, futarchy, badges |
DAICO.t.sol |
Token sales, tap mechanism, LP config, summon helpers |
Tribute.t.sol |
OTC escrow: propose, cancel, claim tributes |
MolochViewHelper.t.sol |
Batch read functions for dApps |
ContractURI.t.sol |
On-chain metadata and DUNA covenant |
URIVisualization.t.sol |
SVG rendering for cards |
Bytecodesize.t.sol |
Contract size limits |
Key test scenarios:
- Proposal lifecycle (open β vote β queue β execute)
- Split delegation with multiple delegates
- Futarchy funding and payout
- Ragequit with multiple tokens
- Badge auto-updates on balance changes
- DAICO tap claims and rate changes
- Tribute propose/cancel/claim flows
forge script script/Deploy.s.sol --rpc-url $RPC_URL --broadcast| Protection | Mechanism |
|---|---|
| Flash loan attacks | Snapshot at block N-1 |
| Reentrancy | Transient storage guards (EIP-1153) |
| Majority tyranny | Ragequit β minorities can exit with their share |
| Malicious proposals | Timelocks give time to ragequit; bumpConfig() invalidates all pending |
| Token reentrancy | Ragequit requires sorted token arrays |
// 1. Deploy DAO
Summoner summoner = new Summoner();
Moloch dao = summoner.summon("MyDAO", "DAO", "", 5000, true, address(0),
bytes32(0), [alice, bob], [100e18, 100e18], new Call[](0));
// 2. Alice delegates 70% to expert1, 30% to expert2
Shares shares = dao.shares();
shares.setSplitDelegation([expert1, expert2], [7000, 3000]);
// 3. Create and vote on treasury proposal
bytes memory data = abi.encodeWithSignature(
"transfer(address,uint256)", charlie, 10 ether
);
uint256 id = dao.proposalId(0, weth, 0, data, bytes32("prop1"));
dao.castVote(id, 1); // Vote FOR
// 4. Wait for voting period...
// 5. Execute if passed
if (dao.state(id) == ProposalState.Succeeded) {
dao.executeByVotes(0, weth, 0, data, bytes32("prop1"));
}
// 6. Charlie can ragequit if unhappy
address[] memory tokens = getSortedTreasuryTokens();
dao.ragequit(tokens, myShares, 0);| Technique | Savings | Details |
|---|---|---|
| Clone pattern | ~80% deployment | Minimal proxy clones for Shares, Loot, Badges |
| Transient storage | ~5k/call | EIP-1153 for reentrancy guards |
| Badge bitmap | ~20k/update | 256 holders in single storage slot |
| Packed structs | ~20k/write | Tallies fit in one slot (3 Γ uint96) |
A: Yes! Use cancelVote(proposalId) before the proposal is executed. You'll get your vote receipt back and can vote again.
A: Badges automatically update. If you fall out of top 256, you lose the badge. If you enter top 256, you get one instantly.
A: Yes, and it's the default. Your votes stay with you unless you explicitly delegate.
A:
call(op=0): Execute from DAO's context (normal)delegatecall(op=1): Execute in DAO's storage (upgrades/modules)
A: Yes! Specify how many shares/loot to burn. You don't have to exit completely.
A: Deterministically from: keccak256(dao, op, to, value, data, nonce, config). Anyone can compute it.
A: Snapshots at block N-1. You can't buy tokens after seeing a proposal and vote.
A: Yes, through proposals with delegatecall or by deploying new contracts.
A: A version number that's part of every proposal ID. The DAO can increment it via bumpConfig() to invalidate all old/pending proposal IDs and permits. This is a governance "emergency brake" if malicious proposals were created.
A: Yes! All metadata is on-chain (including SVGs). Use MolochViewHelper for batch reads.
A: Built-in setSale() is simpler β direct minting at a fixed price. DAICO adds tap mechanisms (controlled fund release), optional LP initialization, and operates as an external escrow contract for investor protection.
A: The tap limits how fast the ops team can withdraw raised funds. DAO members can vote to lower the rate (or freeze it) if they lose confidence. If members ragequit, the tap auto-adjusts to the reduced treasury.
A: Yes, use the Tribute contract. Lock your assets, propose the trade to the DAO, and if they vote to accept, the swap executes atomically.
These contracts are unaudited. Use at your own risk. No warranties or guarantees provided.
MIT