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: 49/168
Findings: 4
Award: $273.39
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: MEP
Also found by: 0xSky, CertoraInc, MiloTruck, PwnPatrol, R2, Tointer, V_B, __141345__, antonttc, azephiar, cccz, d3e4, datapunk, davidbrai, easy_peasy, hansfriese, minhtrng, neumo, pcarranzav, peritoflores, scaraven, teawaterwire, tonisives, unforgiven, wagmi, zkhorse, zzzitron
5.6134 USDC - $5.61
There is a typo that can result in owners not getting part of their share. For example, with share percentages [1,1,1,1,1,1,20], last owner would actually get 19% instead of 20. And with 80 founders with 1% and one founder with 20%, last owner would get just 4%. This is happening because baseTokenId not wrapping when it goes beyond 99.
change line to baseTokenId = (baseTokenId + schedule) % 100;
Paste this in Token.t.sol to test this issue (last assert would fail without fix) :
function test_brokeFoundersShare() public { createUsers(7, 1 ether); address[] memory wallets = new address[](7); uint256[] memory percents = new uint256[](7); uint256[] memory vestExpirys = new uint256[](7); uint256 end = 4 weeks; unchecked { for (uint256 i; i < 6; ++i) { wallets[i] = otherUsers[i]; percents[i] = 1; vestExpirys[i] = end; } wallets[6] = otherUsers[6]; percents[6] = 20; vestExpirys[6] = end; } deployWithCustomFounders(wallets, percents, vestExpirys); assertEq(token.totalFounders(), 7); assertEq(token.totalFounderOwnership(), 26); Founder memory founder; uint actualTotalFounderOwnership; for (uint256 i; i < 100; ++i) { founder = token.getScheduledRecipient(i); if(founder.wallet != address(0)){ actualTotalFounderOwnership++; } } assertEq(token.totalFounderOwnership(), actualTotalFounderOwnership); }
#0 - GalloDaSballo
2022-09-26T00:13:41Z
Dup of #269
🌟 Selected for report: azephiar
Also found by: 0x52, 0xSmartContract, Ch_301, Tointer, __141345__, bin2chen, indijanc
token.totalSupply() returning minted amount, but actual totalSupply can be lower, since auctions that ended without bidder will result in token burning. This wrong value used in Governor.sol to calculate proposalThreshold and quorumThreshold, which then assigned to proposal and used in governance.
As an example we can imagine project where 50% of all auctions ends up without bidder. This can be either because of malicious attack, low activity, high minimum bid, incentive to ignore some tokens due to their metadata, or any combination of the above. In this example, when we minted token with id 1000, actual supply would be 500. But governance contract would calculate quorum and proposal thresholds as if there is 1000 tokens that can vote. This potentially can make DAO ungovernable, especially in high threshold setups. In less drastic situations, it still would affect governance in a non expected and possibly harmful way
bug here: https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/token/Token.sol#L280 totalSupply used here to calculate thresholds: https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/governance/governor/Governor.sol#L465-L477 then it gets to all proposals here: https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/governance/governor/Governor.sol#L168 and there: https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/governance/governor/Governor.sol#L123
VS Code
Make counter that would count burned tokens, then subtract this value from totalSupply calculation. And rename totalSupply variable in settings struct to avoid confusion
#0 - GalloDaSballo
2022-09-20T14:43:25Z
Dup of #405
🌟 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.7742 USDC - $60.77
blockhash(block.number)
would always return 0. It should be changed to blockhash(block.number - 1)
. This is not affecting anything in it's current form, but can be dangerous if later someone would change the code
#0 - GalloDaSballo
2022-09-27T01:09:59Z
L
🌟 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
this line can be changed to uint256 seed = uint256(blockhash(block.number - 1));
This would cut 150 gas on average and reduce codebase a little (you could delete _generateSeed function after this change). There is no advantage to generate it the way _generateSeed function does it, blockhash provides sufficent amount of entropy, as it hashes whole block and it's metadata
#0 - GalloDaSballo
2022-09-26T20:39:50Z
150