# Constraint checked against wrong quantity

Limit checks comparing a bound to another bound or a recomputed value, not the executed quantity

_Area: Smart contract access control and control flow. Seen in 3 disclosed reports; latest 2023-09-26. Updated 2026-10-23._

## How it works
A user sets a bound (max items to sell, max price, max slippage). The code then checks that bound against something other than the quantity it actually executes: the counterparty's bound, a value recomputed after state change, or a helper's narrower domain. The bound is never enforced against the real executed value, so the trade can exceed what the user authorized.

## Where it shows up
- Matching engines validating min/max constraints per party.
- Order fills where a constructed item count is derived separately from the constraint check.
- Slippage/limit requires reading a market field (e.g. last implied rate) rather than the price used to execute.
- Helper functions with their own input range (e.g. `_indexOf` reverting above MAX_PRICE) called with values from a wider domain (referencePrice up to 50x MAX_PRICE).
- Any `require` whose left side is a stored bound or post-mutation value rather than the computed execution amount.

## How to review
For each limit check, identify the exact value the user bounded and the exact value the protocol executes, and confirm the comparison is between those two. The invariant: `executedQuantity <= userBound` (and for slippage, `executedRate <= rateLimit`), where executedQuantity/executedRate are the same variables used to move assets or price the trade. Trace every caller's input domain against any helper's accepted range; a helper that reverts on out-of-range input must not receive values the caller can legitimately produce.

## Variants seen
- Bound-vs-bound: `areNumItemsValid` compares buy.constraints[0] <= sell.constraints[0] instead of numConstructedItems <= sell.constraints[0], letting matchOrders sell more NFTs than authorized [E1](https://bugbountylibrary.com/r/c4%3A2022-06-infinity%3AH-10.md).
- Post-trade recomputation: slippage check compares rateLimit to market.lastImpliedRate (post-trade) instead of postFeeInterestRate actually used to price [E3](https://bugbountylibrary.com/r/sherlock%3A2023-03-notional%3AM-8.md).
- Domain mismatch: settlement calls `_indexOf(auctionPrice)` which reverts above MAX_PRICE, but auctionPrice derives from referencePrice bounded by MAX_INFLATED_PRICE (50x), blocking settlement [E2](https://bugbountylibrary.com/r/sherlock%3A2023-09-ajna%3AM-5.md).

## Impact and severity
E1: sellers lose NFTs beyond their authorization (high). E3: trades execute beyond the user's slippage limit (medium). E2: auction settlement reverts, temporarily blocking settlement and harming the borrower (medium). Severity rises when the wrong comparison silently permits asset loss rather than a revert; reverts are noisy, over-fills are not.

## Why fixes fail
Not shown in evidence.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2022-06-infinity%3AH-10.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2023-09-ajna%3AM-5.md
- E3: https://bugbountylibrary.com/r/sherlock%3A2023-03-notional%3AM-8.md
