Core Contracts

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

Missing Stale Price Check in NFT Oracle Price Retrieval

Summary

The protocol’s function for retrieving NFT prices is intended to validate the freshness of the price data provided by the oracle. However, while the function retrieves both the price and its timestamp, it fails to enforce any staleness check. This oversight can lead to the use of outdated price information when valuing NFT collateral, potentially resulting in mispricing and triggering unjust liquidations.

Vulnerability Details

Intended Behavior:

When retrieving an NFT’s price, the function should:

  1. Obtain the current price and the time at which it was last updated.

  2. Verify that the price data is recent—i.e., the timestamp is within an acceptable “freshness” window.

  3. Reject stale price data by reverting if the data is too old.

Current Implementation:

function getNFTPrice(uint256 tokenId) public view returns (uint256) {
(uint256 price, uint256 lastUpdateTimestamp) = priceOracle.getLatestPrice(tokenId);
if (price == 0) revert InvalidNFTPrice();
return price;
}
  • The function only checks that price is nonzero.

  • The returned lastUpdateTimestamp is entirely ignored, meaning there is no verification of whether the price is current.

Root Cause:

The absence of a check against a maximum acceptable age (e.g., a MAX_PRICE_AGE constant) allows stale prices to be used in further calculations, even though the function’s comment suggests that price staleness should be verified.

Impact

  • Collateral Misvaluation: Outdated NFT prices could lead to collateral being over- or under-valued, which affects a borrower’s health factor.

  • Unjust Liquidations: Borrowers might be liquidated based on stale price data, even if their actual collateral is sufficient.

Tools Used

Manual Code Review

Recommendations

  1. Implement a Staleness Check:
    Introduce a constant (e.g., MAX_PRICE_AGE) and compare it against the current time. For example:

    uint256 constant MAX_PRICE_AGE = 1 hours; // or another suitable duration
    function getNFTPrice(uint256 tokenId) public view returns (uint256) {
    (uint256 price, uint256 lastUpdateTimestamp) = priceOracle.getLatestPrice(tokenId);
    if (price == 0) revert InvalidNFTPrice();
    if (block.timestamp > lastUpdateTimestamp + MAX_PRICE_AGE) revert PriceDataStale();
    return price;
    }
Updates

Lead Judging Commences

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