Blog

  • Uniswap Overview

    Protocol, Interface, Labs

    To begin, we should make clear the distinctions between the different areas of “Uniswap”, some of which may confuse new users.

    • Uniswap Labs: The company which developed the Uniswap protocol, along with the web interface.
    • Uniswap Foundation: A non-profit organization that supports the development of the Uniswap protocol and its DeFi ecosystem.
    • Uniswap Protocol: A suite of persistent, non-upgradable smart contracts that together create an automated market maker, a protocol that facilitates peer-to-peer market making and swapping of ERC-20 tokens on the Ethereum blockchain.
    • Uniswap Interface: A web interface that allows for easy interaction with the Uniswap protocol. The interface is only one of many ways one may interact with the Uniswap protocol.
    • Uniswap Governance: A governance system for governing the Uniswap Protocol, enabled by the UNI token.

    The Uniswap Protocol

    Introduction

    The Uniswap protocol is a peer-to-peer1 system designed for exchanging cryptocurrencies (ERC-20 Tokens) on the Ethereum blockchain. The protocol is implemented as a set of persistent, non-upgradable smart contracts; designed to prioritize censorship resistance, security, self-custody, and to function without any trusted intermediaries who may selectively restrict access.

    There are currently four versions of the Uniswap protocol. v1 and v2 are open source and licensed under GPL. v3 introduced concentrated liquidity and is open source with slight modifications, which are viewable herev4 introduces the singleton pool architecture and hooks system, enabling unprecedented protocol customization, and uses a dual license structure viewable here. Each version of Uniswap, once deployed, will function in perpetuity, with 100% uptime, provided the continued existence of the Ethereum blockchain.

    How does the Uniswap protocol compare to a typical market?

    To understand how the Uniswap protocol differs from a traditional exchange, it is helpful to first look at two subjects: how the Automated Market Maker design deviates from traditional central limit order book-based exchanges, and how permissionless systems depart from conventional permissioned systems.

    Order Book VS AMM

    Most publicly accessible markets use a central limit order book style of exchange, where buyers and sellers create orders organized by price level that are progressively filled as demand shifts. Anyone who has traded stocks through brokerage firms will be familiar with an order book system.

    The Uniswap protocol takes a different approach, using an Automated Market Maker (AMM), sometimes referred to as a Constant Function Market Maker, in place of an order book. Through its evolution, the protocol has enhanced this model: v3 introduced concentrated liquidity for capital efficiency, and v4‘s singleton pool architecture and hooks system enable unprecedented customization of pool behavior while maintaining the core AMM principles.

    At a very high level, an AMM replaces the buy and sell orders in an order book market with a liquidity pool of two assets, both valued relative to each other. As one asset is traded for the other, the relative prices of the two assets shift, and a new market rate for both is determined. In this dynamic, a buyer or seller trades directly with the pool, rather than with specific orders left by other parties. The advantages and disadvantages of Automated Market Makers versus their traditional order book counterparts are under active research by a growing number of parties. We have collected some notable examples on our research page.

    Permissionless Systems

    The second departure from traditional markets is the permissionless and immutable design of the Uniswap protocol. These design decisions were inspired by Ethereum’s core tenets, and our commitment to the ideals of permissionless access and immutability as indispensable components of a future in which anyone in the world can access financial services without fear of discrimination or counter-party risk.

    Permissionless design means that the protocol’s services are entirely open for public use, with no ability to selectively restrict who can or cannot use them. Anyone can swap, provide liquidity, or create new markets at will. This is a departure from traditional financial services, which typically restrict access based on geography, wealth status, and age.

    The protocol is also immutable, in other words not upgradeable. No party is able to pause the contracts, reverse trade execution, or otherwise change the behavior of the protocol in any way. It is worth noting that Uniswap Governance has the right (but no obligation) to divert a percentage of swap fees on any pool to a specified address. However, this capability is known to all participants in advance, and to prevent abuse, the percentage is constrained between 10% and 25%.

  • Hooks

    Introduction

    Uniswap v4 inherits all of the capital efficiency gains of Uniswap v3 while introducing major architectural improvements.

    The key innovations are the Hook System and Singleton Architecture, which together enable unprecedented protocol customization and gas optimization.

    Hooks

    Hooks allow developers to customize and extend the behavior of liquidity pools. They are external smart contracts that can be attached to individual pools to intercept and modify the execution flow at specific points during pool-related actions.

    The logic is executed before and/or after major operations such as pool creation, liquidity addition and removal, swapping, and donations.

    Through these hook functions, developers can build sophisticated features like custom AMMs with different pricing curves, yield farming protocols, advanced trading features including limit orders, dynamic fee strategies, and custom oracle implementations. Each pool can have one hook (though a hook can serve multiple pools), hooks are optional and specified during pool creation, and developers can implement any combination of hook functions based on their needs.

    Singleton Architecture

    The hook system in v4 is built on top of a revolutionary architectural change known as the singleton design. Unlike previous versions where each pool was a separate smart contract, v4 manages all pools through a single contract called the PoolManager. This architectural innovation brings several key improvements:

    • Efficient Pool Creation: Pools are created as state updates rather than contract deployments, significantly reducing gas costs
    • Gas Optimization: Multi-hop swaps and complex operations are streamlined through a single contract
    • Flash Accounting: Token balances are tracked internally and settled at the end of transactions, minimizing transfers
    • Native ETH Support: Direct ETH trading without the need to wrap to WETH, improving user experience

    These core features are just the beginning of what’s possible with Uniswap v4.

    To explore all features including flash accounting, native ETH support, dynamic fees, and custom accounting, check out the v4 whitepaper.

  • Swaps

    Introduction

    Swaps are the most common way of interacting with the Uniswap protocol. For end-users, swapping is straightforward: a user selects an ERC-20 token that they own and a token they would like to trade it for. Executing a swap sells the currently owned tokens for the proportional1 amount of the tokens desired, minus the swap fee, which is awarded to liquidity providers2. Swapping with the Uniswap protocol is a permissionless process.

    note: Using web interfaces (websites) to swap via the Uniswap protocol can introduce additional permission structures, and may result in different execution behavior compared to using the Uniswap protocol directly. To learn more about the differences between the protocol and a web interface, see What is Uniswap.

    Swaps using the Uniswap protocol are different from traditional order book trades in that they are not executed against discrete orders on a first-in-first-out basis — rather, swaps execute against a passive pool of liquidity, with liquidity providers earning fees proportional to their capital committed

    Price Impact

    In a traditional order-book market, a sizeable market-buy order may deplete the available liquidity of a prior limit-sell and continue to execute against a subsequent limit-sell order at a higher price. The result is the final execution price of the order is somewhere in between the two limit-sell prices against which the order was filled.

    Price impact affects the execution price of a swap similarly but is a result of a different dynamic. When using an automated market maker, the relative value of one asset in terms of the other continuously shifts during the execution of a swap, leaving the final execution price somewhere between where the relative price started – and ended.

    This dynamic affects every swap using the Uniswap protocol, as it is an inextricable part of AMM design.

    As the amount of liquidity available at different price points can vary, the price impact for a given swap size will change relative to the amount of liquidity available at any given point in price space. The greater the liquidity available at a given price, the lower the price impact for a given swap size. The lesser the liquidity available, the higher the price impact.

    Approximate3 price impact is anticipated in real-time via the Uniswap interface, and warnings appear if unusually high price impact will occur during a swap. Anyone executing a swap will have the ability to assess the circumstances of price impact when needed.

    Slippage

    The other relevant detail to consider when approaching swaps with the Uniswap protocol is slippage. Slippage is the term we use to describe alterations to a given price that could occur while a submitted transaction is pending.

    When transactions are submitted to Ethereum, their order of execution is established by the amount of “gas” offered as a fee for executing each transaction. The higher the fee offered, the faster the transaction is executed. The transactions with a lower gas fee will remain pending for an indeterminate amount of time. During this time, the price environment in which the transaction will eventually be executed will change, as other swaps will be taking place.

    Slippage tolerances establish a margin of change acceptable to the user beyond price impact. As long as the execution price is within the slippage range, e.g., %1, the transaction will be executed. If the execution price ends up outside of the accepted slippage range, the transaction will fail, and the swap will not occur.

    A comparable situation in a traditional market would be a market-buy order executed after a delay. One can know the expected price of a market-buy order when submitted, but much can change in the time between submission and execution.

    Safety Checks

    Price impact and slippage can both change while a transaction is pending, which is why we have built numerous safety checks into the Uniswap protocol to protect end-users from drastic changes in the execution environment of their swap. Some of the most commonly encountered safety checks:

    • Expired : A transaction error that occurs if a swap is pending longer than a predetermined deadline. The deadline is a point in time after which the swap will be canceled to protect against unusually long pending periods and the changes in price that typically accompany the passage of time.
    • INSUFFICIENT_OUTPUT_AMOUNT : When a user submits a swap, the Uniswap interface will send an estimate of how much of the purchased token the user should expect to receive. If the anticipated output amount of a swap does not match the estimate within a certain margin of error (the slippage tolerance), the swap will be canceled. This attempts to protect the user from any drastic and unfavorable price changes while their transaction is pending.

    1. Proportional in this instance takes into account many factors, including the relative price of one token in terms of the other, slippage, price impact, and other factors related to the open and adversarial nature of Ethereum.
    2. For information about liquidity provision, see the liquidity user guide
    3. The Uniswap interface informs the user about the circumstances of their swap, but it is not guaranteed.
  • Fees

    Swap Fees

    Swap fees are distributed pro-rata to all in-range1 liquidity at the time of the swap. If the spot price moves out of a position’s range, the given liquidity is no longer active and does not generate any fees. If the spot price reverses and reenters the position’s range, the position’s liquidity becomes active again and will generate fees.

    Swap fees are not automatically reinvested as they were in previous versions of Uniswap. Instead, they are collected separately from the pool and must be manually redeemed when the owner wishes to collect their fees.

    Pool Fees Tiers

    Uniswap v3 introduces multiple pools for each token pair, each with a different swapping fee. Liquidity providers may initially create pools at three fee levels: 0.05%, 0.30%, and 1%. More fee levels may be added by UNI governance, e.g. the 0.01% fee level added by this governance proposal in December 2021, as executed here.

    Breaking pairs into separate pools was previously untenable due to the issue of liquidity fragmentation. Any incentive alignments achieved by more fee optionality invariably resulted in a net loss to traders, due to lower pairwise liquidity and the resulting increase in price impact upon swapping.

    The introduction of concentrated liquidity decouples total liquidity from price impact. With price impact concerns out of the way, breaking pairs into multiple pools becomes a feasible approach to improving the functionality of a pool for assets previously underserved by the 0.30% swap fee.

    Finding The Right Pool Fee

    We anticipate that certain types of assets will gravitate towards specific fee tiers, based on where the incentives for both swappers and liquidity providers come nearest to alignment.

    We expect low volatility assets (stable coins) will likely congregate in the lowest fee tier, as the price risk for liquidity providers holding these assets is very low, and those swapping will be motivated to pursue an execution price closest to 1:1 as they can get.

    Similarly, we anticipate more exotic assets, or those traded rarely, will naturally gravitate towards a higher fee – as liquidity providers will be motivated to offset the cost risk of holding these assets for the duration of their position.

    Protocol Fees

    Both Uniswap v3 and v4 include a protocol fee mechanism that can be activated through UNI governance. This fee structure offers greater flexibility compared to v2, allowing governance to adjust the fraction of swap fees allocated to the protocol. For detailed information about protocol fees, refer to the v3 whitepaper and v4 whitepaper.

  • Oracle

    All Uniswap v3 pools can serve as oracles, offering access to historical price and liquidity data. This capability unlocks a wide range of on-chain use cases.

    Historical data is stored as an array of observations. At first, each pool tracks only a single observation, overwriting it as blocks elapse. This limits how far into the past users may access data. However, any party willing to pay the transaction fees may increase the number of tracked observations (up to a maximum of 65535), expanding the period of data availability to ~9 days or more.

    Storing price and liquidity history directly in the pool contract substantially reduces the potential for logical errors on the part of the calling contract, and reduces integration costs by eliminating the need to store historical values. Additionally, the v3 oracle’s considerable maximum length makes oracle price manipulation significantly more difficult, as the calling contract may cheaply construct a time-weighted average over any arbitrary range inside of (or fully encompassing) the length of the oracle array.

    Observations

    Observations take the following form:

    struct Observation {
    // the block timestamp of the observation
    uint32 blockTimestamp;
    // the tick accumulator, i.e. tick * time elapsed since the pool was first initialized
    int56 tickCumulative;
    // the seconds per liquidity, i.e. seconds elapsed / max(1, liquidity) since the pool was first initialized
    uint160 secondsPerLiquidityCumulativeX128;
    // whether or not the observation is initialized
    bool initialized;
    }

    Copy

    Observations may be retrieved via the observations method on v3 pools. However, this is not the recommended way to consume oracle data. Instead, prefer observe:

    function observe(uint32[] calldata secondsAgos)
    external
    view
    returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);

    Copy

    Each time observe is called, the caller must specify an array containing any number of seconds ago, denoting the times to return observations from. Note that each of the given times must be more recent (or as old as) the oldest stored observation. Note: if the times don’t correspond exactly to a block in which an observation was written, a counterfactual observation will be constructed, removing the need for the caller to interpolate manually. This is one of the primary reasons to use observe over observations.

    Note that because the oracle is only updated at most once every block, calling observe with a secondsAgo value of 0 will return the most recently written observation, which can only be as recent as the beginning of the current block (or older).

    Tick Accumulator

    The tick accumulator stores the cumulative sum of the active tick at the time of the observation. The tick accumulator value increases monotonically and grows by the value of the current tick – per second.

    To derive the arithmetic mean tick over an interval, the caller needs to retrieve two observations, one after the other, take the delta of the two values, and divide by the time elapsed between them. Calculating a TWAP from the tick accumulator is also covered in the whitepaper. Note that using an arithmetic mean tick to derive a price corresponds to a geometric mean price.

    See OracleLibrary for an example of how to use the tick accumulator.

    Liquidity Accumulator

    The liquidity accumulator stores the value of seconds / in-range liquidity at the time of the observation. The liquidity accumulator value increases monotonically and grows by the value of seconds / in-range liquidity – per second.

    To derive the harmonic mean liquidity over an interval, the caller needs to retrieve two observations, one after the other, take the delta of the two values, then divide the time elapsed by this value. Calculating TWAL is addressed in finer detail in the whitepaper.

    note

    The in-range liquidity accumulator should be used with care. Because the current tick and the current in-range liquidity can be entirely uncorrelated, there are scenarios in which taking the arithmetic mean tick and the harmonic mean liquidity over the same interval in a pool can inaccurately characterize this pool relative to another. For example, if the current tick on pool A is 0 for 5 seconds, and 100 for 5 seconds, the tick accumulator will be 50. If over this same interval, the in-range liquidity was 5000 and 50, the harmonic mean liquidity will be ~99. Compare this to pool B (composed of the same assets) where the tick was 50 and the in-range liquidity was ~99 for 10 seconds. The accumulator values will be identical, but the underlying behavior is of course quite different.

    Deriving Price From A Tick

    When we use “active tick” or otherwise to refer to the current tick of a pool, we mean the lower tick boundary that is closest to the current price.

    When a pool is created, each token is assigned to either token0 or token1 based on the contract address of the tokens in the pair. Whether or not a token is token0 or token1 is meaningless; it is only used to maintain a fixed assignment for the purpose of relative valuation and general logic in the pool contract.

    Deriving an asset price from the current tick is achievable due to the fixed expression across the pool contract of token0 in terms of token1.


    An example of finding the price of WETH in a WETH / USDC pool, where WETH is token0 and USDC is token1:

    You have an oracle reading that shows a return of tickCumulative as [70_0001_070_000], with an elapsed time between the observations of 10 seconds.

    We can derive the average tick over this interval by taking the difference in accumulator values (1_070_000 – 70_000 = 1_000_000), and dividing by the time elapsed (1_000_000 / 10 = 100_000).

    With a tick reading of 100_000, we can find the value of token1 (USDC) in terms of token0 (WETH) by using the current tick as i in the formula p(i) = 1.0001**i (see 6.1 in the whitepaper).

    1.0001**100_000 ≅ 22015.5 USDC / WETH


    Ticks are signed integers and can be expressed as a negative number, so for any circumstances where token0 is of a lower value than token1, a negative tick value will be returned by tickCumulative and a relative value of < 0 will be returned by a calculation of token0 in terms of token1.