# Desynchronization of Cabal’s internal accounting with actual staked INIT amounts leads to over-minting of sxINIT tokens

Cabal's compound_xinit_pool_rewards never syncs internal staked_amounts with real Initia stakes, so unaccounted slashing skews the sxINIT exchange rate and over-mints.

- Payout: Audit contest
- Severity: medium
- Program: Cabal
- Found by: ChainSentry
- Disclosed: 2025-05-28
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2025-04-cabal-liquid-staking-token#m-07
- Library page: https://bugbountylibrary.com/r/c4%3A2025-04-cabal-liquid-staking-token%3AM-07
- Tags: area:web3 domain:web3 impact:funds-loss impact:integrity kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:oracle-manipulation

**Target:** Move staking/reward-compounding module (cabal.move compound_xinit_pool_rewards)
**Root cause:** compound_xinit_pool_rewards adds claimed rewards to m_store.staked_amounts without querying pool_router::get_real_total_stakes, so external reductions like slashing are never reflected in internal accounting.
**Steps:**
1. Note compound_xinit_pool_rewards updates m_store.staked_amounts[pool_index] += rewards_remaining and mints xINIT, never calling get_real_total_stakes.
2. Slashing reduces actual staked INIT (e.g. 1,000,000,000 -> 950,000,000) while staked_amounts stays 1,000,000,000.
3. Rewards of 50,000,000 claimed: staked_amounts becomes 1,050,000,000 but real stake is 1,000,000,000.
4. User stakes 100,000,000 xINIT; exchange rate 1.05 yields 95,238,095 sxINIT instead of 100,000,000.
5. New sxINIT is under-backed by ~4,761,905 INIT, diluting the staker.
**How found:** Code review of compound_xinit_pool_rewards noticed it mutates staked_amounts without calling the available get_real_total_stakes oracle, then reasoned about slashing as an external state change.
**Exploitation:** Passive: attacker waits for a slashing event, then stakes xINIT after reward compounding to receive sxINIT at an inflated exchange rate, capturing value from existing holders; repeated slashings widen the gap.
**Escalation:** Multiple or larger slashing events compound the divergence, worsening dilution and unbonding shortfalls.
**Insight:** When a protocol caches a value that an external system can mutate (slashing, rebasing, validator actions), check every write path for a re-sync call; an unused get_real_* query function is a strong hint the cache can drift.

