Core Contracts

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

Improper Liquidation State Handling in Lending Protocol causing Risk of Unchecked Borrowing and Repayment

Summary

The [isUnderLiquidation](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d8used in multiple functions within the lending protocol to determine whether a user is under liquidation. However, the contract does not implement any mechanism to update this mapping based on objective financial metrics such as the health factor. This creates a potential risk where users who should be under liquidation may not be marked as such, allowing them to borrow or repay debt under conditions that should trigger liquidation.

Vulnerability Details

The isUnderLiquidation mapping is set manually without being dynamically updated based on real-time calculations of a user’s financial position (e.g., health factor). The main issues are:24263a4c0b601bcb7f/contracts/core/pools/LendingPool/LendingPool.sol#L86) mapping is

  1. Lack of Automated Liquidation Status Updates:

    • The contract does not include a function that continuously checks a user’s health factor and updates isUnderLiquidation accordingly.

    • A user may fall below the liquidation threshold but still be able to interact with the system without restrictions.

  2. Users Might Evade Liquidation:

    • If a user should be under liquidation but is not marked as such, they may continue borrowing or repaying debt strategically to avoid liquidation.

    • This could allow users to manipulate their debt and collateral position in ways that unfairly benefit them at the expense of other protocol participants.

  3. The **borrow** Function Checks **isUnderLiquidation** But Not Health Factor:

    • In the borrow function, a user is blocked from borrowing if isUnderLiquidation[msg.sender] == true, but the contract does not verify if the user should be under liquidation.

    • Without an explicit check on the health factor, users who should be liquidated may still be able to take out loans.

Impact

The absence of a dynamic update mechanism for isUnderLiquidation introduces significant financial risks, including:

  1. Bad Debt Accumulation:

    • If liquidation does not happen when it should, users could default on their loans, leading to uncollectible debt for the protocol.

  2. Systemic Risk for the Lending Pool:

    • Allowing users to borrow when they should be liquidated could lead to an overleveraged system where collateral backing the loans is insufficient.

  3. Unfair Liquidation Delays:

    • Liquidators might be unable to act in time if a user strategically manipulates their debt or repayment without isUnderLiquidation being properly updated.

Tools Used

  • Manual Code Review: A detailed inspection of the smart contract code revealed that isUnderLiquidation is not updated dynamically.

  • Slither (Static Analysis): Used to detect missing state updates and logical inconsistencies.

  • Foundry/Hardhat Testing: Simulated various scenarios where a user’s health factor falls below the liquidation threshold but isUnderLiquidation remains unchanged.

Recommendations

To mitigate these risks, the following improvements should be implemented:

  1. Introduce a Health Factor Check Before Borrowing

    • Modify the borrow function to calculate the user’s health factor before approving new debt.

    • Example:

      uint256 healthFactor = getUserCollateralValue(msg.sender) * 1e18 / userTotalDebt;
      if (healthFactor < MIN_HEALTH_FACTOR) {
      isUnderLiquidation[msg.sender] = true;
      revert CannotBorrowUnderLiquidation();
      }
  2. Dynamically Update **isUnderLiquidation** Based on Health Factor

    • Implement a function that automatically updates isUnderLiquidation based on real-time collateral and debt balances.

    • Example:

      function updateLiquidationStatus(address user) public {
      uint256 healthFactor = getUserCollateralValue(user) * 1e18 / getUserDebt(user);
      isUnderLiquidation[user] = healthFactor < MIN_HEALTH_FACTOR;
      }
  3. Ensure **isUnderLiquidation** is Checked in All Key Functions

    • Modify repay to prevent users under liquidation from making repayments that could artificially avoid liquidation without repaying the full debt.

    • Example:

      if (isUnderLiquidation[onBehalfOf]) revert CannotRepayUnderLiquidation();
  4. Improve Liquidation Handling in **finalizeLiquidation**

    • Ensure that finalizeLiquidation can only be triggered for users who are truly under liquidation.

Updates

Lead Judging Commences

inallhonesty Lead Judge 2 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.