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

[x/gamm][Refactor] New AMM interface #1066

Merged
merged 14 commits into from
Mar 22, 2022
Merged

[x/gamm][Refactor] New AMM interface #1066

merged 14 commits into from
Mar 22, 2022

Conversation

ValarDragon
Copy link
Member

@ValarDragon ValarDragon commented Mar 10, 2022

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:

  • Defining new Pool interface
  • Make balancer pool implement new API
  • Comment out some files that I think we should fix in future PR
  • (In progress) Change keeper logic to compile
    • Status:
    • ExitPool
      • Keeper side done
      • Balancer side done
    • Swap
      • Balancer side done
      • Keeper side done
    • JoinPool
      • Keeper side needs big refactor
      • Balancer side simple, still needs to be done
      • This is the big breaking change
    • CreatePool
      • TBD on what even the right structure should be. For now just get something thats maybe awkward that works.

Changes I want to still make:

  • Change MsgJoinSwapExternAmountIn take in Coins instead of just Coin.
  • Write a document detailing design decisions here. E.g.
  • Fix queries for pool assets
  • Move poolassets.go to balancer types, and have everything new just use sdk.Coins in a simpler way. (Maybe we fix balancer in a second PR w/ migration logic)
  • Make an interface for MsgCreatePools

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:

  • Targeted PR against correct branch (see CONTRIBUTING.md)
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/)
  • Added a relevant changelog entry to the Unreleased section in CHANGELOG.md
  • Re-reviewed Files changed in the Github PR explorer

@ValarDragon ValarDragon added state-machine-breaking C:x/gamm Changes, features and bugs related to the gamm module. labels Mar 10, 2022
@czarcas7ic czarcas7ic mentioned this pull request Mar 10, 2022
6 tasks
@mattverse
Copy link
Member

@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?

@ValarDragon
Copy link
Member Author

Yup! That'd be great

@ValarDragon ValarDragon force-pushed the dev/new_amm_interface branch from e1b4187 to d6c1062 Compare March 10, 2022 22:37
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.

concept Ack!
Just out of curiosity, what's the difference between amm.go and balancer_pool.go?

Comment on lines 38 to 57
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
Copy link
Member

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

Copy link
Collaborator

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

@ValarDragon
Copy link
Member Author

My goal was to put all the math public functions in amm.go, and everything else moved to balancer_pool.go

@ValarDragon ValarDragon force-pushed the dev/new_amm_interface branch 4 times, most recently from fdf1dbe to fe3ee9b Compare March 17, 2022 02:01
- 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
@ValarDragon ValarDragon force-pushed the dev/new_amm_interface branch from fe3ee9b to 0fe0f42 Compare March 17, 2022 05:28
@ValarDragon ValarDragon force-pushed the dev/new_amm_interface branch from 43ba32e to ad77fc7 Compare March 19, 2022 23:55
@ValarDragon ValarDragon force-pushed the dev/new_amm_interface branch from ad77fc7 to 671fa00 Compare March 20, 2022 05:21
@ValarDragon
Copy link
Member Author

ValarDragon commented Mar 20, 2022

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:

  • (maybe) CreatePoolMsg interface
  • Fixing tests
    • Appears that most of them right now are due to spot price params changing. I think we just need to switch them around.

@ValarDragon ValarDragon force-pushed the dev/new_amm_interface branch 3 times, most recently from 4caf3b5 to 7f3238a Compare March 21, 2022 03:10
@ValarDragon ValarDragon marked this pull request as ready for review March 21, 2022 03:10
- 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
@ValarDragon ValarDragon force-pushed the dev/new_amm_interface branch from 7f3238a to f127eaf Compare March 21, 2022 03:24
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.

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)
Copy link
Collaborator

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

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

Comment on lines 38 to 57
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
Copy link
Collaborator

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
Copy link
Collaborator

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?

Copy link
Member Author

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
Copy link
Collaborator

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?

Copy link
Member Author

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

Copy link
Member Author

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?

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!

Left a few comments about error checks and nits.

@codecov-commenter
Copy link

codecov-commenter commented Mar 22, 2022

Codecov Report

Merging #1066 (bb23596) into main (5b1d86f) will decrease coverage by 1.16%.
The diff coverage is 37.01%.

@@            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     
Impacted Files Coverage Δ
x/gamm/genesis.go 71.42% <ø> (+3.42%) ⬆️
x/gamm/keeper/invariants.go 0.00% <ø> (-14.93%) ⬇️
x/gamm/keeper/msg_server.go 2.79% <0.00%> (-0.02%) ⬇️
x/gamm/pool-models/balancer/amm.go 0.00% <0.00%> (ø)
x/gamm/types/pool.go 0.00% <ø> (ø)
x/gamm/types/pool_asset.go 0.00% <0.00%> (ø)
x/gamm/pool-models/balancer/balancer_pool.go 59.51% <3.44%> (-7.76%) ⬇️
x/gamm/keeper/pool.go 68.00% <33.33%> (-1.68%) ⬇️
x/superfluid/keeper/epoch.go 67.92% <50.00%> (ø)
x/gamm/keeper/share.go 63.63% <61.53%> (-6.37%) ⬇️
... and 15 more

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 5b1d86f...bb23596. Read the comment docs.

@ValarDragon
Copy link
Member Author

All comments addressed!

@ValarDragon ValarDragon merged commit f1389ee into main Mar 22, 2022
@ValarDragon ValarDragon deleted the dev/new_amm_interface branch March 22, 2022 18:49
@p0mvn p0mvn mentioned this pull request May 9, 2022
12 tasks
@p0mvn p0mvn changed the title New AMM interface [x/gamm][Refactor] New AMM interface May 9, 2022
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.

5 participants