Skip to content

Functions

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 0x00000000...4e6f2a (etherscan)
Network Ethereum Mainnet
Analysis Date 2026-10-27

Function Selectors

The contract wraps the Majeur Summoner, the factory for Moloch-style Decentralized Autonomous Organizations (DAOs). Struct parameters are shown by name. In the selector computation each expands to its tuple of member types, in declaration order — SafeConfig has 21 members, SaleModule 7, TapModule 5, SeedModule 8, and Call is (address,uint256,bytes).

SELECTOR FUNCTION SIGNATURE CATEGORY
0x024b6d40 safeSummon(string,string,string,uint16,bool,address,bytes32,address[],uint256[],uint256[],SafeConfig,Call[]) User
0x4e1e3b11 safeSummonDAICO(string,string,string,uint16,bool,address,bytes32,address[],uint256[],uint256[],SafeConfig,SaleModule,TapModule,SeedModule,Call[]) User
0x8d797976 summonStandard(string,string,string,bytes32,address[],uint256[],bool) User
0x91ea2453 summonFast(string,string,string,bytes32,address[],uint256[],bool) User
0xc7d43a7d summonFounder(string,string,string,bytes32) User
0x94c2d76d summonStandardDAICO(string,string,string,bytes32,address[],uint256[],bool,SaleModule,TapModule,SeedModule) User
0x07f1831f summonFastDAICO(string,string,string,bytes32,address[],uint256[],bool,SaleModule,TapModule,SeedModule) User
0x94d6f6d4 create2Deploy(bytes,bytes32) User
0xac9650d8 multicall(bytes[]) User
0x7d64e7d8 predictDAO(bytes32,address[],uint256[]) View
0x78923610 predictShares(address) View
0x6de0b938 predictLoot(address) View
0x98b44bb6 predictCreate2(bytes,bytes32) View
0x03666cdd previewCalls(SafeConfig) View
0x0e1adbf1 previewModuleCalls(SaleModule,TapModule,SeedModule) View
0x59c75af0 burnPermitCall(bytes32,address[],uint256[],uint256,address) View

Summary

CATEGORY COUNT
Total Functions 16
User Functions 9
Admin Functions 0
View Functions 7

Every user function is payable and permissionless. The validation rules in _validate and _validateModules are tabulated in Validation Rules; the calls _buildCalls encodes are listed in Init Calls Generated.


Init Calls Generated

_buildCalls emits calls in a fixed order; a call is present only when its trigger is non-zero. All targets are the DAO unless noted. Loot mints from _buildLootMints, then module calls from _buildModuleCalls, then caller extraCalls are appended after these.

ORDER CALL TRIGGER
1 setProposalThreshold(proposalThreshold) Always
2 setProposalTTL(proposalTTL) Always
3 setTimelockDelay(timelockDelay) timelockDelay > 0
4 setQuorumAbsolute(quorumAbsolute) quorumAbsolute > 0
5 setMinYesVotesAbsolute(minYesVotes) minYesVotes > 0
6 setTransfersLocked(lockShares, lockLoot) Either flag set
7 setAutoFutarchy(param, cap) autoFutarchyParam > 0
8 setFutarchyRewardToken(token) Futarchy on and token non-zero
9 setSale(payToken, price, cap, minting, true, isLoot) saleActive
10 setPermit(1, burner, 0, burnUnsold(saleToken, deadline), keccak256("ShareBurner"), burner, 1) saleBurnDeadline > 0
11 RollbackGuardian.configure(guardian, expiry) — target is the singleton rollbackGuardian != 0
12 setPermit(0, dao, 0, bumpConfig(), keccak256("RollbackGuardian"), singleton, 1) rollbackGuardian != 0
13 setPermit(0, dao, 0, setAutoFutarchy(0,0), keccak256("RollbackGuardian.killFutarchy"), singleton, 1) rollbackGuardian != 0

Call 10 is a Delegatecall permit (op = 1): when the ShareBurner spends it, the DAO executes ShareBurner code in its own context. Calls 12 and 13 are ordinary call permits.


User Functions

Function: safeSummon(string,string,string,uint16,bool,address,bytes32,address[],uint256[],uint256[],SafeConfig,Call[])

The general entry point. Validates a caller-built SafeConfig, prepends initial loot mints, encodes the config into init calls, appends extraCalls, and summons through Summoner.

ATTRIBUTE VALUE
Selector 0x024b6d40
Parameters Org name, symbol, URI; quorumBps; ragequittable; renderer; salt; initHolders; initShares; initLoot; config; extraCalls
Access Anyone, payable
Returns The new DAO address
On-chain calls 0 of 121
FLAG OBSERVATION
△ extraCalls execute after every validated call and are not inspected. A trailing setProposalThreshold(0) or setProposalTTL(0) in extraCalls undoes the corresponding check
◇ initShares and initHolders are not checked for length equality here; Moloch.init enforces it (LengthMismatch)
◇ Loot mints are placed before extraCalls but after the config calls, in the order config → loot mints → extraCalls
◇ Never called directly on mainnet; all custom configurations went through safeSummonDAICO
CONDITION REQUIREMENT
Configuration _validate rules — see Validation Rules
initLoot Empty, or the same length as initHolders
STEP ACTION
1 _validate(quorumBps, config, initHolders.length)
2 Predict the DAO address from salt, initHolders, initShares
3 Build mintFromMoloch calls on the predicted Loot clone for each non-zero initLoot[i]
4 Concatenate loot mints and extraCalls; prepend the SafeConfig calls
5 SUMMONER.summon{value: msg.value}(...)
CONDITION REVERT MESSAGE
Any _validate rule fails NoInitialHolders, ProposalThresholdRequired, ProposalTTLRequired, QuorumBpsOutOfRange, TimelockExceedsTTL, QuorumRequiredForFutarchy, FutarchyCapRequired, MintingSaleWithDynamicQuorum, SalePriceRequired, RollbackSingletonRequired
Summoner CREATE2 collision (address already taken) 0x30116425 from Summoner
Any init call reverts inside Moloch.init NotOk() from the DAO
initLoot length mismatch InitLootLengthMismatch
function safeSummon(
    string calldata orgName,
    string calldata orgSymbol,
    string calldata orgURI,
    uint16 quorumBps,
    bool ragequittable,
    address renderer,
    bytes32 salt,
    address[] calldata initHolders,
    uint256[] calldata initShares,
    uint256[] calldata initLoot,
    SafeConfig calldata config,
    Call[] calldata extraCalls
) public payable returns (address dao) {
    // ── Validate ──────────────────────────────────────────────
    _validate(quorumBps, config, initHolders.length);
    if (initLoot.length != 0 && initLoot.length != initHolders.length) {
        revert InitLootLengthMismatch();
    }

    // ── Predict DAO address ───────────────────────────────────
    address daoAddr = _predictDAO(salt, initHolders, initShares);

    // ── Build initCalls ───────────────────────────────────────
    Call[] memory extra =
        _mergeExtra(_buildLootMints(daoAddr, initHolders, initLoot), extraCalls);
    Call[] memory calls = _buildCalls(daoAddr, config, extra);

    // ── Summon ────────────────────────────────────────────────
    dao = SUMMONER.summon{value: msg.value}(
        orgName,
        orgSymbol,
        orgURI,
        quorumBps,
        ragequittable,
        renderer,
        salt,
        initHolders,
        initShares,
        calls
    );
}

Function: safeSummonDAICO(string,string,string,uint16,bool,address,bytes32,address[],uint256[],uint256[],SafeConfig,SaleModule,TapModule,SeedModule,Call[])

safeSummon plus the three module structs that make up a Decentralized Autonomous Initial Coin Offering (DAICO) setup. Each module whose singleton is non-zero is wired to the DAO through allowances and a configure call executed by the DAO during init.

ATTRIBUTE VALUE
Selector 0x4e1e3b11
Parameters As safeSummon, plus sale, tap, seed
Access Anyone, payable
Returns The new DAO address
On-chain calls 9 of 121
FLAG OBSERVATION
△ Module singleton addresses are caller-supplied and unchecked. The DAO grants each an allowance and calls its configure as itself
△ The SeedModule share sentinel mints new shares to the DAO, increasing the supply that quorumBps is measured against while those shares sit with the DAO or in a pool
◇ Call order is config → loot mints → modules → extraCalls
◇ All nine on-chain calls used ShareSale 0x00000000...EA60f9 (etherscan) and/or TapVest 0x00000000...7bF56D (etherscan); none used a seed module
CONDITION REQUIREMENT
Single sale mechanism !(config.saleActive && sale.singleton != address(0))
Configuration _validate rules — see Validation Rules
Modules _validateModules — sale price set, minting sale needs quorumAbsolute, seed gate needs a sale
STEP ACTION
1 Validate config and modules
2 Predict the DAO address
3 Build loot mints and module calls against predicted addresses
4 Merge loot mints, module calls and extraCalls; prepend config calls
5 SUMMONER.summon{value: msg.value}(...)
CONDITION REVERT MESSAGE
Any _validate rule fails NoInitialHolders, ProposalThresholdRequired, ProposalTTLRequired, QuorumBpsOutOfRange, TimelockExceedsTTL, QuorumRequiredForFutarchy, FutarchyCapRequired, MintingSaleWithDynamicQuorum, SalePriceRequired, RollbackSingletonRequired
Summoner CREATE2 collision (address already taken) 0x30116425 from Summoner
Any init call reverts inside Moloch.init NotOk() from the DAO
Both sale paths set ModuleSaleConflict
Seed gated on a missing sale SeedGateWithoutSale
initLoot length mismatch InitLootLengthMismatch
function safeSummonDAICO(
    string calldata orgName,
    string calldata orgSymbol,
    string calldata orgURI,
    uint16 quorumBps,
    bool ragequittable,
    address renderer,
    bytes32 salt,
    address[] calldata initHolders,
    uint256[] calldata initShares,
    uint256[] calldata initLoot,
    SafeConfig calldata config,
    SaleModule calldata sale,
    TapModule calldata tap,
    SeedModule calldata seed,
    Call[] calldata extraCalls
) public payable returns (address dao) {
    if (config.saleActive && sale.singleton != address(0)) {
        revert ModuleSaleConflict();
    }
    _validate(quorumBps, config, initHolders.length);
    _validateModules(quorumBps, config.quorumAbsolute, sale, seed);
    if (initLoot.length != 0 && initLoot.length != initHolders.length) {
        revert InitLootLengthMismatch();
    }

    address daoAddr = _predictDAO(salt, initHolders, initShares);
    Call[] memory lootMints = _buildLootMints(daoAddr, initHolders, initLoot);
    Call[] memory modCalls = _buildModuleCalls(daoAddr, sale, tap, seed);

    // Merge: loot mints + modules + extraCalls
    Call[] memory allExtra = new Call[](lootMints.length + modCalls.length + extraCalls.length);
    uint256 idx;
    for (uint256 j; j < lootMints.length; j++) {
        allExtra[idx++] = lootMints[j];
    }
    for (uint256 j; j < modCalls.length; j++) {
        allExtra[idx++] = modCalls[j];
    }
    for (uint256 j; j < extraCalls.length; j++) {
        allExtra[idx++] = extraCalls[j];
    }

    Call[] memory calls = _buildCalls(daoAddr, config, allExtra);

    dao = SUMMONER.summon{value: msg.value}(
        orgName,
        orgSymbol,
        orgURI,
        quorumBps,
        ragequittable,
        renderer,
        salt,
        initHolders,
        initShares,
        calls
    );
}

Function: summonStandard(string,string,string,bytes32,address[],uint256[],bool)

Preset: 7 days proposal time-to-live (TTL), 2 days timelock, quorumBps 1000, ragequit on, the hardcoded RENDERER, and a proposal threshold of 1% of the initial share total (floor 1).

ATTRIBUTE VALUE
Selector 0x8d797976
Parameters Name, symbol, URI, salt, initHolders, initShares, lockShares
Access Anyone, payable
Returns The new DAO address
On-chain calls 15 of 121
FLAG OBSERVATION
◇ No extraCalls parameter, so the validated values are the values the DAO starts with
△ The threshold is 1% of the initial supply only. A DAO launched with one share has a threshold of 0.01 shares regardless of later issuance
◇ _defaultThreshold sums initShares with checked arithmetic; an overflowing total reverts
CONDITION REVERT MESSAGE
Any _validate rule fails NoInitialHolders, ProposalThresholdRequired, ProposalTTLRequired, QuorumBpsOutOfRange, TimelockExceedsTTL, QuorumRequiredForFutarchy, FutarchyCapRequired, MintingSaleWithDynamicQuorum, SalePriceRequired, RollbackSingletonRequired
Summoner CREATE2 collision (address already taken) 0x30116425 from Summoner
Share total overflows uint256 Panic 0x11
function summonStandard(
    string calldata orgName,
    string calldata orgSymbol,
    string calldata orgURI,
    bytes32 salt,
    address[] calldata initHolders,
    uint256[] calldata initShares,
    bool lockShares
) public payable returns (address) {
    SafeConfig memory c;
    c.proposalThreshold = _defaultThreshold(initShares);
    c.proposalTTL = 7 days;
    c.timelockDelay = 2 days;
    c.lockShares = lockShares;
    return
        _summonPreset(orgName, orgSymbol, orgURI, 1000, true, salt, initHolders, initShares, c);
}

Function: summonFast(string,string,string,bytes32,address[],uint256[],bool)

Preset: 3 days proposal TTL, 1 day timelock, quorumBps 500, ragequit on, the hardcoded RENDERER, and a proposal threshold of 1% of the initial share total (floor 1).

ATTRIBUTE VALUE
Selector 0x91ea2453
Parameters Name, symbol, URI, salt, initHolders, initShares, lockShares
Access Anyone, payable
Returns The new DAO address
On-chain calls 3 of 121
FLAG OBSERVATION
◇ No extraCalls parameter, so the validated values are the values the DAO starts with
△ The threshold is 1% of the initial supply only. A DAO launched with one share has a threshold of 0.01 shares regardless of later issuance
◇ _defaultThreshold sums initShares with checked arithmetic; an overflowing total reverts
CONDITION REVERT MESSAGE
Any _validate rule fails NoInitialHolders, ProposalThresholdRequired, ProposalTTLRequired, QuorumBpsOutOfRange, TimelockExceedsTTL, QuorumRequiredForFutarchy, FutarchyCapRequired, MintingSaleWithDynamicQuorum, SalePriceRequired, RollbackSingletonRequired
Summoner CREATE2 collision (address already taken) 0x30116425 from Summoner
Share total overflows uint256 Panic 0x11
function summonFast(
    string calldata orgName,
    string calldata orgSymbol,
    string calldata orgURI,
    bytes32 salt,
    address[] calldata initHolders,
    uint256[] calldata initShares,
    bool lockShares
) public payable returns (address) {
    SafeConfig memory c;
    c.proposalThreshold = _defaultThreshold(initShares);
    c.proposalTTL = 3 days;
    c.timelockDelay = 1 days;
    c.lockShares = lockShares;
    return
        _summonPreset(orgName, orgSymbol, orgURI, 500, true, salt, initHolders, initShares, c);
}

Function: summonFounder(string,string,string,bytes32)

Preset for a single founder: msg.sender receives 10,000,000 shares, the threshold is 100,000 shares, TTL is one day, there is no timelock, quorumBps is 1000 and ragequit is on.

ATTRIBUTE VALUE
Selector 0xc7d43a7d
Parameters Name, symbol, URI, salt
Access Anyone, payable
Returns The new DAO address
On-chain calls 3 of 121
FLAG OBSERVATION
△ Produces a single-key DAO. The founder alone meets quorum and majority, and with no timelock a passing proposal executes immediately
◇ Skips _validate; the hardcoded values satisfy every rule
◇ Duplicates the _predictDAO arithmetic inline because the holder arrays are built in memory rather than received as calldata
CONDITION REVERT MESSAGE
Summoner CREATE2 collision (address already taken) 0x30116425 from Summoner
Any init call reverts inside Moloch.init NotOk() from the DAO
function summonFounder(
    string calldata orgName,
    string calldata orgSymbol,
    string calldata orgURI,
    bytes32 salt
) public payable returns (address) {
    address[] memory h = new address[](1);
    h[0] = msg.sender;
    uint256[] memory s = new uint256[](1);
    s[0] = 10_000_000e18;

    SafeConfig memory c;
    c.proposalThreshold = 100_000e18; // 1% of 10M
    c.proposalTTL = 1 days;

    // Inline prediction (can't pass memory arrays to calldata _predictDAO)
    bytes32 _salt = keccak256(abi.encode(h, s, salt));
    address daoAddr = address(
        uint160(
            uint256(
                keccak256(
                    abi.encodePacked(
                        bytes1(0xff),
                        address(SUMMONER),
                        _salt,
                        keccak256(
                            abi.encodePacked(
                                hex"602d5f8160095f39f35f5f365f5f37365f73",
                                MOLOCH_IMPL,
                                hex"5af43d5f5f3e6029573d5ffd5b3d5ff3"
                            )
                        )
                    )
                )
            )
        )
    );

    Call[] memory extra = new Call[](0);
    Call[] memory calls = _buildCalls(daoAddr, c, extra);

    return SUMMONER.summon{value: msg.value}(
        orgName, orgSymbol, orgURI, 1000, true, RENDERER, salt, h, s, calls
    );
}

Function: summonStandardDAICO(string,string,string,bytes32,address[],uint256[],bool,SaleModule,TapModule,SeedModule)

The Standard preset combined with the module structs of safeSummonDAICO. Routes through the internal _summonDAICOPreset, which validates config and modules, builds module calls, and summons with the hardcoded RENDERER.

ATTRIBUTE VALUE
Selector 0x94c2d76d
Parameters As the preset, plus sale, tap, seed
Access Anyone, payable
Returns The new DAO address
On-chain calls 0 of 121
FLAG OBSERVATION
△ A minting sale module reverts here with MintingSaleWithDynamicQuorum: the preset sets quorumBps but leaves quorumAbsolute at 0, and there is no parameter to supply one. Only non-minting sales are usable through these two presets
◇ No initLoot and no extraCalls
CONDITION REVERT MESSAGE
Any _validate rule fails NoInitialHolders, ProposalThresholdRequired, ProposalTTLRequired, QuorumBpsOutOfRange, TimelockExceedsTTL, QuorumRequiredForFutarchy, FutarchyCapRequired, MintingSaleWithDynamicQuorum, SalePriceRequired, RollbackSingletonRequired
Summoner CREATE2 collision (address already taken) 0x30116425 from Summoner
Any init call reverts inside Moloch.init NotOk() from the DAO
Minting sale module MintingSaleWithDynamicQuorum
Seed gated on a missing sale SeedGateWithoutSale
function summonStandardDAICO(
    string calldata orgName,
    string calldata orgSymbol,
    string calldata orgURI,
    bytes32 salt,
    address[] calldata initHolders,
    uint256[] calldata initShares,
    bool lockShares,
    SaleModule calldata sale,
    TapModule calldata tap,
    SeedModule calldata seed
) public payable returns (address) {
    SafeConfig memory c;
    c.proposalThreshold = _defaultThreshold(initShares);
    c.proposalTTL = 7 days;
    c.timelockDelay = 2 days;
    c.lockShares = lockShares;
    return _summonDAICOPreset(
        orgName,
        orgSymbol,
        orgURI,
        1000,
        true,
        salt,
        initHolders,
        initShares,
        c,
        sale,
        tap,
        seed
    );
}

Function: summonFastDAICO(string,string,string,bytes32,address[],uint256[],bool,SaleModule,TapModule,SeedModule)

The Fast preset combined with the module structs of safeSummonDAICO. Routes through the internal _summonDAICOPreset, which validates config and modules, builds module calls, and summons with the hardcoded RENDERER.

ATTRIBUTE VALUE
Selector 0x07f1831f
Parameters As the preset, plus sale, tap, seed
Access Anyone, payable
Returns The new DAO address
On-chain calls 0 of 121
FLAG OBSERVATION
△ A minting sale module reverts here with MintingSaleWithDynamicQuorum: the preset sets quorumBps but leaves quorumAbsolute at 0, and there is no parameter to supply one. Only non-minting sales are usable through these two presets
◇ No initLoot and no extraCalls
CONDITION REVERT MESSAGE
Any _validate rule fails NoInitialHolders, ProposalThresholdRequired, ProposalTTLRequired, QuorumBpsOutOfRange, TimelockExceedsTTL, QuorumRequiredForFutarchy, FutarchyCapRequired, MintingSaleWithDynamicQuorum, SalePriceRequired, RollbackSingletonRequired
Summoner CREATE2 collision (address already taken) 0x30116425 from Summoner
Any init call reverts inside Moloch.init NotOk() from the DAO
Minting sale module MintingSaleWithDynamicQuorum
Seed gated on a missing sale SeedGateWithoutSale
function summonFastDAICO(
    string calldata orgName,
    string calldata orgSymbol,
    string calldata orgURI,
    bytes32 salt,
    address[] calldata initHolders,
    uint256[] calldata initShares,
    bool lockShares,
    SaleModule calldata sale,
    TapModule calldata tap,
    SeedModule calldata seed
) public payable returns (address) {
    SafeConfig memory c;
    c.proposalThreshold = _defaultThreshold(initShares);
    c.proposalTTL = 3 days;
    c.timelockDelay = 1 days;
    c.lockShares = lockShares;
    return _summonDAICOPreset(
        orgName, orgSymbol, orgURI, 500, true, salt, initHolders, initShares, c, sale, tap, seed
    );
}

Function: create2Deploy(bytes,bytes32)

Deploys arbitrary creation bytecode with CREATE2 from SafeSummoner's address, forwarding msg.value to the new contract. Unrelated to DAO summoning; the most-called function (91 of 121 transactions).

ATTRIBUTE VALUE
Selector 0x94d6f6d4
Parameters creationCode (with constructor arguments appended), salt
Access Anyone, payable
Returns The deployed address
On-chain calls 91 of 121 (90 succeeded)
FLAG OBSERVATION
△ The salt is not bound to the caller. Anyone can deploy the same creationCode and salt first; the result is the same contract at the same address, and the original call then reverts
◇ The deployed contract's constructor sees msg.sender == SafeSummoner. A constructor that made msg.sender its owner would leave ownership with a contract that cannot exercise it. A scan of the 79 verified deployments found no constructor doing so
◇ Deterministic per (bytecode, salt). Leading-zero vanity addresses such as TokenList's 0x00000060...531524 (etherscan) are found off-chain by grinding the salt
STEP ACTION
1 Copy creationCode to memory
2 create2(callvalue(), ptr, len, salt)
CONDITION REVERT MESSAGE
Address already has code, constructor reverted, or insufficient balance for callvalue Create2Failed
function create2Deploy(bytes calldata creationCode, bytes32 salt)
    public
    payable
    returns (address deployed)
{
    assembly ("memory-safe") {
        let ptr := mload(0x40)
        calldatacopy(ptr, creationCode.offset, creationCode.length)
        deployed := create2(callvalue(), ptr, creationCode.length, salt)
    }
    if (deployed == address(0)) revert Create2Failed();
}

Function: multicall(bytes[])

Executes each entry as a delegatecall into SafeSummoner itself and returns the results. Intended for sequences such as deploying a module with create2Deploy and summoning a DAO that uses it, in one transaction.

ATTRIBUTE VALUE
Selector 0xac9650d8
Parameters data — an array of encoded SafeSummoner calls
Access Anyone, payable
Returns bytes[] results
On-chain calls 0 of 121
FLAG OBSERVATION
△ msg.value is visible to every sub-call and each payable sub-call forwards it in full. With two payable sub-calls the contract sends 2 × msg.value; the difference comes from SafeSummoner's own balance. Confirmed by simulation
◇ Non-payable helpers (predictDAO, previewCalls and the rest) revert inside a multicall sent with value, because delegatecall preserves msg.value and the callee's value check fires
◇ SafeSummoner has no storage, so self-delegatecall cannot corrupt state
CONDITION REVERT MESSAGE
Any sub-call reverts The sub-call's revert data, bubbled verbatim
function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {
    results = new bytes[](data.length);
    for (uint256 i; i != data.length; ++i) {
        (bool ok, bytes memory result) = address(this).delegatecall(data[i]);
        if (!ok) {
            assembly ("memory-safe") {
                revert(add(result, 0x20), mload(result))
            }
        }
        results[i] = result;
    }
}

View Functions

Function: predictDAO(bytes32,address[],uint256[])

Returns the address Summoner will deploy a DAO to for the given salt, holders and shares.

ATTRIBUTE VALUE
Selector 0x7d64e7d8
Parameters salt, initHolders, initShares
Access Anyone, pure
Returns Predicted DAO address
FLAG OBSERVATION
△ The prediction does not depend on the caller or the init calls. Any party can summon at this address with different init calls; confirmed by simulation
☑ Held for all 30 DAOs summoned through SafeSummoner: each stores the threshold and TTL its init calls wrote to the predicted address
function predictDAO(bytes32 salt, address[] calldata initHolders, uint256[] calldata initShares)
    public
    pure
    returns (address)
{
    return _predictDAO(salt, initHolders, initShares);
}

Function: predictShares(address)

Returns the Shares clone address for a DAO: CREATE2 from the DAO with salt bytes32(bytes20(dao)) over the clone code for SHARES_IMPL.

ATTRIBUTE VALUE
Selector 0x78923610
Parameters dao
Access Anyone, pure
Returns Predicted Shares address
FLAG OBSERVATION
☑ Matched dao.shares() for all 30 DAOs
function predictShares(address dao) public pure returns (address) {
    return _predictShares(dao);
}

Function: predictLoot(address)

Returns the Loot clone address for a DAO, as predictShares with LOOT_IMPL.

ATTRIBUTE VALUE
Selector 0x6de0b938
Parameters dao
Access Anyone, pure
Returns Predicted Loot address
FLAG OBSERVATION
☑ Matched dao.loot() for all 30 DAOs
function predictLoot(address dao) public pure returns (address) {
    return _predictLoot(dao);
}

Function: predictCreate2(bytes,bytes32)

Returns the address create2Deploy would deploy creationCode to with salt.

ATTRIBUTE VALUE
Selector 0x98b44bb6
Parameters creationCode, salt
Access Anyone, view
Returns Predicted address
function predictCreate2(bytes calldata creationCode, bytes32 salt)
    public
    view
    returns (address)
{
    return address(
        uint160(
            uint256(
                keccak256(
                    abi.encodePacked(bytes1(0xff), address(this), salt, keccak256(creationCode))
                )
            )
        )
    );
}

Function: previewCalls(SafeConfig)

Returns the init calls _buildCalls would generate for a config, with address(0) standing in for the DAO.

ATTRIBUTE VALUE
Selector 0x03666cdd
Parameters config
Access Anyone, pure
Returns Call[]
FLAG OBSERVATION
△ Every address derived from the DAO is wrong in the preview — the targets are address(0), and the ShareBurner's burnUnsold argument is the Shares or Loot address predicted from address(0). The output shows structure, not the calldata that will execute
function previewCalls(SafeConfig calldata config) public pure returns (Call[] memory) {
    Call[] memory empty = new Call[](0);
    return _buildCalls(address(0), config, empty);
}

Function: previewModuleCalls(SaleModule,TapModule,SeedModule)

Returns the module init calls _buildModuleCalls would generate, with address(0) as the DAO.

ATTRIBUTE VALUE
Selector 0x0e1adbf1
Parameters sale, tap, seed
Access Anyone, pure
Returns Call[]
FLAG OBSERVATION
△ The NatSpec says sentinel tokens "resolve to predicted addresses"; they resolve to addresses predicted from address(0), not from the eventual DAO
function previewModuleCalls(
    SaleModule calldata sale,
    TapModule calldata tap,
    SeedModule calldata seed
) public pure returns (Call[] memory) {
    return _buildModuleCalls(address(0), sale, tap, seed);
}

Function: burnPermitCall(bytes32,address[],uint256[],uint256,address)

Builds the setPermit call that lets a ShareBurner burn a DAO's unsold shares after deadline, for DAOs that add the burn outside the SafeConfig path.

ATTRIBUTE VALUE
Selector 0x59c75af0
Parameters salt, initHolders, initShares, deadline, singleton (address(0) = SHARE_BURNER)
Access Anyone, pure
Returns A single Call
FLAG OBSERVATION
◇ Always targets the Shares token. The SafeConfig path picks Shares or Loot from saleIsLoot; this helper has no such option
△ The permit id includes the DAO's config counter. Any bumpConfig executed after the permit is set leaves it unspendable
function burnPermitCall(
    bytes32 salt,
    address[] calldata initHolders,
    uint256[] calldata initShares,
    uint256 deadline,
    address singleton
) public pure returns (Call memory) {
    address burner = singleton == address(0) ? SHARE_BURNER : singleton;
    address dao = _predictDAO(salt, initHolders, initShares);
    address sharesAddr = _predictShares(dao);
    bytes memory burnData = abi.encodeCall(IShareBurner.burnUnsold, (sharesAddr, deadline));
    return Call(
        dao,
        0,
        abi.encodeCall(
            IMoloch.setPermit,
            (
                uint8(1),
                burner,
                uint256(0),
                burnData,
                keccak256("ShareBurner"),
                burner,
                uint256(1)
            )
        )
    );
}