How the AMM Constant Product Formula Works (x*y=k)

How the AMM Constant Product Formula Works (x*y=k)

The first time I swapped on a DEX, I got fewer tokens than the screen promised, and I sat there convinced I’d been scammed. I hadn’t. What I did not understand was how automated market maker AMM constant product formula works — that the number on the screen was never a fixed price, and my own trade had moved it. The constant product formula was quietly doing exactly what it’s built to do.

This is the piece I wish someone had handed me that night. I’ll rebuild the mental model from zero, using one real ETH/USDC pool and arithmetic you can follow on your phone. You’ll see why the price moves, why a big trade gets crushed, and why a deeper pool quotes you a better deal.

Here’s the honest part first: almost everything I assumed about DEX pricing was wrong. So I’ll walk through what I believed, why it broke, and the checks I now run before I press swap. This is the mental model I use, not a trade idea.

What I believed: “the pool looks up the market price”

My first wrong assumption was the biggest one. I pictured a liquidity pool as a little robot that checks Coinbase, sees ETH at $2,000, and hands me ETH at $2,000. A vending machine wired to the outside world.

It isn’t. The pool has no idea what ETH costs anywhere else. It cannot see Coinbase. It cannot read the news. It holds two piles of tokens, and the ratio between those two piles is the price. That’s it.

Take a pool with 10 ETH and 20,000 USDC. The price the pool quotes is just 20,000 divided by 10, which is 2,000 USDC per ETH. Not because a feed told it so. Because that’s the ratio sitting in its reserves right now.

So why does the pool price usually match the real market? Arbitrage. If the pool drifts to 1,900 while exchanges say 2,000, someone buys the cheap ETH from the pool until the ratio climbs back. The formula is blind; arbitrageurs are the eyes. Once I understood that the pool is not reading a price but being dragged toward one, half my confusion disappeared.

If you’ve never watched reserves move in real time, my walkthrough on how to read on-chain data for beginners shows where those two piles actually live on a block explorer.

Diagram of an automated market maker liquidity pool showing two token reserves, with the ratio between them labeled a…

The constant product formula, in plain English

Here’s the whole engine in one line. In a constant product formula market maker, you multiply the two reserves together, and that product must stay the same after every swap.

Written out: x times y equals k, where x is one token’s reserve, y is the other’s, and k is a constant. In our pool, x = 10 ETH, y = 20,000 USDC, so k = 200,000. That number is the invariant. Ignoring fees, every trade has to leave k at 200,000.

The constant product formula (x·y=k), defined: it’s the rule that governs a constant product automated market maker. The product of the two token reserves must stay constant through every swap. Because the pool’s price is simply the ratio of those reserves, forcing the product to stay fixed means any trade that changes the reserves also changes the price — automatically, with no order book and no price feed.

That single constraint does all the work. When you buy ETH, you add USDC to one pile and remove ETH from the other. To keep the product at 200,000, the pool must hand back less ETH than a flat 2,000 price would suggest. The curve, not a fee, is what makes your average price worse as you buy more.

One note before the numbers: I’m ignoring swap fees throughout, so the arithmetic stays clean. Real pools skim a small fee (often 0.3%), which actually nudges k slightly upward over time. That’s a detail, not the mechanism.

What broke: “the quoted price is the price I’ll get”

This is the assumption that cost me that first confusing night. I saw “2,000” and expected 2,000. On a curve, the quote is the price for an infinitely small trade. The moment your trade has size, it moves along the curve, and your realized price drifts.

Let me walk two trades through the same 10 ETH / 20,000 USDC pool so you can see it.

A small buy. I want 0.1 ETH out. ETH reserve drops from 10 to 9.9. To keep k at 200,000, the USDC reserve must climb to 200,000 ÷ 9.9 = 20,202.02. So I pay 202.02 USDC for 0.1 ETH. That’s an effective 2,020 USDC per ETH — about 1% worse than the 2,000 spot. Small trade, small gap. Fine.

A big buy. Now I want 3.333 ETH, a third of the whole pool. ETH reserve falls from 10 to 6.667. USDC must rise to 200,000 ÷ 6.667 = 30,000. So I pay 10,000 USDC for 3.333 ETH — an effective 3,000 USDC per ETH. That’s 50% worse than spot. Same pool, same formula, wildly different price, purely because I moved the reserves hard.

That gap between the quote and what you actually get is price impact. It isn’t a bug, a fee, or a scam. It falls straight out of the curve. Slippage tolerance — the setting your wallet asks about — is just the guardrail that cancels the trade if impact exceeds what you agreed to. For the deeper math behind this, Paradigm’s write-up on price impact is the rigorous version.

The number that changes everything: pool depth

So a big trade gets crushed. Is the fix “trade less”? Sometimes. But the real variable is depth — how much liquidity sits in the pool.

Run the exact same 3.333 ETH buy in a pool ten times deeper: 100 ETH and 200,000 USDC, same 2,000 spot, but k = 20,000,000. Now buying 3.333 ETH barely dents it. I pay 6,896.55 USDC for the same 3.333 ETH — an effective ≈ 2,069 USDC per ETH, only about 3.5% worse than spot.

Same trade. Same formula. One pool charged me 50% over spot; the deeper pool charged 3.5%. Depth was the whole difference. That’s why serious swaps route through the deepest pools they can find, and why thin pools quote scary prices for anything but dust.

When I first measured this on my own trades, the pattern was blunt: my losses had almost nothing to do with timing and almost everything to do with how small the pool was relative to my order. A $200 swap in a deep pool barely registered. The same $200 in a freshly launched token’s thin pool ate a chunk I couldn’t explain — until I did the reserve math and saw the curve had been steep the whole time. The lesson stuck harder than any warning label: check depth first, price second.

Trade Pool depth You pay You get Effective price Worse than spot
Small buy 10 ETH / 20,000 USDC 202.02 USDC 0.1 ETH 2,020 USDC/ETH ~1%
Big buy 10 ETH / 20,000 USDC 10,000 USDC 3.333 ETH 3,000 USDC/ETH 50%
Big buy 100 ETH / 200,000 USDC 6,896.55 USDC 3.333 ETH ~2,069 USDC/ETH ~3.5%

Spot price is 2,000 USDC/ETH in every row. Fees ignored for clarity.

Infographic comparing price impact of the same swap in a shallow versus a deep liquidity pool, showing the constant p…

What I changed: I stopped reading the number, I read the curve

Once I saw those three rows, my old assumptions collapsed one by one. Let me name the ones that broke, because naming them is what fixed my habits.

“Bigger trade, same price per token.” Wrong. On a constant product formula, every additional token you pull out costs more than the last. The marginal price climbs as reserves empty. There is no bulk discount; there’s a bulk penalty.

“Adding liquidity moves the price.” Also wrong, and this one surprised me. When someone deposits at the current ratio — say another 10 ETH and 20,000 USDC — the spot price stays 2,000. What changed is depth. Deposits don’t move the price; they move how hard the next trade has to push to move it. That’s the whole game: liquidity providers change price impact, not spot price.

“k is some magic constant.” No. k is just the product of the reserves, nothing mystical. It holds constant through a swap (fees aside), and it grows when fees accrue or when new liquidity is added. It shrinks when liquidity is withdrawn. It’s a bookkeeping number, not a law of physics.

So now, before I swap, I don’t stare at the headline price. I ask three things: How deep is this pool relative to my trade size? What’s my realized price after impact, not the quote? And is my slippage tolerance set tight enough to bail me out if a bot jumps in front of me? That last one matters because price impact is exactly the crack that MEV bots exploit with sandwich trades around large swaps.

Order book vs AMM: two different ways to quote a price

The clearest way I finally understood AMMs was to hold them next to the thing they replaced: the order book.

On a centralized exchange, a price exists because people posted it. Buyers stack bids, sellers stack asks, and your trade eats through whatever orders are sitting there. If nobody’s selling, there’s no price. A human (or their bot) decided each number.

On an AMM, nobody posts a price. A formula computes one from the reserves, and it’s always willing to trade — at some price, even if that price is terrible for a big order in a thin pool. That’s the trade-off: an order book can be empty; a constant product pool is never empty, but it charges you for depth you don’t have.

Neither is “better.” They fail differently. An order book fails by having no counterparty. An AMM fails by quoting you a brutal price when liquidity is thin. Knowing which failure you’re facing tells you where to trade. And modern routing has blurred the line — intent-based DEXs let solvers compete to find you a better fill across many pools at once.

Uniswap’s own plain-language explainer on automated market makers is a good primary source if you want the concept in the protocol’s own words, and Wikipedia’s entry on the constant function market maker covers the broader family of curves.

Side-by-side diagram contrasting an order book of stacked bids and asks against an AMM constant product formula curve…

Where the simple model stops: v3 and other curves

The x·y=k pool I’ve described is the classic version — Uniswap v2 and its many clones. It’s the cleanest way to learn the mechanism, but it’s not the only curve, and I’d be misleading you to stop there.

Uniswap v3 added concentrated liquidity. Same core idea, but LPs can park their funds inside a narrow price range instead of spreading it across every price from zero to infinity. Inside that range, the pool behaves as if it’s far deeper, so price impact drops for trades near the current price. Same formula spirit, tighter aim.

There are other curves too. Stablecoin-focused pools (like Curve’s) use a flatter equation so two assets meant to trade near 1:1 barely move each other. The constant product formula is the foundation, not the ceiling. But if you understand why x·y=k makes your big trade expensive, every other curve is a variation on that one insight.

One more honest limit: my worked example ignores fees, MEV, and gas. In the real world those all shave your result further. The mechanics I’ve shown are the floor of what you pay, not the whole bill.

FAQ

Does an AMM look up the price from other exchanges? No. The formula never reads an external price. The pool’s price is simply the ratio of its two reserves. When that ratio drifts away from the wider market, arbitrage traders buy or sell until it lines back up. The syncing is external; the quoting is purely internal to the pool.

Why did I get a worse price than the quote when I swapped? Because your own trade moved the price as it executed. The quote assumes a tiny trade; a real-sized order walks along the curve, and each token you pull out costs more than the last. That gap is price impact, and it grows fast in thin pools.

**What does x*y=k actually mean in plain English?** Multiply the two token reserves in a pool and you get a number, k. Every swap has to leave that product unchanged (ignoring fees). Since the price is the ratio of reserves, holding the product fixed forces the price to move whenever the reserves move. That’s the entire pricing rule.

Why do bigger trades get worse prices on Uniswap? Because the constant product formula curves. As you drain one reserve, keeping the product constant means the other reserve rises faster and faster, so your average price climbs. A trade that takes a third of the pool can cost 50% over spot. The deeper the pool, the smaller that penalty.

What is the difference between slippage and price impact? Price impact is the price change caused by your own trade against the curve — it’s predictable from the reserves. Slippage is the extra gap from things moving between quote and execution, like another trade landing first. Slippage tolerance is the setting that cancels your swap if the total gap exceeds your limit.

Does the constant k ever change? Yes, slowly. Within a single swap, k stays constant if you ignore fees. But real pools add a small fee to each trade, which nudges k upward over time. It also grows when liquidity providers deposit more, and shrinks when they withdraw. k is a running total of pool size, not a fixed law.

Does adding more liquidity change the price? No, not the spot price. A deposit made at the current reserve ratio leaves the ratio — and therefore the price — untouched. What it changes is depth: how much the next trade has to push to move the price. More liquidity means smaller price impact for the same trade size.

The reframe

For months I thought a DEX was quoting me a price. It never was. A constant product pool quotes me a curve, and the single number on the screen is just where I’m standing on it before I take a step. Move a little, the number barely shifts. Move a lot in a shallow pool, and I’m the one who moved it.

So the question I ask now isn’t “is this price good?” It’s “how steep is the curve here, and how far am I about to walk on it?” Depth answers that better than any headline number. Read the pool’s size against your trade, and the constant product formula stops feeling like a trick and starts feeling like a map.

Next in Crypto Mental Models, I’ll open a real pool on a block explorer and trace a single live swap — watching the reserves flip and k hold — so you can see the formula move token by token instead of taking my arithmetic on faith.


seonjae — Korean office worker documenting his transition into AI systems, agents, and vibe coding — without a CS background. Shipping in public.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *