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

[NonPoolSuperfluid] Use full routes instead of only one pool for pricing #8276

Merged
merged 61 commits into from
Jun 5, 2024

Conversation

nicolaslara
Copy link
Contributor

@nicolaslara nicolaslara commented May 17, 2024

Closes: #XXX

What is the purpose of the change

Allow native superfluid to use a full route instead of only one pool

Testing and Verifying

tests updated

Documentation and Release Note

  • Does this pull request introduce a new feature or user-facing behavior changes?
  • Changelog entry added to Unreleased section of CHANGELOG.md?

Where is the change documented?

  • Specification (x/{module}/README.md)
  • Osmosis documentation site
  • Code comments?
  • N/A

@nicolaslara nicolaslara added the V:state/breaking State machine breaking PR label May 23, 2024
@nicolaslara nicolaslara marked this pull request as ready for review May 23, 2024 15:09
Copy link
Contributor

coderabbitai bot commented May 23, 2024

Walkthrough

The recent changes expand support for non-pool assets in superfluid staking, enhancing functionality by integrating multi-pool arithmetic TWAP calculations. Key updates include modifying the SuperfluidAsset structure to use SwapAmountInRoute for price routes, adding validation functions, and updating relevant tests. These changes improve flexibility and accuracy in asset price calculations for superfluid staking, ensuring a more robust and versatile staking mechanism.

Changes

Files/Paths Change Summary
proto/osmosis/superfluid/superfluid.proto Imported swap_route.proto, modified SuperfluidAsset to use SwapAmountInRoute for price routes.
x/poolmanager/types/routes.go Added Equal method to SwapAmountInRoute struct for route comparison.
x/superfluid/keeper/epoch.go Updated TWAP price calculation to use GetMultiPoolArithmeticTwapToNow, adjusted SetOsmoEquivalentMultiplier parameter.
x/superfluid/keeper/epoch_test.go Updated test cases to reflect changes in SuperfluidAsset structure and price route handling.
x/superfluid/keeper/gov/gov.go Updated logic for handling superfluid assets proposals, including validation of native assets and price routes.
x/superfluid/keeper/stake.go Introduced ValidateNativeAsset function to validate native assets for superfluid staking.
x/superfluid/keeper/gov_test.go Modified nativeAsset struct in test cases to include PriceRoute.
x/superfluid/keeper/stake_test.go Updated test cases to use PriceRoute in SuperfluidAsset, added poolmanagertypes import.
x/superfluid/types/expected_keepers.go Modified TwapKeeper interface to use GetMultiPoolArithmeticTwapToNow method.
x/twap/api.go Added GetMultiPoolArithmeticTwapToNow function for multi-pool arithmetic TWAP calculation, imported necessary packages.
x/twap/api_test.go Added test function TestUnsafeGetMultiPoolArithmeticTwapToNow, imported poolmanagertypes, added poolTwoRecord variable.
x/twap/types/errors.go Added new error variables ErrEmptyRoute and ErrMismatchedQuoteAsset.
x/superfluid/keeper/integration_test.go Added functionality for reward distribution, delegation rewards, and voting in TestSuite functions, updated AddNewSuperfluidAsset parameters.

Sequence Diagram(s) (Beta)

sequenceDiagram
    participant User
    participant SuperfluidKeeper
    participant TwapKeeper
    participant PoolManager

    User->>SuperfluidKeeper: Request to add Superfluid Asset
    SuperfluidKeeper->>TwapKeeper: Validate asset using GetMultiPoolArithmeticTwapToNow
    TwapKeeper->>PoolManager: Fetch Swap Routes
    PoolManager-->>TwapKeeper: Return Swap Routes
    TwapKeeper-->>SuperfluidKeeper: Return TWAP Price
    SuperfluidKeeper-->>User: Asset Added Successfully

Poem

In the realm of code so bright,
Superfluid assets take their flight.
Routes and prices, all align,
Multi-pool paths, now so fine.
Staking flows, rewards in sight,
Osmosis' future, shining light. 🌟


Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between be2a32b and 63e48b5.

Files selected for processing (1)
  • x/superfluid/keeper/integration_test.go (11 hunks)
Files skipped from review as they are similar to previous changes (1)
  • x/superfluid/keeper/integration_test.go

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Outside diff range and nitpick comments (10)
proto/osmosis/superfluid/superfluid.proto (1)

33-35: Ensure the price_route field is properly documented.

Consider adding more detailed comments for the price_route field to explain its usage and the expected format of SwapAmountInRoute.

CHANGELOG.md (9)

Line range hint 635-635: Avoid using bare URLs; provide descriptive link text.

- * [sdk-#100](https://github.com/osmosis-labs/cosmos-sdk/pull/100) Upgrade iavl with fast storage
+ * [Upgrade iavl with fast storage](https://github.com/osmosis-labs/cosmos-sdk/pull/100)

Line range hint 693-693: Avoid using bare URLs; provide descriptive link text.

- * [iavl-5](https://github.com/osmosis-labs/iavl/pull/5) Fast storage optimization for queries and iterations
+ * [Fast storage optimization for queries and iterations](https://github.com/osmosis-labs/iavl/pull/5)

Line range hint 1033-1033: Correct the heading level for better document structure.

- #### Golang API breaks
+ ### Golang API breaks

Line range hint 1045-1045: Correct the heading level for better document structure.

- #### Bug Fixes
+ ### Bug Fixes

Line range hint 1054-1054: Correct the heading level for better document structure.

- #### Features
+ ### Features

Line range hint 1059-1059: Correct the heading level for better document structure.

- #### Minor improvements & Bug Fixes
+ ### Minor improvements & Bug Fixes

Line range hint 1111-1111: Correct the heading level for better document structure.

- #### SDK fork updates
+ ### SDK fork updates

Line range hint 372-372: Remove trailing punctuation in heading for consistency.

- ## v6.4.0.
+ ## v6.4.0

Line range hint 1274-1274: Ensure all links have descriptive text instead of being empty.

Please provide descriptive text for the link at line 1274 to improve accessibility and context.

x/superfluid/keeper/stake.go Outdated Show resolved Hide resolved
x/superfluid/keeper/gov/gov.go Show resolved Hide resolved
x/poolmanager/types/routes.go Show resolved Hide resolved
@nicolaslara nicolaslara changed the title Nicolas/superfluid btc multiple pools [NonPoolSuperfluid] Use full routes instead of only one pool for pricing May 23, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Outside diff range and nitpick comments (4)
CHANGELOG.md (4)

Line range hint 1058-1058: Adjust heading levels to increment by one level at a time for better document structure.

- ### State Breaking
+ ## State Breaking
- ### Features
+ ## Features
- ### Bug Fixes
+ ## Bug Fixes
- ### Misc Improvements
+ ## Misc Improvements
- ### SDK fork updates
+ ## SDK fork updates

Also applies to: 1070-1070, 1079-1079, 1084-1084, 1136-1136


Line range hint 397-397: Remove trailing punctuation from the heading for consistency.

- ## v6.4.0.
+ ## v6.4.0

Line range hint 660-660: Replace bare URLs with descriptive links to improve readability.

- [sdk-#100](https://github.com/osmosis-labs/cosmos-sdk/pull/100)
+ [sdk-#100](https://github.com/osmosis-labs/cosmos-sdk/pull/100 "Upgrade iavl with fast storage")

- [iavl-5](https://github.com/osmosis-labs/iavl/pull/5)
+ [iavl-5](https://github.com/osmosis-labs/iavl/pull/5 "Fast storage optimization for queries and iterations")

Also applies to: 718-718


Line range hint 1299-1299: Ensure all links are functional and not empty.

- [v6.4.0](https://github.com/osmosis-labs/osmosis/releases/tag/v6.4.0)
+ [v6.4.0](https://github.com/osmosis-labs/osmosis/releases/tag/v6.4.0 "View the v6.4.0 release details")

x/superfluid/keeper/epoch.go Show resolved Hide resolved
x/superfluid/keeper/epoch_test.go Outdated Show resolved Hide resolved
Comment on lines 483 to 484
// Validators get stake and uosmo. I think this is an issue with test setup
s.Require().Equal(2, len(validatorRewards.Rewards.Rewards))
Copy link
Member

Choose a reason for hiding this comment

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

Would like to get to the bottom of this prior to merge

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reason for this is that what gets distributed is every collected fee. That comes from checking the fee collector's balances here: https://github.com/cosmos/cosmos-sdk/blob/main/x/distribution/keeper/allocation.go#L23

Somewhere along the line, someone is sending stake to the fee collector (haven't figured out where, but I think that's ok). The behaviour of distributing that fee is correct though

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good, lets add a TODO to either prevent this other distribution from happening, or in the comments add explicit detail of where this other send is coming from and how to verify.

Copy link
Member

Choose a reason for hiding this comment

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

Double emission in test fixed here 63e48b5

Copy link
Member

@czarcas7ic czarcas7ic left a comment

Choose a reason for hiding this comment

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

Would like to see the GetMultiPoolArithmeticTwapToNow test in api_test.go, but other than that it looks fine. I will approve but I personally would like to review the test if possible before merge.

Comment on lines 483 to 484
// Validators get stake and uosmo. I think this is an issue with test setup
s.Require().Equal(2, len(validatorRewards.Rewards.Rewards))
Copy link
Member

Choose a reason for hiding this comment

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

Sounds good, lets add a TODO to either prevent this other distribution from happening, or in the comments add explicit detail of where this other send is coming from and how to verify.

x/superfluid/keeper/stake_test.go Outdated Show resolved Hide resolved
x/twap/api.go Outdated
// Only pools with two assets are considered.
// For each pool n, its base asset will be the quote asset of pool n-1. The first pool's base asset is specified
// in baseAssetDenom and the last pool's quote asset is specified in quoteAssetDenom.
func (k Keeper) GetMultiPoolArithmeticTwapToNow(
Copy link
Member

Choose a reason for hiding this comment

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

I think this needs testing in the respective api_test.go file, despite it being used in the integration test.

Would personally like to see a test case that convinces someone that the resulting twap is transformed properly to the quote asset (so maybe two very different asset precisions)

Copy link
Member

Choose a reason for hiding this comment

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

We need some warnings here for this not actually being the correct TWAP of the pair.

We want the average value of $price_{pool1} * price_{pool2}$ which is $$\text{scaling factor} * \sum_{b \in blocks} \frac{price_{pool1} * price_{pool2}}{ \text{b.block time}}$$

This PR is returning $$\left(\sum_{b \in blocks} \frac{price_{pool1}}{ b.block_time}\right) * \left(\sum_{b \in blocks} \frac{price_{pool2}}{b.block_time}\right)$$

These are not the same.

So we need to be careful about the precise usages here, or consider bucketing into many smaller intervals for a big TWAP, to improve accuracy.

Copy link
Member

Choose a reason for hiding this comment

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

TL;DR average(a*b) != average(a)*average(b)

We can add a comment saying this is likely an acceptable approximation error in the following two cases:

  • if one asset is a stable pair we are fine assuming is basically constant for the time range
  • If all assets involved are major assets, and we rely on a proto-rev cyclic arb assumption. Then the result should be within a (guess-timate) 1-3% error tolerance. (roughly ~.3% * num_pools in path to close arb)

Copy link
Member

Choose a reason for hiding this comment

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

Explanation added here 3509723, thanks for breaking this down

Copy link
Member

Choose a reason for hiding this comment

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

Also, tests and bug in the method corrected here be2a32b

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think solving it with documentation makes sense here, as what we want is the "current price of an asset through a route, based on each historical twap" even if that isn't the theoretical twap of the route.

@ValarDragon I understand that they aren't the same for a twap of the route, but do you agree that the product of averages is enough to determine an accepted price of the route at the time queried? Just double checking my understanding here, but I think for errors to accumulate we would need each pool in the route to be mispriced in the same direction.

Copy link
Member

Choose a reason for hiding this comment

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

I think its enough to determine an acceptable price in the circumstances were concerned about! The general case requires us to be careful / think about no possible tail explosions. (E.g. we don't weight pools by liquidity at time, so if you averaged across routes, or even in a route with one low liquidity pool, you could get non-sensical values)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Outside diff range and nitpick comments (1)
x/twap/api.go (1)

150-195: Consider adding more detailed documentation about the limitations and potential inaccuracies of the UnsafeGetMultiPoolArithmeticTwapToNow method to ensure users are fully aware of the conditions under which it can be used safely.

Tools
golangci-lint

166-166: undefined: Keeper

@czarcas7ic
Copy link
Member

czarcas7ic commented Jun 3, 2024

	baseAsset := baseAssetDenom
	quoteAsset := route[0].TokenOutDenom
	for _, pool := range route {
		twap, err := k.GetArithmeticTwapToNow(ctx, pool.PoolId, baseAsset, quoteAsset, startTime)
		if err != nil {
			return osmomath.Dec{}, errorsmod.Wrapf(err, "failed to get arithmetic twap for pool %d", pool.PoolId)
		}
		price = price.Mul(twap)
		// Update the assets to the next pool's base and quote assets
		baseAsset = quoteAsset
		quoteAsset = pool.TokenOutDenom
	}

	return price, nil
}

I am pretty sure the way we set quoteAsset = pool.TokenOutDenom inside the loop is wrong, we want to set it to the next pool's tokenOut, not the pool we just finished. Otherwise we are route[0].TokenOutDenom twice as the quote

I solved in this commit, but will need ACK be2a32b

@nicolaslara
Copy link
Contributor Author

Thanks for the fix and tests @czarcas7ic !

Copy link
Contributor

@PaddyMc PaddyMc left a comment

Choose a reason for hiding this comment

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

💪

@PaddyMc PaddyMc merged commit 314fcfd into main Jun 5, 2024
1 check passed
@PaddyMc PaddyMc deleted the nicolas/superfluid-btc-multiple-pools branch June 5, 2024 08:43
@coderabbitai coderabbitai bot mentioned this pull request Jun 5, 2024
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C:app-wiring Changes to the app folder C:CLI C:x/poolmanager C:x/superfluid C:x/twap Changes to the twap module V:state/breaking State machine breaking PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants