Skip to content

Commit

Permalink
[CL]: Increase min tick past canonical tick range (#5551)
Browse files Browse the repository at this point in the history
* increase min tick past canonical tick range

* remove canonical tick related tests

* fix more test cases

* recompute last high level test vector

* update low level tick tests to use new min tick

* clean up diff

* add further boundary tests around min tick

* recompute tick level tests

* fix migration and superfluid tests

* clean up prints and comments

* Update x/concentrated-liquidity/lp_test.go

* fix test names

---------

Co-authored-by: Adam Tucker <[email protected]>
  • Loading branch information
AlpinYukseloglu and czarcas7ic authored Jun 21, 2023
1 parent 45b9004 commit 90ca18a
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 163 deletions.
42 changes: 19 additions & 23 deletions x/concentrated-liquidity/lp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,25 +160,6 @@ var (
amount0Expected: DefaultAmt0Expected.Add(roundingError),
amount1Expected: DefaultAmt1Expected,
},
"use ticks that are not the canonical tick for a given price, expect them to be rounded to the proper tick": {
lowerTick: -161987600,
expectedLowerTick: -161000000,
upperTick: -160009800,
expectedUpperTick: -160000000,
currentTick: DefaultUpperTick,

isNotFirstPositionWithSameAccount: true,
positionId: 2,

liquidityAmount: sdk.MustNewDecFromStr("15731321859400083838.506717486806808937").MulInt64(2),
preSetChargeSpreadRewards: oneEth,
expectedSpreadRewardGrowthOutsideLower: oneEthCoins,
expectedSpreadRewardGrowthOutsideUpper: oneEthCoins,

// Rounding up in favor of the pool.
amount0Expected: sdk.ZeroInt(),
amount1Expected: DefaultAmt1,
},
}
)

Expand Down Expand Up @@ -447,8 +428,20 @@ func (s *KeeperTestSuite) TestWithdrawPosition() {
setupConfig: baseCase,
sutConfigOverwrite: &lpTest{
// Note: subtracting one due to truncations in favor of the pool when withdrawing.
amount0Expected: DefaultAmt0.Sub(sdk.OneInt()),
amount1Expected: DefaultAmt1.Sub(sdk.OneInt()),
// amount0Expected = (liquidity * (sqrtPriceB - sqrtPriceA)) / (sqrtPriceB * sqrtPriceA)
// Where:
// * liquidity = FullRangeLiquidityAmt
// * sqrtPriceB = MaxSqrtPrice
// * sqrtPriceA = DefaultCurrSqrtPrice
// Exact calculation: https://www.wolframalpha.com/input?i=70710678.118654752940000000+*+%2810000000000000000000.000000000000000000+-+70.710678118654752440%29+%2F+%2810000000000000000000.000000000000000000+*+70.710678118654752440%29
amount0Expected: sdk.NewInt(999999),
// amount1Expected = liq * (sqrtPriceB - sqrtPriceA)
// Where:
// * liquidity = FullRangeLiquidityAmt
// * sqrtPriceB = DefaultCurrSqrtPrice
// * sqrtPriceA = MinSqrtPrice
// Exact calculation: https://www.wolframalpha.com/input?i=70710678.118654752940000000+*+%2870.710678118654752440+-+0.000001000000000000%29
amount1Expected: sdk.NewInt(4999999929),
liquidityAmount: FullRangeLiquidityAmt,
underlyingLockId: 1,
},
Expand Down Expand Up @@ -835,8 +828,11 @@ func (s *KeeperTestSuite) TestAddToPosition() {
// 1998976eth (amount withdrawn with rounded down amounts) + 998977(token amount in)
amount0Expected: sdk.NewInt(2997953),
// tokens Provided for token1 is 9999999999 (amount withdrawn) + 5000000000 = 14999999999usdc.
// we calcualte calc amount1 by using: https://www.wolframalpha.com/input?i=70.728769315114743567+*+212041526.154556192320661969
amount1Expected: sdk.NewInt(14997436189),
// We calculate calc amount1 by using the following equation:
// liq * (sqrtPriceB - sqrtPriceA), where liq is equal to the original joined liq + added liq, sqrtPriceB is current sqrt price, and sqrtPriceA is min sqrt price.
// Note that these numbers were calculated using `GetLiquidityFromAmounts` and `TickToSqrtPrice` and thus assume correctness of those functions.
// https://www.wolframalpha.com/input?i=212041526.154556192317664016+*+%2870.728769315114743566+-+0.000001000000000000%29
amount1Expected: sdk.NewInt(14997435977),
},
timeElapsed: defaultTimeElapsed,
amount0ToAdd: amount0PerfectRatio,
Expand Down
126 changes: 79 additions & 47 deletions x/concentrated-liquidity/math/tick_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@ func (suite *ConcentratedMathTestSuite) TestTickToSqrtPrice() {
expectedPrice: types.MaxSpotPrice,
},
"Min tick and max k": {
tickIndex: -162000000,
tickIndex: types.MinTick,
expectedPrice: types.MinSpotPrice,
},
"error: tickIndex less than minimum": {
tickIndex: -162000000 - 1,
expectedError: types.TickIndexMinimumError{MinTick: -162000000},
tickIndex: types.MinTick - 1,
expectedError: types.TickIndexMinimumError{MinTick: types.MinTick},
},
"error: tickIndex greater than maximum": {
tickIndex: 342000000 + 1,
Expand Down Expand Up @@ -234,25 +234,25 @@ func (suite *ConcentratedMathTestSuite) TestTicksToSqrtPrice() {
expectedUpperPrice: sdk.MustNewDecFromStr("10733"),
},
"Max tick and min k": {
lowerTickIndex: sdk.NewInt(-162000000),
upperTickIndex: sdk.NewInt(342000000),
lowerTickIndex: sdk.NewInt(types.MinTick),
upperTickIndex: sdk.NewInt(types.MaxTick),
expectedUpperPrice: types.MaxSpotPrice,
expectedLowerPrice: types.MinSpotPrice,
},
"error: lowerTickIndex less than minimum": {
lowerTickIndex: sdk.NewInt(-162000000 - 1),
lowerTickIndex: sdk.NewInt(types.MinTick - 1),
upperTickIndex: sdk.NewInt(36073300),
expectedError: types.TickIndexMinimumError{MinTick: -162000000},
expectedError: types.TickIndexMinimumError{MinTick: types.MinTick},
},
"error: upperTickIndex greater than maximum": {
lowerTickIndex: sdk.NewInt(-162000000),
upperTickIndex: sdk.NewInt(342000000 + 1),
expectedError: types.TickIndexMaximumError{MaxTick: 342000000},
lowerTickIndex: sdk.NewInt(types.MinTick),
upperTickIndex: sdk.NewInt(types.MaxTick + 1),
expectedError: types.TickIndexMaximumError{MaxTick: types.MaxTick},
},
"error: provided lower tick and upper tick are same": {
lowerTickIndex: sdk.NewInt(-162000000),
upperTickIndex: sdk.NewInt(-162000000),
expectedError: types.InvalidLowerUpperTickError{LowerTick: sdk.NewInt(-162000000).Int64(), UpperTick: sdk.NewInt(-162000000).Int64()},
lowerTickIndex: sdk.NewInt(types.MinTick),
upperTickIndex: sdk.NewInt(types.MinTick),
expectedError: types.InvalidLowerUpperTickError{LowerTick: sdk.NewInt(types.MinTick).Int64(), UpperTick: sdk.NewInt(types.MinTick).Int64()},
},
}

Expand Down Expand Up @@ -425,9 +425,11 @@ func (suite *ConcentratedMathTestSuite) TestPriceToTickRoundDown() {
tickExpected: types.MinTick,
},
"tick spacing 100, Spot price one tick above min, one tick above min -> MinTick": {
price: types.MinSpotPrice.Add(sdk.SmallestDec()),
tickSpacing: defaultTickSpacing,
tickExpected: closestTickAboveMinPriceDefaultTickSpacing.Int64(),
price: types.MinSpotPrice.Add(sdk.SmallestDec()),
tickSpacing: defaultTickSpacing,
// Since the tick should always be the closest tick below (and `smallestDec` isn't sufficient
// to push us into the next tick), we expect MinTick to be returned here.
tickExpected: types.MinTick,
},
"tick spacing 100, Spot price one tick below max, one tick below max -> MaxTick - 1": {
price: closestPriceBelowMaxPriceDefaultTickSpacing,
Expand Down Expand Up @@ -505,49 +507,41 @@ func (suite *ConcentratedMathTestSuite) TestTickToSqrtPricePriceToTick_InverseRe
},
"min spot price": {
price: types.MinSpotPrice,
tickExpected: -162000000,
tickExpected: types.MinTick,
},
"smallest + min price increment": {
price: sdk.MustNewDecFromStr("0.000000000000000002"),
tickExpected: -161000000,
"smallest + min price + tick": {
price: sdk.MustNewDecFromStr("0.000000000001000001"),
tickExpected: types.MinTick + 1,
},
"min price increment 10^1": {
price: sdk.MustNewDecFromStr("0.000000000000000009"),
tickExpected: -154000000,
},
"smallest + min price increment 10^1": {
price: sdk.MustNewDecFromStr("0.000000000000000010"),
tickExpected: -153000000,
price: sdk.MustNewDecFromStr("0.000000000010000000"),
tickExpected: types.MinTick + (9 * 1e6),
},
"smallest + min price increment * 10^2": {
price: sdk.MustNewDecFromStr("0.000000000000000100"),
tickExpected: -144000000,
"min price increment 10^2": {
price: sdk.MustNewDecFromStr("0.000000000100000000"),
tickExpected: types.MinTick + (2 * 9 * 1e6),
},
"smallest + min price increment * 10^3": {
price: sdk.MustNewDecFromStr("0.000000000000001000"),
tickExpected: -135000000,
"min price increment 10^3": {
price: sdk.MustNewDecFromStr("0.000000001000000000"),
tickExpected: types.MinTick + (3 * 9 * 1e6),
},
"smallest + min price increment * 10^4": {
price: sdk.MustNewDecFromStr("0.000000000000010000"),
tickExpected: -126000000,
"min price increment 10^4": {
price: sdk.MustNewDecFromStr("0.000000010000000000"),
tickExpected: types.MinTick + (4 * 9 * 1e6),
},
"smallest + min price * increment 10^5": {
price: sdk.MustNewDecFromStr("0.000000000000100000"),
tickExpected: -117000000,
"min price increment 10^5": {
price: sdk.MustNewDecFromStr("0.000000100000000000"),
tickExpected: types.MinTick + (5 * 9 * 1e6),
},
"smallest + min price * increment 10^6": {
price: sdk.MustNewDecFromStr("0.000000000001000000"),
tickExpected: -108000000,
"min price increment 10^6": {
price: sdk.MustNewDecFromStr("0.000001000000000000"),
tickExpected: types.MinTick + (6 * 9 * 1e6),
},
"smallest + min price * increment 10^6 + tick": {
price: sdk.MustNewDecFromStr("0.000000000001000001"),
tickExpected: -107999999,
},
"smallest + min price * increment 10^17": {
"min price * increment 10^11": {
price: sdk.MustNewDecFromStr("0.100000000000000000"),
tickExpected: -9000000,
},
"smallest + min price * increment 10^18": {
"min price * increment 10^12": {
price: sdk.MustNewDecFromStr("1.000000000000000000"),
tickExpected: 0,
},
Expand Down Expand Up @@ -755,6 +749,10 @@ func (s *ConcentratedMathTestSuite) TestSqrtPriceToTickRoundDownSpacing() {
s.Require().NoError(err)
_, sqpMaxTickSubOne, err := math.TickToSqrtPrice(types.MaxTick - 1)
s.Require().NoError(err)
_, sqpMinTickPlusOne, err := math.TickToSqrtPrice(types.MinTick + 1)
s.Require().NoError(err)
_, sqpMinTickPlusTwo, err := math.TickToSqrtPrice(types.MinTick + 2)
s.Require().NoError(err)

testCases := map[string]struct {
sqrtPrice sdk.Dec
Expand Down Expand Up @@ -836,6 +834,40 @@ func (s *ConcentratedMathTestSuite) TestSqrtPriceToTickRoundDownSpacing() {
tickSpacing: defaultTickSpacing,
tickExpected: types.MaxTick - defaultTickSpacing,
},
"sqrt price corresponds exactly to min tick + 1 (tick spacing 1)": {
sqrtPrice: sqpMinTickPlusOne,
tickSpacing: 1,
tickExpected: types.MinTick + 1,
},
"sqrt price corresponds exactly to min tick + 1 minus 1 ULP (tick spacing 1)": {
// Calculated using TickToSqrtPrice(types.MinTick + 1) - 1 ULP
sqrtPrice: sqpMinTickPlusOne.Sub(sdk.SmallestDec()),
tickSpacing: 1,
tickExpected: types.MinTick,
},
"sqrt price corresponds exactly to min tick + 1 plus 1 ULP (tick spacing 1)": {
// Calculated using TickToSqrtPrice(types.MinTick + 1) + 1 ULP
sqrtPrice: sqpMinTickPlusOne.Add(sdk.SmallestDec()),
tickSpacing: 1,
tickExpected: types.MinTick + 1,
},
"sqrt price corresponds exactly to min tick + 2 (tick spacing 1)": {
sqrtPrice: sqpMinTickPlusTwo,
tickSpacing: 1,
tickExpected: types.MinTick + 2,
},
"sqrt price corresponds exactly to min tick + 2 plus 1 ULP (tick spacing 1)": {
// Calculated using TickToSqrtPrice(types.MinTick + 2) + 1 ULP
sqrtPrice: sqpMinTickPlusTwo.Add(sdk.SmallestDec()),
tickSpacing: 1,
tickExpected: types.MinTick + 2,
},
"sqrt price corresponds exactly to min tick + 2 minus 1 ULP (tick spacing 1)": {
// Calculated using TickToSqrtPrice(types.MinTick + 2) - 1 ULP
sqrtPrice: sqpMinTickPlusTwo.Sub(sdk.SmallestDec()),
tickSpacing: 1,
tickExpected: types.MinTick + 1,
},
}
for name, tc := range testCases {
s.Run(name, func() {
Expand Down
2 changes: 1 addition & 1 deletion x/concentrated-liquidity/python/swap_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from math import *

# Precomputed sqrt values using osmomath.MonotonicSqrt
minSqrtPrice = Decimal("0.000000001000000000")
minSqrtPrice = Decimal("0.000001000000000000")
sqrt4000 = Decimal("63.245553203367586640")
sqrt4545 = Decimal("67.416615162732695594")
sqrt4994 = Decimal("70.668238976219012614")
Expand Down
86 changes: 0 additions & 86 deletions x/concentrated-liquidity/tick_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1405,89 +1405,3 @@ func (s *KeeperTestSuite) TestValidateTickRangeIsValid() {
})
}
}

func (s *KeeperTestSuite) TestRoundTickToCanonicalPriceTick() {
tests := []struct {
name string
lowerTick int64
upperTick int64
expectedNewLowerTick int64
expectedNewUpperTick int64
expectedError error
}{
{
name: "exact upper tick for 0.000000000000000003 to exact lower tick for 0.000000000000000002",
lowerTick: -161000000,
expectedNewLowerTick: -161000000,
upperTick: -160000000,
expectedNewUpperTick: -160000000,
},
{
name: "exact upper tick for 0.000000000000000003 to inexact lower tick for 0.000000000000000002",
lowerTick: -161001234,
expectedNewLowerTick: -161000000,
upperTick: -160000000,
expectedNewUpperTick: -160000000,
},
{
name: "inexact upper tick for 0.000000000000000003 to exact lower tick for 0.000000000000000002",
lowerTick: -161000000,
expectedNewLowerTick: -161000000,
upperTick: -160001234,
expectedNewUpperTick: -160000000,
},
{
name: "inexact upper tick for 0.000000000000000003 to inexact lower tick for 0.000000000000000002",
lowerTick: -161001234,
expectedNewLowerTick: -161000000,
upperTick: -160001234,
expectedNewUpperTick: -160000000,
},
{
name: "upper tick one tick away from lower tick",
lowerTick: -161001234,
expectedNewLowerTick: -161000000,
upperTick: -160999999,
expectedNewUpperTick: -160000000,
},
{
name: "error: new upper tick is lower than new lower tick",
lowerTick: -160001234,
expectedNewLowerTick: -160000000,
upperTick: -161001234,
expectedNewUpperTick: -161000000,
expectedError: types.InvalidLowerUpperTickError{LowerTick: -160000000, UpperTick: -161000000},
},
{
name: "error: new upper tick is the same as new lower tick",
lowerTick: -160001234,
expectedNewLowerTick: -160000000,
upperTick: -160000000,
expectedNewUpperTick: -160000000,
expectedError: types.InvalidLowerUpperTickError{LowerTick: -160000000, UpperTick: -160000000},
},
}

for _, test := range tests {
s.Run(test.name, func() {
s.SetupTest()

_, sqrtPriceTickLower, err := math.TickToSqrtPrice(test.lowerTick)
s.Require().NoError(err)
_, sqrtPriceTickUpper, err := math.TickToSqrtPrice(test.upperTick)
s.Require().NoError(err)

// System Under Test
newLowerTick, newUpperTick, err := cl.RoundTickToCanonicalPriceTick(test.lowerTick, test.upperTick, sqrtPriceTickLower, sqrtPriceTickUpper, DefaultTickSpacing)

if test.expectedError != nil {
s.Require().Error(err)
s.Require().ErrorContains(err, test.expectedError.Error())
} else {
s.Require().NoError(err)
s.Require().Equal(test.expectedNewLowerTick, newLowerTick)
s.Require().Equal(test.expectedNewUpperTick, newUpperTick)
}
})
}
}
4 changes: 2 additions & 2 deletions x/concentrated-liquidity/types/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

const (
// Precomputed values for min and max tick
MinTick, MaxTick int64 = -162000000, 342000000
MinTick, MaxTick int64 = -108000000, 342000000
ExponentAtPriceOne int64 = -6
ConcentratedGasFeeForSwap = 10_000
BaseGasFeeForNewIncentive = 10_000
Expand All @@ -19,7 +19,7 @@ const (

var (
MaxSpotPrice = sdk.MustNewDecFromStr("100000000000000000000000000000000000000")
MinSpotPrice = sdk.MustNewDecFromStr("0.000000000000000001") // 10^-18
MinSpotPrice = sdk.MustNewDecFromStr("0.000000000001") // 10^-12
MaxSqrtPrice = osmomath.MustMonotonicSqrt(MaxSpotPrice)
MinSqrtPrice = osmomath.MustMonotonicSqrt(MinSpotPrice)
// Supported uptimes preset to 1 ns, 1 min, 1 hr, 1D, 1W, 2W
Expand Down
Loading

0 comments on commit 90ca18a

Please sign in to comment.