How an Automated Market Maker Prices Your Trade

A client sent me a swap receipt last year and asked why the number at the bottom was smaller than the number the screen had quoted thirty seconds earlier. He assumed he had been charged a hidden fee. He had not. He had moved the price himself, and the pool had charged him for it in the only way a pool can.
That is worth understanding properly, because almost every complaint I hear about on-chain trading turns out to be someone discovering the arithmetic after the fact. The tax treatment of a liquidity position is a separate question and I have covered it in DeFi liquidity pool tax in Canada. This is about the mechanism itself.
There is no order book, so nothing is matching you
A conventional exchange holds a book of bids and offers. Your trade executes against someone else’s resting order, and the price you get is the price somebody was willing to accept.
An automated market maker has no counterparty in that sense. It holds two piles of tokens and a rule. The most common rule, and the one worth learning because almost everything else is a variation on it, is the constant product:
x * y = k
x is the quantity of one token in the pool, y is the quantity of the other,
and k is a constant that the swap must not change. Put tokens in on one side,
and the contract hands you back exactly enough from the other side to keep the
product where it was.
The spot price is just the ratio of the two piles, y / x. Nobody sets it. It
is whatever the last trade left behind.
Price impact is the mechanism, not a fee
Say a pool holds 1,000 of token A and 100,000 of token B. Spot price is 100 B per A. You want to sell 10 A.
After your deposit the pool holds 1,010 A. To keep the product constant it must hold 100,000,000 / 1,010, which is 99,009.9 B. So you receive 990.1 B, not the 1,000 B the spot price implied. Your average execution price was 99.01, about 1% worse than the screen quote.
You did not pay a 1% fee. You consumed the top 1% of the curve. And the relationship is entirely determined by how big your trade is relative to the pool, which makes it predictable before you sign anything.
| Trade size vs the pool’s reserve of the token you are selling | Execution price vs spot |
|---|---|
| 0.1% | 0.10% worse |
| 0.5% | 0.50% worse |
| 1% | 0.99% worse |
| 5% | 4.76% worse |
| 10% | 9.09% worse |
| 25% | 20.00% worse |
| 50% | 33.33% worse |
Those figures are derived from the constant product formula above, before any swap fee and assuming nothing else trades against the pool while you wait. They are not a survey of real pools. They are what the curve does.
The practical reading: if your order is a rounding error against the pool, the curve costs you almost nothing. If your order is a visible fraction of the pool, the curve is the dominant cost and no amount of shopping for a low-fee venue will fix it. Depth beats fee rate, every time.
A pool has one honest advantage here. Its reserves are on-chain and anyone can read them, so the depth cannot be manufactured for a screenshot, which is not something you can say about a centralised venue’s reported volume.
The swap fee sits on top
Protocols also skim a fee from the input before the curve is applied, and that fee accrues to the liquidity providers rather than to the protocol treasury in most designs. Rates differ by protocol and increasingly by individual pool, with stable pairs typically set far below volatile ones. Read the pool’s own parameters rather than assuming a house rate.
The order of operations matters for record keeping. The fee comes off the input, then the curve determines the output, so the fee is embedded in your execution price rather than itemised. Reconstructing it later from a wallet export is tedious, which is one more reason to keep contemporaneous records as described in crypto ACB and record keeping.
Slippage tolerance is not the same thing
Price impact is what your own trade does. Slippage is what everyone else’s trades do between the moment you sign and the moment you land in a block.
The slippage tolerance you set is a ceiling: it tells the router to revert the transaction if the output falls below that bound. Set it too tight and your transaction fails while still costing gas. Set it too loose and you have authorised a worse fill than you would ever accept, which is precisely the opening a sandwich attack needs. That trade-off is the subject of MEV and the cost buried in your transaction.
The liquidity provider’s side of the curve
Supplying to a pool sounds like collecting rent. The uncomfortable part is that the same formula that prices trades also rebalances your position against you whenever the price moves.
Because x * y must stay constant, the pool automatically sells whichever
token is rising and buys whichever is falling. When you withdraw you get back a
different mix than you put in, and the value of that mix is below the value of
simply having held the two tokens. The gap is usually called impermanent loss,
which is a bad name: it is only impermanent if the price comes back.
For a constant product pool, the position’s value relative to holding is
2 * sqrt(r) / (1 + r), where r is the ratio of the new price to the price
when you deposited.
| Price change since you deposited | Value vs simply holding |
|---|---|
| 1.1x | 0.11% below |
| 1.25x | 0.62% below |
| 1.5x | 2.02% below |
| 2x | 5.72% below |
| 3x | 13.40% below |
| 5x | 25.46% below |
| 10x | 42.50% below |
Again, arithmetic from the formula, not observed returns. The function is symmetric, so a halving costs the same as a doubling.
What this table is actually for is sizing the fee income you need. Providing liquidity is a bet that accumulated fees exceed divergence loss over your holding period. For a genuinely correlated pair the right column stays small and the bet is reasonable. For a volatile pair against a stablecoin it does not, and a headline yield that ignores the right column is not telling you about the return. I have set out the broader position sizing question in what DeFi actually costs in Canadian tax.
What I would check before signing
The Bank of Canada’s staff work on decentralized finance makes the point that many of the vulnerabilities here mirror familiar ones in traditional finance rather than being novel, and that includes the plumbing that feeds prices into these systems. Its analysis of DeFi oracles is worth reading if you assume the price a protocol uses is the price you see. A thin pool is also a cheap thing to push, which is why a pool used as a price source is an oracle design question rather than a trading one.
Three things, in order:
- The reserve size of the token you are selling. Divide your order by it. That number is your price impact floor before anything else happens.
- Whether a router is splitting your order. Aggregators route across several pools precisely to keep each slice small. A single deep pool and a split across five shallow ones can differ by a lot on the same trade.
- Your slippage bound, set deliberately. The default is a default, not a recommendation.
None of this makes on-chain trading good or bad. It makes it legible, which is more than can be said for a lot of what gets marketed alongside it. The protocol-level questions, admin keys and oracle design and treasury composition, are a separate exercise I have set out in a due diligence checklist for a DeFi protocol, and the Ottawa-specific framing is in the DeFi revolution.
If you are running size through pools and want a second read on what your execution is actually costing you, or on whether a liquidity position has been earning its keep, send me the transaction history and I will work through it.
