MerkleReserveMinter minting methodology is incompatible with current governance structure and can lead to migrated DAOs being hijacked immediately
MerkleReserveMinter allows large number of tokens to be minted instantaneously which is incompatible with the current governance structure which relies on tokens being minted individually and time locked after minting by the auction. By minting and creating a proposal in the same block a user is able to create a proposal with significantly lower quorum than expected. This could easily be used to hijack the migrated DAO.\\nMerkleReserveMinter.sol#L154-L167\\n```\\nunchecked {\\n    for (uint256 i = 0; i < claimCount; ++i) {\\n        // Load claim in memory\\n        MerkleClaim memory claim = claims[I];\\n\\n        // Requires one proof per tokenId to handle cases where users want to partially claim\\n        if (!MerkleProof.verify(claim.merkleProof, settings.merkleRoot, keccak256(abi.encode(claim.mintTo, claim.tokenId)))) {\\n            revert INVALID_MERKLE_PROOF(claim.mintTo, claim.merkleProof, settings.merkleRoot);\\n        }\\n\\n        // Only allowing reserved tokens to be minted for this strategy\\n        IToken(tokenContract).mintFromReserveTo(claim.mintTo, claim.tokenId);\\n    }\\n}\\n```\\n\\nWhen minting from the claim merkle tree, a user is able to mint as many tokens as they want in a single transaction. This means in a single transaction, the supply of the token can increase very dramatically. Now we'll take a look at the governor contract as to why this is such an issue.\\nGovernor.sol#L184-L192\\n```\\n    // Store the proposal data\\n    proposal.voteStart = SafeCast.toUint32(snapshot);\\n    proposal.voteEnd = SafeCast.toUint32(deadline);\\n    proposal.proposalThreshold = SafeCast.toUint32(currentProposalThreshold);\\n    proposal.quorumVotes = SafeCast.toUint32(quorum());\\n    proposal.proposer = msg.sender;\\n    proposal.timeCreated = SafeCast.toUint32(block.timestamp);\\n\\n    emit ProposalCreated(proposalId, _targets, _values, _calldatas, _description, descriptionHash, proposal);\\n```\\n\\nGovernor.sol#L495-L499\\n```\\nfunction quorum() public view returns (uint256) {\\n    unchecked {\\n        return (settings.token.totalSupply() * settings.quorumThresholdBps) / BPS_PER_100_PERCENT;\\n    }\\n}\\n```\\n\\nWhen creating a proposal, we see that it uses a snapshot of the CURRENT total supply. This is what leads to the issue. The setup is fairly straightforward and occurs all in a single transaction:\\nCreate a malicious proposal (which snapshots current supply)\\nMint all the tokens\\nVote on malicious proposal with all minted tokens\\nThe reason this works is because the quorum is based on the supply before the mint while votes are considered after the mint, allowing significant manipulation of the quorum.
Token should be changed to use a checkpoint based total supply, similar to how balances are handled. Quorum should be based on that instead of the current supply.
DOA can be completely hijacked
```\\nunchecked {\\n    for (uint256 i = 0; i < claimCount; ++i) {\\n        // Load claim in memory\\n        MerkleClaim memory claim = claims[I];\\n\\n        // Requires one proof per tokenId to handle cases where users want to partially claim\\n        if (!MerkleProof.verify(claim.merkleProof, settings.merkleRoot, keccak256(abi.encode(claim.mintTo, claim.tokenId)))) {\\n            revert INVALID_MERKLE_PROOF(claim.mintTo, claim.merkleProof, settings.merkleRoot);\\n        }\\n\\n        // Only allowing reserved tokens to be minted for this strategy\\n        IToken(tokenContract).mintFromReserveTo(claim.mintTo, claim.tokenId);\\n    }\\n}\\n```\\n