Section 11 of 16
Library: Helpers and Math
What You Are Building
UniswapV2Library is a stateless library that provides the mathematical foundation the Router depends on. Every swap amount calculation, every pair address lookup, every reserve fetch goes through this library.
The library contains eight functions, each building on the previous ones. By the end of this section you will have implemented all the math that powers Uniswap V2 trading.
Token Sorting
Uniswap V2 always stores tokens in ascending address order. Token0 is the token with the smaller address. This is not arbitrary. It ensures that for any pair of tokens, there is exactly one canonical ordering. Without this, you could create two pairs for the same token combination.
sortTokens takes two addresses, validates they are different and non-zero, then returns them in ascending order. Every other function in the library calls this first.
CREATE2 Address Calculation
pairFor computes the address of a pair contract without making any external calls. This is possible because the Factory uses CREATE2 to deploy pairs. The CREATE2 address formula is:
address = keccak256(0xff ++ factory ++ salt ++ init_code_hash)[12:]
The salt is the keccak256 hash of the two sorted token addresses packed together. The init code hash is a constant that depends on the pair contract's bytecode. Since the bytecode never changes, the hash never changes.
This means anyone can compute where a pair lives (or will live) without querying the blockchain. The Router uses this to find pairs instantly.
Reserve Fetching
getReserves calls the pair's getReserves() function and returns the reserves sorted to match the input token order. This is important because the pair always stores reserves as (reserve0, reserve1) based on its internal token ordering, but callers might pass tokens in any order.
The Quote Function
quote calculates the proportional amount of tokenB given an amount of tokenA and the current reserves. The formula is:
amountB = amountA * reserveB / reserveA
This is used when adding liquidity to determine how much of the second token matches a given amount of the first token at the current price ratio.
Swap Amount Calculations
The core of Uniswap V2 math lives in getAmountOut and getAmountIn.
getAmountOut: Given an exact input amount, how much output do you receive? The 0.3% fee is applied to the input:
amountInWithFee = amountIn * 997
numerator = amountInWithFee * reserveOut
denominator = reserveIn * 1000 + amountInWithFee
amountOut = numerator / denominator
The 997/1000 ratio implements the 0.3% fee. The fee stays in the pool, increasing the reserves and the value of LP positions.
getAmountIn: Given a desired output amount, how much input do you need? This is the inverse:
numerator = reserveIn * amountOut * 1000
denominator = (reserveOut - amountOut) * 997
amountIn = numerator / denominator + 1
The + 1 rounds up to ensure the pool always receives enough input. Without rounding up, precision loss could leave the pool with slightly less than expected.
Path Chaining
getAmountsOut and getAmountsIn chain the single-hop calculations across multi-hop paths. For a path [WETH, USDC, DAI]:
getAmountsOut starts with the input amount and calculates each hop forward: WETH amount in, USDC amount out (which becomes the next input), DAI amount out.
getAmountsIn starts with the desired output and calculates each hop backward: DAI amount out, USDC amount in (which becomes the next output), WETH amount in.
Your Task
Implement all eight functions in UniswapV2Library. The starter code gives you the library declaration and the INIT_CODE_HASH constant placeholder. You write everything else.