An automated market maker (AMM) like Uniswap sets prices with a formula instead of an order book. A pool holds two tokens, and in the classic design the product of the two balances must stay constant: x * y = k. The price is simply the ratio of the balances, and every trade shifts that ratio, so the price moves as you buy or sell. Arbitrage traders then keep the pool's price close to prices elsewhere.
Why not just use an order book?
Traditional exchanges match buyers and sellers through an order book, a list of bids and offers. Running one fully on-chain is costly on Ethereum. Every new order, change and cancellation is a transaction that costs gas, and market makers need to update quotes constantly.
An AMM removes the need for anyone to post quotes. Liquidity providers (LPs) deposit both tokens into a smart contract called a liquidity pool. Traders swap against the pool directly, and the contract works out the price from its own balances. It is always open, and anyone can trade against it or add liquidity.
The constant product formula
Uniswap v2, and the original idea behind v1, uses the constant product rule. If a pool holds x units of token A and y units of token B:
x * y = k
A trade must leave the product k unchanged, ignoring fees. The spot price, the price for a tiny trade, is the ratio of the reserves:
price of A (in B) = y / x
When you add token B and remove token A, x goes down and y goes up, so A gets more expensive. The curve never runs out: as one balance approaches zero, its price rises toward infinity.
A worked example
Take an ETH/USDC pool with 100 ETH and 300,000 USDC.
k = 100 * 300,000 = 30,000,000- Spot price of ETH = 300,000 / 100 = 3,000 USDC
Now a trader wants to buy 10 ETH. After the trade the pool will have 90 ETH, so the USDC balance must satisfy 90 * y = 30,000,000:
- New USDC balance = 333,333.33
- USDC the trader pays = 333,333.33 − 300,000 = 33,333.33 (before fees)
- Average price paid = 3,333.33 per ETH
- New spot price = 333,333.33 / 90 = about 3,703.70 USDC
The trader paid more than the starting price of 3,000. That gap is price impact, and it grows with the size of the trade relative to the pool. A 10 ETH trade in a 100 ETH pool moves the price a lot. The same trade in a 10,000 ETH pool would barely move it. This is why deep liquidity matters.
Fees
Every swap pays a fee to LPs. In Uniswap v2 it is 0.3% of the input amount. The fee is taken before the constant product check, so k grows slightly with each trade and LPs earn a share of that growth.
For selling an amount dx of token A into the pool, the output of token B is:
dy = (y * dx * (1 - f)) / (x + dx * (1 - f))
where f is the fee rate, for example 0.003. In the example above, with a 0.3% fee, buying 10 ETH would cost about 33,433.63 USDC instead of 33,333.33.
How arbitrage keeps prices honest
The pool does not know the "real" price of ETH. It only knows its own balances. So what stops it drifting away from the wider market?
Arbitrage. Suppose ETH trades at 3,100 on other exchanges while the pool says 3,000. A trader buys cheap ETH from the pool and sells it elsewhere. Each purchase removes ETH from the pool and raises its price. The trader keeps going until the pool's price is close to 3,100, minus fees and gas, at which point there is no more profit.
This means:
- The pool follows the market because arbitrage traders are paid to move it.
- When the price moves, arbitrage traders profit at the expense of LPs, who effectively sold at the old price.
- Small gaps smaller than fees plus gas can persist, so pool prices sit within a band around the market price.
Impermanent loss
Because the pool keeps rebalancing, LPs end up holding more of the token that fell and less of the one that rose. Compared with simply holding the two tokens, this is a loss called impermanent loss. It is "impermanent" only because it disappears if prices return to where they were when the LP deposited.
For a 50/50 constant product pool, if the price ratio changes by a factor r:
impermanent loss = 2 * sqrt(r) / (1 + r) - 1
| Price change | Loss vs. holding |
|---|---|
| 1.25x or 0.8x | about 0.6% |
| 1.5x | about 2.0% |
| 2x or 0.5x | about 5.7% |
| 4x or 0.25x | 20% |
Trading fees are meant to compensate LPs for this. Whether they do depends on volume, volatility and fee tier.
Uniswap v3: concentrated liquidity
In v2, liquidity is spread across every possible price from zero to infinity. Most of it sits at prices that are never reached, so it earns little.
Uniswap v3, launched in 2021, introduced concentrated liquidity. Each LP chooses a price range, such as 2,500 to 3,500 USDC per ETH. Within that range, their capital acts like a much larger v2 position, which means deeper liquidity and lower price impact for traders.
Key changes:
- The price range is split into small steps called ticks. Liquidity is active only while the current price is inside an LP's range.
- If the price leaves the range, the position turns entirely into one token and stops earning fees until the price returns.
- Pools come in multiple fee tiers. Common ones are 0.05% for closely correlated pairs, 0.3% for most pairs, and 1% for exotic pairs, with a lower tier added later for stablecoin pairs.
- Positions are unique, so v3 represents them as NFTs rather than fungible LP tokens.
The price still follows the same constant product logic inside each tick range. Concentration makes LPs more capital efficient, but it also amplifies impermanent loss when the price moves through their range.
Uniswap v4: hooks
Uniswap v4, launched in early 2025, keeps concentrated liquidity and puts all pools inside a single contract to cut gas costs. Its main addition is hooks: custom contracts that pool creators can attach to run logic before or after swaps and liquidity changes. Hooks can enable features like dynamic fees or on-chain limit orders. They also add risk, because a pool is only as safe as its hook code.
Risks for traders
- Slippage. The price can move between when you submit a trade and when it executes. Wallets let you set a slippage tolerance, the most you are willing to accept, and the trade fails if the price moves further.
- Sandwich attacks. A bot sees your pending trade, buys just before you to push the price up, then sells right after. A wide slippage tolerance makes this easier. Using private transaction relays or tight tolerances reduces the risk.
- Thin pools. Low liquidity means large price impact and easier manipulation.
- Using spot price as an oracle. A pool's instant price can be pushed around within a single transaction. Protocols that need a price feed should use time-weighted averages or dedicated oracles, not the current pool ratio.
Key takeaways
- An AMM prices assets with a formula based on its own reserves, not an order book.
- In a constant product pool,
x * y = kand the spot price is the ratio of reserves. - Larger trades relative to pool size cause more price impact.
- Arbitrage traders keep pool prices in line with the wider market, and LPs bear the cost as impermanent loss.
- Uniswap v3 concentrates liquidity into price ranges; v4 adds a single contract and hooks.
- Traders should watch slippage settings and pool depth to avoid poor fills and sandwich attacks.
Get the weekly commit
New blockchain deep dives every week.

