---
# System prepended metadata

title: Math for LP Units in Asymmetric Case

---

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