Core Contracts

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

NFT Minting vulnerable to stale oracle prices

Summary

The mint function in RAACNFT contract uses house prices from RAACHousePrices contract without validating whether the price data is stale, potentially allowing users to mint NFTs at outdated prices that don't reflect current market values.

Vulnerability Details

In RAACHousePrices.sol, prices are updated by the oracle and a timestamp is recorded:

function setHousePrice(
uint256 _tokenId,
uint256 _amount
) external onlyOracle {
tokenToHousePrice[_tokenId] = _amount;
@> lastUpdateTimestamp = block.timestamp;
emit PriceUpdated(_tokenId, _amount);
}

However, in RAACNFT.sol's mint function, prices are used without any staleness check:

function mint(uint256 _tokenId, uint256 _amount) public override {
// @audit-issue it doesn't check for stale price.
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 key issues are:

  • While lastUpdateTimestamp exists, it's never checked during minting

  • No maximum staleness threshold is enforced

  • Price validation only checks for non-zero values and sufficient payment

Impact

Users could mint NFTs at outdated prices during oracle downtime or delays, either paying too much or too little depending on market movements. This is particularly severe for real estate assets where price differences can represent significant monetary values.

Tools Used

Manual Review

Recommendations

  1. Add a staleness threshold check in the mint function:

+ uint256 MAX_PRICE_DELAY = 1 days; // Or appropriate threshold. Should be dynamic.
+ require(block.timestamp - raac_hp.lastUpdateTimestamp() <= MAX_PRICE_DELAY, "Stale price")

Additionally, consider adding a price tolerance mechanism that requires prices to be recently confirmed if they have moved beyond a certain threshold.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

LendingPool::getNFTPrice or getPrimeRate doesn't validate timestamp staleness despite claiming to, allowing users to exploit outdated collateral values during price drops

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

LendingPool::getNFTPrice or getPrimeRate doesn't validate timestamp staleness despite claiming to, allowing users to exploit outdated collateral values during price drops

Support

FAQs

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