# Reward array index out of bounds

Loop bound or live external length exceeds a locally sized reward array, reverting or overwriting rewards

_Area: DeFi accounting and math bugs. Seen in 4 disclosed reports; latest 2024-07-15. Updated 2026-10-24._

## How it works
A reward array is sized once (at mint, or to a fixed last period), but the loop that indexes it takes its upper bound from a live, growing source: a global epoch counter, `getLatestFinishedPeriod()`, or `extraRewardsLength()` read fresh each call. The array length and the reachable index drift apart. Either the index runs past the end and reverts, or a duplicate key silently overwrites an earlier entry. The broken assumption is that the array's size and the loop's bound stay in sync; nothing enforces it.

## Where it shows up
- Claim/withdraw loops whose end comes from an external counter, indexing a locally sized array [E1](https://bugbountylibrary.com/r/sherlock%3A2024-06-magicsea%3AH-4.md).
- Fixed-length arrays written at mint, while the live length is re-read later [E4](https://bugbountylibrary.com/r/sherlock%3A2023-04-blueberry%3AH-7.md).
- Concatenated lists from multiple sources written into a keyed mapping by assignment, not increment [E3](https://bugbountylibrary.com/r/sherlock%3A2023-11-convergence%3AH-3.md).
- Documented formulas re-implemented with a loop that subtracts the wrong set [E2](https://bugbountylibrary.com/r/c4%3A2021-10-pooltogether%3AH-01.md).

## How to review
For every loop, find the array's declared size and the maximum index reachable. The invariant: max reachable index < array length, for all states the external counter can reach. Check that the loop bound is capped at the array's own last period, not the global one [E1](https://bugbountylibrary.com/r/sherlock%3A2024-06-magicsea%3AH-4.md). Check that any list snapshotted at creation is not later indexed by a live length [E4](https://bugbountylibrary.com/r/sherlock%3A2023-04-blueberry%3AH-7.md). Check that keyed writes sum rather than assign when keys can repeat [E3](https://bugbountylibrary.com/r/sherlock%3A2023-11-convergence%3AH-3.md). Re-derive documented formulas and compare to the code [E2](https://bugbountylibrary.com/r/c4%3A2021-10-pooltogether%3AH-01.md).

## Variants seen
- Unbounded epoch bound vs. array sized to last voting period [E1](https://bugbountylibrary.com/r/sherlock%3A2024-06-magicsea%3AH-4.md).
- Fixed array at mint vs. growing extra-reward list [E4](https://bugbountylibrary.com/r/sherlock%3A2023-04-blueberry%3AH-7.md).
- Duplicate token in concatenated list overwrites prior amount [E3](https://bugbountylibrary.com/r/sherlock%3A2023-11-convergence%3AH-3.md).
- Off-by-many subtraction in a prize-count divisor [E2](https://bugbountylibrary.com/r/c4%3A2021-10-pooltogether%3AH-01.md).

## Impact and severity
High: permanent loss of unclaimed bribes [E1](https://bugbountylibrary.com/r/sherlock%3A2024-06-magicsea%3AH-4.md), lost reward tokens [E3](https://bugbountylibrary.com/r/sherlock%3A2023-11-convergence%3AH-3.md), bricked `pendingRewards` and liquidations [E4](https://bugbountylibrary.com/r/sherlock%3A2023-04-blueberry%3AH-7.md), inflated payouts [E2](https://bugbountylibrary.com/r/c4%3A2021-10-pooltogether%3AH-01.md). Worse when the revert is permanent (no recovery path) or the loss is silent (overwrite, no revert).

## Why fixes fail
No fix evidence in these reports.

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2024-06-magicsea%3AH-4.md
- E2: https://bugbountylibrary.com/r/c4%3A2021-10-pooltogether%3AH-01.md
- E3: https://bugbountylibrary.com/r/sherlock%3A2023-11-convergence%3AH-3.md
- E4: https://bugbountylibrary.com/r/sherlock%3A2023-04-blueberry%3AH-7.md
