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
Rank: 72/243
Findings: 3
Award: $41.10
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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
0 USDC - $0.00
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L58 https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L105 https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L125
The auctionDemo
smart contract has three functions responsible for the NFT auction. All these functions, participateToAuction, claimAuction, and cancelBid
, lack reentrancy checks and can be called when block.timestamp == minter.getAuctionEndTime()
, meaning at the same time.
The participateToAuction, cancelBid, and claimAuction
functions can be called in the last second of the auction:
block.timestamp <= minter.getAuctionEndTime(_tokenid) block.timestamp >= minter.getAuctionEndTime(_tokenid)
Additionally, there are no reentrancy checks in the aforementioned functions, and low-level calls are not checked for success.
Let's consider the following scenario:
Grouping all the aforementioned issues, we have the following scenario:
Preconditions
: There are two different auctions for NFT with id 1, the highest bid being 3 ETH, and for NFT with id 2, the highest bid being 5 ETH.
claimAuction
and cancelBid
in the same transaction. Additionally, other users may also cancelBid
in the same block, even after a refund in the claimAuction
function.The user can obtain the NFT and claim ETH for participating.
Manual
Consider changing claimAuction
as follows:
function claimAuction( uint256 _tokenid ) public WinnerOrAdminRequired(_tokenid, this.claimAuction.selector) { require( - block.timestamp >= minter.getAuctionEndTime(_tokenid) && + block.timestamp > minter.getAuctionEndTime(_tokenid) && auctionClaim[_tokenid] == false && minter.getAuctionStatus(_tokenid) == true ); ///code }
Invalid Validation
#0 - c4-pre-sort
2023-11-14T09:58:42Z
141345 marked the issue as duplicate of #1904
#1 - c4-pre-sort
2023-11-14T23:31:55Z
141345 marked the issue as duplicate of #962
#2 - c4-judge
2023-12-04T21:42:38Z
alex-ppg marked the issue as duplicate of #1323
#3 - c4-judge
2023-12-08T17:39:45Z
alex-ppg marked the issue as satisfactory
35.614 USDC - $35.61
When a user calls one of the following functions: mint, burnToMint, or burnOrSwapExternalToMint
, the current price for the NFT is calculated, depending on the collection type. The issue arises in sale model 2, specifically when a user mints an NFT in the last second, resulting in the acquisition of the NFT at an incorrect amount.
All the above functions have a time check implemented as follows:
block.timestamp >= collectionPhases[col].publicStartTime && block.timestamp <= collectionPhases[col].publicEndTime
The getPrice function for sale model 2 checks as follows:
block.timestamp > collectionPhases[_collectionId].allowlistStartTime && block.timestamp < collectionPhases[_collectionId].publicEndTime
As a result, when purchasing an NFT in the last second before the publicEndTime
using sale model 2, the user is charged an incorrect price, and the transaction fails.
If the collection has a sales option of 2, the user must buy the NFT at the wrong price.
Manual
Consider changing getPrice
as follows:
else if ( collectionPhases[_collectionId].salesOption == 2 && - block.timestamp > collectionPhases[_collectionId].allowlistStartTime && - block.timestamp < collectionPhases[_collectionId].publicEndTime + block.timestamp >= collectionPhases[_collectionId].allowlistStartTime && + block.timestamp <= collectionPhases[_collectionId].publicEndTime )
Invalid Validation
#0 - c4-pre-sort
2023-11-16T01:42:12Z
141345 marked the issue as duplicate of #1391
#1 - c4-judge
2023-12-08T21:39:57Z
alex-ppg marked the issue as partial-50
🌟 Selected for report: HChang26
Also found by: 0x3b, 0xMAKEOUTHILL, 0xSwahili, 0xarno, ABA, DeFiHackLabs, Eigenvectors, Haipls, Kow, MrPotatoMagic, Neon2835, Nyx, Zac, alexfilippov314, ayden, c3phas, immeas, innertia, lsaudit, merlin, mojito_auditor, oakcobalt, ohm, oualidpro, peanuts, phoenixV110, sces60107, t0x1c, tnquanghuy0512, ubl4nk, volodya, xAriextz
5.4864 USDC - $5.49
To participate in the auction, one needs to invoke the participateToAuction
function and have the highest bid. To claim the NFT, the claimAuction
function should be called. These two functions have incorrect auction end time checks, introducing a vulnerability to potential fund losses.
The issue lies in the auction end time verification:
/// participateToAuction require( block.timestamp <= minter.getAuctionEndTime(_tokenid)); /// claimAuction require(block.timestamp >= minter.getAuctionEndTime(_tokenid));
So, it is possible to participate and claim the NFT simultaneously.
Let's consider the following scenario:
Preconditions
: The last highest bid is 8 ETH.
participateToAuction
) at the last moment (block.timestamp == auctionEndTime
) with a bid of 10 ETH.participateToAuction
) with a bid of 9 ETH, and simultaneously claims the NFT (claimAuction
), sends ETH to the owner and refunds other users.cancelBid
function.The ETH used to participate in the auction will be lost.
Manual
Consider changing claimAuction
as follows:
function claimAuction( uint256 _tokenid ) public WinnerOrAdminRequired(_tokenid, this.claimAuction.selector) { require( - block.timestamp >= minter.getAuctionEndTime(_tokenid) && + block.timestamp > minter.getAuctionEndTime(_tokenid) && auctionClaim[_tokenid] == false && minter.getAuctionStatus(_tokenid) == true ); ///code }
Invalid Validation
#0 - c4-pre-sort
2023-11-14T09:54:08Z
141345 marked the issue as duplicate of #1935
#1 - c4-pre-sort
2023-11-14T14:21:43Z
141345 marked the issue as duplicate of #962
#2 - c4-judge
2023-12-02T15:32:48Z
alex-ppg marked the issue as not a duplicate
#3 - c4-judge
2023-12-02T15:34:26Z
alex-ppg marked the issue as duplicate of #1926
#4 - c4-judge
2023-12-08T18:47:26Z
alex-ppg marked the issue as satisfactory
#5 - c4-judge
2023-12-08T21:49:15Z
alex-ppg marked the issue as partial-50
#6 - c4-judge
2023-12-09T00:21:43Z
alex-ppg changed the severity to 2 (Med Risk)