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: 2/168
Findings: 7
Award: $4,647.17
🌟 Selected for report: 1
🚀 Solo Findings: 1
🌟 Selected for report: berndartmueller
Also found by: 0x52, 0xSky, Chom, PwnPatrol, bin2chen, cccz, davidbrai, elprofesor, izhuer, m9800, rvierdiiev
Governor::propose
function checks if sender has more than proposalThreshold()
votes to create proposal. It checks it in such a way if (getVotes(msg.sender, block.timestamp - 1) < proposalThreshold()) revert BELOW_PROPOSAL_THRESHOLD();
. It checks the votes in the checkpoint that was before block.timestamp
.
This allows user to transfer all his nft(checkpoint with block.timestamp
is created where proposer doesn't have votes), then create a proposal in the same block(votes from checkpoint that was before are used).
Use if (getVotes(msg.sender, block.timestamp) < proposalThreshold()) revert BELOW_PROPOSAL_THRESHOLD();
instead to check checkpoint with current block.timestamp as well.
#0 - GalloDaSballo
2022-09-20T21:43:54Z
70.6842 USDC - $70.68
Governor
has functions to update settings.votingDelay
, settings.votingPeriod
, settings.proposalThresholdBps
, settings.quorumThresholdBps
. They are Governor::updateVotingDelay
, Governor::updateVotingPeriod
, Governor::updateProposalThresholdBps
, Governor::updateQuorumThresholdBps
. These functions don't do any checkings of input values. Providing incorrect values may break the logic of governing.
Governor::updateVotingDelay
function should check the value using some upper bound value.
Governor::updateVotingPeriod
function should at least check that the value is not 0, because then voting will finish instantly.
Governor::updateProposalThresholdBps
function should check at least that the value is not bigger then 100%(however smarter will be to use some upper and lower bound values).
Governor::updateQuorumThresholdBps
function should check at least that the value is not bigger then 100% and is not 0(however smarter will be to use some upper and lower bound values).
Add input checking to the setters.
#0 - iainnash
2022-09-26T19:42:42Z
Severity here seems limited (and lots of individual dup tickets for all the setters) since the DAO creator/voting sets these parameters themselves. Still a bug nonetheless.
#1 - GalloDaSballo
2022-09-27T02:10:42Z
Dup of #482
🌟 Selected for report: rbserver
Also found by: ayeslick, rvierdiiev
729.7931 USDC - $729.79
Governor::veto
function gives ability for vetoer to block any proposal. And there is no ability to somehow beat veto.
That means that vetoer can control all system using veto in case when he doesn't like smth.
Some mechanism like 50% of total votes can unblock veto should resolve such problem. Dao should be able to control vetoer.
Add ability to beat veto using some mechanism. For example 50% of total votes.
#0 - iainnash
2022-09-26T18:14:18Z
The vetoer having 100% power is by design, this is not a vuln/bug in the contract but an intentional ability to have early on before ownership is removed from the deployer.
#1 - GalloDaSballo
2022-09-27T02:16:37Z
Dup of #622
🌟 Selected for report: __141345__
Also found by: pauliax, rbserver, rvierdiiev, sorrynotsorry
354.6794 USDC - $354.68
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L331 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L315 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L323 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L106 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L119 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L141
In Auction
contract there is ability for the owner to use setTimeBuffer
, setMinimumBidIncrement
, setReservePrice
functions to change settings.timeBuffer
, settings.minBidIncrement
and settings.reservePrice
params. All this settings have impact on createBid
function as they are used to determine time to extend auction, minimum bid increment and start price for the nft. So if you change any of this values during the auction it will impact current auction.
These are setters. https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L331 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L315 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L323
And here you can find how these settings are used in current auction in createBid
function.
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L106
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L119
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L141
settings.timeBuffer
, settings.minBidIncrement
and settings.reservePrice
should be set for each auction at creation time.
#0 - GalloDaSballo
2022-09-26T12:12:12Z
Dup of #450
🌟 Selected for report: rvierdiiev
2702.9374 USDC - $2,702.94
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/Token.sol#L71-L126 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/Token.sol#L154 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/Token.sol#L207-L213
According to nouns builder, founder can have percentage of created nft. This is set in Token::_addFounders
function.
When new nft is minted by mint
function then total supply of tokens is incremented and assigned to tokenId using tokenId = settings.totalSupply++
. Then this token is checked if it should be mint to founder(then again increment total supply of tokens) or should be mint to auction using while (_isForFounder(tokenId))
.
If token wasn't sold during the auction then auction burns it using burn
function. And this function doesn't decrement settings.totalSupply
value. But total supply has changed now, it has decreased by one.
So suppose that we have 1 founder of dao that should receive 2% of nft, that means that if 100 nft are available(for example), then 2 of them belongs to that founder. If we have minted 100 nft and 10 of them were not sold(they were then burned), then there are 90 nft available now. And in current implementation founder has ownership of 2 of them, however 2 is not 2% of 90. So in case when nft are not sold on auction the percentage of founder's tokens is increasing and the increasing speed depends on how many tokens were not sold. Also founder gets more power in the community(as he has more percentage now).
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/Token.sol#L71-L126 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/Token.sol#L154 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/Token.sol#L207-L213
When burn
function is called then do settings.totalSupply--
.
#0 - GalloDaSballo
2022-09-26T19:27:17Z
In contrast to #423 this report is arguing the fairness of token distribution when a token is burned.
I think that, because they are relating to a different aspect, this report is unique, however, because the impact and mechanism is based on burn not changing totalSupply, and "accounting being incorrect" because of that, then I believe this is also a Medium Severity finding
🌟 Selected for report: Jeiwan
Also found by: imare, ladboy233, rvierdiiev
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/metadata/MetadataRenderer.sol#L91-L163 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/metadata/MetadataRenderer.sol#L185-L201 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/metadata/MetadataRenderer.sol#L222 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/Token.sol#L172
When new token is minted then metadata should be created for it. After the minting MetadataRenderer::onMinted
function is called that returns boolean
. If metadata was not created then Token::_mint
function will revert.
MetadataRenderer::onMinted
function is getting properties.length
(count of metadata properties) and then tries to fill each property in loop. In the end of function it always returns true. If noone provided properties before then empty metadata will be created(but still function will return true and token will be minted). However if you then call MetadataRenderer::getAttributes
or MetadataRenderer::tokenURI
the function will revert with TOKEN_NOT_MINTED
error. This is because the metadata for token is empty.
Why that can happen that properties.length
may be empty? That can happen if the owner didn't call MetadataRenderer::addProperties
function that is responsible for storing metadata params.
I believe that MetadataRenderer::onMinted
should not be called before MetadataRenderer::addProperties
.
After token is minted then metadata is rendered. https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/Token.sol#L172 On minted is called and if properties length is 0 it's still returns true. https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/metadata/MetadataRenderer.sol#L185-L201 When you try to get metadata of token then function reverts. https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/metadata/MetadataRenderer.sol#L222
This function should provide metadata configuration and may not forgot to be called. https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/metadata/MetadataRenderer.sol#L91-L163
Make sure that MetadataRenderer::onMinted
could not be called before MetadataRenderer::addProperties
. You can check for the properties.length != 0
for example to allow to use MetadataRenderer::onMinted
.
#0 - GalloDaSballo
2022-09-21T14:28:33Z
🌟 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.861 USDC - $60.86
_proposalId
exists. Revert when no _proposalId
instead of returning 0 values.
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/governance/governor/Governor.sol#L482
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/governance/governor/Governor.sol#L488
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/governance/governor/Governor.sol#L516
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/governance/governor/Governor.sol#L508
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/governance/governor/Governor.sol#L516
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/governance/treasury/Treasury.sol#L69
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/governance/treasury/Treasury.sol#L76_founders[i].wallet
is not 0 address as this address is very important for the dao.
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/Token.sol#L97_founderId
exists. Revert when no _ founderId
instead of returning 0 values.
https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/token/Token.sol#L247#0 - GalloDaSballo
2022-09-27T00:49:22Z
L
NC
R
NC
1L 1R 2NC