Core Contracts

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

RAACNFT contract lacks a way to retrieve the collected crvUSD via mints

Summary

The RAACNFT.sol contract enables minting NFTs by taking in crvUSD via RAACNFT::mint, however, there is no way to retrieve these crvUSD for the owner / admin / stakeholder.

Vulnerability Details

The RAACNFT::mint function can be used by anyone to mint NFTs by paying certain amount of crvUSD as per the current house price.

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); <<@ - // crvUSD is transferred to the RAACNFT contract
// mint tokenId to user
_safeMint(msg.sender, _tokenId);

However, after these purchases are taken place, the owner / admin / stakeholder has no function for retrieving these crvUSD in the contract.
The RAACNFT.sol is a non upgradable contract, hence the funds will be lost.

Impact

  1. Loss of funds for the owner / admin / stakeholder as there's no way to retrieve the funds.

  2. Renders the contract useless.

Proof of concept

Add the below test case inside the RAACNFT.test.js file:

describe("Inability to retrieve tokens", () => {
beforeEach(async () => {
await crvUSD.connect(user1).approve(raacNFT.getAddress(), ethers.parseEther("1000"));
});
it("should mint NFT successfully but not able to retrive the crvUSD tokens", async () => {
// NFT is minted here successfully
await expect(raacNFT.connect(user1).mint(TOKEN_ID, HOUSE_PRICE))
.to.emit(raacNFT, "NFTMinted")
.withArgs(user1.address, TOKEN_ID, HOUSE_PRICE);
expect(await raacNFT.ownerOf(TOKEN_ID)).to.equal(user1.address);
// However, now there's no way to retrieve the crvUSD tokens sent to the contract
expect(await crvUSD.balanceOf(raacNFT.getAddress())).to.equal(HOUSE_PRICE);
});
});

Tools Used

Manual Review
/
Hardhat

Recommendations

It is recommended to add a withdraw token function for the owner in the RAACNFT.sol contract:

function withdraw() external onlyOwner {
uint256 balance = token.balanceOf(address(this));
token.safeTransfer(owner(), balance);
}
Updates

Lead Judging Commences

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