-
Notifications
You must be signed in to change notification settings - Fork 173
Description
Proposal: Bad Debt Isolation & Repayment Mechanism
Caution
The Problem: In the current x/leverage architecture, when a user's collateral is fully liquidated but borrow balances remain, the remaining debt is flagged as "Bad Debt". However, this debt remains tracked as standard borrow shares. Because interest in Umee is calculated globally via an InterestScalar acting on all borrow shares, bad debt continues to accrue interest indefinitely. This infinitely increases the protocol's deficit and artificially inflates the utilization rate, driving up Borrow APY for healthy users.
1. Executive Summary
This proposal suggests an architectural shift to isolate bad debt. By completely removing uncollateralized debt from the standard borrow tracking system and moving it to a static, global ledger, the protocol can freeze the debt size (stopping interest accrual) while continuing to pay it down programmatically from newly accrued protocol reserves.
2. Proposed Architecture
The solution requires two primary state transitions: isolating the debt to freeze its value, and updating the global sweep mechanism to pay it down efficiently.
A. The Isolation Mechanism (Freezing the Debt)
Currently, the liquidation hook postLiquidate flags an address|denom when collateral hits zero.
Proposed Change:
Instead of just flagging the address, the protocol should execute a debt write-off during the liquidation state transition:
- Calculate Final Debt: Convert the user's remaining borrow shares into a static base token amount (e.g.,
100 USDC). - Erase the Position: Delete the user's borrow position entirely so they no longer hold borrow shares.
- Decrease Total Borrowed: Subtract the static amount from the leverage module's
TotalBorrowedstate. This immediately fixes the utilization rate calculation, ensuring healthy borrowers are not penalized with high interest rates caused by dead liquidity. - Move to Isolated State: Add the static amount to a new global variable:
IsolatedBadDebt[denom].
B. Modified Reserve Sweep Procedure (Automatic Repayment)
Currently, the SweepBadDebts function (called in EndBlocker) iterates over all flagged address|denom pairs across the network, attempting to repay each individually. This is highly inefficient.
Proposed Change:
The SweepBadDebts function should be refactored to operate globally rather than individually:
- In
EndBlocker, the protocol checks ifIsolatedBadDebt[denom] > 0. - It checks if the module has accumulated
Reserves[denom] > 0from recent interest accruals. - If both are true, it calculates the repayment amount:
Repayment = min(IsolatedBadDebt, Reserves). - It subtracts
Repaymentfrom both theIsolatedBadDebttracker and theReservespool in a singleO(1)state operation.
3. Key Benefits
| Benefit Area | Description |
|---|---|
| Protocol Solvency | Prevents bad debt from growing exponentially via compound interest, allowing the protocol's reserves to actually catch up and eliminate the deficit. |
| Market Fairness | Removing dead debt from TotalBorrowed restores accurate utilization rates. Healthy borrowers will no longer pay artificially inflated APYs caused by bad actors. |
| Performance | Replacing an O(N) network-wide iteration over individual bad debt addresses with a single O(1) global math operation saves significant computation overhead in the EndBlocker. |
| User Experience | Liquidated users no longer see an infinitely growing negative balance that they can never realistically repay. |
4. Implementation Steps
- Introduce a new KVStore prefix for
IsolatedBadDebtstructured bydenom.- Update
x/leverage/keeper/liquidate.go->postLiquidate()to wipe the borrow position and map it toIsolatedBadDebt.- Update
x/leverage/keeper/iter.go->SweepBadDebts()to utilize the globalO(1)repayment logic.- Ensure
ReserveFactorcontinues accruing from healthyTotalBorrowedbalances to fund the repayment.