Description
After reviewing LendingPool.sol, the report is valid but needs more precise technical details. The issue lies in the finalizeLiquidation function lacking health factor validation at liquidation execution time.
Vulnerable Code
function finalizeLiquidation(address userAddress) external nonReentrant onlyStabilityPool {
if (!isUnderLiquidation[userAddress]) revert NotUnderLiquidation();
if (block.timestamp <= liquidationStartTime[userAddress] + liquidationGracePeriod) {
revert GracePeriodNotExpired();
}
UserData storage user = userData[userAddress];
}
Impact
-
Financial Loss Risk
Users whose positions recover during grace period still get liquidated
NFT collateral could be seized despite improved health factor
No consideration of market price improvements
-
Protocol Risk
Unfair liquidations damage protocol reputation
Potential regulatory issues from improper liquidation practices
Legal exposure from affected users
Proof of Concept
function proveIncorrectLiquidation() public {
lendingPool.initiateLiquidation(user);
mockPriceOracle.setNFTPrice(tokenId, newHigherPrice);
lendingPool.finalizeLiquidation(user);
}
Recommended Mitigation
function finalizeLiquidation(address userAddress) external nonReentrant onlyStabilityPool {
if (!isUnderLiquidation[userAddress]) revert NotUnderLiquidation();
if (block.timestamp <= liquidationStartTime[userAddress] + liquidationGracePeriod) {
revert GracePeriodNotExpired();
}
uint256 currentHealthFactor = calculateHealthFactor(userAddress);
if (currentHealthFactor >= healthFactorLiquidationThreshold) {
revert PositionHealthyCannotLiquidate();
}
emit LiquidationPrices(
userAddress,
getUserCollateralValue(userAddress),
getUserDebt(userAddress),
currentHealthFactor
);
UserData storage user = userData[userAddress];
}
Additional Recommendations
Add snapshot of health metrics at liquidation initiation
Implement price oracle staleness checks
Add events for liquidation state changes
Consider graceful liquidation cancellation if position recovers