Core Contracts

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

Locked ERC20 Tokens Due to Missing Withdrawal Mechanism in RAACNFT Contract

Summary

The RAACNFT contract lacks a mechanism to withdraw ERC20 tokens accumulated during the minting process. Tokens transferred to the contract as payment for minting NFTs remain permanently locked, leading to loss of funds for the contract owner and users.

Vulnerability Details

In the mint function, users transfer ERC20 tokens to the contract using token.safeTransferFrom(msg.sender, address(this), _amount). While excess tokens beyond the required price are refunded, the tokens corresponding to the actual price (i.e., price) remain in the contract. The contract does not implement any function to withdraw these tokens, resulting in permanent lock of funds.

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);
}

There is no method (e.g., withdrawTokens) to transfer the accumulated ERC20 tokens out of the contract. This means all tokens paid for minting NFTs (after refunds) are irrecoverably trapped in the contract.

Impact

All ERC20 tokens paid for minting NFTs are stuck in the contract.

Tools Used

Manual Review

Recommendations

Add a withdrawal function to allow the contract owner to retrieve accumulated ERC20 tokens:

function withdrawTokens(address recipient) external onlyOwner {
uint256 balance = token.balanceOf(address(this));
token.safeTransfer(recipient, balance);
}

This ensures the contract owner can recover funds, mitigating the risk of permanent token lockup.

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!