The closeLiquidation function in the LendingPool contract is intended to allow a user to close their liquidation status by repaying their outstanding debt during the grace period. However, the function’s validation for the remaining debt uses the wrong comparison operator relative to the DUST_THRESHOLD. Currently, the code reverts if the user's remaining debt is greater than the DUST_THRESHOLD (set to 1e6). According to the intended behavior, the function should only allow the closure of liquidation when the user's remaining debt is significant (i.e. greater than or equal to 1e6), and it should revert if the user's remaining debt is less than this threshold. In other words, the check should revert if userDebt < DUST_THRESHOLD rather than if userDebt > DUST_THRESHOLD. This bug may allow users with negligible debt to bypass the liquidation process, leading to incorrect system behavior and potential denial of service.
Current Behavior:
In the closeLiquidation function, after updating the reserve state and verifying that the grace period has not expired, the function calculates the user's debt:
With the current check, if a user's remaining debt is greater than the DUST_THRESHOLD (1e6), the function reverts with DebtNotZero(). This prevents liquidation closure for users who still have a significant debt, contrary to the intended logic.
Intended Behavior:
The function is expected to allow closing liquidation when a user has a significant remaining debt—specifically, when userDebt is greater than or equal to 1e6. If the user’s remaining debt is below 1e6 (i.e. considered negligible or "dust"), then the function should revert. The correct check should thus be:
This change ensures that liquidation can only be closed if the user's remaining debt is at least 1e6, preventing scenarios where users might bypass the liquidation process with an insufficient repayment.
Setup:
Alice deposits 1000e18 reserve assets and mints an NFT as collateral.
She borrows 900e18, reducing her health factor below the liquidation threshold.
Liquidation Initiation:
Bob initiates Alice's liquidation, flagging her as under liquidation and starting the grace period.
Liquidation Closure Attempt:
When Alice calls closeLiquidation, the function calculates her remaining debt.
With the current check (if (userDebt > DUST_THRESHOLD) revert DebtNotZero();), if Alice’s remaining debt is greater than 1e6, the function reverts—blocking her from closing liquidation even when she has repaid enough to be eligible.
According to the intended logic, the function should allow closure when the remaining debt is significant (≥1e6) and only revert when it is too low (i.e., <1e6). The improper check leads to a denial of liquidation closure.
Create a Foundry Project:
Open your terminal and run:
Place Contract Files:
Place all relevant contract files (e.g., LendingPool.sol, RAACNFT.sol, RAACHousePrices.sol, etc.) in the src directory of your project.
Create Test Directory:
Create a directory named test adjacent to the src directory, and add the test file (e.g., PoolsTest.t.sol) containing the above test suite code.
Run the Test:
Execute the following command in your terminal:
This command will run the specific test with verbose output, allowing you to verify that the current dust threshold check is causing a revert when it should allow liquidation closure for users with significant remaining debt.
Output:
Liquidation Process Blocked:
Due to the incorrect dust threshold check, users who have repaid enough to still hold a significant amount of debt (≥1e6) are unable to close liquidation, resulting in a denial of service for closing liquidation.
User Frustration and System Instability:
Affected users remain trapped in liquidation despite having a non-negligible debt balance, which undermines the intended risk mitigation process and may lead to broader operational issues.
Manual Review
Foundry (forge)
To fix this vulnerability, the debt validation check in closeLiquidation should be inverted. Replace the current check:
with the following:
This change ensures that liquidation can only be closed if the user's remaining debt is significant (i.e., at least 1e6). If the remaining debt is below this threshold, the function will revert, preventing closure of liquidation when there is insufficient debt to justify the process.
After applying this modification, rerun the test suite to confirm that the liquidation closure behaves as intended.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.