NextGen - 00decree's results

Advanced smart contracts for launching generative art projects on Ethereum.

General Information

Platform: Code4rena

Start Date: 30/10/2023

Pot Size: $49,250 USDC

Total HM: 14

Participants: 243

Period: 14 days

Judge: 0xsomeone

Id: 302

League: ETH

NextGen

Findings Distribution

Researcher Performance

Rank: 91/243

Findings: 3

Award: $26.18

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: smiling_heretic

Also found by: 00decree, 00xSEV, 0x180db, 0x3b, 0x656c68616a, 0xAadi, 0xAleko, 0xAsen, 0xDetermination, 0xJuda, 0xMAKEOUTHILL, 0xMango, 0xMosh, 0xSwahili, 0x_6a70, 0xarno, 0xgrbr, 0xpiken, 0xsagetony, 3th, 8olidity, ABA, AerialRaider, Al-Qa-qa, Arabadzhiev, AvantGard, CaeraDenoir, ChrisTina, DanielArmstrong, DarkTower, DeFiHackLabs, Deft_TT, Delvir0, Draiakoo, Eigenvectors, Fulum, Greed, HChang26, Haipls, Hama, Inference, Jiamin, JohnnyTime, Jorgect, Juntao, Kaysoft, Kose, Kow, Krace, MaNcHaSsS, Madalad, MrPotatoMagic, Neon2835, NoamYakov, Norah, Oxsadeeq, PENGUN, REKCAH, Ruhum, Shubham, Silvermist, Soul22, SovaSlava, SpicyMeatball, Talfao, TermoHash, The_Kakers, Toshii, TuringConsulting, Udsen, VAD37, Vagner, Zac, Zach_166, ZdravkoHr, _eperezok, ak1, aldarion, alexfilippov314, alexxander, amaechieth, aslanbek, ast3ros, audityourcontracts, ayden, bdmcbri, bird-flu, blutorque, bronze_pickaxe, btk, c0pp3rscr3w3r, c3phas, cartlex_, cccz, ciphermarco, circlelooper, crunch, cryptothemex, cu5t0mpeo, darksnow, degensec, dethera, devival, dimulski, droptpackets, epistkr, evmboi32, fibonacci, gumgumzum, immeas, innertia, inzinko, jasonxiale, joesan, ke1caM, kimchi, lanrebayode77, lsaudit, mahyar, max10afternoon, merlin, mrudenko, nuthan2x, oakcobalt, openwide, orion, phoenixV110, pontifex, r0ck3tz, rotcivegaf, rvierdiiev, seeques, shenwilly, sl1, slvDev, t0x1c, tallo, tnquanghuy0512, tpiliposian, trachev, twcctop, vangrim, volodya, xAriextz, xeros, xuwinnie, y4y, yobiz, zhaojie

Awards

0 USDC - $0.00

Labels

bug
3 (High Risk)
partial-25
upgraded by judge
duplicate-1323

External Links

Lines of code

https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L57-L61

Vulnerability details

Impact

Since the contract allow multiple active bid, an Attacker can place a minimum bid and another arbitrary high bid to prevent other user from participating in the auction. Then right before the auction ends, the Attacker can cancel the highest bid and win the auction with the minimum bid, essentially preventing any competition.

Proof of Concept

  • Run forge init in project root

  • setup deployer script and test file: Gist link: link

Filepath: - script/DeployProtocol2.s.sol - test/AuctionDemoTest2.t.sol
  • Run the test:
forge test --mt testAttackerMultipleActiveBid -vv
  • Which will yields the following output: Assertion will pass, which proof that the ATTACKER can win auction with minimum fund (1 wei in the PoC).
Running 1 test for test/AuctionDemoTest2.t.sol:AuctionDemoTest2 [PASS] testAttackerMultipleActiveBid() (gas: 1279087) Logs: 9999999999999999999999 Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 9.57ms Ran 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)

Tools Used

Manual code review, Forge

  1. Only allow a single active bid from each user for every single auction. If the participate re-bid with higher price, old bid should be cancelled and updated to latest bid.

Assessed type

Other

#0 - c4-pre-sort

2023-11-20T15:31:11Z

141345 marked the issue as duplicate of #962

#1 - c4-judge

2023-12-02T15:12:36Z

alex-ppg marked the issue as not a duplicate

#2 - c4-judge

2023-12-02T15:15:32Z

alex-ppg marked the issue as duplicate of #1784

#3 - c4-judge

2023-12-07T11:50:19Z

alex-ppg marked the issue as duplicate of #1323

#4 - c4-judge

2023-12-08T17:22:23Z

alex-ppg marked the issue as partial-25

#5 - c4-judge

2023-12-08T17:27:57Z

alex-ppg marked the issue as satisfactory

#6 - c4-judge

2023-12-08T18:06:05Z

alex-ppg marked the issue as partial-25

#7 - c4-judge

2023-12-09T00:20:29Z

alex-ppg changed the severity to 3 (High Risk)

Awards

25.2356 USDC - $25.24

Labels

bug
2 (Med Risk)
satisfactory
duplicate-971

External Links

Lines of code

https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L113

Vulnerability details

Impact

Invariant the owner of the token will receive the funds broken, implementation is sending the fund to owner() which will be the address that deployed AuctionDemo.sol. The fund will not be at direct risk, since the address belongs to the protocol will be receiving the fund.

Proof of Concept

  • Run forge init in project root

  • setup deployer script and test file: Gist link: link

Filepath: - script/DeployProtocol2.s.sol - test/AuctionDemoTest2.t.sol
  • Run the test:
forge test --mt testAuctionTokenOwner -vv
  • Which will yields the following output: Assertion will pass, which proof the fund is sent to owner() instead of token owner
Running 1 test for test/AuctionDemoTest2.t.sol:AuctionDemoTest2 [PASS] testAuctionTokenOwner() (gas: 1205318) Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 7.41ms Ran 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)

Tools Used

Manual Review, Forge

Replace owner() with ownerOfToken

File: AuctionDemo.sol
- 168:                 (bool success, ) = payable(owner()).call{value: highestBid}("");
- 169:                 emit ClaimAuction(owner(), _tokenid, success, highestBid);

+ 168:                 (bool success, ) = payable(ownerOfToken).call{value: highestBid}("");
+ 169:                 emit ClaimAuction(ownerOfToken, _tokenid, success, highestBid);

Assessed type

Context

#0 - c4-pre-sort

2023-11-20T15:32:00Z

141345 marked the issue as duplicate of #245

#1 - c4-judge

2023-12-08T22:27:28Z

alex-ppg marked the issue as satisfactory

Lines of code

https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L112

Vulnerability details

Impact

Attacker can participate auction through a smart contract that did not implement ERC721Receiver, then claimAuction() will revert with error ERC721: transfer to non ERC721Receiver implementer.

ALL the auction bid fund will be permanently loss.

Proof of Concept

  • Run forge init in project root

  • setup deployer script and test file: Gist link to all files: link

Filepath: - test/mock/Attacker.sol - script/DeployProtocol.s.sol - test/AuctionDemoTest.t.sol
  • Run the test:
forge test --mt testMintAndAuction -vv
  • Which will yields the following output: Assertion failure indicating fund failed to be refunded to participating user.
[â ¢] Compiling... No files changed, compilation skipped Running 1 test for test/AuctionDemoTest.t.sol:AuctionDemoTest [FAIL. Reason: Assertion failed.] testMintAndAuction() (gas: 1626277) Logs: Error: a == b not satisfied [uint] Left: 9000000000000000000 Right: 10000000000000000000 Error: a == b not satisfied [uint] Left: 8000000000000000000 Right: 10000000000000000000 Test result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 5.30ms Ran 1 test suites: 0 tests passed, 1 failed, 0 skipped (1 total tests) Failing tests: Encountered 1 failing test in test/AuctionDemoTest.t.sol:AuctionDemoTest [FAIL. Reason: Assertion failed.] testMintAndAuction() (gas: 1626277)

Tools Used

Manual Code Review, Forge

  1. The protocol can implement a check if participating address is contract and has ERC721Receiver implemented.
     function participateToAuction(uint256 _tokenid) public payable {
        require(msg.value > returnHighestBid(_tokenid) && block.timestamp <= minter.getAuctionEndTime(_tokenid) && minter.getAuctionStatus(_tokenid) == true);

+        if (isContract(msg.sender)) {
+            // The address is a contract, now check if it supports ERC721Receiver
+           ERC165 erc165 = ERC165(msg.sender);
+            require(erc165.supportsInterface(0x150b7a02), "Contract did not support ERC721Receiver"); // ERC721Receiver's interface ID
+        }

        auctionInfoStru memory newBid = auctionInfoStru(msg.sender, msg.value, true);
        auctionInfoData[_tokenid].push(newBid);
    }

+    function isContract(address _address) public view returns (bool) {
+        uint256 size;
+        assembly {
+            size := extcodesize(_address)
+        }
+        return size > 0;
+    }
  1. The participating contract can still be selfdestruct or bypass extcodesize() check and lead to same issue, so it is recommended to implement the withdrawal pattern for participant refund and winner claiming. This lays the burden of proof on the refund/token receiver.
function auctionRefundWithdraw(uint256 _tokenid) public { // if auctionEnded && !claimed && msg.sender == participating user // participating user withdrawing their OWN refund only } function auctionWinnerClaim(uint256 _tokenid) public { // if auctionEnded && !claimed && msg.sender == winner/highest bidder // auction Winner claiming their token }
  1. A separate withdrawal function for the protocol owner/admin to withdraw the bid fees after an auction has ended, regardless if the winner has claim their token or not.
function auctionProtocolFeeWithdraw(uint256 _tokenid) public{ // if auctionEnded && !claimed && msg.sender == admin // protocol admin withdraw the winning auction bid }

Assessed type

ETH-Transfer

#0 - c4-pre-sort

2023-11-20T15:31:42Z

141345 marked the issue as duplicate of #486

#1 - c4-judge

2023-12-01T22:36:13Z

alex-ppg marked the issue as not a duplicate

#2 - c4-judge

2023-12-01T22:36:31Z

alex-ppg marked the issue as duplicate of #1759

#3 - c4-judge

2023-12-08T22:14:07Z

alex-ppg marked the issue as satisfactory

#4 - c4-judge

2023-12-09T00:23:12Z

alex-ppg changed the severity to 2 (Med Risk)

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