# When stake eth in earningreinvest, the reduction of maxearning may not work

In Goat's earningReinvest, maxEarning reduction is overwritten by shareCommission inside earningWithdraw, letting stakers inflate maxEarning and dilute poolOwner scores.

- 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.3
- Library page: https://bugbountylibrary.com/r/cantina%3Agoat_mar2024%3A3.1.3
- Tags: domain:web3 impact:integrity kind:contest platform:cantina sev:high tech:solidity technique:source-review vuln:business-logic vuln:reward-distribution

**Target:** Solidity staking/earning contract (earningReinvest, earningWithdraw, shareCommission)
**Root cause:** earningReinvest decrements maxEarning before calling earningWithdraw, but earningWithdraw's internal shareCommission recomputes and raises _maxEarningOf from _sharedA, discarding the intended reduction.
**Steps:**
1. Set state: maxEarning=1000, _sharedA=1000, balanceOf=1100, sPercent=10%, fs=1.
2. Call `earningReinvest(true, poolOwner, maxDuration, 1000, ...)`; maxEarning is set to 0.
3. Inside earningWithdraw, `shareCommission(account)` updates _sharedA to 1090 and _maxEarningOf from 0 to 1090.
4. At end of _stake, fs = ((1090-1000)+1000*2%)/1090 = 0.1, reducing poolOwner score to 1/10.
**How found:** Code reading of earningReinvest ordering: noticed earningWithdraw calls shareCommission which calls _updateMaxEarning, overwriting the earlier manual reduction.
**Exploitation:** Attacker stakes ETH earnings via earningReinvest with maxDuration; the pre-withdraw maxEarning decrement is nullified by shareCommission, leaving inflated maxEarning and diluting the poolOwner's score to 1/10.
**Insight:** When a function manually adjusts a value that a callee also recomputes (shareCommission -> _updateMaxEarning), check call ordering: any pre-call mutation is silently discarded.
