Relevant GitHub Links
https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/primitives/RAACHousePrices.sol#L13
https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/pools/LendingPool/LendingPool.sol#L591
Summary
The LendingPool does not validate the staleness of house prices when calculating health factors, which could delay liquidations in illiquid real estate market conditions.
Vulnerability Details
The RAACHousePrices oracle and LendingPool interaction lacks staleness validation:
contract RAACHousePrices is Ownable {
mapping(uint256 => uint256) public tokenToHousePrice;
uint256 public lastUpdateTimestamp;
}
function getNFTPrice(uint256 tokenId) public view returns (uint256) {
(uint256 price, uint256 lastUpdateTimestamp) = priceOracle.getLatestPrice(tokenId);
if (price == 0) revert InvalidNFTPrice();
return price;
}
While price staleness could affect health factor calculations:
function calculateHealthFactor(address userAddress) public view returns (uint256) {
uint256 collateralValue = getUserCollateralValue(userAddress);
uint256 userDebt = getUserDebt(userAddress);
if (userDebt < 1) return type(uint256).max;
uint256 collateralThreshold = collateralValue.percentMul(liquidationThreshold);
return (collateralThreshold * 1e18) / userDebt;
}
Impact
Potential delay in liquidations during market downturns
Increased bad debt possible
StabilityPool protected by manager intervention ability
Tools Used
Manual Review
Recommendations
Add configurable staleness threshold with governance control:
contract LendingPool {
uint256 public maxPriceStaleness = 7 days;
function getNFTPrice(uint256 tokenId) public view returns (uint256) {
(uint256 price, uint256 lastUpdateTimestamp) = priceOracle.getLatestPrice(tokenId);
if (price == 0) revert InvalidNFTPrice();
if (block.timestamp - lastUpdateTimestamp > maxPriceStaleness) {
revert StalePriceNotAllowed();
}
return price;
}
}