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
Rank: 29/160
Findings: 2
Award: $58.07
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0bi, 0x040, 0x1337, 0x1f8b, 0xDjango, 0xNazgul, 0xNineDec, 0xRajeev, 0xSky, 0xSmartContract, 0xbepresent, 0xkatana, 0xmatt, 8olidity, Aymen0909, Bjorn_bug, Bnke0x0, CertoraInc, Ch_301, Chom, CodingNameKiki, Deivitto, DevABDee, DimitarDimitrov, Dravee, ElKu, Funen, GalloDaSballo, GimelSec, Guardian, Haruxe, JC, JansenC, Jeiwan, JohnSmith, KIntern_NA, Lambda, LeoS, Noah3o6, Olivierdem, R2, RaymondFam, Respx, ReyAdmirado, Rohan16, Rolezn, Ruhum, Saintcode_, Sm4rty, SooYa, Soosh, TomJ, Tomo, Trabajo_de_mates, Waze, _Adam, __141345__, ajtra, android69, asutorufos, auditor0517, berndartmueller, bobirichman, brgltd, c3phas, cRat1st0s, carlitox477, catchup, cccz, csanuragjain, d3e4, delfin454000, dipp, djxploit, durianSausage, erictee, exd0tpy, fatherOfBlocks, gogo, hyh, ladboy233, lukris02, mics, mrpathfindr, natzuu, oyc_109, p_crypt0, pashov, pauliax, pfapostol, prasantgupta52, rajatbeladiya, rbserver, ret2basic, rfa, robee, rokinot, rvierdiiev, sach1r0, saian, seyni, shenwilly, sikorico, simon135, sryysryy, sseefried, throttle, tnevler, tonisives, wagmi, xiaoming90, yixxas, z3s, zkhorse, zzzitron
38.8441 USDC - $38.84
decimals()
, name()
and symbol()
are optional parts of the ERC20 specification, so there are tokens that
do not implement them. It’s not safe to cast arbitrary token addresses
in order to call these functions. If IERC20Metadata
is to be relied on, that should be the variable type of the token variable, rather than it being address
, so the compiler can verify that types correctly match, rather than this being a runtime failure. See this prior instance of this issue which was marked as Low risk. Do this to resolve the issue.):
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 135-136):
abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name())), getChainId(), address(this)) );
address(0x0)
when assigning values to address
state variables:File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 150-154):
vetoer = vetoer_; votingPeriod = votingPeriod_; votingDelay = votingDelay_; proposalThresholdBPS = proposalThresholdBPS_; quorumVotesBPS = quorumVotesBPS_;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 642):
vetoer = newVetoer;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol(line 156-159):
vetoer = vetoer_; votingPeriod = votingPeriod_; votingDelay = votingDelay_; proposalThresholdBPS = proposalThresholdBPS_;
File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 71):
admin = admin_;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 201):
_delegates[delegator] = delegatee;
initialize
functions can be front-run (See this finding from a prior badger-dao contest for details):File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 113):
function initialize(
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 124):
`function initialize(
permit()
calls is the same as the one used for delegateBySig()
.This should at the very least be documented so signers know that the
order of operations between the two functions matters, and so that multicall()
s can be organized appropriately):
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 141):
require(nonce == nonces[signatory]++, 'ERC721Checkpointable::delegateBySig: invalid nonce');
receive()
function will lock Ether in contract (If the intention is for the Ether to be used, the function should call another function, otherwise it should revert):File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 1030):
receive() external payable {}
File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 138-140):
receive() external payable { _fallback(); }
The position can be withdrawed if current block timestamp is greater than the position’s expiration
However, when current block timestamp is equal to the position’s expiration (block.timestamp == positionExpirations
), the state is unknown (cannot be exercised or withdraw)):
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 142):
require(block.timestamp <= expiry, 'ERC721Checkpointable::delegateBySig: signature expired');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 438):
} else if (block.timestamp >= proposal.eta + timelock.GRACE_PERIOD()) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol(line 449):
} else if (block.timestamp >= proposal.eta + timelock.GRACE_PERIOD()) {
##Non-Critical Issues
return
statement when the function defines a named return variable, is redundant:File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 522):
return votes;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 681):
return chainId;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol(line 267):
return newProposal.id;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 278):
return newProposal.id;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 614):
return votes;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 1027):
return chainId;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 287):
return chainId;
require()
/revert()
statements should have descriptive reason strings:File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 98):
revert(add(returnData, 0x20), returndatasize())
File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 118):
revert(free_mem_ptr, returndatasize())
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 1019):
require(n <= type(uint32).max, errorMessage);
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 254):
require(n < 2**32, errorMessage);
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 259):
require(n < 2**96, errorMessage);
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 269):
require(c >= a, errorMessage);
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 278):
require(b <= a, errorMessage);
File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 98):
revert(add(returnData, 0x20), returndatasize())
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 673):
return (number * bps) / 10000;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 908-909):
uint256 againstVotesBPS = (10000 * againstVotes) / totalSupply; uint256 quorumAdjustmentBPS = (params.quorumCoefficient * againstVotesBPS) / 1e6;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 254):
require(n < 2**32, errorMessage);
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 259):
require(n < 2**96, errorMessage);
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 851):
uint256 center = upper - (upper - lower) / 2;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 1007):
return (number * bps) / 10000;
File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 98):
revert(add(returnData, 0x20), returndatasize())
File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 113):
let free_mem_ptr := mload(0x40)
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol(line 184):
uint32 center = upper - (upper - lower) / 2;
string.concat()
to be used instead of abi.encodePacked(<str>,<str>)
):File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 61):
pragma solidity ^0.8.6;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 53):
pragma solidity ^0.8.6;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 35):
pragma solidity ^0.8.6;
string.concat()
to be used instead of abi.encodePacked(<str>,<str>)
):File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 37-62):
` event ProposalCreated( uint256 id, address proposer, address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, uint256 startBlock, uint256 endBlock, string description );
/// @notice An event emitted when a new proposal is created, which includes additional information event ProposalCreatedWithRequirements( uint256 id, address proposer, address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, uint256 startBlock, uint256 endBlock, uint256 proposalThreshold, uint256 quorumVotes, string description );`
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 70):
event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 votes, string reason);
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 76):
event ProposalQueued(uint256 id, uint256 eta);
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 85-106):
` event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);
/// @notice An event emitted when the voting period is set event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);
/// @notice Emitted when implementation is changed event NewImplementation(address oldImplementation, address newImplementation);
/// @notice Emitted when proposal threshold basis points is set event ProposalThresholdBPSSet(uint256 oldProposalThresholdBPS, uint256 newProposalThresholdBPS);
/// @notice Emitted when quorum votes basis points is set event QuorumVotesBPSSet(uint256 oldQuorumVotesBPS, uint256 newQuorumVotesBPS);
/// @notice Emitted when pendingAdmin is changed event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
/// @notice Emitted when pendingAdmin is accepted, which means admin is updated event NewAdmin(address oldAdmin, address newAdmin);
/// @notice Emitted when vetoer is changed event NewVetoer(address oldVetoer, address newVetoer)`
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 111-123):
` event MinQuorumVotesBPSSet(uint16 oldMinQuorumVotesBPS, uint16 newMinQuorumVotesBPS);
/// @notice Emitted when maxQuorumVotesBPS is set event MaxQuorumVotesBPSSet(uint16 oldMaxQuorumVotesBPS, uint16 newMaxQuorumVotesBPS);
/// @notice Emitted when quorumCoefficient is set event QuorumCoefficientSet(uint32 oldQuorumCoefficient, uint32 newQuorumCoefficient);
/// @notice Emitted when a voter cast a vote requesting a gas refund. event RefundableVote(address indexed voter, uint256 refundAmount, bool refundSent);
/// @notice Emitted when admin withdraws the DAO's balance. event Withdraw(uint256 amount, bool sent);`
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 73):
event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);
File: 2022-08-nounsdao/contracts/base/ERC721Enumerable.sol (line 1):
// SPDX-License-Identifier: MIT
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 204-208):
bool canceled; /// @notice Flag marking whether the proposal has been vetoed bool vetoed; /// @notice Flag marking whether the proposal has been executed bool executed;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 216):
bool hasVoted;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 304-308):
bool canceled; /// @notice Flag marking whether the proposal has been vetoed bool vetoed; /// @notice Flag marking whether the proposal has been executed bool executed;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 320):
bool hasVoted;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 390-394):
bool canceled; /// @notice Flag marking whether the proposal has been vetoed bool vetoed; /// @notice Flag marking whether the proposal has been executed bool executed;
public
functions not called by the contract should be declared external
instead (Contracts are allowed to override their parents’ functions and change the visibility from public
to external
):File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 649):
function _burnVetoPower() public {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 660):
function proposalThreshold() public view returns (uint256) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 668):
function quorumVotes() public view returns (uint256) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 851):
function _burnVetoPower() public {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 862):
function proposalThreshold() public view returns (uint256) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 995):
function minQuorumVotes() public view returns (uint256) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 1002):
function maxQuorumVotes() public view returns (uint256) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 76-85):
` uint256 public constant MIN_VOTING_PERIOD = 5_760; // About 24 hours
/// @notice The max setable voting period uint256 public constant MAX_VOTING_PERIOD = 80_640; // About 2 weeks
/// @notice The min setable voting delay uint256 public constant MIN_VOTING_DELAY = 1;
/// @notice The max setable voting delay uint256 public constant MAX_VOTING_DELAY = 40_320; // About 1 week`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 68-77):
` uint256 public constant MIN_VOTING_PERIOD = 5_760; // About 24 hours
/// @notice The max setable voting period uint256 public constant MAX_VOTING_PERIOD = 80_640; // About 2 weeks
/// @notice The min setable voting delay uint256 public constant MIN_VOTING_DELAY = 1;
/// @notice The max setable voting delay uint256 public constant MAX_VOTING_DELAY = 40_320; // About 1 week`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 97-101):
` bytes32 public constant DOMAIN_TYPEHASH = keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');
/// @notice The EIP-712 typehash for the ballot struct used by the contract bytes32 public constant BALLOT_TYPEHASH = keccak256('Ballot(uint256 proposalId,uint8 support)');`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 101-105):
` bytes32 public constant DOMAIN_TYPEHASH = keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');
/// @notice The EIP-712 typehash for the ballot struct used by the contract bytes32 public constant BALLOT_TYPEHASH = keccak256('Ballot(uint256 proposalId,uint8 support)');`
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 59-64):
` bytes32 public constant DOMAIN_TYPEHASH = keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');
/// @notice The EIP-712 typehash for the delegation struct used by the contract bytes32 public constant DELEGATION_TYPEHASH = keccak256('Delegation(address delegatee,uint256 nonce,uint256 expiry)');`
the interfaces directory. The interfaces below do not follow this pattern):
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 402):
interface INounsDAOExecutor {
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 436):
interface NounsTokenLike {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 61):
pragma solidity ^0.8.6;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 53):
pragma solidity ^0.8.6;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 33):
pragma solidity ^0.8.6;
File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 36):
pragma solidity ^0.8.6;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 35):
pragma solidity ^0.8.6;
File: 2022-08-nounsdao/contracts/base/ERC721Enumerable.sol (line 28):
pragma solidity ^0.8.0;
assembly{ id := chainid() }
=> uint256 id = block.chainid
, assembly { size := extcodesize() }
=> uint256 size = address().code.length
):File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 679):
chainId := chainid()
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 1013):
chainId := chainid()
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 285):
chainId := chainid()
🌟 Selected for report: IllIllI
Also found by: 0x040, 0x1f8b, 0xDjango, 0xNazgul, 0xNineDec, 0xSmartContract, 0xbepresent, 0xc0ffEE, 0xkatana, 2997ms, ACai, Amithuddar, Aymen0909, Ben, BipinSah, Bjorn_bug, Bnke0x0, CertoraInc, Ch_301, Chom, CodingNameKiki, Deivitto, DevABDee, DimitarDimitrov, Diraco, Dravee, ElKu, EthLedger, Fitraldys, Funen, GalloDaSballo, GimelSec, Guardian, IgnacioB, JC, JohnSmith, Junnon, KIntern_NA, Lambda, LeoS, Noah3o6, Olivierdem, Polandia94, R2, Randyyy, RaymondFam, Respx, ReyAdmirado, Rohan16, RoiEvenHaim, Rolezn, Ruhum, SaharAP, Saintcode_, SerMyVillage, Shishigami, Sm4rty, SooYa, TomJ, Tomio, Tomo, Waze, Yiko, _Adam, __141345__, a12jmx, ajtra, ak1, bobirichman, brgltd, bulej93, c3phas, cRat1st0s, carlitox477, catchup, ch0bu, d3e4, delfin454000, djxploit, durianSausage, erictee, exolorkistis, fatherOfBlocks, francoHacker, gogo, hyh, ignacio, jag, joestakey, karanctf, ladboy233, lucacez, lukris02, m_Rassska, martin, medikko, mics, mrpathfindr, natzuu, newfork01, oyc_109, pauliax, peritoflores, pfapostol, prasantgupta52, rbserver, ret2basic, rfa, robee, rokinot, rotcivegaf, rvierdiiev, sach1r0, saian, samruna, seyni, shark, shr1ftyy, sikorico, simon135, sryysryy, tay054, tnevler, wagmi, zishansami
19.2277 USDC - $19.23
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 128-134):
` address public admin;
/// @notice Pending administrator for this contract address public pendingAdmin;
/// @notice Active brains of Governor address public implementation;`
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 145-166):
` address public vetoer;
/// @notice The delay before voting on a proposal may take place, once proposed, in blocks uint256 public votingDelay;
/// @notice The duration of voting on a proposal, in blocks uint256 public votingPeriod;
/// @notice The basis point number of votes required in order for a voter to become a proposer. *DIFFERS from GovernerBravo uint256 public proposalThresholdBPS;
/// @notice The basis point number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed. *DIFFERS from GovernerBravo uint256 public quorumVotesBPS;
/// @notice The total number of proposals uint256 public proposalCount;
/// @notice The address of the Nouns DAO Executor NounsDAOExecutor INounsDAOExecutor public timelock;
/// @notice The address of the Nouns tokens NounsTokenLike public nouns;`
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 245-266):
` address public vetoer;
/// @notice The delay before voting on a proposal may take place, once proposed, in blocks uint256 public votingDelay;
/// @notice The duration of voting on a proposal, in blocks uint256 public votingPeriod;
/// @notice The basis point number of votes required in order for a voter to become a proposer. *DIFFERS from GovernerBravo uint256 public proposalThresholdBPS;
/// @notice The basis point number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed. *DIFFERS from GovernerBravo uint256 public quorumVotesBPS;
/// @notice The total number of proposals uint256 public proposalCount;
/// @notice The address of the Nouns DAO Executor NounsDAOExecutor INounsDAOExecutor public timelock;
/// @notice The address of the Nouns tokens NounsTokenLike public nouns;`
function or by the constructor, avoids a separate Gsset (20000 gas). Reads of the variables are also cheaper):
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 128):
'address public admin;'
<array>.length
should not be looked up in every loop of a forloop
(Even memory arrays incur the overhead of bit tests and bit shifts tocalculate the array length. Storage array length checks incur an extra Gwarmaccess (100 gas) PER-LOOP.):
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 281):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 319):
for (uint256 i = 0; i < proposal.targets.length; i++) {;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 346):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 371):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 292):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 330):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 375):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 382):
for (uint256 i = 0; i < proposal.targets.length; i++) {
++i/i++
should be unchecked{++i}
/unchecked{++i}
when it is not possible for them to overflow, as is the case when used in for
and while
loops:File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 281):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 319):
for (uint256 i = 0; i < proposal.targets.length; i++) {;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 346):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 371):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 292):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 330):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 375):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 382):
for (uint256 i = 0; i < proposal.targets.length; i++) {
require()
/revert()
strings longer than 32 bytes cost extra gas:File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 122-141):
require(address(timelock) == address(0), 'NounsDAO::initialize: can only initialize once'); require(msg.sender == admin, 'NounsDAO::initialize: admin only'); require(timelock_ != address(0), 'NounsDAO::initialize: invalid timelock address'); require(nouns_ != address(0), 'NounsDAO::initialize: invalid nouns address'); require( votingPeriod_ >= MIN_VOTING_PERIOD && votingPeriod_ <= MAX_VOTING_PERIOD, 'NounsDAO::initialize: invalid voting period' ); require( votingDelay_ >= MIN_VOTING_DELAY && votingDelay_ <= MAX_VOTING_DELAY, 'NounsDAO::initialize: invalid voting delay' ); require( proposalThresholdBPS_ >= MIN_PROPOSAL_THRESHOLD_BPS && proposalThresholdBPS_ <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::initialize: invalid proposal threshold' ); require( quorumVotesBPS_ >= MIN_QUORUM_VOTES_BPS && quorumVotesBPS_ <= MAX_QUORUM_VOTES_BPS, 'NounsDAO::initialize: invalid proposal threshold' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 187-198):
require( nouns.getPriorVotes(msg.sender, block.number - 1) > temp.proposalThreshold, 'NounsDAO::propose: proposer votes below proposal threshold' ); require( targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, 'NounsDAO::propose: proposal function information arity mismatch' ); require(targets.length != 0, 'NounsDAO::propose: must provide actions'); require(targets.length <= proposalMaxOperations, 'NounsDAO::propose: too many actions');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 203-210):
require( proposersLatestProposalState != ProposalState.Active, 'NounsDAO::propose: one live proposal per proposer, found an already active proposal' ); require( proposersLatestProposalState != ProposalState.Pending, 'NounsDAO::propose: one live proposal per proposer, found an already pending proposal' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 275-278):
require( state(proposalId) == ProposalState.Succeeded, 'NounsDAO::queue: proposal can only be queued if it is succeeded' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 301-304):
require( !timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), 'NounsDAO::queueOrRevertInternal: identical proposal action already queued at eta' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 313-316):
require( state(proposalId) == ProposalState.Queued, 'NounsDAO::execute: proposal can only be executed if it is queued' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 336-343):
`require(state(proposalId) != ProposalState.Executed, 'NounsDAO::cancel: cannot cancel executed proposal');
Proposal storage proposal = proposals[proposalId]; require( msg.sender == proposal.proposer || nouns.getPriorVotes(proposal.proposer, block.number - 1) < proposal.proposalThreshold, 'NounsDAO::cancel: proposer above threshold' );`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 366):
require(state(proposalId) != ProposalState.Executed, 'NounsDAO::veto: cannot veto executed proposal');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 485):
require(signatory != address(0), 'NounsDAO::castVoteBySig: invalid signature');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 501-505):
require(state(proposalId) == ProposalState.Active, 'NounsDAO::castVoteInternal: voting is closed'); require(support <= 2, 'NounsDAO::castVoteInternal: invalid vote type'); Proposal storage proposal = proposals[proposalId]; Receipt storage receipt = proposal.receipts[voter]; require(receipt.hasVoted == false, 'NounsDAO::castVoteInternal: voter already voted');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 530-534):
require(msg.sender == admin, 'NounsDAO::_setVotingDelay: admin only'); require( newVotingDelay >= MIN_VOTING_DELAY && newVotingDelay <= MAX_VOTING_DELAY, 'NounsDAO::_setVotingDelay: invalid voting delay' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 546-550):
require(msg.sender == admin, 'NounsDAO::_setVotingPeriod: admin only'); require( newVotingPeriod >= MIN_VOTING_PERIOD && newVotingPeriod <= MAX_VOTING_PERIOD, 'NounsDAO::_setVotingPeriod: invalid voting period' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 563-568):
require(msg.sender == admin, 'NounsDAO::_setProposalThresholdBPS: admin only'); require( newProposalThresholdBPS >= MIN_PROPOSAL_THRESHOLD_BPS && newProposalThresholdBPS <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 581-585):
require(msg.sender == admin, 'NounsDAO::_setQuorumVotesBPS: admin only'); require( newQuorumVotesBPS >= MIN_QUORUM_VOTES_BPS && newQuorumVotesBPS <= MAX_QUORUM_VOTES_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 617):
require(msg.sender == pendingAdmin && msg.sender != address(0), 'NounsDAO::_acceptAdmin: pending admin only');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 133-148):
require(address(timelock) == address(0), 'NounsDAO::initialize: can only initialize once'); require(msg.sender == admin, 'NounsDAO::initialize: admin only'); require(timelock_ != address(0), 'NounsDAO::initialize: invalid timelock address'); require(nouns_ != address(0), 'NounsDAO::initialize: invalid nouns address'); require( votingPeriod_ >= MIN_VOTING_PERIOD && votingPeriod_ <= MAX_VOTING_PERIOD, 'NounsDAO::initialize: invalid voting period' ); require( votingDelay_ >= MIN_VOTING_DELAY && votingDelay_ <= MAX_VOTING_DELAY, 'NounsDAO::initialize: invalid voting delay' ); require( proposalThresholdBPS_ >= MIN_PROPOSAL_THRESHOLD_BPS && proposalThresholdBPS_ <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::initialize: invalid proposal threshold bps' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 197-220):
`require( nouns.getPriorVotes(msg.sender, block.number - 1) > temp.proposalThreshold, 'NounsDAO::propose: proposer votes below proposal threshold' ); require( targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, 'NounsDAO::propose: proposal function information arity mismatch' ); require(targets.length != 0, 'NounsDAO::propose: must provide actions'); require(targets.length <= proposalMaxOperations, 'NounsDAO::propose: too many actions');
temp.latestProposalId = latestProposalIds[msg.sender]; if (temp.latestProposalId != 0) { ProposalState proposersLatestProposalState = state(temp.latestProposalId); require( proposersLatestProposalState != ProposalState.Active, 'NounsDAO::propose: one live proposal per proposer, found an already active proposal' ); require( proposersLatestProposalState != ProposalState.Pending, 'NounsDAO::propose: one live proposal per proposer, found an already pending proposal' );`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 286):
require( state(proposalId) == ProposalState.Succeeded, 'NounsDAO::queue: proposal can only be queued if it is succeeded' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 312-315):
require( !timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), 'NounsDAO::queueOrRevertInternal: identical proposal action already queued at eta' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 324-327):
require( state(proposalId) == ProposalState.Queued, 'NounsDAO::execute: proposal can only be executed if it is queued' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 347-354):
`require(state(proposalId) != ProposalState.Executed, 'NounsDAO::cancel: cannot cancel executed proposal');
Proposal storage proposal = _proposals[proposalId]; require( msg.sender == proposal.proposer || nouns.getPriorVotes(proposal.proposer, block.number - 1) < proposal.proposalThreshold, 'NounsDAO::cancel: proposer above threshold' );`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 375-377):
require(vetoer != address(0), 'NounsDAO::veto: veto power burned'); require(msg.sender == vetoer, 'NounsDAO::veto: only vetoer'); require(state(proposalId) != ProposalState.Executed, 'NounsDAO::veto: cannot veto executed proposal');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 593-597):
require(state(proposalId) == ProposalState.Active, 'NounsDAO::castVoteInternal: voting is closed'); require(support <= 2, 'NounsDAO::castVoteInternal: invalid vote type'); Proposal storage proposal = _proposals[proposalId]; Receipt storage receipt = proposal.receipts[voter]; require(receipt.hasVoted == false, 'NounsDAO::castVoteInternal: voter already voted');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 622-626):
require(msg.sender == admin, 'NounsDAO::_setVotingDelay: admin only'); require( newVotingDelay >= MIN_VOTING_DELAY && newVotingDelay <= MAX_VOTING_DELAY, 'NounsDAO::_setVotingDelay: invalid voting delay' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 638-642):
require(msg.sender == admin, 'NounsDAO::_setVotingPeriod: admin only'); require( newVotingPeriod >= MIN_VOTING_PERIOD && newVotingPeriod <= MAX_VOTING_PERIOD, 'NounsDAO::_setVotingPeriod: invalid voting period' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 655-660):
require(msg.sender == admin, 'NounsDAO::_setProposalThresholdBPS: admin only'); require( newProposalThresholdBPS >= MIN_PROPOSAL_THRESHOLD_BPS && newProposalThresholdBPS <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold bps' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 674-685):
`require(msg.sender == admin, 'NounsDAO::_setMinQuorumVotesBPS: admin only'); DynamicQuorumParams memory params = getDynamicQuorumParamsAt(block.number);
require( newMinQuorumVotesBPS >= MIN_QUORUM_VOTES_BPS_LOWER_BOUND && newMinQuorumVotesBPS <= MIN_QUORUM_VOTES_BPS_UPPER_BOUND, 'NounsDAO::_setMinQuorumVotesBPS: invalid min quorum votes bps' ); require( newMinQuorumVotesBPS <= params.maxQuorumVotesBPS, 'NounsDAO::_setMinQuorumVotesBPS: min quorum votes bps greater than max' );`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 702-712):
`require(msg.sender == admin, 'NounsDAO::_setMaxQuorumVotesBPS: admin only'); DynamicQuorumParams memory params = getDynamicQuorumParamsAt(block.number);
require( newMaxQuorumVotesBPS <= MAX_QUORUM_VOTES_BPS_UPPER_BOUND, 'NounsDAO::_setMaxQuorumVotesBPS: invalid max quorum votes bps' ); require( params.minQuorumVotesBPS <= newMaxQuorumVotesBPS, 'NounsDAO::_setMaxQuorumVotesBPS: min quorum votes bps greater than max' );`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 727):
require(msg.sender == admin, 'NounsDAO::_setQuorumCoefficient: admin only');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 801):
require(msg.sender == admin, 'NounsDAO::_setPendingAdmin: admin only');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 819):
`require(msg.sender == pendingAdmin && msg.sender != address(0), 'NounsDAO::_acceptAdmin: pending admin only');'
File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 79-80):
` require(msg.sender == admin, 'NounsDAOProxy::setImplementation: admin only'); require(implementation != address(0), 'NounsDAOProxy::_setImplementation: invalid implementation address');'
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 140-142):
require(signatory != address(0), 'ERC721Checkpointable::delegateBySig: invalid signature'); require(nonce == nonces[signatory]++, 'ERC721Checkpointable::delegateBySig: invalid nonce'); require(block.timestamp <= expiry, 'ERC721Checkpointable::delegateBySig: signature expired');
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 164):
require(blockNumber < block.number, 'ERC721Checkpointable::getPriorVotes: not yet determined');
File: 2022-08-nounsdao/contracts/base/ERC721Enumerable.sol (line 62):
require(index < ERC721.balanceOf(owner), 'ERC721Enumerable: owner index out of bounds');
File: 2022-08-nounsdao/contracts/base/ERC721Enumerable.sol (line 77):
require(index < ERC721Enumerable.totalSupply(), 'ERC721Enumerable: global index out of bounds');
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 122-141):
return _delegate(msg.sender, delegatee);
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 281):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 319):
for (uint256 i = 0; i < proposal.targets.length; i++) {;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 346):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 371):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 292):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 330):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 375):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 382):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 223):
newProposal.eta = 0;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 230-232):
newProposal.forVotes = 0; newProposal.againstVotes = 0; newProposal.abstainVotes = 0;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 231):
newProposal.eta = 0;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 238-240):
newProposal.forVotes = 0; newProposal.againstVotes = 0; newProposal.abstainVotes = 0;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 948):
uint256 lower = 0;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 41):
uint8 public constant decimals = 0;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 181):
uint32 lower = 0;
++i
costs less gas than i++
, especially when it’s used in forloops (--i/i-- too
):File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 281):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 319):
for (uint256 i = 0; i < proposal.targets.length; i++) {;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 346):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 371):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 292):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 330):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 375):
for (uint256 i = 0; i < proposal.targets.length; i++) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 382):
for (uint256 i = 0; i < proposal.targets.length; i++) {
require()
statements that use && Cost gas:File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 126-141):
require( votingPeriod_ >= MIN_VOTING_PERIOD && votingPeriod_ <= MAX_VOTING_PERIOD, 'NounsDAO::initialize: invalid voting period' ); require( votingDelay_ >= MIN_VOTING_DELAY && votingDelay_ <= MAX_VOTING_DELAY, 'NounsDAO::initialize: invalid voting delay' ); require( proposalThresholdBPS_ >= MIN_PROPOSAL_THRESHOLD_BPS && proposalThresholdBPS_ <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::initialize: invalid proposal threshold' ); require( quorumVotesBPS_ >= MIN_QUORUM_VOTES_BPS && quorumVotesBPS_ <= MAX_QUORUM_VOTES_BPS, 'NounsDAO::initialize: invalid proposal threshold' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 191-196):
require( targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, 'NounsDAO::propose: proposal function information arity mismatch' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 531-534):
require( newVotingDelay >= MIN_VOTING_DELAY && newVotingDelay <= MAX_VOTING_DELAY, 'NounsDAO::_setVotingDelay: invalid voting delay' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 547-550):
require( newVotingPeriod >= MIN_VOTING_PERIOD && newVotingPeriod <= MAX_VOTING_PERIOD, 'NounsDAO::_setVotingPeriod: invalid voting period' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 564-568):
require( newProposalThresholdBPS >= MIN_PROPOSAL_THRESHOLD_BPS && newProposalThresholdBPS <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 582-585):
require( newQuorumVotesBPS >= MIN_QUORUM_VOTES_BPS && newQuorumVotesBPS <= MAX_QUORUM_VOTES_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 617):
require(msg.sender == pendingAdmin && msg.sender != address(0), 'NounsDAO::_acceptAdmin: pending admin only');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 137-148):
require( votingPeriod_ >= MIN_VOTING_PERIOD && votingPeriod_ <= MAX_VOTING_PERIOD, 'NounsDAO::initialize: invalid voting period' ); require( votingDelay_ >= MIN_VOTING_DELAY && votingDelay_ <= MAX_VOTING_DELAY, 'NounsDAO::initialize: invalid voting delay' ); require( proposalThresholdBPS_ >= MIN_PROPOSAL_THRESHOLD_BPS && proposalThresholdBPS_ <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::initialize: invalid proposal threshold bps' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 201-206):
require( targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, 'NounsDAO::propose: proposal function information arity mismatch' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 623-626):
require( newVotingDelay >= MIN_VOTING_DELAY && newVotingDelay <= MAX_VOTING_DELAY, 'NounsDAO::_setVotingDelay: invalid voting delay' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 639-642):
require( newVotingPeriod >= MIN_VOTING_PERIOD && newVotingPeriod <= MAX_VOTING_PERIOD, 'NounsDAO::_setVotingPeriod: invalid voting period' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 656-660):
require( newProposalThresholdBPS >= MIN_PROPOSAL_THRESHOLD_BPS && newProposalThresholdBPS <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold bps' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 677-681):
require( newMinQuorumVotesBPS >= MIN_QUORUM_VOTES_BPS_LOWER_BOUND && newMinQuorumVotesBPS <= MIN_QUORUM_VOTES_BPS_UPPER_BOUND, 'NounsDAO::_setMinQuorumVotesBPS: invalid min quorum votes bps' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 819):
require(msg.sender == pendingAdmin && msg.sender != address(0), 'NounsDAO::_acceptAdmin: pending admin only');
uints
/ints
smaller than 32 bytes (256 bits) incurs overhead (> When using elements that are smaller than 32 bytes, yourcontract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.
https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Use a larger size then downcast where needed):
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 462):
uint8 support,
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 474-475):
uint8 support, uint8 v,
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 499):
uint8 support
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 508):
uint96 votes = nouns.getPriorVotes(voter, proposal.startBlock - votingDelay);
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 535):
uint8 support,
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 539):
uint96 votes = castVoteInternal(msg.sender, proposalId, support);
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 554):
uint8 support,
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 566-567):
uint8 support, uint8 v,
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 591-592):
uint8 support ) internal returns (uint96) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 600):
uint96 votes = nouns.getPriorVotes(voter, proposalCreationBlock(proposal));
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 673):
function _setMinQuorumVotesBPS(uint16 newMinQuorumVotesBPS) external {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 687):
uint16 oldMinQuorumVotesBPS = params.minQuorumVotesBPS;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 701):
function _setMaxQuorumVotesBPS(uint16 newMaxQuorumVotesBPS) external {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 714):
uint16 oldMaxQuorumVotesBPS = params.maxQuorumVotesBPS;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 726):
function _setQuorumCoefficient(uint32 newQuorumCoefficient) external {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 730):
uint32 oldQuorumCoefficient = params.quorumCoefficient;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 749-751):
uint16 newMinQuorumVotesBPS, uint16 newMaxQuorumVotesBPS, uint32 newQuorumCoefficient
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 923):
uint32 blockNumber = safe32(blockNumber_, 'NounsDAO::getDynamicQuorumParamsAt: block number exceeds 32 bits');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 965):
uint32 blockNumber = safe32(block.number, 'block number exceeds 32 bits');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 1019-1020):
require(n <= type(uint32).max, errorMessage); return uint32(n);
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 1024):
if (n > type(uint16).max) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 1027):
return uint16(n);
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 111-117):
` event MinQuorumVotesBPSSet(uint16 oldMinQuorumVotesBPS, uint16 newMinQuorumVotesBPS);
/// @notice Emitted when maxQuorumVotesBPS is set event MaxQuorumVotesBPSSet(uint16 oldMaxQuorumVotesBPS, uint16 newMaxQuorumVotesBPS);
/// @notice Emitted when quorumCoefficient is set event QuorumCoefficientSet(uint32 oldQuorumCoefficient, uint32 newQuorumCoefficient);`
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 216-220):
bool hasVoted; /// @notice Whether or not the voter supports the proposal or abstains uint8 support; /// @notice The number of votes the voter had, which were cast uint96 votes;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 322-324):
uint8 support; /// @notice The number of votes the voter had, which were cast uint96 votes;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 352-357):
uint16 minQuorumVotesBPS; /// @notice The maximum basis point number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed. uint16 maxQuorumVotesBPS; /// @notice The dynamic quorum coefficient /// @dev Assumed to be fixed point integer with 6 decimals, i.e 0.2 is represented as 0.2 * 1e6 = 200000 uint32 quorumCoefficient;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 363):
uint32 fromBlock;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 41):
uint8 public constant decimals = 0
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 53-56):
`mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;
/// @notice The number of checkpoints for each account mapping(address => uint32) public numCheckpoints;`
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 79):
function votesToDelegate(address delegator) public view returns (uint96) {
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 130):
uint8 v,
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 151-152):
function getCurrentVotes(address account) external view returns (uint96) { uint32 nCheckpoints = numCheckpoints[account];
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 166):
uint32 nCheckpoints = numCheckpoints[account];
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 181-184):
uint32 lower = 0; uint32 upper = nCheckpoints - 1; while (upper > lower) { uint32 center = upper - (upper - lower) / 2;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 205):
uint96 amount = votesToDelegate(delegator);
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 213):
uint96 amount
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 217-238):
` uint32 srcRepNum = numCheckpoints[srcRep]; uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0; uint96 srcRepNew = sub96(srcRepOld, amount, 'ERC721Checkpointable::_moveDelegates: amount underflows'); _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew); }
if (dstRep != address(0)) { uint32 dstRepNum = numCheckpoints[dstRep]; uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0; uint96 dstRepNew = add96(dstRepOld, amount, 'ERC721Checkpointable::_moveDelegates: amount overflows'); _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew); } }
}
function _writeCheckpoint( address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes ) internal { uint32 blockNumber = safe32(`
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 255):
return uint32(n);
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 260):
return uint96(n);
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 264-268):
uint96 a, uint96 b, string memory errorMessage ) internal pure returns (uint96) { uint96 c = a + b;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 274-275):
uint96 a, uint96 b,
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 277):
) internal pure returns (uint96) {
keccak256()
, should use immutable
rather than constant
(See this issue for a detail description of the issue):File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 97-101):
` bytes32 public constant DOMAIN_TYPEHASH = keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');
/// @notice The EIP-712 typehash for the ballot struct used by the contract bytes32 public constant BALLOT_TYPEHASH = keccak256('Ballot(uint256 proposalId,uint8 support)');`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 479-483):
bytes32 domainSeparator = keccak256( abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainIdInternal(), address(this)) ); bytes32 structHash = keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support)); bytes32 digest = keccak256(abi.encodePacked('\x19\x01', domainSeparator, structHash));
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 101-105):
` bytes32 public constant DOMAIN_TYPEHASH = keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');
/// @notice The EIP-712 typehash for the ballot struct used by the contract bytes32 public constant BALLOT_TYPEHASH = keccak256('Ballot(uint256 proposalId,uint8 support)');`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 571-575):
bytes32 domainSeparator = keccak256( abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainIdInternal(), address(this)) ); bytes32 structHash = keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support)); bytes32 digest = keccak256(abi.encodePacked('\x19\x01', domainSeparator, structHash));
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 59-65):
` bytes32 public constant DOMAIN_TYPEHASH = keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');
/// @notice The EIP-712 typehash for the delegation struct used by the contract bytes32 public constant DELEGATION_TYPEHASH = keccak256('Delegation(address delegatee,uint256 nonce,uint256 expiry)');`
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 134-138):
bytes32 domainSeparator = keccak256( abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name())), getChainId(), address(this)) ); bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)); bytes32 digest = keccak256(abi.encodePacked('\x19\x01', domainSeparator, structHash));
require()
/revert()
checks should be refactored to a modifier or function:File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 709-712):
require( params.minQuorumVotesBPS <= newMaxQuorumVotesBPS, 'NounsDAO::_setMaxQuorumVotesBPS: min quorum votes bps greater than max' );
require()
or revert()
statements that check input arguments should be at the top of the function (Checks that involve constants should come before checks that involve state variables):File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 122-125):
`require(address(timelock) == address(0), 'NounsDAO::initialize: can only initialize once'); require(msg.sender == admin, 'NounsDAO::initialize: admin only'); require(timelock_ != address(0), 'NounsDAO::initialize: invalid timelock address'); require(nouns_ != address(0), 'NounsDAO::initialize: invalid nouns address');'
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 485):
require(signatory != address(0), 'NounsDAO::castVoteBySig: invalid signature');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 617):
require(msg.sender == pendingAdmin && msg.sender != address(0), 'NounsDAO::_acceptAdmin: pending admin only');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 135-136):
` require(timelock_ != address(0), 'NounsDAO::initialize: invalid timelock address'); require(nouns_ != address(0), 'NounsDAO::initialize: invalid nouns address');''
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 375):
`require(vetoer != address(0), 'NounsDAO::veto: veto power burned');'
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 819):
`require(msg.sender == pendingAdmin && msg.sender != address(0), 'NounsDAO::_acceptAdmin: pending admin only');'
File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 80):
`require(implementation_ != address(0), 'NounsDAOProxy::_setImplementation: invalid implementation address');'
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 140):
` require(signatory != address(0), 'ERC721Checkpointable::delegateBySig: invalid signature');''
revert()
/require()
strings to save deployment gas:File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 122-141):
require(address(timelock) == address(0), 'NounsDAO::initialize: can only initialize once'); require(msg.sender == admin, 'NounsDAO::initialize: admin only'); require(timelock_ != address(0), 'NounsDAO::initialize: invalid timelock address'); require(nouns_ != address(0), 'NounsDAO::initialize: invalid nouns address'); require( votingPeriod_ >= MIN_VOTING_PERIOD && votingPeriod_ <= MAX_VOTING_PERIOD, 'NounsDAO::initialize: invalid voting period' ); require( votingDelay_ >= MIN_VOTING_DELAY && votingDelay_ <= MAX_VOTING_DELAY, 'NounsDAO::initialize: invalid voting delay' ); require( proposalThresholdBPS_ >= MIN_PROPOSAL_THRESHOLD_BPS && proposalThresholdBPS_ <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::initialize: invalid proposal threshold' ); require( quorumVotesBPS_ >= MIN_QUORUM_VOTES_BPS && quorumVotesBPS_ <= MAX_QUORUM_VOTES_BPS, 'NounsDAO::initialize: invalid proposal threshold' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 187-198):
require( nouns.getPriorVotes(msg.sender, block.number - 1) > temp.proposalThreshold, 'NounsDAO::propose: proposer votes below proposal threshold' ); require( targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, 'NounsDAO::propose: proposal function information arity mismatch' ); require(targets.length != 0, 'NounsDAO::propose: must provide actions'); require(targets.length <= proposalMaxOperations, 'NounsDAO::propose: too many actions');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 203-210):
require( proposersLatestProposalState != ProposalState.Active, 'NounsDAO::propose: one live proposal per proposer, found an already active proposal' ); require( proposersLatestProposalState != ProposalState.Pending, 'NounsDAO::propose: one live proposal per proposer, found an already pending proposal' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 275-278):
require( state(proposalId) == ProposalState.Succeeded, 'NounsDAO::queue: proposal can only be queued if it is succeeded' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 301-304):
require( !timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), 'NounsDAO::queueOrRevertInternal: identical proposal action already queued at eta' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 313-316):
require( state(proposalId) == ProposalState.Queued, 'NounsDAO::execute: proposal can only be executed if it is queued' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 336-343):
`require(state(proposalId) != ProposalState.Executed, 'NounsDAO::cancel: cannot cancel executed proposal');
Proposal storage proposal = proposals[proposalId]; require( msg.sender == proposal.proposer || nouns.getPriorVotes(proposal.proposer, block.number - 1) < proposal.proposalThreshold, 'NounsDAO::cancel: proposer above threshold' );`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 366):
require(state(proposalId) != ProposalState.Executed, 'NounsDAO::veto: cannot veto executed proposal');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 485):
require(signatory != address(0), 'NounsDAO::castVoteBySig: invalid signature');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 501-505):
require(state(proposalId) == ProposalState.Active, 'NounsDAO::castVoteInternal: voting is closed'); require(support <= 2, 'NounsDAO::castVoteInternal: invalid vote type'); Proposal storage proposal = proposals[proposalId]; Receipt storage receipt = proposal.receipts[voter]; require(receipt.hasVoted == false, 'NounsDAO::castVoteInternal: voter already voted');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 530-534):
require(msg.sender == admin, 'NounsDAO::_setVotingDelay: admin only'); require( newVotingDelay >= MIN_VOTING_DELAY && newVotingDelay <= MAX_VOTING_DELAY, 'NounsDAO::_setVotingDelay: invalid voting delay' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 546-550):
require(msg.sender == admin, 'NounsDAO::_setVotingPeriod: admin only'); require( newVotingPeriod >= MIN_VOTING_PERIOD && newVotingPeriod <= MAX_VOTING_PERIOD, 'NounsDAO::_setVotingPeriod: invalid voting period' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 563-568):
require(msg.sender == admin, 'NounsDAO::_setProposalThresholdBPS: admin only'); require( newProposalThresholdBPS >= MIN_PROPOSAL_THRESHOLD_BPS && newProposalThresholdBPS <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 581-585):
require(msg.sender == admin, 'NounsDAO::_setQuorumVotesBPS: admin only'); require( newQuorumVotesBPS >= MIN_QUORUM_VOTES_BPS && newQuorumVotesBPS <= MAX_QUORUM_VOTES_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 617):
require(msg.sender == pendingAdmin && msg.sender != address(0), 'NounsDAO::_acceptAdmin: pending admin only');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 133-148):
require(address(timelock) == address(0), 'NounsDAO::initialize: can only initialize once'); require(msg.sender == admin, 'NounsDAO::initialize: admin only'); require(timelock_ != address(0), 'NounsDAO::initialize: invalid timelock address'); require(nouns_ != address(0), 'NounsDAO::initialize: invalid nouns address'); require( votingPeriod_ >= MIN_VOTING_PERIOD && votingPeriod_ <= MAX_VOTING_PERIOD, 'NounsDAO::initialize: invalid voting period' ); require( votingDelay_ >= MIN_VOTING_DELAY && votingDelay_ <= MAX_VOTING_DELAY, 'NounsDAO::initialize: invalid voting delay' ); require( proposalThresholdBPS_ >= MIN_PROPOSAL_THRESHOLD_BPS && proposalThresholdBPS_ <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::initialize: invalid proposal threshold bps' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 197-220):
`require( nouns.getPriorVotes(msg.sender, block.number - 1) > temp.proposalThreshold, 'NounsDAO::propose: proposer votes below proposal threshold' ); require( targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, 'NounsDAO::propose: proposal function information arity mismatch' ); require(targets.length != 0, 'NounsDAO::propose: must provide actions'); require(targets.length <= proposalMaxOperations, 'NounsDAO::propose: too many actions');
temp.latestProposalId = latestProposalIds[msg.sender]; if (temp.latestProposalId != 0) { ProposalState proposersLatestProposalState = state(temp.latestProposalId); require( proposersLatestProposalState != ProposalState.Active, 'NounsDAO::propose: one live proposal per proposer, found an already active proposal' ); require( proposersLatestProposalState != ProposalState.Pending, 'NounsDAO::propose: one live proposal per proposer, found an already pending proposal' );`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 286):
require( state(proposalId) == ProposalState.Succeeded, 'NounsDAO::queue: proposal can only be queued if it is succeeded' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 312-315):
require( !timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), 'NounsDAO::queueOrRevertInternal: identical proposal action already queued at eta' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 324-327):
require( state(proposalId) == ProposalState.Queued, 'NounsDAO::execute: proposal can only be executed if it is queued' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 347-354):
`require(state(proposalId) != ProposalState.Executed, 'NounsDAO::cancel: cannot cancel executed proposal');
Proposal storage proposal = _proposals[proposalId]; require( msg.sender == proposal.proposer || nouns.getPriorVotes(proposal.proposer, block.number - 1) < proposal.proposalThreshold, 'NounsDAO::cancel: proposer above threshold' );`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 375-377):
require(vetoer != address(0), 'NounsDAO::veto: veto power burned'); require(msg.sender == vetoer, 'NounsDAO::veto: only vetoer'); require(state(proposalId) != ProposalState.Executed, 'NounsDAO::veto: cannot veto executed proposal');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 593-597):
require(state(proposalId) == ProposalState.Active, 'NounsDAO::castVoteInternal: voting is closed'); require(support <= 2, 'NounsDAO::castVoteInternal: invalid vote type'); Proposal storage proposal = _proposals[proposalId]; Receipt storage receipt = proposal.receipts[voter]; require(receipt.hasVoted == false, 'NounsDAO::castVoteInternal: voter already voted');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 622-626):
require(msg.sender == admin, 'NounsDAO::_setVotingDelay: admin only'); require( newVotingDelay >= MIN_VOTING_DELAY && newVotingDelay <= MAX_VOTING_DELAY, 'NounsDAO::_setVotingDelay: invalid voting delay' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 638-642):
require(msg.sender == admin, 'NounsDAO::_setVotingPeriod: admin only'); require( newVotingPeriod >= MIN_VOTING_PERIOD && newVotingPeriod <= MAX_VOTING_PERIOD, 'NounsDAO::_setVotingPeriod: invalid voting period' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 655-660):
require(msg.sender == admin, 'NounsDAO::_setProposalThresholdBPS: admin only'); require( newProposalThresholdBPS >= MIN_PROPOSAL_THRESHOLD_BPS && newProposalThresholdBPS <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold bps' );
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 674-685):
`require(msg.sender == admin, 'NounsDAO::_setMinQuorumVotesBPS: admin only'); DynamicQuorumParams memory params = getDynamicQuorumParamsAt(block.number);
require( newMinQuorumVotesBPS >= MIN_QUORUM_VOTES_BPS_LOWER_BOUND && newMinQuorumVotesBPS <= MIN_QUORUM_VOTES_BPS_UPPER_BOUND, 'NounsDAO::_setMinQuorumVotesBPS: invalid min quorum votes bps' ); require( newMinQuorumVotesBPS <= params.maxQuorumVotesBPS, 'NounsDAO::_setMinQuorumVotesBPS: min quorum votes bps greater than max' );`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 702-712):
`require(msg.sender == admin, 'NounsDAO::_setMaxQuorumVotesBPS: admin only'); DynamicQuorumParams memory params = getDynamicQuorumParamsAt(block.number);
require( newMaxQuorumVotesBPS <= MAX_QUORUM_VOTES_BPS_UPPER_BOUND, 'NounsDAO::_setMaxQuorumVotesBPS: invalid max quorum votes bps' ); require( params.minQuorumVotesBPS <= newMaxQuorumVotesBPS, 'NounsDAO::_setMaxQuorumVotesBPS: min quorum votes bps greater than max' );`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 727):
require(msg.sender == admin, 'NounsDAO::_setQuorumCoefficient: admin only');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 801):
require(msg.sender == admin, 'NounsDAO::_setPendingAdmin: admin only');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 819):
`require(msg.sender == pendingAdmin && msg.sender != address(0), 'NounsDAO::_acceptAdmin: pending admin only');'
File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 79-80):
` require(msg.sender == admin, 'NounsDAOProxy::setImplementation: admin only'); require(implementation != address(0), 'NounsDAOProxy::_setImplementation: invalid implementation address');'
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 140-142):
require(signatory != address(0), 'ERC721Checkpointable::delegateBySig: invalid signature'); require(nonce == nonces[signatory]++, 'ERC721Checkpointable::delegateBySig: invalid nonce'); require(block.timestamp <= expiry, 'ERC721Checkpointable::delegateBySig: signature expired');
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 164):
require(blockNumber < block.number, 'ERC721Checkpointable::getPriorVotes: not yet determined');
File: 2022-08-nounsdao/contracts/base/ERC721Enumerable.sol (line 62):
require(index < ERC721.balanceOf(owner), 'ERC721Enumerable: owner index out of bounds');
File: 2022-08-nounsdao/contracts/base/ERC721Enumerable.sol (line 77):
require(index < ERC721Enumerable.totalSupply(), 'ERC721Enumerable: global index out of bounds');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 951):
uint256 center = upper - (upper - lower) / 2;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 184):
uint32 center = upper - (upper - lower) / 2
Bitshift right by one bit instead of dividing by 2 to save gas.
contract existence checks if the external call has a return value):
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 61):
pragma solidity ^0.8.6;
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 53):
pragma solidity ^0.8.6;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 33):
pragma solidity ^0.8.6;
File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 36):
pragma solidity ^0.8.6;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 35):
pragma solidity ^0.8.6;
File: 2022-08-nounsdao/contracts/base/ERC721Enumerable.sol (line 28):
pragma solidity ^0.8.0;
address
mappings can be combined into a single mapping
of an address
to a struct
, where appropriate (Saves a storage slot for the mapping. Depending on the circumstancesand sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot):
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 53-56):
` mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;
/// @notice The number of checkpoints for each account mapping(address => uint32) public numCheckpoints;`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 789):
(bool sent, ) = msg.sender.call{ value: amount }('');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 983):
(bool refundSent, ) = msg.sender.call{ value: refundAmount }('');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 174-180):
function propose( address[] memory targets, uint256[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description ) public returns (uint256) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 294-300):
function queueOrRevertInternal( address target, uint256 value, string memory signature, bytes memory data, uint256 eta ) internal {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 184-190):
function propose( address[] memory targets, uint256[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description ) public returns (uint256) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 305-311):
function queueOrRevertInternal( address target, uint256 value, string memory signature, bytes memory data, uint256 eta ) internal {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 533-537):
function castRefundableVoteInternal( uint256 proposalId, uint8 support, string memory reason ) internal {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 903-907):
function dynamicQuorumVotes( uint256 againstVotes, uint256 totalSupply, DynamicQuorumParams memory params ) public pure returns (uint256) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 1018):
function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {
File: 2022-08-nounsdao/contracts/governance/NounsDAOProxy.sol (line 94):
function delegateTo(address callee, bytes memory data) internal {
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 253):
function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 258):
function safe96(uint256 n, string memory errorMessage) internal pure returns (uint96) {
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 263-267):
function add96( uint96 a, uint96 b, string memory errorMessage ) internal pure returns (uint96) {
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 273-277):
function sub96( uint96 a, uint96 b, string memory errorMessage ) internal pure returns (uint96) {
Change function arguments from memory to calldata.
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 789):
(bool sent, ) = msg.sender.call{ value: amount }('');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 983):
(bool refundSent, ) = msg.sender.call{ value: refundAmount }('');
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 204-208):
bool canceled; /// @notice Flag marking whether the proposal has been vetoed bool vetoed; /// @notice Flag marking whether the proposal has been executed bool executed;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 216):
bool hasVoted;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 304-308):
bool canceled; /// @notice Flag marking whether the proposal has been vetoed bool vetoed; /// @notice Flag marking whether the proposal has been executed bool executed;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 320):
bool hasVoted;
File: 2022-08-nounsdao/contracts/governance/NounsDAOInterfaces.sol (line 390-394):
bool canceled; /// @notice Flag marking whether the proposal has been vetoed bool vetoed; /// @notice Flag marking whether the proposal has been executed bool executed;
private
rather than public
for constants, saves gas:File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 67-101):
` string public constant name = 'Nouns DAO';
/// @notice The minimum setable proposal threshold uint256 public constant MIN_PROPOSAL_THRESHOLD_BPS = 1; // 1 basis point or 0.01%
/// @notice The maximum setable proposal threshold uint256 public constant MAX_PROPOSAL_THRESHOLD_BPS = 1_000; // 1,000 basis points or 10%
/// @notice The minimum setable voting period uint256 public constant MIN_VOTING_PERIOD = 5_760; // About 24 hours
/// @notice The max setable voting period uint256 public constant MAX_VOTING_PERIOD = 80_640; // About 2 weeks
/// @notice The min setable voting delay uint256 public constant MIN_VOTING_DELAY = 1;
/// @notice The max setable voting delay uint256 public constant MAX_VOTING_DELAY = 40_320; // About 1 week
/// @notice The minimum setable quorum votes basis points uint256 public constant MIN_QUORUM_VOTES_BPS = 200; // 200 basis points or 2%
/// @notice The maximum setable quorum votes basis points uint256 public constant MAX_QUORUM_VOTES_BPS = 2_000; // 2,000 basis points or 20%
/// @notice The maximum number of actions that can be included in a proposal uint256 public constant proposalMaxOperations = 10; // 10 actions
/// @notice The EIP-712 typehash for the contract's domain bytes32 public constant DOMAIN_TYPEHASH = keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');
/// @notice The EIP-712 typehash for the ballot struct used by the contract bytes32 public constant BALLOT_TYPEHASH = keccak256('Ballot(uint256 proposalId,uint8 support)');`
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 59-105):
` string public constant name = 'Nouns DAO';
/// @notice The minimum setable proposal threshold uint256 public constant MIN_PROPOSAL_THRESHOLD_BPS = 1; // 1 basis point or 0.01%
/// @notice The maximum setable proposal threshold uint256 public constant MAX_PROPOSAL_THRESHOLD_BPS = 1_000; // 1,000 basis points or 10%
/// @notice The minimum setable voting period uint256 public constant MIN_VOTING_PERIOD = 5_760; // About 24 hours
/// @notice The max setable voting period uint256 public constant MAX_VOTING_PERIOD = 80_640; // About 2 weeks
/// @notice The min setable voting delay uint256 public constant MIN_VOTING_DELAY = 1;
/// @notice The max setable voting delay uint256 public constant MAX_VOTING_DELAY = 40_320; // About 1 week
/// @notice The lower bound of minimum quorum votes basis points uint256 public constant MIN_QUORUM_VOTES_BPS_LOWER_BOUND = 200; // 200 basis points or 2%
/// @notice The upper bound of minimum quorum votes basis points uint256 public constant MIN_QUORUM_VOTES_BPS_UPPER_BOUND = 2_000; // 2,000 basis points or 20%
/// @notice The upper bound of maximum quorum votes basis points uint256 public constant MAX_QUORUM_VOTES_BPS_UPPER_BOUND = 6_000; // 4,000 basis points or 60%
/// @notice The maximum setable quorum votes basis points uint256 public constant MAX_QUORUM_VOTES_BPS = 2_000; // 2,000 basis points or 20%
/// @notice The maximum number of actions that can be included in a proposal uint256 public constant proposalMaxOperations = 10; // 10 actions
/// @notice The maximum priority fee used to cap gas refunds in castRefundableVote
uint256 public constant MAX_REFUND_PRIORITY_FEE = 2 gwei;
/// @notice The vote refund gas overhead, including 7K for ETH transfer and 29K for general transaction overhead uint256 public constant REFUND_BASE_GAS = 36000;
/// @notice The EIP-712 typehash for the contract's domain bytes32 public constant DOMAIN_TYPEHASH = keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');
/// @notice The EIP-712 typehash for the ballot struct used by the contract bytes32 public constant BALLOT_TYPEHASH = keccak256('Ballot(uint256 proposalId,uint8 support)');`
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 41):
uint8 public constant decimals = 0;
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 59-64):
` bytes32 public constant DOMAIN_TYPEHASH = keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');
/// @notice The EIP-712 typehash for the delegation struct used by the contract bytes32 public constant DELEGATION_TYPEHASH = keccak256('Delegation(address delegatee,uint256 nonce,uint256 expiry)');`
block should do something useful, such as emitting an event or
reverting. If the contract is meant to be extended, the contract should
be abstract
and the function signatures be added without
any default implementation. If the block is an empty if-statement block
to avoid doing subsequent checks in the else-if/else conditions, the
else-if/else conditions should be nested under the negation of the
if-statement, because they involve different classes of checks, which
may lead to the introduction of errors when the code is later modified (if(x){}else if(y){...}else{...}
=> if(!x){if(y){...}else{...}}
)):
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 1030):
receive() external payable {}
if (<x> == true)
=> if (<x>)
, if (<x> == false)
=> if (!<x>)
):File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV1.sol (line 505):
require(receipt.hasVoted == false, 'NounsDAO::castVoteInternal: voter already voted');
File: 2022-08-nounsdao/contracts/governance/NounsDAOLogicV2.sol (line 597):
require(receipt.hasVoted == false, 'NounsDAO::castVoteInternal: voter already voted');
public
/external
function names and public member variable names can be optimized to save gas. See thislink for an example of how it works. Below are the interfaces/abstract contracts that can be optimized so that the most frequently-called functions use the least amount of gas possible during method lookup. Method IDs that have two leading zero bytes can save 128 gas each during deployment, and renaming functions to have lower method IDs will save 22 gas per call, per sorted position shifted):
File: 2022-08-nounsdao/contracts/base/ERC721Checkpointable.sol (line 39):
abstract contract ERC721Checkpointable is ERC721Enumerable {
File: 2022-08-nounsdao/contracts/base/ERC721Enumerable.sol (line 38):
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {