# Engine uses uncapped debt for executed liquidation

LiquidationEngine computes a capped debt amount but forwards the uncapped user input to the router, letting liquidators exceed the close-factor cap and seize extra collateral bonus.

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

**Target:** LiquidationEngineContract.execute_liquidation / KineticRouterContract.liquidation_call (Soroban/Rust)
**Root cause:** execute_liquidation computes a capped actual_debt_to_cover via calculate_liquidation but discards it and passes the original user-supplied debt_to_cover to kinetic_router.liquidation_call, so the router executes an amount the engine never capped.
**Steps:**
1. Call LiquidationEngineContract.execute_liquidation with debt_to_cover exceeding the close-factor cap.
2. Observe calculate_liquidation returns capped actual_debt_to_cover and records it via add_user_liquidated_this_tx.
3. Observe execute_liquidation forwards the original uncapped debt_to_cover to kinetic_router.liquidation_call.
4. Router validates each call in isolation and executes the uncapped amount, repaying/seizing more than the cap allows.
5. Split calls within one atomic transaction to further exceed the cumulative per-tx close-factor cap.
**How found:** Code review of execute_liquidation vs calculate_liquidation: noticed the capped actual_debt_to_cover is computed and recorded but the original debt_to_cover is what gets forwarded to the router, and that the router only validates each call in isolation.
**Exploitation:** Liquidator submits execute_liquidation with debt_to_cover above the close-factor cap; the router executes the uncapped amount, repaying more debt and seizing more collateral than permitted, capturing extra liquidation bonus from the borrower while engine accounting and LiquidationCall records diverge from actual execution.
**Escalation:** Splitting multiple liquidation calls within a single atomic transaction bypasses the intended cumulative per-transaction close-factor protection.
**Insight:** When a contract computes a capped/sanitized value for accounting but forwards the raw input downstream, check every call site for the sanitized variable; also check whether per-call validation in a downstream contract defeats an upstream cumulative cap when calls can be batched atomically.
