# 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 } }