NextGen - merlin'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: 72/243

Findings: 3

Award: $41.10

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

External Links

Lines of code

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

Vulnerability details

Bug Description

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.

Proof-of-Concept

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.

  1. A malicious user participates with a small bid (1 wei) in the auction for NFT id - 1.
  2. Other users also participate in the auction, and the highest bid reaches 3 ETH.
  3. In the last second of the auction, the malicious user rebids for the auction with NFT 1 with a bid of 4 ETH, executes 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.

Impact

The user can obtain the NFT and claim ETH for participating.

Tools Used

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
}

Assessed type

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

Awards

35.614 USDC - $35.61

Labels

bug
2 (Med Risk)
partial-50
duplicate-1275

External Links

Lines of code

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

Vulnerability details

Bug Description

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.

Impact

If the collection has a sales option of 2, the user must buy the NFT at the wrong price.

Tools Used

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
        )

Assessed type

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

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#L105

Vulnerability details

Bug Description

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.

Proof-of-Concept

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.

  1. Bob participates in the auction (participateToAuction) at the last moment (block.timestamp == auctionEndTime) with a bid of 10 ETH.
  2. Alice frontruns Bob's transaction, participates in the auction (participateToAuction) with a bid of 9 ETH, and simultaneously claims the NFT (claimAuction), sends ETH to the owner and refunds other users.
  3. Bob's transaction executes in the same block and doesn't fail. After this, Bob won't be able to retrieve his funds through the cancelBid function.

Impact

The ETH used to participate in the auction will be lost.

Tools Used

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
}

Assessed type

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)

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