Core Contracts

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

Missing Price Staleness Check in NFT Oracle Integration

Summary

The LendingPool contract fails to implement staleness checks when fetching NFT prices from the oracle, potentially allowing the use of outdated price data for critical operations like borrowing, liquidations, and collateral valuations.

Vulnerability Details

In getNFTPrice(), the contract retrieves price data from the oracle but ignores the lastUpdateTimestamp:

This function is used in critical operations:

  1. Collateral valuation (getUserCollateralValue)

  2. Health factor calculations (calculateHealthFactor)

  3. NFT withdrawal checks (withdrawNFT)

  4. Liquidation decisions (initiateLiquidation)

Poc:

Overborrowing attack:
A malicious user deposited an NFT which initial price of the NFT is 100ETH

  • Due to market movement, price of the NFT drops to 60ETH,

  • Malicious user see that price has not been updated in the lendingpool

  • Malicious user can quickly borrow 80% of the 100ETH which is 80ETH against NFT which has dropped in market but not updated on the lendingPool.

  • He made extra 20ETH from the pool because he was able to take out 80ETH from the pool against a collateral of 100ETH that has dropped to 60ETH.

Root Cause

The vulnerability stems from:

  1. No timestamp validation in price feeds

  2. Missing oracle freshness checks

Impact

  1. Incorrect collateral valuation leading to under/over-borrowing

  2. Potential manipulation of liquidations using stale prices

  3. System operating on outdated market data

  4. Risk of significant financial losses

Tools Used

Manual code review

Recommendations

Add staleness check with configurable threshold:

contract LendingPool {
uint256 public constant PRICE_STALENESS_THRESHOLD = 1 days;
function getNFTPrice(uint256 tokenId) public view returns (uint256) {
(uint256 price, uint256 lastUpdateTimestamp) = priceOracle.getLatestPrice(tokenId);
if (price == 0) revert InvalidNFTPrice();
// Add staleness check
if (block.timestamp - lastUpdateTimestamp > PRICE_STALENESS_THRESHOLD)
revert StalePriceData();
return price;
}
error StalePriceData();
}

}

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.