# Vault portion calculation in `PrizePool::getVaultPortion()` is incorrect as `_startDrawIdInclusive` has been erased

PrizePool.getVaultPortion reads a startDrawId already overwritten in the total accumulator's circular buffer, inflating vault odds and risking claim reverts.

- Payout: Contest reward
- Severity: high
- Program: PoolTogether
- Credited: 0x73696d616f
- Disclosed: 2024-05-10
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2024-05-pooltogether-judging/issues/96
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-05-pooltogether%3AH-1
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:sherlock sev:high tech:solidity technique:incomplete-fix technique:source-review vuln:accounting-error vuln:business-logic vuln:precision-loss

**Target:** PrizePool.getVaultPortion / computeRangeStartDrawIdInclusive (Solidity)
**Root cause:** computeRangeStartDrawIdInclusive computes startDrawIdInclusive = lastAwardedDrawId - rangeSize + 1 where rangeSize can equal grandPrizePeriodDraws (366), landing on a drawId already overwritten in the total accumulator's circular buffer but still present in vault/donation accumulators.
**Steps:**
1. Set grand prize odds so estimated frequency rounds to 366 draws.
2. Advance to lastAwardedDrawId_ == 366 so current open drawId 367 overwrites index 0 (drawId 1) in the total accumulator.
3. Call getVaultPortion: total accumulator spans draws 2..366 (365 days) while vault/donation accumulators still include drawId 1 (366 days).
4. Observe vault portion exceeds total portion; in extreme donation cases totalContributed - totalDonated underflows in getVaultShares.
5. Repro: loop 366 times contribute(100e18); awardDraw(1); mockTwab(...); then contributePrizeTokens(otherVault,0) and claimPrize(msg.sender,0,0).
**How found:** Code reading of computeRangeStartDrawIdInclusive and the circular buffer indexing; noticed total accumulator is written every draw while vault/donation accumulators are sparse, so the same index holds different drawIds across accumulators.
**Exploitation:** Attacker or unlucky state causes vault portion to be computed over a longer window than the total, inflating their share of prizes; a large donation in the erased draw can make totalContributed - totalDonated underflow, permanently reverting claims.
**Escalation:** Repeated buffer wraparound keeps the mismatch persistent; a strategically timed donation in the soon-to-be-erased draw can brick prize claims.
**Insight:** When multiple ring buffers are indexed by the same drawId but written at different frequencies, any window boundary computed from one buffer can silently reference a slot already overwritten in another; check range caps against buffer size and write cadence.
