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: 23/168
Findings: 8
Award: $919.25
🌟 Selected for report: 0
🚀 Solo Findings: 0
235.614 USDC - $235.61
Malicious user can get unlimited count of votes
unchecked(1 - 2) == MAX_UIN256
Writed test in hardhat:
... let aliceAddress = accounts[0].address; let bobAddress = accounts[1].address; // 1. Alice bought 1 NFT on auction await token.mint(); // 2. Alice delegates votes to Bob await token.delegate(bobAddress, {from: aliceAddress}); // 3. Alice bought second NFT on auction await token.mint(); // 4. Alice delegates voted to someone else await token.delegate(someoneElse, {from: aliceAddress}); // 5. Bob has 6277101735386680763835789423207666416102355444464034512895 votes console.log("bobVotes = %s", await token.getVotes(bobAddress) + ''); ...
Save how many tokens were delegated. And when delegation revoked, use that value to subtraction
#0 - GalloDaSballo
2022-09-20T21:05:32Z
If settings.token.totalSupply() < 10_000 / settings.quorumThresholdBps
, function will return 0
So all created proposition will automatically be in status ProposalState.Succeeded
after voting delay
Review your calculations, maybe add second statement for cases while totalSupply()
is low
#0 - GalloDaSballo
2022-09-20T21:29:23Z
🌟 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
baseTokenId
can be more then 100
Your expression is (baseTokenId += schedule) % 100
But it should be baseTokenId = (baseTokenId + schedule) % 100
Now in some cases baseTokenId can be more then 100
In such cases founder will not receive his NFT, for which baseTokenId were >= 100
Fix statement
#0 - GalloDaSballo
2022-09-20T19:47:25Z
#1 - GalloDaSballo
2022-09-25T19:45:05Z
You have no checks that votingDelay more then 0
If anyone will deploy DAO with votingDelay=0
, anyone will be able to manipulate votes:
getVotes(_voter, proposal.timeCreated)
(proposal.timeCreated - current block. because ``votingDelay=0`)So malicious user can create proposal and vote it with many tokens (even when he have just 1)
See above
Add checks for governance params. Check then votingDelay more then allowed minimum
#0 - GalloDaSballo
2022-09-20T19:56:50Z
#1 - GalloDaSballo
2022-09-25T20:36:06Z
Because I bulked other findings of the same type (Lack of checks from Admin Settings), I will bulk this one as well for fairness
34.7819 USDC - $34.78
Judge has assessed an item in Issue #139 as Medium risk. The relevant finding follows:
#0 - GalloDaSballo
2022-09-27T14:44:55Z
Recommendations Add required checks
Dup of #523
🌟 Selected for report: azephiar
Also found by: R2, Solimander, __141345__, bin2chen, cccz, davidbrai, pauliax, rbserver
If settings.token.totalSupply() < 10_000/settings.proposalThresholdBps)
, then function returns 0
So anyone can send proposal
Review math, maybe add other statement while there are low totalSupply
#0 - GalloDaSballo
2022-09-20T13:18:16Z
Dup of #604
🌟 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
131.8319 USDC - $131.83
Auction.constructor()
and Auction.initialize()
manager
, _token
, _founder
, _duration
, _reservePrice
,treasury
may be 0
Add required checks
Prolongation logic: auction.endTime = uint40(block.timestamp + settings.timeBuffer)
And may be prolonging forever
Add hard limit
No checks for _targets.length
. When executing this proposal, OutOfGas may happen and it proposal will not be executed ever
Add limit for _targets.length
Governor.propose()
No checks that sum of _values
exists on balance
It will fail on executing
Add balance checks and do not accept proposal if no balance for it's execution
uint32
may become a problem in futureBalance of token is uint256
. But you stores votes in uint32
Governor.execute()
is payable?The function should not be payable. All funds should be stored in treasury
It would be better to make at as role, not hardcoded variable And to be able to give that role to more than 1 address
There may be mistakes and typos on copying
Manager.constructor()
_tokenImpl
, _metadataImpl
, _auctionImpl
, _treasuryImpl
, _governorImpl
may be 0
Add required checks
Token.constructor()
and Token.initialize()
manager
, metadataRenderer
, auction
may be 0
Add required checks
_founders[i].wallet == 0
(i > 0)There is a check only for first founder, not for other
Add required checks
MetadataRenderer.constructor()
and MetadataRenderer.initialize()
_manager
, _token
, _founder
, treasury
may be 0
Add required checks
MetadataRenderer.numProperties
is not limitedIt may lead to OutOfGas in MetadataRenderer.onMinted()
Add required checks
blockhash(block.number)
is uselessblockhash(block.number) is always 0
Other properties will be ignored in MetadataRenderer.onMinted()
But there are no checks in MetadataRenderer.addProperties()
Add required checks
#0 - GalloDaSballo
2022-09-27T13:45:06Z
L
L
L
TODO
L
4L
🌟 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.4512 USDC - $45.45
https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/auction/Auction.sol#L211
block.timestamp
costs only 2 gas, it so cheep
So you do not need to create new variable
https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/governance/governor/Governor.sol#L128
You already saved function result in currentProposalThreshold
, use it
https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/lib/token/ERC721Votes.sol#L70 You have many calls to this object, so it would be better to save it to memory
EIP712._computeDomainSeparator()
https://github.com/code-423n4/2022-09-nouns-builder/blob/7e9fddbbacdd7d7812e912a369cfd862ee67dc03/src/lib/utils/EIP712.sol#L68 There is no overrides for this function, so you can just hardcode this value and remove function
#0 - GalloDaSballo
2022-09-26T20:20:05Z
1 gas
200
100
Disputed, they check for chainId (technically can be done cheaper)
301