Repayments
How repayments flow through the protocol - debt detection, share burning, and overpayment handling
Repayment Flow Overview
Repayment Subaccount
Repayments use a different prefix than deposits to distinguish them:
- Deposit prefix:
0x1 - Repayment prefix:
0x2
This allows the protocol to correctly attribute incoming funds as debt repayment rather than new collateral.
Detection Process
The detection process is identical to deposits:
- Inflow Detection - Pool scans for new balances every 60 seconds
- Treasury Transfer - Funds moved from repayment subaccount to treasury
- Event Creation - Pool creates a
RepaymentConfirmedevent
Debt Share Burning
When the lending canister receives a repayment event:
- Checks idempotency (skip if already processed)
- Syncs pool indices
- Calculates current debt
- Burns debt shares:
shares_to_burn = repay_amount / borrow_index - Handles any overpayment
Example: User has 1000 debt shares at borrow_index = 1.05 → Current debt = 1050 tokens. User repays 525 tokens → Shares burned = 525 / 1.05 = 500 shares → Remaining: 500 shares = 525 tokens debt
Overpayment Handling
If the user sends more than their outstanding debt, the excess becomes protocol service fees. The user's debt is fully cleared.
Why not refund?
- Refunds require another blockchain transaction
- Gas costs may exceed overpayment amount
- Simplifies protocol logic
Overpayments are not automatically refunded. Send the exact amount or slightly less than your outstanding debt.
Partial Repayments
Users can repay any amount up to their full debt. The protocol calculates how many debt shares to burn based on the current borrow index.
Example:
- User has 1000 debt shares at borrow_index = 1.05 → Current debt = 1050 tokens
- User repays 525 tokens → Shares burned = 525 / 1.05 = 500 shares
- Remaining: 500 shares = 525 tokens debt
Interest Consideration
When repaying, remember that debt accrues interest continuously (even while repayment transactions are processing):
Example (simplified, compounding not shown for clarity): Borrowed 1000 USDT, 6 months elapsed, 10% APY → Accrued interest: ~50 USDT → Total debt: ~1050 USDT
Repayment Address
Each user has a unique repayment address per pool:
| Chain | Method |
|---|---|
| Bitcoin | Same address as deposit, distinguished by subaccount prefix |
Repayment addresses are only available for Bitcoin. Other assets must be repaid directly from a linked wallet.
Repayment via deposit addresses are not yet supported for USDT. Coming soon.
Timing
| Step | Trigger | Latency |
|---|---|---|
| Native tx confirmation | Blockchain | Varies by chain |
| ckAsset minting | Minter | Immediate |
| Inflow detection | Timer | ~60 sec |
| Treasury transfer | WAL | ~30 sec |
| Treasury detection | Timer | ~60 sec |
| Event notification | Timer | ~60 sec |
| Debt share burning | Event | Immediate |
Health Factor Impact
Repaying debt improves your health factor:
Before repayment: Collateral: 40,000, HF = 1.0 (at risk)
**After repaying 50,000, Debt: $30,000, HF = 1.33 (safer)
Idempotency
Repayments have the same deduplication as deposits:
- Ledger index tracking: Each transaction processed once
- PROCESSED_INFLOWS set: Event deduplication
- Subaccount debouncing: One job per subaccount per scan
Repayments are automatically detected. Just send assets to your repayment address - no additional action required.