Uniswap v3 Deep Dive

Key Concepts for Context

  • Decentralized exchange (DEX): peer-to-peer or peer-to-protocol marketplaces where traders can exchange their blockchain tokens without any central authority taking custody of their funds.

  • Counterparty: someone on the opposite side of a deal or transaction. For example, if you are buying crypto, your counterparty would be a crypto seller.

  • Liquidity provider (LP): someone who deposits their tokens into a DEX’s liquidity pool in exchange for fees and other benefits. The DEX collects a small fee on all trading volume and disburses the fees to LPs proportional to the amount of liquidity they deposited.

  • Impermanent loss: a financial risk faced by LPs due to the potential for their deposited assets to fluctuate in price. Due to impermanent loss, an LP may sometimes be better off keeping their assets than depositing them into a liquidity pool. More info on Binance.

Decentralized crypto exchanges (DEXs) have become an essential part of the decentralized finance (DeFi) ecosystem. Each day, tens of billions of dollars are transacted on DEXes, enabling crypto holders to easily buy and sell digital assets without having to find counterparties themselves or delegate custody of their assets. This liquidity not only provides profit opportunities for traders and investors but also helps the markets efficiently discover the prices of digital assets. Today, Uniswap is one of the largest DEXs in the world, supporting billions of dollars in transactions every day for individuals, decentralized apps (dApps), and traders around the world.

How DEXs Work

Order Books

In traditional finance, exchanges operate with databases called order books. Stock markets like the New York Stock Exchange enable participants to buy and sell their stocks by recording orders and matching them with counterparties. For example, if you wanted to buy 100 shares of Apple at $170 per share, the exchange would take your buy order and match it with a similar sell order (or multiple) so that you can obtain 100 shares of Apple at around $170 per share. The exchange thus acts as a direct intermediary between individual buyers and sellers, and this model is used by some DEXs as well, such as dYdX.

Automated Market Makers (AMMs)

On the other hand, other DEXs like Uniswap use an automated market maker model to power transactions. Instead of matching buy and sell orders 1-to-1, AMMs use liquidity pools to facilitate trading between two pairs of tokens. Here’s how it works: liquidity providers (LPs) can initialize a pool by depositing an equal value of two different tokens (let’s say ETH and USDC). Then, if someone wants to exchange their ETH for USDC, they would send their ETH into the pool and get back a corresponding amount of USDC. This way, exchanges can happen without having to directly buy and sell orders.

To determine the exchange rate between the two tokens in a pool, Uniswap relies on a constant product function to algorithmically set the price. This function is defined as x * y = k, where x and y are the amounts of tokens 1 and 2 in the pool, respectively, and k is an invariant. Let’s walk through an example with the ETH/USDC pool: suppose that there are currently 100 ETH tokens (x) and 100 USDC tokens (y) in the pool. This means that our invariant k is 100 * 100 = 10,000. Now, let’s say that someone wants to buy some amount of USDC using 10 ETH. Using the constant product function, our new x value would be 100 + 10 = 110 ETH tokens (since the user sent in 10 ETH), and our new y value would be (100 - z) USDC tokens, where z is an unknown quantity that the user gets back from the pool. Since we must maintain the invariant of 10,000, we can solve for z with the equation: 110 * (100 - z) = 10,000. After rearranging the terms, we would get z = 9.09, so the user gets 9.09 USDC for their 10 ETH. The constant product function also encapsulates the market’s supply and demand; if more users wanted USDC, it would cost exponentially more ETH because there are now only 100 - 9.09 = 90.91 USDC tokens left vs. the more abundant 110 ETH tokens. This would also make ETH cheaper compared to USDC, which follows from the supply and demand forces.

The figure shows the result of swapping token A for token B using a constant product function. Credit: MVP Workshop.
The figure shows the result of swapping token A for token B using a constant product function. Credit: MVP Workshop.

Uniswap v3 Innovations

Concentrated Liquidity

In 2021, Uniswap launched Uniswap v3, the latest iteration of the Uniswap protocol that implements substantial improvements to the traditional AMM structure of Uniswap v2. One of the key innovations is concentrated liquidity: the ability for LPs to provide liquidity only within a specific price range. With concentrated liquidity, fees are proportionally distributed only to LPs whose liquidity is in the current price range of a trade, rather than to all LPs. As a result, LPs can provide the same amount of liquidity into specific price ranges of the pools yet earn more fees than with v2. Traders would also have access to virtually the same amount of liquidity, as LPs are incentivized to provide more liquidity to price ranges with higher trading volume, and the trading fees are also tiered based on the volatility of the pool’s tokens (i.e., more volatile tokens will earn more fees). Even with full-range positions similar to those on v2, according to Uniswap’s internal research, LPs have earned between 16% and 160% more fees on v3, depending on the deposited tokens’ fee tier.

Concentrated liquidity along the constant product curve. Credit: Uniswap.
Concentrated liquidity along the constant product curve. Credit: Uniswap.

As an example of the improvement, consider a pool of ETH/USDC, where the price is likely to be somewhat bounded given that the two tokens are very established. An LP could deposit $500k of each token into the pool on Uniswap v2, and they would earn a cut of the 0.3% trading fee on all volume for ETH/USDC that is divided proportionally among all LPs. On the other hand, in Uniswap v3, an LP could create a liquidity “position” for prices between $1000 and $2000 and deposit the same $500k of each token. Since not all liquidity is within that range, the LP would have a claim over a larger proportional share of the pool and thus earn a higher cut of the 0.3% trading fee. A risk-seeking LP could go even further and put all of their capital into a very tight price range (as small as 0.01%), and if the two tokens remain within that price range, then the LP would “own” a significant portion of the pool and thus earn much higher fees compared to what they would make on Uniswap v2 (up to 4000x). Of course, if the price falls outside of the LP’s pre-set price range, then they would not earn any fees, so there is more risk involved. Uniswap v3 thus enables LPs to be more strategic in how they allocate their liquidity, opening up opportunities for higher profits using the same amount of capital.

Theoretical increases in returns for LPs based on liquidity range,  compared to Uniswap v2. Credit: Uniswap.
Theoretical increases in returns for LPs based on liquidity range,  compared to Uniswap v2. Credit: Uniswap.

Technical Implementation

In order to implement concentrated liquidity in code, Uniswap has discrete ticks that LPs can set as the ends of their price range. Intuitively, a tick exists at each power of 1.0001, so each tick is a 0.01% price change away from the next, allowing LPs to be extremely granular in setting their price ranges. A tick becomes initialized if it is not already used as a bound on any price ranges, and whenever the price crosses an initialized tick, liquidity is “kicked” in or out (i.e., included in the pool or not) based on the positions that LPs have taken. When executing swaps within a single initialized tick range, the pool acts like a regular AMM where the “virtual” reserves maintain a constant product function. As tokens are swapped one by one and cause a movement along the price curve, the price may increase or decrease to enter another tick range, in which case the appropriate amount of net liquidity would be added to the pool. The process would then repeat in the new tick range (and potentially more tick ranges) until the token swap is fully executed. One could think of it like a ship moving through locks in a canal: within each tick range (lock), tokens (water) are exchanged until there is none left within the range, at which point the ship (the state of the swap) moves into another lock and continues the process until the swap is completed. As a whole, this technical implementation allows for LPs to have highly granular price ranges and traders to have efficient swap execution even as prices change.

Flowchart showing the logical flow of executing a swap that may cross tick ranges. A swap is executed within its current tick range using a constant product function until the price exits the range, after which another constant product function is used. Credit: Uniswap.
Flowchart showing the logical flow of executing a swap that may cross tick ranges. A swap is executed within its current tick range using a constant product function until the price exits the range, after which another constant product function is used. Credit: Uniswap.

Price Oracle

Beyond just concentrated liquidity, Uniswap v3 also introduced improvements to its time-weighted average price (TWAP) oracle, which many DeFi projects use to get an accurate picture of price history for digital assets. With Uniswap v2, users of the oracle could access a cumulative sum of prices on a per-second basis via an on-chain call, but would then need to store the cumulative sums themselves in order to determine average prices across a period of time. This would be prone to errors from users, and would also increase costs from having to store many values by themselves. Now, Uniswap v3 reports an array of accumulator values instead of a single value, allowing users to determine an average price going back around 9 days with a single on-chain call, and the cumulative sum of prices has also been replaced with a cumulative sum of log prices for easier calculations (e.g., for geometric means). The accumulator is implemented in code by summing the tick indices, as each tick index is already a power of 1.0001 (i.e., tick 1 corresponds to price 1.0011, tick 10 corresponds to price 1.00110, etc.), making it both conceptually and computationally simpler.

Impermanent Loss: A Persistent Risk

Despite all these systematic improvements, however, one risk continues to loom over the heads of LPs: impermanent loss (IL). Even though Uniswap v3’s concentrated liquidity gives LPs greater control over their funds and unlocks more fee revenue, Nasdaq reports that around half of v3 LPs still lose money due to impermanent loss.

As an example of how impermanent loss happens, say that the earlier ETH/USDC pool has 100 ETH and 100 USDC in total (implying that 1 ETH = 1 USDC). If you had previously deposited 10 ETH and 10 USDC into the pool, then you would have a claim over 10% of the pool’s assets (which would be worth $20). Let’s say that after some time, ETH’s price increased to 4 USDC for 1 ETH. This opens up arbitrage opportunities for traders, who would swap USDC for ETH until the pool reflects the new price, and since the original invariant was 10 * 10 = 100, the new allocation of the pool would be 5 ETH and 20 USDC. Now, if you wanted to withdraw your 10% share of the pool, you would receive 10% of 5 ETH and 20 USDC = 0.5 ETH and 2 USDC. This would be worth only (0.5 ETH * $4/ETH)  + 2 USDC = $4, which is much less than the $20 you originally deposited. The 20 - 4 = $16 loss you took would be considered impermanent loss, and you would’ve had more money (10 ETH * $4/ETH + 10 USDC = $50) by not depositing your tokens at all. The more that the exchange rate deviates from the original rate, the greater your impermanent loss.

Projected amount of impermanent loss based on how much the exchange rate deviates from the original ratio. Credit: Binance Academy.
Projected amount of impermanent loss based on how much the exchange rate deviates from the original ratio. Credit: Binance Academy.

Impermanent loss is an inevitable constraint of Uniswap’s AMM model, especially since crypto assets tend to be very volatile. It’s typically up to the individual LP to mitigate their risk by sticking to safer tokens and DEXs, or by depositing lower amounts. Just-in-time (JIT) liquidity has also emerged as a strategy for very large LPs to avoid IL by depositing and withdrawing their liquidity within the same block, but this only forms a tiny fraction of liquidity provision on Uniswap and has high gas costs. Nevertheless, Uniswap v3 has optimized fee rewards for LPs among current DEXs to help offset the risks of impermanent loss, and it will undoubtedly be a major DEX for years to come.

Author

William Zeng (Blockchain at Berkeley Education Department).

Sources

Subscribe to Blockchain at Berkeley
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.