Core Contracts

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

Inability to Close Liquidation After Adding Sufficient Collateral

Summary

The closeLiquidation function in LendingPool fails to recalculate the user's health factor after potential collateral additions, forcing full debt repayment even when the position becomes healthy again.

Vulnerability Details

In closeLiquidation(), the function only checks if userDebt > DUST_THRESHOLD to determine if liquidation can be closed. It doesn't recalculate the health factor to check if the position has become healthy through additional collateral.

function closeLiquidation() external nonReentrant whenNotPaused {
address userAddress = msg.sender;
if (!isUnderLiquidation[userAddress]) revert NotUnderLiquidation();
ReserveLibrary.updateReserveState(reserve, rateData);
if (block.timestamp > liquidationStartTime[userAddress] + liquidationGracePeriod) {
revert GracePeriodExpired();
}
UserData storage user = userData[userAddress];
uint256 userDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex);
if (userDebt > DUST_THRESHOLD) revert DebtNotZero();
isUnderLiquidation[userAddress] = false;
liquidationStartTime[userAddress] = 0;
emit LiquidationClosed(userAddress);
}

Impact

Users who add sufficient collateral to make their position healthy again during the grace period are still forced to repay their entire debt to avoid liquidation, leading to unnecessary capital inefficiency and potential loss of positions.

Tools Used

Manual Review

Recommendations

Add health factor recalculation in closeLiquidation() and allow closing liquidation if the health factor returns above the threshold

function closeLiquidation() external nonReentrant whenNotPaused {
address userAddress = msg.sender;
if (!isUnderLiquidation[userAddress]) revert NotUnderLiquidation();
ReserveLibrary.updateReserveState(reserve, rateData);
+ uint256 healthFactor = calculateHealthFactor(userAddress);
+ if (healthFactor >= healthFactorLiquidationThreshold) {
+ isUnderLiquidation[userAddress] = false;
+ liquidationStartTime[userAddress] = 0;
+ emit LiquidationClosed(userAddress);
+ return;
+ }
// Existing debt check logic for full repayment path
...
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

LendingPool::finalizeLiquidation() never checks if debt is still unhealthy

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.