From 467940569d2ab3b62d7dec35f3174e9ed35e16aa Mon Sep 17 00:00:00 2001 From: alpo Date: Fri, 16 Jun 2023 12:34:49 -0700 Subject: [PATCH 01/12] increase min tick past canonical tick range --- x/concentrated-liquidity/types/constants.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/concentrated-liquidity/types/constants.go b/x/concentrated-liquidity/types/constants.go index 805db1aad29..68b7fdeab1d 100644 --- a/x/concentrated-liquidity/types/constants.go +++ b/x/concentrated-liquidity/types/constants.go @@ -8,7 +8,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 @@ -17,7 +17,7 @@ const ( var ( MaxSpotPrice = sdk.MustNewDecFromStr("100000000000000000000000000000000000000") - MinSpotPrice = sdk.MustNewDecFromStr("0.000000000000000001") // 10^-18 + MinSpotPrice = sdk.MustNewDecFromStr("0.000000000001") // 10^-12 MaxSqrtPrice, _ = MaxSpotPrice.ApproxRoot(2) MinSqrtPrice, _ = MinSpotPrice.ApproxRoot(2) // Supported uptimes preset to 1 ns, 1 min, 1 hr, 1D, 1W, 2W From f34cbaf257e257e42f5c211f82d47b72a7e83ae4 Mon Sep 17 00:00:00 2001 From: alpo Date: Fri, 16 Jun 2023 17:57:49 -0700 Subject: [PATCH 02/12] remove canonical tick related tests --- x/concentrated-liquidity/lp_test.go | 19 ------ x/concentrated-liquidity/tick_test.go | 86 --------------------------- 2 files changed, 105 deletions(-) diff --git a/x/concentrated-liquidity/lp_test.go b/x/concentrated-liquidity/lp_test.go index 279ed0cf0cf..ea173451c80 100644 --- a/x/concentrated-liquidity/lp_test.go +++ b/x/concentrated-liquidity/lp_test.go @@ -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, - }, } ) diff --git a/x/concentrated-liquidity/tick_test.go b/x/concentrated-liquidity/tick_test.go index d7374523249..6cf07d82775 100644 --- a/x/concentrated-liquidity/tick_test.go +++ b/x/concentrated-liquidity/tick_test.go @@ -1483,89 +1483,3 @@ func (s *KeeperTestSuite) TestGetAllInitializedTicksForPool() { }) } } - -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() - - priceTickLower, _, err := math.TickToSqrtPrice(test.lowerTick) - s.Require().NoError(err) - priceTickUpper, _, err := math.TickToSqrtPrice(test.upperTick) - s.Require().NoError(err) - - // System Under Test - newLowerTick, newUpperTick, err := cl.RoundTickToCanonicalPriceTick(test.lowerTick, test.upperTick, priceTickLower, priceTickUpper, 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) - } - }) - } -} From a9de3ef24f77c9168141669063d64ef1de2fe951 Mon Sep 17 00:00:00 2001 From: alpo Date: Sun, 18 Jun 2023 14:22:47 -0700 Subject: [PATCH 03/12] fix more test cases --- x/concentrated-liquidity/lp_test.go | 13 +++++--- x/concentrated-liquidity/math/tick_test.go | 36 ++++++++++++---------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/x/concentrated-liquidity/lp_test.go b/x/concentrated-liquidity/lp_test.go index ea173451c80..91226647b95 100644 --- a/x/concentrated-liquidity/lp_test.go +++ b/x/concentrated-liquidity/lp_test.go @@ -428,7 +428,9 @@ 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()), + // amount0Expected = (liquidity * (sqrtPriceB - sqrtPriceA)) / (sqrtPriceB * sqrtPriceA) + amount0Expected: DefaultAmt0.Sub(sdk.OneInt()), + // amount1Expected = liq * (sqrtPriceB - sqrtPriceA) amount1Expected: DefaultAmt1.Sub(sdk.OneInt()), liquidityAmount: FullRangeLiquidityAmt, underlyingLockId: 1, @@ -819,8 +821,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 calcualte 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, @@ -1031,7 +1036,6 @@ func (s *KeeperTestSuite) TestAddToPosition() { // Create a position from the parameters in the test case. positionId, _ := s.createPositionWithLockState(tc.createLockState, pool.GetId(), owner, lockCoins, tc.timeElapsed) - s.Ctx = s.Ctx.WithBlockTime(s.Ctx.BlockTime().Add(tc.timeElapsed)) preBalanceToken0 := s.App.BankKeeper.GetBalance(s.Ctx, owner, pool.GetToken0()) @@ -1056,6 +1060,7 @@ func (s *KeeperTestSuite) TestAddToPosition() { } // --- System under test --- + newPosId, newAmt0, newAmt1, err := concentratedLiquidityKeeper.AddToPosition(s.Ctx, sender, config.positionId, tc.amount0ToAdd, tc.amount1ToAdd, config.amount0Minimum, config.amount1Minimum) // config.amount0Minimum if config.expectedError != nil { diff --git a/x/concentrated-liquidity/math/tick_test.go b/x/concentrated-liquidity/math/tick_test.go index 578bbbebd8e..de25cc0a8b6 100644 --- a/x/concentrated-liquidity/math/tick_test.go +++ b/x/concentrated-liquidity/math/tick_test.go @@ -104,12 +104,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, @@ -233,25 +233,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()}, }, } @@ -424,9 +424,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, @@ -504,7 +506,7 @@ 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"), From 4984fd4243d1b360e7e402cb9f066bb9ec2daf69 Mon Sep 17 00:00:00 2001 From: alpo Date: Sun, 18 Jun 2023 16:12:09 -0700 Subject: [PATCH 04/12] recompute last high level test vector --- x/concentrated-liquidity/lp_test.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/x/concentrated-liquidity/lp_test.go b/x/concentrated-liquidity/lp_test.go index 91226647b95..a73d2416e84 100644 --- a/x/concentrated-liquidity/lp_test.go +++ b/x/concentrated-liquidity/lp_test.go @@ -429,9 +429,19 @@ func (s *KeeperTestSuite) TestWithdrawPosition() { sutConfigOverwrite: &lpTest{ // Note: subtracting one due to truncations in favor of the pool when withdrawing. // amount0Expected = (liquidity * (sqrtPriceB - sqrtPriceA)) / (sqrtPriceB * sqrtPriceA) - amount0Expected: DefaultAmt0.Sub(sdk.OneInt()), + // 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) - amount1Expected: DefaultAmt1.Sub(sdk.OneInt()), + // 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, }, From 8b3670db9d7ef562cb10fa31f2a2e751f2bd5a08 Mon Sep 17 00:00:00 2001 From: alpo Date: Mon, 19 Jun 2023 10:12:21 -0700 Subject: [PATCH 05/12] update low level tick tests to use new min tick --- x/concentrated-liquidity/math/tick_test.go | 52 +++++++++------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/x/concentrated-liquidity/math/tick_test.go b/x/concentrated-liquidity/math/tick_test.go index de25cc0a8b6..a8509fdee18 100644 --- a/x/concentrated-liquidity/math/tick_test.go +++ b/x/concentrated-liquidity/math/tick_test.go @@ -508,47 +508,39 @@ func (suite *ConcentratedMathTestSuite) TestTickToSqrtPricePriceToTick_InverseRe price: types.MinSpotPrice, 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, - }, - "smallest + min price * increment 10^6 + tick": { - price: sdk.MustNewDecFromStr("0.000000000001000001"), - tickExpected: -107999999, + "min price increment 10^6": { + price: sdk.MustNewDecFromStr("0.000001000000000000"), + tickExpected: types.MinTick + (6 * 9 * 1e6), }, - "smallest + min price * increment 10^17": { + "smallest + min price * increment 10^11": { price: sdk.MustNewDecFromStr("0.100000000000000000"), tickExpected: -9000000, }, - "smallest + min price * increment 10^18": { + "smallest + min price * increment 10^12": { price: sdk.MustNewDecFromStr("1.000000000000000000"), tickExpected: 0, }, From 1bea6782d76e9e360974ffb841fa888e70ab7c94 Mon Sep 17 00:00:00 2001 From: alpo Date: Mon, 19 Jun 2023 10:20:12 -0700 Subject: [PATCH 06/12] clean up diff --- x/concentrated-liquidity/lp_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/concentrated-liquidity/lp_test.go b/x/concentrated-liquidity/lp_test.go index 0b182b75886..7f40b269545 100644 --- a/x/concentrated-liquidity/lp_test.go +++ b/x/concentrated-liquidity/lp_test.go @@ -1046,6 +1046,7 @@ func (s *KeeperTestSuite) TestAddToPosition() { // Create a position from the parameters in the test case. positionId, _ := s.createPositionWithLockState(tc.createLockState, pool.GetId(), owner, lockCoins, tc.timeElapsed) + s.Ctx = s.Ctx.WithBlockTime(s.Ctx.BlockTime().Add(tc.timeElapsed)) preBalanceToken0 := s.App.BankKeeper.GetBalance(s.Ctx, owner, pool.GetToken0()) @@ -1070,7 +1071,6 @@ func (s *KeeperTestSuite) TestAddToPosition() { } // --- System under test --- - newPosId, newAmt0, newAmt1, err := concentratedLiquidityKeeper.AddToPosition(s.Ctx, sender, config.positionId, tc.amount0ToAdd, tc.amount1ToAdd, config.amount0Minimum, config.amount1Minimum) // config.amount0Minimum if config.expectedError != nil { From 867579212300e9124cff978d7c23dcce66f225ab Mon Sep 17 00:00:00 2001 From: alpo Date: Mon, 19 Jun 2023 10:31:25 -0700 Subject: [PATCH 07/12] add further boundary tests around min tick --- x/concentrated-liquidity/math/tick_test.go | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/x/concentrated-liquidity/math/tick_test.go b/x/concentrated-liquidity/math/tick_test.go index 00d36f21874..9db2e0b442e 100644 --- a/x/concentrated-liquidity/math/tick_test.go +++ b/x/concentrated-liquidity/math/tick_test.go @@ -818,6 +818,42 @@ func (s *ConcentratedMathTestSuite) TestSqrtPriceToTickRoundDownSpacing() { tickSpacing: defaultTickSpacing, tickExpected: types.MaxTick - defaultTickSpacing, }, + "sqrt price corresponds exactly to min tick + 1 (tick spacing 1)": { + // Calculated using TickToSqrtPrice(types.MinTick + 1) + sqrtPrice: sdk.MustNewDecFromStr("0.000001000000500000"), + 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: sdk.MustNewDecFromStr("0.000001000000499999"), + 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: sdk.MustNewDecFromStr("0.000001000000500001"), + tickSpacing: 1, + tickExpected: types.MinTick + 1, + }, + "sqrt price corresponds exactly to min tick + 2 (tick spacing 1)": { + // Calculated using TickToSqrtPrice(types.MinTick + 2) + sqrtPrice: sdk.MustNewDecFromStr("0.000001000000999999"), + 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: sdk.MustNewDecFromStr("0.000001000000999999").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: sdk.MustNewDecFromStr("0.000001000000999999").Sub(sdk.SmallestDec()), + tickSpacing: 1, + tickExpected: types.MinTick + 1, + }, } for name, tc := range testCases { s.Run(name, func() { From b84aef295f8a48adde615eda4809974d57e1ccf0 Mon Sep 17 00:00:00 2001 From: alpo Date: Tue, 20 Jun 2023 20:40:49 -0700 Subject: [PATCH 08/12] recompute tick level tests --- x/concentrated-liquidity/math/tick_test.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/x/concentrated-liquidity/math/tick_test.go b/x/concentrated-liquidity/math/tick_test.go index f46313215cf..25d7baf75e2 100644 --- a/x/concentrated-liquidity/math/tick_test.go +++ b/x/concentrated-liquidity/math/tick_test.go @@ -749,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 @@ -831,38 +835,36 @@ func (s *ConcentratedMathTestSuite) TestSqrtPriceToTickRoundDownSpacing() { tickExpected: types.MaxTick - defaultTickSpacing, }, "sqrt price corresponds exactly to min tick + 1 (tick spacing 1)": { - // Calculated using TickToSqrtPrice(types.MinTick + 1) - sqrtPrice: sdk.MustNewDecFromStr("0.000001000000500000"), + 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: sdk.MustNewDecFromStr("0.000001000000499999"), + 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: sdk.MustNewDecFromStr("0.000001000000500001"), + sqrtPrice: sqpMinTickPlusOne.Add(sdk.SmallestDec()), tickSpacing: 1, tickExpected: types.MinTick + 1, }, "sqrt price corresponds exactly to min tick + 2 (tick spacing 1)": { - // Calculated using TickToSqrtPrice(types.MinTick + 2) - sqrtPrice: sdk.MustNewDecFromStr("0.000001000000999999"), + 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: sdk.MustNewDecFromStr("0.000001000000999999").Add(sdk.SmallestDec()), + 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: sdk.MustNewDecFromStr("0.000001000000999999").Sub(sdk.SmallestDec()), + sqrtPrice: sqpMinTickPlusTwo.Sub(sdk.SmallestDec()), tickSpacing: 1, tickExpected: types.MinTick + 1, }, From bb6d2b944e02c820e74aea3e9e798285a0321971 Mon Sep 17 00:00:00 2001 From: alpo Date: Tue, 20 Jun 2023 22:43:05 -0700 Subject: [PATCH 09/12] fix migration and superfluid tests --- x/concentrated-liquidity/python/swap_test.py | 2 +- x/gamm/keeper/migrate_test.go | 21 ++++++++++++++++++- x/protorev/keeper/epoch_hook_test.go | 4 +++- .../keeper/concentrated_liquidity_test.go | 12 +++++++++-- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/x/concentrated-liquidity/python/swap_test.py b/x/concentrated-liquidity/python/swap_test.py index ccbbadafaa4..8a2b81aa1d2 100644 --- a/x/concentrated-liquidity/python/swap_test.py +++ b/x/concentrated-liquidity/python/swap_test.py @@ -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") diff --git a/x/gamm/keeper/migrate_test.go b/x/gamm/keeper/migrate_test.go index 34db1d3c7d7..9b11d491dbb 100644 --- a/x/gamm/keeper/migrate_test.go +++ b/x/gamm/keeper/migrate_test.go @@ -17,8 +17,27 @@ func (s *KeeperTestSuite) TestMigrate() { defaultGammShares := sdk.NewCoin("gamm/pool/1", sdk.MustNewDecFromStr("100000000000000000000").RoundInt()) invalidGammShares := sdk.NewCoin("gamm/pool/1", sdk.MustNewDecFromStr("190000000000000000001").RoundInt()) defaultAccountFunds := sdk.NewCoins(sdk.NewCoin("eth", sdk.NewInt(200000000000)), sdk.NewCoin("usdc", sdk.NewInt(200000000000))) + + // Explanation of additive tolerance of 100000: + // + // The balance in the CL pool should be equal to the portion of the user's previous GAMM balances that could be + // joined into a full range CL position. These are not exactly equivalent because GAMM pools covers prices (0, inf) + // while CL pools cover prices (minSpotPrice, maxSpotPrice), where minSpotPrice and maxSpotPrice are close to the GAMM + // boundaries but not exactly on them. + // + // # Base equations for full range asset amounts: + // Expected amount of asset 0: (liquidity * (maxSqrtPrice - curSqrtPrice)) / (maxSqrtPrice * curSqrtPrice) + // Expected amount of asset 1: liquidity * (curSqrtPrice - minSqrtPrice) + // + // # Using scripts in x/concentrated-liquidity/python/swap_test.py, we compute the following: + // expectedAsset0 = floor((liquidity * (maxSqrtPrice - curSqrtPrice)) / (maxSqrtPrice * curSqrtPrice)) = 99999999999.000000000000000000 + // expectedAsset1 = floor(liquidity * (curSqrtPrice - minSqrtPrice)) = 99999900000.000000000000000000 + // + // We add 1 to account for ExitPool rounding exit amount up. This is not an issue since the balance is deducted from the user regardless. + // These leaves us with full transfer of asset 0 and a (correct) transfer of asset 1 amounting to full GAMM balance minus 100000. + // We expect this tolerance to be sufficient as long as our test cases are on the same order of magnitude. defaultErrorTolerance := osmomath.ErrTolerance{ - AdditiveTolerance: sdk.NewDec(100), + AdditiveTolerance: sdk.NewDec(100000), RoundingDir: osmomath.RoundDown, } defaultJoinTime := s.Ctx.BlockTime() diff --git a/x/protorev/keeper/epoch_hook_test.go b/x/protorev/keeper/epoch_hook_test.go index ee3d85691de..e28e9c02b6f 100644 --- a/x/protorev/keeper/epoch_hook_test.go +++ b/x/protorev/keeper/epoch_hook_test.go @@ -162,7 +162,7 @@ func (s *KeeperTestSuite) TestUpdateHighestLiquidityPools() { }, expectedBaseDenomPools: map[string]map[string]keeper.LiquidityPoolStruct{ "epochTwo": { - "uosmo": {Liquidity: sdk.Int(sdk.NewUintFromString("999999999000000001000000000000000000")), PoolId: 49}, + "uosmo": {Liquidity: sdk.Int(sdk.NewUintFromString("999999000000000001000000000000000000")), PoolId: 49}, }, }, }, @@ -177,6 +177,8 @@ func (s *KeeperTestSuite) TestUpdateHighestLiquidityPools() { err := s.App.ProtoRevKeeper.UpdateHighestLiquidityPools(s.Ctx, tc.inputBaseDenomPools) s.Require().NoError(err) + fmt.Println("tc.inputBaseDenomPools: ", tc.inputBaseDenomPools) + fmt.Println("tc.expectedBaseDenomPools: ", tc.expectedBaseDenomPools) s.Require().Equal(tc.inputBaseDenomPools, tc.expectedBaseDenomPools) }) } diff --git a/x/superfluid/keeper/concentrated_liquidity_test.go b/x/superfluid/keeper/concentrated_liquidity_test.go index 7351de18bde..b0bb2d4d4f1 100644 --- a/x/superfluid/keeper/concentrated_liquidity_test.go +++ b/x/superfluid/keeper/concentrated_liquidity_test.go @@ -155,9 +155,17 @@ func (s *KeeperTestSuite) TestAddToConcentratedLiquiditySuperfluidPosition() { } s.Require().NoError(err) - // Define error tolerance + // We allow for an downward additive tolerance of 101 to accommodate our single happy path case while efficiently checking exact + // balance diffs. + // + // Using our full range asset amount equations, we get the following: + // + // expectedAsset0 = floor((liquidityDelta * (maxSqrtPrice - curSqrtPrice)) / (maxSqrtPrice * curSqrtPrice)) = 99999998.000000000000000000 + // expectedAsset1 = floor(liquidityDelta * (curSqrtPrice - minSqrtPrice)) = 99999899.000000000000000000 + // + // Note that the expected difference valid additive difference of 101 on asset 1. var errTolerance osmomath.ErrTolerance - errTolerance.AdditiveTolerance = sdk.NewDec(1) + errTolerance.AdditiveTolerance = sdk.NewDec(101) errTolerance.RoundingDir = osmomath.RoundDown postAddToPositionStakeSupply := bankKeeper.GetSupply(ctx, bondDenom) From aca6f226a515b0df91a8ebe3c994b18189c36302 Mon Sep 17 00:00:00 2001 From: alpo Date: Tue, 20 Jun 2023 22:48:51 -0700 Subject: [PATCH 10/12] clean up prints and comments --- x/protorev/keeper/epoch_hook_test.go | 2 -- x/superfluid/keeper/concentrated_liquidity_test.go | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/x/protorev/keeper/epoch_hook_test.go b/x/protorev/keeper/epoch_hook_test.go index e28e9c02b6f..60e3d3a834f 100644 --- a/x/protorev/keeper/epoch_hook_test.go +++ b/x/protorev/keeper/epoch_hook_test.go @@ -177,8 +177,6 @@ func (s *KeeperTestSuite) TestUpdateHighestLiquidityPools() { err := s.App.ProtoRevKeeper.UpdateHighestLiquidityPools(s.Ctx, tc.inputBaseDenomPools) s.Require().NoError(err) - fmt.Println("tc.inputBaseDenomPools: ", tc.inputBaseDenomPools) - fmt.Println("tc.expectedBaseDenomPools: ", tc.expectedBaseDenomPools) s.Require().Equal(tc.inputBaseDenomPools, tc.expectedBaseDenomPools) }) } diff --git a/x/superfluid/keeper/concentrated_liquidity_test.go b/x/superfluid/keeper/concentrated_liquidity_test.go index b0bb2d4d4f1..de420c7e344 100644 --- a/x/superfluid/keeper/concentrated_liquidity_test.go +++ b/x/superfluid/keeper/concentrated_liquidity_test.go @@ -155,8 +155,7 @@ func (s *KeeperTestSuite) TestAddToConcentratedLiquiditySuperfluidPosition() { } s.Require().NoError(err) - // We allow for an downward additive tolerance of 101 to accommodate our single happy path case while efficiently checking exact - // balance diffs. + // We allow for an downward additive tolerance of 101 to accommodate our single happy path case while efficiently checking exact balance diffs. // // Using our full range asset amount equations, we get the following: // From a1b7c5ccb7c350aac3ab2f69867ddc460c0b99d3 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 21 Jun 2023 15:54:59 -0500 Subject: [PATCH 11/12] Update x/concentrated-liquidity/lp_test.go --- x/concentrated-liquidity/lp_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/concentrated-liquidity/lp_test.go b/x/concentrated-liquidity/lp_test.go index 5c5669e3f60..74fdc8578a6 100644 --- a/x/concentrated-liquidity/lp_test.go +++ b/x/concentrated-liquidity/lp_test.go @@ -828,7 +828,7 @@ 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 the following equation: + // 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 From 749212c5d5df4f66eb1884748c7724eab722734a Mon Sep 17 00:00:00 2001 From: alpo Date: Wed, 21 Jun 2023 14:23:30 -0700 Subject: [PATCH 12/12] fix test names --- x/concentrated-liquidity/math/tick_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/concentrated-liquidity/math/tick_test.go b/x/concentrated-liquidity/math/tick_test.go index 25d7baf75e2..21527660572 100644 --- a/x/concentrated-liquidity/math/tick_test.go +++ b/x/concentrated-liquidity/math/tick_test.go @@ -537,11 +537,11 @@ func (suite *ConcentratedMathTestSuite) TestTickToSqrtPricePriceToTick_InverseRe price: sdk.MustNewDecFromStr("0.000001000000000000"), tickExpected: types.MinTick + (6 * 9 * 1e6), }, - "smallest + min price * increment 10^11": { + "min price * increment 10^11": { price: sdk.MustNewDecFromStr("0.100000000000000000"), tickExpected: -9000000, }, - "smallest + min price * increment 10^12": { + "min price * increment 10^12": { price: sdk.MustNewDecFromStr("1.000000000000000000"), tickExpected: 0, },