liquidate() requires ending_user_health_factor > starting_user_health_factor (strict greater-than). Combined with the 10% LIQUIDATION_BONUS, a mathematical impossibility arises when the collateral-to-debt ratio falls below 110%.
For any partial liquidation amount d against a position with collateral value C and debt D:
Post-liquidation ratio: (C - 1.1d) / (D - d)
For HF to improve: (C - 1.1d) / (D - d) > C / D
Simplifying: C * d > 1.1 * d * D, so C > 1.1 * D
When C/D <= 1.1, no partial liquidation amount can improve the health factor. The assert always reverts.
Full liquidation (d = D) would set debt to 0 and HF to max_value(uint256). But full liquidation requires redeeming 1.1 * D in collateral. When C < 1.1 * D, the subtraction in _redeem_collateral underflows (Vyper safe math) and reverts before the HF check is reached.
Two separate failure modes:
110% > C/D > 100% (partial): HF doesn't improve, reverts at the assert
C/D < 110% (full): Requires more collateral than exists, underflows at _redeem_collateral
This is distinct from the known insolvency issue in the README ("If the protocol ever becomes insolvent, there is almost no way to recover"). Insolvency means C < D (ratio < 100%). This bug triggers at C/D < 1.1 (ratio < 110%) where positions still have positive equity but cannot be liquidated.
Likelihood:
Any ETH/BTC price drop that pushes a position below 110% CR triggers this. Happens routinely in crypto markets.
The existing test test_must_improve_health_factor_on_liquidation confirms the revert.
Impact:
Positions between 100%-110% CR become permanent zombies. No one can liquidate them.
Further price drops push these positions below 100%, creating irrecoverable bad debt.
Protocol solvency invariant breaks as underwater positions accumulate.
Allow full liquidation to bypass the HF improvement check. When debt goes to 0, HF becomes max_value(uint256), so the special case is easy to detect:
This allows full liquidation (debt zeroed, HF = max) while still requiring partial liquidations to improve the position. Additionally, consider reducing or eliminating the bonus for deeply undercollateralized positions so partial liquidations can also succeed below 110%.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.