The Constant Product Formula
The concept
Every Uniswap v2–style pool holds two reserves — say ETH and USDC — and enforces one rule on every trade: the product of the two reserves must stay constant. Written as x y = k, where x and y are the reserve balances and k is a constant, this single equation is the entire pricing engine. There is no order book, no market maker quoting prices by hand — the formula is* the market maker. This is the foundational idea you will build on through the rest of this module and the next: everything from slippage to impermanent loss to concentrated liquidity in Uniswap v3 is a refinement of this one curve.
Geometrically, x * y = k traces a hyperbola. A trade moves you along that curve: you add some of one asset to the pool and the contract computes exactly how much of the other asset must leave to keep the product constant. Because the curve is convex, each additional unit of the input asset buys you proportionally less of the output asset than the unit before it — this is the mechanical origin of slippage, which you'll quantify precisely in the next lesson.
The instantaneous price of one asset in terms of the other is simply the ratio of reserves: price(ETH in USDC) = y / x. No external price feed is consulted; the pool's own reserve ratio is its price. This also explains why a pool can never be fully drained — as x approaches zero, the formula demands y approach infinity to keep the product constant, so the price of the scarce asset rises without bound, making the last units economically unreachable.
Strictly speaking, k is not perfectly constant in practice — it increases slightly on every real trade, because the standard 0.3% fee is deducted from the input before the invariant math runs and stays in the pool rather than being paid out to a treasury. This detail matters: it is the entire mechanism by which liquidity providers earn, and you will use it directly in the liquidity-provision lesson later in this module.
The swap output formula, derived algebraically from the invariant with a fee f deducted from the input, is:
dy = (y * dx * (1 - f)) / (x + dx * (1 - f))
where dx is the amount you put in and dy is the amount you receive.
Worked example
Take a 100 ETH / 300,000 USDC pool (so k = 100 * 300,000 = 30,000,000, and the starting price is 3,000 USDC per ETH). A trader swaps in 5 ETH, with the standard 0.3% fee.
x, y = 100, 300_000
fee = 0.003
dx = 5
dx_eff = dx * (1 - fee) # 4.985 ETH after fee
dy = (y * dx_eff) / (x + dx_eff) # USDC out
new_x = x + dx
new_y = y - dy
print(round(dy, 2)) # ≈ 14,251.99 USDC received
print(round(new_y / new_x, 2)) # ≈ 2,826.40 new implied price
The trader receives about 14,252 USDC for 5 ETH — an average execution price of ~2,850 USDC/ETH, noticeably below the 3,000 starting price. The post-trade reserves are ~105 ETH and ~285,748 USDC, so k is preserved (it rises very slightly because the fee stays in the pool rather than being paid out). The new implied price, ~2,826 USDC/ETH, is lower than before the trade — exactly what you'd expect after selling ETH into the pool.
Now run the same pool through a much larger trade — 40 ETH instead of 5 — to see how the curve's convexity bites harder as trade size grows relative to reserves:
dx = 40
dx_eff = dx * (1 - fee)
dy = (y * dx_eff) / (x + dx_eff)
print(round(dy, 2)) # ≈ 85,459.94 USDC received
print(round(dy / dx, 2)) # ≈ 2,136.50 average execution price
Selling 40 ETH (40% of reserves) realizes an average price of only ~2,137 USDC/ETH — a much steeper discount than the 5 ETH trade's ~2,850 average. The absolute amount received does not scale linearly with input size; this nonlinearity is the entire reason sizing matters before you trade.
Try it yourself
Build a simple spreadsheet (or the Python snippet above) modeling this same 100 ETH / 300,000 USDC pool. Run three trade sizes — 1 ETH, 5 ETH, and 20 ETH — through the formula and record the USDC received and the resulting implied price for each. Plot (or just tabulate) the effective price per ETH against trade size. You should see the effective price degrade faster than linearly as trade size grows relative to the 100 ETH reserve — this is the price-impact curve you will formalize mathematically in the next lesson, "Slippage and Price Impact."
Resources
- Uniswap v2 whitepaper — the original constant-product formula derivation (uniswap.org/whitepaper.pdf)
- Uniswap v2 Core docs — "Pair" contract reference and swap formula (docs.uniswap.org/contracts/v2/concepts/protocol-overview/how-uniswap-works)
- Investopedia, "Automated Market Maker (AMM)" — plain-language overview of constant-product mechanics
Recap
x * y = kis the entire pricing mechanism of a constant-product AMM: price is just the reserve ratio, and trades move along a hyperbola.- The swap formula
dy = (y·dx(1-f)) / (x + dx(1-f))tells you exactly how much you receive for any input size, fee included. - Larger trades relative to pool depth get a worse average price — the convexity of the curve is the mathematical root of slippage.
kactually increases slightly with every trade because the fee stays in the pool — the mechanism that funds LP returns.