Nouns Builder contest - neumo's results

A permissionless, governed protocol to deploy nouns-style DAOs complete with treasury, generative collections, and governance mechanisms.

General Information

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

Nouns Builder

Findings Distribution

Researcher Performance

Rank: 106/168

Findings: 2

Award: $66.38

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

5.6134 USDC - $5.61

Labels

bug
duplicate
2 (Med Risk)

External Links

Lines of code

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#L118

Vulnerability details

Impact

Function _addFounders in Token.sol does not always allocate the correct percentage of NFTs for each founder.

Proof of Concept

In the test below (which I included inside Token.t.sol test file), there are two founders with 30 and 50 percent of allocation respectively, but in the end the allocation is only 35% for the 50 percent founder.

function test_FoundersPercentIssue() public { // Deploy address[] memory wallets = new address[](2); uint256[] memory percents = new uint256[](2); uint256[] memory vestingEnds = new uint256[](2); wallets[0] = founder; wallets[1] = founder2; percents[0] = 30; percents[1] = 50; vestingEnds[0] = 4 weeks; vestingEnds[1] = 4 weeks; setFounderParams(wallets, percents, vestingEnds); setMockTokenParams(); setMockAuctionParams(); setMockGovParams(); deploy(foundersArr, tokenParams, auctionParams, govParams); // end Deploy assertEq(token.totalFounders(), 2); assertEq(token.totalFounderOwnership(), 80); address wallet; uint8 numFounder; uint8 numFounder2; for(uint256 i;i<100;i++){ (wallet,,) = token.tokenRecipient(i); if(wallet == founder){ numFounder++; } else if(wallet == founder2){ numFounder2++; } } assertEq(numFounder, 30); assertEq(numFounder2, 35); }

Tools Used

Forge

The buggy line is this, because when baseTokenId is incremented by schedule and goes beyond 100, the token is not allocated to the founder because only the first 100 are counted towards allocation and minting in function _isForFounder. The las part of the line, % 100 doesn't affect the value of baseTokenId.

Instead of:

(baseTokenId += schedule) % 100;

it should be:

baseTokenId = (baseTokenId + schedule) % 100;

#0 - GalloDaSballo

2022-09-20T12:57:28Z

Dup of #499

Lines of code

https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L147-L150 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L146 https://github.com/code-423n4/2022-09-nouns-builder/blob/main/src/auction/Auction.sol#L323-L327

Vulnerability details

Impact

There is an unchecked block that in case timeBuffer is sufficiently large, would make the sum overflow and set the endTime of the auction in the past, making the auction end automatically. The developers are aware of this, that's why they have this comment. But I think it's not a matter of realistically overflowing, it could be set to a value large enough by mistake. It's not worth it to not validate the value of the time buffer, because the consequences could be devastating.

The best option would be to validate in function setTimeBuffer that the timeBuffer cannot be set to a large value.

Tools Used

Manual analysis

Change function setTimeBuffer with this:

function setTimeBuffer(uint256 _timeBuffer) external onlyOwner { require(_timeBuffer < 31536000, "TimeBuffer: too big"); settings.timeBuffer = SafeCast.toUint40(_timeBuffer); emit TimeBufferUpdated(_timeBuffer); }

I supposed that timeBuffer should be less than one year (probably much less), so I compared here with the number of seconds in a year.

#0 - GalloDaSballo

2022-09-20T23:16:27Z

We have to acknowledge that a zero timeBuffer means each new auction will sell to the first bidder, while unorthodox this is a type of expression that certain projects may want to have for a certain period of time

Because of that I don't believe that a vulnerability was shown here

#1 - neumoxx

2022-09-22T10:10:20Z

@GalloDaSballo A zero timeBuffer has the impact of not extending the auction beyond the end time, It does not imply that it will sell to the first bidder. The issue here is that an overflow by setting the timeBuffer to a high enough value, could set the endTime of the auction in the past.

#2 - GalloDaSballo

2022-09-22T14:01:48Z

@GalloDaSballo A zero timeBuffer has the impact of not extending the auction beyond the end time, It does not imply that it will sell to the first bidder. The issue here is that an overflow by setting the timeBuffer to a high enough value, could set the endTime of the auction in the past.

Thank you for the comment, I'll double check, at this time I got these type of reports bulked as "unchecked validation of auction params", but I'll have to separate them with nuance as I spend more time with all the findings

#3 - iainnash

2022-09-26T19:08:58Z

I think what @neumoxx wrote is more concerning than the submission. I'd say the submission as-is is closer to a QA.

#4 - GalloDaSballo

2022-09-26T19:41:36Z

I think the submission has validity and unfortunately is not as developed as it could have.

By thinking about it, if settings.duration < settings.timeBuffer with timeBuffer big enough to cause and overflow, then any new auction would be created, and it would be basically ended after starting.

Assuming all those values are non-zero then this would allow an attacker to infinitely mint the token as they could -> createBid -> settleCurrentAndCreateNewAuction repeatedly until they have minted as many tokens as they want, while paying reservePrice.

The situation would be contingent on setup, this is additionally attenuated by the fact that Governance would need to vote these irrational values into the contract (defaults are safe), and they would have to do so without simming or running any additional checks.

I think because the lack of POC and detail, I'll downgrade to QA as recommended, however the finding is valid and I recommend the sponsor to check that no overflow can happen nor that a auction can be insta settled under specific circumstances.

I think this was a great opportunity for a more developed report and perhaps next time a coded POC will help push the finding to it's fullest

#5 - GalloDaSballo

2022-09-26T19:41:58Z

L

#6 - iainnash

2022-09-26T20:02:58Z

@GalloDaSballo Good point! Yes with further development and a coded POC this could be a medium risk level bug.

However, in any case still worth providing a fix around better validation here.

#7 - neumoxx

2022-09-27T10:23:41Z

I think the submission has validity and unfortunately is not as developed as it could have.

By thinking about it, if settings.duration < settings.timeBuffer with timeBuffer big enough to cause and overflow, then any new auction would be created, and it would be basically ended after starting.

Assuming all those values are non-zero then this would allow an attacker to infinitely mint the token as they could -> createBid -> settleCurrentAndCreateNewAuction repeatedly until they have minted as many tokens as they want, while paying reservePrice.

The situation would be contingent on setup, this is additionally attenuated by the fact that Governance would need to vote these irrational values into the contract (defaults are safe), and they would have to do so without simming or running any additional checks.

I think because the lack of POC and detail, I'll downgrade to QA as recommended, however the finding is valid and I recommend the sponsor to check that no overflow can happen nor that a auction can be insta settled under specific circumstances.

I think this was a great opportunity for a more developed report and perhaps next time a coded POC will help push the finding to it's fullest

It's sad because I wanted to express this exact behaviour but just by explining it. Next time I'll sure code a POC, still learning how all this works! Thanks anyway Alex.

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter