NextGen - Delvir0'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: 168/243

Findings: 2

Award: $0.47

🌟 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)
satisfactory
edited-by-warden
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

Vulnerability details

Impact

Due to improper two aspects, there's a scenario where cancelBid and claimAuction are both callable while it always should be one of the two.

claimAuction() has the following require statement require(block.timestamp >= minter.getAuctionEndTime(_tokenid)) cancelBid() has the following require(block.timestamp <= minter.getAuctionEndTime(_tokenid))

This means that if block.timestamp == minter.getAuctionEndTime(_tokenid) both functions will be activated.

When claimAuction() is called auctionInfoData[_tokenid][i].status is never set to false like it would in cancelBid().

This results in the attack vector where cancelBid() is called after claimAuction() in the same block.timestamp. This could lead to 1. the winner getting the NFT and getting his bid back 2. a bidder receiving his bid twice. An attacker could check the current balance of the contract, deposit the same amount and withdraw that amount * 2 by above mentioned attack.

Proof of Concept

  1. minter.getAuctionEndTime(_tokenid) == 100, current block.timestamp == 100
  2. claimAuction() is called where the following passes block.timestamp >= minter.getAuctionEndTime(_tokenid) && auctionClaim[_tokenid] == false && minter.getAuctionStatus(_tokenid) == true
  3. Monitor mempool and submit a cancelBid() transaction and ensure it is mined in the same timestamp
  4. cancelBid() passes the following requirements block.timestamp <= minter.getAuctionEndTime(_tokenid) and auctionInfoData[_tokenid][index].bidder == msg.sender && auctionInfoData[_tokenid][index].status == true since the status is never set to false in claimAuction()

Tools Used

manual review

For this specific issue either fixing cause 1 or 2 will fix this problem. The timestamp checks needs to be checked throughout the whole codebase. I would recommend:

  1. Either end actions at the endtime or after the endtime throughout the whole codebase. Example: endOfAuction == endTime here, when block.timestamp hits endTime, the auction would be ended. OR: endOfAcution > endTime here, when block.timestamp hits endTime, the auction is still open and would end when that specific time has been PASSED.

  2. set blocktimestamp requirement of AuctionDemo.sol to: require(block.timestamp <= minter.getAuctionEndTime(_tokenid)

  3. in claimAcution(), set auctionInfoData[_tokenid][index].status to false BEFORE sending back the ETH or NFT

Assessed type

Invalid Validation

#0 - c4-pre-sort

2023-11-15T07:42:02Z

141345 marked the issue as duplicate of #1172

#1 - c4-judge

2023-12-06T21:28:10Z

alex-ppg marked the issue as duplicate of #1323

#2 - c4-judge

2023-12-08T18:05:02Z

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

Note: 1. this requires the attacker to lose his highest bid and lose out on the NFT 2. unlike the bot report this is not due to the loop DOS.

When the auction is over, claimAuction() loops over the bids and either 1. sends the NFT to the highest bidder and 2. returns the bids to the participants. However, if the highest bidder reverts the transfer on purpose, no one will be able to get their bids value back. This is due to the fact that when calling the function, it will loop over all bids and eventually end up in the transfer call.

Proof of Concept

  1. Attacker sends highest bid via a contract
  2. Attacker sets _checkOnERC721Received to revert (or does not implement it at all)
  3. When the admin calls claimAuction(), it will always revert

Tools Used

Manual review

There are two ways to handle this.

  1. Implement a failsafe for the functions when they revert. This could be done by continuing the function but saving the revert values for a later moment, for example with a try catch. If the try attempt fails, save the values (bid amount and bidder) into a mapping and provide an additional function to retrieve those funds at a later time.
  2. Redesign the claimAuction() without the modifier and where the transfer only occurs if msg.sender == auctionInfoData[_tokenid][i].bidder

Assessed type

DoS

#0 - c4-pre-sort

2023-11-19T15:03:49Z

141345 marked the issue as duplicate of #486

#1 - c4-judge

2023-12-01T22:42:58Z

alex-ppg marked the issue as not a duplicate

#2 - c4-judge

2023-12-01T22:43:21Z

alex-ppg marked the issue as duplicate of #1759

#3 - c4-judge

2023-12-08T22:14:34Z

alex-ppg marked the issue as partial-50

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