Summary
No check for stale oracle prices, risking undercollateralized loans.
* Checks if the price is stale
*/
function getNFTPrice(uint256 tokenId) public view returns (uint256) {
(uint256 price, uint256 lastUpdateTimestamp) = priceOracle.getLatestPrice(tokenId);
if (price == 0) revert InvalidNFTPrice();
return price;
Vulnerability Details
LendingPool's getNFTPrice()
retrieves oracle prices without validating staleness or deviation limits, enabling loans against potentially outdated or manipulated NFT valuations.
No staleness check despite comment indicating it should check
* @notice Gets the current price of an NFT from the oracle
* @param tokenId The token ID of the NFT
* @return The price of the NFT
*
* Checks if the price is stale
*/
In a State where
NFT price = 100 ETH at timestamp T
Price oracle stops updating
Market price drops to 10 ETH
Exploitation
function getNFTPrice(uint256 tokenId) public view returns (uint256) {
(uint256 price, uint256 lastUpdateTimestamp) = priceOracle.getLatestPrice(tokenId);
if (price == 0) revert InvalidNFTPrice();
return price;
}
function getNFTPrice(uint256 tokenId) public view returns (uint256) {
(uint256 price, uint256 lastUpdateTimestamp) = priceOracle.getLatestPrice(tokenId);
if (price == 0) revert InvalidNFTPrice();
return price;
}
function borrow(uint256 amount) external {
uint256 collateralValue = getNFTPrice(tokenId);
}
Will result in:
Loans issued at 100 ETH valuation
Actual collateral value = 10 ETH
Protocol becomes undercollateralized
Liquidations fail to cover debt
Mango Markets oracle manipulation attack ($114M loss) demonstrates how insufficient price validation leads to undercollateralized positions. Both cases show how DeFi lending protocols requiring accurate collateral valuation can be exploited through oracle trust assumptions.
Impact
function getNFTPrice(uint256 tokenId) public view returns (uint256) {
(uint256 price, uint256 lastUpdateTimestamp) = priceOracle.getLatestPrice(tokenId);
if (price == 0) revert InvalidNFTPrice();
return price;
}
Loans issued at 10x actual collateral value
Liquidations fail to cover outstanding debt
Maximum loss = Sum of all loans issued against stale/manipulated prices
Tools Used
vs
Recommendations
Add a time threshold for price validity
uint256 private constant PRICE_STALENESS_THRESHOLD = 24 hours;
uint256 private constant MIN_NFT_PRICE = 1000;
uint256 private constant MAX_PRICE_DEVIATION = 50;
function getNFTPrice(uint256 tokenId) public view returns (uint256) {
(uint256 price, uint256 lastUpdateTimestamp) = priceOracle.getLatestPrice(tokenId);
if (block.timestamp - lastUpdateTimestamp > PRICE_STALENESS_THRESHOLD) {
revert StalePriceData();
}
if (price == 0 || price < MIN_NFT_PRICE) revert InvalidNFTPrice();
return price;
}