Price Impact Is Something You Cause, Not Receive

Impact, slippage, and fees are three different costs that get blamed on each other. How to compute each one and act on the difference.

BoltTx Team··8 min read
solanaprice-impactslippageammtrading-botexecution

A trade fills worse than expected and gets logged as slippage. Some of it was, some of it was the pool fee, and most of it was probably the trade moving the price itself.

★These three costs have different causes and different fixes, and lumping them together means fixing the wrong one.★

The Three Costs

Cost Caused by Fix
★Price impact★ ★Your own size against the reserves★ ★Trade smaller★
★Slippage★ ★Others trading between quote and execution★ ★Land faster★
Pool fee The pool's fee rate Choose a cheaper venue

★Price impact is deterministic.★ Given reserves and a size, it is a known quantity before you submit — it is not uncertainty, it is arithmetic.

★Slippage is the uncertain part★, and it exists only because time passes between your decision and your execution.

Most bots configure a "slippage tolerance" that is silently absorbing all three. That works until the impact component grows large enough to eat the whole tolerance, and then every trade reverts for reasons that look like volatility.

Computing Impact

Impact is the gap between what you receive and what an infinitesimally small trade would receive at the same reserves:

function priceImpact(amountIn: bigint, reserveIn: bigint, reserveOut: bigint, feeBps: bigint) {
  const inAfterFee = amountIn * (10_000n - feeBps) / 10_000n;

  // ★What you actually get.★
  const actualOut = (inAfterFee * reserveOut) / (reserveIn + inAfterFee);

  // ★What you would get at the current price with no size effect.★
  const spotOut = (inAfterFee * reserveOut) / reserveIn;

  return Number(spotOut - actualOut) / Number(spotOut);
}

★Note that the fee is applied in both branches.★ Comparing a fee-adjusted output against a fee-free spot price mixes the pool fee into your impact figure, which is exactly the conflation this article is about.

The result is a pure size effect — the cost of being large relative to the pool, with the fee accounted for separately.

If your impact math is right and transactions still miss, a free BoltTx key is one line to test the submission path.

Setting Slippage From Impact

Once the two are separate, the tolerance follows:

const impact = priceImpact(amountIn, reserveIn, reserveOut, feeBps);

// ★Tolerance covers movement while in flight, NOT your own impact.★
const tolerance = volatilityBuffer;

const expectedOut = amountOut(amountIn, reserveIn, reserveOut, feeBps);
const minOut = expectedOut * BigInt(Math.floor((1 - tolerance) * 10_000)) / 10_000n;

expectedOut already includes your impact, because it was computed from the reserves.★ Adding impact into the tolerance on top of that double-counts it — and produces a minimum so loose that it stops protecting you at all.

The failure this prevents: a bot that sets 5% tolerance because "the pool is thin" is not compensating for impact, it is inviting a 5% worse fill from anyone who trades ahead of it.

Impact Is Asymmetric

The same nominal size costs differently in each direction:

// ★Buying: you deplete the token reserve.★
const buyImpact  = priceImpact(solIn, reserveSol, reserveToken, fee);

// ★Selling: you deplete the SOL reserve — and after your buy, it is thinner.★
const sellImpact = priceImpact(tokenIn, reserveToken, reserveSol, fee);

★A round trip pays impact twice, on a pool your own entry made worse.★ That is the number to size against — not the entry impact alone, which is the one most bots check.

Where the Number Goes Wrong

Stale reserves. Impact computed from reserves several slots old describes a pool that no longer exists. ★Use getAccountInfoAndContext so the reserves and their slot arrive together.★

Wrong pool type. The formula above is constant-product. Concentrated liquidity behaves differently, and applying this arithmetic to it produces a confidently wrong number.

Multi-hop routes. Impact compounds across hops rather than adding. Each leg trades against reserves the previous leg already moved.

Ignoring the fee tier. A pool with a higher fee rate changes the output but not the impact — treating the difference as impact points you at the wrong lever.

Using It as a Filter

★The most valuable application is rejecting trades rather than pricing them.★

const impact = priceImpact(size, reserveIn, reserveOut, feeBps);

if (impact > MAX_IMPACT) {
  const smaller = maxSizeForImpact(reserves, MAX_IMPACT);
  return smaller > MIN_SIZE
    ? { action: "resize", size: smaller }      // ★trade less★
    : { action: "skip" };                      // ★pool too thin for you★
}

A resize is usually better than a skip, because impact grows faster than linearly — halving your size cuts impact by more than half, so a trade that is unattractive at full size can be fine at a fraction of it.

★For an arbitrage bot this filter is the difference between a profitable strategy and one whose edge is consumed by its own execution.★ The opportunity is computed at spot; the fill happens at impact.

What Landing Looks Like

Real transactions through our delivery nodes: median confirmation 336ms — under one slot.

★Impact is fixed at the moment of execution; slippage grows with every slot before it.★ Sizing controls the first, landing speed controls the second, and confusing them means applying the wrong remedy to whichever one is hurting.

Where BoltTx Fits

We handle submission. Impact calculation and sizing stay entirely in your code.

Submissions route through our own delivery nodes in four regions with stake-weighted routing and no public mempool exposure, so a transaction is not observable in transit before it lands — which directly reduces the slippage component, since fewer parties can act on your intent before it executes.

You sign locally. We never hold funds, never sign, and never modify transaction contents, including the minimum output you computed. The tip travels inside the transaction, paid on chain from your own wallet, and reverts with the transaction if it fails, because that is how Solana handles atomic transactions. You pay only on transactions that reach the chain.

Get a free API key. No monthly fee:

const connection = new Connection("https://la.bolttx.io/?api-key=YOUR_KEY");

FAQ

What is price impact on a Solana swap? The gap between what your trade receives and what an infinitesimally small trade would receive at the same reserves. It is caused by your own size, not by the market.

What is the difference between price impact and slippage? Impact is deterministic and caused by your size against the reserves. Slippage is uncertain and caused by others trading between your quote and your execution. Different causes, different fixes.

How do I calculate price impact? Compute the actual output from the reserves, compute the spot output with no size effect, and take the relative difference. Apply the pool fee in both so it does not contaminate the figure.

Should I include impact in my slippage tolerance? No. Your expected output already includes impact if you computed it from the reserves. Adding it again double-counts and produces a minimum output that no longer protects you.

Why does my trade fill worse than the quote? Some combination of impact, slippage, and the pool fee. Separating them is the only way to know whether to trade smaller, land faster, or use a different venue.

Does price impact grow linearly with trade size? No, faster than linearly on constant-product pools. That is why halving your size reduces impact by more than half, and why resizing often beats skipping.

Is impact the same for buying and selling? No. Each direction depletes a different reserve, and your entry makes the exit side thinner. A round trip pays impact twice, on a pool your own trade degraded.

How do I set a maximum acceptable impact? Pick a tolerance for your strategy, then derive the maximum size from the reserves rather than picking a size directly. Every pool then reports its own limit.

Does the pool fee count as price impact? No, they are separate costs. Mixing the fee into your impact figure is the most common calculation error, and it points you at the wrong lever for fixing it.

How does impact work on multi-hop routes? It compounds rather than adds, since each leg trades against reserves the previous leg already moved. Computing it per hop and summing understates the total.

Can I reduce impact by splitting a trade? Not within the same pool and block, since the reserves move as each part executes. Splitting across genuinely different pools does help, because each absorbs a smaller share.

Why does my arbitrage lose money despite a positive spread? Because the spread was computed at spot and the fill happens at impact. Both legs pay it, and for a thin pool that can exceed the edge entirely.

Does concentrated liquidity change the impact formula? Yes. Liquidity sits in ranges rather than across the curve, so constant-product arithmetic gives a confidently wrong answer. Check the pool type first.

How stale can my reserve data be? Only as stale as you can tolerate being wrong. Read the reserves with their context slot so you can measure the staleness rather than assume it.

Should high impact make me skip or resize? Resize first. Because impact grows faster than linearly, a trade unattractive at full size is often fine at a fraction, and a skip forgoes the opportunity entirely.

What is a reasonable impact threshold? Strategy dependent, but the useful discipline is having one at all and deriving size from it, rather than discovering impact after the fill in your P&L.

Back to all posts