# Uniswap V2 recap
If you haven't read my [previous article](https://hackmd.io/@carlitox477/BkOrSI4yA), you should; but in case you are super lazy like me, here's a short recap of the main ideas of the article:
1. This is is a rectangle:

2. This is how you calculate its area:
$$Rectangle \; area = shorter \; side \; length \times longer \; side \; length$$
3. If we want to determine the side length for every rectangle with an area of $k$, we can visualize it in [this graph](https://www.geogebra.org/calculator/thcaar5d), where we connect the points $(0,0)$, $(0,y)$, $(x,y)$, and $(x,0)$ to form the rectangle.
4. We can think of $x$ and $y$ as the amounts of tokens $X$ and $Y$ in a pool, respectively.
5. When we perform a swap without fees, the area of the rectangle must remain constant, meaning $x_{before\; swap} \times y_{before\; swap} = x_{after\; swap} \times y_{after\; swap}$. Where
* $x_{after\; swap} = x_{before\; swap} + \Delta x$
* $y_{after\; swap} = y_{before\; swap} + \Delta y$
* If we consider swapping tokens $Y$ for tokens $X$, then:
* $\Delta x = - amountOut_{X}$
* $\Delta y = amountIn_{Y}$
6. When we perform a swap with fees:
* $\Delta x = - amountOut_{X}$
* $\Delta y = amountSent_{Y} * (1 - fee \%)$
* Then $x_{before\; swap} \times y_{before\; swap} = ( x_{before\; swap} + \Delta x) \times (y_{before\; swap} + \Delta y)$, but:
* $x_{after\; swap} = x_{before\; swap} - amountOut_{X}$
* $y_{after\; swap} = y_{before\; swap} + amountSent_{Y}$
* Therefore, $k_{after \; swap} = (x_{before\; swap} - amountOut_{X}) \times (y_{before\; swap} + amountSent_{Y})$
8. The problem with uniswap V2 invariant is that it enforces to provide liquidity through the whole curve, while an approach of order books allows to provide liquidity to just one price.
# Limiting price range idea
At the end of our last ~~season~~ article, we demonstrated that in a liquidity pool with $1,000$ tokens $X$ ($USDC$) and $1,000$ tokens $Y$ ($USDT$), if someone attempts to buy $900$ $USDC$ , they would have to pay $9$ $USDT$ per $USDC$. This scenario discourages the exchange of large amounts of $USDC$ and $USDT$ in this pool. How can we modify Uniswap V2 to cap the $USDC$ price within a range of $[0.95, 1.05]$ $USDT$ per $USDC$?
In Uniswap V2
* The price $P$ is defined as $P = \frac{y}{x}$.
* The constant product formula $x \times y = k$ can be rephrased as $x \times y = L^2$, where $L^2$ is an alternative representation of $k$, which will be clarified later.
Our goal is to ensure that when $x_{real} = 0$, $P = 0.95$, and when $y_{real} = 0$, $P = 1.05$. However, given that in V2, $x = x_{real}$ and $y = y_{real}$, applying the same formula would not allow for this due to:
* Geometrically, a rectangle with one side length of $0$ is illogical.
* If $x_{real} = 0$, then $P$ becomes undefined, considering $x = x_{real}$.
* If $y_{real} = 0$, then $x_{real}$ can take any value.
* The constant $k$ cannot be maintained if $x = 0$ or $y = 0$
To address this, we can redefine $x$ and $y$ as:
$$x = x_{\text{virtual}} + x_{\text{real}}$$
$$y = y_{\text{virtual}} + y_{\text{real}}$$
Thus:
* The price $P = \frac{y}{x} = \frac{y_{virtual} + y_{real}}{x_{virtual} + x_{real}}$
* $(x_{virtual} + x_{real}) \times (y_{virtual}+ y_{real}) = L^2$
* $x - x_{virtual} = x_{real}$
* $y - y_{virtual} = y_{real}$
This approach introduces the concept of virtual liquidity in Uniswap, assuming additional tokens to maintain the invariant within a specified price range. The condition for swaps is that $0.95 \leq P_{\text{after swap}} \leq 1.05$, ensuring that $P_{\text{after swap}}$ remains within the desired range:
$$(x_{virtual} + x_{real \; after \; swap}) \times (y_{virtual} + y_{real \; after \; swap}) = L_{before \; swap}^{2}$$
But how do we calculate the virtual liquidity, i.e., $x_{\text{virtual}}$ and $y_{\text{virtual}}$?
To answer this, we first need to understand how liquidity is added within a specified price range.
# Adding liquidity
To add liquidity we assume that:
* We are aware of the current price. If we are the first to add liquidity, we will arbitrarily define a current price, which will dictate the amount of liquidity we need to add.
* The current price must be at the boundary of the price ranges. For example, if $P_{c} = 1$ (with $P_{c}$ representing the current price), we can introduce liquidity in price ranges $[0.7,1)$, $[0.8,1)$, $[0.85,1)$, $[1,1.05)$, and $[1,2)$, but not in $[0.95, 1.05)$.
# Virtual liquidity calculation
We know two things:
1. $(x_{virtual\; liquidity} + x_{real \; liquidity}) \times (y_{virtual\; liquidity} + x_{real \; liquidity}) = L^{2}$
2. $P_{c} = \frac{y_{virtual\; liquidity} \;+\; y_{real \; liquidity}}{x_{virtual\; liquidity} \;+\; x_{real \; liquidity}}$
By dividing the first equation by the second, we derive that:
1. $\frac{(x_{virtual\; liquidity} \;+\; x_{real \; liquidity}) \times (y_{virtual\; liquidity} \;+\; y_{real \; liquidity})}{\frac{y_{virtual\; liquidity} \;+\; y_{real \; liquidity}}{x_{virtual\; liquidity} \;+\; x_{real \; liquidity}}} = \frac{L^{2}}{P_{c} }$
1. $\frac{(x_{virtual\; liquidity} \;+\; x_{real \; liquidity})}{\frac{1}{x_{virtual\; liquidity} \;+\; x_{real \; liquidity}}} = \frac{L^{2}}{P_{c} }$
1. $(x_{virtual\; liquidity} + x_{real \; liquidity})^{2} = \frac{L^{2}}{P_{c} }$
1. $(x_{virtual\; liquidity} + x_{real \; liquidity})= \sqrt{\frac{L^{2}}{P_{c} }}$
1. $(x_{virtual\; liquidity} + x_{real \; liquidity})= \frac{L}{\sqrt{P_{c} }}$
Conversely, by multiplying $L^2$ by $P_c$, we find that:
1. $((x_{virtual\; liquidity} + x_{real \; liquidity}) \times (y_{virtual\; liquidity} + y_{real \; liquidity})) \times \frac{y_{virtual\; liquidity} + y_{real \; liquidity}}{x_{virtual\; liquidity} + x_{real \; liquidity}}= L^{2} \times P_{c}$
2. $((y_{virtual\; liquidity} + y_{real \; liquidity})) \times (y_{virtual\; liquidity} + y_{real \; liquidity})= L^{2} \times P_{c}$
3. $(y_{virtual\; liquidity} + y_{real \; liquidity})^{2} = L^{2} \times P$
4. $y_{virtual\; liquidity} + y_{real \; liquidity} = L \times \sqrt{P_{c} }$
Therefore, we ascertain that:
1. $x_{virtual\; liquidity} + x_{real \; liquidity}= \frac{L}{\sqrt{P_{c} }}$
2. $y_{virtual\; liquidity} + y_{real \; liquidity} = L \times \sqrt{P_{c}}$
Considering the conditions:
* $P_{A} \leq P_{c}$
* $P_{B} < P_{c}$
* $P_{A} < P_{B}$
If adding liquidity in the price range $[P_A; P_B)$:
* For $P_c = P_A$, implying all liquidity must be in token $X$, thus
$$y_{virtual\; liquidity} + y_{real \; liquidity} = y_{virtual\; liquidity} + 0 \implies$$
$$y_{virtual\; liquidity} = L \times \sqrt{P_{A}}$$
* For $P_c = P_B$, implying all liquidity must be in token $Y$, thus:
$$x_{virtual\; liquidity} + x_{real \; liquidity}= x_{virtual\; liquidity} + 0 \implies$$
$$x_{virtual\; liquidity} = \frac{L}{\sqrt{P_{B}}}$$
The equations below are equivalent:
$$(x_{virtual\; liquidity} + x_{real \; liquidity}) \times (y_{virtual\; liquidity} + y_{real \; liquidity}) = L^{2}$$
$$(\frac{L}{\sqrt{P_{B}}} + x_{real \; liquidity_{P_{c}}}) \times (L \times \sqrt{P_{A}} + y_{real \; liquidity_{P_{c}}}) = L^{2}$$
From this last equation we can calculate $L$ in two ways:
1. $(\frac{L}{\sqrt{P_{B}}} + x_{real \; liquidity_{P_{A}}}) \times (L \times \sqrt{P_{A}}) = L^{2}$ (when $P_{c} = P_{A}$ there is only token $X$)
1. $(\frac{L}{\sqrt{P_{B}}} + x_{real \; liquidity_{P_{A}}}) \times (L \times \sqrt{P_{A}}) = L^{2}$
2. $(\frac{L}{\sqrt{P_{B}}} + x_{real \; liquidity_{P_{A}}}) \times \sqrt{P_{A}} = L$
3. $(\frac{L}{\sqrt{P_{B}}} + x_{real \; liquidity_{P_{A}}}) = \frac{L}{\sqrt{P_{A}}}$
4. $x_{real \; liquidity_{P_{A}}} = \frac{L}{\sqrt{P_{A}}} - \frac{L}{\sqrt{P_{B}}}$
5. $x_{real \; liquidity_{P_{A}}} = L \times (\frac{1}{\sqrt{P_{A}}} - \frac{1}{\sqrt{P_{B}}})$
6. $L = \frac{x_{real \; liquidity_{P_{A}}}}{\frac{1}{\sqrt{P_{A}}} - \frac{1}{\sqrt{P_{B}}}}$
2. $(\frac{L}{\sqrt{P_{B}}}) \times (L \times \sqrt{P_{A}} + y_{real \; liquidity_{P_{B}}}) = L^{2}$ (when $P_{c} = P_{B}$ there is only token $Y$)
1. $(\frac{L}{\sqrt{P_{B}}}) \times (L \times \sqrt{P_{A}} + y_{real \; liquidity_{P_{B}}}) = L^{2}$
2. $(\frac{1}{\sqrt{P_{B}}}) \times (L \times \sqrt{P_{A}} + y_{real \; liquidity_{P_{B}}}) = L$
3. $L \times \sqrt{P_{A}} + y_{real \; liquidity_{P_{B}}} = L \times \sqrt{P_{B}}$
4. $y_{real \; liquidity_{P_{B}}} = L \times \sqrt{P_{B}} - L \times \sqrt{P_{A}}$
5. $y_{real \; liquidity_{P_{B}}} = L \times (\sqrt{P_{B}} - \sqrt{P_{A}})$
6. $L = \frac{y_{real \; liquidity_{P_{B}}}}{\sqrt{P_{B}} - \sqrt{P_{A}}}$
With $P_c$ at either $P_A$ or $P_B$, calculating $L$ becomes straightforward, needing only $y_{real \; liquidity_{P_{c}}}$ or $x_{real \; liquidity_{P_{c}}}$. When adding liquidity within $[P_A, P_B)$ where $P_A \leq P_c < P_B$, we can determine the required addition for a given amount of two tokens.
## Example: Adding liquidity when $P_{A} \leq P_{c} < P_{B}$
At the beginning of the article we wanted to add liquidity for $1,000$ tokens $X$ and $1,000$ tokens $Y$ (considering that $X$ was USDC and $Y$ was USDT) in a price range of $[0.95; 1.05)$ USDT per USDC.
We are going to change our original intentions to: we want to add liquidity for **at most** $1,000$ tokens $X$ and $1,000$ tokens $Y$ (considering that $X$ was USDC and $Y$ was USDT) in a price range of $[0.95; 1.05)$ USDT per USDC at a current price of $1$ considering there is no liquidity added yet.
This problem can be divided in 2:
1. We want to add liquidity for at most $1,000$ tokens $X$ and $0$ tokens $Y$ (considering that $X$ was USDC and $Y$ was USDT) in a price range of $[1.00; 1.05)$ USDT per USDC at a current price of $1.00$ considering there is no liquidity added yet.
2. We want to add liquidity for at most $0$ tokens $X$ and $1,000$ tokens $Y$ (considering that $X$ was USDC and $Y$ was USDT) in a price range of $[0.95; 1.00)$ USDT per USDC at a current price of $1$ considering there is no liquidity added yet.
### Problem 1
For problem 1 we have that:
* $P_{A} = P_{c} = 1.00$
* $P_{B} = 1.05$
* $x_{real \; liquidity_{P_{c}}} = x_{real \; liquidity_{P_{B}}} = 1,000$
* $y_{real \; liquidity_{P_{c}}} = y_{real \; liquidity_{P_{B}}} = 0$
Therefore
1. $L = \frac{x_{real \; liquidity_{P_{A}}}}{\frac{1}{\sqrt{P_{A}}} - \frac{1}{\sqrt{P_{B}}}}$
2. $L = \frac{1,000}{\frac{1}{\sqrt{1}} - \frac{1}{\sqrt{1.05}}}$
3. $L = \frac{1,000}{1- \frac{1}{\sqrt{1.05}}}$
4. $L \approx 41,493.90$ (We are doing some rounding here)
### Problem 2
For problem 2 we have that:
* $P_{A} = 0.95$
* $P_{B} = P_{c} = 1$
* $x_{real \; liquidity_{P_{c}}} = x_{real \; liquidity_{P_{B}}} = 0$
* $y_{real \; liquidity_{P_{c}}} = y_{real \; liquidity_{P_{B}}} = 1,000$
Therefore:
1. $L = \frac{y_{real \; liquidity_{P_{B}}}}{\sqrt{P_{B}} - \sqrt{P_{A}}}$
2. $L = \frac{1,000}{\sqrt{1} - \sqrt{0.95}}$
3. $L \approx 39,493.59$ (We are doing some rounding here)
## Problem 3
We get 2 different $L$ when dividing our original problem. What's happening? What is happening is that we are adding more liquidity in one side compared to the other. To solve this issue we must calculate the amount of token to add for the first problem considering the liquidity obtained in the second problem. This number is going to be less than $1,000$. Now we know that:
* $P_{A} = 0.95$
* $P_{B} = 1.05$
* $P_{c} = 1$
* $L = 39,493.59$
* $y_{real \; liquidity_{P_{c}}} = 1,000$
* $x_{real \; liquidity_{P_{c}}} =\; ?$
Therefore
1. $(\frac{L}{\sqrt{P_{B}}} + x_{real \; liquidity_{P_{c}}}) \times (L \times \sqrt{P_{A}} + y_{real \; liquidity_{P_{c}}}) = L^{2}$
1. $\frac{L}{\sqrt{P_{B}}} + x_{real \; liquidity_{P_{c}}} = \frac{L^{2}}{L \times \sqrt{P_{A}} + y_{real \; liquidity_{P_{c}}}}$
1. $x_{real \; liquidity_{P_{c}}} = \frac{L^{2}}{L \times \sqrt{P_{A}} + y_{real \; liquidity_{P_{c}}}} - \frac{L}{\sqrt{P_{B}}}$
1. $x_{real \; liquidity_{P_{c}}} \approx 951.79$ (We are doing some rounding here)
### Solution for original problem
We can conclude that if we have $1,000$ tokens $Y$ and $1,000$ tokens $X$, and we want to add the max liquidity we can in price range $[0.95;1.05)$ considering $1$ as current prices, we will have to add $1,000$ tokens $Y$ and $951.79$ tokens $X$. This would a liquidity of $39,494.47$ to current liquidity.
### Alternative solution: Adding liquidity in 2 ranges
From our original problem, let's suppose that instead of adding liquidity in price range $[0.95,1.05)$, we add it in price range $[0.95,1)$ and $[1,1.05)$. We would have 2 rectangles: one with $39,493.58$ units of liquidity (with $1,000$ tokens $X$ and $0$ tokens $Y$), and the other one with $41,493.9$ (with $1,000$ tokens $Y$ and $0$ tokens $X$) with a current price of $1$.
The area will change depending on which is the current price. For instance, if price moves to $1.03$, the liquidity would be of $41,493.9$, but if the price changed to $0.99$ the liquidity would be of $39,493.58$.
## Add liquidity above current price
If we try to add liquidity in a price range $[P_{A}; P_{B})$ when current $P_{c} < P_{A}$, then we are trying to add liquidity above current price. To do this, liquidity to add must be composed just by token $X$, and this amount will become available to perform swaps only when $P_{c} \geq P_{A}$.
In this way we know that:
* $x_{real \; liquidity_{P_{A}}} = x_{to \; add} = 1,000$
* $y_{real \; liquidity_{P_{A}}} = 0$
* $L = \frac{x_{real \; liquidity_{P_{A}}}}{\frac{1}{\sqrt{P_{A}}} - \frac{1}{\sqrt{P_{B}}}} \implies L = \frac{x_{to \; add}}{\frac{1}{\sqrt{P_{A}}} - \frac{1}{\sqrt{P_{B}}}}$
* $x_{virtual \; liquidity} = \frac{L}{\sqrt{P_{B}}}$
* $y_{virtual\; liquidity} = L \times \sqrt{P_{A}}$
## Add liquidity below current price
If when we try to add liquidity in a price range $[P_{A}; P_{B})$ $P_{c} \geq P_{B}$, then we are trying to add liquidity below current price. To do this, liquidity to add must be composed just by token $Y$, and this amount will become available to perform swaps only when $P_{c} < P_{B}$.
In this way we know that:
* $x_{real \; liquidity_{P_{B}}} = 0$
* $y_{real \; liquidity_{P_{B}}} = y_{to \; add} = 1,000$
* $L = \frac{y_{real \; liquidity_{P_{B}}}}{\sqrt{P_{B}} - \sqrt{P_{A}}}$
* $x_{virtual \; liquidity} = \frac{L}{\sqrt{P_{B}}}$
* $y_{virtual\; liquidity} = L \times \sqrt{P_{A}}$
# Thinking in terms of liquidity variation
Instead of calculating the amount of liquidity that we want to add, we can also say that we are calculating the variation of liquidity given a variation of tokens $X$ or $Y$. In this way
* $\Delta L = \frac{\Delta y}{\sqrt{P_{c}} - \sqrt{P_{A}}}$
* $\Delta L = \frac{ \Delta x}{\frac{1}{\sqrt{P_{c}}} - \frac{1}{\sqrt{P_{A}}}}$
This also means that:
* $\Delta y = \Delta L \times (\sqrt{P_{c}} - \sqrt{P_{A}})$
* $\Delta x = \Delta L \times \frac{1}{\sqrt{P_{c}}} - \frac{1}{\sqrt{P_{A}}}$
## Remove liquidity
We can use previous equations to calculate the amount of liquidity to remove in a price range $[P_{A},P_{B})$:
* When $P_{A} \leq P_{c} < P_{B}$:
* $\Delta L_{P_{A}, P_{c}} = \frac{\Delta x}{\frac{1}{\sqrt{P_{A}}} - \frac{1}{\sqrt{P_{c}}}}$
* $\Delta L_{P_{c},P_{B}} = \frac{\Delta y}{\sqrt{P_{B}} - \sqrt{P_{c}}}$
* $\Delta L_{P_{A},P_{B}} = min(\Delta L_{P_{A},P_{c}}, \Delta L_{P_{c}, P_{B}})$
* $\Delta x = \Delta L_{P_{A},P_{B}} \times (\frac{1}{\sqrt{P_{c}}} - \frac{1}{\sqrt{P_{B}}})$
* $\Delta y = \Delta L_{P_{A},P_{B}} \times (\sqrt{P_{c}} - \sqrt{P_{A}})$
* When $P_{c} > P_{B}$: $\Delta L_{P_{A},P_{B}} = \frac{\Delta x}{\frac{1}{\sqrt{P_{A}}} - \frac{1}{\sqrt{P_{B}}}}$
* When $P_{c} \leq P_{A}$: $\Delta L_{P_{A}, P_{B}} = \frac{\Delta y}{\sqrt{P_{B}} - \sqrt{P_{A}}}$
## Google sheet playground
To do the math related to previous example I did [this little playground in a google sheet](https://docs.google.com/spreadsheets/d/1CsfXp42ZqXEFLFUeFJaiOIN_hW_Tcy8VLuVwobrN4Cg/edit?usp=sharing). Feel free to copy it in order to play with it and get a better understanding about how liquidity is added in a Uniswap V3 pool
# The problem of tracking liquidity
In Unsiwap V3 anyone can provide liquidity in any price range, however only when current price is in between the price where where that liquidity was provided this liquidity become available.
In next graph we assume that:
* User A provide a liquidity of $39,493.59$ in price range $[0.95; 1.05)$ at a current price of $1$, compoused by:
* $951.79$ tokens $X$
* $1,000$ tokens $Y$
* User B provide a liquidity of $16,540.71$ in price range $[0.97; 1.03)$ at a current price of $1$, compoused by:
* $242.66$ tokens $X$
* $250$ tokens $Y$
<iframe src="https://www.geogebra.org/calculator/y69de6cx?embed" width="800" height="600" allowfullscreen style="border: 1px solid #e4e4e4;border-radius: 4px;" frameborder="0"></iframe>
From $P_{1.05}$ to $P_{1.03}$ and from $P_{0.97}$ to $P_{0.95}$ we are meant to use the green function, while from $P_{1.03}$ to $P_{0.97}$ we are meant to use the blue one.
Why the blue line represent more liquidity than the blue one? Because its add the liquidity from User A and User B. This happens because price range $[0.97;1.03)$ is included in price range $[0.95;1.05)$
With 2 position is very easy to graph the idea of how liquidity is handled, but what happens in reallity where there are thousands of positions in different price ranges? How do we track current liquidity? When do we increase it? When do we decrease it?
To address these problems uniswap introduced two variable:
* Current liquidity: Liquidity that is considered as active
* Liquidity net: Its a variable associated that is associated to each price, and represent how much current liquidty must be increased or decreased when a price is reached from a lower or greater price.
When we add $l$ liquidity in price range $[P_{A}; P_{B})$, liquidity net associated to $P_{A}$ is increased by $l$, but liquidity net associated to $P_{B}$ is decreased also by $l$. But what happens if liquidity associated to $P_{B}$ is 0? Well, after decreasing it liquidity net, the liquidity net associated with it will be $-l$. Meanig that liquidity net can have negative values.
I know this seems confusing, so let's see it in a graphic way, for just a second let's ignore the exact amount of tokens that are added when a user adds liquidity, let's just focus in this value, liquidity.
1. User A is the first to add liquidity, he do it in price range $[0.95;1.05)$ for a total of $39,493.59$, this can be seen as:

Notice that current liquidity increase by $39,493.59$ because current price is $1$
2. User B provide a liquidity of $16,540.71$ in price range $[0.97; 1.03)$, price still at $1$:

Given that current price is $1$, and this value is included in the specified price range, we must add the just added liquidity to current liquidity.
3. User C add $17,000.00$ liquidity in price range $[1.03; 1.05)$.

Given that current price is $1$, and this value is not included in the specified price range, therefore we must not include the just added liquidity to current liquidity. Also, notice that net liquidity for prices $1.03$ and $1.03$ were modified.
Now let's suppose that from current price $1.00$ the price goes to $1.04$, how much liquidity should be added or removed? Given that we crossed price $1.03$ from a lower price, the net liquidity associtated to $1.03$ must be added, this is $+459.63$

Finally the goes from $1.04$ to $0.96$. How much liquidity should be added/removed?
* Given that we are crossing $1.03$ from a greater price, we must substract its associated liquidity net, which is $+459,63$
* Given that we are crossing $0.97$ from a greater price, we must substract its associated liquidity net $+16,540,71$
A total of $17,000$ must be substracted from current liquidity

## Implementation problem
The only way to move a price is performing a swap, to implement previous behaviour we must check if a price was crossed during this operation. If liquidity is allowed to be added to any price, then this operation can become extremelly expensive in gas terms to execute. How Uniswap deals with this? The answer to this question is going to be answered in next article :D