Nouns DAO contest - Chom's results

A DAO-driven NFT project on Ethereum.

General Information

Platform: Code4rena

Start Date: 22/08/2022

Pot Size: $50,000 USDC

Total HM: 4

Participants: 160

Period: 5 days

Judge: gzeon

Total Solo HM: 2

Id: 155

League: ETH

Nouns DAO

Findings Distribution

Researcher Performance

Rank: 73/160

Findings: 2

Award: $52.10

🌟 Selected for report: 0

🚀 Solo Findings: 0

Anyone can create proposal without holding any NFT if they borrow NFT then create proposal then return it

https://github.com/code-423n4/2022-08-nounsdao/blob/c1c7c6201d0247f92472419ff657b570f9104565/contracts/governance/NounsDAOLogicV2.sol#L197-L200

require( nouns.getPriorVotes(msg.sender, block.number - 1) > temp.proposalThreshold, 'NounsDAO::propose: proposer votes below proposal threshold' );
  1. Borrow Noun DAO NFT to have enough for passing proposalThreshold
  2. Wait for 1 block
  3. Create proposal, proposalThreshold will be passed since we are holding enough Noun DAO NFT
  4. Return Noun DAO NFT

Validate targets[i] != address(0) on proposal creation

https://github.com/code-423n4/2022-08-nounsdao/blob/c1c7c6201d0247f92472419ff657b570f9104565/contracts/governance/NounsDAOLogicV2.sol#L184-L190

function propose( address[] memory targets, uint256[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description ) public returns (uint256) {

Each member of targets shouldn't be address(0) but it haven't been validated yet

Add unchecked

https://github.com/code-423n4/2022-08-nounsdao/blob/c1c7c6201d0247f92472419ff657b570f9104565/contracts/governance/NounsDAOLogicV2.sol#L291

unchecked { uint256 eta = block.timestamp + timelock.delay(); }

delay shouldn't large so it won't overflow uint256

Add unchecked

https://github.com/code-423n4/2022-08-nounsdao/blob/c1c7c6201d0247f92472419ff657b570f9104565/contracts/governance/NounsDAOLogicV2.sol#L948-L960

unchecked { uint256 lower = 0; uint256 upper = len - 1; while (upper > lower) { uint256 center = upper - (upper - lower) / 2; DynamicQuorumParamsCheckpoint memory cp = quorumParamsCheckpoints[center]; if (cp.fromBlock == blockNumber) { return cp.params; } else if (cp.fromBlock < blockNumber) { lower = center; } else { upper = center - 1; } } }

Binary search shouldn't overflow uint256

Use custom error instead of require

require(state(proposalId) != ProposalState.Executed, 'NounsDAO::cancel: cannot cancel executed proposal');

to

error ProposalExecuted(); if (state(proposalId) == ProposalState.Executed) revert ProposalExecuted();

Cache for loop length, Use ++i instead of i++ and add unchecked

for (uint256 i = 0; i < proposal.targets.length; i++) {

to

uint256 targetsLength = proposal.targets.length; for (uint256 i = 0; i < targetsLength; ) { ... unchecked { ++i; } }
AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter