# If pool owner withdraws 100% of earnings, poolusers will be permanently blocked from withdrawing staked funds

Pool owner withdrawing 100% of earnings zeroes Fs, making calDuration return 0 and lockWithdraw revert on division by zero, permanently locking users' staked ETH.

- Payout: Contest reward
- Severity: high
- Program: Goat
- Credited: Spearmint
- Disclosed: 2024-06-12
- Write-up quality: 7/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_goat_mar2024.pdf#3.1.11
- Library page: https://bugbountylibrary.com/r/cantina%3Agoat_mar2024%3A3.1.11
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:cantina sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:dos

**Target:** Locker.sol / Earning.sol staking and withdrawal contracts
**Root cause:** calFs returns 0 when earningBalance_ is 0, which propagates into calDuration producing duration=0; _withdraw then computes total * pastTime / duration and reverts on division by zero.
**Steps:**
1. Pool owner John calls `controller.ethStake{value: 10 ether}(...)` creating a pool.
2. Alice and Eve stake 100 ether each into John's pool via `controller.ethStake{value: 100 ether}(payable(John), ...)`.
3. Skip 30 days; John calls `controller.earningWithdraw(true, earning.earningOf(John), payable(John), 1)` withdrawing 100% of earnings, setting earningBalance_=0 and Fs=0.
4. Alice calls `locker.approveAdmin(address(controller))` then `controller.lockWithdraw(true, payable(John), AliceStakedWstethAmount, payable(Alice), false, 1)`.
5. Transaction reverts with `panic: division or modulo by zero (0x12)` because calDuration returns 0 and _withdraw divides by duration.
**How found:** Code reading of calFs/calDuration/_withdraw revealed that earningBalance_=0 yields Fs=0 and duration=0, and the division in _withdraw would panic; confirmed with a Foundry fork test on Arbitrum Sepolia.
**Exploitation:** Any pool owner withdraws all accrued earnings; Fs becomes 0; every subsequent lockWithdraw by pool users reverts on division by zero, permanently trapping their staked ETH while the owner keeps their own stake.
**Insight:** When a scaling factor feeds a divisor, trace the zero-value branch: here calFs's max==0 guard returns DEMI but the owner path (2*DEMI - fs) collapses to 0, so check both branches of factor computations for zero divisors.
