Quietbroom Blog

Understanding Uniswap V3 - Part II

Motivation

When providing liquidity on V3, an LP doesn’t necessarily have to provide an equivalent amount of xx and yy tokens like how it was with V2. What an LP provides depends on the price range they specify and where the range is relative to the current price.

Each position that an LP creates is a mapping from an account address, lower bound, and upper bound to a liquidity value LL. This liquidity will be combined later on, when the price crosses this particular LP’s range, with all the other LPs to create a global LL value for swaps.

So, depending on the range specified by the LP relative to the current price P, there are three different ways to compute this LL value, and therefore, how much of each xx and yy token to deposit.

1. PPaP \leq P_{a}, current price is below the LP’s range

2. PbPP_{b} \leq P, current price is above the LP’s range

3. PaPPbP_{a} \le P \le P_{b}, current price is within the LP’s range

For each of these cases, we will see how much of token xx and token yy that an LP has to deposit when they specify some PaP_{a} and PbP_{b}

Calculate L when PPaP \leq P_{a}

Here, we have a graph where PP is below PaP_{a}:

image info

From Part 1 in this series, we know that yrealy_{real} reserves become 00 when the price reaches or exceeds PaP_{a}. So, for any price at PaP_{a} or below, there are 00 yrealy_{real} tokens in the LP position for this range.


To solve for LL, we take our concentrated liquidity function and specify that yrealy_{real} is 00 when PPaP \leq P_{a}:

(xreal+LPb)(0+LPa)=L2(xreal+LPb)(LPa)=L2(x_{real} + \frac{L}{\sqrt{P_{b}}})(0 + L \sqrt{P_{a}}) = L^{2} \longrightarrow (x_{real} + \frac{L}{\sqrt{P_{b}}})(L \sqrt{P_{a}}) = L^{2}

Cancel out an LL on each side:

(xreal+LPb)Pa=L(x_{real} + \frac{L}{\sqrt{P_{b}}}) \cdot \sqrt{P_{a}} = L

Multiply out Pa\sqrt{P_{a}}:

xrealPa+LPaPb=Lx_{real} \cdot \sqrt{P_{a}} + L \cdot \frac{\sqrt{P_{a}}}{\sqrt{P_{b}}} = L

Move LL to one side:

xrealPa=LLPaPbx_{real} \cdot \sqrt{P_{a}} = L - L \cdot \frac{\sqrt{P_{a}}}{\sqrt{P_{b}}}

Divide both sides by Pa\sqrt{P_{a}}:

xreal=LPaLPaPbPaxreal=LPaLPbx_{real} = \frac{L}{\sqrt{P_{a}}} - L \cdot \frac{\sqrt{P_{a}}}{\sqrt{P_{b}} \cdot \sqrt{P_{a}}} \longrightarrow x_{real} = \frac{L}{\sqrt{P_{a}}} - \frac{L}{\sqrt{P_{b}}}

Factor out the binomial:

xreal=LPaPbPbLPbPaPaxreal=LPbPaPbPax_{real} = \frac{L}{\sqrt{P_{a}}} \cdot \frac{\sqrt{P_{b}}}{\sqrt{P_{b}}} - \frac{L}{\sqrt{P_{b}}} \cdot \frac{\sqrt{P_{a}}}{\sqrt{P_{a}}} \longrightarrow x_{real} = L \cdot \frac{\sqrt{P_{b}} - \sqrt{P_{a}}}{\sqrt{P_{b}} \cdot \sqrt{P_{a}}}

Solve for LL by cross multiplication:

xrealL=PbPaPbPaL(PbPa)=xreal(PbPa)\frac{x_{real}}{L} = \frac{\sqrt{P_{b}} - \sqrt{P_{a}}}{\sqrt{P_{b}} \cdot \sqrt{P_{a}}} \longrightarrow L \cdot (\sqrt{P_{b}} - \sqrt{P_{a}}) = x_{real} \cdot (\sqrt{P_{b}} \cdot \sqrt{P_{a}})

Finally:

L=xrealPbPaPbPaL = x_{real} \cdot \frac{\sqrt{P_{b}} \cdot \sqrt{P_{a}}}{\sqrt{P_{b}} - \sqrt{P_{a}}}

We can see that calculating liquidity to provide only requires the deposit of xrealx_{real} tokens by the LP when price PP is below PaP_{a}.

Calculate L when PbPP_{b} \leq P

Here, we have a graph where PP is above PbP_{b}:

image info

From Part 1 in this series, we know that xrealx_{real} reserves become 0 when the price reaches or exceeds PbP_{b}. So, for any price at PbP_{b} or higher, there are 00 xrealx_{real} tokens in the LP position for this range.


To solve for LL, we take our concentrated liquidity function and specify that xrealx_{real} is 00 when PbPP_{b} \leq P:

(0+LPb)(yreal+LPa)=L2LPb(yreal+LPa)=L2(0 + \frac{L}{\sqrt{P_{b}}})(y_{real} + L \sqrt{P_{a}}) = L^{2} \longrightarrow \frac{L}{\sqrt{P_{b}}} \cdot (y_{real} + L \sqrt{P_{a}}) = L^{2}

Cancel out an LL on each side:

1Pb(yreal+LPa)=L\frac{1}{\sqrt{P_{b}}} \cdot (y_{real} + L \sqrt{P_{a}}) = L

Multiply out 1Pb\displaystyle\frac{1}{\sqrt{P_{b}}}:

yrealPb+LPaPb=L\frac{y_{real}}{\sqrt{P_{b}}} + L \cdot \frac{\sqrt{P_{a}}}{\sqrt{P_{b}}} = L

Move LL to one side:

yrealPb=LLPaPb\frac{y_{real}}{\sqrt{P_{b}}} = L - L \cdot \frac{\sqrt{P_{a}}}{\sqrt{P_{b}}}

Multiply both sides by Pb\sqrt{P_{b}}:

yreal=LPbLPaPbPbyreal=LPbLPay_{real} = L \cdot \sqrt{P_{b}} - L \cdot \frac{\sqrt{P_{a}} \cdot \sqrt{P_{b}}}{\sqrt{P_{b}}} \longrightarrow y_{real} = L \cdot \sqrt{P_{b}} - L \cdot \sqrt{P_{a}}

Pull LL out of the binomial:

yreal=L(PbPa)y_{real} = L \cdot (\sqrt{P_{b}} - \sqrt{P_{a}})

Finally:

L=yrealPbPaL = \frac{y_{real}}{\sqrt{P_{b}} - \sqrt{P_{a}}}

We can see that calculating liquidity to provide only requires the deposit of yrealy_{real} tokens by the LP when price PP is above PbP_{b}.

Calculate L when PaPPbP_{a} \le P \le P_{b}

Here, we have a graph when PP is between PaP_{a} and PbP_{b}.

image info

The goal here to determine the ratio of xx and yy tokens to deposit for the specified range, PaP_{a} and PbP_{b}.


We know that when PP is below PaP_{a}, the range only has xrealx_{real} tokens as liquidity:

image info

And we also know that when PP is above PbP_{b} the range only has yy tokens in it:

image info

If we combine these two examples, we can see that to the left of PP only exists xx tokens and to the right only yy tokens.

image info

The intuition here is that any range, where PP is inside PaP_{a} and PbP_{b}, can be split up into two sub-ranges, with one only containing xrealx_{real} tokens and one only containing yrealy_{real} tokens:

image info

Since we have already solved for LL in both cases where a range has only xrealx_{real} tokens or only yrealy_{real} tokens, we can also solve for this case.


We start with our liquidity calculation for LL in a range with only xrealx_{real} tokens:

L=xrealPbPaPbPaL = x_{real} \cdot \frac{\sqrt{P_{b}} \cdot \sqrt{P_{a}}}{\sqrt{P_{b}} - \sqrt{P_{a}}}

Since we know the range PbP_{b} to PP only has xrealx_{real} tokens, we use this range instead:

L=xrealPbPPbPL = x_{real} \cdot \frac{\sqrt{P_{b}} \cdot \sqrt{P}}{\sqrt{P_{b}} - \sqrt{P}}

Now that we have an LL value, we can use it to solve for yrealy_{real}. We’ll use the range PP to PaP_{a} since we know it only has yrealy_{real} tokens:

L=yrealPbPaL=yrealPPaL = \frac{y_{real}}{\sqrt{P_{b}} - \sqrt{P_{a}}} \longrightarrow L = \frac{y_{real}}{\sqrt{P} - \sqrt{P_{a}}}

Solve for yrealy_{real}:

yreal=L(PPa)y_{real} = L \cdot (\sqrt{P} - \sqrt{P_{a}})

So, given xrealx_{real} as input, we can calculate the LL value, then use LL to solve for yrealy_{real}. Using the LL value from the xrealx_{real} calculation works on the yrealy_{real} side because on either side of PP, there is expected to be LL liquidity. This is the case because the entire range has LL=L2L \cdot L = L^{2} as its constant product.

This process is how V3 calculates how much of each token that an LP should provide. An LP specifies a range, enters an amount of token xx, and based on the current price, a yy amount of the token is specified to deposit as well.

Let’s see an example

An LP is adding a Δx\Delta x of 22 ETH in a ETH/DAI pool. ETH’s current price is P=2000P = 2000, and the LP has specified the range from Pa=1500P_{a} = 1500 to Pb=2500P_{b} = 2500. How much DAI does the LP need to add along with the 22 ETH?

With PbP_{b} to PP as our range and xrealx_{real} set as 22, we can calculate how much liquidity will be added to the pool:

L=xrealPbPPbP=22500200025002000=847.2136L = x_{real} \cdot \frac{\sqrt{P_{b}} \cdot \sqrt{P}}{\sqrt{P_{b}} - \sqrt{P}} = 2 \cdot \frac{\sqrt{2500} \cdot \sqrt{2000}}{\sqrt{2500} - \sqrt{2000}} = 847.2136

With our new ΔL\Delta L value, we can calculate how much yrealy_{real} the LP will be expected to add, with a range of PP to PaP_{a}:

yreal=L(PPa)=847.2136(20001500)=5076.1y_{real} = L \cdot (\sqrt{P} - \sqrt{P_{a}}) = 847.2136 \cdot (\sqrt{2000} - \sqrt{1500}) = 5076.1

To provide liquidity in a range from 15001500 to 25002500 with 22 ETH, the LP would need to deposit 5076.15076.1 DAI as well.


Alec DiFederico

Hey there, I'm Alec.

This is my portfolio/blog where you can fing things I find interesting or some projects I've built.

Enjoy your stay, and feel free to check out my github while you're here.