# Emission updates retroactively rewrite unaccrued rewards

K2 Incentives admin setters change emission params without checkpointing the reward index, retroactively rewriting unaccrued rewards and miscrediting users.

- 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-06
- Library page: https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AM-06
- 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 smart contract reward accounting (Incentives contract)
**Root cause:** Admin reward-parameter setters mutate emission state without first checkpointing the current reward index; set_emission_per_second additionally decodes scaled_total_supply as u128 instead of i128, hitting the _ => 0 fallback and skipping the index update.
**Steps:**
1. Call `set_emission_per_second`: contract invokes token via `try_invoke_contract::<u128>` but token returns i128, so decode fails into `_ => 0` and index is not accrued before the rate change.
2. Call `set_distribution_end`: new end time applied to the entire uncheckpointed interval without accruing rewards first.
3. Call `remove_asset_reward`: emission config mutated without checkpointing prior reward index.
4. Observe rewards for elapsed time recomputed at new parameters instead of prior ones.
**How found:** Code review of admin setters noticed the missing checkpoint calls and the u128/i128 type mismatch in the scaled_total_supply invocation causing the fallback branch.
**Insight:** When auditing reward-accrual contracts, check every admin setter that mutates emission/rate/end-time params for a prior index checkpoint, and verify the decoded return type of cross-contract calls matches the callee's actual ABI type—a silent fallback branch can mask a skipped accrual.
