Open sherlock-admin3 opened 1 month ago
Design Decision\Invalid: This exactly the way it is expected to work as it is implemented exactly the same way in Aave
It is stated in the Readme, that this is an aave fork. The liquidation will also be handled through the same liquidation bots as in Aave
Are there any off-chain mechanisms or off-chain procedures for the protocol (keeper bots, arbitrage bots, etc.)? There are liquidation bots that run off-chain to execute liquidations similar to how liquidations work on Aave.
escalate per comment
You've created a valid escalation!
To remove the escalation from consideration: Delete your comment.
You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.
This codebase being a fork of AAVE does not mean this issue is an intentional design choice by ZeroLend due to the following reasons:
Here is a report from Inverse Finance which argues for a non-constant liquidation incentive as a solution to this issue:
To prevent this exploit we have to make the incentive non-constant, such that the incentive cannot pay more than the loss of the excess collateral. The incentive may be limited to only pay for the part of the liquidation that doesn't bring the debt over the collateral. This may be implemented such that if the debt is critically collateralized the liquidator effectively liquidates with incentive only until the debt equals the collateral, and thereafter the rest is just liquidated without incentive. Note that this still means debts can be critically collateralized, which means that they will be completely liquidated (regardless of the liquidation factor).
Likewise, the same escalation argument could be brought against issues like #275 of which we both submitted as valid issues even though the same issue also exists in AAVE.
tallo
High
Partial liquidations can sometimes lower a positions health and lead to guaranteed bad debt
Summary
Partial liquidations are allowed when a users healthFactor
.95 < healthFactor < 1
. When users have a single asset as collateral this often leads to a position having a decreased health factor after liquidation. The user can be repeatedly liquidated and the protocol guaranteed bad debt.Root Cause
The cases where a position's health factor decreases can be derived as follows: Partial liquidation percent: 50% Liquidator discount K: 5% C: initial collateral value D: initial debt value LT: Liquidation threshold Initial Health factor = (C LT) / D < 1 After partial Liquidation: New Debt: D' = D 0.5 Liquidated Collateral: L = (D 0.5)/(1 - K) New Collateral: C' = C-L New Health Factor = (C' LT)/D' For the health factor to increase the following inequality must hold: (C' LT) / D' > (C LT) / D (C - L) > C 0.5 (C - (D 0.5)/(1 - K) > C 0.5 -(D 0.5 / (1 - K)) > -C 0.5 D 0.5 / (1 - K) < C * 0.5 D / (1 - K) < C (1 - K ) > D / C C / D > 1 / (1 - K) In other words, liquidation only leads to an increase in the health factor when there is enough collateral to pay off the discount. This inequality is more likely to be unsatisfied with higher LTV assets since the C / D value will be lower.
Internal pre-conditions
External pre-conditions
Attack Path
Impact
PoC
set the PoolSetup.sol#_basicPoolInitParams function to the following. This is to change the LTV's/liquidation thresholds of the assets.
place the following test inside NFTPositionManagerTest.t.sol
Logs: d / c < .95 => 7.5e10 / 7.8e10 = 9.61538461538461538e17 ratio < 0.95 => 9.61538461538461538e17 < 9.5e17 => false alice HF before any liquidations: 9.88e17
bad debt: false d / c < .95 => 3.75e10 / 3.8625e10 = 9.7087378640776699e17 ratio < 0.95 => 9.7087378640776699e17 < 9.5e17 => false alice HF after first liquidation: 9.785e17 Total amount liquidated: 5.04807692307692307692e20
bad debt: false d / c < .95 => 1.875e10 / 1.89375e10 = 9.90099009900990099e17 ratio < 0.95 => 9.90099009900990099e17 < 9.5e17 => false alice HF after second liquidation: 9.595e17 Total amount liquidated: 7.57211538461538461538e20
bad debt: true d / c < .95 => 9.375e9 / 9.09375e9 = 1.030927835051546391e18 ratio < 0.95 => 1.030927835051546391e18 < 9.5e17 => false alice HF after second liquidation: 9.215e17 Total amount liquidated: 8.8341346153846153846e20
The test shows how after subsequent liquidations, the health factor fails to improve after several liquidations. The position is both unhealthier after each liquidation, and the user is being liquidated beyond 50% of their debt when their
HF > 0.95
. Eventually, after the 3rd liquidation the protocol is left with bad debt (collateral < debt)Mitigation
Do not allow partial liquidations when the inequality is unfavorable. Consider disallowing liquidations if they decrease the health factor.