code-423n4 / 2024-07-traitforge-findings

0 stars 0 forks source link

Excess value in `forgeWithListed()` function is not refunded to the user #349

Closed howlbot-integration[bot] closed 1 month ago

howlbot-integration[bot] commented 2 months ago

Lines of code

https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/EntityForging/EntityForging.sol#L125-L126

Vulnerability details

Impact

Excess ETH in forgeWithListed() is not refunded to the user.

Proof of Concept

In EntityForging.sol we have forgeWithListed():

  function forgeWithListed(
    uint256 forgerTokenId,
    uint256 mergerTokenId
  ) external payable whenNotPaused nonReentrant returns (uint256) {
    Listing memory _forgerListingInfo = listings[listedTokenIds[forgerTokenId]];
    require(
      _forgerListingInfo.isListed,
      "Forger's entity not listed for forging"
    );
    require(
      nftContract.ownerOf(mergerTokenId) == msg.sender,
      'Caller must own the merger token'
    );
    require(
      nftContract.ownerOf(forgerTokenId) != msg.sender,
      'Caller should be different from forger token owner'
    );
    require(
      nftContract.getTokenGeneration(mergerTokenId) ==
        nftContract.getTokenGeneration(forgerTokenId),
      'Invalid token generation'
    );

    uint256 forgingFee = _forgerListingInfo.fee;
    require(msg.value >= forgingFee, 'Insufficient fee for forging');

    _resetForgingCountIfNeeded(forgerTokenId); // Reset for forger if needed
    _resetForgingCountIfNeeded(mergerTokenId); // Reset for merger if needed

    // Check forger's breed count increment but do not check forge potential here
    // as it is already checked in listForForging for the forger
    forgingCounts[forgerTokenId]++;

    // Check and update for merger token's forge potential
    uint256 mergerEntropy = nftContract.getTokenEntropy(mergerTokenId);
    require(mergerEntropy % 3 != 0, 'Not merger');
    uint8 mergerForgePotential = uint8((mergerEntropy / 10) % 10); // Extract the 5th digit from the entropy
    forgingCounts[mergerTokenId]++;
    require(
      mergerForgePotential > 0 &&
        forgingCounts[mergerTokenId] <= mergerForgePotential,
      'forgePotential insufficient'
    );

    uint256 devFee = forgingFee / taxCut;
    uint256 forgerShare = forgingFee - devFee;
    address payable forgerOwner = payable(nftContract.ownerOf(forgerTokenId));

    uint256 newTokenId = nftContract.forge(
      msg.sender,
      forgerTokenId,
      mergerTokenId,
      ''
    );
    (bool success, ) = nukeFundAddress.call{ value: devFee }('');
    require(success, 'Failed to send to NukeFund');
    (bool success_forge, ) = forgerOwner.call{ value: forgerShare }('');
    require(success_forge, 'Failed to send to Forge Owner');

    // Cancel listed forger nft
    _cancelListingForForging(forgerTokenId);

    uint256 newEntropy = nftContract.getTokenEntropy(newTokenId);

    emit EntityForged(
      newTokenId,
      forgerTokenId,
      mergerTokenId,
      newEntropy,
      forgingFee
    );

    return newTokenId;
  }

This function allows a user to merge two NFTs (Non-Fungible Tokens): one that is listed for forging and another that the user owns.

The function retrieves the forging fee from the listing and checks if the caller sent enough ETH to cover the fee. If not, it reverts.

uint256 forgingFee = _forgerListingInfo.fee; require(msg.value >= forgingFee, 'Insufficient fee for forging');

But the function does not refund excess ETH to the user. This means that this ETH will be lost.

Tools Used

Visual Studio Code

Recommended Mitigation Steps

To fix this issue, the function should ensure that the amount being transferred does not exceed the value of msg.value. The other option is to return the excess ETH.

Assessed type

ETH-Transfer

c4-judge commented 2 months ago

koolexcrypto changed the severity to QA (Quality Assurance)

c4-judge commented 1 month ago

koolexcrypto marked the issue as grade-c

c4-judge commented 1 month ago

This previously downgraded issue has been upgraded by koolexcrypto

c4-judge commented 1 month ago

koolexcrypto marked the issue as duplicate of #687

c4-judge commented 1 month ago

koolexcrypto marked the issue as duplicate of #218

c4-judge commented 1 month ago

koolexcrypto changed the severity to QA (Quality Assurance)