Core Contracts

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

Missing Token Withdrawal Mechanism

Summary

The RAACNFT contract lacks a mechanism to withdraw ERC20 tokens that accumulate in the contract during the minting process. This oversight creates a permanent lock of funds in the contract, preventing the protocol from accessing or managing these assets.

Vulnerability Details

During the minting process of RAACNFT tokens, users send ERC20 tokens (likely crvUSD) to the contract as payment for the NFTs. The contract correctly handles the initial payment and any immediate refunds for overpayment, but it does not implement any functionality to withdraw the collected payments. This creates a permanent accumulation of funds in the contract with no way to access them.

Vulnerable Code

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

The contract receives and holds the price amount of tokens but provides no mechanism to withdraw these accumulated funds.

Proof of Concept

To demonstrate this issue:

  1. User A mints an NFT by sending 1000 tokens

  2. The NFT costs 900 tokens

  3. User A receives a 100 token refund

  4. The remaining 900 tokens are permanently locked in the contract

  5. This process repeats with each mint, continuously accumulating locked tokens

Impact

This vulnerability has several significant implications:

  1. Protocol Revenue Lock: All revenue generated from NFT minting becomes permanently locked in the contract.

  2. Financial Inefficiency: The protocol cannot utilize these funds for operational expenses or protocol improvements.

  3. Emergency Situations: In case of critical issues, there's no way to rescue the locked funds.

  4. Business Operations: The inability to access collected fees could impact the protocol's ability to maintain and service the real-world properties these NFTs represent.

Tools Used

Manual Review

Recommendations

Implement a secure withdrawal mechanism that allows authorized parties to access the accumulated tokens.

Here's a suggested implementation:

// Add to contract state
address public treasury;
// Add to constructor
constructor(...) {
treasury = _treasury; // Set initial treasury address
}
// Add withdrawal function
function withdrawAccumulatedTokens() external onlyOwner {
uint256 balance = token.balanceOf(address(this));
require(balance > 0, "No tokens to withdraw");
token.safeTransfer(treasury, balance);
emit TokensWithdrawn(treasury, balance);
}
// Add function to update treasury if needed
function setTreasury(address _newTreasury) external onlyOwner {
require(_newTreasury != address(0), "Invalid treasury address");
treasury = _newTreasury;
emit TreasuryUpdated(_newTreasury);
}
// Add events
event TokensWithdrawn(address indexed to, uint256 amount);
event TreasuryUpdated(address indexed newTreasury);
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 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 4 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.