# Unvalidated order parameters cause bad debt

Order ids, swap paths and trade sizes accepted without bounds or existence checks before settlement

_Area: DeFi oracles, liquidations and flash loans. Seen in 4 disclosed reports; latest 2025-08-04. Updated 2026-10-23._

## How it works
Order and liquidation code often trusts caller-supplied parameters (order ids, swap paths, trade sizes) and validates only aggregate outcomes or a subset of fields. When a parameter is unbounded or only checked inside a conditional branch, an attacker can pick a value that passes the visible checks while breaking an invariant the code assumed: execution stays within gas limits, an id refers to the intended record, or a trade stays within the position's own balance. The result is deferred settlement at stale prices, orphaned bad-debt records, or positions flipped past zero.

## Where it shows up
- Order creation that accepts a `swapPath` or array without a length cap, validated only for market existence [E1](https://bugbountylibrary.com/r/sherlock%3A2023-02-gmx%3AH-21.md)
- Functions that load a record by user-supplied id and validate identity only inside a conditional branch [E2](https://bugbountylibrary.com/r/c4%3A2024-03-dittoeth%3AM-01.md)
- Liquidation checks that constrain only aggregate metrics (debt decrease, collateral/debt ratio) but not trade size relative to the position's own balance [E3](https://bugbountylibrary.com/r/c4%3A2025-03-starknet-perpetual%3AM-02.md)
- Callbacks or external calls whose success/failure the caller controls, combined with gas-heavy execution [E1](https://bugbountylibrary.com/r/sherlock%3A2023-02-gmx%3AH-21.md)

## How to review
For each caller-supplied parameter, ask: is there an explicit upper bound, and is existence/identity checked unconditionally before any branch? The invariant: every accepted parameter must be bounded and validated on all paths, and settlement must not depend on caller-controlled success. For liquidations, the trade size must be bounded by the liquidated position's own balance, not just by improved risk ratios [E3](https://bugbountylibrary.com/r/c4%3A2025-03-starknet-perpetual%3AM-02.md). For order ids, the identity check must run before, not inside, conditional logic [E2](https://bugbountylibrary.com/r/c4%3A2024-03-dittoeth%3AM-01.md). For paths, cap length so execution cannot approach block gas limits [E1](https://bugbountylibrary.com/r/sherlock%3A2023-02-gmx%3AH-21.md).

## Variants seen
- Unbounded swap path plus gas-heavy callback defers execution to stale prices [E1](https://bugbountylibrary.com/r/sherlock%3A2023-02-gmx%3AH-21.md)
- Id validated only inside a `minShortErc` branch, leaving dust orders uncancelled and bad debt unliquidatable [E2](https://bugbountylibrary.com/r/c4%3A2024-03-dittoeth%3AM-01.md)
- Liquidation over-trades past zero because only TR and TV/TR are checked [E3](https://bugbountylibrary.com/r/c4%3A2025-03-starknet-perpetual%3AM-02.md)

## Impact and severity
Led to stale-price fills, protocol bad debt, and unauthorized position flips. Severity rises when the bad state is persistent (unliquidatable records) or when the attacker controls timing of settlement.

## Why fixes fail
Branch-scoped validation (E2) and aggregate-only checks (E3) leave the underlying parameter unbounded; a fix must bound the parameter itself, not just add another outcome check.

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2023-02-gmx%3AH-21.md
- E2: https://bugbountylibrary.com/r/c4%3A2024-03-dittoeth%3AM-01.md
- E3: https://bugbountylibrary.com/r/c4%3A2025-03-starknet-perpetual%3AM-02.md
