Section 9 of 16
Core Protocol Complete
Final Build
Submit your complete protocol and run the full test suite.
What You Built
You just wrote the entire Uniswap V2 core protocol. Three contracts, every function, every invariant. This is not a simplified version. This is the code that handles billions of dollars in real trading volume, modernized to Solidity 0.8.x.
Here is everything you implemented across the three contracts:
UniswapV2ERC20 (The LP Token)
| Function | Purpose |
|----------|---------|
| _mint() | Create LP tokens when liquidity is added |
| _burn() | Destroy LP tokens when liquidity is removed |
| _approve() | Set spending allowance |
| _transfer() | Move tokens between addresses |
| approve() | Public allowance setter |
| transfer() | Public token transfer |
| transferFrom() | Transfer with allowance (infinite approval optimization) |
| permit() | EIP-2612 gasless approval via signature |
UniswapV2Pair (The AMM)
| Function | Purpose |
|----------|---------|
| initialize() | Set token addresses (called once by factory) |
| getReserves() | Read packed reserves and timestamp |
| _safeTransfer() | Safe ERC-20 transfer for non-compliant tokens |
| lock modifier | Reentrancy guard |
| _update() | Store reserves and accumulate TWAP prices |
| _mintFee() | Collect protocol fees as LP token dilution |
| mint() | Add liquidity, receive LP tokens |
| burn() | Remove liquidity, receive underlying tokens |
| swap() | Trade tokens with fee-adjusted K invariant check |
UniswapV2Factory (The Deployer)
| Function | Purpose |
|----------|---------|
| createPair() | Deploy pair via CREATE2 with deterministic address |
| setFeeTo() | Set protocol fee recipient |
| setFeeToSetter() | Transfer governance |
Key Concepts You Now Understand
Constant product invariant: x * y >= k after every swap. The fee makes K grow over time.
Storage packing: Three values in one slot (uint112, uint112, uint32) to minimize SLOADs.
TWAP oracle: Cumulative price accumulation using UQ112x112 fixed-point math. Intentional overflow with unchecked blocks.
MINIMUM_LIQUIDITY: 1000 wei permanently locked to prevent share inflation attacks.
Transfer-first pattern: Tokens arrive before the function is called. The function reads balances and computes deltas.
Optimistic transfers: swap() sends tokens out before verifying the invariant. This enables flash loans.
CREATE2: Deterministic pair addresses computed from token addresses and a fixed init code hash.
Protocol fee via LP dilution: Instead of skimming tokens on every swap, the protocol mints LP tokens proportional to the growth in sqrt(k).
The Final Test
The test below covers all core functions across all three contracts. It verifies that your implementation matches the actual Uniswap V2 behavior. Run it to confirm your complete core protocol is correct.
What Comes Next
Part 2 covers the Periphery: the Library (helper math and pair address computation) and the Router (slippage protection, deadlines, multi-hop swaps, WETH wrapping, and fee-on-transfer token support). The core protocol you just built is the engine. The periphery is the user interface that makes it safe to use.