Platform: Code4rena
Start Date: 06/09/2022
Pot Size: $90,000 USDC
Total HM: 33
Participants: 168
Period: 9 days
Judge: GalloDaSballo
Total Solo HM: 10
Id: 157
League: ETH
Rank: 99/168
Findings: 2
Award: $106.18
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Lambda
Also found by: 0x1337, 0x1f8b, 0x4non, 0x85102, 0xA5DF, 0xNazgul, 0xSmartContract, 0xbepresent, 0xc0ffEE, 8olidity, Aymen0909, B2, Bnke0x0, CRYP70, Captainkay, CertoraInc, Ch_301, Chom, ChristianKuri, CodingNameKiki, Deivitto, Diana, DimitarDimitrov, ElKu, EthLedger, Franfran, Funen, GimelSec, JansenC, Jeiwan, Jujic, Lead_Belly, MEP, MasterCookie, MiloTruck, Noah3o6, PPrieditis, PaludoX0, Picodes, PwnPatrol, R2, Randyyy, RaymondFam, Respx, ReyAdmirado, Rolezn, Samatak, Tointer, Tomo, V_B, Waze, _Adam, __141345__, a12jmx, ak1, asutorufos, azephiar, ballx, bharg4v, bin2chen, bobirichman, brgltd, bulej93, c3phas, cccz, ch0bu, cloudjunky, cryptonue, cryptostellar5, cryptphi, csanuragjain, d3e4, datapunk, davidbrai, delfin454000, dharma09, dic0de, dipp, djxploit, eierina, erictee, fatherOfBlocks, gogo, hansfriese, hyh, imare, indijanc, izhuer, jonatascm, ladboy233, leosathya, lucacez, lukris02, m9800, martin, minhtrng, ne0n, neumo, oyc_109, p_crypt0, pashov, pauliax, pcarranzav, pedr02b2, peritoflores, pfapostol, rbserver, ret2basic, robee, rvierdiiev, sach1r0, sahar, scaraven, sikorico, simon135, slowmoses, sorrynotsorry, tnevler, tonisives, volky, yixxas, zkhorse, zzzitron
60.7743 USDC - $60.77
Missing checks for zero-addresses may lead to infunctional protocol, if the variable addresses are updated incorrectly.
Proof of Concept Navigate to the following contracts.
https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/auction/Auction.sol#L39 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/auction/Auction.sol#L54-L59 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/governance/governor/Governor.sol#L41 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/governance/governor/Governor.sol#L57-L64 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/governance/governor/Governor.sol#L116-L117 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/governance/governor/Governor.sol#L324-L325 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/governance/treasury/Treasury.sol#L32 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/governance/treasury/Treasury.sol#L43 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/governance/treasury/Treasury.sol#L141-L142 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/manager/Manager.sol#L55-L60 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/token/Token.sol#L30 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/token/Token.sol#L43-L47 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/token/metadata/MetadataRenderer.sol#L32 https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/token/metadata/MetadataRenderer.sol#L45-L49
Recommended Mitigation Steps Consider adding zero-address checks in the discussed constructors: require(newAddr != address(0));.
__GAP[50]
STORAGE VARIABLE TO ALLOW FOR NEW STORAGE VARIABLES IN LATER VERSIONSSee this link for a description of this storage variable. While some contracts may not currently be sub-classed, adding the variable now protects against forgetting to add it in the future.
All upgradeables contracts
#0 - GalloDaSballo
2022-09-27T00:26:05Z
1L 1NC
🌟 Selected for report: pfapostol
Also found by: 0x1f8b, 0x4non, 0x5rings, 0xA5DF, 0xSmartContract, 0xc0ffEE, 0xkatana, Aymen0909, Bnke0x0, CertoraInc, Chandr, CodingNameKiki, Cr4ckM3, Deivitto, DimSon, Franfran, JAGADESH, JC, Jeiwan, Lambda, LeoS, Matin, Metatron, Migue, MiloTruck, PPrieditis, PaludoX0, R2, RaymondFam, Respx, ReyAdmirado, Rolezn, Saintcode_, Samatak, SnowMan, StevenL, Tointer, TomJ, Tomo, WatchDogs, Waze, _Adam, __141345__, ajtra, asutorufos, ballx, brgltd, bulej93, c3phas, ch0bu, dharma09, djxploit, durianSausage, easy_peasy, fatherOfBlocks, gianganhnguyen, gogo, imare, leosathya, lucacez, martin, oyc_109, pauliax, peiw, prasantgupta52, ret2basic, rfa, robee, sikorico, simon135, tofunmi, volky, wagmi, zishansami
45.4145 USDC - $45.41
Uninitialized variables are assigned with the types default value. Explicitly initializing a variable with it's default value costs unnecesary gas.
There are 5 instances of this issue:
File: src/governance/treasury/Treasury.sol 167: for (uint256 i = 0; i < numTargets; ++i) {
File: src/token/metadata/MetadataRenderer.sol 119: for (uint256 i = 0; i < numNewProperties; ++i) { 133: for (uint256 i = 0; i < numNewItems; ++i) { 189: for (uint256 i = 0; i < numProperties; ++i) { 229: for (uint256 i = 0; i < numProperties; ++i) {
!= 0 costs less gas compared to > 0 for unsigned integers in require statements with the optimizer enabled (6 gas)
For uints the minimum value would be 0 and never a negative value. Since it cannot be a negative value, then the check > 0 is essentially checking that the value is not equal to 0 therefore >0 can be replaced with !=0 which saves gas.
Proof: While it may seem that > 0 is cheaper than !=, this is only true without the optimizer enabled and outside a require statement. If you enable the optimizer at 10k AND you’re in a require statement, this will save gas. You can see this tweet for more proofs: https://twitter.com/gzeon/status/1485428085885640706
I suggest changing > 0 with != 0 here:
File: ERC1967Upgrade.sol Line 61
if (_data.length > 0 || _forceCall) {
File: ERC721Votes.sol Line 203
if (_from != _to && _amount > 0) {
There are 6 instances of this issue:
File: Governor.sol Line 230
nonces[_voter]++
File: ERC721Votes.sol Line 162
nonces[_from]++
File: ERC721Votes.sol Line 207
uint256 nCheckpoints = numCheckpoints[_from]++;
File: ERC721Votes.sol Line 222
uint256 nCheckpoints = numCheckpoints[_to]++;
File: Token.sol Line 91
uint256 founderId = settings.numFounders++;
File: Token.sol Line 154
tokenId = settings.totalSupply++;
File: Governor.sol Line 280
proposal.againstVotes += uint32(weight);
File: Governor.sol Line 285
proposal.forVotes += uint32(weight);
File: Governor.sol Line 290
proposal.abstainVotes += uint32(weight);
File: Token.sol Line 88
if ((totalOwnership += uint8(founderPct)) > 100) revert INVALID_FOUNDER_OWNERSHIP();
File: Token.sol Line 118
(baseTokenId += schedule) % 100;
File: MetadataRender.sol Line 140
_propertyId += numStoredProperties;
Here, the values emitted shouldn’t be read from storage. The existing memory values should be used instead: File: Auction.sol Line 172
Auction memory _auction = auction; // Ensure the auction wasn't already settled if (auction.settled) revert AUCTION_SETTLED();
It must be read from the variable created in memory and not from storage
The code can be optimized by minimising the number of SLOADs. SLOADs are expensive 100 gas compared to MLOADs/MSTOREs(3gas) Storage value should get cached in memory
File: Auction.sol Lines 244-260
Create a variable in memory to read auction
, and not read it twice from storage:
function unpause() external onlyOwner { _unpause(); Auction memory _auction = auction; // If this is the first auction: if (_auction.tokenId == 0) { // Transfer ownership of the contract to the DAO transferOwnership(settings.treasury); // Start the first auction _createAuction(); } // Else if the contract was paused and the previous auction was settled: else if (_auction.settled) { // Start the next auction _createAuction(); } }
File: Token.sol Lines 177-199
function _isForFounder(uint256 _tokenId) private returns (bool) { // Get the base token id uint256 baseTokenId = _tokenId % 100; tokenRecipient memory _toketokenRecipient = tokenRecipient[baseTokenId]; // If there is no scheduled recipient: if (_tokenRecipient.wallet == address(0)) { return false; // Else if the founder is still vesting: } else if (block.timestamp < _tokenRecipient.vestExpiry) { // Mint the token to the founder _mint(_tokenRecipient.wallet, _tokenId); return true; // Else the founder has finished vesting: } else { // Remove them from future lookups delete tokenRecipient[baseTokenId]; return false; } }
#0 - GalloDaSballo
2022-09-26T20:05:34Z
150 gas 100 SLOAD Rest from ++ and from i = 0