# Reward redistribution re-locks claimable tokens

Recomputed rates or reward totals that ignore already-claimed or already-elapsed periods, re-locking vested value

_Area: DeFi accounting and math bugs. Seen in 3 disclosed reports; latest 2025-09-11. Updated 2026-11-01._

## How it works
Accounting code often recomputes a rate or a "rewards received" figure from a formula that subtracts or divides by a term meant to represent what is still outstanding. The assumption that breaks: the formula assumes every path that moves the underlying asset also updates that term. When one path (a refund, an unlist, an early return) skips the update, or divides by remaining periods while ignoring periods already elapsed, the recomputed number is wrong. The result is that value already earned or already claimable gets folded back into future periods, so it is re-locked or inflated rather than paid out.

## Where it shows up
- A balance-derived accounting function overridden with a subtraction term (e.g. `idleETH`) that some transfer paths update and others do not [E1](https://bugbountylibrary.com/r/c4%3A2022-11-stakehouse%3AH-10.md).
- Rate/schedule recomputation on refund or unlist: `(total - claimed) / (steps - stepsClaimed)` [E3](https://bugbountylibrary.com/r/c4%3A2024-12-secondswap%3AM-18.md).
- An accounting variable refreshed only inside a function guarded by an unrelated condition (e.g. `if (rewards == 0) return;`) [E2](https://bugbountylibrary.com/r/c4%3A2025-08-morpheus%3AM-04.md).
- Any early return that sits before a state update other functions depend on [E2](https://bugbountylibrary.com/r/c4%3A2025-08-morpheus%3AM-04.md).
- Asymmetric pairs: a deposit path that decrements a term while the return path does not increment it [E1](https://bugbountylibrary.com/r/c4%3A2022-11-stakehouse%3AH-10.md).

## How to review
For each accounting variable, list every path that moves the underlying asset in or out and confirm the subtracted/added term is updated symmetrically on all of them [E1](https://bugbountylibrary.com/r/c4%3A2022-11-stakehouse%3AH-10.md). For any recomputed rate or schedule, check the denominator and numerator both account for periods already elapsed or amounts already claimed since the last state change; the invariant is that already-claimable value must never decrease when a refund or unlist happens [E3](https://bugbountylibrary.com/r/c4%3A2024-12-secondswap%3AM-18.md). For any variable refreshed inside a conditional, ask whether that condition can become permanently false (post-emission, post-maxEndTime) and whether the variable then goes stale [E2](https://bugbountylibrary.com/r/c4%3A2025-08-morpheus%3AM-04.md).

## How finders spotted it
- Compared the overridden `totalRewardsReceived` formula against `batchDepositETHForStaking` (decrements `idleETH`) versus `bringUnusedETHBackIntoGiantPool` (does not increment it), spotting the asymmetry [E1](https://bugbountylibrary.com/r/c4%3A2022-11-stakehouse%3AH-10.md).
- Read `distributeRewards`, noticed the `if (rewards_ == 0) return;` guard precedes the `lastUnderlyingBalance` update, then reasoned `getPeriodRewards` is permanently zero after `maxEndTime` [E2](https://bugbountylibrary.com/r/c4%3A2025-08-morpheus%3AM-04.md).
- Read the unlist `releaseRate` formula and noticed it divides remaining amount by remaining steps without accounting for steps unlocked/claimed between listing and unlisting [E3](https://bugbountylibrary.com/r/c4%3A2024-12-secondswap%3AM-18.md).

## Variants seen
- Missing increment of a subtracted term on a return path, inflating rewards per share [E1](https://bugbountylibrary.com/r/c4%3A2022-11-stakehouse%3AH-10.md).
- Early return skipping a balance snapshot, permanently blocking yield withdrawal [E2](https://bugbountylibrary.com/r/c4%3A2025-08-morpheus%3AM-04.md).
- Refund redistributed over remaining steps, re-locking already-claimable tokens [E3](https://bugbountylibrary.com/r/c4%3A2024-12-secondswap%3AM-18.md).

## Impact and severity
E1 let an attacker drain roughly 2 ETH from the pool by inflating accumulated rewards per LP share [E1](https://bugbountylibrary.com/r/c4%3A2022-11-stakehouse%3AH-10.md). E2 permanently stuck post-emission yield [E2](https://bugbountylibrary.com/r/c4%3A2025-08-morpheus%3AM-04.md). E3 locked tokens that were already unlocked and claimable [E3](https://bugbountylibrary.com/r/c4%3A2024-12-secondswap%3AM-18.md). Impact rises when the mis-accounting is reachable by any caller and scales with pool balance or locked vesting size.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2022-11-stakehouse%3AH-10.md
- E2: https://bugbountylibrary.com/r/c4%3A2025-08-morpheus%3AM-04.md
- E3: https://bugbountylibrary.com/r/c4%3A2024-12-secondswap%3AM-18.md
