# Price band caps apply to decreasing orders, but not to liquidations

Price band caps block users from reducing positions against OracleMaker when its quote drifts outside bands, forcing unavoidable liquidations.

- Payout: Contest reward
- Severity: medium
- Program: Perpetual
- Credited: IllIllI
- Disclosed: 2024-02-19
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2024-02-perpetual-judging/issues/116
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-02-perpetual%3AM-5
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:liquidation

**Target:** ClearingHouse.sol openPosition/liquidate price band checks
**Root cause:** ClearingHouse._openPosition enforces _checkPriceBand on settlement price, but liquidate() has no price band check and no order-gateway authorization. OracleMaker quotes worsen with one-sided flow and can exceed the band while oracle midpoint stays inside it.
**Steps:**
1. Traders repeatedly hit one side of OracleMaker bid/ask, pushing its quote progressively worse
2. OracleMaker quote drifts outside the configured price band while Pyth oracle price remains at midpoint
3. User submits a reduce-only order against OracleMaker to exit before liquidation; `_checkPriceBand` in `_openPosition` reverts the settlement
4. Liquidation path `liquidate()` has no price band check, so liquidator seizes position at oracle midpoint while user could not self-close
**How found:** Code reading: noticed `_checkPriceBand` applied in `_openPosition` but absent in `liquidate()`; reasoned that OracleMaker's spread widens with one-sided flow, so its quote can exit the band even when oracle midpoint is inside, blocking voluntary exits.
**Exploitation:** Not an attacker extraction; a user attempting to reduce exposure before liquidation has orders rejected because OracleMaker's worsened quote exceeds the price band, while liquidators execute freely at oracle price, causing the user to incur liquidation penalty instead of exiting.
**Insight:** When a price-band/limit check guards one settlement path but not another (liquidation), check whether the guarded path's quote source (an AMM-style maker whose price worsens with flow) can drift outside the band while the unguarded path's reference price (oracle midpoint) stays inside — that asymmetry traps users.
