# Incentives silently skip reward checkpointing by querying scaled_total_supply() with the wrong ABI type

Incentives contract queries scaled_total_supply() as u128 while tokens return i128, silently collapsing supply to 0 and skipping reward checkpoints.

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

**Target:** Soroban incentives contract cross-contract call to a-token/debt-token
**Root cause:** Incentives contract decodes scaled_total_supply() as u128 but token contracts return i128; the failed decode falls into a `_ => 0` branch, zeroing total_supply in reward checkpointing paths.
**Steps:**
1. Call `try_invoke_contract::<u128, IncentivesError>(..., "scaled_total_supply", ...)` against real a-token WASM
2. Observe result is not Ok(Ok(_)) because actual return type is i128
3. Fallback `_ => 0` sets total_supply = 0
4. In claim_all_rewards(), global index update is skipped; user receives only previously materialized rewards
5. In set_emission_per_second(), old interval not checkpointed; next handle_action() reprices skipped interval at new rate
**How found:** Code review of cross-contract call return types: noticed incentives assumes u128 while a-token/debt-token declare i128, then confirmed via PoC on real WASM that the decode fails and hits the `_ => 0` fallback.
**Exploitation:** No attacker action; the bug triggers on normal claim_all_rewards() and set_emission_per_second() calls, causing underpayment of the latest interval and retroactive mispricing after emission changes.
**Insight:** When auditing cross-contract calls in Soroban/Rust, diff the declared return type in the callee against the generic type parameter in try_invoke_contract; silent `_ => 0` fallbacks on decode failure turn type mismatches into accounting bugs.
