# Math for LP Units in Asymmetric Case
** Updated as of July 15th
A swap (if needed) followed by liquidity add has the same asset ratio as in the pool.
We follow the notation for the swap in https://hackmd.io/vrCeYGvURZio4yWc-ChYzA#Computations so Y is ROWAN and X is the other TOKEN. Note we use a linear instead of slip based fee so have a different token exchange function.
The function for calculating the s values is in calculateSwapAmtAsymm. There are sample numbers for the variables in func main() to run test calculations for s. There is a more comprehensive version of the code below under "More Code" to calculate LP units.
```
package main
import (
"fmt"
"math"
)
func main() {
var Y, X float64 = 100000, 100000
var y, x float64 = 8000, 2000
var f, r float64 = 0.003, 0.01
s := calculateSwapAmtAsymm(Y, X, y, x, f, r)
fmt.Println("s = ", s)
}
func calculateSwapAmtAsymm(Y, X, y, x, f, r float64) float64 {
if (y+Y)/(x+X) > y/x {
solution_for_s := math.Abs((math.Sqrt(Y*(-1*(x+X))*(-1*f*f*x*Y-f*f*X*Y-2*f*r*x*Y+4*f*r*X*y+2*f*r*X*Y+4*f*X*y+4*f*X*Y-r*r*x*Y-r*r*X*Y-4*r*X*y-4*r*X*Y-4*X*y-4*X*Y)) + f*x*Y + f*X*Y + r*x*Y - 2*r*X*y - r*X*Y - 2*X*y - 2*X*Y) / (2 * (r + 1) * (y + Y)))
return solution_for_s
} else {
solution_for_s := math.Abs((math.Sqrt(math.Pow((-1*f*r*X*y-f*r*X*Y-f*X*y-f*X*Y+r*X*y+r*X*Y+2*x*Y+2*X*Y), 2)-4*(x+X)*(x*Y*Y-X*y*Y)) + f*r*X*y + f*r*X*Y + f*X*y + f*X*Y - r*X*y - r*X*Y - 2*x*Y - 2*X*Y) / (2 * (x + X)))
return solution_for_s
}
}
```
### For the code above
#### IF statement
The variable inputs above with `x = 8000` and `y = 2000` will trigger the `if` statement
Formula used in Wolfram Alpha to solve for s:
`(x+X)/(y+Y) = (x−s) / (y + s*Y/(s+X)*(1−f)/(1+r)) solve for s`
found in
https://www.wolframalpha.com/input?i=%28x%2BX%29+%2F+%28y%2BY%29+%3D+%28x-s%29+%2F+%28y+%2B+%28%28sY%29%2F+%28s%2BX%29%29*%281-f%29%2F%281%2Br%29%29+solve+for+s
There are two solutions, with solution1 = -solution2 due to the absolute value. Therefore, we wrap the solution for s in an absolute value in the code and only solve once.
Solution for $s$: `s = 2918.4761`
#### ELSE statement
The variable inputs above with `x = 2000` and `y = 8000` below will trigger the `else` statement
Formula used in Wolfram Alpha to solve for s:
`(y+Y)/(x+X) = (y-s) / (x + (s*X)/(s+Y)*(1+r)*(1-f)) solve for s`
found in
https://www.wolframalpha.com/input?i=%28y%2BY%29+%2F%28x%2BX%29+%3D+%28y-s%29+%2F+%28x+%2B+%28%28sX%29%2F+%28s%2BY%29*%281-f%29*%281%2Br%29%29%29%2C+solve+for+s
Similar to the if statement, we only use one solution for s here and wrap it in an absolute value.
Solution for $s$: `s = 2888.7913`
** Note the else statement covers the $x = y$ case. If you run the code for values where $x = y$, you will see the output for $s$ is 0, which is correct as the $x = y$ case needs no adjustment to symmetric for LP units calculations.
### Appendix
#### Equation derivations
#### 1. $$ \frac{x+X}{y+Y} = (x-s) / (y + (1-f)g(X,Y,s,r)) $$
$$y_o(s) = f(X,Y,s) =\frac{sY}{s+X} = sY/(s+X) $$
$$g(X,Y,s,r) = y(s) = y_o(s)/(1+r) = sY/(s+X)/(1+r) = sY/((s+X)(1+r)) $$
Input $g(X,Y,s,r)$ into $Y/X$ function from above
$$ \frac{x+X}{y+Y} = (x-s) / (y + (1-f)*(sY/((s+X)*(1+r))))$$
Reorganize to get the function input into wolfram:
$$ (x+X)/(y+Y) = (x-s) / (y + (s*Y)/(s+X)*(1-f)/(1+r))$$
#### 2. $$ \frac{y+Y}{x+X} = (y-s) / (x + (1-f)g(X,Y,s,r)) $$
$$x_o(s) = f(X,Y,s) =\frac{sX}{s+Y} = sX/(s+Y) $$
$$g(X,Y,s,r) = x(s) = x_o(s)*(1+r) = sX/(s+Y)*(1+r) $$
Input $g(X,Y,s,r)$ into $Y/X$ function from above
$$ \frac{y+Y}{x+X} = (y-s) / (x + (1-f)*(sX/(s+Y)*(1+r)))$$
Reorganize to get the function input into wolfram:
$$ (y+Y)/(x+X) = (y-s) / (x + (s*X)/(s+Y)*(1+r)*(1-f))$$
### More Code
```
func getData() (float64, float64, float64, float64, float64, float64, float64) {
var Y, X, P float64 = 100000, 100000, 100000
var y, x float64 = 2000, 8000
var f, r float64 = 0.003, 0.01
return Y, X, P, y, x, f, r
}
func main() {
Y, X, P, y, x, f, r := getData()
s := calculateSwapAmtAsymm(Y, X, y, x, f, r)
fmt.Println("s = ", s)
xCorrected, yCorrected, LPUnits, UpdatedP := calculateLPUnits(Y, X, P, y, x, f, r, s)
fmt.Println("xCorrected = ", xCorrected, ", yCorrected = ", yCorrected, ", LPUnits = ", LPUnits, ", UpdatedP = ", UpdatedP)
}
func calculateSwapAmtAsymm(Y, X, y, x, f, r float64) float64 {
if (y+Y)/(x+X) > y/x {
solution_for_s := math.Abs((math.Sqrt(Y*(-1*(x+X))*(-1*f*f*x*Y-f*f*X*Y-2*f*r*x*Y+4*f*r*X*y+2*f*r*X*Y+4*f*X*y+4*f*X*Y-r*r*x*Y-r*r*X*Y-4*r*X*y-4*r*X*Y-4*X*y-4*X*Y)) + f*x*Y + f*X*Y + r*x*Y - 2*r*X*y - r*X*Y - 2*X*y - 2*X*Y) / (2 * (r + 1) * (y + Y)))
return solution_for_s
} else {
solution_for_s := math.Abs((math.Sqrt(math.Pow((-1*f*r*X*y-f*r*X*Y-f*X*y-f*X*Y+r*X*y+r*X*Y+2*x*Y+2*X*Y), 2)-4*(x+X)*(x*Y*Y-X*y*Y)) + f*r*X*y + f*r*X*Y + f*X*y + f*X*Y - r*X*y - r*X*Y - 2*x*Y - 2*X*Y) / (2 * (x + X)))
return solution_for_s
}
}
func calculateLPUnits(Y, X, P, y, x, f, r, s float64) (float64, float64, float64, float64) {
if (y+Y)/(x+X) > y/x {
xCorrected := x - s
yCorrected := y + (1-f)/(1+r)*s*Y/(s+X)
LPUnits := xCorrected / X * P
UpdatedP := P + LPUnits
return xCorrected, yCorrected, LPUnits, UpdatedP
} else {
xCorrected := x + (1-f)*(1+r)*s*X/(s+Y)
yCorrected := y - s
LPUnits := xCorrected / X * P
UpdatedP := P + LPUnits
return xCorrected, yCorrected, LPUnits, UpdatedP
}
}