# When the poolowner gets shared earnings, the power of that pool becomes stale

Goat's pool power factor fs is only recalculated on stake/withdraw, so shared earnings credited to a pool owner leave fs stale and reward distribution incorrect.

- Payout: Contest reward
- Severity: high
- Program: Goat
- Credited: cccz
- Disclosed: 2024-06-12
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_goat_mar2024.pdf#3.1.6
- Library page: https://bugbountylibrary.com/r/cantina%3Agoat_mar2024%3A3.1.6
- Tags: domain:web3 impact:integrity kind:contest platform:cantina sev:high tech:solidity technique:source-review vuln:business-logic vuln:reward-distribution

**Target:** Staking pool power/fs accounting contract (_reCalFs, shareCommission)
**Root cause:** fs = balanceOf/maxEarningOf is recomputed only during stake/withdraw in the pool, but shareCommission changes both balanceOf and maxEarningOf of the pool owner without triggering _reCalFs, leaving fs stale.
**Steps:**
1. Observe _reCalFs computes fs from _eEarning.balanceOf(account_) + defenderEarningFreezedOf and _eEarning.maxEarningOf(account_).
2. Note shareCommission transfers sponsor share and calls _updateMaxEarning when _sharedA exceeds _maxEarningOf, changing both numerator and denominator.
3. Set state: balanceOf(A)=100, maxEarningOf(A)=200, fsA=0.5.
4. A receives 50 shared earnings; correct fsA should be 150/200=0.75.
5. Since _reCalFs only runs on stake/withdraw in PoolA, fsA stays 0.5, making pool power stale and reward distribution wrong.
**How found:** Code reading of _reCalFs and shareCommission revealed that shared earnings mutate balanceOf and maxEarningOf without any fs recalculation trigger, only stake/withdraw paths update fs.
**Insight:** When a ratio metric is cached and recomputed only on user-initiated actions, audit every other code path that mutates its inputs (here balance and max earning) for a missing recompute; commission/reward crediting is a classic gap.
