# Dust cleanup burns more debt than callers account for

DebtToken burn_scaled promotes a partial burn into a full dust wipe, but KineticRouter repay only transfers the requested amount, letting borrowers cancel more debt than they pay.

- Payout: Contest reward
- Severity: high
- Program: K2
- Credited: v12
- Disclosed: 2026-08-20
- Write-up quality: 7/10
- Original: https://code4rena.com/reports/2026-04-k2#h-14
- Library page: https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AH-14
- Tags: domain:web3 impact:funds-loss impact:integrity kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic vuln:precision-loss

**Target:** DebtTokenContract::burn_scaled and KineticRouter repay/execute_repay/add_reserve_deficit
**Root cause:** burn_scaled rounds to scaled units and when new_scaled_debt <= 1 promotes a partial burn into a full debt wipe, but callers use requested/pre-burn amounts as source of truth instead of the actual burn result.
**Steps:**
1. Borrower holds a position with scaled debt near the dust threshold (new_scaled_debt <= 1 after a partial burn).
2. Call `KineticRouter::repay` with `amount_to_repay` just large enough that `burn_scaled` hits the dust-cleanup branch.
3. Router transfers only `amount_to_repay` underlying to the debt token.
4. `burn_scaled` zeroes the remaining scaled debt instead of burning only the requested amount.
5. `execute_repay` ignores the burn_scaled return and computes `remaining_debt = debt_balance - amount_to_repay`, leaving `is_borrowing` set and router state inconsistent.
6. Repeat to leak reserve value; also `add_reserve_deficit` records stale caller-supplied amount, under-recording liquidation bad debt.
**How found:** Code review of burn_scaled rounding logic and tracing its return value through execute_repay, repay, and add_reserve_deficit to spot the semantic gap between requested and actual burn amounts.
**Exploitation:** Borrower repays a small amount sized to trigger the dust-cleanup branch, receiving full debt cancellation for less underlying than the debt removed; repeated cycles drain reserve value. Same desync strands phantom borrow positions consuming MAX_USER_RESERVES=15 slots and understates reserve deficits.
**Escalation:** Repeated repay cycles accumulate reserve value leakage; phantom borrow slots exhaust per-user reserve limit; understated deficits let later reserve collection treat shortfall as withdrawable.
**Insight:** When a token's burn/mint function has a rounding or dust-cleanup branch that can change the effective amount, audit every caller for whether it reconciles to the function's return value rather than the requested amount; borrow-flag clearing and deficit accounting derived from pre-burn arithmetic are prime desync spots.
