> ## Documentation Index
> Fetch the complete documentation index at: https://docs.defiloops.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Slippage is not impact

> Two bounds in basis points that protect against opposite things, and what happens when you send both

`slippageBps` and `maxImpactBps` are both basis points, both make a trade safer,
and both appear on the same request. They are not variants of one idea, and
setting one does not do the other's job.

The short version: **slippage protects you from other people, impact protects
you from yourself.**

Written against `swap-router` at `d88da91`. Every figure below was measured on a
Base fork at blocks 50,807,273 to 50,807,275, minutes apart: the pool moves
between them, which is exactly why each measurement names its block.

## Slippage never changes the trade

The same 50,000 USDC into WETH, quoted twice, at 10 bps and at 50 bps of
slippage:

|                     | slippage 10 bps    | slippage 50 bps    |
| ------------------- | ------------------ | ------------------ |
| block               | 50,807,273         | 50,807,274         |
| `amountIn`          | 50,000.00 USDC     | 50,000.00 USDC     |
| `amountOutAfterFee` | 20.762508 WETH     | 20.762508 WETH     |
| `minAmountOut`      | **20.741745 WETH** | **20.658695 WETH** |
| `priceImpactPips`   | 94 (0.94 bps)      | 94 (0.94 bps)      |

Five times the slippage, and the trade is identical: same input, same output,
same impact. The only number that moved is the floor.

That is the whole of it. `slippageBps` is a statement about **what you will
still accept**, not an instruction about what to trade. It becomes
`minAmountOut`, which the aggregation router enforces on chain, and if the
market has moved past it by the time your transaction mines the swap **reverts**.

<Note>
  The floor is a haircut on `amountOutAfterFee`: the output **after** the
  protocol fee, not before it. A floor computed from the gross figure is one the
  router cannot meet, and it would revert every swap for a reason that reads like
  slippage.
</Note>

## Impact is the cost you cause

Price impact is what your own size does to the pool as it walks the book. It is
already in the quote above: that 50,000 USDC trade moves the price 0.87 bps, and
no slippage setting changes that number: slippage is applied *after* impact has
been paid.

`maxImpactBps` is the bound on it. The service quotes your amount, and if the
impact it reports exceeds the cap it **bisects the offer down** until it fits,
then answers with the smaller trade. You are not refused; you are given less
than you asked for, at a better average price, and told so.

Measured at block 50,807,274 and 50,807,275, offering 450,000 USDC both times:

|                     | slippage 50 only | slippage 50 + `maxImpactBps: 5` |
| ------------------- | ---------------- | ------------------------------- |
| `amountIn`          | 450,000.00 USDC  | **370,343.34 USDC**             |
| `amountOutAfterFee` | 186.745035 WETH  | 153.704969 WETH                 |
| `minAmountOut`      | 185.811310 WETH  | 152.936444 WETH                 |
| impact              | 6.08 bps         | **5.00 bps**                    |
| `boundBy`           | `null`           | `"impact"`                      |

The cap cut the offer to 82.29% of itself and landed the impact at exactly 500
pips, the boundary, found by search rather than by scaling. The answer says so:

```json theme={null}
"amountIn": "370343337637",
"sizedDown": {
  "offeredAmountIn": "450000000000",
  "maxImpactBps": 5,
  "costBps": null,
  "impactBps": 5,
  "impactPips": 500,
  "sizedPctBps": 8229
},
"boundBy": "impact"
```

`sizedDown` is deliberately not folded into `fill`. A limit fill stops at a price
and carries a `sqrtPriceLimitX96` to execute it; this is an ordinary swap of a
smaller amount, and reusing that shape would hand back a price limit nothing
solved for. `amountIn` is **already** the reduced figure, so the quote can be
built and sent as it stands: the block only explains why it is smaller than
what you asked for.

It searches for the **largest** size that fits rather than accepting the first
one that does. Impact is convex: depth is concentrated, so scaling by
`cap / impact` overshoots downward hard. Measured on Base: 3,000,000 USDC capped
at 5 bps came back as 237,675 by that ratio, while the true 5 bps maximum on that
pair was 2,317,948. A tenth of the volume, every step defensible.

## Neither one substitutes for the other

**Slippage does not stop you causing impact.** A trade with 12 bps of impact and
50 bps of slippage sails through. The impact is inside the quote, so the floor is
computed from the already-worsened price. You paid it, and nothing complained.

**A cap does not protect you from time.** `maxImpactBps` is measured at quote
time, on a snapshot. If somebody else moves the market between your quote and
your transaction mining, the cap has nothing to say about it: only
`minAmountOut` stands between you and the new price.

|                        | `slippageBps`                 | `maxImpactBps`                 |
| ---------------------- | ----------------------------- | ------------------------------ |
| protects against       | **other people**, over time   | **your own size**, right now   |
| acts on                | the floor                     | the offer                      |
| changes the trade size | never                         | yes: shrinks it                |
| measured               | after the quote, as a haircut | on the quote's reported impact |
| when breached          | reverts on chain              | quietly trades less            |
| enforced by            | the aggregation router        | the quoting service            |
| reported in            | `minAmountOut`                | `sizedDown`, `boundBy`         |

## Sending both

They compose, and the order is what makes them coherent:

1. **`maxImpactBps` acts first, on the offer.** The bisection settles on a
   smaller amount.
2. **`slippageBps` then prices that amount.** `minAmountOut` is derived from the
   quote of the reduced trade, not of the one you asked for.

So the floor always belongs to the amount that will actually be sent. A floor
derived from a larger offer is one a smaller trade can never clear; that is
`InsufficientOutput`, and it is the failure this ordering exists to prevent.

The same 450,000 USDC offer, capped at 5 bps, priced at two tolerances: block
50,807,275 for both:

|                     | slippage 50 + cap 5 | slippage 5 + cap 5  |
| ------------------- | ------------------- | ------------------- |
| `amountIn`          | 370,343.34 USDC     | 370,343.34 USDC     |
| `amountOutAfterFee` | 153.704969 WETH     | 153.704969 WETH     |
| impact              | 5.00 bps            | 5.00 bps            |
| `minAmountOut`      | 152.936444 WETH     | **153.628117 WETH** |

Identical trades. The cap decided the size and slippage decided nothing but the
floor, which is the whole page in one pair of rows.

<Warning>
  `slippageBps: 5` beside `maxImpactBps: 5` is legal and usually wrong. The two
  fives mean unrelated things; one bounds the size you may trade, the other how
  far the price may move afterwards, and they do not add up to anything. Five bps
  of slippage is a floor five hundredths of a percent below the quote, so almost
  any adverse movement reverts you.

  There is an irony in the pairing, too: the cap makes each trade smaller, so
  filling the size you wanted takes more transactions, each with its own window in
  which a 5 bps move can revert. If you are capping impact because you are trading
  big, `maxImpactBps: 5, slippageBps: 50` is the pairing that expresses "do not let
  me move the market, but do actually land".
</Warning>

`limitRate` with `slippageBps` is a different story and is **refused**: with a
limit the floor *is* the caller's own rate, so a tolerance would be a second and
conflicting guarantee. `slippageBps` with `maxImpactBps` has no such conflict,
which is exactly why it is allowed.

## Read impact in pips, not bps

`priceImpactBps` is truncated. On the trade above it reads **0** while
`priceImpactPips` reads **87**: 0.87 bps.

Comparing a cap against the truncated figure is wrong by up to a whole basis
point, which is 2% of a 50 bps cap and **100% of a 1 bps cap**, and
`maxImpactBps: 1` is precisely the request "fill me at near-zero impact". The
service enforces the cap in pips for that reason. Show pips to anybody who has
to act on the number.

<Note>
  The confusion is not only conceptual. In the service, `max_price_impact_bps` and
  `max_slippage_bps` were adjacent `u32` parameters until they were bundled into a
  struct, because a caller could transpose them and no compiler would notice.
</Note>

## Where `costBps` fits

A third bound, and a third question, see [Bounded execution](/routing).

`costBps` also bounds the size, like `maxImpactBps`, but on a different basis: it
is the **marginal** rate the book is walked to, over direct pools, rather than
the **average** the quote reports over any route. Because a trade stopped at a
marginal rate delivers an average about half as far from spot, `costBps: 25` is
roughly `maxImpactBps: 10`, not 25.

| bound          | the question                                 | who decides the size                |
| -------------- | -------------------------------------------- | ----------------------------------- |
| `slippageBps`  | what will I still accept if the price moves? | nobody: the size is yours           |
| `maxImpactBps` | how much may I move the pool?                | the router, by shrinking your offer |
| `costBps`      | how large a trade does the book take?        | the book, before you choose         |
| `limitRate`    | what price will I accept?                    | the pool, which stops there         |

## Does capping mean trading in pieces?

Capping impact makes each trade smaller, which raises the obvious next question:
if you then send the rest, have you saved anything? Sent immediately, no, and
the per-slice impact figures make it look as though you have.

That question has its own page: [Does splitting cost less?](/splitting).

## In a plan

A `swap.router` step names them as `max_slippage` and `max_impact_bps`, both in
basis points:

```json theme={null}
"Params": {
  "asset_in": "USDC",
  "asset_out": "WETH",
  "max_slippage": "50",
  "max_impact_bps": "5"
}
```

`max_slippage` is required when the step states no price of its own: the
minimum has to come from what the venue would pay, and deriving it from the
input amount is meaningless across two tokens with different decimals. State a
`limit_price` instead and it becomes the floor, at which point `max_slippage`
has nothing left to do.


## Related topics

- [Bounded execution](/routing.md)
- [DeFiLoops](/index.md)
- [Every tool](/tools/reference.md)
- [The catalogue](/adapters/catalogue.md)
- [Does splitting cost less?](/splitting.md)
