Section 1 of 16

Learn
+5 Lynx

Introduction to Uniswap V2

What You Are Building

You are going to build the actual Uniswap V2 protocol. Not a simplified version. Not a toy. The real thing.

Uniswap V2 is the most forked protocol in DeFi history. SushiSwap, PancakeSwap, and hundreds of other DEXs run this exact architecture. It handles billions of dollars in daily trading volume. When people say "AMM," this is the protocol they're usually talking about.

By the end of this module, you will have written every function in the protocol. You will understand why each line exists, what happens if you remove it, and how the pieces connect. You will have a complete, deployable codebase you can fork for your own project.

The Architecture

Uniswap V2 is 5 contracts split into two layers:

Core (3 contracts, what you build in Part 1):

UniswapV2ERC20 is the LP token. Every pair inherits from this. It is a standard ERC-20 with one addition: permit(), which allows gasless approvals using EIP-2612 signatures. This lets users approve and swap in a single transaction.

UniswapV2Pair is the AMM itself. It holds reserves of two tokens, tracks cumulative prices for the TWAP oracle, and exposes three core functions: mint() to add liquidity, burn() to remove it, and swap() to trade. The constant product invariant (x * y = k) is enforced inside swap() after accounting for the 0.3% fee.

UniswapV2Factory deploys new pairs. It uses CREATE2 to give each pair a deterministic address (computed from the two token addresses). This means the Router can calculate pair addresses without querying the blockchain.

Periphery (2 contracts, what you build in Part 2):

UniswapV2Library contains helper functions: sorting tokens, computing pair addresses, calculating swap amounts with fees, and chaining calculations across multi-hop paths.

UniswapV2Router02 is the user-facing contract. Users never call the Pair directly. The Router handles slippage protection (minimum output amounts), deadlines (prevent stale transactions), multi-hop paths (ETH to DAI through USDC), and WETH wrapping.

How This Module Works

This is not a tutorial. You are replicating a production protocol.

Each section gives you the contract scaffolding: declarations, state variables, events, imports. Your job is to write the function bodies. The logic. The math. The validation. The parts that make the protocol work.

The starter code has TODO blocks where you need to write. Each TODO explains what the function should do, but not how. That's for you to figure out. When you are done, run the tests to verify your implementation matches the actual Uniswap V2 behavior.

If you get stuck, you can reveal the reference implementation. This is the actual Uniswap V2 code, modernized to Solidity 0.8.x. Compare your solution to theirs. Understand the differences.

About the Code

The original Uniswap V2 was written in Solidity 0.5.16 (core) and 0.6.6 (periphery). We have modernized it to Solidity 0.8.20 with these changes:

  • SafeMath removed: Solidity 0.8.x has built-in overflow checking. All .add(), .sub(), .mul() calls are replaced with native +, -, * operators.
  • Type max values: uint(-1) becomes type(uint256).max.
  • Everything else stays the same: The architecture, the math, the invariants, the storage layout. The logic is identical to production Uniswap V2.

The source code is licensed under GPL-3.0, which means you can fork it, modify it, and deploy your own version. That is exactly what hundreds of protocols have done. Now you will understand every line they forked.

What You Will Learn

By building this protocol yourself, you will understand:

  • How the constant product invariant enforces prices without an order book
  • Why LP tokens use the geometric mean (sqrt) for the first deposit
  • How MINIMUM_LIQUIDITY prevents share inflation attacks
  • How the TWAP oracle accumulates prices for manipulation-resistant price feeds
  • Why the K invariant check in swap() accounts for fees using adjusted balances
  • How CREATE2 gives pairs deterministic addresses without querying state
  • How the Router protects users from MEV with slippage and deadline parameters
  • Why fee-on-transfer tokens need special handling

These are not theoretical concepts. They are implementation details that matter when you audit, fork, or build on top of this code.

Verify Your Understanding

What is the core mathematical invariant that Uniswap V2 uses to determine token prices?

Two words. Think about what stays the same after every swap.

Knowledge Check

Answer correctly to earn lynx

Verify your understanding