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: 14/160
Findings: 3
Award: $1,117.27
🌟 Selected for report: 0
🚀 Solo Findings: 0
1039.0663 USDC - $1,039.07
Judge has assessed an item in Issue #264 as Medium risk. The relevant finding follows:
If the newVetoer
is set to the incorrect address, the functionality will be unretrievable.
1 instance of this issue has been found:
[L-05] NounsDAOLogicV2.sol#L839-L845
function _setVetoer(address newVetoer) public { require(msg.sender == vetoer, 'NounsDAO::_setVetoer: vetoer only'); emit NewVetoer(vetoer, newVetoer); vetoer = newVetoer; }
🌟 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
Finding | Instances | |
---|---|---|
[L-01] | Floating Pragma | 1 |
[L-02] | Confusing function name “delegates()” | 1 |
[L-03] | Proposal Threshold is not inclusive | 1 |
[L-04] | Lack of validation on quorum params setter | 1 |
[L-05] | Single-step Vetoer transfer is unsafe | 1 |
[L-06] | Empty fallback() /receive() function | 1 |
Finding | Instances | |
---|---|---|
[N-01] | The use of magic numbers is not recommended | 2 |
[N-02] | Incorrect spec | 2 |
[N-03] | Typos | 2 |
Contract | Total Instances | Total Findings | Low Findings | Low Instances | NC Findings | NC Instances |
---|---|---|---|---|---|---|
NounsDAOLogicV2.sol | 5 | 5 | 3 | 3 | 2 | 2 |
NounsDAOLogicV1.sol | 3 | 3 | 0 | 0 | 3 | 3 |
NounsDAOLogicV1.sol | 2 | 2 | 1 | 1 | 1 | 1 |
ERC721Checkpointable.sol | 1 | 1 | 1 | 1 | 0 | 0 |
NounsDAOLogicV2.sol | 1 | 1 | 1 | 1 | 0 | 0 |
A floating pragma might result in contract being tested/deployed with different compiler versions possibly leading to unexpected behaviour. 1 instance of this issue has been found:
[L-01] NounsDAOLogicV2.sol#L53-L54
pragma solidity ^0.8.6;
It seems confusing to name the function delegates()
(plural) when a delegator will only have, at most, 1 delegatee at a time.
1 instance of this issue has been found:
[L-02] ERC721Checkpointable.sol#L88
function delegates(address delegator) public view returns (address) { address current = _delegates[delegator]; return current == address(0) ? delegator : current; }
Proposers with the exact number of votes required by the proposal threshold should not be reverted. 1 instance of this issue has been found:
[L-03] NounsDAOLogicV1.sol#L187-L190
require( nouns.getPriorVotes(msg.sender, block.number - 1) > temp.proposalThreshold, 'NounsDAO::propose: proposer votes below proposal threshold' );
The quorum coeefficient should be "a fixed point integer with 6 decimals" but its value is not validated. This could have unexpected effects on the dynamic quorum calculation. 1 instance of this issue has been found:
[L-04] NounsDAOLogicV2.sol#L726
function _setQuorumCoefficient(uint32 newQuorumCoefficient) external { require(msg.sender == admin, 'NounsDAO::_setQuorumCoefficient: admin only'); DynamicQuorumParams memory params = getDynamicQuorumParamsAt(block.number); uint32 oldQuorumCoefficient = params.quorumCoefficient; params.quorumCoefficient = newQuorumCoefficient; _writeQuorumParamsCheckpoint(params); emit QuorumCoefficientSet(oldQuorumCoefficient, newQuorumCoefficient); }
If the newVetoer
is set to the incorrect address, the functionality will be unretrievable.
1 instance of this issue has been found:
[L-05] NounsDAOLogicV2.sol#L839-L845
function _setVetoer(address newVetoer) public { require(msg.sender == vetoer, 'NounsDAO::_setVetoer: vetoer only'); emit NewVetoer(vetoer, newVetoer); vetoer = newVetoer; }
fallback()
/receive()
functionIf intended functionality is to make use of ETH
the receive()
function should implement some operation, if not it should revert the transaction.
1 instance of this issue has been found:
[L-06] NounsDAOLogicV2.sol#L1030-L1031
receive() external payable {}
Consider setting constant numbers as a constant
variable for better readability and clarity.
2 instances of this issue have been found:
[N-01] NounsDAOLogicV2.sol#L908-L909
uint256 againstVotesBPS = (10000 * againstVotes) / totalSupply;
[N-01b] NounsDAOLogicV1.sol#L673-L674
return (number * bps) / 10000;
Remove or correct the comment so it refelcts the actual and intended functionality of the code. 2 instances of this issue have been found:
[N-02] NounsDAOLogicV2.sol#L851-L856
function _burnVetoPower() public { // Check caller is pendingAdmin and pendingAdmin ≠ address(0) require(msg.sender == vetoer, 'NounsDAO::_burnVetoPower: vetoer only'); _setVetoer(address(0)); }
[N-02b] NounsDAOLogicV1.sol#L649-L654
function _burnVetoPower() public { // Check caller is pendingAdmin and pendingAdmin ≠ address(0) require(msg.sender == vetoer, 'NounsDAO::_burnVetoPower: vetoer only'); _setVetoer(address(0)); }
Please fix typos. 2 instances of this issue have been found:
[N-03] NounsDAOLogicV1.sol#L46
// - Veto ability which allows `veteor` to halt any proposal at any stage unless -> vetoer
[N-03b] NounsDAOLogicV1.sol#L104-L105
* @notice Used to initialize the contract during delegator contructor -> constructor
🌟 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
39.356 USDC - $39.36
Finding | Instances | |
---|---|---|
[G-01] | Multiple address mappings can be combined into a single mapping of an address to a struct, where appropriate | 2 |
[G-02] | Cache array.length in require() statement | 2 |
[G-03] | for loop increments should be unchecked{} if overflow is not possible | 8 |
[G-04] | array.length should be cached in for loop | 8 |
[G-05] | Using prefix(++i ) instead of postfix (i++ ) saves gas | 8 |
[G-06] | Use custom errors rather than revert() /require() strings to save gas | 2 |
[G-07] | Unnecessary inits to 0 | 10 |
[G-08] | require() /revert() checks used multiples times should be turned into a function or modifier | 4 |
[G-09] | String longer than 32 bytes cost more gas | 64 |
[G-10] | bool is gas inefficient when used in storage | 5 |
Contract | Instances | Gas Ops |
---|---|---|
NounsDAOLogicV2.sol | 48 | 8 |
NounsDAOLogicV1.sol | 46 | 8 |
ERC721Checkpointable.sol | 9 | 3 |
NounsDAOInterfaces.sol | 5 | 1 |
NounsDAOProxy.sol | 2 | 1 |
ERC721Enumerable.sol | 2 | 1 |
NounsDAOLogicV1.sol | 1 | 1 |
Saves a storage slot for the mapping. Depending on the circumstances and 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. Finally, if both fields are accessed in the same function, can save ~42 gas per access due to not having to recalculate the key's keccak256 hash (Gkeccak256 - 30 gas) and that calculation's associated stack operatio 2 instances of this issue have been found:
[G-01] ERC721Checkpointable.sol#L44-L45
mapping(address => address) private _delegates;
[G-01b] ERC721Checkpointable.sol#L53-L56
mapping(address => mapping(uint32 => Checkpoint)) public checkpoints; /// @notice The number of checkpoints for each account mapping(address => uint32) public numCheckpoints;
array.length
in require()
statementtargets.length
is used multiple times. Caching it in memory can decrease gas usage from every read.
2 instances of this issue have been found:
[G-02] NounsDAOLogicV2.sol#L201-L208
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');
[G-02b] NounsDAOLogicV1.sol#L191-L198
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');
for
loop increments should be unchecked{}
if overflow is not possibleFrom Solidity 0.8.0
onwards using the unchecked
keyword saves 30 to 40 gas per loop.
Example:
uint length = array.length; for (uint i; i < length;){ uncheck { ++i } }
8 instances of this issue have been found:
[G-03] NounsDAOLogicV2.sol#L382-L383
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-03b] NounsDAOLogicV2.sol#L330-L331
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-03c] NounsDAOLogicV2.sol#L292-L293
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-03d] NounsDAOLogicV1.sol#L371-L372
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-03e] NounsDAOLogicV1.sol#L346-L347
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-03f] NounsDAOLogicV1.sol#L319-L320
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-03g] NounsDAOLogicV1.sol#L281-L282
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-03h] NounsDAOLogicV2.sol#L357-L358
for (uint256 i = 0; i < proposal.targets.length; i++) {
array.length
should be cached in for
loopCaching the length array would save gas on each iteration by not having to read from memory or storage multiple times. Example:
uint length = array.length; for (uint i; i < length;){ uncheck { ++i } }
8 instances of this issue have been found:
[G-04] NounsDAOLogicV2.sol#L382-L383
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-04b] NounsDAOLogicV2.sol#L330-L331
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-04c] NounsDAOLogicV2.sol#L292-L293
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-04d] NounsDAOLogicV1.sol#L371-L372
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-04e] NounsDAOLogicV1.sol#L346-L347
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-04f] NounsDAOLogicV1.sol#L319-L320
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-04g] NounsDAOLogicV1.sol#L281-L282
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-04h] NounsDAOLogicV2.sol#L357-L358
for (uint256 i = 0; i < proposal.targets.length; i++) {
++i
) instead of postfix (i++
) saves gasIt saves 6 gas per iteration. 8 instances of this issue have been found:
[G-05] NounsDAOLogicV2.sol#L382-L383
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-05b] NounsDAOLogicV2.sol#L330-L331
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-05c] NounsDAOLogicV2.sol#L292-L293
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-05d] NounsDAOLogicV1.sol#L371-L372
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-05e] NounsDAOLogicV1.sol#L346-L347
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-05f] NounsDAOLogicV1.sol#L319-L320
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-05g] NounsDAOLogicV1.sol#L281-L282
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-05h] NounsDAOLogicV2.sol#L357-L358
for (uint256 i = 0; i < proposal.targets.length; i++) {
revert()
/require()
strings to save gasCustom errors save ~50 gas each time they're hit by avoiding having to allocate and store the revert string.
Only one instance was given but the issue can be attributed to all require()
/revert()
functions that do not implement custom errors in the contract.
2 instances of this issue have been found:
[G-06] NounsDAOLogicV2.sol#L133-L134
require(address(timelock) == address(0), 'NounsDAO::initialize: can only initialize once');
[G-06b] NounsDAOLogicV1.sol#L122-L123
require(address(timelock) == address(0), 'NounsDAO::initialize: can only initialize once');
These values are set by default. 10 instances of this issue have been found:
[G-07] ERC721Checkpointable.sol#L41-L42
uint8 public constant decimals = 0;
[G-07b] NounsDAOLogicV2.sol#L382-L383
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-07c] NounsDAOLogicV2.sol#L357-L358
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-07d] NounsDAOLogicV2.sol#L330-L331
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-07e] NounsDAOLogicV2.sol#L292-L293
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-07f] NounsDAOLogicV1.sol#L371-L372
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-07g] NounsDAOLogicV1.sol#L346-L347
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-07h] NounsDAOLogicV1.sol#L319-L320
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-07i] NounsDAOLogicV1.sol#L281-L282
for (uint256 i = 0; i < proposal.targets.length; i++) {
[G-07j] NounsDAOLogicV1.sol#L230-L235
newProposal.forVotes = 0; newProposal.againstVotes = 0; newProposal.abstainVotes = 0; newProposal.canceled = false; newProposal.executed = false; newProposal.vetoed = false;
require()
/revert()
checks used multiples times should be turned into a function or modifierDoing so increases code readability decreases number of instructions for the compiler. 4 instances of this issue have been found:
[G-08] NounsDAOLogicV2.sol#L801
require(msg.sender == admin -> repeated 8 times
[G-08b] NounsDAOLogicV2.sol#L853
require(msg.sender == vetoer -> repeated 3 times
[G-08c] NounsDAOLogicV1.sol#L365
require(msg.sender == vetoer -> repeated 3 times
[G-08d] NounsDAOLogicV1.sol#L599
require(msg.sender == admin -> repeated 6 times
" Each 32 byte chunk of the string requires an extra mstore. That is, additional cost for mstore, memory expansion costs, as well as stack operations. Note that, this runtime cost is only relevant when the revert condition is met." Source 64 instances of this issue have been found:
[G-09] NounsDAOProxy.sol#L80-L81
require(implementation_ != address(0), 'NounsDAOProxy::_setImplementation: invalid implementation address');
[G-09b] NounsDAOProxy.sol#L79-L80
require(msg.sender == admin, 'NounsDAOProxy::_setImplementation: admin only');
[G-09c] ERC721Enumerable.sol#L77-L78
require(index < ERC721Enumerable.totalSupply(), 'ERC721Enumerable: global index out of bounds');
[G-09d] ERC721Enumerable.sol#L62-L63
require(index < ERC721.balanceOf(owner), 'ERC721Enumerable: owner index out of bounds');
[G-09e] ERC721Checkpointable.sol#L292-L293
"ERC721Checkpointable::_writeCheckpoint: block number exceeds 32 bits" );
[G-09f] ERC721Checkpointable.sol#L277-L278
"ERC721Checkpointable::_moveDelegates: amount overflows" );
[G-09g] ERC721Checkpointable.sol#L264-L265
"ERC721Checkpointable::_moveDelegates: amount underflows" );
[G-09h] ERC721Checkpointable.sol#L201-L204
require( blockNumber < block.number, "ERC721Checkpointable::getPriorVotes: not yet determined" );
[G-09i] ERC721Checkpointable.sol#L163-L174
require( signatory != address(0), "ERC721Checkpointable::delegateBySig: invalid signature" ); require( nonce == nonces[signatory]++, "ERC721Checkpointable::delegateBySig: invalid nonce" ); require( block.timestamp <= expiry, "ERC721Checkpointable::delegateBySig: signature expired" );
[G-09j] ERC721Checkpointable.sol#L91-L94
safe96( balanceOf(delegator), "ERC721Checkpointable::votesToDelegate: amount exceeds 96 bits" );
[G-09k] NounsDAOLogicV2.sol#L923-L924
uint32 blockNumber = safe32(blockNumber_, 'NounsDAO::getDynamicQuorumParamsAt: block number exceeds 32 bits');
[G-09l] NounsDAOLogicV2.sol#L853-L854
require(msg.sender == vetoer, 'NounsDAO::_burnVetoPower: vetoer only');
[G-09m] NounsDAOLogicV2.sol#L840-L841
require(msg.sender == vetoer, 'NounsDAO::_setVetoer: vetoer only');
[G-09n] NounsDAOLogicV2.sol#L819-L820
require(msg.sender == pendingAdmin && msg.sender != address(0), 'NounsDAO::_acceptAdmin: pending admin only');
[G-09o] NounsDAOLogicV2.sol#L801-L802
require(msg.sender == admin, 'NounsDAO::_setPendingAdmin: admin only');
[G-09p] NounsDAOLogicV2.sol#L727-L728
require(msg.sender == admin, 'NounsDAO::_setQuorumCoefficient: admin only');
[G-09q] NounsDAOLogicV2.sol#L702-L703
require(msg.sender == admin, 'NounsDAO::_setMaxQuorumVotesBPS: admin only');
[G-09r] NounsDAOLogicV2.sol#L705-L712
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' );
[G-09s] NounsDAOLogicV2.sol#L674-L685
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' );
[G-09t] NounsDAOLogicV2.sol#L655-L660
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' );
[G-09u] NounsDAOLogicV2.sol#L638-L642
require(msg.sender == admin, 'NounsDAO::_setVotingPeriod: admin only'); require( newVotingPeriod >= MIN_VOTING_PERIOD && newVotingPeriod <= MAX_VOTING_PERIOD, 'NounsDAO::_setVotingPeriod: invalid voting period' );
[G-09v] NounsDAOLogicV2.sol#L623-L626
require( newVotingDelay >= MIN_VOTING_DELAY && newVotingDelay <= MAX_VOTING_DELAY, 'NounsDAO::_setVotingDelay: invalid voting delay' );
[G-09w] NounsDAOLogicV2.sol#L622-L623
require(msg.sender == admin, 'NounsDAO::_setVotingDelay: admin only');
[G-09x] NounsDAOLogicV2.sol#L593-L594
require(state(proposalId) == ProposalState.Active, 'NounsDAO::castVoteInternal: voting is closed'); require(support <= 2, 'NounsDAO::castVoteInternal: invalid vote type');
[G-09y] NounsDAOLogicV2.sol#L597-L598
require(receipt.hasVoted == false, 'NounsDAO::castVoteInternal: voter already voted');
[G-09z] NounsDAOLogicV2.sol#L433-L434
require(proposalCount >= proposalId, 'NounsDAO::state: invalid proposal id');
[G-09{] NounsDAOLogicV2.sol#L577-L578
require(signatory != address(0), 'NounsDAO::castVoteBySig: invalid signature');
[G-09|] NounsDAOLogicV2.sol#L375-L376
require(vetoer != address(0), 'NounsDAO::veto: veto power burned');
[G-09}] NounsDAOLogicV2.sol#L377-L378
require(state(proposalId) != ProposalState.Executed, 'NounsDAO::veto: cannot veto executed proposal');
[G-09~] NounsDAOLogicV2.sol#L347-L348
require(state(proposalId) != ProposalState.Executed, 'NounsDAO::cancel: cannot cancel executed proposal');
[G-09] NounsDAOLogicV2.sol#L312-L315
require( !timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), 'NounsDAO::queueOrRevertInternal: identical proposal action already queued at eta' );
[G-09] NounsDAOLogicV2.sol#L286-L289
require( state(proposalId) == ProposalState.Succeeded, 'NounsDAO::queue: proposal can only be queued if it is succeeded' );
[G-09] NounsDAOLogicV2.sol#L213-L220
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' );
[G-09] NounsDAOLogicV2.sol#L197-L209
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');
[G-09] NounsDAOLogicV2.sol#L133-L134
require(address(timelock) == address(0), 'NounsDAO::initialize: can only initialize once');
[G-09] NounsDAOLogicV2.sol#L135-L148
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' );
[G-09 ] NounsDAOLogicV2.sol#L105-L106
bytes32 public constant BALLOT_TYPEHASH = keccak256('Ballot(uint256 proposalId,uint8 support)');
[G-09] NounsDAOLogicV2.sol#L102-L103
keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');
[G-09] NounsDAOLogicV1.sol#L651-L652
require(msg.sender == vetoer, 'NounsDAO::_burnVetoPower: vetoer only');
[G-09] NounsDAOLogicV1.sol#L638-L639
require(msg.sender == vetoer, 'NounsDAO::_setVetoer: vetoer only');
[G-09] NounsDAOLogicV1.sol#L617-L618
require(msg.sender == pendingAdmin && msg.sender != address(0), 'NounsDAO::_acceptAdmin: pending admin only');
[G-09] NounsDAOLogicV1.sol#L599-L600
require(msg.sender == admin, 'NounsDAO::_setPendingAdmin: admin only');
[G-09] NounsDAOLogicV1.sol#L581-L585
require(msg.sender == admin, 'NounsDAO::_setQuorumVotesBPS: admin only'); require( newQuorumVotesBPS >= MIN_QUORUM_VOTES_BPS && newQuorumVotesBPS <= MAX_QUORUM_VOTES_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold' );
[G-09] NounsDAOLogicV1.sol#L563-L568
require(msg.sender == admin, 'NounsDAO::_setProposalThresholdBPS: admin only'); require( newProposalThresholdBPS >= MIN_PROPOSAL_THRESHOLD_BPS && newProposalThresholdBPS <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold' );
[G-09] NounsDAOLogicV1.sol#L546-L550
require(msg.sender == admin, 'NounsDAO::_setVotingPeriod: admin only'); require( newVotingPeriod >= MIN_VOTING_PERIOD && newVotingPeriod <= MAX_VOTING_PERIOD, 'NounsDAO::_setVotingPeriod: invalid voting period' );
[G-09] NounsDAOLogicV1.sol#L530-L534
require(msg.sender == admin, 'NounsDAO::_setVotingDelay: admin only'); require( newVotingDelay >= MIN_VOTING_DELAY && newVotingDelay <= MAX_VOTING_DELAY, 'NounsDAO::_setVotingDelay: invalid voting delay' );
[G-09] NounsDAOLogicV1.sol#L505-L506
require(receipt.hasVoted == false, 'NounsDAO::castVoteInternal: voter already voted');
[G-09] NounsDAOLogicV1.sol#L501-L502
require(state(proposalId) == ProposalState.Active, 'NounsDAO::castVoteInternal: voting is closed'); require(support <= 2, 'NounsDAO::castVoteInternal: invalid vote type');
[G-09] NounsDAOLogicV1.sol#L485-L486
require(signatory != address(0), 'NounsDAO::castVoteBySig: invalid signature');
[G-09] NounsDAOLogicV1.sol#L422-L423
require(proposalCount >= proposalId, 'NounsDAO::state: invalid proposal id');
[G-09] NounsDAOLogicV1.sol#L366-L367
require(state(proposalId) != ProposalState.Executed, 'NounsDAO::veto: cannot veto executed proposal');
[G-09] NounsDAOLogicV1.sol#L364-L365
require(vetoer != address(0), 'NounsDAO::veto: veto power burned');
[G-09] NounsDAOLogicV1.sol#L339-L343
require( msg.sender == proposal.proposer || nouns.getPriorVotes(proposal.proposer, block.number - 1) < proposal.proposalThreshold, 'NounsDAO::cancel: proposer above threshold' );
[G-09] NounsDAOLogicV1.sol#L336-L337
require(state(proposalId) != ProposalState.Executed, 'NounsDAO::cancel: cannot cancel executed proposal');
[G-09] NounsDAOLogicV1.sol#L313-L316
require( state(proposalId) == ProposalState.Queued, 'NounsDAO::execute: proposal can only be executed if it is queued' );
[G-09] NounsDAOLogicV1.sol#L301-L304
require( !timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), 'NounsDAO::queueOrRevertInternal: identical proposal action already queued at eta' );
[G-09] NounsDAOLogicV1.sol#L275-L278
require( state(proposalId) == ProposalState.Succeeded, 'NounsDAO::queue: proposal can only be queued if it is succeeded' );
[G-09] NounsDAOLogicV1.sol#L203-L210
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' );
[G-09] NounsDAOLogicV1.sol#L197-L198
require(targets.length != 0, 'NounsDAO::propose: must provide actions'); require(targets.length <= proposalMaxOperations, 'NounsDAO::propose: too many actions');
[G-09] NounsDAOLogicV1.sol#L191-L196
require( targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, 'NounsDAO::propose: proposal function information arity mismatch' );
[G-09] NounsDAOLogicV1.sol#L187-L190
require( nouns.getPriorVotes(msg.sender, block.number - 1) > temp.proposalThreshold, 'NounsDAO::propose: proposer votes below proposal threshold' );
[G-09] NounsDAOLogicV1.sol#L124-L141
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' );
[G-09] NounsDAOLogicV1.sol#L122-L123
require(address(timelock) == address(0), 'NounsDAO::initialize: can only initialize once');
[G-09 ] NounsDAOLogicV1.sol#L101-L102
bytes32 public constant BALLOT_TYPEHASH = keccak256('Ballot(uint256 proposalId,uint8 support)');
bool
is gas inefficient when used in storageInstead use uint256
values to represent true/false instead.
Reference
5 instances of this issue have been found:
[G-10] NounsDAOInterfaces.sol#L390-L394
bool canceled; /// @notice Flag marking whether the proposal has been vetoed bool vetoed; /// @notice Flag marking whether the proposal has been executed bool executed;
[G-10b] NounsDAOInterfaces.sol#L320-L321
bool hasVoted;
[G-10c] NounsDAOInterfaces.sol#L304-L308
bool canceled; /// @notice Flag marking whether the proposal has been vetoed bool vetoed; /// @notice Flag marking whether the proposal has been executed bool executed;
[G-10d] NounsDAOInterfaces.sol#L215-L220
/// @notice Whether or not a vote has been cast 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;
[G-10e] NounsDAOInterfaces.sol#L204-L208
bool canceled; /// @notice Flag marking whether the proposal has been vetoed bool vetoed; /// @notice Flag marking whether the proposal has been executed bool executed;