Core Contracts

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

Payment `token` gets locked permanently in RAACNFT.sol

Summary

The RAACNFT contract allows users to mint NFTs by paying with an ERC20 token. However, there is no function to withdraw the collected tokens from the contract. This results in permanently locked funds, rendering the contract incapable of utilizing the tokens for any purpose.

Vulnerability details

mint Function (Tokens are Collected but Not Withdrawable)

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 from user to contract - requires pre-approval from user
token.safeTransferFrom(msg.sender, address(this), _amount);
// mint tokenId to user
_safeMint(msg.sender, _tokenId);
// If user approved more than necessary, refund the difference
if (_amount > price) {
uint256 refundAmount = _amount - price;
token.safeTransfer(msg.sender, refundAmount);
}
emit NFTMinted(msg.sender, _tokenId, price);
}

In the above function, ERC20 tokens are transferred into the contract upon minting an NFT. However, there is no function to withdraw these tokens, effectively locking them inside the contract.

Impact

Without a withdrawal mechanism, all ERC20 tokens sent to the contract remain inaccessible. This can lead to financial losses, particularly if the contract accumulates a large balance of tokens that are meant to be used for operations, rewards, or transfers to other addresses.

Recommended Mitigation

Introduce a function to allow the contract owner to withdraw accumulated ERC20 tokens. Below is a suggested implementation:

function withdrawTokens(address recipient, uint256 amount) external onlyOwner {
if (recipient == address(0)) revert RAACNFT__InvalidAddress();
uint256 contractBalance = token.balanceOf(address(this));
if (amount > contractBalance) revert RAACNFT__InsufficientFunds();
token.safeTransfer(recipient, amount);
}

This function:

  • Ensures only the contract owner can withdraw funds.

  • Prevents sending funds to the zero address.

  • Checks if the contract has enough balance before withdrawing.

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!