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: 45/243
Findings: 3
Award: $191.94
🌟 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#L124 https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L104
Should not enable claiming at auction end time, or the winner can claim token without pay the ETH.
There are 2 phases in an entire auction, the bidding phase
and claiming phase
.
In bidding phase, bidders place bids if they want to participate, or cancel bids if they want to leave; In claiming phase, winner claiming the token and the ETH will be returned to other bidders.
Unfortunately, if we look carefully at cancelBid and claimAuction, we can find that there is time overlap between the 2 phases:
// bidding phase require(block.timestamp <= minter.getAuctionEndTime(_tokenid), "Auction ended");
// claiming phase require(block.timestamp >= minter.getAuctionEndTime(_tokenid) && auctionClaim[_tokenid] == false && minter.getAuctionStatus(_tokenid) == true);
Both claiming and canceling can be done at auctionEndTime
, this means the winner may first claim the token and then cancel the winning bid to get ETH back at the time point.
Manual Review
To mitigate this issue, please remove the time overlap and only allow claiming after auctionEndTime
.
ERC721
#0 - c4-pre-sort
2023-11-15T07:27:46Z
141345 marked the issue as duplicate of #962
#1 - c4-judge
2023-12-01T15:15:49Z
alex-ppg marked the issue as not a duplicate
#2 - c4-judge
2023-12-01T15:15:57Z
alex-ppg marked the issue as duplicate of #1788
#3 - c4-judge
2023-12-08T18:02:33Z
alex-ppg marked the issue as partial-50
#4 - c4-judge
2023-12-08T18:02:39Z
alex-ppg marked the issue as partial-25
🌟 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
Should not allow bidders to cancel bids before auction is ended, or the bidders will be grief attacked.
By calling cancelBid or cancelAllBids, bidder in an auction can cancel the bids before the auction is ended. This encourages a bidder to bid by calling participateToAuction. However, this can also be leveraged by an attacker who can bid with an unreasonably high price, honest bidders who tries to bid with a reasonable price will be grief attacked because only the highest bid is accepted.
function participateToAuction(uint256 _tokenid) public payable { require(msg.value > returnHighestBid(_tokenid) && block.timestamp <= minter.getAuctionEndTime(_tokenid) && minter.getAuctionStatus(_tokenid) == true); auctionInfoStru memory newBid = auctionInfoStru(msg.sender, msg.value, true); auctionInfoData[_tokenid].push(newBid); }
The highest bid is the attacker's bid and others cannot participate, right before auction is ended, the attacker cancel the bid and leave the auction with no bids.
Manual Review
To mitigate this issue, please do not allow bidders to cancel bids before auction is ended.
Access Control
#0 - c4-pre-sort
2023-11-15T07:26:52Z
141345 marked the issue as duplicate of #962
#1 - c4-judge
2023-12-02T15:12:28Z
alex-ppg marked the issue as not a duplicate
#2 - c4-judge
2023-12-02T15:15:05Z
alex-ppg marked the issue as duplicate of #1784
#3 - c4-judge
2023-12-07T11:50:26Z
alex-ppg marked the issue as duplicate of #1323
#4 - c4-judge
2023-12-08T17:17:48Z
alex-ppg marked the issue as partial-25
#5 - c4-judge
2023-12-08T17:27:56Z
alex-ppg marked the issue as satisfactory
#6 - c4-judge
2023-12-08T18:02:23Z
alex-ppg marked the issue as partial-25
🌟 Selected for report: ast3ros
Also found by: 00xSEV, Al-Qa-qa, CaeraDenoir, Jiamin, Juntao, Ruhum, bart1e, circlelooper, crunch, gumgumzum, rishabh, smiling_heretic, ustas
191.4685 USDC - $191.47
Should not minting new collection token before burning the old collection token, or the old collection may be leveraged by the owner before burning.
mintAndAuction allows collection token owner to mint a new collection token by burning the old one. The minting and burning is done through burnToMint in NextGenCore
contract.
function burnToMint(uint256 mintIndex, uint256 _burnCollectionID, uint256 _tokenId, uint256 _mintCollectionID, uint256 _saltfun_o, address burner) external { require(msg.sender == minterContract, "Caller is not the Minter Contract"); require(_isApprovedOrOwner(burner, _tokenId), "ERC721: caller is not token owner or approved"); collectionAdditionalData[_mintCollectionID].collectionCirculationSupply = collectionAdditionalData[_mintCollectionID].collectionCirculationSupply + 1; if (collectionAdditionalData[_mintCollectionID].collectionTotalSupply >= collectionAdditionalData[_mintCollectionID].collectionCirculationSupply) { _mintProcessing(mintIndex, ownerOf(_tokenId), tokenData[_tokenId], _mintCollectionID, _saltfun_o); // burn token _burn(_tokenId); burnAmount[_burnCollectionID] = burnAmount[_burnCollectionID] + 1; } }
The new collection token will be minted to the receiver before the old collection token is burned.
Given that the old collection token can be used as a collateral in a lending platform as it has value of mintpass. Consider a case where:
mintAndAuction
from a contract to mint a new collection token;onERC721Received
is called on the contract, contract uses the old collection token as collateral and borrows money from the lending platform;Manual Review
To mitigate this issue, please burn the old collection token before minting the new one.
ERC721
#0 - c4-pre-sort
2023-11-19T05:11:44Z
141345 marked the issue as primary issue
#1 - c4-pre-sort
2023-11-20T09:25:12Z
141345 marked the issue as duplicate of #1597
#2 - c4-pre-sort
2023-11-26T14:00:14Z
141345 marked the issue as duplicate of #1742
#3 - c4-judge
2023-11-29T19:54:36Z
alex-ppg marked the issue as not a duplicate
#4 - c4-judge
2023-11-29T19:54:54Z
alex-ppg marked the issue as duplicate of #1597
#5 - c4-judge
2023-12-05T12:24:54Z
alex-ppg changed the severity to 2 (Med Risk)
#6 - c4-judge
2023-12-08T21:24:24Z
alex-ppg marked the issue as satisfactory
🌟 Selected for report: The_Kakers
Also found by: 00decree, 00xSEV, 0x180db, 0x3b, 0xJuda, 0x_6a70, 0xarno, 0xpiken, Arabadzhiev, Bauchibred, BugsFinder0x, BugzyVonBuggernaut, ChrisTina, DeFiHackLabs, Delvir0, HChang26, Haipls, Jiamin, Juntao, KupiaSec, Madalad, Neon2835, Nyx, Ocean_Sky, SpicyMeatball, Talfao, Taylor_Webb, Timenov, Tricko, ZdravkoHr, _eperezok, alexxander, amaechieth, bdmcbri, bronze_pickaxe, circlelooper, crunch, cu5t0mpeo, dimulski, fibonacci, funkornaut, immeas, ke1caM, lsaudit, nuthan2x, r0ck3tz, rotcivegaf, spark, tnquanghuy0512, twcctop, xeros
0.4703 USDC - $0.47
Should not pay back ETH to bidders while transferring token to winner, or bidders may not be successfully paid.
By calling claimAuction, the winner of an auction will get the token.
if (auctionInfoData[_tokenid][i].bidder == highestBidder && auctionInfoData[_tokenid][i].bid == highestBid && auctionInfoData[_tokenid][i].status == true) { IERC721(gencore).safeTransferFrom(ownerOfToken, highestBidder, _tokenid); (bool success, ) = payable(owner()).call{value: highestBid}(""); emit ClaimAuction(owner(), _tokenid, success, highestBid); }
And other bidders are getting ETH back.
} else if (auctionInfoData[_tokenid][i].status == true) { (bool success, ) = payable(auctionInfoData[_tokenid][i].bidder).call{value: auctionInfoData[_tokenid][i].bid}(""); emit Refund(auctionInfoData[_tokenid][i].bidder, _tokenid, success, highestBid); }
The problem is that the transaction may fail when transferring the token to the winner, and this is possible if the receiver is a contract which does not implement the ERC721Receiver interface, especially for the onERC721Received
function.
Manual Review
To mitigate this issue, please implement another method for the bidders to get ETH back.
ERC721
#0 - c4-pre-sort
2023-11-15T07:27:23Z
141345 marked the issue as duplicate of #1632
#1 - c4-pre-sort
2023-11-15T08:06:03Z
141345 marked the issue as duplicate of #843
#2 - c4-pre-sort
2023-11-16T13:36:32Z
141345 marked the issue as duplicate of #486
#3 - c4-judge
2023-12-01T22:26:39Z
alex-ppg marked the issue as not a duplicate
#4 - c4-judge
2023-12-01T22:26:50Z
alex-ppg marked the issue as duplicate of #1759
#5 - c4-judge
2023-12-08T22:11:26Z
alex-ppg marked the issue as partial-50
#6 - c4-judge
2023-12-09T00:23:12Z
alex-ppg changed the severity to 2 (Med Risk)