-
Notifications
You must be signed in to change notification settings - Fork 629
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
[x/gamm][Refactor] New AMM interface #1066
Conversation
@ValarDragon Is my understanding correct that you need review on the first two commits on this PR and see if #1051 would be unnecessary and go with the design you proposed in this PR? |
Yup! That'd be great |
e1b4187
to
d6c1062
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
concept Ack!
Just out of curiosity, what's the difference between amm.go and balancer_pool.go?
x/gamm/pool-models/balancer/amm.go
Outdated
func (p Pool) parsePoolAssetsByDenoms(tokenADenom, tokenBDenom string) ( | ||
Aasset types.PoolAsset, Basset types.PoolAsset, err error) { | ||
Aasset, found1 := types.GetPoolAssetByDenom(p.PoolAssets, tokenADenom) | ||
Basset, found2 := types.GetPoolAssetByDenom(p.PoolAssets, tokenBDenom) | ||
if !(found1 && found2) { | ||
return Aasset, Basset, errors.New("TODO: fill message here") | ||
} | ||
return Aasset, Basset, nil | ||
} | ||
|
||
func (p Pool) parsePoolAssets(tokensA sdk.Coins, tokenBDenom string) ( | ||
tokenA sdk.Coin, Aasset types.PoolAsset, Basset types.PoolAsset, err error) { | ||
if len(tokensA) != 1 { | ||
return tokenA, Aasset, Basset, errors.New("TODO: Fill message here") | ||
} | ||
Aasset, Basset, err = p.parsePoolAssetsByDenoms(tokensA[0].Denom, tokenBDenom) | ||
return tokensA[0], Aasset, Basset, err | ||
} | ||
|
||
// CalcOutAmtGivenIn calculates token to be swapped out given |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this approach where poolAssets are no longer poolI but went in balancerPoolAsset
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, this separation between assets / pool is definitely the way
My goal was to put all the math public functions in amm.go, and everything else moved to balancer_pool.go |
fdf1dbe
to
fe3ee9b
Compare
- Does not update JoinPool, will be done in next commit This implements swap, and exit pool for the keeper, both using the AMM interface correctly
fe3ee9b
to
0fe0f42
Compare
43ba32e
to
ad77fc7
Compare
ad77fc7
to
671fa00
Compare
JoinPool logic now added, with the multi-asset non-even liquidity code added (but untested). We mainly need to add tests ala #1116 for each of the perfect inverse between joinpool / exit pool. I mostly want to check via test more of the edge case around rounding for JoinPoolNoSwap happens correctly. (No extra iterations through the single asset adds) Remaining items for this PR:
|
4caf3b5
to
7f3238a
Compare
- Swap spot price args temporarily to be the old style (which should change to new one) - Spot price rounding fix (needed weight to be decimal) - Change tests to get spot price from keeper, not pool directly - Fix bug in CalcAmountOutGivenIn - Add accounting for TokenInMaxs being nil - Add breaking change note for tokenInMaxs needs 0 coins or all coins
7f3238a
to
f127eaf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall it looks like a great change. Merging multiple swap methods is awesome.
GetTotalLpBalances(ctx sdk.Context) sdk.Coins | ||
GetTotalShares() sdk.Int | ||
|
||
CalcOutAmtGivenIn(ctx sdk.Context, tokenIn sdk.Coins, tokenOutDenom string, swapFee sdk.Dec) (tokenOut sdk.DecCoin, err error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need different method for InOut and OutIn? I think it would not be a hassle to implement just two methods, so it will be fine, but just wanted to make sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason was because of swap fee handling and liquidity during high volatility. One goal I didn't really document anywhere was enabling assymetric swap fees from the underlying AMM. I think the future of AMM's is that they track volatility themselves, and have different swap fees (Spreads) depending on the direction the trade is going during high volatility, and change the amount of effective liquidity. Similar to real market makers!
The alternative is we make the AMM interface do that, but I think the generality may suffer a bit
x/gamm/pool-models/balancer/amm.go
Outdated
func (p Pool) parsePoolAssetsByDenoms(tokenADenom, tokenBDenom string) ( | ||
Aasset types.PoolAsset, Basset types.PoolAsset, err error) { | ||
Aasset, found1 := types.GetPoolAssetByDenom(p.PoolAssets, tokenADenom) | ||
Basset, found2 := types.GetPoolAssetByDenom(p.PoolAssets, tokenBDenom) | ||
if !(found1 && found2) { | ||
return Aasset, Basset, errors.New("TODO: fill message here") | ||
} | ||
return Aasset, Basset, nil | ||
} | ||
|
||
func (p Pool) parsePoolAssets(tokensA sdk.Coins, tokenBDenom string) ( | ||
tokenA sdk.Coin, Aasset types.PoolAsset, Basset types.PoolAsset, err error) { | ||
if len(tokensA) != 1 { | ||
return tokenA, Aasset, Basset, errors.New("TODO: Fill message here") | ||
} | ||
Aasset, Basset, err = p.parsePoolAssetsByDenoms(tokensA[0].Denom, tokenBDenom) | ||
return tokensA[0], Aasset, Basset, err | ||
} | ||
|
||
// CalcOutAmtGivenIn calculates token to be swapped out given |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, this separation between assets / pool is definitely the way
// TODO: Ensure this can only be called via gamm | ||
// TODO: Think through the API guarantees this is providing in conjunction with the caller being | ||
// expected to Set the pool into state as well. | ||
ApplySwap(ctx sdk.Context, tokenIn sdk.Coins, tokenOut sdk.Coins) error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great interface! Maybe add shareIn, shareOut sdk.Int
to capture shareswap case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting idea. At the moment JoinPool / ExitPool be mutative. (This is because I made iterative logic in the join pool code, which would be harder if it was non mutative)
wdyt about those being mutative, vs an "apply liquidity change" method?
@@ -24,6 +24,7 @@ service Msg { | |||
} | |||
|
|||
// ===================== MsgJoinPool | |||
// This is really MsgJoinPoolNoSwap |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we rename the protobuf message name, or does it break things?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we can rename the struct, but we can't rename the amino route :/
Renaming any amino routes has to be blocked until we get a solution for #1017
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think we should rename the struct but not the amino route? Is that more or less confusing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work!
Left a few comments about error checks and nits.
Codecov Report
@@ Coverage Diff @@
## main #1066 +/- ##
==========================================
- Coverage 20.76% 19.59% -1.17%
==========================================
Files 199 200 +1
Lines 25649 25940 +291
==========================================
- Hits 5326 5083 -243
- Misses 19360 19950 +590
+ Partials 963 907 -56
Continue to review full report at Codecov.
|
All comments addressed! |
Closes: #XXX
Description
(WIP) New AMM interface in preparation for implementing stableswap. This PR is intended to be reviewed commit by commit.
The order of commits right now is:
Changes I want to still make:
It turns out that we can do most of the CFMM optimization at a higher layer of abstraction, so I no longer think its worth making more CFMM scaffolding atm. Please let me know your thoughts after taking a look as well! I think the main thing in favor of CFMM scaffolding is further simplifying the amm.go file, but I don't think its that much code duplication atm.
For contributor use:
docs/
) or specification (x/<module>/spec/
)Unreleased
section inCHANGELOG.md
Files changed
in the Github PR explorer