# Stranded surplus on extreme or empty paths

Extreme price limits, empty payloads, or zero-liquidity edges that strand value or block refunds

_Area: DeFi accounting and math bugs. Seen in 2 disclosed reports; latest 2024-02-14. Updated 2026-10-29._

## How it works
A contract moves value along a path that can stop early or be skipped entirely, but its bookkeeping assumes the path always completes. When the path exits early (price limit hit, zero liquidity, empty payload), the value that was not consumed stays in the contract with no code to return or deposit it. The assumption that breaks: "the full amount I sent will be consumed or delivered." Nothing reconciles the difference.

## Where it shows up
- Swap calls with `sqrtPriceLimitX96` set to `TickMath.MAX/MIN_SQRT_RATIO` instead of a slippage bound [E3](https://bugbountylibrary.com/r/c4%3A2023-05-juicebox%3AM-02.md)
- Callbacks that wrap/transfer only the consumed amount and never refund `msg.value` surplus [E3](https://bugbountylibrary.com/r/c4%3A2023-05-juicebox%3AM-02.md)
- Bridge/router helpers that send an empty payload, so the destination receive hook is skipped [E1](https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AH-6.md)
- Third-party CPI calls made in an edge state the callee rejects (e.g. zero liquidity) [E2](https://bugbountylibrary.com/r/c4%3A2023-12-autonolas%3AH-03.md)
- Any branch where a remainder or surplus is computed but not returned

## How to review
Trace every value-moving path to its exit conditions. The invariant: for each call, `value_in == value_consumed + value_refunded_or_deposited`, and this must hold on early-exit and empty-payload paths, not just the happy path. Check:
- Does the swap/callback refund `msg.value` minus actual consumed amount? [E3](https://bugbountylibrary.com/r/c4%3A2023-05-juicebox%3AM-02.md)
- Does the destination hook actually run, or is it skipped by an empty payload? [E1](https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AH-6.md)
- Does the callee accept the edge state your code creates (zero liquidity, zero delta)? [E2](https://bugbountylibrary.com/r/c4%3A2023-12-autonolas%3AH-03.md)
- Is there any code path that returns stranded funds to the user or vault?

## Variants seen
- Extreme price limit halts swap early; surplus ETH stranded with no refund [E3](https://bugbountylibrary.com/r/c4%3A2023-05-juicebox%3AM-02.md)
- Empty payload skips `sgReceive`, bridged ETH lands in contract undeposited and stealable [E1](https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AH-6.md)
- Redundant CPI in zero-liquidity state always reverts, locking last liquidity unit [E2](https://bugbountylibrary.com/r/c4%3A2023-12-autonolas%3AH-03.md)

## Why fixes fail
E2 shows a redundant call added after liquidity already reached zero; the callee's guard rejects it, so the fix itself reverts. E3's callback handles only the consumed amount, so partial fills still strand value.

## Impact and severity
Stranded ETH is often stealable by anyone (E1: all ETH), or permanently locked (E3, E2). Severity is high when stranded value is both large and reachable by an attacker; worse when no refund path exists at all.

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AH-6.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-12-autonolas%3AH-03.md
- E3: https://bugbountylibrary.com/r/c4%3A2023-05-juicebox%3AM-02.md
