Skip to content

UniswapV2 — The Math Behind Automated Market Makers

Posted on:January 18, 2024 at 10:00 AM

Want to explore these formulas interactively?UniswapV2 Interactive Simulator lets you configure reserves, execute trades, and watch contract internals update live in your browser.

UniswapV2 launched in May 2020 and changed DeFi forever. At its core is a formula so elegant it fits on a business card: x · y = k. Yet this three-character equation encodes price discovery, liquidity provision, fee distribution, and arbitrage mechanics all at once.

This post derives the math from scratch, explains every edge case, and builds intuition for what happens at the protocol level every time you swap tokens.

Table of contents

Open Table of contents

The Constant Product Formula

A UniswapV2 pool holds two tokens — call them token X and token Y. At any point in time:

x · y = k

Where:

When you trade, you add tokens of one type and receive tokens of the other type. The key constraint is that k must remain constant (modulo fees — more on that shortly).

A Concrete Example

Imagine a USDC/ETH pool with:

The implicit price of ETH is x/y = 2,000 USDC/ETH. But this is not a fixed price — it moves as trades happen.

Price Impact and Slippage

Suppose you want to buy Δy ETH from the pool by sending Δx USDC. The invariant must hold:

(x + Δx) · (y - Δy) = k

Solving for Δy:

y - Δy = k / (x + Δx)
Δy = y - k / (x + Δx)
Δy = y - (x·y) / (x + Δx)
Δy = y · Δx / (x + Δx)

This is the exact output formula. Let’s plug in numbers: buying ETH by sending 10,000 USDC:

Δy = 500 × 10,000 / (1,000,000 + 10,000)
Δy = 5,000,000 / 1,010,000
Δy ≈ 4.95 ETH

The “naive” price would give you 10,000 / 2,000 = 5 ETH. You actually get 4.95 ETH — the missing 0.05 ETH is price impact, caused by your trade moving the market.

The Price Impact Formula

The price impact percentage for buying Δx worth of X tokens:

Price Impact = Δx / (x + Δx) × 100%

For our example: 10,000 / 1,010,000 = 0.99%

This scales non-linearly. A trade of 100,000 USDC (10% of liquidity) would have ~9% price impact. This is why large trades are fragmented across multiple routes in aggregators like 1inch.

The 0.3% Fee

UniswapV2 charges a 0.3% fee on every swap, paid in the input token. In practice, the protocol applies the fee by only counting 99.7% of the input:

Δx_effective = Δx × 0.997

The actual formula in the contract uses integer arithmetic to avoid floating point:

uint amountInWithFee = amountIn.mul(997);
uint numerator = amountInWithFee.mul(reserveOut);
uint denominator = reserveIn.mul(1000).add(amountInWithFee);
amountOut = numerator / denominator;

This is equivalent to:

Δy = (y · Δx · 997) / (x · 1000 + Δx · 997)

Applying this to our example:

Δy = (500 × 10,000 × 997) / (1,000,000 × 1000 + 10,000 × 997)
Δy = 4,985,000,000 / 1,009,970,000
Δy ≈ 4.936 ETH

So of the “price impact loss” of 0.05 ETH, about 0.015 ETH goes to the fee (0.3% of input ≈ 30 USDC ÷ 2000 ≈ 0.015 ETH). The rest is genuine slippage.

Liquidity Provider Shares

When you add liquidity, you receive LP tokens representing your proportional share of the pool. The pool mints LP tokens at a rate that preserves proportionality:

LP_minted = total_LP_supply × min(Δx/x, Δy/y)

The min() ensures you can’t game the ratio. If the pool has 1M USDC and 500 ETH (ratio 2000:1) and you try to add 10k USDC and 10 ETH (ratio 1000:1), you’d only get credit for the lesser proportion.

Impermanent Loss

Here’s the painful part of LP provision. Suppose ETH doubles from $2,000 to $4,000. Arbitrageurs will buy ETH from the pool until its price matches the market, shifting reserves to a new equilibrium:

x_new · y_new = k
x_new / y_new = 4,000 (new market price)
→ x_new = √(k × 4000) = √(500,000,000 × 4000) ≈ 1,414,213 USDC
→ y_new = √(k / 4000) ≈ 353.55 ETH

Your pool holdings are now worth:

If you had just held: 500 ETH × $4,000 + 1,000,000 = $3,000,000

Impermanent loss = ($3,000,000 - $2,828,427) / $3,000,000 ≈ 5.72%

The general formula for IL given a price ratio change r = P_new/P_old:

IL = 2√r/(1+r) - 1 (always negative — LP value < hold value)
Price changeIL (loss vs holding)
1.25x (25% up)-0.6%
1.5x (50% up)-2.0%
2x (doubled)-5.7%
3x-13.4%
5x-25.5%
10x-42.5%

This is why “impermanent loss” is a misnomer — at extreme price moves, it’s very permanent.

The TWAP Oracle

UniswapV2 introduced an on-chain price oracle using a Time-Weighted Average Price (TWAP). Every block, the contract accumulates:

price0CumulativeLast += reserve1/reserve0 × timeElapsed
price1CumulativeLast += reserve0/reserve1 × timeElapsed

Using fixed-point arithmetic (UQ112×112 format — 112 bits integer, 112 bits fractional). To get the TWAP over a period:

TWAP = (price0Cumulative_t2 - price0Cumulative_t1) / (t2 - t1)

This is resistant to single-block manipulation because an attacker would need to maintain a false price for many blocks (very expensive). Most DeFi protocols that need a price feed use a 30-minute TWAP at minimum.

The Mint and Burn Functions

When you add the very first liquidity (pool creation), there’s a bootstrapping problem — there’s no existing LP supply to calculate proportions from. UniswapV2 solves this with:

initial_LP = √(Δx × Δy) - MINIMUM_LIQUIDITY

Where MINIMUM_LIQUIDITY = 1000 (permanently locked to prevent division-by-zero). The geometric mean ensures the initial LP token value doesn’t depend on the ratio you seed with.

The sync() and skim() Functions

Two safety functions handle cases where the actual token balances drift from recorded reserves (e.g., someone sends tokens directly without using the swap function):

Comparing AMMs: Why x·y=k Works

The constant product formula is just one point in a spectrum of bonding curves:

FormulaCharacteristic
x·y=k (UniswapV2)Infinite price range, always liquid
(x+y)=k (linear)Fixed price, capital efficient but runs out
Stableswap (Curve)Between linear and xy=k, good for pegged pairs
x·y=k with ticks (V3)Concentrated liquidity in ranges

The constant product works precisely because it never reaches zero — you can always trade, but large trades cost exponentially more. This creates natural arbitrage incentives.

What This Means for Developers

If you’re building on top of AMMs — whether for arbitrage, MEV, integrations, or your own DeFi protocol — understanding this math unlocks everything:

The code is simple. The math is beautiful. The emergent behavior — a decentralized, self-regulating market — is genuinely remarkable.

Further Reading