Core Contracts

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

Stale Price Oracle in getNFTPrice() Function Leading to Outdated Price Risk

Summary

The getNFTPrice() function in LendingPool doesn't check if the price update is recent, allowing stale prices to be used for collateral valuation.

Vulnerability Details

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/pools/LendingPool/LendingPool.sol#L591

function getNFTPrice(uint256 tokenId) public view returns (uint256) {
(uint256 price, uint256 lastUpdateTimestamp) = priceOracle.getLatestPrice(tokenId);
if (price == 0) revert InvalidNFTPrice();
return price;
}
  • The function retrieves both the price and lastUpdateTimestamp from priceOracle.getLatestPrice(tokenId).

  • It checks if price == 0 and reverts with InvalidNFTPrice() if true, ensuring a non-zero price.

    But It does not perform any validation on lastUpdateTimestamp to determine if the price is stale. The lastUpdateTimestamp is returned but not used within getNFTPrice() to enforce freshness.

  • There’s no defined maximum age (e.g., MAX_PRICE_AGE) or check like require(block.timestamp - lastUpdateTimestamp <= MAX_PRICE_AGE, "Stale price").

  • In LendingPool:

    • getNFTPrice() is called in functions like:

      • getUserCollateralValue(): Calculates total collateral value for a user’s NFTs.

      • withdrawNFT(): Checks if withdrawal leaves the user undercollateralized.

      • borrow(): Ensures sufficient collateral for borrowing.

    • If getNFTPrice() returns a stale price, collateralValue could be overestimated or underestimated, allowing a user to borrow more or less than the current market value of their NFT collateral supports

Impact

  • If an NFT’s price has dropped since the last update, a user could borrow against an outdated high value, leaving the protocol undercollateralized if the NFT is liquidated at a lower market value.

  • If the price has risen, a user might be unable to withdraw their NFT due to an underestimated collateralValue, locking funds unnecessarily.

Tools Used

Recommendations

  • Add Freshness Check in getNFTPrice()

  • MAX_PRICE_AGE could be configurable via setParameter()

require(block.timestamp - lastUpdateTimestamp <= MAX_PRICE_AGE, "Stale price");
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!