Nouns DAO contest - rotcivegaf'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: 132/160

Findings: 1

Award: $16.66

🌟 Selected for report: 0

🚀 Solo Findings: 0

Gas report

[G-01] Caching length on for and use unchecked for increment

In NounsDAOLogicV1.sol: L281, L319, L346, L371 In NounsDAOLogicV2.sol: L292, L330, L357, L382

Example:

From:

for (uint256 i; i < array.length; i++) {
  ...
}

To:

uint256 arrayLength = array.length;

for (uint256 i; i < arrayLength;) {
  ...
  unchecked {
    ++i;
  }
}

[G-02] In NounsDAOLogicV1.sol#L617 and NounsDAOLogicV2.sol#L819: The msg.sender != address(0) it's redundant

[G-03] The id in the Proposal and ProposalCondensed structs it's redundant

To simplify code and save gas, remove the id of the structs

In NounsDAOInterfaces.sol file remove the lines: L175-L176, L275-L276, L369-L370

In NounsDAOLogicV1 contract change L216-L267:

-       proposalCount++;
-       Proposal storage newProposal = proposals[proposalCount];
+       uint256 _proposalCount = ++proposalCount;
+       Proposal storage newProposal = proposals[_proposalCount];

-       newProposal.id = proposalCount;
        newProposal.proposer = msg.sender;
        newProposal.proposalThreshold = temp.proposalThreshold;
        newProposal.quorumVotes = bps2Uint(quorumVotesBPS, temp.totalSupply);
        newProposal.eta = 0;
        newProposal.targets = targets;
        newProposal.values = values;
        newProposal.signatures = signatures;
        newProposal.calldatas = calldatas;
        newProposal.startBlock = temp.startBlock;
        newProposal.endBlock = temp.endBlock;
        newProposal.forVotes = 0;
        newProposal.againstVotes = 0;
        newProposal.abstainVotes = 0;
        newProposal.canceled = false;
        newProposal.executed = false;
        newProposal.vetoed = false;

-       latestProposalIds[newProposal.proposer] = newProposal.id;
+       latestProposalIds[newProposal.proposer] = _proposalCount;

        /// @notice Maintains backwards compatibility with GovernorBravo events
        emit ProposalCreated(
-           newProposal.id,
+           _proposalCount,
            msg.sender,
            targets,
            values,
            signatures,
            calldatas,
            newProposal.startBlock,
            newProposal.endBlock,
            description
        );

        /// @notice Updated event with `proposalThreshold` and `quorumVotes`
        emit ProposalCreatedWithRequirements(
-           newProposal.id,
+           _proposalCount,
            msg.sender,
            targets,
            values,
            signatures,
            calldatas,
            newProposal.startBlock,
            newProposal.endBlock,
            newProposal.proposalThreshold,
            newProposal.quorumVotes,
            description
        );

-       return newProposal.id;
+       return _proposalCount;

In NounsDAOLogicV2 contract

-       proposalCount++;
-       Proposal storage newProposal = _proposals[proposalCount];
-       newProposal.id = proposalCount;
+       uint256 _proposalCount = ++proposalCount;
+       Proposal storage newProposal = _proposals[_proposalCount];
        newProposal.proposer = msg.sender;
        newProposal.proposalThreshold = temp.proposalThreshold;
        newProposal.eta = 0;
        newProposal.targets = targets;
        newProposal.values = values;
        newProposal.signatures = signatures;
        newProposal.calldatas = calldatas;
        newProposal.startBlock = temp.startBlock;
        newProposal.endBlock = temp.endBlock;
        newProposal.forVotes = 0;
        newProposal.againstVotes = 0;
        newProposal.abstainVotes = 0;
        newProposal.canceled = false;
        newProposal.executed = false;
        newProposal.vetoed = false;
        newProposal.totalSupply = temp.totalSupply;
        newProposal.creationBlock = block.number;

-       latestProposalIds[newProposal.proposer] = newProposal.id;
+       latestProposalIds[newProposal.proposer] = _proposalCount;

        /// @notice Maintains backwards compatibility with GovernorBravo events
        emit ProposalCreated(
-           newProposal.id,
+           _proposalCount,
            msg.sender,
            targets,
            values,
            signatures,
            calldatas,
            newProposal.startBlock,
            newProposal.endBlock,
            description
        );

        /// @notice Updated event with `proposalThreshold` and `minQuorumVotes`
        /// @notice `minQuorumVotes` is always zero since V2 introduces dynamic quorum with checkpoints
        emit ProposalCreatedWithRequirements(
-           newProposal.id,
+           _proposalCount,
            msg.sender,
            targets,
            values,
            signatures,
            calldatas,
            newProposal.startBlock,
            newProposal.endBlock,
            newProposal.proposalThreshold,
            minQuorumVotes(),
            description
        );

-       return newProposal.id;
+       return _proposalCount;
-        } else if (proposal.forVotes <= proposal.againstVotes || proposal.forVotes < quorumVotes(proposal.id)) {
+        } else if (proposal.forVotes <= proposal.againstVotes || proposal.forVotes < quorumVotes(proposalId)) {
-               id: proposal.id,
                proposer: proposal.proposer,
                proposalThreshold: proposal.proposalThreshold,
-               quorumVotes: quorumVotes(proposal.id),
+               quorumVotes: quorumVotes(proposalId),

[G-04] Use implementation_ to save SLOAD gas

In NounsDAOProxy.sol#L85 use implementation_ instead of implementation:

emit NewImplementation(oldImplementation, implementation_);
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