Core Contracts

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

Liquidation State Inconsistency Can Lead to Unfair Liquidations in lendingpool

Summary

The LendingPool contract has a vulnerability in its liquidation process where users who have repaid their debt can still be liquidated if they don't explicitly call closeLiquidation. Additionally, liquidators have an incentive to wait until after the grace period to call finalizeLiquidation as they will pay less for the liquidation.

Vulnerability Details

Source

The vulnerability stems from three key issues:

  1. The liquidation state (isUnderLiquidation) is not automatically cleared when a user repays their debt

  2. Users must manually call closeLiquidation even after full repayment

  3. The grace period check in finalizeLiquidation allows liquidators to wait for better terms

function closeLiquidation(address userAddress) external nonReentrant {
if (!isUnderLiquidation[userAddress]) revert NotUnderLiquidation();
// update state
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);
}

Proof of Concept

Scenario 1 - User Repays But Forgets to Close Liquidation:

  1. User's position becomes liquidatable

  2. User repays their debt through the repay function

  3. User doesn't call closeLiquidation

  4. Liquidator can still call finalizeLiquidation after grace period

  5. User loses their NFTs despite having repaid the debt

Scenario 2 - Liquidator Waits for Grace Period :

  1. User's position becomes liquidatable

  2. Liquidator waits until after grace period

  3. Calls finalizeLiquidation

  4. Gets NFTs at a potentially lower price due to market conditions

  5. Original user suffers greater losses

Impact

  • Users can lose collateral even after debt repayment

  • Liquidators can game the system by waiting for grace period expiration

  • Creates unfair advantages for liquidators

  • Users may lose more value than necessary in liquidations

Tools Used

  • Manual code review

Recommendations

  1. Automatically clear liquidation state on full repayment:

function _repay(uint256 amount, address onBehalfOf) internal {
// ... existing code ...
if (user.scaledDebtBalance == 0) {
+ isUnderLiquidation[onBehalfOf] = false;
+ liquidationStartTime[onBehalfOf] = 0;
+ emit LiquidationClosed(onBehalfOf);
}
}
  1. Consider removing the manual closeLiquidation requirement and make it automatic based on debt status.

Updates

Lead Judging Commences

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

A borrower can LendingPool::repay to avoid liquidation but might not be able to call LendingPool::closeLiquidation successfully due to grace period check, loses both funds and collateral

Support

FAQs

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

Give us feedback!