Price Impact

Price Impact refers to the change in the price of a token caused by a trade. It is particularly relevant when swapping tokens but is also indirectly connected to adding/removing liquidity.

The Bush appopen in new window calculates and displays Price Impact using different methods depending on the action being taken, and some more detail for each is given below. Both can be reproduced off-chain with the @bush.fi/mathsopen in new window package.

Swaps

Price impact for swaps is calculated using a simple market-based formula that compares the USD value of tokens going in versus tokens coming out:

  1. Compare the USD value of the input token versus the USD value of the output token
  2. priceImpact = 1 - (usdOut / usdIn)
  3. Only consider negative differences (positive differences are treated as 0)
  4. Return the absolute value as a percentage

Note: the calculation is specifically designed for swaps and uses current market prices rather than pool-specific mathematical models. It therefore includes the swap fee and any spread between the pool's price and the market price.

A pool-only alternative, which needs no external prices, is to compare the effective price of the trade with the pool's spot price: quote the swap for the requested amount and for a very small amount with the maths Vault, and take 1 - (amountOut / amountIn) / (spotAmountOut / spotAmountIn).

Adds/Removes

Note: proportional add/remove liquidity operations have zero price impact by design, because they do not move the pool's prices.

For unbalanced and single-token operations, price impact is measured with the ABA method: perform the operation, immediately perform its inverse proportionally, and compare what you end with to what you started with. The difference is the value lost to the pool's price change (and the swap fee charged on the non-proportional portion). Everything needed is in the maths Vault, so it runs entirely off-chain:

import { Vault, AddKind, RemoveKind } from '@bush.fi/maths';

const vault = new Vault();

// A: add the unbalanced amounts, get BPT
const { bptAmountOutRaw } = vault.addLiquidity(
  { pool, maxAmountsInRaw: amountsIn, minBptAmountOutRaw: 0n, kind: AddKind.UNBALANCED },
  poolState,
);

// B: remove that BPT proportionally, get amounts back
const { amountsOutRaw } = vault.removeLiquidity(
  { pool, minAmountsOutRaw: amountsIn.map(() => 0n), maxBptAmountInRaw: bptAmountOutRaw, kind: RemoveKind.PROPORTIONAL },
  poolState, // initial state: the two legs are evaluated independently
);

// A - B: what was lost, per token. The amounts back are proportional, so the loss is
// concentrated in the tokens that were over-supplied; value it (e.g. in the pool's own
// spot prices or in USD) to express it as a percentage of the value added.
const deltas = amountsIn.map((a, i) => a - amountsOutRaw[i]);

The same approach applies to removes (remove single-token, then add the amounts back proportionally) and, step by step, to nested and boosted pools. Because both legs are exact reproductions of the Vault's maths, the result matches what the contracts would charge.

Where price impact comes from

In a Bush pool three things move the price against a trader:

  • Swap fee - charged on every swap and on the non-proportional part of adds/removes. See Swap Fees.
  • Curvature of the invariant - the pool's maths (weighted, stable, ...) prices each marginal unit worse than the last. Deeper pools and stable-math pools have less of it.
  • Dynamic fee hooks - a hook such as StableSurge raises the fee for trades that unbalance the pool.