Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: high
Valid

Lack of Withdraw Mechanism for ERC20 Tokens in RAACNFT Contract

Overview

The RAACNft contract allows users to mint NFTs by paying in an ERC20 token. However, the contract lacks a mechanism for the owner to withdraw the accumulated ERC20 tokens. As a result, any ERC20 tokens sent to the contract during the minting process will be permanently locked, rendering them inaccessible to the contract owner.

Vulnerability Details

  1. Functionality of mint:

    • The mint function allows users to mint an NFT by transferring a specified amount of ERC20 tokens to the contract.

    • The function calculates the required price for the NFT using raac_hp.tokenToHousePrice(_tokenId).

    • If the user sends more tokens than required, the excess is refunded.

    • The ERC20 tokens transferred to the contract are stored in the contract's balance but cannot be withdrawn by the owner.

  2. Impact:

    • Locked Funds: All ERC20 tokens transferred to the contract during the minting process will be permanently stuck in the contract, as there is no mechanism to withdraw them.

    • Economic Loss: The contract owner will be unable to access or utilize the accumulated tokens, leading to significant financial loss.

  3. Example Scenario:

    • A user mints an NFT by transferring 100 ERC20 tokens to the contract.

    • The contract retains these tokens, but the owner has no way to withdraw them.

    • Over time, multiple users mint NFTs, and the contract accumulates a large balance of ERC20 tokens that are effectively lost.

Proof of Concept (PoC)

Below is an example of how the mint function works and the lack of a withdrawal mechanism:

function mint(uint256 _tokenId, uint256 _amount) public override {
uint256 price = raac_hp.tokenToHousePrice(_tokenId);
if(price == 0) { revert RAACNFT__HousePrice(); }
if(price > _amount) { revert RAACNFT__InsufficientFundsMint(); }
// Transfer ERC20 tokens from user to contract
token.safeTransferFrom(msg.sender, address(this), _amount);
// Mint NFT to user
_safeMint(msg.sender, _tokenId);
// Refund excess tokens if any
if (_amount > price) {
uint256 refundAmount = _amount - price;
token.safeTransfer(msg.sender, refundAmount);
}
emit NFTMinted(msg.sender, _tokenId, price);
}

In this function:

  • The RAACNft receives ERC20 tokens but does not provide any mechanism for the owner to withdraw them.

  • The tokens remain in the contract's balance indefinitely.

Recommendations

To address this issue, implement a withdrawal mechanism that allows the contract owner to withdraw the accumulated ERC20 tokens. Below are the recommended solutions:

  1. Add a Withdraw Function:

    • Implement a function that allows the contract owner to withdraw the ERC20 tokens to a specified address.

    • Example:

      function withdrawTokens(address _to, uint256 _amount) external onlyOwner {
      require(_to != address(0), "Invalid address");
      require(_amount > 0, "Amount must be greater than 0");
      require(token.balanceOf(address(this)) >= _amount, "Insufficient balance");
      token.safeTransfer(_to, _amount);
      emit TokensWithdrawn(_to, _amount);
      }
  2. Restrict Access to Owner:

    • Ensure that only the contract owner can call the withdrawal function by using the onlyOwner modifier.

    • Example:

      modifier onlyOwner() {
      require(msg.sender == owner, "Only owner can call this function");
      _;
      }
  3. Emit an Event for Transparency:

    • Emit an event when tokens are withdrawn to provide transparency and allow tracking of withdrawals.

    • Example:

      event TokensWithdrawn(address indexed to, uint256 amount);
  4. Consider Adding a Fee Mechanism:

    1. If the contract is designed to take a fee from the minting process, ensure that the fee is explicitly tracked and can be withdrawn separately.

By implementing a secure withdrawal function restricted to the contract owner, this issue can be resolved, ensuring that the contract owner can access and utilize the accumulated tokens. This modification is critical for the contract's functionality and economic viability.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

RAACNFT collects payment for NFT minting but lacks withdrawal functionality, permanently locking all tokens in the contract

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

RAACNFT collects payment for NFT minting but lacks withdrawal functionality, permanently locking all tokens in the contract

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!