NextGen - Zac'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: 132/243

Findings: 2

Award: $5.49

🌟 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-50
duplicate-1323

External Links

Lines of code

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

Vulnerability details

Impact

In the AuctionDemo a malicious bidder can prevent others from bidding by placing a very large bid at the start, then cancelling the bid at the deadline. Others users are not able to bid because they must place a higher bid than the current highest bid, which is now much higher than it should be.

This is done in the following steps:

  1. User places bid at the very start(or near the start when the price is still much lower than expected)
  2. User waits until the deadline and cancels their bid
  3. In the same transaction as step 2 they can place a very low bid and win the auction.

It is worth noting that the attacker doesn't need to do step 3. This is important as it means that they can place a high bid that blocks the auction at any time even if they don't have the intention of winning the auction.

Proof of Concept

In this example we can assume the NFT is worth roughly 1 ETH

// attacker places a very high bid at the start of the auction vm.startPrank(attacker); auction.participateToAuction{value: 100 ether}(tokenIndex); // advance to the end of the auction vm.warp(block.timestamp + 1000); // attacker cancels the bid auction.cancelBid(tokenIndex, 0); // attacker places smallest possible bid auction.participateToAuction{value: 1}(tokenIndex);

Tools Used

Foundry

One of the ways to mitigate this would be to allow people to bid even if they are not the highest bid. An alternative would be to not allow the cancelling of bids.

Assessed type

DoS

#0 - c4-pre-sort

2023-11-15T14:48:06Z

141345 marked the issue as duplicate of #962

#1 - c4-judge

2023-12-02T15:13:19Z

alex-ppg marked the issue as not a duplicate

#2 - c4-judge

2023-12-02T15:17:06Z

alex-ppg marked the issue as duplicate of #1784

#3 - c4-judge

2023-12-07T11:49:33Z

alex-ppg marked the issue as duplicate of #1323

#4 - c4-judge

2023-12-08T17:27:14Z

alex-ppg marked the issue as partial-50

#5 - c4-judge

2023-12-08T17:28:22Z

alex-ppg marked the issue as satisfactory

#6 - c4-judge

2023-12-08T18:23:56Z

alex-ppg marked the issue as partial-50

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)
satisfactory
duplicate-1323

External Links

Lines of code

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

Vulnerability details

Impact

In the AuctionDemo contract the winner of the auction can claim their NFT and cancel their bid. This means that they can get the NFT for free.

This is done in the following steps, at the end of the auction(block.timestamp == minter.getAuctionEndTime(_tokenid)):

  1. Attacker places a bid
  2. Attacker calls claimAuction() to claim their NFT
  3. Attacker calls cancelBid() or cancelAllBids() to cancel their bid

This attack does require the amount of ETH in the contract to be greater than or equal to the winning bid(before the attacker places the bid). This should easiely be possible with other auctions happening.

It also has the effect of there not being enough ETH left for the other auctions meaning that some of the bidders will not recieve their refund and the owner may not recieve the winning bid.

Proof of Concept

In this POC we assume there are other auctions happening and that the sum of their bids is greater than 1 ETH This ensures there is enough balance for the attacker to cancel their bid

// advance to the end of the auction(block.timestamp == minter.getAuctionEndTime(_tokenid)) vm.warp(block.timestamp + 1000); // attacker places a bid vm.startPrank(attacker); auction.participateToAuction{value: 1 ether}(tokenIndex); // attacker claims their nft auction.claimAuction(tokenIndex); // attacker cancels the bid auction.cancelBid(tokenIndex, 0); vm.stopPrank();

Tools Used

Foundry

Update claimAuction() so that it can only be called after the end of the auction and not at the end.

This ensures that claimAuction() and cancelBid()/cancelAllBids() are not able to be called in the same transaction


-    require(block.timestamp >= minter.getAuctionEndTime(_tokenid) && auctionClaim[_tokenid] == false && minter.getAuctionStatus(_tokenid) == true);

+    require(block.timestamp > minter.getAuctionEndTime(_tokenid) && auctionClaim[_tokenid] == false && minter.getAuctionStatus(_tokenid) == true);

Assessed type

Timing

#0 - c4-pre-sort

2023-11-15T10:25:25Z

141345 marked the issue as duplicate of #962

#1 - c4-judge

2023-12-01T16:04:04Z

alex-ppg marked the issue as not a duplicate

#2 - c4-judge

2023-12-01T16:04:12Z

alex-ppg marked the issue as duplicate of #1788

#3 - c4-judge

2023-12-08T18:21:53Z

alex-ppg marked the issue as satisfactory

Awards

5.4864 USDC - $5.49

Labels

bug
2 (Med Risk)
downgraded by judge
partial-50
duplicate-175

External Links

Lines of code

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

Vulnerability details

Impact

The highest bidder can frontrun anyone that waits until the end of the auction to bid(block.timestamp == minter.getAuctionEndTime(_tokenid)).

The current highest bidder can frontrun any bids at the deadline with a call to claimAuction(). The bids will still succeed and the new highest bidder will not be able to refund and will not be able to claim their NFT.

Proof of Concept

In this example Alice is the highest bidder and Bob waits until the end to bid.

  1. Alices places a bid
// Alice places a bid of 1 ether vm.prank(alice); auction.participateToAuction{value: 1 ether}(tokenIndex);

Advance to the end of the auction

2a. Bob places a bid at the deadline

// Bob places a bid of 2 ether vm.prank(bob); auction.participateToAuction{value: 2 ether}(tokenIndex);

2b. Alice frontruns bob with a call to claimAuction()

vm.prank(alice); auction.claimAuction(tokenIndex);

Alice has recieved the NFT Bob has not recieved the NFT and has no way to refund/cancel his bid

Tools Used

Foundry

It should not be possible to bid at the same time as calling claimAuction()

To solve this we can change claimAuction so that it can only be called after the end of the auction and not at the end.


-    require(block.timestamp >= minter.getAuctionEndTime(_tokenid) && auctionClaim[_tokenid] == false && minter.getAuctionStatus(_tokenid) == true);

+    require(block.timestamp > minter.getAuctionEndTime(_tokenid) && auctionClaim[_tokenid] == false && minter.getAuctionStatus(_tokenid) == true);

Assessed type

Timing

#0 - c4-pre-sort

2023-11-15T09:01:04Z

141345 marked the issue as duplicate of #962

#1 - c4-judge

2023-12-02T15:33:31Z

alex-ppg marked the issue as not a duplicate

#2 - c4-judge

2023-12-02T15:35:42Z

alex-ppg marked the issue as duplicate of #1926

#3 - c4-judge

2023-12-08T18:52:18Z

alex-ppg marked the issue as partial-50

#4 - c4-judge

2023-12-09T00:21:41Z

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