Root + Impact
Description
-
liquidation should reduce protocol bad debt and allow insolvent positions to be unwound.
-
the engine always gives the liquidator a 10% collateral bonus and then requires the user’s health factor to improve after liquidation. For sufficiently underwater positions, seizing debt_to_cover + bonus worth of collateral worsens the collateralization ratio instead of improving it. In that state, every liquidation reverts with DSCEngine__HealthFactorNotImproved, permanently trapping bad debt in the system.
token_amount_from_debt_covered: uint256 = self._get_token_amount_from_usd(
collateral, debt_to_cover
)
bonus_collateral: uint256 = (
token_amount_from_debt_covered * LIQUIDATION_BONUS
)
<self._redeem_collateral(
collateral,
token_amount_from_debt_covered + bonus_collateral,
user,
msg.sender,
)>
<self._burn_dsc(debt_to_cover, user, msg.sender)>
ending_user_health_factor: uint256 = self._health_factor(user)
<assert (
ending_user_health_factor > starting_user_health_factor
), "DSCEngine__HealthFactorNotImproved">
Risk
Likelihood:
-
Positions become eligible for liquidation whenever collateral price drops enough.
-
Once a position is at or below the mathematical recovery threshold, every liquidator will hit the same revert.
Impact:
Proof of Concept
Let:
C = collateral value
D = debt
HF = 0.5 * C / D
After liquidating x debt with a 10% collateral bonus:
C' = C - 1.1x
D' = D - x
New health factor:
HF' = 0.5 * (C - 1.1x) / (D - x)
For HF' > HF:
(C - 1.1x)/(D - x) > C/D
=> C > 1.1D
So if the position is already at or below 110% collateralization,
any liquidation makes health factor worse and the transaction reverts.
*/
Concrete example:
Initial collateral value = $10,000
Initial debt = $10,000
Initial HF = 0.5
Liquidate $1,000 debt:
Collateral seized = $1,100
New collateral = $8,900
New debt = $9,000
New HF = 0.5 * 8,900 / 9,000 = 0.4944...
HF decreased, so liquidation reverts.
*/
Recommended Mitigation
- require ending_user_health_factor > starting_user_health_factor for every liquidation
+ allow liquidation whenever protocol bad debt is reduced
+ allow full liquidation of underwater positions even if partial liquidation does not improve HF
+ cap liquidation bonus or seized collateral so liquidation cannot worsen the borrower position
+ add tests for positions below 110% collateralization