Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: duplicate price for multiple ticks #5173

Merged
merged 26 commits into from
May 15, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
db88fa2
initial push
czarcas7ic May 11, 2023
17574ad
Merge branch 'main' into adam/MsgUnlockAndMigrateSharesToFullRangeCon…
czarcas7ic May 11, 2023
02b0341
update readme
czarcas7ic May 11, 2023
766283b
initial push
czarcas7ic May 12, 2023
c3b5d5d
Merge branch 'main' into adam/duplicate-price-for-multiple-ticks-patch
czarcas7ic May 12, 2023
9e688e0
implement round tick
czarcas7ic May 13, 2023
b5f5383
add test for round tick
czarcas7ic May 13, 2023
296271f
add readme
czarcas7ic May 13, 2023
a08aa03
return new lower and upper tick when create pos
czarcas7ic May 13, 2023
ca34bb8
initial push audit changes
czarcas7ic May 14, 2023
9fb6fcd
Merge branch 'adam/MsgUnlockAndMigrateSharesToFullRangeConcentratedPo…
czarcas7ic May 14, 2023
f7509a8
use enum for migration type
czarcas7ic May 15, 2023
5c82ca3
add back proto tag
czarcas7ic May 15, 2023
f8756cd
rename to validateGammLockForSuperfluidStaking
czarcas7ic May 15, 2023
a9d0c31
remove unused errors
czarcas7ic May 15, 2023
c3a7ac5
Merge branch 'main' into adam/MsgUnlockAndMigrateSharesToFullRangeCon…
czarcas7ic May 15, 2023
53c59cc
Merge branch 'adam/MsgUnlockAndMigrateSharesToFullRangeConcentratedPo…
czarcas7ic May 15, 2023
058fcc4
Merge branch 'main' into adam/MsgUnlockAndMigrateSharesToFullRangeCon…
czarcas7ic May 15, 2023
b966b05
Update x/superfluid/keeper/migrate.go
czarcas7ic May 15, 2023
17f5bde
add check for both bonded and unbonding
czarcas7ic May 15, 2023
46b9ef0
named return values createPosition
czarcas7ic May 15, 2023
814ea89
Update x/concentrated-liquidity/tick.go
czarcas7ic May 15, 2023
a74fbd6
change roundTick to roundTickToCanonicalPriceTick
czarcas7ic May 15, 2023
b5923f0
initialize int64 vars
czarcas7ic May 15, 2023
3ace477
Merge branch 'adam/MsgUnlockAndMigrateSharesToFullRangeConcentratedPo…
czarcas7ic May 15, 2023
f6d640e
Revert "Merge branch 'adam/MsgUnlockAndMigrateSharesToFullRangeConcen…
czarcas7ic May 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -938,8 +938,6 @@ github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 h1:Ylmch
github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3/go.mod h1:lV6KnqXYD/ayTe7310MHtM3I2q8Z6bBfMAi+bhwPYtI=
github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230503232557-ba905586c111 h1:1ahWbf9iF9sxDOjxrHWFaBGLE0nWFdpiX1pqObUaJO8=
github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230503232557-ba905586c111/go.mod h1:a7lhiXRpn8QJ21OhFpaEnUNErTSIafaYpp02q6uI/Dk=
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230504190933-b174397f0bc5 h1:fBzTtgZHxvZkpwlg6YtAsNaexEHYaFZDXsYfPQWu9GE=
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230504190933-b174397f0bc5/go.mod h1:hk/o9/kmTSZmZqwXcSrPuwj/gpRMCqbE/d3vj6teL2A=
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230510161551-8bf252f26bae h1:I1Cy+GpTPWbVi0lBw9+bS1w42YfQjvXNK9bW4YbHhcs=
github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230510161551-8bf252f26bae/go.mod h1:hk/o9/kmTSZmZqwXcSrPuwj/gpRMCqbE/d3vj6teL2A=
github.com/osmosis-labs/osmosis/x/epochs v0.0.0-20230328024000-175ec88e4304 h1:RIrWLzIiZN5Xd2JOfSOtGZaf6V3qEQYg6EaDTAkMnCo=
Expand Down
6 changes: 6 additions & 0 deletions proto/osmosis/concentrated-liquidity/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ message MsgCreatePositionResponse {
(gogoproto.moretags) = "yaml:\"liquidity_created\"",
(gogoproto.nullable) = false
];
// the lower and upper tick are in the response because there are
// instances in which multiple ticks represent the same price, so
// we may move their provided tick to the canonical tick that represents
// the same price.
int64 lower_tick = 6 [ (gogoproto.moretags) = "yaml:\"lower_tick\"" ];
int64 upper_tick = 7 [ (gogoproto.moretags) = "yaml:\"upper_tick\"" ];
}

// ===================== MsgAddToPosition
Expand Down
8 changes: 4 additions & 4 deletions tests/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,9 @@ func (s *IntegrationTestSuite) TestConcentratedLiquidity() {
nextInitTick := sdk.NewInt(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 := cl.TickToSqrtPrice(nextInitTick.Add(tickOffset))
s.Require().NoError(err)
sqrtPriceAtNextInitializedTick, err := cl.TickToSqrtPrice(nextInitTick)
_, sqrtPriceAtNextInitializedTick, err := cl.TickToSqrtPrice(nextInitTick)
s.Require().NoError(err)

// Calculate Δ(sqrtPrice):
Expand Down Expand Up @@ -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 := cl.TickToSqrtPrice(nextInitTick.Sub(tickOffset))
s.Require().NoError(err)
sqrtPriceAtNextInitializedTick, err = cl.TickToSqrtPrice(nextInitTick)
_, sqrtPriceAtNextInitializedTick, err = cl.TickToSqrtPrice(nextInitTick)
s.Require().NoError(err)

// Calculate numerators
Expand Down
9 changes: 9 additions & 0 deletions x/concentrated-liquidity/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,15 @@ a) Preventing trade at a desirable spot price or
b) Having the front end round the tick's actual price to the nearest
human readable/desirable spot price

One side effect of increasing precision as we get closer to the minimum tick
is that multiple ticks can represent the same price. For example, tick
-161795100 (along with the ticks surrounding it) correlate to a price
of 0.000000000000000002. To get around any issues this may cause, when a
position is created with a user defined lower and upper tick, we determine
if a larger tick exists that represents the same price. If so, we use that tick
instead of the user defined tick. In the above example, the tick would be
changed to -161000000, which is the first tick that represents the same price.

## Concentrated Liquidity Module Messages

### `MsgCreatePosition`
Expand Down
2 changes: 1 addition & 1 deletion x/concentrated-liquidity/export_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ import (
"github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/math"
)

func TickToSqrtPrice(tickIndex sdk.Int) (price sdk.Dec, err error) {
func TickToSqrtPrice(tickIndex sdk.Int) (price sdk.Dec, sqrtPrice sdk.Dec, err error) {
return math.TickToSqrtPrice(tickIndex)
}
6 changes: 5 additions & 1 deletion x/concentrated-liquidity/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ func (k Keeper) SetPositionIdToLock(ctx sdk.Context, positionId, underlyingLockI
k.setPositionIdToLock(ctx, positionId, underlyingLockId)
}

func RoundTick(lowerTick, upperTick int64, priceTickLower, priceTickUpper sdk.Dec, tickSpacing uint64) (int64, int64, error) {
return roundTick(lowerTick, upperTick, priceTickLower, priceTickUpper, tickSpacing)
}

// fees methods
func (k Keeper) CreateFeeAccumulator(ctx sdk.Context, poolId uint64) error {
return k.createFeeAccumulator(ctx, poolId)
Expand Down Expand Up @@ -176,7 +180,7 @@ func PreparePositionAccumulator(feeAccumulator accum.AccumulatorObject, position
return preparePositionAccumulator(feeAccumulator, positionKey, feeGrowthOutside)
}

func (k Keeper) CreatePosition(ctx sdk.Context, poolId uint64, owner sdk.AccAddress, tokensProvided sdk.Coins, amount0Min, amount1Min sdk.Int, lowerTick, upperTick int64) (uint64, sdk.Int, sdk.Int, sdk.Dec, time.Time, error) {
func (k Keeper) CreatePosition(ctx sdk.Context, poolId uint64, owner sdk.AccAddress, tokensProvided sdk.Coins, amount0Min, amount1Min sdk.Int, lowerTick, upperTick int64) (uint64, sdk.Int, sdk.Int, sdk.Dec, time.Time, int64, int64, error) {
return k.createPosition(ctx, poolId, owner, tokensProvided, amount0Min, amount1Min, lowerTick, upperTick)
}

Expand Down
6 changes: 3 additions & 3 deletions x/concentrated-liquidity/fees_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1503,7 +1503,7 @@ func (s *KeeperTestSuite) TestFunctional_Fees_LP() {
s.Require().Error(err)

// Create position in the default range 1.
positionIdOne, _, _, liquidity, _, err := concentratedLiquidityKeeper.CreatePosition(ctx, pool.GetId(), owner, DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
positionIdOne, _, _, liquidity, _, _, _, err := concentratedLiquidityKeeper.CreatePosition(ctx, pool.GetId(), owner, DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
s.Require().NoError(err)

// Swap once.
Expand All @@ -1527,7 +1527,7 @@ func (s *KeeperTestSuite) TestFunctional_Fees_LP() {
s.validatePositionFeeGrowth(pool.GetId(), positionIdOne, cl.EmptyCoins)

// Create position in the default range 2.
positionIdTwo, _, _, fullLiquidity, _, err := concentratedLiquidityKeeper.CreatePosition(ctx, pool.GetId(), owner, DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
positionIdTwo, _, _, fullLiquidity, _, _, _, err := concentratedLiquidityKeeper.CreatePosition(ctx, pool.GetId(), owner, DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
s.Require().NoError(err)

// Swap once in the other direction.
Expand Down Expand Up @@ -1555,7 +1555,7 @@ func (s *KeeperTestSuite) TestFunctional_Fees_LP() {
s.Require().Equal(expectesFeesCollected.String(), feesCollected.AmountOf(ETH).String())

// Create position in the default range 3.
positionIdThree, _, _, fullLiquidity, _, err := concentratedLiquidityKeeper.CreatePosition(ctx, pool.GetId(), owner, DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
positionIdThree, _, _, fullLiquidity, _, _, _, err := concentratedLiquidityKeeper.CreatePosition(ctx, pool.GetId(), owner, DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
s.Require().NoError(err)

collectedThree, err := s.App.ConcentratedLiquidityKeeper.CollectFees(ctx, owner, positionIdThree)
Expand Down
6 changes: 3 additions & 3 deletions x/concentrated-liquidity/incentives_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -940,7 +940,7 @@ func (s *KeeperTestSuite) TestUpdateUptimeAccumulatorsToNow() {
if !tc.isInvalidBalancerPool {
depositedCoins := sdk.NewCoins(sdk.NewCoin(clPool.GetToken0(), testQualifyingDepositsOne), sdk.NewCoin(clPool.GetToken1(), testQualifyingDepositsOne))
s.FundAcc(testAddressOne, depositedCoins)
_, _, _, qualifyingLiquidity, _, err = clKeeper.CreatePosition(s.Ctx, clPool.GetId(), testAddressOne, depositedCoins, sdk.ZeroInt(), sdk.ZeroInt(), clPool.GetCurrentTick().Int64()-100, clPool.GetCurrentTick().Int64()+100)
_, _, _, qualifyingLiquidity, _, _, _, err = clKeeper.CreatePosition(s.Ctx, clPool.GetId(), testAddressOne, depositedCoins, sdk.ZeroInt(), sdk.ZeroInt(), clPool.GetCurrentTick().Int64()-100, clPool.GetCurrentTick().Int64()+100)
s.Require().NoError(err)

// If a canonical balancer pool exists, we add its respective shares to the qualifying amount as well.
Expand Down Expand Up @@ -3589,7 +3589,7 @@ func (s *KeeperTestSuite) TestFunctional_ClaimIncentices_LiquidityChange_Varying
s.Require().NoError(err)

// Set up position
positionIdOne, _, _, _, _, err := s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, defaultPoolId, defaultAddress, DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
positionIdOne, _, _, _, _, _, _, err := s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, defaultPoolId, defaultAddress, DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
s.Require().NoError(err)

// Increase block time by the fully charged duration (first time)
Expand All @@ -3604,7 +3604,7 @@ func (s *KeeperTestSuite) TestFunctional_ClaimIncentices_LiquidityChange_Varying
s.Ctx = s.Ctx.WithBlockTime(s.Ctx.BlockTime().Add(testFullChargeDuration))

// Create another position
positionIdTwo, _, _, _, _, err := s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, defaultPoolId, defaultAddress, DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
positionIdTwo, _, _, _, _, _, _, err := s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, defaultPoolId, defaultAddress, DefaultCoins, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick)
s.Require().NoError(err)

// Increase block time by the fully charged duration (third time)
Expand Down
6 changes: 3 additions & 3 deletions x/concentrated-liquidity/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (s *KeeperTestSuite) SetupDefaultPosition(poolId uint64) {

func (s *KeeperTestSuite) SetupPosition(poolId uint64, owner sdk.AccAddress, providedCoins sdk.Coins, lowerTick, upperTick int64, joinTime time.Time) (sdk.Dec, uint64) {
s.FundAcc(owner, providedCoins)
positionId, _, _, _, _, err := s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, poolId, owner, providedCoins, sdk.ZeroInt(), sdk.ZeroInt(), lowerTick, upperTick)
positionId, _, _, _, _, _, _, err := s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, poolId, owner, providedCoins, sdk.ZeroInt(), sdk.ZeroInt(), lowerTick, upperTick)
s.Require().NoError(err)
liquidity, err := s.App.ConcentratedLiquidityKeeper.GetPositionLiquidity(s.Ctx, positionId)
s.Require().NoError(err)
Expand Down Expand Up @@ -136,13 +136,13 @@ func (s *KeeperTestSuite) validateTickUpdates(ctx sdk.Context, poolId uint64, ow
s.Require().NoError(err)
s.Require().Equal(expectedRemainingLiquidity.String(), lowerTickInfo.LiquidityGross.String())
s.Require().Equal(expectedRemainingLiquidity.String(), lowerTickInfo.LiquidityNet.String())
s.Require().Equal(lowerTickInfo.FeeGrowthOppositeDirectionOfLastTraversal.String(), expectedLowerFeeGrowthOppositeDirectionOfLastTraversal.String())
s.Require().Equal(expectedLowerFeeGrowthOppositeDirectionOfLastTraversal.String(), lowerTickInfo.FeeGrowthOppositeDirectionOfLastTraversal.String())

upperTickInfo, err := s.App.ConcentratedLiquidityKeeper.GetTickInfo(s.Ctx, poolId, upperTick)
s.Require().NoError(err)
s.Require().Equal(expectedRemainingLiquidity.String(), upperTickInfo.LiquidityGross.String())
s.Require().Equal(expectedRemainingLiquidity.Neg().String(), upperTickInfo.LiquidityNet.String())
s.Require().Equal(upperTickInfo.FeeGrowthOppositeDirectionOfLastTraversal.String(), expectedUpperFeeGrowthOppositeDirectionOfLastTraversal.String())
s.Require().Equal(expectedUpperFeeGrowthOppositeDirectionOfLastTraversal.String(), upperTickInfo.FeeGrowthOppositeDirectionOfLastTraversal.String())
}

func (s *KeeperTestSuite) initializeTick(ctx sdk.Context, currentTick int64, tickIndex int64, initialLiquidity sdk.Dec, feeGrowthOppositeDirectionOfTraversal sdk.DecCoins, uptimeTrackers []model.UptimeTracker, isLower bool) {
Expand Down
40 changes: 23 additions & 17 deletions x/concentrated-liquidity/lp.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,38 +31,44 @@ const noUnderlyingLockId = uint64(0)
// - the liquidity delta is zero
// - the amount0 or amount1 returned from the position update is less than the given minimums
// - the pool or user does not have enough tokens to satisfy the requested amount
func (k Keeper) createPosition(ctx sdk.Context, poolId uint64, owner sdk.AccAddress, tokensProvided sdk.Coins, amount0Min, amount1Min sdk.Int, lowerTick, upperTick int64) (uint64, sdk.Int, sdk.Int, sdk.Dec, time.Time, error) {
func (k Keeper) createPosition(ctx sdk.Context, poolId uint64, owner sdk.AccAddress, tokensProvided sdk.Coins, amount0Min, amount1Min sdk.Int, lowerTick, upperTick int64) (uint64, sdk.Int, sdk.Int, sdk.Dec, time.Time, int64, int64, error) {
czarcas7ic marked this conversation as resolved.
Show resolved Hide resolved
// Use the current blockTime as the position's join time.
joinTime := ctx.BlockTime()

// Retrieve the pool associated with the given pool ID.
pool, err := k.getPoolById(ctx, poolId)
if err != nil {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, err
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, err
}

// Check if the provided tick range is valid according to the pool's tick spacing and module parameters.
if err := validateTickRangeIsValid(pool.GetTickSpacing(), lowerTick, upperTick); err != nil {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, err
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, err
}
amount0Desired := tokensProvided.AmountOf(pool.GetToken0())
amount1Desired := tokensProvided.AmountOf(pool.GetToken1())
if amount0Desired.IsZero() && amount1Desired.IsZero() {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, errors.New("cannot create a position with zero amounts of both pool tokens")
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, errors.New("cannot create a position with zero amounts of both pool tokens")
}

// sanity check that both given minimum accounts are not negative amounts.
if amount0Min.IsNegative() {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, types.NotPositiveRequireAmountError{Amount: amount0Min.String()}
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, types.NotPositiveRequireAmountError{Amount: amount0Min.String()}
}
if amount1Min.IsNegative() {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, types.NotPositiveRequireAmountError{Amount: amount1Min.String()}
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, types.NotPositiveRequireAmountError{Amount: amount1Min.String()}
}

// Transform the provided ticks into their corresponding sqrtPrices.
sqrtPriceLowerTick, sqrtPriceUpperTick, err := math.TicksToSqrtPrice(lowerTick, upperTick)
priceLowerTick, priceUpperTick, sqrtPriceLowerTick, sqrtPriceUpperTick, err := math.TicksToSqrtPrice(lowerTick, upperTick)
if err != nil {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, err
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, err
}

// If multiple ticks can represent the same spot price, ensure we are using the largest of those ticks.
lowerTick, upperTick, err = roundTick(lowerTick, upperTick, priceLowerTick, priceUpperTick, pool.GetTickSpacing())
Copy link
Member

Choose a reason for hiding this comment

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

Do we also need to handle this for the initial tick?

initialTick, err := math.PriceToTickRoundDown(initialSpotPrice, pool.GetTickSpacing())
if err != nil {
return err
}

Copy link
Member Author

Choose a reason for hiding this comment

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

No, only because the PriceToTickRoundDown function always returns the canonical tick. The only thing that needs to be changed is user provided ticks

if err != nil {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, err
}

positionId := k.getNextPositionIdAndIncrement(ctx)
Expand All @@ -71,39 +77,39 @@ func (k Keeper) createPosition(ctx sdk.Context, poolId uint64, owner sdk.AccAddr
// in order to assign an initial spot price.
hasPositions, err := k.HasAnyPositionForPool(ctx, poolId)
if err != nil {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, err
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, err
}
if !hasPositions {
err := k.initializeInitialPositionForPool(ctx, pool, amount0Desired, amount1Desired)
if err != nil {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, err
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, err
}
}

// Calculate the amount of liquidity that will be added to the pool when this position is created.
liquidityDelta := math.GetLiquidityFromAmounts(pool.GetCurrentSqrtPrice(), sqrtPriceLowerTick, sqrtPriceUpperTick, amount0Desired, amount1Desired)
if liquidityDelta.IsZero() {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, errors.New("liquidityDelta calculated equals zero")
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, errors.New("liquidityDelta calculated equals zero")
}

// Initialize / update the position in the pool based on the provided tick range and liquidity delta.
actualAmount0, actualAmount1, err := k.UpdatePosition(ctx, poolId, owner, lowerTick, upperTick, liquidityDelta, joinTime, positionId)
if err != nil {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, err
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, err
}

// Check if the actual amounts of tokens 0 and 1 are greater than or equal to the given minimum amounts.
if actualAmount0.LT(amount0Min) {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, types.InsufficientLiquidityCreatedError{Actual: actualAmount0, Minimum: amount0Min, IsTokenZero: true}
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, types.InsufficientLiquidityCreatedError{Actual: actualAmount0, Minimum: amount0Min, IsTokenZero: true}
}
if actualAmount1.LT(amount1Min) {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, types.InsufficientLiquidityCreatedError{Actual: actualAmount1, Minimum: amount1Min}
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, types.InsufficientLiquidityCreatedError{Actual: actualAmount1, Minimum: amount1Min}
}

// Transfer the actual amounts of tokens 0 and 1 from the position owner to the pool.
err = k.sendCoinsBetweenPoolAndUser(ctx, pool.GetToken0(), pool.GetToken1(), actualAmount0, actualAmount1, owner, pool.GetAddress())
if err != nil {
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, err
return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, time.Time{}, 0, 0, err
}

emitLiquidityChangeEvent(ctx, types.TypeEvtCreatePosition, positionId, owner, poolId, lowerTick, upperTick, joinTime, liquidityDelta, actualAmount0, actualAmount1)
Expand All @@ -116,7 +122,7 @@ func (k Keeper) createPosition(ctx sdk.Context, poolId uint64, owner sdk.AccAddr
k.listeners.AfterInitialPoolPositionCreated(ctx, owner, poolId)
}

return positionId, actualAmount0, actualAmount1, liquidityDelta, joinTime, nil
return positionId, actualAmount0, actualAmount1, liquidityDelta, joinTime, lowerTick, upperTick, nil
}

// WithdrawPosition attempts to withdraw liquidityAmount from a position with the given pool id in the given tick range.
Expand Down Expand Up @@ -298,7 +304,7 @@ func (k Keeper) addToPosition(ctx sdk.Context, owner sdk.AccAddress, positionId
return 0, sdk.Int{}, sdk.Int{}, err
}
tokensProvided := sdk.NewCoins(sdk.NewCoin(pool.GetToken0(), amount0Desired), sdk.NewCoin(pool.GetToken1(), amount1Desired))
newPositionId, actualAmount0, actualAmount1, _, _, err := k.createPosition(ctx, position.PoolId, owner, tokensProvided, amount0Withdrawn, amount1Withdrawn, position.LowerTick, position.UpperTick)
newPositionId, actualAmount0, actualAmount1, _, _, _, _, err := k.createPosition(ctx, position.PoolId, owner, tokensProvided, amount0Withdrawn, amount1Withdrawn, position.LowerTick, position.UpperTick)
if err != nil {
return 0, sdk.Int{}, sdk.Int{}, err
}
Expand Down
Loading