# xERC4626.sol Some users may not be able to withdraw until rewardsCycleEnd the due to underflow in beforeWithdraw()

xERC4626 caches storedTotalAssets excluding unlocked rewards, so full withdrawals underflow in beforeWithdraw and lock all users' funds until rewardsCycleEnd.

- Payout: Audit contest
- Severity: medium
- Program: Tribe
- Found by: WatchPug
- Disclosed: 2022-07-14
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2022-04-xtribe#m-01
- Library page: http://bugbountylibrary.com/r/c4%3A2022-04-xtribe%3AM-01
- Tags: area:web3 domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** xERC4626.sol ERC4626 reward-streaming vault (beforeWithdraw/syncRewards)
**Root cause:** storedTotalAssets only includes unlocked rewards at cycle end, but beforeWithdraw subtracts the full withdrawal amount (which may include unlocked rewards) from it, causing underflow.
**Steps:**
1. Set rewardsCycleLength = 100 days.
2. Alice deposit() 100 TRIBE.
3. Owner transfers 100 TRIBE rewards and calls syncRewards().
4. 1 day later Alice redeem() all shares: shares worth 101 TRIBE but storedTotalAssets = 100, so `storedTotalAssets -= amount` reverts.
5. Bob deposit() 1 TRIBE; Alice withdraw() 101 TRIBE, storedTotalAssets becomes 0.
6. Bob cannot withdraw even 1 wei since storedTotalAssets is 0.
**How found:** Code review of the cached storedTotalAssets accounting versus totalAssets() including unlocked rewards, then reasoning through a full-withdrawal scenario after syncRewards.
**Exploitation:** Not an attack: a legitimate full withdrawal after rewards sync reverts, and a subsequent withdrawal drains storedTotalAssets to zero, blocking all other depositors from withdrawing until rewardsCycleEnd.
**Insight:** When a vault caches total assets separately from a streaming/unlocked reward balance, check every subtraction site against the cached value for withdrawals that legitimately include unlocked rewards.

