🌱
Dev Compendium
  • Ethereum
    • Solidity
      • EVM
      • Architecture
      • Execution Context
      • Transactions
      • Gas
      • Calldata, Memory & Storage
      • Gas Optimisation
      • Function Declarations
      • receive() & fallback()
      • CALL vs. DELEGATE CALL
    • Yul
      • Introduction
      • Types
      • Basic Operations
      • Storage
      • Memory
        • Arrays
        • Structs
        • Tuples, revert, keccak256
        • Logs and Events
        • Gotchas
        • abi.encode
      • Calldata
        • External Calls
        • Dynamic Length Inputs
        • Transferring Value
        • Receiving Contract Calls
      • Contracts in Yul
      • Other Yul Functions
    • Foundry
    • Security
      • Common Vulnerabilities
      • Best Practices
      • Development Workflow
      • Contract Migration
    • Auditing Tools
      • Slither
      • Mythril
      • Fuzzing
    • Upgradable Contracts
      • Upgrade Patterns
      • ERC-1967 Implementation
      • Deployment
    • MEV
    • Tooling
      • Chainlink
      • IPFS
      • Radicle
    • Frontend
      • Contract Hooks
      • Wallet Connection
        • wagmi.sh
        • Rainbow Kit
      • thirdweb
    • Protocol Research
      • Uniswap v2
      • Uniswap v3
      • Curve
      • GMX
  • Starkware
    • Fundamentals
    • Account Abstraction
    • Universal Deployer
    • Cairo 1.0
    • starknet.js
    • Security Model
  • Zero Knowledge
    • Group Theory
    • ECDSA
  • Rust
    • Basic Operations
    • Set up
    • Primitives
    • Control Flow
    • Mutability & Shadowing
    • Adding Behavior
    • Lifetimes
    • Std Library
  • SUI
    • Architecture
    • Consensus Mechanism
    • Local Node Setup
    • Sui Client CLI
    • Move Contracts
      • Move
      • Move.toml
      • Move.lock
      • Accessing Time in Sui Move
      • Set up Development Framework
      • Debug & Publish
      • Package Upgrades
      • Sui Move Library
      • Difference from Core Move
    • Object Programming
      • Object Basics
      • Using Objects
      • Immutable Objects
      • Object Wrapping
      • Dynamic Fields
      • Collections
      • Unit Testing
      • Deployment with CLI
  • NEAR
    • Architecture
    • Contract Standards
      • Fungible Token (NEP-141)
      • Non-Fungible Token (NEP-171)
      • Storage Management (NEP-145)
      • Events (NEP-297)
      • Meta-Transactions
    • Rust Contracts
      • Development Workflow
      • Smart Contract Layout
      • Storage Management
      • Events & Meta-transactions
      • Method Types
      • Upgrading Contracts
      • Unit Testing
    • NEAR Libraries
    • Environment Variables
    • Serialisation
    • Security Concepts
    • Collections
    • JS SDK
Powered by GitBook
On this page
  • Constant Product
  • Architecture
  • Core Contracts
  • Design Decisions
  1. Ethereum
  2. Protocol Research

Uniswap v2

PreviousProtocol ResearchNextUniswap v3

Last updated 2 years ago

  • Uniswap is an automated liquidity protocol powered by a and implemented in a system of non-upgradeable smart contracts.

  • Each Uniswap smart contract, or pair, manages a liquidity pool made up of reserves of two tokens.

  • Anyone can become a liquidity provider (LP) for a pool by depositing an equivalent value of each underlying token in return for pool tokens. These tokens track pro-rata LP shares of the total reserves, and can be redeemed for the underlying assets at any time

Constant Product

Expressed as x * y = k, states that trades must not change the product (k) of a pair’s reserve balances (x and y). Because k remains unchanged from the reference frame of a trade, it is often referred to as the invariant.

  • Uniswap applies a 0.30% fee to trades, which is added to reserves. As a result, each trade actually increases k

  • This functions as a payout to LPs, which is realized when they burn their pool tokens to withdraw their portion of total reserves

  • Because the relative price of the two pair assets can only be changed through trading, divergences between the Uniswap price and external prices create arbitrage opportunities. This mechanism ensures that Uniswap prices always trend toward the market-clearing price.

Architecture

Logic related to trader security or ease-of-use is implemented in external helper contracts. External helpers can be improved and replaced without needing to migrate liquidity, which improves on the flexibility and modularity of Uniswap.

Core Contracts

Singleton Factory

  • Holds the generic bytecode responsible for powering pairs

  • Create one and only one smart contract per unique token pair

  • Contains logic to turn on the protocol charge

  • Create Pair Function:

    • checks that token A and token B are different addresses

    • check that neither are the zero address

    • check that pair does not already exist

    • get bytecode for pair contract

    • calculate create2 salt for these two token addresses

    • deploy pair contract using create2

    • initialise the pair contract with the token addresses

    • update the pair mapping to track created pairs

function createPair(address tokenA, address tokenB) 
		external returns (address pair) {
				bytes memory bytecode = type(UniswapV2Pair).creationCode;
        bytes32 salt = keccak256(abi.encodePacked(token0, token1));
        assembly {
            pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }
		}

Pairs

  • Serve as automated market makers

  • Keep track of pool token balances

  • Expose data which can be used to build decentralized price oracles

  • Swap Function:

    • to address: the user

    • why are there two out tokens

    • checks that input token amounts are positive

    • checks that pool has sufficient tokens to transfer to caller

    • checks that caller has sent sufficient amount of input tokens

    • calculate and remove 0.3% uniswap fee from input tokens

    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) 
    		external lock {}

Design Decisions

Sending Tokens

  • typically, smart contracts require the user to give approval of the token contract to itself, before calling transferFrom on the token

  • however, this is not how v2 pair contracts accept tokens

  • v2 pairs check their token balances at the end of every interaction

  • Then, at the beginning of the next interaction, current balances are differenced against the stored values to determine the amount of tokens that were sent by the current interactor.

  • tokens must be transferred to the pair before calling any token-requiring method (except in Flash Swaps)

WETH

  • Unlike Uniswap V1 pools, V2 pairs do not support ETH directly, so ETH⇄ERC-20 pairs must be emulated with WETH

  • motivation behind this choice was to remove ETH-specific code in the core to have a leaner codebase

  • The router convert ETH to WETH so that users may utilise it directly.

Minimum Liquidity

  • For the first LP provision, LP tokens are burnt so the market maker cannot “rug”.

are the essential Uniswap V2 smart contracts:

- implements core swapping and liquidity provision functionality

- deploys contracts for any ERC20 token/ERC20 token pair

(periphery) is an initial set of helpers, including:

that performs the safety checks needed for safely swapping, adding, and removing liquidity.

that can remove liquidity from Uniswap V1 and deposit it into Uniswap V2 in a single transaction.

that can be used in the creation of other helper contracts.

that creates a simple TWAP from Uniswap V2 cumulative prices.

that withdraws ERC20 tokens, executes arbitrary code, and then pays for them.

To ameliorate rounding errors and increase the theoretical minimum tick size (smallest increment) for liquidity provision, pairs burn the first (returns 1000 for all pairs) pool tokens.

For most pairs, this will represent a trivial value. The burning happens automatically during the first liquidity provision, after which point the is forevermore bounded.

Uniswap V2 Core
UniswapV2Pair.sol
UniswapV2Factory.sol
UniswapV2Pair.sol
Uniswap V2 Periphery
A router contract
A migrator contract
A library contract
An example oracle contract
An example flash swap contract
MINIMUM_LIQUIDITY
totalSupply
constant product formula
ERC-20