diff --git a/tests/cl-genesis-positions/convert.go b/tests/cl-genesis-positions/convert.go index b4b7698769b..b5f44b8a5d8 100644 --- a/tests/cl-genesis-positions/convert.go +++ b/tests/cl-genesis-positions/convert.go @@ -156,15 +156,15 @@ func ConvertSubgraphToOsmosisGenesis(positionCreatorAddresses []sdk.AccAddress, panic(err) } - if lowerTickOsmosis.GT(upperTickOsmosis) { + if lowerTickOsmosis > upperTickOsmosis { fmt.Printf("lowerTickOsmosis (%s) > upperTickOsmosis (%s), skipping", lowerTickOsmosis, upperTickOsmosis) continue } - if lowerTickOsmosis.Equal(upperTickOsmosis) { + if lowerTickOsmosis == upperTickOsmosis { // bump up the upper tick by one. We don't care about having exactly the same tick range // Just a roughly similar breakdown - upperTickOsmosis = upperTickOsmosis.Add(sdk.OneInt()) + upperTickOsmosis = upperTickOsmosis + 1 } depositedAmount0, failedParsing := parseStringToInt(uniV3Position.DepositedToken0) @@ -186,8 +186,8 @@ func ConvertSubgraphToOsmosisGenesis(positionCreatorAddresses []sdk.AccAddress, position, err := clMsgServer.CreatePosition(sdk.WrapSDKContext(osmosis.Ctx), &cltypes.MsgCreatePosition{ PoolId: poolId, Sender: randomCreator.String(), - LowerTick: lowerTickOsmosis.Int64(), - UpperTick: upperTickOsmosis.Int64(), + LowerTick: lowerTickOsmosis, + UpperTick: upperTickOsmosis, TokensProvided: tokensProvided, TokenMinAmount0: sdk.ZeroInt(), TokenMinAmount1: sdk.ZeroInt(), @@ -208,8 +208,8 @@ func ConvertSubgraphToOsmosisGenesis(positionCreatorAddresses []sdk.AccAddress, JoinTime: osmosis.Ctx.BlockTime().Format("2006-01-02T15:04:05Z"), // ISO 8601 Liquidity: position.LiquidityCreated.String(), PositionID: strconv.FormatUint(position.PositionId, 10), - LowerTick: lowerTickOsmosis.String(), - UpperTick: upperTickOsmosis.String(), + LowerTick: strconv.FormatInt(lowerTickOsmosis, 10), + UpperTick: strconv.FormatInt(upperTickOsmosis, 10), }) } diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 63f60d3ee92..15df18bc7d3 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -30,7 +30,7 @@ import ( v16 "github.com/osmosis-labs/osmosis/v15/app/upgrades/v16" "github.com/osmosis-labs/osmosis/v15/tests/e2e/configurer/config" "github.com/osmosis-labs/osmosis/v15/tests/e2e/initialization" - cl "github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity" + clmath "github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/math" cltypes "github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/types" ) @@ -222,7 +222,7 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { concentratedPool := s.updatedPool(chainANode, poolID) // Sanity check that pool initialized with valid parameters (the ones that we haven't explicitly specified) - s.Require().Equal(concentratedPool.GetCurrentTick(), sdk.ZeroInt()) + s.Require().Equal(concentratedPool.GetCurrentTick().Int64(), int64(0)) s.Require().Equal(concentratedPool.GetCurrentSqrtPrice(), sdk.ZeroDec()) s.Require().Equal(concentratedPool.GetLiquidity(), sdk.ZeroDec()) @@ -231,7 +231,7 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { s.Require().Equal(concentratedPool.GetToken0(), denom0) s.Require().Equal(concentratedPool.GetToken1(), denom1) s.Require().Equal(concentratedPool.GetTickSpacing(), tickSpacing) - s.Require().Equal(concentratedPool.GetExponentAtPriceOne(), cltypes.ExponentAtPriceOne) + s.Require().Equal(concentratedPool.GetExponentAtPriceOne().Int64(), cltypes.ExponentAtPriceOne) s.Require().Equal(concentratedPool.GetSwapFee(sdk.Context{}), sdk.MustNewDecFromStr(swapFee)) fundTokens := []string{"100000000uosmo", "100000000uion", "100000000stake"} @@ -365,15 +365,15 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { // * Uncollected fees from multiple swaps are correctly summed up and collected // tickOffset is a tick index after the next initialized tick to which this swap needs to move the current price - tickOffset := sdk.NewInt(300) + tickOffset := int64(300) sqrtPriceBeforeSwap = concentratedPool.GetCurrentSqrtPrice() liquidityBeforeSwap = concentratedPool.GetLiquidity() - nextInitTick := sdk.NewInt(40000) // address1 position1's upper tick + nextInitTick := int64(40000) // address1 position1's upper tick // Calculate sqrtPrice after and at the next initialized tick (upperTick of address1 position1 - 40000) - _, sqrtPriceAfterNextInitializedTick, err := cl.TickToSqrtPrice(nextInitTick.Add(tickOffset)) + _, sqrtPriceAfterNextInitializedTick, err := clmath.TickToSqrtPrice(nextInitTick + tickOffset) s.Require().NoError(err) - _, sqrtPriceAtNextInitializedTick, err := cl.TickToSqrtPrice(nextInitTick) + _, sqrtPriceAtNextInitializedTick, err := clmath.TickToSqrtPrice(nextInitTick) s.Require().NoError(err) // Calculate Δ(sqrtPrice): @@ -502,10 +502,10 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { // * liquidity of positions that come in range are correctly kicked in // tickOffset is a tick index after the next initialized tick to which this swap needs to move the current price - tickOffset = sdk.NewInt(300) + tickOffset = 300 sqrtPriceBeforeSwap = concentratedPool.GetCurrentSqrtPrice() liquidityBeforeSwap = concentratedPool.GetLiquidity() - nextInitTick = sdk.NewInt(40000) + nextInitTick = 40000 // Calculate amount required to get to // 1) next initialized tick @@ -513,9 +513,9 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() { // Using: CalcAmount0Delta = liquidity * ((sqrtPriceB - sqrtPriceA) / (sqrtPriceB * sqrtPriceA)) // Calculate sqrtPrice after and at the next initialized tick (which is upperTick of address1 position1 - 40000) - _, sqrtPricebBelowNextInitializedTick, err := cl.TickToSqrtPrice(nextInitTick.Sub(tickOffset)) + _, sqrtPricebBelowNextInitializedTick, err := clmath.TickToSqrtPrice(nextInitTick - tickOffset) s.Require().NoError(err) - _, sqrtPriceAtNextInitializedTick, err = cl.TickToSqrtPrice(nextInitTick) + _, sqrtPriceAtNextInitializedTick, err = clmath.TickToSqrtPrice(nextInitTick) s.Require().NoError(err) // Calculate numerators diff --git a/x/concentrated-liquidity/export_internal.go b/x/concentrated-liquidity/export_internal.go deleted file mode 100644 index 4eb7cb713a4..00000000000 --- a/x/concentrated-liquidity/export_internal.go +++ /dev/null @@ -1,11 +0,0 @@ -package concentrated_liquidity - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/math" -) - -func TickToSqrtPrice(tickIndex sdk.Int) (price sdk.Dec, sqrtPrice sdk.Dec, err error) { - return math.TickToSqrtPrice(tickIndex) -} diff --git a/x/concentrated-liquidity/export_test.go b/x/concentrated-liquidity/export_test.go index 4ef0a24224a..ce1058de969 100644 --- a/x/concentrated-liquidity/export_test.go +++ b/x/concentrated-liquidity/export_test.go @@ -51,7 +51,7 @@ func (k Keeper) SendCoinsBetweenPoolAndUser(ctx sdk.Context, denom0, denom1 stri return k.sendCoinsBetweenPoolAndUser(ctx, denom0, denom1, amount0, amount1, sender, receiver) } -func (k Keeper) CalcInAmtGivenOutInternal(ctx sdk.Context, desiredTokenOut sdk.Coin, tokenInDenom string, swapFee sdk.Dec, priceLimit sdk.Dec, poolId uint64) (writeCtx func(), tokenIn, tokenOut sdk.Coin, updatedTick sdk.Int, updatedLiquidity, updatedSqrtPrice sdk.Dec, err error) { +func (k Keeper) CalcInAmtGivenOutInternal(ctx sdk.Context, desiredTokenOut sdk.Coin, tokenInDenom string, swapFee sdk.Dec, priceLimit sdk.Dec, poolId uint64) (writeCtx func(), tokenIn, tokenOut sdk.Coin, updatedTick int64, updatedLiquidity, updatedSqrtPrice sdk.Dec, err error) { return k.calcInAmtGivenOut(ctx, desiredTokenOut, tokenInDenom, swapFee, priceLimit, poolId) } @@ -62,7 +62,7 @@ func (k Keeper) SwapOutAmtGivenIn( tokenIn sdk.Coin, tokenOutDenom string, swapFee sdk.Dec, - priceLimit sdk.Dec) (calcTokenIn, calcTokenOut sdk.Coin, currentTick sdk.Int, liquidity, sqrtPrice sdk.Dec, err error) { + priceLimit sdk.Dec) (calcTokenIn, calcTokenOut sdk.Coin, currentTick int64, liquidity, sqrtPrice sdk.Dec, err error) { return k.swapOutAmtGivenIn(ctx, sender, pool, tokenIn, tokenOutDenom, swapFee, priceLimit) } @@ -74,11 +74,11 @@ func (k Keeper) ComputeOutAmtGivenIn( swapFee sdk.Dec, priceLimit sdk.Dec, -) (calcTokenIn, calcTokenOut sdk.Coin, currentTick sdk.Int, liquidity, sqrtPrice sdk.Dec, err error) { +) (calcTokenIn, calcTokenOut sdk.Coin, currentTick int64, liquidity, sqrtPrice sdk.Dec, err error) { return k.computeOutAmtGivenIn(ctx, poolId, tokenInMin, tokenOutDenom, swapFee, priceLimit) } -func (k *Keeper) SwapInAmtGivenOut(ctx sdk.Context, sender sdk.AccAddress, pool types.ConcentratedPoolExtension, desiredTokenOut sdk.Coin, tokenInDenom string, swapFee sdk.Dec, priceLimit sdk.Dec) (calcTokenIn, calcTokenOut sdk.Coin, currentTick sdk.Int, liquidity, sqrtPrice sdk.Dec, err error) { +func (k *Keeper) SwapInAmtGivenOut(ctx sdk.Context, sender sdk.AccAddress, pool types.ConcentratedPoolExtension, desiredTokenOut sdk.Coin, tokenInDenom string, swapFee sdk.Dec, priceLimit sdk.Dec) (calcTokenIn, calcTokenOut sdk.Coin, currentTick int64, liquidity, sqrtPrice sdk.Dec, err error) { return k.swapInAmtGivenOut(ctx, sender, pool, desiredTokenOut, tokenInDenom, swapFee, priceLimit) } @@ -281,7 +281,7 @@ func (k Keeper) GetAllPositions(ctx sdk.Context) ([]model.Position, error) { return k.getAllPositions(ctx) } -func (k Keeper) UpdatePoolForSwap(ctx sdk.Context, pool types.ConcentratedPoolExtension, sender sdk.AccAddress, tokenIn sdk.Coin, tokenOut sdk.Coin, newCurrentTick sdk.Int, newLiquidity sdk.Dec, newSqrtPrice sdk.Dec) error { +func (k Keeper) UpdatePoolForSwap(ctx sdk.Context, pool types.ConcentratedPoolExtension, sender sdk.AccAddress, tokenIn sdk.Coin, tokenOut sdk.Coin, newCurrentTick int64, newLiquidity sdk.Dec, newSqrtPrice sdk.Dec) error { return k.updatePoolForSwap(ctx, pool, sender, tokenIn, tokenOut, newCurrentTick, newLiquidity, newSqrtPrice) } diff --git a/x/concentrated-liquidity/fees_test.go b/x/concentrated-liquidity/fees_test.go index 0cb7231928a..295184239c6 100644 --- a/x/concentrated-liquidity/fees_test.go +++ b/x/concentrated-liquidity/fees_test.go @@ -489,8 +489,7 @@ func (suite *KeeperTestSuite) TestGetInitialFeeGrowthOppositeDirectionOfLastTrav validPoolId = 1 ) - initialPoolTickInt, err := math.PriceToTickRoundDown(DefaultAmt1.ToDec().Quo(DefaultAmt0.ToDec()), DefaultTickSpacing) - initialPoolTick := initialPoolTickInt.Int64() + initialPoolTick, err := math.PriceToTickRoundDown(DefaultAmt1.ToDec().Quo(DefaultAmt0.ToDec()), DefaultTickSpacing) suite.Require().NoError(err) tests := map[string]struct { @@ -1580,12 +1579,12 @@ func (s *KeeperTestSuite) CollectAndAssertFees(ctx sdk.Context, poolId uint64, t // Claim consecutive range position fees across two of four accounts for i := 0; i < positions.numConsecutive; i++ { - totalFeesCollected = s.collectFeesAndCheckInvariance(ctx, i, DefaultExponentConsecutivePositionLowerTick.Int64(), DefaultExponentConsecutivePositionUpperTick.Int64(), positionIds[2][i], totalFeesCollected, expectedFeeDenoms[2], activeTicks) + totalFeesCollected = s.collectFeesAndCheckInvariance(ctx, i, DefaultExponentConsecutivePositionLowerTick, DefaultExponentConsecutivePositionUpperTick, positionIds[2][i], totalFeesCollected, expectedFeeDenoms[2], activeTicks) } // Claim overlapping range position fees on one of four accounts for i := 0; i < positions.numOverlapping; i++ { - totalFeesCollected = s.collectFeesAndCheckInvariance(ctx, i, DefaultExponentOverlappingPositionLowerTick.Int64(), DefaultExponentOverlappingPositionUpperTick.Int64(), positionIds[3][i], totalFeesCollected, expectedFeeDenoms[3], activeTicks) + totalFeesCollected = s.collectFeesAndCheckInvariance(ctx, i, DefaultExponentOverlappingPositionLowerTick, DefaultExponentOverlappingPositionUpperTick, positionIds[3][i], totalFeesCollected, expectedFeeDenoms[3], activeTicks) } // Define error tolerance diff --git a/x/concentrated-liquidity/keeper_test.go b/x/concentrated-liquidity/keeper_test.go index 0abfb7885f5..14e541bd4bc 100644 --- a/x/concentrated-liquidity/keeper_test.go +++ b/x/concentrated-liquidity/keeper_test.go @@ -113,12 +113,12 @@ func (s *KeeperTestSuite) SetupFullRangePositionAcc(poolId uint64, owner sdk.Acc } func (s *KeeperTestSuite) SetupConsecutiveRangePositionAcc(poolId uint64, owner sdk.AccAddress) uint64 { - _, positionId := s.SetupPosition(poolId, owner, DefaultCoins, DefaultExponentConsecutivePositionLowerTick.Int64(), DefaultExponentConsecutivePositionUpperTick.Int64(), s.Ctx.BlockTime()) + _, positionId := s.SetupPosition(poolId, owner, DefaultCoins, DefaultExponentConsecutivePositionLowerTick, DefaultExponentConsecutivePositionUpperTick, s.Ctx.BlockTime()) return positionId } func (s *KeeperTestSuite) SetupOverlappingRangePositionAcc(poolId uint64, owner sdk.AccAddress) uint64 { - _, positionId := s.SetupPosition(poolId, owner, DefaultCoins, DefaultExponentOverlappingPositionLowerTick.Int64(), DefaultExponentOverlappingPositionUpperTick.Int64(), s.Ctx.BlockTime()) + _, positionId := s.SetupPosition(poolId, owner, DefaultCoins, DefaultExponentOverlappingPositionLowerTick, DefaultExponentOverlappingPositionUpperTick, s.Ctx.BlockTime()) return positionId } diff --git a/x/concentrated-liquidity/lp.go b/x/concentrated-liquidity/lp.go index 0f9df91a6b9..4d97abf6cc5 100644 --- a/x/concentrated-liquidity/lp.go +++ b/x/concentrated-liquidity/lp.go @@ -437,7 +437,7 @@ func (k Keeper) initializeInitialPositionForPool(ctx sdk.Context, pool types.Con // In such a case, we do not want to round the sqrt price to 100_000_000 X/Y, but rather // let it float within the possible tick range. pool.SetCurrentSqrtPrice(initialCurSqrtPrice) - pool.SetCurrentTick(initialTick) + pool.SetCurrentTick(sdk.NewInt(initialTick)) err = k.setPool(ctx, pool) if err != nil { return err diff --git a/x/concentrated-liquidity/math/precompute.go b/x/concentrated-liquidity/math/precompute.go index 7996ba3058e..8b2e3ebc46e 100644 --- a/x/concentrated-liquidity/math/precompute.go +++ b/x/concentrated-liquidity/math/precompute.go @@ -7,8 +7,7 @@ import ( ) var ( - sdkOneInt = sdk.OneInt() - sdkOneDec = sdk.NewDec(1) + sdkOneDec = sdk.OneDec() sdkNineDec = sdk.NewDec(9) sdkTenDec = sdk.NewDec(10) powersOfTen []sdk.Dec diff --git a/x/concentrated-liquidity/math/tick.go b/x/concentrated-liquidity/math/tick.go index a9318ad202c..fb59bb8d5e4 100644 --- a/x/concentrated-liquidity/math/tick.go +++ b/x/concentrated-liquidity/math/tick.go @@ -16,11 +16,11 @@ func TicksToSqrtPrice(lowerTick, upperTick int64) (sdk.Dec, sdk.Dec, sdk.Dec, sd if lowerTick >= upperTick { return sdk.Dec{}, sdk.Dec{}, sdk.Dec{}, sdk.Dec{}, types.InvalidLowerUpperTickError{LowerTick: lowerTick, UpperTick: upperTick} } - priceUpperTick, sqrtPriceUpperTick, err := TickToSqrtPrice(sdk.NewInt(upperTick)) + priceUpperTick, sqrtPriceUpperTick, err := TickToSqrtPrice(upperTick) if err != nil { return sdk.Dec{}, sdk.Dec{}, sdk.Dec{}, sdk.Dec{}, err } - priceLowerTick, sqrtPriceLowerTick, err := TickToSqrtPrice(sdk.NewInt(lowerTick)) + priceLowerTick, sqrtPriceLowerTick, err := TickToSqrtPrice(lowerTick) if err != nil { return sdk.Dec{}, sdk.Dec{}, sdk.Dec{}, sdk.Dec{}, err } @@ -30,7 +30,7 @@ func TicksToSqrtPrice(lowerTick, upperTick int64) (sdk.Dec, sdk.Dec, sdk.Dec, sd // TickToSqrtPrice returns the sqrtPrice given a tickIndex // If tickIndex is zero, the function returns sdk.OneDec(). // It is the combination of calling TickToPrice followed by Sqrt. -func TickToSqrtPrice(tickIndex sdk.Int) (sdk.Dec, sdk.Dec, error) { +func TickToSqrtPrice(tickIndex int64) (sdk.Dec, sdk.Dec, error) { price, err := TickToPrice(tickIndex) if err != nil { return sdk.Dec{}, sdk.Dec{}, err @@ -46,33 +46,33 @@ func TickToSqrtPrice(tickIndex sdk.Int) (sdk.Dec, sdk.Dec, error) { // TickToPrice returns the price given a tickIndex // If tickIndex is zero, the function returns sdk.OneDec(). -func TickToPrice(tickIndex sdk.Int) (price sdk.Dec, err error) { - if tickIndex.IsZero() { +func TickToPrice(tickIndex int64) (price sdk.Dec, err error) { + if tickIndex == 0 { return sdk.OneDec(), nil } // The formula is as follows: geometricExponentIncrementDistanceInTicks = 9 * 10**(-exponentAtPriceOne) // Due to sdk.Power restrictions, if the resulting power is negative, we take 9 * (1/10**exponentAtPriceOne) exponentAtPriceOne := types.ExponentAtPriceOne - geometricExponentIncrementDistanceInTicks := sdkNineDec.Mul(PowTenInternal(exponentAtPriceOne.Neg())) + geometricExponentIncrementDistanceInTicks := sdkNineDec.Mul(PowTenInternal(-exponentAtPriceOne)).TruncateInt64() // Check that the tick index is between min and max value - if tickIndex.LT(sdk.NewInt(types.MinTick)) { + if tickIndex < types.MinTick { return sdk.Dec{}, types.TickIndexMinimumError{MinTick: types.MinTick} } - if tickIndex.GT(sdk.NewInt(types.MaxTick)) { + if tickIndex > types.MaxTick { return sdk.Dec{}, types.TickIndexMaximumError{MaxTick: types.MaxTick} } // Use floor division to determine what the geometricExponent is now (the delta) - geometricExponentDelta := tickIndex.ToDec().QuoIntMut(geometricExponentIncrementDistanceInTicks.TruncateInt()).TruncateInt() + geometricExponentDelta := tickIndex / geometricExponentIncrementDistanceInTicks // Calculate the exponentAtCurrentTick from the starting exponentAtPriceOne and the geometricExponentDelta - exponentAtCurrentTick := exponentAtPriceOne.Add(geometricExponentDelta) - if tickIndex.IsNegative() { + exponentAtCurrentTick := exponentAtPriceOne + geometricExponentDelta + if tickIndex < 0 { // We must decrement the exponentAtCurrentTick when entering the negative tick range in order to constantly step up in precision when going further down in ticks // Otherwise, from tick 0 to tick -(geometricExponentIncrementDistanceInTicks), we would use the same exponent as the exponentAtPriceOne - exponentAtCurrentTick = exponentAtCurrentTick.Sub(sdkOneInt) + exponentAtCurrentTick = exponentAtCurrentTick - 1 } // Knowing what our exponentAtCurrentTick is, we can then figure out what power of 10 this exponent corresponds to @@ -80,10 +80,10 @@ func TickToPrice(tickIndex sdk.Int) (price sdk.Dec, err error) { currentAdditiveIncrementInTicks := powTenBigDec(exponentAtCurrentTick) // Now, starting at the minimum tick of the current increment, we calculate how many ticks in the current geometricExponent we have passed - numAdditiveTicks := tickIndex.ToDec().Sub(geometricExponentDelta.ToDec().Mul(geometricExponentIncrementDistanceInTicks)) + numAdditiveTicks := tickIndex - (geometricExponentDelta * geometricExponentIncrementDistanceInTicks) // Finally, we can calculate the price - price = PowTenInternal(geometricExponentDelta).Add(osmomath.BigDecFromSDKDec(numAdditiveTicks).Mul(currentAdditiveIncrementInTicks).SDKDec()) + price = PowTenInternal(geometricExponentDelta).Add(osmomath.NewBigDec(numAdditiveTicks).Mul(currentAdditiveIncrementInTicks).SDKDec()) if price.GT(types.MaxSpotPrice) || price.LT(types.MinSpotPrice) { return sdk.Dec{}, types.PriceBoundError{ProvidedPrice: price, MinSpotPrice: types.MinSpotPrice, MaxSpotPrice: types.MaxSpotPrice} @@ -93,17 +93,17 @@ func TickToPrice(tickIndex sdk.Int) (price sdk.Dec, err error) { // PriceToTick takes a price and returns the corresponding tick index assuming // tick spacing of 1. -func PriceToTick(price sdk.Dec) (sdk.Int, error) { +func PriceToTick(price sdk.Dec) (int64, error) { if price.Equal(sdk.OneDec()) { - return sdk.ZeroInt(), nil + return 0, nil } if price.IsNegative() { - return sdk.Int{}, fmt.Errorf("price must be greater than zero") + return 0, fmt.Errorf("price must be greater than zero") } if price.GT(types.MaxSpotPrice) || price.LT(types.MinSpotPrice) { - return sdk.Int{}, types.PriceBoundError{ProvidedPrice: price, MinSpotPrice: types.MinSpotPrice, MaxSpotPrice: types.MaxSpotPrice} + return 0, types.PriceBoundError{ProvidedPrice: price, MinSpotPrice: types.MinSpotPrice, MaxSpotPrice: types.MaxSpotPrice} } // Determine the tick that corresponds to the price @@ -115,23 +115,36 @@ func PriceToTick(price sdk.Dec) (sdk.Int, error) { // PriceToTickRoundDown takes a price and returns the corresponding tick index. // If tickSpacing is provided, the tick index will be rounded down to the nearest multiple of tickSpacing. -func PriceToTickRoundDown(price sdk.Dec, tickSpacing uint64) (sdk.Int, error) { +// CONTRACT: tickSpacing must be smaller or equal to the max of 1 << 63 - 1. +// This is not a concern because we have authorized tick spacings that are smaller than this max, +// and we don't expect to ever require it to be this large. +func PriceToTickRoundDown(price sdk.Dec, tickSpacing uint64) (int64, error) { tickIndex, err := PriceToTick(price) if err != nil { - return sdk.Int{}, err + return 0, err } // Round the tick index down to the nearest tick spacing if the tickIndex is in between authorized tick values - tickSpacingInt := sdk.NewIntFromUint64(tickSpacing) - tickIndexModulus := tickIndex.Mod(tickSpacingInt) - if !tickIndexModulus.Equal(sdk.ZeroInt()) { - tickIndex = tickIndex.Sub(tickIndexModulus) + // Note that this is Euclidean modulus. + // The difference from default Go modulus is that Go default results + // in a negative remainder when the dividend is negative. + // Consider example tickIndex = -17, tickSpacing = 10 + // tickIndexModulus = tickIndex % tickSpacing = -7 + // tickIndexModulus = -7 + 10 = 3 + // tickIndex = -17 - 3 = -20 + tickIndexModulus := tickIndex % int64(tickSpacing) + if tickIndexModulus < 0 { + tickIndexModulus += int64(tickSpacing) + } + + if tickIndexModulus != 0 { + tickIndex = tickIndex - tickIndexModulus } // Defense-in-depth check to ensure that the tick index is within the authorized range // Should never get here. - if tickIndex.GT(sdk.NewInt(types.MaxTick)) || tickIndex.LT(sdk.NewInt(types.MinTick)) { - return sdk.Int{}, types.TickIndexNotWithinBoundariesError{ActualTick: tickIndex.Int64(), MinTick: types.MinTick, MaxTick: types.MaxTick} + if tickIndex > types.MaxTick || tickIndex < types.MinTick { + return 0, types.TickIndexNotWithinBoundariesError{ActualTick: tickIndex, MinTick: types.MinTick, MaxTick: types.MaxTick} } return tickIndex, nil @@ -139,31 +152,31 @@ func PriceToTickRoundDown(price sdk.Dec, tickSpacing uint64) (sdk.Int, error) { // powTen treats negative exponents as 1/(10**|exponent|) instead of 10**-exponent // This is because the sdk.Dec.Power function does not support negative exponents -func PowTenInternal(exponent sdk.Int) sdk.Dec { - if exponent.GTE(sdk.ZeroInt()) { - return powersOfTen[exponent.Int64()] +func PowTenInternal(exponent int64) sdk.Dec { + if exponent >= 0 { + return powersOfTen[exponent] } - return negPowersOfTen[-exponent.Int64()] + return negPowersOfTen[-exponent] } -func powTenBigDec(exponent sdk.Int) osmomath.BigDec { - if exponent.GTE(sdk.ZeroInt()) { - return bigPowersOfTen[exponent.Int64()] +func powTenBigDec(exponent int64) osmomath.BigDec { + if exponent >= 0 { + return bigPowersOfTen[exponent] } - return bigNegPowersOfTen[-exponent.Int64()] + return bigNegPowersOfTen[-exponent] } // CalculatePriceToTick takes in a price and returns the corresponding tick index. // This function does not take into consideration tick spacing. -func CalculatePriceToTick(price sdk.Dec) (tickIndex sdk.Int) { +func CalculatePriceToTick(price sdk.Dec) (tickIndex int64) { // The formula is as follows: geometricExponentIncrementDistanceInTicks = 9 * 10**(-exponentAtPriceOne) // Due to sdk.Power restrictions, if the resulting power is negative, we take 9 * (1/10**exponentAtPriceOne) exponentAtPriceOne := types.ExponentAtPriceOne - geometricExponentIncrementDistanceInTicks := sdkNineDec.Mul(PowTenInternal(exponentAtPriceOne.Neg())) + geometricExponentIncrementDistanceInTicks := sdkNineDec.Mul(PowTenInternal(exponentAtPriceOne * -1)).TruncateInt64() // Initialize the current price to 1, the current precision to exponentAtPriceOne, and the number of ticks passed to 0 - currentPrice := sdk.OneDec() - ticksPassed := sdk.ZeroInt() + currentPrice := sdkOneDec + ticksPassed := int64(0) exponentAtCurrentTick := exponentAtPriceOne @@ -178,21 +191,21 @@ func CalculatePriceToTick(price sdk.Dec) (tickIndex sdk.Int) { if price.GT(sdkOneDec) { for currentPrice.LT(price) { currentAdditiveIncrementInTicks = powTenBigDec(exponentAtCurrentTick) - maxPriceForCurrentAdditiveIncrementInTicks := osmomath.BigDecFromSDKDec(geometricExponentIncrementDistanceInTicks).Mul(currentAdditiveIncrementInTicks) - currentPrice.AddMut(maxPriceForCurrentAdditiveIncrementInTicks.SDKDec()) - exponentAtCurrentTick = exponentAtCurrentTick.Add(sdkOneInt) - ticksPassed = ticksPassed.Add(geometricExponentIncrementDistanceInTicks.TruncateInt()) + maxPriceForCurrentAdditiveIncrementInTicks := osmomath.NewBigDec(geometricExponentIncrementDistanceInTicks).Mul(currentAdditiveIncrementInTicks) + currentPrice = currentPrice.Add(maxPriceForCurrentAdditiveIncrementInTicks.SDKDec()) + exponentAtCurrentTick = exponentAtCurrentTick + 1 + ticksPassed = ticksPassed + geometricExponentIncrementDistanceInTicks } } else { // We must decrement the exponentAtCurrentTick by one when traversing negative ticks in order to constantly step up in precision when going further down in ticks // Otherwise, from tick 0 to tick -(geometricExponentIncrementDistanceInTicks), we would use the same exponent as the exponentAtPriceOne - exponentAtCurrentTick := exponentAtPriceOne.Sub(sdkOneInt) + exponentAtCurrentTick := exponentAtPriceOne - 1 for currentPrice.GT(price) { currentAdditiveIncrementInTicks = powTenBigDec(exponentAtCurrentTick) - maxPriceForCurrentAdditiveIncrementInTicks := osmomath.BigDecFromSDKDec(geometricExponentIncrementDistanceInTicks).Mul(currentAdditiveIncrementInTicks) - currentPrice.SubMut(maxPriceForCurrentAdditiveIncrementInTicks.SDKDec()) - exponentAtCurrentTick = exponentAtCurrentTick.Sub(sdkOneInt) - ticksPassed = ticksPassed.Sub(geometricExponentIncrementDistanceInTicks.TruncateInt()) + maxPriceForCurrentAdditiveIncrementInTicks := osmomath.NewBigDec(geometricExponentIncrementDistanceInTicks).Mul(currentAdditiveIncrementInTicks) + currentPrice = currentPrice.Sub(maxPriceForCurrentAdditiveIncrementInTicks.SDKDec()) + exponentAtCurrentTick = exponentAtCurrentTick - 1 + ticksPassed = ticksPassed - geometricExponentIncrementDistanceInTicks } } @@ -200,6 +213,6 @@ func CalculatePriceToTick(price sdk.Dec) (tickIndex sdk.Int) { ticksToBeFulfilledByExponentAtCurrentTick := osmomath.BigDecFromSDKDec(price.Sub(currentPrice)).Quo(currentAdditiveIncrementInTicks) // Finally, add the ticks we have passed from the completed geometricExponent values, as well as the ticks we have passed in the current geometricExponent value - tickIndex = ticksPassed.Add(ticksToBeFulfilledByExponentAtCurrentTick.SDKDec().RoundInt()) + tickIndex = ticksPassed + ticksToBeFulfilledByExponentAtCurrentTick.SDKDec().RoundInt64() return tickIndex } diff --git a/x/concentrated-liquidity/math/tick_test.go b/x/concentrated-liquidity/math/tick_test.go index 18eb73bd0f3..c1998271bb3 100644 --- a/x/concentrated-liquidity/math/tick_test.go +++ b/x/concentrated-liquidity/math/tick_test.go @@ -14,9 +14,9 @@ const ( var ( // spot price - (10^(spot price exponent - 6 - 1)) // Note we get spot price exponent by counting the number of digits in the max spot price and subtracting 1. - closestPriceBelowMaxPriceDefaultTickSpacing = types.MaxSpotPrice.Sub(sdk.NewDec(10).PowerMut(uint64(len(types.MaxSpotPrice.TruncateInt().String()) - 1 - int(types.ExponentAtPriceOne.Neg().Int64()) - 1))) + closestPriceBelowMaxPriceDefaultTickSpacing = types.MaxSpotPrice.Sub(sdk.NewDec(10).PowerMut(uint64(len(types.MaxSpotPrice.TruncateInt().String()) - 1 - int(-types.ExponentAtPriceOne) - 1))) // min tick + 10 ^ -expoentAtPriceOne - closestTickAboveMinPriceDefaultTickSpacing = sdk.NewInt(types.MinTick).Add(sdk.NewInt(10).ToDec().Power(types.ExponentAtPriceOne.Neg().Uint64()).TruncateInt()) + closestTickAboveMinPriceDefaultTickSpacing = sdk.NewInt(types.MinTick).Add(sdk.NewInt(10).ToDec().Power(uint64(types.ExponentAtPriceOne * -1)).TruncateInt()) ) // use following equations to test testing vectors using sage @@ -29,152 +29,152 @@ var ( // (numAdditiveTicks(tickIndex, exponentAtPriceOne) * currentAdditiveIncrementInTicks(tickIndex, exponentAtPriceOne)) func (suite *ConcentratedMathTestSuite) TestTickToSqrtPrice() { testCases := map[string]struct { - tickIndex sdk.Int + tickIndex int64 expectedPrice sdk.Dec expectedError error }{ "Ten billionths cent increments at the millionths place: 1": { - tickIndex: sdk.NewInt(-51630100), + tickIndex: -51630100, expectedPrice: sdk.MustNewDecFromStr("0.0000033699"), }, "Ten billionths cent increments at the millionths place: 2": { - tickIndex: sdk.NewInt(-51630000), + tickIndex: -51630000, expectedPrice: sdk.MustNewDecFromStr("0.0000033700"), }, "One millionths cent increments at the hundredths place: 1": { - tickIndex: sdk.NewInt(-11999800), + tickIndex: -11999800, expectedPrice: sdk.MustNewDecFromStr("0.070002"), }, "One millionths cent increments at the hundredths place: 2": { - tickIndex: sdk.NewInt(-11999700), + tickIndex: -11999700, expectedPrice: sdk.MustNewDecFromStr("0.070003"), }, "One hundred thousandth cent increments at the tenths place: 1": { - tickIndex: sdk.NewInt(-999800), + tickIndex: -999800, expectedPrice: sdk.MustNewDecFromStr("0.90002"), }, "One hundred thousandth cent increments at the tenths place: 2": { - tickIndex: sdk.NewInt(-999700), + tickIndex: -999700, expectedPrice: sdk.MustNewDecFromStr("0.90003"), }, "One ten thousandth cent increments at the ones place: 1": { - tickIndex: sdk.NewInt(1000000), + tickIndex: 1000000, expectedPrice: sdk.MustNewDecFromStr("2"), }, "One dollar increments at the ten thousands place: 2": { - tickIndex: sdk.NewInt(1000100), + tickIndex: 1000100, expectedPrice: sdk.MustNewDecFromStr("2.0001"), }, "One thousandth cent increments at the tens place: 1": { - tickIndex: sdk.NewInt(9200100), + tickIndex: 9200100, expectedPrice: sdk.MustNewDecFromStr("12.001"), }, "One thousandth cent increments at the tens place: 2": { - tickIndex: sdk.NewInt(9200200), + tickIndex: 9200200, expectedPrice: sdk.MustNewDecFromStr("12.002"), }, "One cent increments at the hundreds place: 1": { - tickIndex: sdk.NewInt(18320100), + tickIndex: 18320100, expectedPrice: sdk.MustNewDecFromStr("132.01"), }, "One cent increments at the hundreds place: 2": { - tickIndex: sdk.NewInt(18320200), + tickIndex: 18320200, expectedPrice: sdk.MustNewDecFromStr("132.02"), }, "Ten cent increments at the thousands place: 1": { - tickIndex: sdk.NewInt(27732100), + tickIndex: 27732100, expectedPrice: sdk.MustNewDecFromStr("1732.10"), }, "Ten cent increments at the thousands place: 2": { - tickIndex: sdk.NewInt(27732200), + tickIndex: 27732200, expectedPrice: sdk.MustNewDecFromStr("1732.20"), }, "Dollar increments at the ten thousands place: 1": { - tickIndex: sdk.NewInt(36073200), + tickIndex: 36073200, expectedPrice: sdk.MustNewDecFromStr("10732"), }, "Dollar increments at the ten thousands place: 2": { - tickIndex: sdk.NewInt(36073300), + tickIndex: 36073300, expectedPrice: sdk.MustNewDecFromStr("10733"), }, "Max tick and min k": { - tickIndex: sdk.NewInt(342000000), + tickIndex: 342000000, expectedPrice: types.MaxSpotPrice, }, "Min tick and max k": { - tickIndex: sdk.NewInt(-162000000), + tickIndex: -162000000, expectedPrice: types.MinSpotPrice, }, "error: tickIndex less than minimum": { - tickIndex: sdk.NewInt(-162000000 - 1), + tickIndex: -162000000 - 1, expectedError: types.TickIndexMinimumError{MinTick: -162000000}, }, "error: tickIndex greater than maximum": { - tickIndex: sdk.NewInt(342000000 + 1), + tickIndex: 342000000 + 1, expectedError: types.TickIndexMaximumError{MaxTick: 342000000}, }, "Gyen <> USD, tick -20594000 -> price 0.0074060": { - tickIndex: sdk.NewInt(-20594000), + tickIndex: -20594000, expectedPrice: sdk.MustNewDecFromStr("0.007406000000000000"), }, "Gyen <> USD, tick -20594000 + 100 -> price 0.0074061": { - tickIndex: sdk.NewInt(-20593900), + tickIndex: -20593900, expectedPrice: sdk.MustNewDecFromStr("0.007406100000000000"), }, "Spell <> USD, tick -29204000 -> price 0.00077960": { - tickIndex: sdk.NewInt(-29204000), + tickIndex: -29204000, expectedPrice: sdk.MustNewDecFromStr("0.000779600000000000"), }, "Spell <> USD, tick -29204000 + 100 -> price 0.00077961": { - tickIndex: sdk.NewInt(-29203900), + tickIndex: -29203900, expectedPrice: sdk.MustNewDecFromStr("0.000779610000000000"), }, "Atom <> Osmo, tick -12150000 -> price 0.068500": { - tickIndex: sdk.NewInt(-12150000), + tickIndex: -12150000, expectedPrice: sdk.MustNewDecFromStr("0.068500000000000000"), }, "Atom <> Osmo, tick -12150000 + 100 -> price 0.068501": { - tickIndex: sdk.NewInt(-12149900), + tickIndex: -12149900, expectedPrice: sdk.MustNewDecFromStr("0.068501000000000000"), }, "Boot <> Osmo, tick 64576000 -> price 25760000": { - tickIndex: sdk.NewInt(64576000), + tickIndex: 64576000, expectedPrice: sdk.MustNewDecFromStr("25760000"), }, "Boot <> Osmo, tick 64576000 + 100 -> price 25760000": { - tickIndex: sdk.NewInt(64576100), + tickIndex: 64576100, expectedPrice: sdk.MustNewDecFromStr("25761000"), }, "BTC <> USD, tick 38035200 -> price 30352": { - tickIndex: sdk.NewInt(38035200), + tickIndex: 38035200, expectedPrice: sdk.MustNewDecFromStr("30352"), }, "BTC <> USD, tick 38035200 + 100 -> price 30353": { - tickIndex: sdk.NewInt(38035300), + tickIndex: 38035300, expectedPrice: sdk.MustNewDecFromStr("30353"), }, "SHIB <> USD, tick -44821000 -> price 0.000011790": { - tickIndex: sdk.NewInt(-44821000), + tickIndex: -44821000, expectedPrice: sdk.MustNewDecFromStr("0.00001179"), }, "SHIB <> USD, tick -44821100 + 100 -> price 0.000011791": { - tickIndex: sdk.NewInt(-44820900), + tickIndex: -44820900, expectedPrice: sdk.MustNewDecFromStr("0.000011791"), }, "ETH <> BTC, tick -12104000 -> price 0.068960": { - tickIndex: sdk.NewInt(-12104000), + tickIndex: -12104000, expectedPrice: sdk.MustNewDecFromStr("0.068960"), }, "ETH <> BTC, tick -121044000 + 1 -> price 0.068961": { - tickIndex: sdk.NewInt(-12103900), + tickIndex: -12103900, expectedPrice: sdk.MustNewDecFromStr("0.068961"), }, "one tick spacing interval smaller than max sqrt price, max tick neg six - 100 -> one tick spacing interval smaller than max sqrt price": { - tickIndex: sdk.NewInt(types.MaxTick).Sub(sdk.NewInt(100)), + tickIndex: types.MaxTick - 100, expectedPrice: sdk.MustNewDecFromStr("99999000000000000000000000000000000000"), }, "max sqrt price, max tick neg six -> max spot price": { - tickIndex: sdk.NewInt(types.MaxTick), + tickIndex: types.MaxTick, expectedPrice: types.MaxSpotPrice, }, } @@ -279,71 +279,71 @@ func (suite *ConcentratedMathTestSuite) TestPriceToTick() { testCases := map[string]struct { price sdk.Dec - tickExpected string + tickExpected int64 }{ "BTC <> USD, tick 38035200 -> price 30352": { price: sdk.MustNewDecFromStr("30352"), - tickExpected: "38035200", + tickExpected: 38035200, }, "BTC <> USD, tick 38035300 + 100 -> price 30353": { price: sdk.MustNewDecFromStr("30353"), - tickExpected: "38035300", + tickExpected: 38035300, }, "SHIB <> USD, tick -44821000 -> price 0.000011790": { price: sdk.MustNewDecFromStr("0.000011790"), - tickExpected: "-44821000", + tickExpected: -44821000, }, "SHIB <> USD, tick -44820900 -> price 0.000011791": { price: sdk.MustNewDecFromStr("0.000011791"), - tickExpected: "-44820900", + tickExpected: -44820900, }, "ETH <> BTC, tick -12104000 -> price 0.068960": { price: sdk.MustNewDecFromStr("0.068960"), - tickExpected: "-12104000", + tickExpected: -12104000, }, "ETH <> BTC, tick -12104000 + 100 -> price 0.068961": { price: sdk.MustNewDecFromStr("0.068961"), - tickExpected: "-12103900", + tickExpected: -12103900, }, "max sqrt price -1, max neg tick six - 100 -> max tick neg six - 100": { price: sdk.MustNewDecFromStr("99999000000000000000000000000000000000"), - tickExpected: sdk.NewInt(types.MaxTick - 100).String(), + tickExpected: types.MaxTick - 100, }, "max sqrt price, max tick neg six -> max spot price": { price: types.MaxSqrtPrice.Power(2), - tickExpected: sdk.NewInt(types.MaxTick).String(), + tickExpected: types.MaxTick, }, "Gyen <> USD, tick -20594000 -> price 0.0074060": { price: sdk.MustNewDecFromStr("0.007406"), - tickExpected: "-20594000", + tickExpected: -20594000, }, "Gyen <> USD, tick -20594000 + 100 -> price 0.0074061": { price: sdk.MustNewDecFromStr("0.0074061"), - tickExpected: "-20593900", + tickExpected: -20593900, }, "Spell <> USD, tick -29204000 -> price 0.00077960": { price: sdk.MustNewDecFromStr("0.0007796"), - tickExpected: "-29204000", + tickExpected: -29204000, }, "Spell <> USD, tick -29204000 + 100 -> price 0.00077961": { price: sdk.MustNewDecFromStr("0.00077961"), - tickExpected: "-29203900", + tickExpected: -29203900, }, "Atom <> Osmo, tick -12150000 -> price 0.068500": { price: sdk.MustNewDecFromStr("0.0685"), - tickExpected: "-12150000", + tickExpected: -12150000, }, "Atom <> Osmo, tick -12150000 + 100 -> price 0.068501": { price: sdk.MustNewDecFromStr("0.068501"), - tickExpected: "-12149900", + tickExpected: -12149900, }, "Boot <> Osmo, tick 64576000 -> price 25760000": { price: sdk.MustNewDecFromStr("25760000"), - tickExpected: "64576000", + tickExpected: 64576000, }, "Boot <> Osmo, tick 64576000 + 100 -> price 25761000": { price: sdk.MustNewDecFromStr("25761000"), - tickExpected: "64576100", + tickExpected: 64576100, }, } for name, tc := range testCases { @@ -356,8 +356,8 @@ func (suite *ConcentratedMathTestSuite) TestPriceToTick() { suite.Require().NoError(err) suite.Require().NoError(err1) - suite.Require().Equal(tc.tickExpected, tick.String()) - suite.Require().Equal(tc.tickExpected, tickRoundDown.String()) + suite.Require().Equal(tc.tickExpected, tick) + suite.Require().Equal(tc.tickExpected, tickRoundDown) }) } } @@ -366,57 +366,57 @@ func (suite *ConcentratedMathTestSuite) TestPriceToTickRoundDown() { testCases := map[string]struct { price sdk.Dec tickSpacing uint64 - tickExpected string + tickExpected int64 }{ "tick spacing 100, price of 1": { price: sdk.OneDec(), tickSpacing: defaultTickSpacing, - tickExpected: "0", + tickExpected: 0, }, "tick spacing 100, price of 1.000030, tick 30 -> 0": { price: sdk.MustNewDecFromStr("1.000030"), tickSpacing: defaultTickSpacing, - tickExpected: "0", + tickExpected: 0, }, "tick spacing 100, price of 0.9999970, tick -30 -> -100": { price: sdk.MustNewDecFromStr("0.9999970"), tickSpacing: defaultTickSpacing, - tickExpected: "-100", + tickExpected: -100, }, "tick spacing 50, price of 0.9999730, tick -270 -> -300": { price: sdk.MustNewDecFromStr("0.9999730"), tickSpacing: 50, - tickExpected: "-300", + tickExpected: -300, }, "tick spacing 100, MinSpotPrice, MinTick": { price: types.MinSpotPrice, tickSpacing: defaultTickSpacing, - tickExpected: sdk.NewInt(types.MinTick).String(), + 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.String(), + tickExpected: closestTickAboveMinPriceDefaultTickSpacing.Int64(), }, "tick spacing 100, Spot price one tick below max, one tick below max -> MaxTick - 1": { price: closestPriceBelowMaxPriceDefaultTickSpacing, tickSpacing: defaultTickSpacing, - tickExpected: sdk.NewInt(types.MaxTick - 100).String(), + tickExpected: types.MaxTick - 100, }, "tick spacing 100, Spot price 100_000_050 -> 72000000": { price: sdk.NewDec(100_000_050), tickSpacing: defaultTickSpacing, - tickExpected: "72000000", + tickExpected: 72000000, }, "tick spacing 100, Spot price 100_000_051 -> 72000100 (rounded up to tick spacing)": { price: sdk.NewDec(100_000_051), tickSpacing: defaultTickSpacing, - tickExpected: "72000000", + tickExpected: 72000000, }, "tick spacing 1, Spot price 100_000_051 -> 72000001 no tick spacing rounding": { price: sdk.NewDec(100_000_051), tickSpacing: 1, - tickExpected: "72000001", + tickExpected: 72000001, }, } for name, tc := range testCases { @@ -426,7 +426,7 @@ func (suite *ConcentratedMathTestSuite) TestPriceToTickRoundDown() { tick, err := math.PriceToTickRoundDown(tc.price, tc.tickSpacing) suite.Require().NoError(err) - suite.Require().Equal(tc.tickExpected, tick.String()) + suite.Require().Equal(tc.tickExpected, tick) }) } } @@ -437,117 +437,117 @@ func (suite *ConcentratedMathTestSuite) TestTickToSqrtPricePriceToTick_InverseRe testCases := map[string]struct { price sdk.Dec truncatedPrice sdk.Dec - tickExpected string + tickExpected int64 }{ "50000 to tick": { price: sdk.MustNewDecFromStr("50000"), - tickExpected: "40000000", + tickExpected: 40000000, }, "5.01 to tick": { price: sdk.MustNewDecFromStr("5.01"), - tickExpected: "4010000", + tickExpected: 4010000, }, "50000.01 to tick": { price: sdk.MustNewDecFromStr("50000.01"), - tickExpected: "40000001", + tickExpected: 40000001, }, "0.090001 to tick": { price: sdk.MustNewDecFromStr("0.090001"), - tickExpected: "-9999900", + tickExpected: -9999900, }, "0.9998 to tick": { price: sdk.MustNewDecFromStr("0.9998"), - tickExpected: "-2000", + tickExpected: -2000, }, "53030 to tick": { price: sdk.MustNewDecFromStr("53030"), - tickExpected: "40303000", + tickExpected: 40303000, }, "max spot price": { price: types.MaxSpotPrice, - tickExpected: sdk.NewInt(types.MaxTick).String(), + tickExpected: types.MaxTick, }, "max spot price - smallest price delta given exponent at price one of -6": { // 37 - 6 is calculated by counting the exponent of max spot price and subtracting exponent at price one price: types.MaxSpotPrice.Sub(sdk.NewDec(10).PowerMut(37 - 6)), - tickExpected: sdk.NewInt(types.MaxTick).Sub(sdk.OneInt()).String(), // still max + tickExpected: types.MaxTick - 1, // still max }, "min spot price": { price: types.MinSpotPrice, - tickExpected: "-162000000", + tickExpected: -162000000, }, "smallest + min price increment": { price: sdk.MustNewDecFromStr("0.000000000000000002"), - tickExpected: "-161000000", + tickExpected: -161000000, }, "min price increment 10^1": { price: sdk.MustNewDecFromStr("0.000000000000000009"), - tickExpected: "-154000000", + tickExpected: -154000000, }, "smallest + min price increment 10^1": { price: sdk.MustNewDecFromStr("0.000000000000000010"), - tickExpected: "-153000000", + tickExpected: -153000000, }, "smallest + min price increment * 10^2": { price: sdk.MustNewDecFromStr("0.000000000000000100"), - tickExpected: "-144000000", + tickExpected: -144000000, }, "smallest + min price increment * 10^3": { price: sdk.MustNewDecFromStr("0.000000000000001000"), - tickExpected: "-135000000", + tickExpected: -135000000, }, "smallest + min price increment * 10^4": { price: sdk.MustNewDecFromStr("0.000000000000010000"), - tickExpected: "-126000000", + tickExpected: -126000000, }, "smallest + min price * increment 10^5": { price: sdk.MustNewDecFromStr("0.000000000000100000"), - tickExpected: "-117000000", + tickExpected: -117000000, }, "smallest + min price * increment 10^6": { price: sdk.MustNewDecFromStr("0.000000000001000000"), - tickExpected: "-108000000", + tickExpected: -108000000, }, "smallest + min price * increment 10^6 + tick": { price: sdk.MustNewDecFromStr("0.000000000001000001"), - tickExpected: "-107999999", + tickExpected: -107999999, }, "smallest + min price * increment 10^17": { price: sdk.MustNewDecFromStr("0.100000000000000000"), - tickExpected: "-9000000", + tickExpected: -9000000, }, "smallest + min price * increment 10^18": { price: sdk.MustNewDecFromStr("1.000000000000000000"), - tickExpected: "0", + tickExpected: 0, }, "at price level of 0.01 - odd": { price: sdk.MustNewDecFromStr("0.012345670000000000"), - tickExpected: "-17765433", + tickExpected: -17765433, }, "at price level of 0.01 - even": { price: sdk.MustNewDecFromStr("0.01234568000000000"), - tickExpected: "-17765432", + tickExpected: -17765432, }, "at min price level of 0.01 - odd": { price: sdk.MustNewDecFromStr("0.000000000001234567"), - tickExpected: "-107765433", + tickExpected: -107765433, }, "at min price level of 0.01 - even": { price: sdk.MustNewDecFromStr("0.000000000001234568"), - tickExpected: "-107765432", + tickExpected: -107765432, }, "at price level of 1_000_000_000 - odd end": { price: sdk.MustNewDecFromStr("1234567000"), - tickExpected: "81234567", + tickExpected: 81234567, }, "at price level of 1_000_000_000 - in-between supported": { price: sdk.MustNewDecFromStr("1234567500"), - tickExpected: "81234568", + tickExpected: 81234568, truncatedPrice: sdk.MustNewDecFromStr("1234568000"), }, "at price level of 1_000_000_000 - even end": { price: sdk.MustNewDecFromStr("1234568000"), - tickExpected: "81234568", + tickExpected: 81234568, }, } for name, tc := range testCases { @@ -559,7 +559,7 @@ func (suite *ConcentratedMathTestSuite) TestTickToSqrtPricePriceToTick_InverseRe // 1. Compute tick from price. tickFromPrice, err := math.PriceToTickRoundDown(tc.price, tickSpacing) suite.Require().NoError(err) - suite.Require().Equal(tc.tickExpected, tickFromPrice.String()) + suite.Require().Equal(tc.tickExpected, tickFromPrice) // 2. Compute price from tick (inverse price) price, err := math.TickToPrice(tickFromPrice) @@ -577,7 +577,7 @@ func (suite *ConcentratedMathTestSuite) TestTickToSqrtPricePriceToTick_InverseRe suite.Require().NoError(err) // Make sure original tick and inverse tick match. - suite.Require().Equal(tickFromPrice.String(), inverseTickFromPrice.String()) + suite.Require().Equal(tickFromPrice, inverseTickFromPrice) // 4. Validate PriceToTick and TickToSqrtPrice functions _, sqrtPrice, err := math.TickToSqrtPrice(tickFromPrice) @@ -601,37 +601,37 @@ func (suite *ConcentratedMathTestSuite) TestTickToSqrtPricePriceToTick_InverseRe func (suite *ConcentratedMathTestSuite) TestCalculatePriceToTick() { testCases := map[string]struct { price sdk.Dec - expectedTickIndex sdk.Int + expectedTickIndex int64 }{ "Price greater than 1": { price: sdk.MustNewDecFromStr("9.78"), - expectedTickIndex: sdk.NewInt(8780000), + expectedTickIndex: 8780000, }, "Price less than 1": { price: sdk.MustNewDecFromStr("0.71"), - expectedTickIndex: sdk.NewInt(-2900000), + expectedTickIndex: -2900000, }, "100_000_000 -> 72000000": { price: sdk.NewDec(100_000_000), - expectedTickIndex: sdk.NewInt(72000000), + expectedTickIndex: 72000000, }, "100_000_050 -> 72000000": { price: sdk.NewDec(100_000_050), - expectedTickIndex: sdk.NewInt(72000000), + expectedTickIndex: 72000000, }, "100_000_051 -> 72000001": { price: sdk.NewDec(100_000_051), - expectedTickIndex: sdk.NewInt(72000001), + expectedTickIndex: 72000001, }, "100_000_100 -> 72000001": { price: sdk.NewDec(100_000_100), - expectedTickIndex: sdk.NewInt(72000001), + expectedTickIndex: 72000001, }, } for name, t := range testCases { suite.Run(name, func() { tickIndex := math.CalculatePriceToTick(t.price) - suite.Require().Equal(t.expectedTickIndex.String(), tickIndex.String()) + suite.Require().Equal(t.expectedTickIndex, tickIndex) }) } } diff --git a/x/concentrated-liquidity/model/pool.go b/x/concentrated-liquidity/model/pool.go index 4e3d0857203..d1693043631 100644 --- a/x/concentrated-liquidity/model/pool.go +++ b/x/concentrated-liquidity/model/pool.go @@ -46,7 +46,7 @@ func NewConcentratedLiquidityPool(poolId uint64, denom0, denom1 string, tickSpac Token0: denom0, Token1: denom1, TickSpacing: tickSpacing, - ExponentAtPriceOne: types.ExponentAtPriceOne, + ExponentAtPriceOne: sdk.NewInt(types.ExponentAtPriceOne), SwapFee: swapFee, } return pool, nil diff --git a/x/concentrated-liquidity/model/pool_test.go b/x/concentrated-liquidity/model/pool_test.go index 0a532cb43c5..820baef8656 100644 --- a/x/concentrated-liquidity/model/pool_test.go +++ b/x/concentrated-liquidity/model/pool_test.go @@ -271,7 +271,7 @@ func (s *ConcentratedPoolTestSuite) TestApplySwap() { s.Run(tt.name, func() { // Create a concentrated liquidity pool struct instance mock_pool := model.Pool{ - ExponentAtPriceOne: types.ExponentAtPriceOne, + ExponentAtPriceOne: sdk.NewInt(types.ExponentAtPriceOne), CurrentTickLiquidity: tt.currentLiquidity, CurrentTick: tt.currentTick, CurrentSqrtPrice: tt.currentSqrtPrice, @@ -406,7 +406,7 @@ func (s *ConcentratedPoolTestSuite) TestNewConcentratedLiquidityPool() { func (suite *ConcentratedPoolTestSuite) TestCalcActualAmounts() { var ( tickToSqrtPrice = func(tick int64) sdk.Dec { - _, sqrtPrice, err := clmath.TickToSqrtPrice(sdk.NewInt(tick)) + _, sqrtPrice, err := clmath.TickToSqrtPrice(tick) suite.Require().NoError(err) return sqrtPrice } @@ -517,7 +517,7 @@ func (suite *ConcentratedPoolTestSuite) TestCalcActualAmounts() { pool := model.Pool{ CurrentTick: sdk.NewInt(tc.currentTick), } - _, pool.CurrentSqrtPrice, _ = clmath.TickToSqrtPrice(pool.CurrentTick) + _, pool.CurrentSqrtPrice, _ = clmath.TickToSqrtPrice(pool.CurrentTick.Int64()) actualAmount0, actualAmount1, err := pool.CalcActualAmounts(suite.Ctx, tc.lowerTick, tc.upperTick, tc.liquidityDelta) @@ -611,7 +611,7 @@ func (suite *ConcentratedPoolTestSuite) TestUpdateLiquidityIfActivePosition() { CurrentTick: sdk.NewInt(tc.currentTick), CurrentTickLiquidity: defaultLiquidityAmt, } - _, pool.CurrentSqrtPrice, _ = clmath.TickToSqrtPrice(pool.CurrentTick) + _, pool.CurrentSqrtPrice, _ = clmath.TickToSqrtPrice(pool.CurrentTick.Int64()) wasUpdated := pool.UpdateLiquidityIfActivePosition(suite.Ctx, tc.lowerTick, tc.upperTick, tc.liquidityDelta) if tc.lowerTick <= tc.currentTick && tc.currentTick <= tc.upperTick { diff --git a/x/concentrated-liquidity/swaps.go b/x/concentrated-liquidity/swaps.go index 3358c41f28e..58599aafdef 100644 --- a/x/concentrated-liquidity/swaps.go +++ b/x/concentrated-liquidity/swaps.go @@ -41,7 +41,7 @@ type SwapState struct { // Current tick while calculating swap. // Initialized to the pool's current tick. // Updated each time a tick is crossed. - tick sdk.Int + tick int64 // Current liqudiity within the active tick. // Initialized to the pool's current tick's liquidity. @@ -159,20 +159,20 @@ func (k Keeper) swapOutAmtGivenIn( tokenOutDenom string, swapFee sdk.Dec, priceLimit sdk.Dec, -) (calcTokenIn, calcTokenOut sdk.Coin, currentTick sdk.Int, liquidity, sqrtPrice sdk.Dec, err error) { +) (calcTokenIn, calcTokenOut sdk.Coin, currentTick int64, liquidity, sqrtPrice sdk.Dec, err error) { tokenIn, tokenOut, newCurrentTick, newLiquidity, newSqrtPrice, err := k.computeOutAmtGivenIn(ctx, pool.GetId(), tokenIn, tokenOutDenom, swapFee, priceLimit) if err != nil { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } if !tokenOut.Amount.IsPositive() { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, types.InvalidAmountCalculatedError{Amount: tokenOut.Amount} + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, types.InvalidAmountCalculatedError{Amount: tokenOut.Amount} } // Settles balances between the tx sender and the pool to match the swap that was executed earlier. // Also emits swap event and updates related liquidity metrics if err := k.updatePoolForSwap(ctx, pool, sender, tokenIn, tokenOut, newCurrentTick, newLiquidity, newSqrtPrice); err != nil { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } return tokenIn, tokenOut, newCurrentTick, newLiquidity, newSqrtPrice, nil @@ -186,15 +186,15 @@ func (k *Keeper) swapInAmtGivenOut( tokenInDenom string, swapFee sdk.Dec, priceLimit sdk.Dec, -) (calcTokenIn, calcTokenOut sdk.Coin, currentTick sdk.Int, liquidity, sqrtPrice sdk.Dec, err error) { +) (calcTokenIn, calcTokenOut sdk.Coin, currentTick int64, liquidity, sqrtPrice sdk.Dec, err error) { writeCtx, tokenIn, tokenOut, newCurrentTick, newLiquidity, newSqrtPrice, err := k.calcInAmtGivenOut(ctx, desiredTokenOut, tokenInDenom, swapFee, priceLimit, pool.GetId()) if err != nil { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } // check that the tokenOut calculated is both valid and less than specified limit if !tokenIn.Amount.IsPositive() { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, types.InvalidAmountCalculatedError{Amount: tokenIn.Amount} + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, types.InvalidAmountCalculatedError{Amount: tokenIn.Amount} } // N.B. making the call below ensures that any mutations done inside calcInAmtGivenOut @@ -205,7 +205,7 @@ func (k *Keeper) swapInAmtGivenOut( // Settles balances between the tx sender and the pool to match the swap that was executed earlier. // Also emits swap event and updates related liquidity metrics if err := k.updatePoolForSwap(ctx, pool, sender, tokenIn, tokenOut, newCurrentTick, newLiquidity, newSqrtPrice); err != nil { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } return tokenIn, tokenOut, newCurrentTick, newLiquidity, newSqrtPrice, nil @@ -253,11 +253,11 @@ func (k Keeper) computeOutAmtGivenIn( tokenOutDenom string, swapFee sdk.Dec, priceLimit sdk.Dec, -) (tokenIn, tokenOut sdk.Coin, updatedTick sdk.Int, updatedLiquidity, updatedSqrtPrice sdk.Dec, err error) { +) (tokenIn, tokenOut sdk.Coin, updatedTick int64, updatedLiquidity, updatedSqrtPrice sdk.Dec, err error) { // Get pool and asset info p, err := k.getPoolById(ctx, poolId) if err != nil { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } asset0 := p.GetToken0() asset1 := p.GetToken1() @@ -276,7 +276,7 @@ func (k Keeper) computeOutAmtGivenIn( // Take provided price limit and turn this into a sqrt price limit since formulas use sqrtPrice sqrtPriceLimit, err := priceLimit.ApproxSqrt() if err != nil { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, fmt.Errorf("issue calculating square root of price limit") + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, fmt.Errorf("issue calculating square root of price limit") } // Set the swap strategy @@ -286,20 +286,20 @@ func (k Keeper) computeOutAmtGivenIn( // on the correct side of the price limit given swap direction. curSqrtPrice := p.GetCurrentSqrtPrice() if err := swapStrategy.ValidateSqrtPrice(sqrtPriceLimit, curSqrtPrice); err != nil { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } // Check that the specified tokenIn matches one of the assets in the specified pool if tokenInMin.Denom != asset0 && tokenInMin.Denom != asset1 { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, types.TokenInDenomNotInPoolError{TokenInDenom: tokenInMin.Denom} + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, types.TokenInDenomNotInPoolError{TokenInDenom: tokenInMin.Denom} } // Check that the specified tokenOut matches one of the assets in the specified pool if tokenOutDenom != asset0 && tokenOutDenom != asset1 { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, types.TokenOutDenomNotInPoolError{TokenOutDenom: tokenOutDenom} + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, types.TokenOutDenomNotInPoolError{TokenOutDenom: tokenOutDenom} } // Check that token in and token out are different denominations if tokenInMin.Denom == tokenOutDenom { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, types.DenomDuplicatedError{TokenInDenom: tokenInMin.Denom, TokenOutDenom: tokenOutDenom} + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, types.DenomDuplicatedError{TokenInDenom: tokenInMin.Denom, TokenOutDenom: tokenOutDenom} } // initialize swap state with the following parameters: @@ -309,7 +309,7 @@ func (k Keeper) computeOutAmtGivenIn( amountCalculated: sdk.ZeroDec(), // tokenOut sqrtPrice: curSqrtPrice, // Pad (or don't pad) current tick based on swap direction to avoid off-by-one errors - tick: swapStrategy.InitializeTickValue(p.GetCurrentTick()), + tick: swapStrategy.InitializeTickValue(p.GetCurrentTick().Int64()), liquidity: p.GetLiquidity(), feeGrowthGlobal: sdk.ZeroDec(), } @@ -326,15 +326,15 @@ func (k Keeper) computeOutAmtGivenIn( // if zeroForOneStrategy, we look to the left of the tick the current sqrt price is at // if oneForZeroStrategy, we look to the right of the tick the current sqrt price is at // if no ticks are initialized (no users have created liquidity positions) then we return an error - nextTick, ok := swapStrategy.NextInitializedTick(ctx, poolId, swapState.tick.Int64()) + nextTick, ok := swapStrategy.NextInitializedTick(ctx, poolId, swapState.tick) if !ok { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, fmt.Errorf("there are no more ticks initialized to fill the swap") + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, fmt.Errorf("there are no more ticks initialized to fill the swap") } // Utilizing the next initialized tick, we find the corresponding nextPrice (the target price). _, nextTickSqrtPrice, err := math.TickToSqrtPrice(nextTick) if err != nil { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, fmt.Errorf("could not convert next tick (%v) to nextSqrtPrice", nextTick) + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, fmt.Errorf("could not convert next tick (%v) to nextSqrtPrice", nextTick) } // If nextSqrtPrice exceeds the price limit, we set the nextSqrtPrice to the price limit. @@ -371,9 +371,9 @@ func (k Keeper) computeOutAmtGivenIn( // tick has been consumed and we must move on to the next tick to complete the swap if nextTickSqrtPrice.Equal(sqrtPrice) { // Retrieve the liquidity held in the next closest initialized tick - liquidityNet, err := k.crossTick(ctx, p.GetId(), nextTick.Int64(), sdk.NewDecCoinFromDec(tokenInMin.Denom, swapState.feeGrowthGlobal)) + liquidityNet, err := k.crossTick(ctx, p.GetId(), nextTick, sdk.NewDecCoinFromDec(tokenInMin.Denom, swapState.feeGrowthGlobal)) if err != nil { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } liquidityNet = swapStrategy.SetLiquidityDeltaSign(liquidityNet) // Update the swapState's liquidity with the new tick's liquidity @@ -388,13 +388,13 @@ func (k Keeper) computeOutAmtGivenIn( price := sqrtPrice.Mul(sqrtPrice) swapState.tick, err = math.PriceToTickRoundDown(price, p.GetTickSpacing()) if err != nil { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } } } if err := k.chargeFee(ctx, poolId, sdk.NewDecCoinFromDec(tokenInMin.Denom, swapState.feeGrowthGlobal)); err != nil { - return sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } // Coin amounts require int values @@ -423,11 +423,11 @@ func (k Keeper) calcInAmtGivenOut( swapFee sdk.Dec, priceLimit sdk.Dec, poolId uint64, -) (writeCtx func(), tokenIn, tokenOut sdk.Coin, updatedTick sdk.Int, updatedLiquidity, updatedSqrtPrice sdk.Dec, err error) { +) (writeCtx func(), tokenIn, tokenOut sdk.Coin, updatedTick int64, updatedLiquidity, updatedSqrtPrice sdk.Dec, err error) { ctx, writeCtx = ctx.CacheContext() p, err := k.getPoolById(ctx, poolId) if err != nil { - return writeCtx, sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return writeCtx, sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } asset0 := p.GetToken0() asset1 := p.GetToken1() @@ -445,7 +445,7 @@ func (k Keeper) calcInAmtGivenOut( // take provided price limit and turn this into a sqrt price limit since formulas use sqrtPrice sqrtPriceLimit, err := priceLimit.ApproxSqrt() if err != nil { - return writeCtx, sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, fmt.Errorf("issue calculating square root of price limit") + return writeCtx, sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, fmt.Errorf("issue calculating square root of price limit") } // set the swap strategy @@ -455,20 +455,20 @@ func (k Keeper) calcInAmtGivenOut( curSqrtPrice := p.GetCurrentSqrtPrice() if err := swapStrategy.ValidateSqrtPrice(sqrtPriceLimit, curSqrtPrice); err != nil { - return writeCtx, sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return writeCtx, sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } // check that the specified tokenOut matches one of the assets in the specified pool if desiredTokenOut.Denom != asset0 && desiredTokenOut.Denom != asset1 { - return writeCtx, sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, types.TokenOutDenomNotInPoolError{TokenOutDenom: desiredTokenOut.Denom} + return writeCtx, sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, types.TokenOutDenomNotInPoolError{TokenOutDenom: desiredTokenOut.Denom} } // check that the specified tokenIn matches one of the assets in the specified pool if tokenInDenom != asset0 && tokenInDenom != asset1 { - return writeCtx, sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, types.TokenInDenomNotInPoolError{TokenInDenom: tokenInDenom} + return writeCtx, sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, types.TokenInDenomNotInPoolError{TokenInDenom: tokenInDenom} } // check that token in and token out are different denominations if desiredTokenOut.Denom == tokenInDenom { - return writeCtx, sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, types.DenomDuplicatedError{TokenInDenom: tokenInDenom, TokenOutDenom: desiredTokenOut.Denom} + return writeCtx, sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, types.DenomDuplicatedError{TokenInDenom: tokenInDenom, TokenOutDenom: desiredTokenOut.Denom} } // initialize swap state with the following parameters: @@ -477,7 +477,7 @@ func (k Keeper) calcInAmtGivenOut( amountSpecifiedRemaining: desiredTokenOut.Amount.ToDec(), // tokenOut amountCalculated: sdk.ZeroDec(), // tokenIn sqrtPrice: curSqrtPrice, - tick: swapStrategy.InitializeTickValue(p.GetCurrentTick()), + tick: swapStrategy.InitializeTickValue(p.GetCurrentTick().Int64()), liquidity: p.GetLiquidity(), feeGrowthGlobal: sdk.ZeroDec(), } @@ -492,15 +492,15 @@ func (k Keeper) calcInAmtGivenOut( // if zeroForOne is false, we look to the left of the tick the current sqrt price is at // if zeroForOne is true, we look to the right of the tick the current sqrt price is at // if no ticks are initialized (no users have created liquidity positions) then we return an error - nextTick, ok := swapStrategy.NextInitializedTick(ctx, poolId, swapState.tick.Int64()) + nextTick, ok := swapStrategy.NextInitializedTick(ctx, poolId, swapState.tick) if !ok { - return writeCtx, sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, fmt.Errorf("there are no more ticks initialized to fill the swap") + return writeCtx, sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, fmt.Errorf("there are no more ticks initialized to fill the swap") } // utilizing the next initialized tick, we find the corresponding nextPrice (the target price) _, sqrtPriceNextTick, err := math.TickToSqrtPrice(nextTick) if err != nil { - return writeCtx, sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, fmt.Errorf("could not convert next tick (%v) to nextSqrtPrice", nextTick) + return writeCtx, sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, fmt.Errorf("could not convert next tick (%v) to nextSqrtPrice", nextTick) } sqrtPriceTarget := swapStrategy.GetSqrtTargetPrice(sqrtPriceNextTick) @@ -533,9 +533,9 @@ func (k Keeper) calcInAmtGivenOut( // tick has been consumed and we must move on to the next tick to complete the swap if sqrtPriceNextTick.Equal(sqrtPrice) { // retrieve the liquidity held in the next closest initialized tick - liquidityNet, err := k.crossTick(ctx, p.GetId(), nextTick.Int64(), sdk.NewDecCoinFromDec(desiredTokenOut.Denom, swapState.feeGrowthGlobal)) + liquidityNet, err := k.crossTick(ctx, p.GetId(), nextTick, sdk.NewDecCoinFromDec(desiredTokenOut.Denom, swapState.feeGrowthGlobal)) if err != nil { - return writeCtx, sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return writeCtx, sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } liquidityNet = swapStrategy.SetLiquidityDeltaSign(liquidityNet) // update the swapState's liquidity with the new tick's liquidity @@ -550,13 +550,13 @@ func (k Keeper) calcInAmtGivenOut( price := sqrtPrice.Mul(sqrtPrice) swapState.tick, err = math.PriceToTickRoundDown(price, p.GetTickSpacing()) if err != nil { - return writeCtx, sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return writeCtx, sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } } } if err := k.chargeFee(ctx, poolId, sdk.NewDecCoinFromDec(tokenInDenom, swapState.feeGrowthGlobal)); err != nil { - return writeCtx, sdk.Coin{}, sdk.Coin{}, sdk.Int{}, sdk.Dec{}, sdk.Dec{}, err + return writeCtx, sdk.Coin{}, sdk.Coin{}, 0, sdk.Dec{}, sdk.Dec{}, err } // coin amounts require int values @@ -591,7 +591,7 @@ func (k Keeper) updatePoolForSwap( sender sdk.AccAddress, tokenIn sdk.Coin, tokenOut sdk.Coin, - newCurrentTick sdk.Int, + newCurrentTick int64, newLiquidity sdk.Dec, newSqrtPrice sdk.Dec, ) error { @@ -617,7 +617,7 @@ func (k Keeper) updatePoolForSwap( return types.InsufficientPoolBalanceError{Err: err} } - err = pool.ApplySwap(newLiquidity, newCurrentTick, newSqrtPrice) + err = pool.ApplySwap(newLiquidity, sdk.NewInt(newCurrentTick), newSqrtPrice) if err != nil { return fmt.Errorf("error applying swap: %w", err) } diff --git a/x/concentrated-liquidity/swaps_test.go b/x/concentrated-liquidity/swaps_test.go index f59e3049730..765325e455b 100644 --- a/x/concentrated-liquidity/swaps_test.go +++ b/x/concentrated-liquidity/swaps_test.go @@ -38,7 +38,7 @@ type SwapTest struct { expectedTokenIn sdk.Coin expectedTokenOut sdk.Coin - expectedTick sdk.Int + expectedTick int64 expectedSqrtPrice sdk.Dec expectedLowerTickFeeGrowth sdk.DecCoins expectedUpperTickFeeGrowth sdk.DecCoins @@ -82,7 +82,7 @@ var ( // expectedTokenOut: 8396.71424216 rounded down https://www.wolframalpha.com/input?i=%281517882343.751510418088349649+*+%2870.738348247484497717+-+70.710678118654752440+%29%29+%2F+%2870.710678118654752440+*+70.738348247484497717%29 expectedTokenIn: sdk.NewCoin("usdc", sdk.NewInt(42000000)), expectedTokenOut: sdk.NewCoin("eth", sdk.NewInt(8396)), - expectedTick: sdk.NewInt(31003900), + expectedTick: 31003900, expectedSqrtPrice: sdk.MustNewDecFromStr("70.738348247484497717"), // https://www.wolframalpha.com/input?i=70.710678118654752440+%2B+42000000+%2F+1517882343.751510418088349649 // tick's accum coins stay same since crossing tick does not occur in this case expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, @@ -101,7 +101,7 @@ var ( // expectedTokenOut: 66808388.8901 rounded down https://www.wolframalpha.com/input?i=1517882343.751510418088349649+*+%2870.710678118654752440+-+70.6666639108571443311%29 expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(13370)), expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(66808388)), - expectedTick: sdk.NewInt(30993700), + expectedTick: 30993700, expectedSqrtPrice: sdk.MustNewDecFromStr("70.666663910857144332"), // https://www.wolframalpha.com/input?i=%28%281517882343.751510418088349649%29%29+%2F+%28%28%281517882343.751510418088349649%29+%2F+%2870.710678118654752440%29%29+%2B+%2813370%29%29 expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -126,7 +126,7 @@ var ( // expectedTokenOut: 8398.3567 rounded down https://www.wolframalpha.com/input?i=%283035764687.503020836176699298+*+%2870.724513183069625078+-+70.710678118654752440+%29%29+%2F+%2870.710678118654752440+*+70.724513183069625078%29 expectedTokenIn: sdk.NewCoin("usdc", sdk.NewInt(42000000)), expectedTokenOut: sdk.NewCoin("eth", sdk.NewInt(8398)), - expectedTick: sdk.NewInt(31001900), + expectedTick: 31001900, expectedSqrtPrice: sdk.MustNewDecFromStr("70.724513183069625078"), // https://www.wolframalpha.com/input?i=70.710678118654752440+%2B++++%2842000000++%2F+3035764687.503020836176699298%29 // two positions with same liquidity entered poolLiqAmount0: sdk.NewInt(1000000).MulRaw(2), @@ -149,7 +149,7 @@ var ( // expectedTokenOut: 66829187.9678 rounded down https://www.wolframalpha.com/input?i=3035764687.503020836176699298+*+%2870.710678118654752440+-+70.688664163408836319%29 expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(13370)), expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(66829187)), - expectedTick: sdk.NewInt(30996800), + expectedTick: 30996800, expectedSqrtPrice: sdk.MustNewDecFromStr("70.688664163408836320"), // https://www.wolframalpha.com/input?i=%28%283035764687.503020836176699298%29%29+%2F+%28%28%283035764687.503020836176699298%29+%2F+%2870.710678118654752440%29%29+%2B+%2813370.0000%29%29 // two positions with same liquidity entered poolLiqAmount0: sdk.NewInt(1000000).MulRaw(2), @@ -186,7 +186,7 @@ var ( // expectedTokenOut: 998976.6183474263883566299269 + 821653.4522259 = 1820630.070 round down = 1.820630 eth expectedTokenIn: sdk.NewCoin("usdc", sdk.NewInt(10000000000)), expectedTokenOut: sdk.NewCoin("eth", sdk.NewInt(1820630)), - expectedTick: sdk.NewInt(32105400), + expectedTick: 32105400, expectedSqrtPrice: sdk.MustNewDecFromStr("78.137149196095607129"), // https://www.wolframalpha.com/input?i=74.16198487095662948711397441+%2B+4761322417+%2F+1197767444.955508123222985080 expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -219,7 +219,7 @@ var ( expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(2000000)), expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(9103422788)), // crosses one tick with fee growth outside - expectedTick: sdk.NewInt(30095100), + expectedTick: 30095100, expectedSqrtPrice: sdk.MustNewDecFromStr("63.993489023323078693"), // https://www.wolframalpha.com/input?i=%28%281198735489.597250295669959397%29%29+%2F+%28%28%281198735489.597250295669959397%29+%2F+%28+67.41661516273269559379442134%29%29+%2B+%28951138.000000000000000000%29%29 // crossing tick happens single time for each upper tick and lower tick. // Thus the tick's fee growth is DefaultFeeAccumCoins * 3 - DefaultFeeAccumCoins @@ -259,7 +259,7 @@ var ( // expectedTokenOut: 998976.6183474263883566299269692777 + 865185.2591363751404579873403641 = 1864161.877 round down = 1.864161 eth expectedTokenIn: sdk.NewCoin("usdc", sdk.NewInt(10000000000)), expectedTokenOut: sdk.NewCoin("eth", sdk.NewInt(1864161)), - expectedTick: sdk.NewInt(32055900), + expectedTick: 32055900, expectedSqrtPrice: sdk.MustNewDecFromStr("77.819789636800169392"), // https://www.wolframalpha.com/input?i=74.16198487095662948711397441+%2B++++%282452251164.000000000000000000+%2F+670416088.605668727039240782%29 expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -294,7 +294,7 @@ var ( expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, expectedSecondLowerTickFeeGrowth: secondPosition{tickIndex: 310010, expectedFeeGrowth: cl.EmptyCoins}, expectedSecondUpperTickFeeGrowth: secondPosition{tickIndex: 322500, expectedFeeGrowth: cl.EmptyCoins}, - expectedTick: sdk.NewInt(31712600), + expectedTick: 31712600, expectedSqrtPrice: sdk.MustNewDecFromStr("75.582373164412551491"), // https://www.wolframalpha.com/input?i=74.16198487095662948711397441++%2B+%28+952251164.000000000000000000++%2F+670416088.605668727039240782%29 newLowerPrice: sdk.NewDec(5001), newUpperPrice: sdk.NewDec(6250), @@ -321,7 +321,7 @@ var ( secondPositionUpperPrice: sdk.NewDec(4999), expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(2000000)), expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(9321276930)), - expectedTick: sdk.NewInt(30129000), + expectedTick: 30129000, expectedSqrtPrice: sdk.MustNewDecFromStr("64.257943794993248954"), // https://www.wolframalpha.com/input?i=%28%28670416215.71882744366040059300%29%29+%2F+%28%28%28670416215.71882744366040059300%29+%2F+%2867.41661516273269559379442134%29%29+%2B+%28488827.000000000000000000%29%29 // Started from DefaultFeeAccumCoins * 3, crossed tick once, thus becoming // DefaultFeeAccumCoins * 3 - DefaultFeeAccumCoins = DefaultFeeAccumCoins * 2 @@ -351,7 +351,7 @@ var ( secondPositionUpperPrice: sdk.NewDec(4999), expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(1800000)), expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(8479320318)), - expectedTick: sdk.NewInt(30292000), + expectedTick: 30292000, expectedSqrtPrice: sdk.MustNewDecFromStr("65.513815285481060960"), // https://www.wolframalpha.com/input?i=%28%28670416215.718827443660400593000%29%29+%2F+%28%28%28670416215.718827443660400593000%29+%2F+%2867.41661516273269559379442134%29%29+%2B+%28288827.000000000000000000%29%29 // Started from DefaultFeeAccumCoins * 3, crossed tick once, thus becoming // DefaultFeeAccumCoins * 3 - DefaultFeeAccumCoins = DefaultFeeAccumCoins * 2 @@ -390,7 +390,7 @@ var ( // expectedTokenOut: 998976.61834742638835 + 821569.240826953837970 = 1820545.85917438022632 round down = 1.820545 eth expectedTokenIn: sdk.NewCoin("usdc", sdk.NewInt(10000000000)), expectedTokenOut: sdk.NewCoin("eth", sdk.NewInt(1820545)), - expectedTick: sdk.NewInt(32105500), + expectedTick: 32105500, expectedSqrtPrice: sdk.MustNewDecFromStr("78.138055169663761658"), // https://www.wolframalpha.com/input?i=74.16872656315463530313879691++%2B+%28+4761322417.000000000000000000++%2F+1199528406.187413669220037261%29 expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -415,7 +415,7 @@ var ( // expectedTokenOut: 64417624.98716495170 rounded down https://www.wolframalpha.com/input?key=&i=1517882343.751510418088349649+*+%2870.710678118654752440+-+70.668238976219012614%29 expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(12892)), expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(64417624)), - expectedTick: func() sdk.Int { + expectedTick: func() int64 { tick, _ := math.PriceToTickRoundDown(sdk.NewDec(4994), DefaultTickSpacing) return tick }(), @@ -445,7 +445,7 @@ var ( // expectedFeeGrowthAccumulatorValue: 0.000276701288297452 expectedTokenIn: sdk.NewCoin("usdc", sdk.NewInt(42000000)), expectedTokenOut: sdk.NewCoin("eth", sdk.NewInt(8312)), - expectedTick: sdk.NewInt(31003800), + expectedTick: 31003800, expectedSqrtPrice: sdk.MustNewDecFromStr("70.738071546196200264"), // https://www.wolframalpha.com/input?i=70.71067811865475244008443621+%2B++++%2841580000.000000000000000000+%2F+1517882343.751510418088349649%29 expectedFeeGrowthAccumulatorValue: sdk.MustNewDecFromStr("0.000276701288297452"), }, @@ -470,7 +470,7 @@ var ( // expectedFeeGrowthAccumulatorValue: 0.000000132124865162033700093060000008 expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(13370)), expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(64824917)), - expectedTick: sdk.NewInt(30996900), + expectedTick: 30996900, expectedSqrtPrice: sdk.MustNewDecFromStr("70.689324382628080102"), // https://www.wolframalpha.com/input?i=%28%283035764687.503020836176699298%29%29+%2F+%28%28%283035764687.503020836176699298%29+%2F+%2870.71067811865475244008443621%29%29+%2B+%2812968.900000000000000000%29%29 expectedFeeGrowthAccumulatorValue: sdk.MustNewDecFromStr("0.000000132091924532"), // two positions with same liquidity entered @@ -496,7 +496,7 @@ var ( expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(2000000)), expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(8691708221)), expectedFeeGrowthAccumulatorValue: sdk.MustNewDecFromStr("0.000073738597832046"), - expectedTick: sdk.NewInt(30139200), + expectedTick: 30139200, expectedSqrtPrice: sdk.MustNewDecFromStr("64.336946417392457832"), // https://www.wolframalpha.com/input?i=%28%281198735489.597250295669959397%29%29+%2F+%28%28%281198735489.597250295669959397%29+%2F+%28+67.41661516273269559379442134%29%29+%2B+%28851137.999999999999999999%29%29 newLowerPrice: sdk.NewDec(4000), newUpperPrice: sdk.NewDec(4545), @@ -519,7 +519,7 @@ var ( expectedTokenIn: sdk.NewCoin("usdc", sdk.NewInt(10000000000)), expectedTokenOut: sdk.NewCoin("eth", sdk.NewInt(1695807)), expectedFeeGrowthAccumulatorValue: sdk.MustNewDecFromStr("0.624166726347032857"), - expectedTick: sdk.NewInt(31825900), + expectedTick: 31825900, expectedSqrtPrice: sdk.MustNewDecFromStr("76.328178655208424124"), // https://www.wolframalpha.com/input?i=+74.16198487095662948711397441+%2B++++%281452251164.000000000000000001+%2F+670416088.605668727039240782%29 newLowerPrice: sdk.NewDec(5001), newUpperPrice: sdk.NewDec(6250), @@ -539,7 +539,7 @@ var ( expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(1800000)), expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(8440657775)), expectedFeeGrowthAccumulatorValue: sdk.MustNewDecFromStr("0.000005569829831408"), - expectedTick: sdk.NewInt(30299600), + expectedTick: 30299600, expectedSqrtPrice: sdk.MustNewDecFromStr("65.571484748647169032"), // https://www.wolframalpha.com/input?i=%28%28670416215.718827443660400593000%29%29+%2F+%28%28%28670416215.718827443660400593000%29+%2F+%28+67.41661516273269559379442134%29%29+%2B+%28279827.000000000000000001%29%29 newLowerPrice: sdk.NewDec(4000), newUpperPrice: sdk.NewDec(4999), @@ -559,7 +559,7 @@ var ( expectedTokenIn: sdk.NewCoin("usdc", sdk.NewInt(10000000000)), expectedTokenOut: sdk.NewCoin("eth", sdk.NewInt(1771252)), expectedFeeGrowthAccumulatorValue: sdk.MustNewDecFromStr("0.221769187794051751"), - expectedTick: sdk.NewInt(32066500), + expectedTick: 32066500, expectedSqrtPrice: sdk.MustNewDecFromStr("77.887956882326389372"), // https://www.wolframalpha.com/input?i=74.16872656315463530313879691+%2B++++%284461322417.000000000000000001+%2F+1199528406.187413669220037261%29 newLowerPrice: sdk.NewDec(5501), newUpperPrice: sdk.NewDec(6250), @@ -580,7 +580,7 @@ var ( expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(13023)), expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(64417624)), expectedFeeGrowthAccumulatorValue: sdk.MustNewDecFromStr("0.000000085792039652"), - expectedTick: func() sdk.Int { + expectedTick: func() int64 { tick, _ := math.PriceToTickRoundDown(sdk.NewDec(4994), DefaultTickSpacing) return tick }(), @@ -627,7 +627,7 @@ var ( // print(token_in) expectedTokenOut: sdk.NewCoin(USDC, sdk.NewInt(42000000)), expectedTokenIn: sdk.NewCoin(ETH, sdk.NewInt(8404)), - expectedTick: sdk.NewInt(30996000), + expectedTick: 30996000, expectedSqrtPrice: sdk.MustNewDecFromStr("70.683007989825007162"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -648,7 +648,7 @@ var ( // print(token_in) expectedTokenOut: sdk.NewCoin(ETH, sdk.NewInt(13370)), expectedTokenIn: sdk.NewCoin(USDC, sdk.NewInt(66891663)), - expectedTick: sdk.NewInt(31006200), + expectedTick: 31006200, expectedSqrtPrice: sdk.MustNewDecFromStr("70.754747188468900467"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -676,7 +676,7 @@ var ( // print(token_in) expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(66829187)), expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(13370)), - expectedTick: sdk.NewInt(30996800), + expectedTick: 30996800, expectedSqrtPrice: sdk.MustNewDecFromStr("70.688664163727643650"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -702,7 +702,7 @@ var ( // print(token_in) expectedTokenOut: sdk.NewCoin("eth", sdk.NewInt(8398)), expectedTokenIn: sdk.NewCoin("usdc", sdk.NewInt(41998216)), - expectedTick: sdk.NewInt(31001900), + expectedTick: 31001900, expectedSqrtPrice: sdk.MustNewDecFromStr("70.724512595179305566"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -747,7 +747,7 @@ var ( // print(token_in) expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(9103422788)), expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(2000000)), - expectedTick: sdk.NewInt(30095100), + expectedTick: 30095100, expectedSqrtPrice: sdk.MustNewDecFromStr("63.993489023888951975"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins.MulDec(sdk.NewDec(2)), @@ -796,7 +796,7 @@ var ( // print(token_in) expectedTokenOut: sdk.NewCoin(ETH, sdk.NewInt(1820630)), expectedTokenIn: sdk.NewCoin(USDC, sdk.NewInt(9999999570)), - expectedTick: sdk.NewInt(32105400), + expectedTick: 32105400, expectedSqrtPrice: sdk.MustNewDecFromStr("78.137148837036751553"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -853,7 +853,7 @@ var ( // print(token_in) expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(2000000)), expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(9321276930)), - expectedTick: sdk.NewInt(30129000), + expectedTick: 30129000, expectedSqrtPrice: sdk.MustNewDecFromStr("64.257943796086567725"), // Started from DefaultFeeAccumCoins * 3, crossed tick once, thus becoming // DefaultFeeAccumCoins * 3 - DefaultFeeAccumCoins = DefaultFeeAccumCoins * 2 @@ -909,7 +909,7 @@ var ( // print(token_in) expectedTokenIn: sdk.NewCoin(ETH, sdk.NewInt(1800000)), expectedTokenOut: sdk.NewCoin(USDC, sdk.NewInt(8479320318)), - expectedTick: sdk.NewInt(30292000), + expectedTick: 30292000, expectedSqrtPrice: sdk.MustNewDecFromStr("65.513815286452064191"), // Started from DefaultFeeAccumCoins * 3, crossed tick once, thus becoming // DefaultFeeAccumCoins * 3 - DefaultFeeAccumCoins = DefaultFeeAccumCoins * 2 @@ -968,7 +968,7 @@ var ( // print(token_in) expectedTokenIn: sdk.NewCoin(USDC, sdk.NewInt(9999994688)), expectedTokenOut: sdk.NewCoin(ETH, sdk.NewInt(1864161)), - expectedTick: sdk.NewInt(32055900), + expectedTick: 32055900, expectedSqrtPrice: sdk.MustNewDecFromStr("77.819781711876553576"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -1023,7 +1023,7 @@ var ( expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, expectedSecondLowerTickFeeGrowth: secondPosition{tickIndex: 310010, expectedFeeGrowth: cl.EmptyCoins}, expectedSecondUpperTickFeeGrowth: secondPosition{tickIndex: 322500, expectedFeeGrowth: cl.EmptyCoins}, - expectedTick: sdk.NewInt(31712600), + expectedTick: 31712600, expectedSqrtPrice: sdk.MustNewDecFromStr("75.582372355128594341"), newLowerPrice: sdk.NewDec(5001), newUpperPrice: sdk.NewDec(6250), @@ -1068,7 +1068,7 @@ var ( // print(token_in) expectedTokenOut: sdk.NewCoin(ETH, sdk.NewInt(1820545)), expectedTokenIn: sdk.NewCoin(USDC, sdk.NewInt(9999994756)), - expectedTick: sdk.NewInt(32105500), + expectedTick: 32105500, expectedSqrtPrice: sdk.MustNewDecFromStr("78.138050797173647031"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -1099,7 +1099,7 @@ var ( // print(token_in_1) expectedTokenOut: sdk.NewCoin(ETH, sdk.NewInt(4291)), expectedTokenIn: sdk.NewCoin(USDC, sdk.NewInt(21463952)), - expectedTick: sdk.NewInt(31002000), + expectedTick: 31002000, expectedSqrtPrice: sdk.MustNewDecFromStr("70.724818840347693039"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -1131,7 +1131,7 @@ var ( // print(fee_growth) expectedTokenOut: sdk.NewCoin(USDC, sdk.NewInt(42000000)), expectedTokenIn: sdk.NewCoin(ETH, sdk.NewInt(8489)), - expectedTick: sdk.NewInt(30996000), + expectedTick: 30996000, expectedSqrtPrice: sdk.MustNewDecFromStr("70.683007989825007162"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -1163,7 +1163,7 @@ var ( // print(fee_growth) expectedTokenOut: sdk.NewCoin(ETH, sdk.NewInt(8398)), expectedTokenIn: sdk.NewCoin(USDC, sdk.NewInt(43297130)), - expectedTick: sdk.NewInt(31001900), + expectedTick: 31001900, expectedSqrtPrice: sdk.MustNewDecFromStr("70.724512595179305566"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -1210,7 +1210,7 @@ var ( // print(fee_growth) expectedTokenOut: sdk.NewCoin(ETH, sdk.NewInt(1820630)), expectedTokenIn: sdk.NewCoin(USDC, sdk.NewInt(10010009580)), - expectedTick: sdk.NewInt(32105400), + expectedTick: 32105400, expectedSqrtPrice: sdk.MustNewDecFromStr("78.137148837036751553"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -1268,7 +1268,7 @@ var ( // print(fee_growth) expectedTokenIn: sdk.NewCoin("eth", sdk.NewInt(2222223)), expectedTokenOut: sdk.NewCoin("usdc", sdk.NewInt(9321276930)), - expectedTick: sdk.NewInt(30129000), + expectedTick: 30129000, expectedSqrtPrice: sdk.MustNewDecFromStr("64.257943796086567725"), // Started from DefaultFeeAccumCoins * 3, crossed tick once, thus becoming // DefaultFeeAccumCoins * 3 - DefaultFeeAccumCoins = DefaultFeeAccumCoins * 2 @@ -1332,7 +1332,7 @@ var ( expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, expectedSecondLowerTickFeeGrowth: secondPosition{tickIndex: 310010, expectedFeeGrowth: cl.EmptyCoins}, expectedSecondUpperTickFeeGrowth: secondPosition{tickIndex: 322500, expectedFeeGrowth: cl.EmptyCoins}, - expectedTick: sdk.NewInt(31712600), + expectedTick: 31712600, expectedSqrtPrice: sdk.MustNewDecFromStr("75.582372355128594341"), newLowerPrice: sdk.NewDec(5001), newUpperPrice: sdk.NewDec(6250), @@ -1375,7 +1375,7 @@ var ( // print(fee_growth) expectedTokenOut: sdk.NewCoin(ETH, sdk.NewInt(1820545)), expectedTokenIn: sdk.NewCoin(USDC, sdk.NewInt(10002995655)), - expectedTick: sdk.NewInt(32105500), + expectedTick: 32105500, expectedSqrtPrice: sdk.MustNewDecFromStr("78.138050797173647031"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -1411,7 +1411,7 @@ var ( // print(fee_growth) expectedTokenOut: sdk.NewCoin(ETH, sdk.NewInt(4291)), expectedTokenIn: sdk.NewCoin(USDC, sdk.NewInt(21680760)), - expectedTick: sdk.NewInt(31002000), + expectedTick: 31002000, expectedSqrtPrice: sdk.MustNewDecFromStr("70.724818840347693039"), expectedLowerTickFeeGrowth: DefaultFeeAccumCoins, expectedUpperTickFeeGrowth: DefaultFeeAccumCoins, @@ -1477,7 +1477,7 @@ func (s *KeeperTestSuite) TestComputeAndSwapOutAmtGivenIn() { newUpperTick, err := math.PriceToTickRoundDown(test.secondPositionUpperPrice, pool.GetTickSpacing()) s.Require().NoError(err) - _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick.Int64(), newUpperTick.Int64()) + _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick, newUpperTick) s.Require().NoError(err) } @@ -1502,7 +1502,7 @@ func (s *KeeperTestSuite) TestComputeAndSwapOutAmtGivenIn() { s.Require().NoError(err) // check that tokenIn, tokenOut, tick, and sqrtPrice from CalcOut are all what we expected - s.Require().Equal(test.expectedTick.String(), updatedTick.String()) + s.Require().Equal(test.expectedTick, updatedTick) s.Require().Equal(test.expectedTokenIn.String(), tokenIn.String()) s.Require().Equal(test.expectedTokenOut.String(), tokenOut.String()) s.Require().Equal(test.expectedSqrtPrice, sqrtPrice) @@ -1555,7 +1555,7 @@ func (s *KeeperTestSuite) TestComputeAndSwapOutAmtGivenIn() { s.Require().Equal(test.expectedTokenIn.String(), tokenIn.String()) s.Require().Equal(test.expectedTokenOut.String(), tokenOut.String()) - s.Require().Equal(test.expectedTick.String(), updatedTick.String()) + s.Require().Equal(test.expectedTick, updatedTick) s.Require().Equal(test.expectedSqrtPrice, sqrtPrice) if test.newLowerPrice.IsNil() && test.newUpperPrice.IsNil() { @@ -1633,7 +1633,7 @@ func (s *KeeperTestSuite) TestSwapOutAmtGivenIn_TickUpdates() { newUpperTick, err := math.PriceToTickRoundDown(test.secondPositionUpperPrice, pool.GetTickSpacing()) s.Require().NoError(err) - _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick.Int64(), newUpperTick.Int64()) + _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick, newUpperTick) s.Require().NoError(err) } @@ -1715,7 +1715,7 @@ func (s *KeeperTestSuite) TestCalcAndSwapInAmtGivenOut() { newUpperTick, err := math.PriceToTickRoundDown(test.secondPositionUpperPrice, pool.GetTickSpacing()) s.Require().NoError(err) - _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick.Int64(), newUpperTick.Int64()) + _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick, newUpperTick) s.Require().NoError(err) } @@ -1736,7 +1736,7 @@ func (s *KeeperTestSuite) TestCalcAndSwapInAmtGivenOut() { s.Require().Equal(test.expectedSqrtPrice, sqrtPrice) s.Require().Equal(test.expectedTokenOut.String(), tokenOut.String()) s.Require().Equal(test.expectedTokenIn.String(), tokenIn.String()) - s.Require().Equal(test.expectedTick.String(), updatedTick.String()) + s.Require().Equal(test.expectedTick, updatedTick) if test.newLowerPrice.IsNil() && test.newUpperPrice.IsNil() { test.newLowerPrice = DefaultLowerPrice @@ -1787,12 +1787,12 @@ func (s *KeeperTestSuite) TestCalcAndSwapInAmtGivenOut() { s.Require().NoError(err) // check that tokenIn, tokenOut, tick, and sqrtPrice from SwapOut are all what we expected - s.Require().Equal(test.expectedTick.String(), updatedTick.String()) + s.Require().Equal(test.expectedTick, updatedTick) s.Require().Equal(test.expectedTokenIn.String(), tokenIn.String()) s.Require().Equal(test.expectedTokenOut.String(), tokenOut.String()) s.Require().Equal(test.expectedSqrtPrice, sqrtPrice) // also ensure the pool's currentTick and currentSqrtPrice was updated due to calling a mutative method - s.Require().Equal(test.expectedTick.String(), pool.GetCurrentTick().String()) + s.Require().Equal(test.expectedTick, pool.GetCurrentTick().Int64()) if test.newLowerPrice.IsNil() && test.newUpperPrice.IsNil() { test.newLowerPrice = DefaultLowerPrice @@ -1879,7 +1879,7 @@ func (s *KeeperTestSuite) TestSwapInAmtGivenOut_TickUpdates() { newUpperTick, err := math.PriceToTickRoundDown(test.secondPositionUpperPrice, pool.GetTickSpacing()) s.Require().NoError(err) - _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick.Int64(), newUpperTick.Int64()) + _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick, newUpperTick) s.Require().NoError(err) } @@ -2314,7 +2314,7 @@ func (s *KeeperTestSuite) TestComputeOutAmtGivenIn() { newUpperTick, err := math.PriceToTickRoundDown(test.secondPositionUpperPrice, pool.GetTickSpacing()) s.Require().NoError(err) - _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick.Int64(), newUpperTick.Int64()) + _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick, newUpperTick) s.Require().NoError(err) } @@ -2382,7 +2382,7 @@ func (s *KeeperTestSuite) TestCalcOutAmtGivenIn_NonMutative() { newUpperTick, err := math.PriceToTickRoundDown(test.secondPositionUpperPrice, pool.GetTickSpacing()) s.Require().NoError(err) - _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick.Int64(), newUpperTick.Int64()) + _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick, newUpperTick) s.Require().NoError(err) } @@ -2451,7 +2451,7 @@ func (s *KeeperTestSuite) TestCalcInAmtGivenOutWriteCtx() { newUpperTick, err := math.PriceToTickRoundDown(test.secondPositionUpperPrice, pool.GetTickSpacing()) s.Require().NoError(err) - _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick.Int64(), newUpperTick.Int64()) + _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick, newUpperTick) s.Require().NoError(err) } @@ -2527,7 +2527,7 @@ func (s *KeeperTestSuite) TestInverseRelationshipSwapOutAmtGivenIn() { newUpperTick, err := math.PriceToTickRoundDown(test.secondPositionUpperPrice, pool.GetTickSpacing()) s.Require().NoError(err) - _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick.Int64(), newUpperTick.Int64()) + _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick, newUpperTick) s.Require().NoError(err) } @@ -2625,7 +2625,7 @@ func (s *KeeperTestSuite) TestInverseRelationshipSwapInAmtGivenOut() { newUpperTick, err := math.PriceToTickRoundDown(test.secondPositionUpperPrice, pool.GetTickSpacing()) s.Require().NoError(err) - _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick.Int64(), newUpperTick.Int64()) + _, _, _, _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, pool.GetId(), s.TestAccs[1], DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), newLowerTick, newUpperTick) s.Require().NoError(err) } @@ -2667,7 +2667,7 @@ func (suite *KeeperTestSuite) TestUpdatePoolForSwap() { poolInitialBalance sdk.Coins tokenIn sdk.Coin tokenOut sdk.Coin - newCurrentTick sdk.Int + newCurrentTick int64 newLiquidity sdk.Dec newSqrtPrice sdk.Dec expectError error @@ -2677,7 +2677,7 @@ func (suite *KeeperTestSuite) TestUpdatePoolForSwap() { poolInitialBalance: defaultInitialBalance, tokenIn: oneHundredETH, tokenOut: oneHundredUSDC, - newCurrentTick: sdk.NewInt(2), + newCurrentTick: 2, newLiquidity: sdk.NewDec(2), newSqrtPrice: sdk.NewDec(2), }, @@ -2686,7 +2686,7 @@ func (suite *KeeperTestSuite) TestUpdatePoolForSwap() { poolInitialBalance: defaultInitialBalance, tokenIn: oneHundredETH.Add(oneHundredETH), tokenOut: oneHundredUSDC, - newCurrentTick: sdk.NewInt(8), + newCurrentTick: 8, newLiquidity: sdk.NewDec(37), newSqrtPrice: sdk.NewDec(91), }, @@ -2695,7 +2695,7 @@ func (suite *KeeperTestSuite) TestUpdatePoolForSwap() { poolInitialBalance: defaultInitialBalance, tokenIn: oneHundredETH.Add(oneHundredETH), tokenOut: oneHundredUSDC, - newCurrentTick: sdk.NewInt(2), + newCurrentTick: 2, newLiquidity: sdk.NewDec(2), newSqrtPrice: sdk.NewDec(2), expectError: types.InsufficientUserBalanceError{}, @@ -2705,7 +2705,7 @@ func (suite *KeeperTestSuite) TestUpdatePoolForSwap() { poolInitialBalance: defaultInitialBalance, tokenIn: oneHundredETH, tokenOut: oneHundredUSDC.Add(oneHundredUSDC), - newCurrentTick: sdk.NewInt(2), + newCurrentTick: 2, newLiquidity: sdk.NewDec(2), newSqrtPrice: sdk.NewDec(2), expectError: types.InsufficientPoolBalanceError{}, @@ -2752,7 +2752,7 @@ func (suite *KeeperTestSuite) TestUpdatePoolForSwap() { } suite.Require().NoError(err) - suite.Require().Equal(tc.newCurrentTick, poolAfterUpdate.GetCurrentTick()) + suite.Require().Equal(tc.newCurrentTick, poolAfterUpdate.GetCurrentTick().Int64()) suite.Require().Equal(tc.newLiquidity, poolAfterUpdate.GetLiquidity()) suite.Require().Equal(tc.newSqrtPrice, poolAfterUpdate.GetCurrentSqrtPrice()) diff --git a/x/concentrated-liquidity/swapstrategy/one_for_zero.go b/x/concentrated-liquidity/swapstrategy/one_for_zero.go index d61278481ad..bcc0c7c803b 100644 --- a/x/concentrated-liquidity/swapstrategy/one_for_zero.go +++ b/x/concentrated-liquidity/swapstrategy/one_for_zero.go @@ -156,8 +156,8 @@ func (s oneForZeroStrategy) ComputeSwapStepInGivenOut(sqrtPriceCurrent, sqrtPric // Therefore, this method is, essentially a no-op. The logic is reversed for // zeroForOneStrategy where we use reverse iterator and have to add one to // the input. Therefore, we define this method to account for different strategies. -func (s oneForZeroStrategy) InitializeTickValue(currentTick sdk.Int) sdk.Int { - return currentTick +func (s oneForZeroStrategy) InitializeTickValue(currentTick int64) int64 { + return currentTick + 1 } // NextInitializedTick returns the next initialized tick index based on the @@ -165,7 +165,7 @@ func (s oneForZeroStrategy) InitializeTickValue(currentTick sdk.Int) sdk.Int { // will be returned. // // oneForZerostrategy searches for the next tick to the right of the current tickIndex. -func (s oneForZeroStrategy) NextInitializedTick(ctx sdk.Context, poolId uint64, tickIndex int64) (next sdk.Int, initialized bool) { +func (s oneForZeroStrategy) NextInitializedTick(ctx sdk.Context, poolId uint64, tickIndex int64) (next int64, initialized bool) { store := ctx.KVStore(s.storeKey) // Construct a prefix store with a prefix of , allowing @@ -186,10 +186,10 @@ func (s oneForZeroStrategy) NextInitializedTick(ctx sdk.Context, poolId uint64, } if tick > tickIndex { - return sdk.NewInt(tick), true + return tick, true } } - return sdk.ZeroInt(), false + return 0, false } // SetLiquidityDeltaSign sets the liquidity delta sign for the given liquidity delta. diff --git a/x/concentrated-liquidity/swapstrategy/swap_strategy.go b/x/concentrated-liquidity/swapstrategy/swap_strategy.go index 367e88319c2..2f8acad24f1 100644 --- a/x/concentrated-liquidity/swapstrategy/swap_strategy.go +++ b/x/concentrated-liquidity/swapstrategy/swap_strategy.go @@ -52,12 +52,12 @@ type swapStrategy interface { // InitializeTickValue returns the initial tick value for computing swaps based // on the actual current tick. // See oneForZeroStrategy or zeroForOneStrategy for implementation details. - InitializeTickValue(currentTick sdk.Int) sdk.Int + InitializeTickValue(currentTick int64) int64 // NextInitializedTick returns the next initialized tick index based on the // provided tickindex. If no initialized tick exists, <0, false> // will be returned. // See oneForZeroStrategy or zeroForOneStrategy for implementation details. - NextInitializedTick(ctx sdk.Context, poolId uint64, tickIndex int64) (next sdk.Int, initialized bool) + NextInitializedTick(ctx sdk.Context, poolId uint64, tickIndex int64) (next int64, initialized bool) // SetLiquidityDeltaSign sets the liquidity delta sign for the given liquidity delta. // This is called when consuming all liquidity. // When a position is created, we add liquidity to lower tick diff --git a/x/concentrated-liquidity/swapstrategy/swap_strategy_test.go b/x/concentrated-liquidity/swapstrategy/swap_strategy_test.go index 2c217227515..e29a1f2b584 100644 --- a/x/concentrated-liquidity/swapstrategy/swap_strategy_test.go +++ b/x/concentrated-liquidity/swapstrategy/swap_strategy_test.go @@ -60,35 +60,35 @@ func (suite *StrategyTestSuite) TestNextInitializedTick() { swapStrategy := swapstrategy.New(false, sdk.ZeroDec(), clStoreKey, sdk.ZeroDec(), defaultTickSpacing) n, initd := swapStrategy.NextInitializedTick(ctx, 1, 78) - suite.Require().Equal(sdk.NewInt(84), n) + suite.Require().Equal(int64(84), n) suite.Require().True(initd) }) suite.Run("returns tick to right if at initialized tick", func() { swapStrategy := swapstrategy.New(false, sdk.ZeroDec(), clStoreKey, sdk.ZeroDec(), defaultTickSpacing) n, initd := swapStrategy.NextInitializedTick(suite.Ctx, 1, -55) - suite.Require().Equal(sdk.NewInt(-4), n) + suite.Require().Equal(int64(-4), n) suite.Require().True(initd) }) suite.Run("returns the tick directly to the right", func() { swapStrategy := swapstrategy.New(false, sdk.ZeroDec(), clStoreKey, sdk.ZeroDec(), defaultTickSpacing) n, initd := swapStrategy.NextInitializedTick(suite.Ctx, 1, 77) - suite.Require().Equal(sdk.NewInt(78), n) + suite.Require().Equal(int64(78), n) suite.Require().True(initd) }) suite.Run("returns the tick directly to the right", func() { swapStrategy := swapstrategy.New(false, sdk.ZeroDec(), clStoreKey, sdk.ZeroDec(), defaultTickSpacing) n, initd := swapStrategy.NextInitializedTick(suite.Ctx, 1, -56) - suite.Require().Equal(sdk.NewInt(-55), n) + suite.Require().Equal(int64(-55), n) suite.Require().True(initd) }) suite.Run("returns the next words initialized tick if on the right boundary", func() { swapStrategy := swapstrategy.New(false, sdk.ZeroDec(), clStoreKey, sdk.ZeroDec(), defaultTickSpacing) n, initd := swapStrategy.NextInitializedTick(suite.Ctx, 1, -257) - suite.Require().Equal(sdk.NewInt(-200), n) + suite.Require().Equal(int64(-200), n) suite.Require().True(initd) }) suite.Run("returns the next initialized tick from the next word", func() { @@ -97,7 +97,7 @@ func (suite *StrategyTestSuite) TestNextInitializedTick() { suite.App.ConcentratedLiquidityKeeper.SetTickInfo(suite.Ctx, 1, 340, model.TickInfo{}) n, initd := swapStrategy.NextInitializedTick(suite.Ctx, 1, 328) - suite.Require().Equal(sdk.NewInt(340), n) + suite.Require().Equal(int64(340), n) suite.Require().True(initd) }) }) @@ -107,21 +107,21 @@ func (suite *StrategyTestSuite) TestNextInitializedTick() { swapStrategy := swapstrategy.New(true, sdk.ZeroDec(), clStoreKey, sdk.ZeroDec(), defaultTickSpacing) n, initd := swapStrategy.NextInitializedTick(suite.Ctx, 1, 79) - suite.Require().Equal(sdk.NewInt(78), n) + suite.Require().Equal(int64(78), n) suite.Require().True(initd) }) suite.Run("returns previous tick even though given is initialized", func() { swapStrategy := swapstrategy.New(true, sdk.ZeroDec(), clStoreKey, sdk.ZeroDec(), defaultTickSpacing) n, initd := swapStrategy.NextInitializedTick(suite.Ctx, 1, 78) - suite.Require().Equal(sdk.NewInt(70), n) + suite.Require().Equal(int64(70), n) suite.Require().True(initd) }) suite.Run("returns next initialized tick far away", func() { swapStrategy := swapstrategy.New(true, sdk.ZeroDec(), clStoreKey, sdk.ZeroDec(), defaultTickSpacing) n, initd := swapStrategy.NextInitializedTick(suite.Ctx, 1, 100) - suite.Require().Equal(sdk.NewInt(84), n) + suite.Require().Equal(int64(84), n) suite.Require().True(initd) }) }) diff --git a/x/concentrated-liquidity/swapstrategy/zero_for_one.go b/x/concentrated-liquidity/swapstrategy/zero_for_one.go index adec4e781e3..25d3f4f4472 100644 --- a/x/concentrated-liquidity/swapstrategy/zero_for_one.go +++ b/x/concentrated-liquidity/swapstrategy/zero_for_one.go @@ -151,8 +151,8 @@ func (s zeroForOneStrategy) ComputeSwapStepInGivenOut(sqrtPriceCurrent, sqrtPric // As a result, we use reverse iterator in NextInitializedTick to find the next // tick to the left of current. The end cursor for reverse iteration is non-inclusive // so must add one here to make sure that the current tick is included in the search. -func (s zeroForOneStrategy) InitializeTickValue(currentTick sdk.Int) sdk.Int { - return currentTick.Add(sdk.OneInt()) +func (s zeroForOneStrategy) InitializeTickValue(currentTick int64) int64 { + return currentTick + 1 } // NextInitializedTick returns the next initialized tick index based on the @@ -160,7 +160,7 @@ func (s zeroForOneStrategy) InitializeTickValue(currentTick sdk.Int) sdk.Int { // will be returned. // // zeroForOneStrategy searches for the next tick to the left of the current tickIndex. -func (s zeroForOneStrategy) NextInitializedTick(ctx sdk.Context, poolId uint64, tickIndex int64) (next sdk.Int, initialized bool) { +func (s zeroForOneStrategy) NextInitializedTick(ctx sdk.Context, poolId uint64, tickIndex int64) (next int64, initialized bool) { store := ctx.KVStore(s.storeKey) // Construct a prefix store with a prefix of , allowing @@ -181,10 +181,10 @@ func (s zeroForOneStrategy) NextInitializedTick(ctx sdk.Context, poolId uint64, panic(fmt.Errorf("invalid tick index (%s): %v", string(iter.Key()), err)) } if tick <= tickIndex { - return sdk.NewInt(tick), true + return tick, true } } - return sdk.ZeroInt(), false + return 0, false } // SetLiquidityDeltaSign sets the liquidity delta sign for the given liquidity delta. diff --git a/x/concentrated-liquidity/tick.go b/x/concentrated-liquidity/tick.go index c84ece6d0d6..c9521ddcb07 100644 --- a/x/concentrated-liquidity/tick.go +++ b/x/concentrated-liquidity/tick.go @@ -209,17 +209,14 @@ func roundTickToCanonicalPriceTick(lowerTick, upperTick int64, priceTickLower, p return 0, 0, err } - newLowerTickInt64 := newLowerTick.Int64() - newUpperTickInt64 := newUpperTick.Int64() - // If the lower or upper tick has changed, we need to re-validate the tick range. - if lowerTick != newLowerTickInt64 || upperTick != newUpperTickInt64 { - err := validateTickRangeIsValid(tickSpacing, newLowerTickInt64, newUpperTickInt64) + if lowerTick != newLowerTick || upperTick != newUpperTick { + err := validateTickRangeIsValid(tickSpacing, newLowerTick, newUpperTick) if err != nil { return 0, 0, err } } - return newLowerTickInt64, newUpperTickInt64, nil + return newLowerTick, newUpperTick, nil } // GetTickLiquidityForFullRange returns an array of liquidity depth for all ticks existing from min tick ~ max tick. @@ -251,7 +248,7 @@ func (k Keeper) GetTickLiquidityForFullRange(ctx sdk.Context, poolId uint64) ([] // use the smallest tick initialized as the starting point for calculating liquidity. currentLiquidity := tick.LiquidityNet - currentTick = nextTick.Int64() + currentTick = nextTick totalLiquidityWithinRange := currentLiquidity // iterator assignments @@ -363,7 +360,7 @@ func (k Keeper) GetTickLiquidityNetInDirection(ctx sdk.Context, poolId uint64, t swapStrategy := swapstrategy.New(zeroForOne, sdk.ZeroDec(), k.storeKey, sdk.ZeroDec(), p.GetTickSpacing()) currentTick := p.GetCurrentTick() - _, currentTickSqrtPrice, err := math.TickToSqrtPrice(currentTick) + _, currentTickSqrtPrice, err := math.TickToSqrtPrice(currentTick.Int64()) if err != nil { return []queryproto.TickLiquidityNet{}, err } @@ -373,7 +370,7 @@ func (k Keeper) GetTickLiquidityNetInDirection(ctx sdk.Context, poolId uint64, t // function to validate that start tick and bound tick are // between current tick and the min/max tick depending on the swap direction. validateTickIsInValidRange := func(validateTick sdk.Int) error { - _, validateSqrtPrice, err := math.TickToSqrtPrice(validateTick) + _, validateSqrtPrice, err := math.TickToSqrtPrice(validateTick.Int64()) if err != nil { return err } @@ -434,16 +431,16 @@ func (k Keeper) GetTickLiquidityNetInDirection(ctx sdk.Context, poolId uint64, t return liquidityDepths, nil } -func (k Keeper) getTickByTickIndex(ctx sdk.Context, poolId uint64, tickIndex sdk.Int) (model.TickInfo, error) { +func (k Keeper) getTickByTickIndex(ctx sdk.Context, poolId uint64, tickIndex int64) (model.TickInfo, error) { store := ctx.KVStore(k.storeKey) - keyTick := types.KeyTick(poolId, tickIndex.Int64()) + keyTick := types.KeyTick(poolId, tickIndex) tickStruct := model.TickInfo{} found, err := osmoutils.Get(store, keyTick, &tickStruct) if err != nil { return model.TickInfo{}, err } if !found { - return model.TickInfo{}, types.TickNotFoundError{Tick: tickIndex.Int64()} + return model.TickInfo{}, types.TickNotFoundError{Tick: tickIndex} } return tickStruct, nil } diff --git a/x/concentrated-liquidity/tick_test.go b/x/concentrated-liquidity/tick_test.go index 59f717b6083..5df29365a8c 100644 --- a/x/concentrated-liquidity/tick_test.go +++ b/x/concentrated-liquidity/tick_test.go @@ -793,7 +793,7 @@ func (s *KeeperTestSuite) TestGetTickLiquidityNetInDirection() { // testing params poolId uint64 tokenIn string - currentPoolTick sdk.Int + currentPoolTick int64 startTick sdk.Int boundTick sdk.Int @@ -998,7 +998,7 @@ func (s *KeeperTestSuite) TestGetTickLiquidityNetInDirection() { poolId: defaultPoolId, tokenIn: ETH, - currentPoolTick: sdk.NewInt(10), + currentPoolTick: 10, startTick: sdk.NewInt(10), boundTick: sdk.NewInt(-15), expectedLiquidityDepths: []queryproto.TickLiquidityNet{ @@ -1017,7 +1017,7 @@ func (s *KeeperTestSuite) TestGetTickLiquidityNetInDirection() { poolId: defaultPoolId, tokenIn: ETH, - currentPoolTick: sdk.NewInt(21), + currentPoolTick: 21, startTick: sdk.NewInt(10), boundTick: sdk.NewInt(-15), expectedLiquidityDepths: []queryproto.TickLiquidityNet{ @@ -1036,7 +1036,7 @@ func (s *KeeperTestSuite) TestGetTickLiquidityNetInDirection() { poolId: defaultPoolId, tokenIn: USDC, - currentPoolTick: sdk.NewInt(5), + currentPoolTick: 5, startTick: sdk.NewInt(5), boundTick: sdk.NewInt(15), expectedLiquidityDepths: []queryproto.TickLiquidityNet{ @@ -1055,7 +1055,7 @@ func (s *KeeperTestSuite) TestGetTickLiquidityNetInDirection() { poolId: defaultPoolId, tokenIn: USDC, - currentPoolTick: sdk.NewInt(-50), + currentPoolTick: -50, startTick: sdk.NewInt(5), boundTick: sdk.NewInt(15), expectedLiquidityDepths: []queryproto.TickLiquidityNet{ @@ -1138,7 +1138,7 @@ func (s *KeeperTestSuite) TestGetTickLiquidityNetInDirection() { poolId: defaultPoolId, tokenIn: ETH, - currentPoolTick: sdk.NewInt(10), + currentPoolTick: 10, startTick: sdk.NewInt(21), boundTick: sdk.NewInt(-15), expectedError: true, @@ -1152,7 +1152,7 @@ func (s *KeeperTestSuite) TestGetTickLiquidityNetInDirection() { poolId: defaultPoolId, tokenIn: USDC, - currentPoolTick: sdk.NewInt(5), + currentPoolTick: 5, startTick: sdk.NewInt(-50), boundTick: sdk.NewInt(15), expectedError: true, @@ -1179,7 +1179,7 @@ func (s *KeeperTestSuite) TestGetTickLiquidityNetInDirection() { // with tick spacing > 1, requiring price to tick conversion with rounding. curTick, err := math.PriceToTick(curPrice) s.Require().NoError(err) - if !test.currentPoolTick.IsNil() { + if test.currentPoolTick > 0 { _, sqrtPrice, err := math.TickToSqrtPrice(test.currentPoolTick) s.Require().NoError(err) @@ -1187,7 +1187,7 @@ func (s *KeeperTestSuite) TestGetTickLiquidityNetInDirection() { curPrice = sqrtPrice } pool.SetCurrentSqrtPrice(curPrice) - pool.SetCurrentTick(curTick) + pool.SetCurrentTick(sdk.NewInt(curTick)) err = s.App.ConcentratedLiquidityKeeper.SetPool(s.Ctx, pool) s.Require().NoError(err) @@ -1407,3 +1407,89 @@ 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) + } + }) + } +} diff --git a/x/concentrated-liquidity/types/constants.go b/x/concentrated-liquidity/types/constants.go index a7d6faabd2f..3c8549431f1 100644 --- a/x/concentrated-liquidity/types/constants.go +++ b/x/concentrated-liquidity/types/constants.go @@ -18,10 +18,10 @@ var ( MaxSqrtPrice, _ = MaxSpotPrice.ApproxRoot(2) MinSqrtPrice, _ = MinSpotPrice.ApproxRoot(2) // Supported uptimes preset to 1 ns, 1 min, 1 hr, 1D, 1W - SupportedUptimes = []time.Duration{time.Nanosecond, time.Minute, time.Hour, time.Hour * 24, time.Hour * 24 * 7} - ExponentAtPriceOne = sdk.NewInt(-6) - AuthorizedTickSpacing = []uint64{1, 10, 100, 1000} - AuthorizedSwapFees = []sdk.Dec{ + SupportedUptimes = []time.Duration{time.Nanosecond, time.Minute, time.Hour, time.Hour * 24, time.Hour * 24 * 7} + ExponentAtPriceOne int64 = -6 + AuthorizedTickSpacing = []uint64{1, 10, 100, 1000} + AuthorizedSwapFees = []sdk.Dec{ sdk.ZeroDec(), sdk.MustNewDecFromStr("0.0001"), // 0.01% sdk.MustNewDecFromStr("0.0005"), // 0.05%