# Surplus tracked apart from reserves

Separate surplus counters disbursed without reconciling against reserves or shadow-contract storage

_Area: DeFi accounting and math bugs. Seen in 2 disclosed reports; one confirmed bounty: $2,000,042; latest 2026-06-07. Updated 2026-10-30._

## How it works
A contract keeps a second ledger for value it holds — a "surplus" counter, a shadow ERC-20 balance, a per-pool exposure — that is supposed to mirror the real reserves. The assumption that breaks is that the two ledgers stay in sync. When a code path updates one and not the other, or disburses from the surplus without checking it against what was actually contributed, the counter can be inflated or drained independently of the real balance. The invariant "surplus never exceeds reconciled reserves" is never enforced, so value can be minted or paid out that was never deposited.

## Where it shows up
- Deposit/disburse command pairs for native tokens held in a counter separate from pool reserves [E2](https://bugbountylibrary.com/r/dhl%3A20260607-ambientcrocswapdex.md).
- Forked clients that redirect balance writes to a shadow contract (e.g. `UsingOVM`), where some opcode handlers still mutate the native balance directly [E1](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-optimism-infinite-money-duplication-bugfix-review.md).
- Aggregation code that clamps signed exposures with `Math.max(_,0)` per item, with some components added inside the loop and others after [E3](https://bugbountylibrary.com/r/c4%3A2025-06-panoptic-hypovault%3AH-02.md).
- Any place a payout reads a stored counter rather than recomputing from reserves.

## How to review
For every surplus/shadow counter, find every write and every read. The property that must hold: after any sequence of operations, the disbursable surplus equals (or is bounded by) the reconciled reserve balance, and every balance-mutating path — including opcode handlers and command dispatchers — routes through the same redirect. For aggregation, check that all signed components are summed before any floor-at-zero clamp, not clamped individually [E3](https://bugbountylibrary.com/r/c4%3A2025-06-panoptic-hypovault%3AH-02.md).

## Variants seen
- Shadow-contract redirect missed in one opcode path, so native balance never cleared [E1](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-optimism-infinite-money-duplication-bugfix-review.md).
- Surplus counter inflated by tick-walking plus narrow-range mint/harvest, then disbursed beyond contribution [E2](https://bugbountylibrary.com/r/dhl%3A20260607-ambientcrocswapdex.md).
- Asymmetric clamping of signed exposures producing inconsistent NAV [E3](https://bugbountylibrary.com/r/c4%3A2025-06-panoptic-hypovault%3AH-02.md).

## Impact and severity
Led to unlimited minting of a native token [E1](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-optimism-infinite-money-duplication-bugfix-review.md) and direct drainage of ~67.85 ETH [E2](https://bugbountylibrary.com/r/dhl%3A20260607-ambientcrocswapdex.md); NAV misreporting in [E3](https://bugbountylibrary.com/r/c4%3A2025-06-panoptic-hypovault%3AH-02.md). Severity is high because the flaw is reachable by ordinary user operations and the loss is the full surplus. It worsens when the counter is user-triggerable and no reconciliation check gates disbursement.

## Why fixes fail
Partial redirects are the trap: fixing the common path but leaving one handler (SELFDESTRUCT, a rare command) mutating state directly reopens the gap [E1](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-optimism-infinite-money-duplication-bugfix-review.md).

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-optimism-infinite-money-duplication-bugfix-review.md
- E2: https://bugbountylibrary.com/r/dhl%3A20260607-ambientcrocswapdex.md
- E3: https://bugbountylibrary.com/r/c4%3A2025-06-panoptic-hypovault%3AH-02.md
