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: 93/160
Findings: 2
Award: $52.10
🌟 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
35.4387 USDC - $35.44
_burnVetoPower
function
function _burnVetoPower() public { // Check caller is pendingAdmin and pendingAdmin ≠address(0) require(msg.sender == vetoer, 'NounsDAO::_burnVetoPower: vetoer only'); _setVetoer(address(0)); }
uint256 public constant MAX_QUORUM_VOTES_BPS_UPPER_BOUND = 6_000; // 4,000 basis points or 60%
vote
with 0 votes and spam the logs - this won't cause any damage because the function won't change the state, but it will emit an event.🌟 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
16.6573 USDC - $16.66
totalSupply
and creationBlock
to uint96
and uint32
respectively so they can fit in the same word and won't require 2 words in the storage (we know totalSupply is a uint96 so it'll be safe)DynamicQuorumParamsCheckpoint
to not contain another struct. The current struct definition requires 2 words in the storage, while the data can be stored in one word (as written in the documentation, a struct member always opens a new word in storage). The current struct:
The more efficient struct:/// @notice A checkpoint for storing dynamic quorum params from a given block struct DynamicQuorumParamsCheckpoint { /// @notice The block at which the new values were set uint32 fromBlock; /// @notice The parameter values of this checkpoint DynamicQuorumParams params; }
/// @notice A checkpoint for storing dynamic quorum params from a given block struct DynamicQuorumParamsCheckpoint { /// @notice The block at which the new values were set uint32 fromBlock; /// @notice The minimum 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 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; }
nouns
, proposalCount
in the propose
functionpropose
function:
newProposal.id
with the cached value of proposalCount
newProposal.proposer
with msg.sender
newProposal.startBlock
, newProposal.endBlock
and newProposal.proposalThreshold
with temp.startBlock
, temp.endBlock
and newProposal.proposalThreshold
timelock
in the queueOrRevertInternal
functionproposal.proposer
in the cancel
functionvetoer
in the veto
functionpendingAdmin
and use it before the require in the _acceptAdmin
functionoldAdmin
and oldPendingAdmin
variables instead of accessing the storage multiple timescalldata
when passing array and struct arguments instead of memory
!= 0
instead of > 0
when comparing uint
s to save gas
x >> i == x / (2 ** i)
).
uint256 center = upper - (upper - lower) / 2;
with uint256 center = upper - ((upper - lower) >> 1);
from != to
instead of calculating it twice in _beforeTokenTransfer
function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); bool diffFromTo = from != to; if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (diffFromTo) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (diffFromTo) { _addTokenToOwnerEnumeration(to, tokenId); } }
!= 0
instead of > 0
when comparing uint
s to save gas
x >> i == x / (2 ** i)
).