Core Contracts

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

Stale Price Usage in `mint()` Due to Lack of Timestamp Validation in `RAACNFT.mint()`

Summary

The RAACNFT.sol contract relies on the tokenToHousePrice(_tokenId) function from RAACHousePrices.sol to determine the minting price of an NFT. However, this function does not provide a timestamp for the last update, leading to the risk of using stale price data if the Chainlink Functions update is delayed or fails.

Vulnerability Details

The mint() function in RAACNFT.sol retrieves the NFT price using raac_hp.tokenToHousePrice(_tokenId). This function does not return a timestamp, meaning there is no way to verify whether the price is fresh or outdated. If Chainlink Functions fail to update the price in time, users may mint NFTs at an outdated price, which can lead to financial discrepancies.

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

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/RAACNFT.sol#L33

A better alternative exists within RAACHousePrices.sol: the getLatestPrice(_tokenId) function, which returns both the latest price and the last update timestamp. However, the mint() function does not currently use this function, leading to potential stale data usage.

function getLatestPrice(
uint256 _tokenId
) external view returns (uint256, uint256) {
return (tokenToHousePrice[_tokenId], lastUpdateTimestamp);
}

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/primitives/RAACHousePrices.sol#L34C4-L38C6

Impact

If the price update from Chainlink Functions is delayed or fails, the contract may allow minting at outdated prices, leading to:

  • Potential underpricing or overpricing of NFTs.

  • Financial loss for users or the protocol.

  • Exploitable opportunities if stale prices favor certain users.

Tools Used

Manual review

Recommendations

Modify the mint() function in RAACNFT.sol to use getLatestPrice(_tokenId) instead of tokenToHousePrice(_tokenId). Additionally, introduce a MAX_STALE_TIME constant to define the maximum allowable staleness for the price before rejecting the transaction. This ensures that only fresh price data is used, mitigating risks related to stale Chainlink Function responses.

Updates

Lead Judging Commences

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

Give us feedback!