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

Stableswap: LP logic #1419

Merged
merged 19 commits into from
May 17, 2022
Merged

Stableswap: LP logic #1419

merged 19 commits into from
May 17, 2022

Conversation

ValarDragon
Copy link
Member

Component of: #1406

What is the purpose of the change

This PR abstracts the Balancer logic for exit pool, and JoinPoolNoSwap logic to internal code usable by both balancer and stableswap.

This PR then adds these functions to stableswap. What is missing from stableswap after this is then the logic for single asset LP'ing. I plan on doing that tomorrow, it will be more logically intense, so I was thinking of doing it in a separate PR to keep this one simple to review, if folks think that is a good plan.

Testing and Verifying

  • Balancer changes are covered by existing tests.
  • This lends some degree of confidence to their correctness within stableswap, as this code is reused.
  • Stableswap needs similar tests. This should imo be done by abstracting the inverse relation tests to allow more pools as input. Cref #{TODO create an issue}

Documentation and Release Note

  • Does this pull request introduce a new feature or user-facing behavior changes? yes
  • Is a relevant changelog entry added to the Unreleased section in CHANGELOG.md? No
  • How is the feature or change documented? Needs documentation within stableswap spec

@ValarDragon ValarDragon requested a review from a team May 5, 2022 04:15
@github-actions github-actions bot added the C:x/gamm Changes, features and bugs related to the gamm module. label May 5, 2022
@ValarDragon ValarDragon requested a review from mconcat May 5, 2022 04:16
@codecov-commenter
Copy link

codecov-commenter commented May 5, 2022

Codecov Report

Merging #1419 (ea60872) into main (f149135) will increase coverage by 0.04%.
The diff coverage is 36.04%.

@@            Coverage Diff             @@
##             main    #1419      +/-   ##
==========================================
+ Coverage   19.50%   19.55%   +0.04%     
==========================================
  Files         231      235       +4     
  Lines       31527    31607      +80     
==========================================
+ Hits         6150     6181      +31     
- Misses      24251    24297      +46     
- Partials     1126     1129       +3     
Impacted Files Coverage Δ
x/gamm/pool-models/balancer/amm.go 25.37% <0.00%> (+3.76%) ⬆️
x/gamm/pool-models/stableswap/amm.go 44.20% <0.00%> (-7.06%) ⬇️
x/gamm/pool-models/stableswap/pool.go 0.00% <0.00%> (ø)
osmoutils/binary_search.go 79.48% <79.48%> (ø)
osmoutils/dec_helper.go 0.00% <0.00%> (ø)
osmoutils/cache_ctx.go 0.00% <0.00%> (ø)
osmoutils/cli_helpers.go 0.00% <0.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9463346...ea60872. Read the comment docs.

Comment on lines +41 to +43
if exitAmt.GTE(asset.Amount) {
return sdk.Coins{}, errors.New("too many shares out")
}
Copy link
Member Author

@ValarDragon ValarDragon May 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is new, but solves an edge case bug with potential rounding errors in the exitAmt multiplication.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for adding more comments as well

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

srry I'm not sure I follow here, could you explain why we're comparing share amount with the actual asset amount?

Copy link
Member Author

@ValarDragon ValarDragon May 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exitAmt isn't a share amount. Its a ratio * assets = assets. (Ratios are unitless!)

ValarDragon and others added 2 commits May 5, 2022 10:56
@ValarDragon ValarDragon force-pushed the dev/stableswap_rem branch from 8169edd to e9fca05 Compare May 6, 2022 05:46
@ValarDragon ValarDragon changed the title Stableswap: Simple parts of LPing Stableswap: LP logic May 6, 2022
@ValarDragon
Copy link
Member Author

ValarDragon commented May 6, 2022

Next steps:

If this PR is growing too large, I'm happy to cut out the single asset join logic into a second PR, which is where all the complexity here is.

Copy link
Member

@p0mvn p0mvn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work!

In terms of whether to split this, I think it would be great to get this approved and merged and continue the work in a separate PR / branch

// (by path-independence, swap all of B -> A, and then swap all of C -> A will yield same amount of A, regardless
// of order and interleaving)
//
// This implementation all of pool.GetTotalPoolLiquidity, pool.ExitPool, and pool.SwapExactAmountIn to not
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// This implementation all of pool.GetTotalPoolLiquidity, pool.ExitPool, and pool.SwapExactAmountIn to not
// This implementation includes calls to all of pool.GetTotalPoolLiquidity, pool.ExitPool, and pool.SwapExactAmountIn to not

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to consider just mentioning that this function updates state. Function specs shouldn't go into detail about implementation

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is that we rely on calls to those pool functions not modifying state, only the pool struct, despite the functions taking in the context.

(So it only supports a subset of pools, which is at the moment all of our current pools. I think our DeFi plans should remove this soon)

x/gamm/pool-models/internal/cfmm_common/lp.go Outdated Show resolved Hide resolved
Comment on lines +41 to +43
if exitAmt.GTE(asset.Amount) {
return sdk.Coins{}, errors.New("too many shares out")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for adding more comments as well

x/gamm/pool-models/internal/cfmm_common/lp.go Show resolved Hide resolved
x/gamm/pool-models/internal/cfmm_common/lp.go Show resolved Hide resolved
x/gamm/pool-models/internal/cfmm_common/lp.go Show resolved Hide resolved

// Creates a pool with tokenIn liquidity added, where it created `sharesIn` number of shares.
// Returns how many tokens you'd get, if you then exited all of `sharesIn` for tokenIn.Denom
estimateCoinOutGivenShares := func(sharesIn sdk.Int) (tokenOut sdk.Int, err error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about making this an actual function so that it can be unit tested?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on this comment!

x/gamm/pool-models/internal/cfmm_common/lp.go Show resolved Hide resolved
x/gamm/pool-models/internal/cfmm_common/lp.go Show resolved Hide resolved
x/gamm/pool-models/stableswap/amm.go Show resolved Hide resolved
@ValarDragon
Copy link
Member Author

Thanks for the review on this!!

Copy link
Member

@mattverse mattverse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM!

I'm surprised how this PR kinda puts all the particles of stable swap together! 🚀

osmoutils/binary_search.go Outdated Show resolved Hide resolved

expectedCompareResult int8
}{
{"0 tolerance: <", ZeroErrTolerance, sdk.NewInt(1000), sdk.NewInt(1001), -1},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

func TestBinarySearch(t *testing.T) {
// straight line function that returns input. Simplest to binary search on,
// binary search directly reveals one bit of the answer in each iteration with this function.
lineF := func(a sdk.Int) (sdk.Int, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x/gamm/pool-models/internal/cfmm_common/lp.go Show resolved Hide resolved
Comment on lines +41 to +43
if exitAmt.GTE(asset.Amount) {
return sdk.Coins{}, errors.New("too many shares out")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

srry I'm not sure I follow here, could you explain why we're comparing share amount with the actual asset amount?

correctnessThreshold := sdk.NewInt(2)
maxIterations := 512
// upperbound of number of LP shares = existingShares * tokenIn.Amount / pool.totalLiquidity.AmountOf(tokenIn.Denom)
existingTokenLiquidity := pool.GetTotalPoolLiquidity(ctx).AmountOf(tokenIn.Denom)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need ctx as a parameter in the first place for GetTotalPoolLiquidity if we're using a dummy ctx? Do you think we can erase ctx for those methods in poolI that takes ctx but does not use it in a separate issue?


// Creates a pool with tokenIn liquidity added, where it created `sharesIn` number of shares.
// Returns how many tokens you'd get, if you then exited all of `sharesIn` for tokenIn.Denom
estimateCoinOutGivenShares := func(sharesIn sdk.Int) (tokenOut sdk.Int, err error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on this comment!


return swapAllCoinsToSingleAsset(poolWithUpdatedLiquidity, ctx, exitedCoins, swapToDenom)
}
// TODO: Come back and revisit err tolerance
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the exact task that this TODO is mentioning? Is it referring to creating test cases?

@@ -0,0 +1,95 @@
package osmoutils
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the standard for methods that go into osmoutils package and methods that stay within a specific package?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. Right now I think the answer is things that seem generally re-usable, but not super well abstracted / haven't found a proper home in the code yet.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, they could plausibly belong in osmomath

Copy link
Collaborator

@mconcat mconcat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some of comments!

osmoutils/binary_search.go Outdated Show resolved Hide resolved
osmoutils/binary_search.go Show resolved Hide resolved
Comment on lines 117 to 118
correctnessThreshold := sdk.NewInt(2)
maxIterations := 512
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 256 is enough to reduce down to single digit while dealing with Int256

@ValarDragon ValarDragon merged commit f304ed8 into main May 17, 2022
@ValarDragon ValarDragon deleted the dev/stableswap_rem branch May 17, 2022 08:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C:x/gamm Changes, features and bugs related to the gamm module.
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

6 participants