# Zero-reward early return skips checkpoint

Early return on zero amount or zero reward skips the balance or index checkpoint

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

## How it works
Accounting code often keeps a baseline (last balance, last timestamp, last index) and a derived accumulator (total rewards, activity ratio, reward rate). The baseline is refreshed only on one path, while the accumulator is bumped or recomputed on every entry. When a caller can reach the accumulator update while the baseline refresh is skipped — via a zero amount, an empty array, or a zero-reward early return — the same delta is counted again, or a gap is never measured. The broken assumption is that "nothing to pay" means "nothing to record."

## Where it shows up
- Accumulator updated unconditionally, baseline refreshed inside a `claimable > 0` / `amount > 0` branch [E1](https://bugbountylibrary.com/r/dhl%3A20261008-x7finance.md)
- `if (rewards == 0) return;` placed before a balance or timestamp update [E4](https://bugbountylibrary.com/r/c4%3A2025-08-morpheus%3AM-04.md)
- Permissionless rate setters that recompute `reward / duration` and truncate [E2](https://bugbountylibrary.com/r/sherlock%3A2024-03-zivoe%3AH-5.md)
- Checkpoint or liveness timestamp advanced only when rewards exist [E3](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AM-10.md)
- Caller-supplied arrays or amounts that can be empty or zero

## How to review
For every accounting variable, ask: on which paths is it written, and can any path update the accumulator without updating its baseline? The invariant: any state transition that consumes or recomputes a delta must also advance the baseline it is measured against, including zero-value calls. Check that early returns happen after, not before, checkpoint writes; that division-based rates are not recomputed from a remainder; and that timestamps used in ratios advance on every eligible call, not only paying ones.

## Variants seen
- Empty-array claim re-counts an unaccounted ETH delta into totalRewards, inflating per-token reward [E1](https://bugbountylibrary.com/r/dhl%3A20261008-x7finance.md)
- Zero-amount deposit recomputes rewardRate by integer division, discarding the remainder each call [E2](https://bugbountylibrary.com/r/sherlock%3A2024-03-zivoe%3AH-5.md)
- Zero-reward drought freezes tsCheckpoint, diluting the activity ratio over the unmeasured gap [E3](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AM-10.md)
- Zero-reward early return skips lastUnderlyingBalance, permanently blocking yield withdrawal [E4](https://bugbountylibrary.com/r/c4%3A2025-08-morpheus%3AM-04.md)

## Impact and severity
Ranged from direct fund loss (one NFT draining ~6.78 ETH [E1](https://bugbountylibrary.com/r/dhl%3A20261008-x7finance.md)) and locked staker rewards (654 USDC / 6.6 WBTC [E2](https://bugbountylibrary.com/r/sherlock%3A2024-03-zivoe%3AH-5.md)) to undeserved payouts [E3](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AM-10.md) and permanently stuck yield [E4](https://bugbountylibrary.com/r/c4%3A2025-08-morpheus%3AM-04.md). Severity rises when the trigger is permissionless and repeatable, and when the skipped checkpoint is permanent (post-emission) rather than transient.

## Evidence
- E1: https://bugbountylibrary.com/r/dhl%3A20261008-x7finance.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2024-03-zivoe%3AH-5.md
- E3: https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AM-10.md
- E4: https://bugbountylibrary.com/r/c4%3A2025-08-morpheus%3AM-04.md
