NextGen - DanielArmstrong'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: 78/243

Findings: 2

Award: $35.61

🌟 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/main/smart-contracts/AuctionDemo.sol#L124-L130

Vulnerability details

Impact

At auction, token is sold at a very low price close to zero. This is in fact the same as losing token.

Proof of Concept

Any bidder can withdraw the bid without any restriction through AuctionDemo.sol#cancelBid function as follows.

File: AuctionDemo.sol
124:    function cancelBid(uint256 _tokenid, uint256 index) public {
125:        require(block.timestamp <= minter.getAuctionEndTime(_tokenid), "Auction ended");
126:        require(auctionInfoData[_tokenid][index].bidder == msg.sender && auctionInfoData[_tokenid][index].status == true);
127:        auctionInfoData[_tokenid][index].status = false;
128:        (bool success, ) = payable(auctionInfoData[_tokenid][index].bidder).call{value: auctionInfoData[_tokenid][index].bid}("");
129:        emit CancelBid(msg.sender, _tokenid, index, success, auctionInfoData[_tokenid][index].bid);
130:    }

Therefore, the attacker makes a very low-price bid at the beginning of the auction and then registers a very high-price bid further, preventing other competitors from making a bid. If a high-price bid is withdrawn just before the auction is over, the attacker can buy the token at a low price.

Here is the attacking scenario.

  1. The manager starts auction for token and the estimated fair price of it is 100.
  2. An attacker, on the beginning of the auction, registers the bid of price 1 (< 100) and the bid of price 10,000 ( > 100) in turn.
  3. Other bidders give up participation because they have to enter the auction only at prices higher than 10,000, which are much higher than the fair price 100.
  4. Just before the end of the auction deadline, the attacker withdraws the second bid at a price of 10,000.
  5. After the auction deadline, the attacker buys a token at a price of 1.
  6. The system (manager + creator) will suffer a loss of `100-1 = 99'.

Tools Used

Manual Review

Modify AuctionDemo.sol#cancelBid function and impose penalty on the highest-priced bidder (msg.sender == returnHighestBidder (_tokenid)). Do not impose penalty when he is not the highest-priced bidder.

Assessed type

Error

#0 - c4-pre-sort

2023-11-15T09:41:48Z

141345 marked the issue as duplicate of #962

#1 - c4-judge

2023-12-02T15:13:13Z

alex-ppg marked the issue as not a duplicate

#2 - c4-judge

2023-12-02T15:16:48Z

alex-ppg marked the issue as duplicate of #1784

#3 - c4-judge

2023-12-07T11:49:39Z

alex-ppg marked the issue as duplicate of #1323

#4 - c4-judge

2023-12-08T17:26:48Z

alex-ppg marked the issue as partial-50

#5 - c4-judge

2023-12-08T17:28:19Z

alex-ppg marked the issue as satisfactory

#6 - c4-judge

2023-12-08T18:20:59Z

alex-ppg marked the issue as partial-50

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/main/smart-contracts/MinterContract.sol#L540

Vulnerability details

Impact

The buyers who buy tokens at the end of the sale may not buy or buy tokens at unexpected high prices.

Proof of Concept

If salesOption==2, the selling price of token decreases linearly or exponentially with time. In the decreaing price sale, the buyer will want to buy a token at the end of the sales period to buy token as cheaply as possible if tokens have no fear of being sold all before the deadline. However, by the following code in the MinterContract.sol#getPrice function, the price of token will jump to the initial selling price at the end of the sale.

File: MinterContract.sol
540:        } else if (collectionPhases[_collectionId].salesOption == 2 && block.timestamp > collectionPhases[_collectionId].allowlistStartTime && block.timestamp < collectionPhases[_collectionId].publicEndTime){

That is when block.timestamp == collectionPhases[_collectionId].publicEndTime, an initial price, not a decreased price, is applied.

Here is the reproducing scenario.

  1. Let suppose that total amount of tokens of a collection is 100, initial price is 1000, decrease rate is 30, timePeriod is one hour and sales period is one day.
  2. The expected price at the end of sales is 1000 - 30 * 23 = 310.
  3. A buyer attempts to buy token by calling the MinterContract.sol#mint function at just the end time of sales.
  4. Because MinterContract.sol#getPrice jumps to 1000 at the end of sales, the buyer does not buy tokens or buys tokens at the high price of 1000 eth.

Tools Used

Manual Review

In MinterContract.sol#L540 modify < with <= as follows.

File: MinterContract.sol
540: -       } else if (collectionPhases[_collectionId].salesOption == 2 && block.timestamp > collectionPhases[_collectionId].allowlistStartTime && block.timestamp < collectionPhases[_collectionId].publicEndTime){
540: +       } else if (collectionPhases[_collectionId].salesOption == 2 && block.timestamp > collectionPhases[_collectionId].allowlistStartTime && block.timestamp <= collectionPhases[_collectionId].publicEndTime){

Assessed type

Math

#0 - c4-pre-sort

2023-11-16T01:43:22Z

141345 marked the issue as duplicate of #1391

#1 - c4-judge

2023-12-08T21:42:47Z

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