Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(CL): merge main into concentrated-liquidity-main #3211

Merged
merged 38 commits into from
Nov 2, 2022
Merged
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
42d73f1
Add servers to openapi spec file (#2980)
daniel-farina Oct 19, 2022
ec7a7a8
Chain.schema.json: Added ibc data, fix genesis name, formatting (#3077)
JeremyParish69 Oct 20, 2022
fdbdc78
labels (#3082)
czarcas7ic Oct 21, 2022
4a67cdd
[x/gamm][stableswap]: Expand inverse relation tests to multi assets a…
AlpinYukseloglu Oct 21, 2022
d812334
remove all uses of two-asset binary search solver (#3084)
AlpinYukseloglu Oct 21, 2022
edfb19b
[stableswap]: Implement simplified direct multi-asset CFMM solver (#3…
AlpinYukseloglu Oct 21, 2022
c51a248
refactor: remove PokePool from the PoolI interface, define on extensi…
p0mvn Oct 21, 2022
f0f31d0
ci(CL): run tests on CL branch and add backport config (#3095)
p0mvn Oct 21, 2022
7f62b6d
After create pool test (#2783)
hieuvubk Oct 22, 2022
b552bab
fix GetModuleToDistributeCoins (#2957)
catShaark Oct 24, 2022
975aeb9
update comment in gamm module (#3103)
ThanhNhann Oct 24, 2022
9176a51
chore(deps): Bump github.com/tendermint/tendermint (#3106)
dependabot[bot] Oct 24, 2022
18f4afa
chore(deps): Bump github.com/golangci/golangci-lint (#3104)
dependabot[bot] Oct 24, 2022
6548902
chore(deps): Bump github.com/stretchr/testify from 1.8.0 to 1.8.1 (#3…
dependabot[bot] Oct 24, 2022
7119419
chore: update concentrated liquidity backport label (#3115)
p0mvn Oct 24, 2022
8590b80
feat(osmomath): log2 approximation (#2788)
p0mvn Oct 24, 2022
ced84c1
[stableswap]: Cap number of assets and post-scaled asset amounts to e…
AlpinYukseloglu Oct 24, 2022
0aa0263
Remove unused versions in mergify (#3121)
niccoloraspa Oct 24, 2022
df9102e
Query lockup params (#3098)
hieuvubk Oct 24, 2022
6274617
CI: Delete failing step (#3124)
ValarDragon Oct 24, 2022
184a85c
[x/gamm][stableswap]: Add inverse join/exit tests, fix single asset j…
AlpinYukseloglu Oct 24, 2022
805f80c
Stableswap implement JoinPoolNoSwap (#2942)
ValarDragon Oct 24, 2022
2ce796c
Make testing suite to ensure queries never alter state (#3001)
hieuvubk Oct 25, 2022
1e80a2a
Remove streamswap (#3146)
hieuvubk Oct 25, 2022
20c72cc
updated the contract to cosmwasm 1.1 and Uint256 for amounts (#2950)
nicolaslara Oct 29, 2022
46d0053
chore: use environment variable instead of build tags to control e2e …
p0mvn Oct 31, 2022
bb5c1c9
Rate limit - Cleaner tests (#3183)
nicolaslara Oct 31, 2022
d8b6d54
changed lints to stable so they change less often (#3184)
nicolaslara Oct 31, 2022
5abf7a4
update version numbers (#3168)
doggystylez Oct 31, 2022
434b42f
chore(deps): Bump github.com/spf13/cobra from 1.6.0 to 1.6.1 (#3187)
dependabot[bot] Oct 31, 2022
a3d0110
chore(deps): Bump github.com/mattn/go-sqlite3 from 1.14.15 to 1.14.16…
dependabot[bot] Oct 31, 2022
5c9bc1b
chore(e2e): add vscode debug configurations (#3180)
p0mvn Oct 31, 2022
5c408f9
osmomath(log/CL): ln(x), log_1.0001(x), log_custom(x) (#3169)
pysel Nov 1, 2022
8cd07fd
feat(release): Automated post-upgrade tasks by code generating upgrad…
pysel Nov 1, 2022
2620afd
chore: Tx post-handler example snippet #3194
alexanderbez Nov 1, 2022
d874d6d
Progress on IBC rate limit spec (#3190)
ValarDragon Nov 1, 2022
29c8561
fix(e2e): various e2e build issues breaking debugging on linux amd64 …
p0mvn Nov 2, 2022
a7acb4f
Merge branch 'main' into roman/merge-main
p0mvn Nov 2, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[stableswap]: Implement simplified direct multi-asset CFMM solver (#3068
)

Closes: #2730

## What is the purpose of the change

This PR implements a direct solver for our multi-asset CFMM. Similar to our two-asset direct solver, it is intended to be kept in our codebase as a reference implementation and proof for our CFMM but is outclassed by our binary search solver for practical use.

## Brief Changelog

- Implement direct multi-asset solver and test it against our full suite of CFMM cases

## Testing and Verifying

- The solver implementation is tested against our full multi-asset CFMM test suite in `amm_test.go`

## Documentation and Release Note

  - Does this pull request introduce a new feature or user-facing behavior changes? (no)
  - Is a relevant changelog entry added to the `Unreleased` section in `CHANGELOG.md`? (no)
  - How is the feature or change documented? (not documented)
AlpinYukseloglu authored Oct 21, 2022
commit edfb19bc7e4d99cde3ccae86dc1d60a38fd31c56
79 changes: 78 additions & 1 deletion x/gamm/pool-models/stableswap/amm.go
Original file line number Diff line number Diff line change
@@ -149,6 +149,84 @@ func solveCfmmDirect(xReserve, yReserve, yIn osmomath.BigDec) osmomath.BigDec {
return xOut
}

// multi-asset CFMM is xyu(x^2 + y^2 + w) = k
// As described in our spec, we can ignore the u term and simply solve within the bounds of k' = k / u
// since u remains constant throughout any independent operation this solver would be used for.
// We want to solve for a given addition of `b` units of y into the pool,
// how many units `a` of x do we get out.
// Let y' = y + b
// we solve k = (x'y')(x'^2 + y^2 + w) for x', using the following equation: https://www.wolframalpha.com/input?i2d=true&i=solve+for+y%5C%2844%29+x*y*%5C%2840%29Power%5Bx%2C2%5D+%2B+Power%5By%2C2%5D+%2B+w%5C%2841%29%3Dk
// which we simplify to be the following: https://www.desmos.com/calculator/zx2qslqndl
// Then we use that to derive the change in x as x_out = x' - x
//
// Since original reserves, y' and k are known and remain constant throughout the calculation,
// deriving x' and then finding x_out is equivalent to finding x_out directly.
func solveCFMMMultiDirect(xReserve, yReserve, wSumSquares, yIn osmomath.BigDec) osmomath.BigDec {
if !xReserve.IsPositive() || !yReserve.IsPositive() || wSumSquares.IsNegative() || !yIn.IsPositive() {
panic("invalid input: reserves and input must be positive")
} else if yIn.GTE(yReserve) {
panic("cannot input more than pool reserves")
}

// find k' using existing reserves (k' = k / v term)
k := cfmmConstantMultiNoV(xReserve, yReserve, wSumSquares)
k2 := k.Mul(k)

// find new yReserve after join
y_new := yReserve.Add(yIn)

// store powers to simplify calculations
y2 := y_new.Mul(y_new)
y3 := y2.Mul(y_new)
y4 := y3.Mul(y_new)

// We then solve for new xReserve using new yReserve and old k using a solver derived from xy(x^2 + y^2 + w) = k
// Full equation: x' = (sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) + 27 k y^2)^(1/3) / (3 2^(1/3) y)
// - (2^(1/3) (w y + y^3))/(sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) + 27 k y^2)^(1/3)
//
//
// To simplify, we make the following abstractions:
// 1. sqrt_term = sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3)
// 2. cube_root_term = (sqrt_term + 27 k y^2)^(1/3)
// 3. term1 = cube_root_term / (3 2^(1/3) y)
// 4. term2 = (2^(1/3) (w y + y^3)) / cube_root_term
//
// With these, the final equation becomes: x' = term1 - term2

// let sqrt_term = sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3)
wypy3 := (wSumSquares.Mul(y_new)).Add(y3)
wypy3pow3 := wypy3.Mul(wypy3).Mul(wypy3)

sqrt_term, err := ((k2.Mul(y4).MulInt64(729)).Add(y3.MulInt64(108).Mul(wypy3pow3))).ApproxRoot(2)
if err != nil {
panic(err)
}

// let cube_root_term = (sqrt_term + 27 k y^2)^(1/3)
cube_root_term, err := (sqrt_term.Add(k.Mul(y2).MulInt64(27))).ApproxRoot(3)
if err != nil {
panic(err)
}

// let term1 = cube_root_term / (3 2^(1/3) y)
term1 := cube_root_term.Quo(cubeRootTwo.MulInt64(3).Mul(y_new))

// let term2 = cube_root_term * (2^(1/3) (w y + y^3))
term2 := (cubeRootTwo.Mul(wypy3)).Quo(cube_root_term)

// finally, let x' = term1 - term2
x_new := term1.Sub(term2)

// find amount of x to output using initial and final xReserve values
xOut := xReserve.Sub(x_new)

if xOut.GTE(xReserve) {
panic("invalid output: greater than full pool reserves")
}

return xOut
}

func approxDecEqual(a, b, tol osmomath.BigDec) bool {
return (a.Sub(b).Abs()).LTE(tol)
}
@@ -159,7 +237,6 @@ var (
)

// solveCFMMBinarySearch searches the correct dx using binary search over constant K.
// added for future extension
func solveCFMMBinarySearchMulti(xReserve, yReserve, wSumSquares, yIn osmomath.BigDec) osmomath.BigDec {
if !xReserve.IsPositive() || !yReserve.IsPositive() || wSumSquares.IsNegative() {
panic("invalid input: reserves and input must be positive")
24 changes: 24 additions & 0 deletions x/gamm/pool-models/stableswap/amm_test.go
Original file line number Diff line number Diff line change
@@ -452,6 +452,30 @@ func TestCFMMInvariantMultiAssets(t *testing.T) {
}
}

func TestCFMMInvariantMultiAssetsDirect(t *testing.T) {
kErrTolerance := osmomath.OneDec()

tests := multiAssetCFMMTestCases

for name, test := range tests {
t.Run(name, func(t *testing.T) {
// system under test
sut := func() {
uReserve := calcUReserve(test.remReserves)
wSumSquares := calcWSumSquares(test.remReserves)

// using multi-asset cfmm
k2 := cfmmConstantMulti(test.xReserve, test.yReserve, uReserve, wSumSquares)
xOut2 := solveCFMMMultiDirect(test.xReserve, test.yReserve, wSumSquares, test.yIn)
k3 := cfmmConstantMulti(test.xReserve.Sub(xOut2), test.yReserve.Add(test.yIn), uReserve, wSumSquares)
osmomath.DecApproxEq(t, k2, k3, kErrTolerance)
}

osmoassert.ConditionalPanic(t, test.expectPanic, sut)
})
}
}

func TestCFMMInvariantMultiAssetsBinarySearch(t *testing.T) {
kErrTolerance := osmomath.OneDec()