-
Notifications
You must be signed in to change notification settings - Fork 607
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
refactor(CL): change tick API from sdk.Dec to osmomath.BigDec #6033
Conversation
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.
LGTM,
The only question / concern I have is regarding state consistency, is the claim that since we are changing to minimum of 12 precision to 30 and cause we're going to a more precise precision, there will be no state break, only have spot price precision increase for future pools?
@@ -439,7 +439,7 @@ func (s *KeeperTestSuite) getInitialPositionAssets(pool types.ConcentratedPoolEx | |||
|
|||
// Calculate asset amounts that would be required to get the required spot price (rounding up on asset1 to ensure we stay in the intended tick) | |||
asset0Amount := sdk.NewInt(100000000000000) | |||
asset1Amount := sdk.NewDecFromInt(asset0Amount).Mul(requiredPrice).Ceil().TruncateInt() | |||
asset1Amount := sdk.NewDecFromInt(asset0Amount).Mul(requiredPrice.SDKDec()).Ceil().TruncateInt() |
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.
Asking to learn: for these places where we turn bigdec into sdk dec, how do we ensure it is safe to do truncations?
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.
Our underlying sqrt function operates on the sdk.Dec
.
As a result, all tick sqrt prices have 18 decimals despite being osmomath.BigDec
with precision of 36.
That is, they get computed to something like 1.123456789123456789000000000000000000` where the last 18 decimals are just zeroes.
However, our "current sqrt price" can fluctuate beyond 18th decimal.
This PR makes the API for sqrt prices to be consistently 36 decimals. However, this change is state-compatible because we simply truncate tick data from 36 to 18 decimals in different places while ensuring 18 decimals by the sqrt function despite having a 36 decimal API.
In the future, this change will allow us to have two strategies for computing sqrt prices from ticks and vice versa. One with 18 decimals, and the other one with 36. As a result, we will be able to lower our min spot price for the strategy with 36 decimals. 18 decimals will continue to exist as is, thus, not requiring a state migration
Tried to cover the state-break concerns in this reply. This PR will be validated against state breaks by synching a v16 node upon approval. Additionally, note that we are not changing precision from 10^-12 to 10^-30. This change will allow us to do the following in the future:
Supporting two kinds of tick conversions will let us avoid having to do a state migration for currently existing CL pools Please let me know if further questions. |
99349ff
to
d7c6129
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.
Ok, I think the change makes sense to me, also please make sure you test this on a node and have it running for a day or so to test this is not state breaking!
func (s oneForZeroStrategy) ComputeSwapWithinBucketOutGivenIn(sqrtPriceCurrent osmomath.BigDec, sqrtPriceTarget, liquidity, amountOneInRemaining sdk.Dec) (osmomath.BigDec, sdk.Dec, sdk.Dec, sdk.Dec) { | ||
sqrtPriceTargetBigDec := osmomath.BigDecFromSDKDec(sqrtPriceTarget) | ||
func (s oneForZeroStrategy) ComputeSwapWithinBucketOutGivenIn(sqrtPriceCurrent, sqrtPriceTarget osmomath.BigDec, liquidity, amountOneInRemaining sdk.Dec) (osmomath.BigDec, sdk.Dec, sdk.Dec, sdk.Dec) { | ||
liquidityBigDec := osmomath.BigDecFromSDKDec(liquidity) | ||
amountOneInRemainingBigDec := osmomath.BigDecFromSDKDec(amountOneInRemaining) |
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.
Example link
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.
LGTM, nice work, especially with the cleanup of all the Dec -> BigDec conversions
@@ -200,7 +201,7 @@ func (k Keeper) prepareBalancerPoolAsFullRange(ctx sdk.Context, clPoolId uint64, | |||
// Calculate the amount of liquidity the Balancer amounts qualify in the CL pool. Note that since we use the CL spot price, this is | |||
// safe against prices drifting apart between the two pools (we take the lower bound on the qualifying liquidity in this case). | |||
// The `sqrtPriceLowerTick` and `sqrtPriceUpperTick` fields are set to the appropriate values for a full range position. | |||
qualifyingFullRangeSharesPreDiscount := math.GetLiquidityFromAmounts(clPool.GetCurrentSqrtPrice(), types.MinSqrtPrice, types.MaxSqrtPrice, asset0Amount, asset1Amount) | |||
qualifyingFullRangeSharesPreDiscount := math.GetLiquidityFromAmounts(clPool.GetCurrentSqrtPrice(), osmomath.BigDecFromSDKDec(types.MinSqrtPrice), osmomath.BigDecFromSDKDec(types.MaxSqrtPrice), asset0Amount, asset1Amount) |
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.
Out of curiosity, is there a reason we cast here instead of just directly changing types.MinSqrtPrice
and types.MaxSqrtPrice
? Is this mainly to keep v1 pools on old precision?
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'm planning to change that incrementally in a future refactor.
Many of the tests / other logic still rely on min and max being `sdk.Dec so I've been trying to limit the scope of changes in this PR
tickSpacing: 1, | ||
tickExpected: types.MinInitializedTick + 2, | ||
}, | ||
"sqrt price corresponds exactly to min tick + 2 minus 1 ULP (tick spacing 1)": { | ||
// Calculated using TickToSqrtPrice(types.MinInitializedTick + 2) - 1 ULP | ||
sqrtPrice: sqpMinTickPlusTwo.Sub(sdk.SmallestDec()), | ||
sqrtPrice: sqpMinTickPlusTwo.Sub(sdkULP), |
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.
Not sure if it's worth the time to convert these to be actual 1 ULP diffs, but just flagging that using sdkULP
tests a qualitatively very different thing (the original tests were essentially very granular boundary checks)
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.
Not sure what you mean here. It should still be equivalent to the previous logic sdkULP
is 10^-18 which is the same as sdk.SmallestDec()
.
Followed up in DM
* refactor(CL): change tick API from sdk.Dec to osmomath.BigDec * changelog (cherry picked from commit 36e7201) # Conflicts: # CHANGELOG.md # x/concentrated-liquidity/math/tick.go # x/concentrated-liquidity/math/tick_test.go # x/concentrated-liquidity/position_test.go # x/concentrated-liquidity/swaps.go # x/concentrated-liquidity/swaps_tick_cross_test.go
* refactor(CL): change tick API from sdk.Dec to osmomath.BigDec * changelog (cherry picked from commit 36e7201)
* refactor(CL): change tick API from sdk.Dec to osmomath.BigDec * changelog (cherry picked from commit 36e7201)
* refactor(CL): change tick API from sdk.Dec to osmomath.BigDec * changelog
* refactor(CL): change tick API from sdk.Dec to osmomath.BigDec * changelog (cherry picked from commit 36e7201)
…#6262) * refactor(CL): change tick API from sdk.Dec to osmomath.BigDec * changelog (cherry picked from commit 36e7201) Co-authored-by: Roman <[email protected]>
…#6245) * refactor(CL): change tick API from sdk.Dec to osmomath.BigDec * changelog (cherry picked from commit 36e7201) Co-authored-by: Roman <[email protected]>
Closes: #6032
What is the purpose of the change
Please see #6032 for a detailed explanation of the motivations behind this refactor.
The primary reason for doing this is to have an
osmomath.BigDec
API in tick conversions to later allow us to support pools withsdk.Dec
osmomath.BigDec
sqrt price ticks. This will allow us to support pools with min spot price of 10^-12 and 10^-30 without migrations.A secondary benefit of this refactor is minimizing conversions between
osmomath.BigDec
andsdk.Dec
due to poor choice of API when doing #5612 pre-launch.This change is expected to be fully state-compatible. To confirm, a node should be synched starting from v16.0.0
TDD: https://app.clickup.com/37420681/v/dc/13nzm9-22453
Testing and Verifying
swap_test.go
andlp_test.go
), proving that there should be no changes to the logic, only the APIs.Documentation and Release Note
Unreleased
section ofCHANGELOG.md
?Where is the change documented?
x/{module}/README.md
)