NextGen - CaeraDenoir'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: 64/243

Findings: 3

Award: $98.50

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

Vulnerability details

Summary

In the AuctionDemo.sol , the claimAuction function has a big flaw that allows any losing bidder to steal part of the owner ether, steal the nft or make the owner unable to receive the ether of the auction.

Vulnerability Details

In the claimAuction function, when the winner or an admin calls it, it is coded to send the funds back to every bidder that lost the auction, but it doesn't change the status of the bid to false.

Since it is possible to call claimAuction and cancelBid if the block.timestamp is equal to the auctionEndTime, an attacker is able to double the eth from a losing bid by calling cancelBid when the external call from claimAuction triggers on his contract.

It is also possible for the attacker to guarantee the win of the nft and pay nothing for it by making two bids at the auctionEndTime timestamp and then calling the claimAuction function, and when receiving the eth for the losing bid, call cancelBid on it to double it and making the attacker recover all his funds and win the auction.

Impact

I'd consider it's impact to be high since an attacker can gain eth or an nft that should not belong to him, and even end up locking funds forever.

Proof of Concept

Stealing the NFT

An auction opens and Alice bids 1 eth

Auction current winner: Alice Contract balance: 1 eth NFT owner: owner()

On the auctionEndTime timestamp, attacker makes two bids and then calls claimAuction.

First bid: 1 eth + 1 gwei

Auction current winner: Attacker Contract balance: 2 eth + 1 gwei NFT owner: owner()

Second bid: 1 eth + 2 gwei

Auction current winner: Attacker Contract balance: 3 eth + 3 gwei NFT owner: owner()

claimAuction is called, Alice is refunded.

Auction current winner: Attacker Contract balance: 2 eth + 3 gwei NFT owner: owner()

When claimAuction refunds the First bid from the attacker, it triggers the attacker receive function

Auction current winner: Attacker Contract balance: 1 eth + 2 gwei NFT owner: owner()

The attacker receive function calls cancelBid for the lost bid.

Auction current winner: Attacker Contract balance: 0 eth + 1 gwei NFT owner: owner()

claimAuction transfers ownership of the NFT.

Auction current winner: Attacker Contract balance: 0 eth + 1 gwei NFT owner: Attacker

Stealing the winners bid + making the auction have no winner

Starting balances:

Attacker balance: 2 ether Alice balance: 1 ether

An auction opens and Alice tries to bid 1 eth and sends the tx to a public mempool, an attacker spots this and places a transaction just before Alice with a bid of 1 ether - 1 gwei.

Auction current winner: Alice Contract balance: 2 eth - 1 gwei NFT owner: owner() Attacker balance: 1 ether + 1 gwei Alice balance: 0 ether

On the auctionEndTime timestamp, attacker makes one winner bid of 1 ether + 1 gwei and then calls claimAuction.

Auction current winner: Attacker Contract balance: 3 eth NFT owner: owner() Attacker balance: 0 ether Alice balance: 0 ether

When the contract refunds the attackers first bid, it triggers his receive function.

Auction current winner: Attacker Contract balance: 2 eth + 1 gwei NFT owner: owner() Attacker balance: 1 ether -1 gwei Alice balance: 0 ether

The attacker receive function calls cancelAllBids, getting a refund of the first 1 eth - 1 gwei bid again, and canceling the winning bid of 1 eth + 1 gwei.

Auction current winner: Attacker Contract balance: 1 gwei NFT owner: owner() Attacker balance: 3 ether -1 gwei Alice balance: 0 ether

claimAuction tries to refund Alice, but it is not able to send any ether as there is no more ether left. The transaction doesn't revert since the boolean return of the .call is not checked, just emited.

Auction current winner: Attacker Contract balance: 1 gwei NFT owner: owner() Attacker balance: 3 ether -1 gwei Alice balance: 0 ether

claimAuction checks if the winner bid is still active, it detects it isn't so it doesn't do anything and the function ends. This makes the auction end with no winner but the actual winner ends up with no NFT and no ETH.

Auction current winner: No one Contract balance: 1 gwei NFT owner: owner() Attacker balance: 3 ether -1 gwei Alice balance: 0 ether

This attack pattern permits the attacker to steal the ether of the winning bid by always placing a bid just 1 gwei lower right before the bid, and performing the attack at the desired timestamp.

There is no risk for the attacker since he can make the winner bid to only go through if the timestamp is equal to auctionEndTime, and if it doesn't work the attacker just gets refunded the losing bid.

The maximum amount that can be stolen by an attacker is equal to the attackers ether amount, but since the winner bid and the double refund happens on the same tx, the attacker can use a flash loan to guarantee winning the auction and being able to call claimAuction.

Tools Used

VSCode

Make sure one of the two functions claimAuction and cancelBid is not able to be called when the block.timestamp is equal to auctionEndTime.

Assessed type

Reentrancy

#0 - c4-pre-sort

2023-11-14T23:30:47Z

141345 marked the issue as duplicate of #962

#1 - c4-judge

2023-12-04T21:40:15Z

alex-ppg marked the issue as duplicate of #1323

#2 - c4-judge

2023-12-08T18:17:51Z

alex-ppg marked the issue as satisfactory

Lines of code

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

Vulnerability details

Summary

In the AuctionDemo.sol , the claimAuction function has a big flaw that allows any losing bidder to trigger any code without a gas limit. This could make it possible to an attacker to poison the entire auction, locking the funds of everyone there.

Vulnerability Details

In the claimAuction function, when the winner or an admin calls it, it is coded to send the funds back to every bidder that lost the auction via a call, but it does not limit the amount of gas forwarded, thus allowing a bad a actor to consume a huge amount of gas without reverting the transaction on his call, but using almost all the gas allowed, thus making the function revert when it tries to use more gas later.

Since claimAuction is the only way to refund the lost bids and also the only way for the winner to claim the nft, this would result in a loss of the entire funds of the auction.

Impact

I'd consider it's impact to be high since an attacker can maliciously prevent everyone from getting a refund and lock the entire ether existing in the contract forever once the auctionEndTime timestamp is surpassed.

Proof of Concept

A new auction is created, attacker poisons the contract with a 1 gwei bid.

Auction current winner: Attacker Contract balance: 1 gwei

Alice enter the bid with 1 ether:

Auction current winner: Alice Contract balance: 1 ether + 1 gwei

time passes and claimAuction becomes available to be called, while cancelBid and cancelAllBids become unable to be called.

Alice, who won the auction, calls claimAuction:

Auction winner: Alice Contract balance: 1 ether + 1 gwei

The claimAuction function sends the ether to the attacker first.

This triggers the attacker receive function, which is coded to use the maximum amount of gas that is allowed to use without reverting.

claimAuction then tries to continue with the transfer of the nft, but it fails as there is no more gas to be used.

This makes the claimAuction revert.

Auction current winner: Alice Contract balance: 1 ether + 1 gwei

The funds end up locked and the NFT ends up not being transfered.

Tools Used

VSCode

Limit the gas that every call is allowed to spend to prevent this kind of gas related lock of funds + DoS.

Assessed type

DoS

#0 - c4-pre-sort

2023-11-20T02:41:46Z

141345 marked the issue as duplicate of #486

#1 - c4-judge

2023-12-01T22:54:31Z

alex-ppg marked the issue as not a duplicate

#2 - c4-judge

2023-12-01T22:54:44Z

alex-ppg marked the issue as duplicate of #1782

#3 - c4-judge

2023-12-08T21:02:28Z

alex-ppg marked the issue as satisfactory

Findings Information

Labels

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

Awards

95.7343 USDC - $95.73

External Links

Lines of code

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

Vulnerability details

Impact

Medium impact, it affects the functionallity of the nfts with other contracts, as they wouldn't want to interact with tokens that could get burned.

Explanation

in the NextGenCore contract, the burnToMint function has the minting of the new nft, which makes an external call via _safeMint, before the burning of the nft-to-burn. This allows any bad actor to transfer the nft to a victim contract without the victim contract being able to stop the _burn from happening.

Make the mint of the nft in burnToMint happen after the burning of the nft that gives access to the mint.

Assessed type

Token-Transfer

#0 - c4-pre-sort

2023-11-20T02:41:20Z

141345 marked the issue as duplicate of #1198

#1 - c4-pre-sort

2023-11-20T09:25:09Z

141345 marked the issue as duplicate of #1597

#2 - c4-pre-sort

2023-11-26T14:00:23Z

141345 marked the issue as duplicate of #1742

#3 - c4-judge

2023-11-29T19:53:28Z

alex-ppg marked the issue as not a duplicate

#4 - c4-judge

2023-11-29T19:53:44Z

alex-ppg marked the issue as duplicate of #1597

#5 - c4-judge

2023-12-08T21:23:50Z

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