5

This is from Uniswapv3 white paper:

In other words, earlier versions were designed to provide liquidity across the entire price range (0, ∞). This is simple to implement and allows liquidity to be efficiently aggregated, but means that much of the assets held in a pool are never touched.

Having considered this, it seems reasonable to allow LPs to concentrate their liquidity to smaller price ranges than (0, ∞). We call liquidity concentrated to a finite range a position. A position only needs to maintain enough reserves to support trading within its range, and therefore can act like a constant product pool with larger reserves (we call these the virtual reserves) within that range

When a user provides liquidity into the pool, how come range is important. Liquidity provider justs puts its assets on the pool and those assets are just in a box and any other user can use those to swap.

Let's say I put one 1eth where 1 eth=1000 dai. As far as I see, regardless of specifying the range or not, these assets will be available in the pool and any user can use them any time. But whitepaper says

much of the assets held in a pool are never touched.

2
  • Concentrated liquidity in Uniswap v3 allows LPs to focus their assets within specific price ranges where trading is more likely, making capital usage more efficient and potentially increasing returns for LPs Apr 20, 2023 at 5:07
  • blog.uniswap.org/jit-liquidity may also help since "Just-In-Time Liquidity" is concentrated liquidity to an extreme.
    – eth
    Apr 23, 2023 at 21:05

4 Answers 4

5
+50

Concentrated liquidity is more capital efficient because with increased concentration, the same amount of tokens invested creates greater depth of liquidity.

From Uniswap's blog:

By concentrating their liquidity, LPs can provide the same liquidity depth as v2 within specified price ranges while putting far less capital at risk.

An informal way how to define capital efficiency is to see it as the ratio between the capital invested and the value generated.

  • Situation A: $1 generates 1 units of value.
  • Situation B: $1 generates 2 units of value.

The capital in situation B is used in 2 times more efficient way.

The main function liquidity pools is to let trading to happen. All else being equal, a pool is more attractive for traders if it has deeper liquidity, because deeper liquidity -> reduced price impact for trades. It means that value (efficiency) of capital is greater if it is used to achieve greater depth of liquidity in the pool.


Some math-based analysis follows.

Exactly how inefficient are v2 pools? Uniswap v2 is a traditional constant-product automated market maker (AMM). The liquidity L is defined with the help of the formula

x * y = L^2,

where x and y are the amounts of assets in the pool. Let's say the initial price of ETH is P0 = $2000, and that someone puts 1 ETH and 2000 DAI in the pool. In this case the value of L is sqrt(2000) or approximately 44.7.

Now for a different price P the amount of ETH in the pool is sqrt(P0 / P), for instance for P = $8000 the pool has 0.5 ETH and for P = $500 it has 2 ETH. This means that 50% of the pool's capital is reserved for ETH prices below $500 and above $8000. Moreover, 10% of the pool's capital is reserved for prices 100x different from the current price, that is, above $200,000 and below $10 per ETH. Sure, these prices are not impossible, but is it really sensible to allocate as much as 10% of capital for these extreme scenarios?

The consequence of the capital being so spread out is that the price impact of trades in v2 pools is high unless the amount of capital is huge.

In v3, LPs can set the price range [Pa, Pb] of each position, where Pa is the minimum price and Pb the maximum price. The virtual liquidity of such a v3 position / pool is defined as:

v3 liquidity formula

For instance, if someone believes that ETH is going to trade in the $500-$8000 range they can set these range endpoints and be 2x more capital efficient. Verify this in code:

L = sqrt(2000)  # v2 liquidity value for 1 ETH + 2000 DAI position
P = 2000        # initial/current price
Pa = 500        # range min price
Pb = 8000       # range max price
# amount of ETH to match the v2 liquidity
x = L * (sqrt(Pb) - sqrt(P)) / (sqrt(Pb) * sqrt(P))
# amount of DAI to match the v2 liquidity
y = L * (sqrt(P) - sqrt(Pa))

The result is x=0.5 (ETH) and y=1000 (DAI) as expected. 2x less ETH and DAI needed to achieve the same liquidity depth!

Expanding this further:

  • [P / 4, P * 4] price range -> 2x capital efficiency

  • [P / 2, P * 2] price range -> 3.41x capital efficiency

  • [P / 1.2, P * 1.2] price range -> 11.48x capital efficiency

  • [P / 1.1, P * 1.1] price range -> 21.49x capital efficiency

  • [P / 1.05, P * 1.05] price range -> 41.49x capital efficiency

  • [P / 1.01, P * 1.01] price range -> 201.5x capital efficiency

Meaning that for stable pairs, v3 pools can easily be hundreds of times more capital efficient than v2.

For more experimentation, the Uniswap's blog also have a nice interactive calculator at the end of the "Capital Efficiency" section.

2
  • How come for P = $8000 the pool has 0.5 ETH and for P = $500 it has 2 ETH. can you explain this sentence pls?
    – Yilmaz
    Apr 25, 2023 at 1:07
  • The amount of ETH in the pool changes with the square root of the price. It follows from the equations x*y=k and x/y=P, with just a bit of algebra we get x = sqrt(k / P). When price increases/decreases 4 times, the amount of ETH in the pool decreases/increases 2 times.
    – kfx
    Apr 25, 2023 at 6:29
4

how come range is important.

Because of price impact.

As a market taker (trader) you want to get the most amount of tokens for the amount of your money you put in the trade (quote token, fiat). Market takers, by definition, can only buy tokens at the given market value, or around mid price, and not in any arbitrary price import.

Thus, the price impact will be lower if the liquidity is concentrated around the mid-price because that's where all the trade volume is happening.

Uniswap v2 and all of its forks distribute the liquidity among zero to infinite price due to the usage of simple bonding curve mechanism. But

  • no one is trading tokens at zero price or infinite price

  • every market taker wants to have the best deal for their amount of token, which is as many tokens at the mid-price at the possible

  • Because Uniswap liquidity is not focused on mid-price, there is going to be a lot of price impact

Uniswap v3 fixes this using concentrated liquidity market maker ranges which allows the market maker to give ranges for which they specify liquidity. To get trading fees, everyone wants to have their ranges around mid price, because that's where the volume is happening. You could think CLMM model as poor man's order book.

3

The concentrated liquidity is capital efficient because it allows LPs to optimize their capital utilization by concentrating their liquidity within a specific price range. Earlier versions of AMMs like uniswap were designed to provide liquidity across the entire price range, resulting much of the assets kept in a pool were never used, as the trades happened within a smaller price range.

In Uniswap V3, a liquidity provider has ability to specify the range of prices within which they want to provide liquidity. This means LPs can concentrate their liquidity in a specific price range where they expect more trading activity to happen. By doing so, they can provide the same level of liquidity as in earlier versions of Uniswap, but with smaller reserves, making their capital more efficient

Lets take a example: let's say that a liquidity provider wants to provide liquidity in the ETH/DAI pair, but they believe that the price of ETH is going to stay within a specific range. So in newer version, they can create a position that only provides liquidity within that range they expect, which means they do not need to hold as much liquidity as they would need to cover the entire price range.

0
import math

def calculate_v3_liquidity(L, P, Pa, Pb):
    """
    Calculate the amount of ETH (x) and DAI (y) to match v2 liquidity in a v3 pool with specified price range.

    :param L: v2 liquidity value.
    :param P: Current price of ETH.
    :param Pa: Minimum price in the v3 price range.
    :param Pb: Maximum price in the v3 price range.
    :return: Tuple of (x, y) representing the required amounts of ETH and DAI.
    """
    x = L * (math.sqrt(Pb) - math.sqrt(P)) / (math.sqrt(Pb) * math.sqrt(P))
    y = L * (math.sqrt(P) - math.sqrt(Pa))
    return x, y

def calculate_capital_efficiency(P, Pa, Pb):
    """
    Calculate the capital efficiency for a given price range in a v3 pool.

    :param P: Current price of ETH.
    :param Pa: Minimum price in the v3 price range.
    :param Pb: Maximum price in the v3 price range.
    :return: Capital efficiency factor.
    """
    L = math.sqrt(2000)  # v2 liquidity value for 1 ETH + 2000 DAI position
    x_v2, y_v2 = 1, 2000  # v2 ETH and DAI amounts
    x_v3, y_v3 = calculate_v3_liquidity(L, P, Pa, Pb)

    # Capital efficiency is the ratio of total v2 capital to total v3 capital
    total_v2 = x_v2 * P + y_v2
    total_v3 = x_v3 * P + y_v3
    return total_v2 / total_v3

Initial setup

P = 2000  # initial/current price
Pa_500_8000 = (500, 8000)  # price range [500, 8000]
Pa_P_4 = (P / 4, P * 4)    # price range [P / 4, P * 4]
Pa_P_2 = (P / 2, P * 2)    # price range [P / 2, P * 2]
Pa_P_1_2 = (P / 1.2, P * 1.2)  # price range [P / 1.2, P * 1.2]
Pa_P_1_1 = (P / 1.1, P * 1.1)  # price range [P / 1.1, P * 1.1]
Pa_P_1_05 = (P / 1.05, P * 1.05)  # price range [P / 1.05, P * 1.05]
Pa_P_1_01 = (P / 1.01, P * 1.01)  # price range [P / 1.01, P * 1.01]

Calculate capital efficiencies

efficiency_500_8000 = calculate_capital_efficiency(P, *Pa_500_8000)
efficiency_P_4 = calculate_capital_efficiency(P, *Pa_P_4)
efficiency_P_2 = calculate_capital_efficiency(P, *Pa_P_2)
efficiency_P_1_2 = calculate_capital_efficiency(P, *Pa_P_1_2)
efficiency_P_1_1 = calculate_capital_efficiency(P, *Pa_P_1_1)
efficiency_P_1_05 = calculate_capital_efficiency(P, *Pa_P_1_05)
efficiency_P_1_01 = calculate_capital_efficiency(P, *Pa_P_1_01)

efficiency_500_8000, efficiency_P_4, efficiency_P_2, efficiency_P_1_2, efficiency_P_1_1, efficiency_P_1_05, efficiency_P_1_01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.