# Missing or wrong slippage guard

Swap or withdrawal where the min-out/max-in bound is absent, miscompared, or bypassed by a later leg

_Area: DeFi accounting and math bugs. Seen in 47 disclosed reports; latest 2026-02-10. Updated 2026-10-23._

## How it works
A swap or withdrawal is meant to guarantee a minimum result for the user. The bug is that the guard is absent, checks the wrong quantity, or checks a quantity that does not reflect what the user actually receives. The transaction succeeds while delivering far less than intended. The broken assumption is that "a limit was passed" equals "the output was bounded." A distinct sub-case is the inverse: a bound set too tight (equal to the full amount) reverts valid transactions because a downstream step truncates the amount [E6](https://bugbountylibrary.com/r/c4%3A2025-11-brix-money%3AM-02.md).

## Where it shows up
- A swap path with no min-out parameter, or a min-out never compared to the received amount.
- A comparison against the input amount instead of the output amount.
- A price bound (e.g. sqrtRatioLimit) treated as slippage protection; it causes partial fills, not a revert [E5](https://bugbountylibrary.com/r/sherlock%3A2023-04-blueberry%3AH-9.md).
- Caller-supplied trade type or amount semantics that flip exact-in to exact-out [E2](https://bugbountylibrary.com/r/sherlock%3A2025-06-notional-exponent%3AH-10.md).
- Guards that bound only one leg, ignoring a second swap leg or shared state [E7](https://bugbountylibrary.com/r/c4%3A2025-08-gte-perps-and-launchpad%3AM-24.md).
- Exact-out paths that check max input but never confirm full output [E8](https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-04.md).
- Same-asset or degenerate inputs that collapse the pricing math [E1](https://bugbountylibrary.com/r/c4%3A2024-02-hydradx%3AH-01.md).
- A guard present in one branch but skipped in a fallback branch [E4](https://bugbountylibrary.com/r/sherlock%3A2023-12-notional-update-5%3AH-1.md).
- A min bound set equal to the amount, ignoring downstream truncation [E6](https://bugbountylibrary.com/r/c4%3A2025-11-brix-money%3AM-02.md).

## How to review
Invariant: for every swap or withdrawal, the amount the user actually receives must be compared to a user-supplied minimum (or the amount paid to a user-supplied maximum), after all legs complete. Checklist:
1. Trace the user's parameter to the final balance delta; confirm the compared variable is the output token, not the input.
2. Confirm every branch (single/multi, exact-in/exact-out, curve+AMM, normal/fallback) enforces the same bound [E4](https://bugbountylibrary.com/r/sherlock%3A2023-12-notional-update-5%3AH-1.md).
3. For multi-leg flows, confirm the bound covers aggregate spend across all legs, not just the first internal call [E7](https://bugbountylibrary.com/r/c4%3A2025-08-gte-perps-and-launchpad%3AM-24.md).
4. For exact-out, require both a max-input check and a full-output assertion [E8](https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-04.md).
5. Reject degenerate inputs (asset_in == asset_out) before pricing [E1](https://bugbountylibrary.com/r/c4%3A2024-02-hydradx%3AH-01.md).
6. Confirm a min bound accounts for any downstream truncation or dust removal, and is not set so tight it forces a revert [E6](https://bugbountylibrary.com/r/c4%3A2025-11-brix-money%3AM-02.md).

## Variants seen
- Same-asset swap collapses reserve math to a 1-unit cost [E1](https://bugbountylibrary.com/r/c4%3A2024-02-hydradx%3AH-01.md).
- Caller-controlled trade type reinterprets the amount field [E2](https://bugbountylibrary.com/r/sherlock%3A2025-06-notional-exponent%3AH-10.md).
- Share price moved by protocol-native flows (loan default), no min-shares guard [E3](https://bugbountylibrary.com/r/sherlock%3A2024-04-teller-finance%3AM-4.md).
- Slippage check skipped in the zero-rate fallback branch [E4](https://bugbountylibrary.com/r/sherlock%3A2023-12-notional-update-5%3AH-1.md).
- Price limit used as slippage guard, leaving partial fill [E5](https://bugbountylibrary.com/r/sherlock%3A2023-04-blueberry%3AH-9.md).
- minAmountLD equals amount, ignoring dust truncation (inverse failure: false revert) [E6](https://bugbountylibrary.com/r/c4%3A2025-11-brix-money%3AM-02.md).
- Slippage checked before a later graduation leg, aggregate spend unbounded [E7](https://bugbountylibrary.com/r/c4%3A2025-08-gte-perps-and-launchpad%3AM-24.md).
- Exact-out partial fill accepted [E8](https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-04.md).

## Why fixes fail
Guards added per branch but not mirrored across modes [E4](https://bugbountylibrary.com/r/sherlock%3A2023-12-notional-update-5%3AH-1.md), and checks placed before a later leg [E7](https://bugbountylibrary.com/r/c4%3A2025-08-gte-perps-and-launchpad%3AM-24.md), leave the aggregate unbounded.

## Impact and severity
Users receive materially less than expected or pay more than their cap; in the same-asset case the pool can be drained for negligible cost [E1](https://bugbountylibrary.com/r/c4%3A2024-02-hydradx%3AH-01.md). Severity is high where loss is direct and repeatable; worse when the guard appears present, since reviewers and users trust it. E3 (share-price manipulation) is an adjacent accounting variant, not a min-out comparison bug.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2024-02-hydradx%3AH-01.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2025-06-notional-exponent%3AH-10.md
- E3: https://bugbountylibrary.com/r/sherlock%3A2024-04-teller-finance%3AM-4.md
- E4: https://bugbountylibrary.com/r/sherlock%3A2023-12-notional-update-5%3AH-1.md
- E5: https://bugbountylibrary.com/r/sherlock%3A2023-04-blueberry%3AH-9.md
- E6: https://bugbountylibrary.com/r/c4%3A2025-11-brix-money%3AM-02.md
- E7: https://bugbountylibrary.com/r/c4%3A2025-08-gte-perps-and-launchpad%3AM-24.md
- E8: https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-04.md
