A vending machine that sets its own price
On a traditional exchange — a stock market, or a centralized crypto exchange — prices come from an order book: a list of buyers and sellers, and a trade happens only when someone willing to buy meets someone willing to sell at the same price. That works beautifully when the book is thick with orders, but on a blockchain it is slow and expensive, and an illiquid market simply has no one to trade against.
An automated market maker (AMM) throws the order book away. Instead, anyone deposits a pair of assets into a shared liquidity pool — say, ETH and USDC sitting together in one smart contract — and a fixed formula decides the price. There is no human quoting, no counterparty waiting: the pool itself is the counterparty, and it will always trade with you. This single idea is the engine under Uniswap and most of DeFi.
The constant product: x · y = k
Call the pool's two reserves x (the amount of ETH) and y (the amount of USDC). The constant-product formula is just this rule: every trade must keep their product unchanged.
x * y = k // k is a constant the pool must preserve Reserves before: x = 10 ETH, y = 20,000 USDC k = 10 * 20,000 = 200,000 Spot price of ETH = y / x = 20,000 / 10 = 2,000 USDC per ETH
Geometrically, x·y=k is a hyperbola: a smooth curve the reserves must always sit on. To take ETH out of the pool you must put USDC in, sliding along the curve to a new point where the product is still k. Two consequences fall straight out of the shape. First, the spot price — the price for an infinitesimally small trade — is exactly the ratio y/x, here 2,000 USDC per ETH. Second, the curve approaches but never touches the axes, so the reserves can never hit zero: the pool can't be fully drained, because the last unit of ETH would cost infinitely much.
Working a swap: buying 1 ETH from a 10 ETH / 20,000 USDC pool
A trader wants to buy exactly 1 ETH. They pay USDC; the pool gives ETH. The only question the formula has to answer is: *how much USDC?* We solve it by demanding that k is unchanged after the swap.
- Before the trade: x = 10 ETH, y = 20,000 USDC, so k = 200,000. The spot price is y/x = 2,000 USDC/ETH.
- The trader takes 1 ETH out, so the ETH reserve must fall to x' = 10 − 1 = 9 ETH.
- k must stay 200,000, so the new USDC reserve is y' = k / x' = 200,000 / 9 = 22,222.22 USDC.
- The USDC the trader must deposit is Δy = y' − y = 22,222.22 − 20,000 = 2,222.22 USDC.
- Effective price = 2,222.22 USDC for 1 ETH — about 11.11% above the 2,000 spot price you started from.
It is worth writing the general rule, because every Uniswap-v2-style swap is a special case of it. To buy an amount b of token X by paying token Y, with reserves x and y, the input you owe is `a = y·b / (x − b)`. Check it: y·1/(10−1) = 20,000/9 = 2,222.22. After the trade the pool holds 9 ETH and 22,222.22 USDC, and the new spot price is 22,222.22/9 ≈ 2,469 USDC/ETH — the next ETH out of this pool would cost even more than this one did.
Price impact: why the curve punishes big trades
Price impact is the gap between the spot price you saw and the effective price your own trade actually paid — caused entirely by your trade moving the reserves along the curve. Buying 1 ETH moved the price from 2,000 to an effective 2,222.22, a price impact of (2,222.22 − 2,000)/2,000 = 11.11%. The crucial property of the hyperbola is that this impact grows super-linearly: doubling the trade far more than doubles the damage.
Same pool: x = 10 ETH, y = 20,000 USDC, k = 200,000 General rule: pay a = y*b / (x - b) to buy b ETH Buy 1 ETH: a = 20,000*1 / (10-1) = 2,222.22 USDC -> eff. 2,222/ETH -> impact 11.1% Buy 2 ETH: a = 20,000*2 / (10-2) = 5,000.00 USDC -> eff. 2,500/ETH -> impact 25.0% Buy 5 ETH: a = 20,000*5 / (10-5) = 20,000.0 USDC -> eff. 4,000/ETH -> impact 100.0% Buy 9 ETH: a = 20,000*9 / (10-9) = 180,000 USDC -> eff. 20,000/ETH -> impact 900.0%
This is not a bug; it is the AMM's defence. The same curvature that makes you pay more for a big trade is what protects the pool from being emptied at the old price, and it is what makes the pool's price move when supply and demand shift. The practical lesson: AMMs are wonderful for small trades relative to pool size, and brutal for large ones. A deeper pool (bigger k) flattens the curve locally and shrinks price impact for the same trade — which is exactly why protocols compete for liquidity.
Where the fee fits in
So far the math was fee-free, which is why k stayed exactly constant. In reality a Uniswap v2 pool charges a 0.30% swap fee on the input, and that is how the people who deposited the ETH and USDC get paid. The contract takes the fee out of your input amount before applying the formula: only 99.7% of what you send is used to move along the curve; the other 0.3% stays in the pool as a reward to liquidity providers.
// Uniswap v2 core: exact-output quote, fee = 0.30% (997/1000)
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut)
internal pure returns (uint amountIn)
{
uint numerator = reserveIn * amountOut * 1000;
uint denominator = (reserveOut - amountOut) * 997;
amountIn = (numerator / denominator) + 1; // +1 rounds in the pool's favour
}
// Buy 1 ETH: reserveIn = 20,000 USDC, reserveOut = 10 ETH, amountOut = 1 ETH
// numerator = 20,000 * 1 * 1000 = 20,000,000
// denominator = (10 - 1) * 997 = 8,973
// amountIn = 20,000,000 / 8,973 + 1 ~= 2,229.91 USDCBecause the fee portion is kept in the pool rather than removed, every trade nudges k very slightly upward. Liquidity providers don't get a separate payout — instead the pool they own a share of slowly grows, and their share is worth more when they withdraw. That steady accrual is the reward for parking capital here; the risk that the parked capital is worth less than simply holding the two assets is called impermanent loss, the subject of the next guide.
Slippage vs price impact: two different numbers
People often blur price impact and slippage, but they are distinct. Price impact is deterministic: given the current reserves, your trade's effect on the price is exactly computable before you sign. Slippage is the additional surprise caused by the pool changing between the moment you sign and the moment your transaction executes — because other people's trades land in blocks ahead of yours and move the reserves you were quoting against.
This is why every swap UI asks for a slippage tolerance (commonly 0.5%). Your wallet encodes it as a minimum acceptable output — Uniswap calls it `amountOutMin` — and the contract reverts the whole transaction if the executed price is worse than that floor. You then pay gas for the failed attempt but receive no bad fill. Set the tolerance too tight and your trades keep reverting on a busy day; set it too loose and you invite a sandwich attack, where a bot buys just before you (pushing your price up), lets your trade execute at the worse price, and sells right after — extracting the slack you left in your tolerance.
What x·y=k buys you, and what it costs
The constant-product AMM is a triumph of simplicity. With one equation you get always-on liquidity (the pool never refuses a trade), permissionless market-making (anyone can deposit and earn fees, no licence required), and a fully on-chain price that needs no trusted quoter. Compared with an on-chain order book, it is dramatically cheaper in gas and needs no one actively posting and cancelling quotes.
The costs are equally real, and honesty about them is the point of this rung. The curve gives worse prices for larger trades, so big swaps need deep pools or get sliced up. The AMM has no independent price discovery — it only knows its own reserves, so it relies on arbitrageurs to trade it back in line whenever its price drifts from the broader market, and every such correction is paid for by the liquidity providers (this is the seed of impermanent loss). And spreading one pool's capital across the entire price curve is capital-inefficient: most of it sits at prices that may never trade. The next guides tackle exactly these holes — impermanent loss, then Uniswap v3's concentrated liquidity that fixes the efficiency problem, then lending markets and the MEV that all of this attracts.