rounding error during full liquidations
Closed this issue · 0 comments
larry0x commented
background
currently, a full liquidation (i.e. 100% of a collateral is liquidated) works as follows (over-simpliefied, in pseudo-code):
- calculate the user's total collateral amount available to be liquidated:
user_collateral_total_amount = scaled_amount_to_underlying_amount(user_collateral_total_scaled_amount)
- calculate the amount of debt to pay as
debt_amount_to_pay = min(sent_debt_asset_amount, close_factor * user_debt_total_amount)
- calculate the amount of collateral to liquidate as
collateral_amount_to_liquidate = debt_amount_to_pay * debt_price * (1 + liquidation_bonus) / collateral_price
- this is a full liquidation, meaning the collateral amount to liquidate is bigger than the user's total available collateral amount. adjust the amount to liquidate:
collateral_amount_to_liquidate = min(collateral_amount_to_liquidate, user_collateral_total_amount)
- calculate the scaled amount to liquidate:
collateral_scaled_amount_to_liquidate = underlying_amount_to_scaled_amount(collateral_amount_to_liquidate)
- transfer the scaled amount from the user's account to the liquidator's:
user_collateral_total_scaled_amount -= collateral_scaled_amount_to_liquidate
liquidator_collateral_total_scaled_amount += collateral_scaled_amount_to_liquidate
the problem
the calculations in step (1) and (5) both use floor, i.e. truncate decimal places. this means the adjusted collateral_amount_to_liquidate
is necessarily smaller than user_collateral_total_scaled_amount
. that is, the user will still have some "dust" collateral left after the "full" liquidation.
this is noted in the relevant unit test:
the solution
steps 1–3 unchanged.
revert the order of steps 4 and 5:
- calculate the scaled amount to liquidate:
collateral_scaled_amount_to_liquidate = underlying_amount_to_scaled_amount(collateral_amount_to_liquidate)
- compare the scaled collateral amount to liquidate with the user's available scaled collateral amount:
collateral_scaled_amount_to_liquidate = min(collateral_scaled_amount_to_liquidate, user_collateral_total_scaled_amount)
step 6 unchanged.
this solves the issue.