diff --git a/CHANGELOG.md b/CHANGELOG.md index c10b637e612..cc208b8020e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### API breaks * [#5983](https://github.com/osmosis-labs/osmosis/pull/5983) refactor(CL): 6 return values in CL CreatePosition with a struct +* [#6004](https://github.com/osmosis-labs/osmosis/pull/6004) reduce number of returns for creating full range position ### Features diff --git a/app/apptesting/concentrated_liquidity.go b/app/apptesting/concentrated_liquidity.go index 4ef899b4297..b67aa820bc6 100644 --- a/app/apptesting/concentrated_liquidity.go +++ b/app/apptesting/concentrated_liquidity.go @@ -72,11 +72,11 @@ func (s *KeeperTestHelper) PrepareConcentratedPoolWithCoinsAndLockedFullRangePos clPool := s.PrepareCustomConcentratedPool(s.TestAccs[0], denom1, denom2, DefaultTickSpacing, sdk.ZeroDec()) fundCoins := sdk.NewCoins(sdk.NewCoin(denom1, DefaultCoinAmount), sdk.NewCoin(denom2, DefaultCoinAmount)) s.FundAcc(s.TestAccs[0], fundCoins) - positionId, _, _, _, concentratedLockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPool.GetId(), s.TestAccs[0], fundCoins, time.Hour*24*14) + positionData, concentratedLockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPool.GetId(), s.TestAccs[0], fundCoins, time.Hour*24*14) s.Require().NoError(err) clPool, err = s.App.ConcentratedLiquidityKeeper.GetConcentratedPoolById(s.Ctx, clPool.GetId()) s.Require().NoError(err) - return clPool, concentratedLockId, positionId + return clPool, concentratedLockId, positionData.ID } // PrepareCustomConcentratedPool sets up a concentrated liquidity pool with the custom parameters. @@ -113,9 +113,9 @@ func (s *KeeperTestHelper) PrepareMultipleConcentratedPools(poolsToCreate uint16 // CreateFullRangePosition creates a full range position and returns position id and the liquidity created. func (s *KeeperTestHelper) CreateFullRangePosition(pool types.ConcentratedPoolExtension, coins sdk.Coins) (uint64, sdk.Dec) { s.FundAcc(s.TestAccs[0], coins) - positionId, _, _, liquidity, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, pool.GetId(), s.TestAccs[0], coins) + positionData, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, pool.GetId(), s.TestAccs[0], coins) s.Require().NoError(err) - return positionId, liquidity + return positionData.ID, positionData.Liquidity } // WithdrawFullRangePosition withdraws given liquidity from a position specified by id. diff --git a/app/upgrades/v16/upgrades.go b/app/upgrades/v16/upgrades.go index 9234578817d..9918a2c2b35 100644 --- a/app/upgrades/v16/upgrades.go +++ b/app/upgrades/v16/upgrades.go @@ -149,7 +149,7 @@ func CreateUpgradeHandler( // Create a full range position via the community pool with the funds that were swapped. fullRangeOsmoDaiCoins := sdk.NewCoins(respectiveOsmo, oneDai) - _, actualOsmoAmtUsed, actualDaiAmtUsed, _, err := keepers.ConcentratedLiquidityKeeper.CreateFullRangePosition(ctx, clPoolId, communityPoolAddress, fullRangeOsmoDaiCoins) + positionData, err := keepers.ConcentratedLiquidityKeeper.CreateFullRangePosition(ctx, clPoolId, communityPoolAddress, fullRangeOsmoDaiCoins) if err != nil { return nil, err } @@ -158,7 +158,7 @@ func CreateUpgradeHandler( // Remove coins we used from the community pool to make the CL position feePool := keepers.DistrKeeper.GetFeePool(ctx) - fulllRangeOsmoDaiCoinsUsed := sdk.NewCoins(sdk.NewCoin(DesiredDenom0, actualOsmoAmtUsed), sdk.NewCoin(DAIIBCDenom, actualDaiAmtUsed)) + fulllRangeOsmoDaiCoinsUsed := sdk.NewCoins(sdk.NewCoin(DesiredDenom0, positionData.Amount0), sdk.NewCoin(DAIIBCDenom, positionData.Amount1)) newPool, negative := feePool.CommunityPool.SafeSub(sdk.NewDecCoinsFromCoins(fulllRangeOsmoDaiCoinsUsed...)) if negative { return nil, fmt.Errorf("community pool cannot be negative: %s", newPool) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 4a72dde4191..cf3da1d437d 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -85,13 +85,13 @@ func CreateUpgradeHandler( // Create a full range position via the community pool with the funds we calculated above. fullRangeCoins := sdk.NewCoins(respectiveBaseAsset, oneOsmo) - _, actualBaseAmtUsed, actualQuoteAmtUsed, _, err := keepers.ConcentratedLiquidityKeeper.CreateFullRangePosition(ctx, clPoolId, communityPoolAddress, fullRangeCoins) + positionData, err := keepers.ConcentratedLiquidityKeeper.CreateFullRangePosition(ctx, clPoolId, communityPoolAddress, fullRangeCoins) if err != nil { return nil, err } // Track the coins used to create the full range position (we manually update the fee pool later all at once). - fullRangeCoinsUsed = fullRangeCoinsUsed.Add(sdk.NewCoins(sdk.NewCoin(QuoteAsset, actualQuoteAmtUsed), sdk.NewCoin(assetPair.BaseAsset, actualBaseAmtUsed))...) + fullRangeCoinsUsed = fullRangeCoinsUsed.Add(sdk.NewCoins(sdk.NewCoin(QuoteAsset, positionData.Amount1), sdk.NewCoin(assetPair.BaseAsset, positionData.Amount0))...) // If pair was previously superfluid enabled, add the cl pool's full range denom as an authorized superfluid asset. if assetPair.Superfluid { diff --git a/x/concentrated-liquidity/lp_test.go b/x/concentrated-liquidity/lp_test.go index faaf21df50b..e546565028c 100644 --- a/x/concentrated-liquidity/lp_test.go +++ b/x/concentrated-liquidity/lp_test.go @@ -12,6 +12,7 @@ import ( cl "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity" "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/model" clmodel "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/model" + cltypes "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" types "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" ) @@ -391,25 +392,25 @@ const ( func (s *KeeperTestSuite) createPositionWithLockState(ls lockState, poolId uint64, owner sdk.AccAddress, providedCoins sdk.Coins, dur time.Duration) (uint64, sdk.Dec) { var ( - positionData cl.CreatePositionData - liquidityCreated sdk.Dec - positionId uint64 - err error + positionData cl.CreatePositionData + fullRangePositionData cltypes.CreateFullRangePositionData + err error ) if ls == locked { - positionId, _, _, liquidityCreated, _, err = s.clk.CreateFullRangePositionLocked(s.Ctx, poolId, owner, providedCoins, dur) + fullRangePositionData, _, err = s.clk.CreateFullRangePositionLocked(s.Ctx, poolId, owner, providedCoins, dur) } else if ls == unlocking { - positionId, _, _, liquidityCreated, _, err = s.clk.CreateFullRangePositionUnlocking(s.Ctx, poolId, owner, providedCoins, dur+time.Hour) + fullRangePositionData, _, err = s.clk.CreateFullRangePositionUnlocking(s.Ctx, poolId, owner, providedCoins, dur+time.Hour) } else if ls == unlocked { - positionId, _, _, liquidityCreated, _, err = s.clk.CreateFullRangePositionUnlocking(s.Ctx, poolId, owner, providedCoins, dur-time.Hour) + fullRangePositionData, _, err = s.clk.CreateFullRangePositionUnlocking(s.Ctx, poolId, owner, providedCoins, dur-time.Hour) } else { positionData, err = s.clk.CreatePosition(s.Ctx, poolId, owner, providedCoins, sdk.ZeroInt(), sdk.ZeroInt(), DefaultLowerTick, DefaultUpperTick) - positionId = positionData.ID - liquidityCreated = positionData.Liquidity + s.Require().NoError(err) + return positionData.ID, positionData.Liquidity } + // full range case s.Require().NoError(err) - return positionId, liquidityCreated + return fullRangePositionData.ID, fullRangePositionData.Liquidity } func (s *KeeperTestSuite) TestWithdrawPosition() { @@ -1999,8 +2000,8 @@ func (s *KeeperTestSuite) TestIsLockMature() { s.Run(name, func() { tc := tc var ( - positionId uint64 concentratedLockId uint64 + positionData types.CreateFullRangePositionData err error ) s.SetupTest() @@ -2012,17 +2013,15 @@ func (s *KeeperTestSuite) TestIsLockMature() { s.FundAcc(s.TestAccs[0], coinsToFund) if tc.unlockingPosition { - positionId, _, _, _, concentratedLockId, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionUnlocking(s.Ctx, pool.GetId(), s.TestAccs[0], coinsToFund, tc.remainingLockDuration) - s.Require().NoError(err) + positionData, concentratedLockId, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionUnlocking(s.Ctx, pool.GetId(), s.TestAccs[0], coinsToFund, tc.remainingLockDuration) } else if tc.lockedPosition { - positionId, _, _, _, concentratedLockId, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, pool.GetId(), s.TestAccs[0], coinsToFund, tc.remainingLockDuration) - s.Require().NoError(err) + positionData, concentratedLockId, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, pool.GetId(), s.TestAccs[0], coinsToFund, tc.remainingLockDuration) } else { - positionId, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, pool.GetId(), s.TestAccs[0], coinsToFund) - s.Require().NoError(err) + positionData, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, pool.GetId(), s.TestAccs[0], coinsToFund) } + s.Require().NoError(err) - _, err = s.App.ConcentratedLiquidityKeeper.GetPosition(s.Ctx, positionId) + _, err = s.App.ConcentratedLiquidityKeeper.GetPosition(s.Ctx, positionData.ID) s.Require().NoError(err) // Increment block time by a second to ensure test cases with zero lock duration are in the past @@ -2031,11 +2030,7 @@ func (s *KeeperTestSuite) TestIsLockMature() { // System under test lockIsMature, _ := s.App.ConcentratedLiquidityKeeper.IsLockMature(s.Ctx, concentratedLockId) - if tc.expectedLockIsMature { - s.Require().True(lockIsMature) - } else { - s.Require().False(lockIsMature) - } + s.Require().Equal(tc.expectedLockIsMature, lockIsMature) }) } } diff --git a/x/concentrated-liquidity/pool_test.go b/x/concentrated-liquidity/pool_test.go index 76f820bd93f..365a88655b5 100644 --- a/x/concentrated-liquidity/pool_test.go +++ b/x/concentrated-liquidity/pool_test.go @@ -683,7 +683,7 @@ func (s *KeeperTestSuite) TestGetUserUnbondingPositions() { // Create 3 locked positions for i := 0; i < 3; i++ { - _, _, _, _, _, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPool.GetId(), defaultAddress, defaultFunds, time.Hour) + _, _, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPool.GetId(), defaultAddress, defaultFunds, time.Hour) s.Require().NoError(err) } diff --git a/x/concentrated-liquidity/position.go b/x/concentrated-liquidity/position.go index f0307051c65..cd4b494e0da 100644 --- a/x/concentrated-liquidity/position.go +++ b/x/concentrated-liquidity/position.go @@ -393,78 +393,78 @@ func (k Keeper) deletePosition(ctx sdk.Context, // CreateFullRangePosition creates a full range (min to max tick) concentrated liquidity position for the given pool ID, owner, and coins. // The function returns the amounts of token 0 and token 1, and the liquidity created from the position. -func (k Keeper) CreateFullRangePosition(ctx sdk.Context, poolId uint64, owner sdk.AccAddress, coins sdk.Coins) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, err error) { +func (k Keeper) CreateFullRangePosition(ctx sdk.Context, poolId uint64, owner sdk.AccAddress, coins sdk.Coins) (types.CreateFullRangePositionData, error) { // Check that exactly two coins are provided. if len(coins) != 2 { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, types.NumCoinsError{NumCoins: len(coins)} + return types.CreateFullRangePositionData{}, types.NumCoinsError{NumCoins: len(coins)} } concentratedPool, err := k.GetConcentratedPoolById(ctx, poolId) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, err + return types.CreateFullRangePositionData{}, err } // Defense in depth, ensure coins provided match the pool's token denominations. if coins.AmountOf(concentratedPool.GetToken0()).LTE(sdk.ZeroInt()) { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, types.Amount0IsNegativeError{Amount0: coins.AmountOf(concentratedPool.GetToken0())} + return types.CreateFullRangePositionData{}, types.Amount0IsNegativeError{Amount0: coins.AmountOf(concentratedPool.GetToken0())} } if coins.AmountOf(concentratedPool.GetToken1()).LTE(sdk.ZeroInt()) { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, types.Amount1IsNegativeError{Amount1: coins.AmountOf(concentratedPool.GetToken1())} + return types.CreateFullRangePositionData{}, types.Amount1IsNegativeError{Amount1: coins.AmountOf(concentratedPool.GetToken1())} } // Create a full range (min to max tick) concentrated liquidity position. positionData, err := k.CreatePosition(ctx, concentratedPool.GetId(), owner, coins, sdk.ZeroInt(), sdk.ZeroInt(), types.MinInitializedTick, types.MaxTick) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, err + return types.CreateFullRangePositionData{}, err } - return positionData.ID, positionData.Amount0, positionData.Amount1, positionData.Liquidity, nil + return types.CreateFullRangePositionData{ID: positionData.ID, Amount0: positionData.Amount0, Amount1: positionData.Amount1, Liquidity: positionData.Liquidity}, nil } // CreateFullRangePositionLocked creates a full range (min to max tick) concentrated liquidity position for the given pool ID, owner, and coins. // CL shares are minted which represent the underlying liquidity and are locked for the given duration. // State entries are also created to map the position ID to the underlying lock ID. -func (k Keeper) CreateFullRangePositionLocked(ctx sdk.Context, clPoolId uint64, owner sdk.AccAddress, coins sdk.Coins, remainingLockDuration time.Duration) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, concentratedLockID uint64, err error) { +func (k Keeper) CreateFullRangePositionLocked(ctx sdk.Context, clPoolId uint64, owner sdk.AccAddress, coins sdk.Coins, remainingLockDuration time.Duration) (positionData types.CreateFullRangePositionData, concentratedLockID uint64, err error) { // Create a full range (min to max tick) concentrated liquidity position. - positionId, amount0, amount1, liquidity, err = k.CreateFullRangePosition(ctx, clPoolId, owner, coins) + positionData, err = k.CreateFullRangePosition(ctx, clPoolId, owner, coins) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return types.CreateFullRangePositionData{}, 0, err } // Mint CL shares (similar to GAMM shares) for the position and lock them for the remaining lock duration. // Also sets the position ID to underlying lock ID mapping. - concentratedLockId, _, err := k.mintSharesAndLock(ctx, clPoolId, positionId, owner, remainingLockDuration) + concentratedLockId, _, err := k.mintSharesAndLock(ctx, clPoolId, positionData.ID, owner, remainingLockDuration) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return types.CreateFullRangePositionData{}, 0, err } - return positionId, amount0, amount1, liquidity, concentratedLockId, nil + return positionData, concentratedLockId, nil } // CreateFullRangePositionUnlocking creates a full range (min to max tick) concentrated liquidity position for the given pool ID, owner, and coins. // This function is strictly used when migrating a balancer position to CL, where the balancer position is currently unlocking. // We lock the cl position for whatever the remaining time is from the balancer position and immediately begin unlocking from where it left off. -func (k Keeper) CreateFullRangePositionUnlocking(ctx sdk.Context, clPoolId uint64, owner sdk.AccAddress, coins sdk.Coins, remainingLockDuration time.Duration) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, concentratedLockID uint64, err error) { +func (k Keeper) CreateFullRangePositionUnlocking(ctx sdk.Context, clPoolId uint64, owner sdk.AccAddress, coins sdk.Coins, remainingLockDuration time.Duration) (positionData types.CreateFullRangePositionData, concentratedLockID uint64, err error) { // Create a full range (min to max tick) concentrated liquidity position. - positionId, amount0, amount1, liquidity, err = k.CreateFullRangePosition(ctx, clPoolId, owner, coins) + positionData, err = k.CreateFullRangePosition(ctx, clPoolId, owner, coins) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return types.CreateFullRangePositionData{}, 0, err } // Mint cl shares for the position and lock them for the remaining lock duration. // Also sets the position ID to underlying lock ID mapping. - concentratedLockId, underlyingLiquidityTokenized, err := k.mintSharesAndLock(ctx, clPoolId, positionId, owner, remainingLockDuration) + concentratedLockId, underlyingLiquidityTokenized, err := k.mintSharesAndLock(ctx, clPoolId, positionData.ID, owner, remainingLockDuration) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return types.CreateFullRangePositionData{}, 0, err } // Begin unlocking the newly created concentrated lock. concentratedLockID, err = k.lockupKeeper.BeginForceUnlock(ctx, concentratedLockId, underlyingLiquidityTokenized) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return types.CreateFullRangePositionData{}, 0, err } - return positionId, amount0, amount1, liquidity, concentratedLockID, nil + return positionData, concentratedLockID, nil } // mintSharesAndLock mints the shares for the full range concentrated liquidity position and locks them for the given duration. It also updates the position ID to underlying lock ID mapping. diff --git a/x/concentrated-liquidity/position_test.go b/x/concentrated-liquidity/position_test.go index 76b6185d89b..1d8f115afe1 100644 --- a/x/concentrated-liquidity/position_test.go +++ b/x/concentrated-liquidity/position_test.go @@ -15,6 +15,7 @@ import ( "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/math" "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/model" "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" + cltypes "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" ) const ( @@ -1031,13 +1032,15 @@ func (s *KeeperTestSuite) TestValidateAndFungifyChargedPositions() { lockDuration := testFullChargeDuration + testFullChargeDuration + test.unlockBeforeBlockTimeMs for _, pos := range test.setupFullyChargedPositions { var ( - liquidityCreated sdk.Dec - err error - positionData cl.CreatePositionData + liquidityCreated sdk.Dec + err error + positionData cl.CreatePositionData + fullRangePositionData cltypes.CreateFullRangePositionData ) if pos.isLocked { - _, _, _, liquidityCreated, _, err = s.clk.CreateFullRangePositionUnlocking(s.Ctx, pos.poolId, pos.acc, pos.coins, lockDuration) + fullRangePositionData, _, err = s.clk.CreateFullRangePositionUnlocking(s.Ctx, pos.poolId, pos.acc, pos.coins, lockDuration) s.Require().NoError(err) + liquidityCreated = fullRangePositionData.Liquidity } else { positionData, err = s.clk.CreatePosition(s.Ctx, pos.poolId, pos.acc, pos.coins, sdk.ZeroInt(), sdk.ZeroInt(), pos.lowerTick, pos.upperTick) s.Require().NoError(err) @@ -1589,8 +1592,7 @@ func (s *KeeperTestSuite) TestFunctionalFungifyChargedPositions() { func (s *KeeperTestSuite) TestCreateFullRangePosition() { var ( - positionId uint64 - liquidity sdk.Dec + positionData cltypes.CreateFullRangePositionData concentratedLockId uint64 err error ) @@ -1671,11 +1673,11 @@ func (s *KeeperTestSuite) TestCreateFullRangePosition() { // System under test if test.isLocked { - positionId, _, _, liquidity, concentratedLockId, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPool.GetId(), defaultAddress, test.coinsForPosition, test.remainingLockDuration) + positionData, concentratedLockId, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPool.GetId(), defaultAddress, test.coinsForPosition, test.remainingLockDuration) } else if test.isUnlocking { - positionId, _, _, liquidity, concentratedLockId, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionUnlocking(s.Ctx, clPool.GetId(), defaultAddress, test.coinsForPosition, test.remainingLockDuration) + positionData, concentratedLockId, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionUnlocking(s.Ctx, clPool.GetId(), defaultAddress, test.coinsForPosition, test.remainingLockDuration) } else { - positionId, _, _, liquidity, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, clPool.GetId(), defaultAddress, test.coinsForPosition) + positionData, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, clPool.GetId(), defaultAddress, test.coinsForPosition) } if test.expectedErr != nil { @@ -1687,14 +1689,14 @@ func (s *KeeperTestSuite) TestCreateFullRangePosition() { s.Require().NoError(err) // Check position - _, err = s.App.ConcentratedLiquidityKeeper.GetPosition(s.Ctx, positionId) + _, err = s.App.ConcentratedLiquidityKeeper.GetPosition(s.Ctx, positionData.ID) s.Require().NoError(err) // Check lock if test.isLocked || test.isUnlocking { concentratedLock, err := s.App.LockupKeeper.GetLockByID(s.Ctx, concentratedLockId) s.Require().NoError(err) - s.Require().Equal(liquidity.TruncateInt().String(), concentratedLock.Coins[0].Amount.String()) + s.Require().Equal(positionData.Liquidity.TruncateInt().String(), concentratedLock.Coins[0].Amount.String()) isUnlocking := concentratedLock.IsUnlocking() s.Require().Equal(!test.isLocked, isUnlocking) } @@ -1767,8 +1769,10 @@ func (s *KeeperTestSuite) TestMintSharesAndLock() { liquidity := sdk.ZeroDec() if test.createFullRangePosition { var err error - positionId, _, _, liquidity, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, clPool.GetId(), test.owner, DefaultCoins) + positionData, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, clPool.GetId(), test.owner, DefaultCoins) s.Require().NoError(err) + positionId = positionData.ID + liquidity = positionData.Liquidity } else { var err error positionData, err := s.App.ConcentratedLiquidityKeeper.CreatePosition(s.Ctx, clPool.GetId(), test.owner, defaultPositionCoins, sdk.ZeroInt(), sdk.ZeroInt(), test.lowerTick, test.upperTick) @@ -1837,10 +1841,10 @@ func (s *KeeperTestSuite) TestPositionHasActiveUnderlyingLock() { name: "position with lock locked", createPosition: func(s *KeeperTestSuite) (uint64, uint64) { s.FundAcc(owner, defaultPositionCoins) - positionID, _, _, _, concentratedLockID, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked( + positionData, concentratedLockID, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked( s.Ctx, clPool.GetId(), owner, defaultPositionCoins, defaultLockDuration) s.Require().NoError(err) - return positionID, concentratedLockID + return positionData.ID, concentratedLockID }, expectedHasActiveLock: true, // lock starts as active expectedHasActiveLockAfterTimeUpdate: true, // since lock is locked, it remains active after time update @@ -1852,10 +1856,10 @@ func (s *KeeperTestSuite) TestPositionHasActiveUnderlyingLock() { name: "position with lock unlocking", createPosition: func(s *KeeperTestSuite) (uint64, uint64) { s.FundAcc(owner, defaultPositionCoins) - positionID, _, _, _, concentratedLockID, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionUnlocking( + positionData, concentratedLockID, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionUnlocking( s.Ctx, clPool.GetId(), owner, defaultPositionCoins, defaultLockDuration) s.Require().NoError(err) - return positionID, concentratedLockID + return positionData.ID, concentratedLockID }, expectedHasActiveLock: true, // lock starts as active expectedHasActiveLockAfterTimeUpdate: false, // since lock is unlocking, it should no longer be active after time update @@ -1867,10 +1871,10 @@ func (s *KeeperTestSuite) TestPositionHasActiveUnderlyingLock() { name: "position without lock", createPosition: func(s *KeeperTestSuite) (uint64, uint64) { s.FundAcc(owner, defaultPositionCoins) - positionID, _, _, _, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition( + positionData, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition( s.Ctx, clPool.GetId(), owner, defaultPositionCoins) s.Require().NoError(err) - return positionID, 0 + return positionData.ID, 0 }, expectedHasActiveLock: false, expectedHasActiveLockAfterTimeUpdate: false, @@ -1964,10 +1968,10 @@ func (s *KeeperTestSuite) TestPositionHasActiveUnderlyingLockAndUpdate() { name: "position with lock locked", createPosition: func(s *KeeperTestSuite) (uint64, uint64) { s.FundAcc(owner, defaultPositionCoins) - positionID, _, _, _, concentratedLockID, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked( + positionData, concentratedLockID, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked( s.Ctx, clPool.GetId(), owner, defaultPositionCoins, defaultLockDuration) s.Require().NoError(err) - return positionID, concentratedLockID + return positionData.ID, concentratedLockID }, expectedHasActiveLock: true, // lock starts as active expectedHasActiveLockAfterTimeUpdate: true, // since lock is locked, it remains active after time update @@ -1981,10 +1985,10 @@ func (s *KeeperTestSuite) TestPositionHasActiveUnderlyingLockAndUpdate() { name: "position with lock unlocking", createPosition: func(s *KeeperTestSuite) (uint64, uint64) { s.FundAcc(owner, defaultPositionCoins) - positionID, _, _, _, concentratedLockID, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionUnlocking( + positionData, concentratedLockID, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionUnlocking( s.Ctx, clPool.GetId(), owner, defaultPositionCoins, defaultLockDuration) s.Require().NoError(err) - return positionID, concentratedLockID + return positionData.ID, concentratedLockID }, expectedHasActiveLock: true, // lock starts as active expectedHasActiveLockAfterTimeUpdate: false, // since lock is unlocking, it should no longer be active after time update @@ -1998,10 +2002,10 @@ func (s *KeeperTestSuite) TestPositionHasActiveUnderlyingLockAndUpdate() { name: "position without lock", createPosition: func(s *KeeperTestSuite) (uint64, uint64) { s.FundAcc(owner, defaultPositionCoins) - positionID, _, _, _, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition( + positionData, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition( s.Ctx, clPool.GetId(), owner, defaultPositionCoins) s.Require().NoError(err) - return positionID, 0 + return positionData.ID, 0 }, expectedHasActiveLock: false, expectedHasActiveLockAfterTimeUpdate: false, @@ -2095,46 +2099,46 @@ func (s *KeeperTestSuite) TestPositionToLockCRUD() { s.FundAcc(owner, defaultPositionCoins) // Create a position with a lock - positionId, _, _, _, concentratedLockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionUnlocking(s.Ctx, clPool.GetId(), owner, defaultPositionCoins, remainingLockDuration) + positionData, concentratedLockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionUnlocking(s.Ctx, clPool.GetId(), owner, defaultPositionCoins, remainingLockDuration) s.Require().NoError(err) // We should be able to retrieve the lockId from the positionId now - retrievedLockId, err := s.App.ConcentratedLiquidityKeeper.GetLockIdFromPositionId(s.Ctx, positionId) + retrievedLockId, err := s.App.ConcentratedLiquidityKeeper.GetLockIdFromPositionId(s.Ctx, positionData.ID) s.Require().NoError(err) s.Require().Equal(concentratedLockId, retrievedLockId) // Check if lock has position in state retrievedPositionId, err := s.App.ConcentratedLiquidityKeeper.GetPositionIdToLockId(s.Ctx, retrievedLockId) s.Require().NoError(err) - s.Require().Equal(positionId, retrievedPositionId) + s.Require().Equal(positionData.ID, retrievedPositionId) // Create a position without a lock - positionId, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, clPool.GetId(), owner, defaultPositionCoins) + positionData, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, clPool.GetId(), owner, defaultPositionCoins) s.Require().Error(err) // Check if position has lock in state, should not - retrievedLockId, err = s.App.ConcentratedLiquidityKeeper.GetLockIdFromPositionId(s.Ctx, positionId) + retrievedLockId, err = s.App.ConcentratedLiquidityKeeper.GetLockIdFromPositionId(s.Ctx, positionData.ID) s.Require().Error(err) s.Require().Equal(uint64(0), retrievedLockId) // Set the position to have a lockId (despite it not actually having a lock) - s.App.ConcentratedLiquidityKeeper.SetPositionIdToLock(s.Ctx, positionId, concentratedLockId) + s.App.ConcentratedLiquidityKeeper.SetPositionIdToLock(s.Ctx, positionData.ID, concentratedLockId) // Check if position has lock in state, it should now - retrievedLockId, err = s.App.ConcentratedLiquidityKeeper.GetLockIdFromPositionId(s.Ctx, positionId) + retrievedLockId, err = s.App.ConcentratedLiquidityKeeper.GetLockIdFromPositionId(s.Ctx, positionData.ID) s.Require().NoError(err) s.Require().Equal(concentratedLockId, retrievedLockId) // Check if lock has position in state retrievedPositionId, err = s.App.ConcentratedLiquidityKeeper.GetPositionIdToLockId(s.Ctx, retrievedLockId) s.Require().NoError(err) - s.Require().Equal(positionId, retrievedPositionId) + s.Require().Equal(positionData.ID, retrievedPositionId) // Remove the lockId from the position - s.App.ConcentratedLiquidityKeeper.RemovePositionIdForLockId(s.Ctx, positionId, retrievedLockId) + s.App.ConcentratedLiquidityKeeper.RemovePositionIdForLockId(s.Ctx, positionData.ID, retrievedLockId) // Check if position has lock in state, should not - retrievedLockId, err = s.App.ConcentratedLiquidityKeeper.GetLockIdFromPositionId(s.Ctx, positionId) + retrievedLockId, err = s.App.ConcentratedLiquidityKeeper.GetLockIdFromPositionId(s.Ctx, positionData.ID) s.Require().Error(err) s.Require().Equal(uint64(0), retrievedLockId) } @@ -2267,9 +2271,9 @@ func (s *KeeperTestSuite) TestGetAndUpdateFullRangeLiquidity() { actualFullRangeLiquidity := sdk.ZeroDec() // Create a full range position. - _, _, _, liquidity, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, clPool.GetId(), owner, tc.positionCoins) + positionData, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, clPool.GetId(), owner, tc.positionCoins) s.Require().NoError(err) - actualFullRangeLiquidity = actualFullRangeLiquidity.Add(liquidity) + actualFullRangeLiquidity = actualFullRangeLiquidity.Add(positionData.Liquidity) clPool, err = s.App.ConcentratedLiquidityKeeper.GetPoolById(s.Ctx, clPoolId) s.Require().NoError(err) @@ -2386,7 +2390,7 @@ func (s *KeeperTestSuite) TestCreateFullRangePositionLocked() { s.FundAcc(defaultAddress, test.coinsForPosition) // System under test - positionId, _, _, liquidity, concentratedLockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPool.GetId(), defaultAddress, test.coinsForPosition, test.remainingLockDuration) + positionData, concentratedLockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPool.GetId(), defaultAddress, test.coinsForPosition, test.remainingLockDuration) if test.expectedErr != nil { s.Require().ErrorContains(err, test.expectedErr.Error()) @@ -2396,18 +2400,18 @@ func (s *KeeperTestSuite) TestCreateFullRangePositionLocked() { s.Require().NoError(err) // Check position - position, err := s.App.ConcentratedLiquidityKeeper.GetPosition(s.Ctx, positionId) + position, err := s.App.ConcentratedLiquidityKeeper.GetPosition(s.Ctx, positionData.ID) s.Require().NoError(err) s.Require().Equal(s.Ctx.BlockTime(), position.JoinTime) s.Require().Equal(types.MaxTick, position.UpperTick) s.Require().Equal(types.MinInitializedTick, position.LowerTick) - s.Require().Equal(liquidity, position.Liquidity) + s.Require().Equal(positionData.Liquidity, position.Liquidity) // Check locked concentratedLock, err := s.App.LockupKeeper.GetLockByID(s.Ctx, concentratedLockId) s.Require().NoError(err) - s.Require().Equal(concentratedLock.Coins[0].Amount.String(), liquidity.TruncateInt().String()) + s.Require().Equal(concentratedLock.Coins[0].Amount.String(), positionData.Liquidity.TruncateInt().String()) s.Require().False(concentratedLock.IsUnlocking()) }) } diff --git a/x/concentrated-liquidity/swaps_tick_cross_test.go b/x/concentrated-liquidity/swaps_tick_cross_test.go index 72de8d56670..0a6274d379d 100644 --- a/x/concentrated-liquidity/swaps_tick_cross_test.go +++ b/x/concentrated-liquidity/swaps_tick_cross_test.go @@ -204,7 +204,7 @@ func (s *KeeperTestSuite) setupPoolAndPositions(testTickSpacing uint64, position // Create a full range position s.FundAcc(s.TestAccs[0], DefaultCoins) - _, _, _, liquidityFullRange, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, poolId, s.TestAccs[0], initialCoins) + positionData, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, poolId, s.TestAccs[0], initialCoins) s.Require().NoError(err) // Refetch pool as the first position updated its state. @@ -214,7 +214,7 @@ func (s *KeeperTestSuite) setupPoolAndPositions(testTickSpacing uint64, position // Create all narrow range positions per given tick spacings away from the current tick // configuration. positionMetas := make([]positionMeta, len(positionTickSpacingsFromCurrTick)) - liquidityAllPositions := liquidityFullRange + liquidityAllPositions := positionData.Liquidity for i, tickSpacingsAway := range positionTickSpacingsFromCurrTick { // Create narrow range position tickSpacingsAway from the current tick positionMetas[i] = s.CreatePositionTickSpacingsFromCurrentTick(poolId, tickSpacingsAway) diff --git a/x/concentrated-liquidity/types/cl.go b/x/concentrated-liquidity/types/cl.go index 5e345f298e8..9fc2bc8d4df 100644 --- a/x/concentrated-liquidity/types/cl.go +++ b/x/concentrated-liquidity/types/cl.go @@ -2,9 +2,21 @@ package types import ( fmt "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" ) // GetConcentratedLockupDenomFromPoolId returns the concentrated lockup denom for a given pool id. func GetConcentratedLockupDenomFromPoolId(poolId uint64) string { return fmt.Sprintf("%s/%d", ConcentratedLiquidityTokenPrefix, poolId) } + +// CreateFullRangePositionData represents the return data from any method +// that creates a full range position. We have multipl variants to +// account for varying locking scenarios. +type CreateFullRangePositionData struct { + ID uint64 + Amount0 sdk.Int + Amount1 sdk.Int + Liquidity sdk.Dec +} diff --git a/x/gamm/keeper/migrate.go b/x/gamm/keeper/migrate.go index 0b5edfc304c..bb325feec52 100644 --- a/x/gamm/keeper/migrate.go +++ b/x/gamm/keeper/migrate.go @@ -20,41 +20,41 @@ import ( func (k Keeper) MigrateUnlockedPositionFromBalancerToConcentrated(ctx sdk.Context, sender sdk.AccAddress, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins, -) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, poolIdLeaving, poolIdEntering uint64, err error) { +) (positionData cltypes.CreateFullRangePositionData, poolIdLeaving, poolIdEntering uint64, err error) { // Get the balancer poolId by parsing the gamm share denom. poolIdLeaving, err = types.GetPoolIdFromShareDenom(sharesToMigrate.Denom) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, err } // Find the governance sanctioned link between the balancer pool and a concentrated pool. poolIdEntering, err = k.GetLinkedConcentratedPoolID(ctx, poolIdLeaving) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, err } // Get the concentrated pool from the message and type cast it to ConcentratedPoolExtension. concentratedPool, err := k.concentratedLiquidityKeeper.GetConcentratedPoolById(ctx, poolIdEntering) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, err } // Exit the balancer pool position. exitCoins, err := k.ExitPool(ctx, sender, poolIdLeaving, sharesToMigrate.Amount, tokenOutMins) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, err } // Defense in depth, ensuring we are returning exactly two coins. if len(exitCoins) != 2 { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, fmt.Errorf("Balancer pool must have exactly two tokens") + return cltypes.CreateFullRangePositionData{}, 0, 0, fmt.Errorf("Balancer pool must have exactly two tokens") } // Create a full range (min to max tick) concentrated liquidity position. - positionId, amount0, amount1, liquidity, err = k.concentratedLiquidityKeeper.CreateFullRangePosition(ctx, concentratedPool.GetId(), sender, exitCoins) + positionData, err = k.concentratedLiquidityKeeper.CreateFullRangePosition(ctx, concentratedPool.GetId(), sender, exitCoins) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, err } - return positionId, amount0, amount1, liquidity, poolIdLeaving, poolIdEntering, nil + return positionData, poolIdLeaving, poolIdEntering, nil } // GetAllMigrationInfo gets all existing links between Balancer Pool and Concentrated Pool, diff --git a/x/gamm/keeper/migrate_test.go b/x/gamm/keeper/migrate_test.go index 8d9f9771c6c..b34fac028ce 100644 --- a/x/gamm/keeper/migrate_test.go +++ b/x/gamm/keeper/migrate_test.go @@ -229,7 +229,7 @@ func (s *KeeperTestSuite) TestMigrate() { // Migrate the user's gamm shares to a full range concentrated liquidity position userBalancesBeforeMigration := s.App.BankKeeper.GetAllBalances(s.Ctx, test.param.sender) - positionId, amount0, amount1, _, poolIdLeaving, poolIdEntering, err := keeper.MigrateUnlockedPositionFromBalancerToConcentrated(s.Ctx, test.param.sender, sharesToMigrate, test.tokenOutMins) + positionData, poolIdLeaving, poolIdEntering, err := keeper.MigrateUnlockedPositionFromBalancerToConcentrated(s.Ctx, test.param.sender, sharesToMigrate, test.tokenOutMins) userBalancesAfterMigration := s.App.BankKeeper.GetAllBalances(s.Ctx, test.param.sender) if test.expectedErr != nil { s.Require().Error(err) @@ -251,7 +251,7 @@ func (s *KeeperTestSuite) TestMigrate() { // Assure the position was not created. // TODO: When we implement lock breaking, we need to change time.Time{} to the lock's end time. - _, err := s.App.ConcentratedLiquidityKeeper.GetPositionLiquidity(s.Ctx, positionId) + _, err := s.App.ConcentratedLiquidityKeeper.GetPositionLiquidity(s.Ctx, positionData.ID) s.Require().Error(err) continue } @@ -264,14 +264,14 @@ func (s *KeeperTestSuite) TestMigrate() { // Determine how much of the user's balance was not used in the migration // This amount should be returned to the user. - expectedUserFinalEthBalanceDiff := expectedCoinsOut.AmountOf(ETH).Sub(amount0) - expectedUserFinalUsdcBalanceDiff := expectedCoinsOut.AmountOf(USDC).Sub(amount1) + expectedUserFinalEthBalanceDiff := expectedCoinsOut.AmountOf(ETH).Sub(positionData.Amount0) + expectedUserFinalUsdcBalanceDiff := expectedCoinsOut.AmountOf(USDC).Sub(positionData.Amount1) s.Require().Equal(userBalancesBeforeMigration.AmountOf(ETH).Add(expectedUserFinalEthBalanceDiff).String(), userBalancesAfterMigration.AmountOf(ETH).String()) s.Require().Equal(userBalancesBeforeMigration.AmountOf(USDC).Add(expectedUserFinalUsdcBalanceDiff).String(), userBalancesAfterMigration.AmountOf(USDC).String()) // Assure the expected position was created. // TODO: When we implement lock breaking, we need to change time.Time{} to the lock's end time. - position, err := s.App.ConcentratedLiquidityKeeper.GetPositionLiquidity(s.Ctx, positionId) + position, err := s.App.ConcentratedLiquidityKeeper.GetPositionLiquidity(s.Ctx, positionData.ID) s.Require().NoError(err) s.Require().Equal(test.expectedLiquidity, position) @@ -294,8 +294,8 @@ func (s *KeeperTestSuite) TestMigrate() { // Assert user amount transferred to cl pool from gamm pool should be equal to the amount we migrated from the migrate message. // This test is within 100 shares due to rounding that occurs from utilizing .000000000000000001 instead of 0. - s.Require().Equal(0, test.errTolerance.Compare(userEthBalanceTransferredToClPool.Amount, amount0)) - s.Require().Equal(0, test.errTolerance.Compare(userUsdcBalanceTransferredToClPool.Amount, amount1)) + s.Require().Equal(0, test.errTolerance.Compare(userEthBalanceTransferredToClPool.Amount, positionData.Amount0)) + s.Require().Equal(0, test.errTolerance.Compare(userUsdcBalanceTransferredToClPool.Amount, positionData.Amount0)) } } diff --git a/x/gamm/types/expected_keepers.go b/x/gamm/types/expected_keepers.go index adce072e991..dd21efda346 100644 --- a/x/gamm/types/expected_keepers.go +++ b/x/gamm/types/expected_keepers.go @@ -55,7 +55,7 @@ type CommunityPoolKeeper interface { type ConcentratedLiquidityKeeper interface { SetParams(ctx sdk.Context, params cltypes.Params) GetConcentratedPoolById(ctx sdk.Context, poolId uint64) (cltypes.ConcentratedPoolExtension, error) - CreateFullRangePosition(ctx sdk.Context, clPoolId uint64, owner sdk.AccAddress, coins sdk.Coins) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, err error) + CreateFullRangePosition(ctx sdk.Context, clPoolId uint64, owner sdk.AccAddress, coins sdk.Coins) (positionData cltypes.CreateFullRangePositionData, err error) } // PoolManager defines the interface needed to be fulfilled for diff --git a/x/lockup/keeper/lock_test.go b/x/lockup/keeper/lock_test.go index 9dc297f72fe..02e799fa9c5 100644 --- a/x/lockup/keeper/lock_test.go +++ b/x/lockup/keeper/lock_test.go @@ -1310,7 +1310,7 @@ func (s *KeeperTestSuite) TestSlashTokensFromLockByIDSendUnderlyingAndBurn() { // Create a cl pool and a locked full range position clPool := s.PrepareConcentratedPool() clPoolId := clPool.GetId() - positionID, _, _, liquidity, concentratedLockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPoolId, addr, tc.positionCoins, time.Hour) + positionData, concentratedLockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPoolId, addr, tc.positionCoins, time.Hour) s.Require().NoError(err) // Refetch the cl pool post full range position creation @@ -1321,7 +1321,7 @@ func (s *KeeperTestSuite) TestSlashTokensFromLockByIDSendUnderlyingAndBurn() { // Check the supply of the cl asset before we slash it is equal to the liquidity created clAssetSupplyPreSlash := s.App.BankKeeper.GetSupply(s.Ctx, clPoolPositionDenom) - s.Require().Equal(liquidity.TruncateInt().String(), clAssetSupplyPreSlash.Amount.String()) + s.Require().Equal(positionData.Liquidity.TruncateInt().String(), clAssetSupplyPreSlash.Amount.String()) // Store the cl pool balance before the slash clPoolBalancePreSlash := s.App.BankKeeper.GetAllBalances(s.Ctx, clPool.GetAddress()) @@ -1331,15 +1331,15 @@ func (s *KeeperTestSuite) TestSlashTokensFromLockByIDSendUnderlyingAndBurn() { Denom: clPoolPositionDenom, Duration: time.Second, }) - s.Require().Equal(liquidity.TruncateInt64(), acc.Int64()) + s.Require().Equal(positionData.Liquidity.TruncateInt64(), acc.Int64()) // The lockup module account balance before the slash should match the liquidity added to the lock lockupModuleBalancePreSlash := s.App.LockupKeeper.GetModuleBalance(s.Ctx) - s.Require().Equal(sdk.NewCoins(sdk.NewCoin(clPoolPositionDenom, liquidity.TruncateInt())), lockupModuleBalancePreSlash) + s.Require().Equal(sdk.NewCoins(sdk.NewCoin(clPoolPositionDenom, positionData.Liquidity.TruncateInt())), lockupModuleBalancePreSlash) // Slash the cl shares and the underlying assets // Figure out the underlying assets from the liquidity slash - position, err := s.App.ConcentratedLiquidityKeeper.GetPosition(s.Ctx, positionID) + position, err := s.App.ConcentratedLiquidityKeeper.GetPosition(s.Ctx, positionData.ID) s.Require().NoError(err) concentratedPool, err := s.App.ConcentratedLiquidityKeeper.GetConcentratedPoolById(s.Ctx, position.PoolId) diff --git a/x/superfluid/keeper/concentrated_liquidity.go b/x/superfluid/keeper/concentrated_liquidity.go index 55f3b752e5f..515de68fe6b 100644 --- a/x/superfluid/keeper/concentrated_liquidity.go +++ b/x/superfluid/keeper/concentrated_liquidity.go @@ -29,33 +29,33 @@ import ( // - The position is not superfluid staked. // - The position is the last position in the pool. // - The lock duration does not match the unbonding duration. -func (k Keeper) addToConcentratedLiquiditySuperfluidPosition(ctx sdk.Context, sender sdk.AccAddress, positionId uint64, amount0ToAdd, amount1ToAdd sdk.Int) (uint64, sdk.Int, sdk.Int, sdk.Dec, uint64, error) { +func (k Keeper) addToConcentratedLiquiditySuperfluidPosition(ctx sdk.Context, sender sdk.AccAddress, positionId uint64, amount0ToAdd, amount1ToAdd sdk.Int) (cltypes.CreateFullRangePositionData, uint64, error) { position, err := k.clk.GetPosition(ctx, positionId) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return cltypes.CreateFullRangePositionData{}, 0, err } if amount0ToAdd.IsNegative() || amount1ToAdd.IsNegative() { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, cltypes.NegativeAmountAddedError{PositionId: position.PositionId, Asset0Amount: amount0ToAdd, Asset1Amount: amount1ToAdd} + return cltypes.CreateFullRangePositionData{}, 0, cltypes.NegativeAmountAddedError{PositionId: position.PositionId, Asset0Amount: amount0ToAdd, Asset1Amount: amount1ToAdd} } // If the position is not superfluid staked, return error. positionHasActiveUnderlyingLock, lockId, err := k.clk.PositionHasActiveUnderlyingLock(ctx, positionId) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return cltypes.CreateFullRangePositionData{}, 0, err } if !positionHasActiveUnderlyingLock || lockId == 0 { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, types.PositionNotSuperfluidStakedError{PositionId: position.PositionId} + return cltypes.CreateFullRangePositionData{}, 0, types.PositionNotSuperfluidStakedError{PositionId: position.PositionId} } // Defense in depth making sure that the position is full-range. if position.LowerTick != cltypes.MinInitializedTick || position.UpperTick != cltypes.MaxTick { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, types.ConcentratedTickRangeNotFullError{ActualLowerTick: position.LowerTick, ActualUpperTick: position.UpperTick} + return cltypes.CreateFullRangePositionData{}, 0, types.ConcentratedTickRangeNotFullError{ActualLowerTick: position.LowerTick, ActualUpperTick: position.UpperTick} } lock, err := k.lk.GetLockByID(ctx, lockId) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return cltypes.CreateFullRangePositionData{}, 0, err } // Defense in depth. Require the underlying lock: @@ -64,60 +64,60 @@ func (k Keeper) addToConcentratedLiquiditySuperfluidPosition(ctx sdk.Context, se // - duration is equal to unbonding time // - end time is zero (not unbonding) if lock.Owner != position.Address { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, types.LockOwnerMismatchError{LockId: lockId, LockOwner: lock.Owner, ProvidedOwner: position.Address} + return cltypes.CreateFullRangePositionData{}, 0, types.LockOwnerMismatchError{LockId: lockId, LockOwner: lock.Owner, ProvidedOwner: position.Address} } if lock.Owner != sender.String() { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, types.LockOwnerMismatchError{LockId: lockId, LockOwner: lock.Owner, ProvidedOwner: sender.String()} + return cltypes.CreateFullRangePositionData{}, 0, types.LockOwnerMismatchError{LockId: lockId, LockOwner: lock.Owner, ProvidedOwner: sender.String()} } unbondingDuration := k.sk.UnbondingTime(ctx) if lock.Duration != unbondingDuration || !lock.EndTime.IsZero() { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, types.LockImproperStateError{LockId: lockId, UnbondingDuration: unbondingDuration.String()} + return cltypes.CreateFullRangePositionData{}, 0, types.LockImproperStateError{LockId: lockId, UnbondingDuration: unbondingDuration.String()} } // Superfluid undelegate the superfluid delegated position. // This deletes the connection between the lock and the intermediate account, deletes the synthetic lock, and burns the synthetic osmo. intermediateAccount, err := k.SuperfluidUndelegateToConcentratedPosition(ctx, sender.String(), lockId) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return cltypes.CreateFullRangePositionData{}, 0, err } // Finish unlocking directly for the lock. // This also breaks and deletes associated synthetic locks. err = k.lk.ForceUnlock(ctx, *lock) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return cltypes.CreateFullRangePositionData{}, 0, err } // Withdraw full liquidity from the position. amount0Withdrawn, amount1Withdrawn, err := k.clk.WithdrawPosition(ctx, sender, positionId, position.Liquidity) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return cltypes.CreateFullRangePositionData{}, 0, err } // If this is the last position in the pool, error. anyPositionsRemainingInPool, err := k.clk.HasAnyPositionForPool(ctx, position.PoolId) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return cltypes.CreateFullRangePositionData{}, 0, err } if !anyPositionsRemainingInPool { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, cltypes.AddToLastPositionInPoolError{PoolId: position.PoolId, PositionId: position.PositionId} + return cltypes.CreateFullRangePositionData{}, 0, cltypes.AddToLastPositionInPoolError{PoolId: position.PoolId, PositionId: position.PositionId} } // Create a coins object that includes the old position coins and the new position coins. concentratedPool, err := k.clk.GetConcentratedPoolById(ctx, position.PoolId) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return cltypes.CreateFullRangePositionData{}, 0, err } newPositionCoins := sdk.NewCoins(sdk.NewCoin(concentratedPool.GetToken0(), amount0Withdrawn.Add(amount0ToAdd)), sdk.NewCoin(concentratedPool.GetToken1(), amount1Withdrawn.Add(amount1ToAdd))) // Create a full range (min to max tick) concentrated liquidity position, lock it, and superfluid delegate it. - newPositionId, actualNewAmount0, actualNewAmount1, newLiquidity, newLockId, err := k.clk.CreateFullRangePositionLocked(ctx, position.PoolId, sender, newPositionCoins, unbondingDuration) + positionData, newLockId, err := k.clk.CreateFullRangePositionLocked(ctx, position.PoolId, sender, newPositionCoins, unbondingDuration) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return cltypes.CreateFullRangePositionData{}, 0, err } err = k.SuperfluidDelegate(ctx, sender.String(), newLockId, intermediateAccount.ValAddr) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err + return cltypes.CreateFullRangePositionData{}, 0, err } // Emit events. @@ -130,13 +130,13 @@ func (k Keeper) addToConcentratedLiquiditySuperfluidPosition(ctx sdk.Context, se types.TypeEvtAddToConcentratedLiquiditySuperfluidPosition, sdk.NewAttribute(sdk.AttributeKeySender, sender.String()), sdk.NewAttribute(types.AttributePositionId, strconv.FormatUint(positionId, 10)), - sdk.NewAttribute(types.AttributeNewPositionId, strconv.FormatUint(newPositionId, 10)), - sdk.NewAttribute(types.AttributeAmount0, actualNewAmount0.String()), - sdk.NewAttribute(types.AttributeAmount1, actualNewAmount1.String()), + sdk.NewAttribute(types.AttributeNewPositionId, strconv.FormatUint(positionData.ID, 10)), + sdk.NewAttribute(types.AttributeAmount0, positionData.Amount0.String()), + sdk.NewAttribute(types.AttributeAmount1, positionData.Amount1.String()), sdk.NewAttribute(types.AttributeConcentratedLockId, strconv.FormatUint(newLockId, 10)), - sdk.NewAttribute(types.AttributeLiquidity, newLiquidity.String()), + sdk.NewAttribute(types.AttributeLiquidity, positionData.Liquidity.String()), ), }) - return newPositionId, actualNewAmount0, actualNewAmount1, newLiquidity, newLockId, nil + return positionData, newLockId, nil } diff --git a/x/superfluid/keeper/concentrated_liquidity_test.go b/x/superfluid/keeper/concentrated_liquidity_test.go index 5463e59c3a5..2218568d7af 100644 --- a/x/superfluid/keeper/concentrated_liquidity_test.go +++ b/x/superfluid/keeper/concentrated_liquidity_test.go @@ -135,7 +135,7 @@ func (s *KeeperTestSuite) TestAddToConcentratedLiquiditySuperfluidPosition() { if !tc.isLastPositionInPool { fundCoins := sdk.NewCoins(sdk.NewCoin(clPool.GetToken0(), sdk.NewInt(100000000)), sdk.NewCoin(clPool.GetToken1(), sdk.NewInt(100000000))) s.FundAcc(nonOwner, fundCoins) - _, _, _, _, err := concentratedLiquidityKeeper.CreateFullRangePosition(ctx, clPool.GetId(), nonOwner, fundCoins) + _, err := concentratedLiquidityKeeper.CreateFullRangePosition(ctx, clPool.GetId(), nonOwner, fundCoins) s.Require().NoError(err) } @@ -147,7 +147,7 @@ func (s *KeeperTestSuite) TestAddToConcentratedLiquiditySuperfluidPosition() { preAddToPositionPoolFunds := bankKeeper.GetAllBalances(ctx, clPoolAddress) // System under test. - newPositionId, finalAmount0, finalAmount1, newLiquidity, newLockId, err := superfluidKeeper.AddToConcentratedLiquiditySuperfluidPosition(ctx, executionAcc, positionId, tc.amount0Added, tc.amount1Added) + positionData, newLockId, err := superfluidKeeper.AddToConcentratedLiquiditySuperfluidPosition(ctx, executionAcc, positionId, tc.amount0Added, tc.amount1Added) if tc.expectedError != nil { s.Require().Error(err) s.Require().ErrorContains(err, tc.expectedError.Error()) @@ -184,11 +184,11 @@ func (s *KeeperTestSuite) TestAddToConcentratedLiquiditySuperfluidPosition() { expectedNewCoins := sdk.NewCoins(sdk.NewCoin(clPool.GetToken0(), amount0.Add(tc.amount0Added)), sdk.NewCoin(clPool.GetToken1(), amount1.Add(tc.amount1Added))) clPoolDenom := cltypes.GetConcentratedLockupDenomFromPoolId(clPool.GetId()) - expectedLockCoins := sdk.NewCoins(sdk.NewCoin(clPoolDenom, newLiquidity.TruncateInt())) + expectedLockCoins := sdk.NewCoins(sdk.NewCoin(clPoolDenom, positionData.Liquidity.TruncateInt())) // Resulting position should have the expected amount of coins within one unit (rounding down). - s.Require().Equal(0, errTolerance.Compare(expectedNewCoins[0].Amount, finalAmount0), fmt.Sprintf("expected (%s), actual (%s)", expectedNewCoins[0].Amount, finalAmount0)) - s.Require().Equal(0, errTolerance.Compare(expectedNewCoins[1].Amount, finalAmount1), fmt.Sprintf("expected (%s), actual (%s)", expectedNewCoins[1].Amount, finalAmount1)) + s.Require().Equal(0, errTolerance.Compare(expectedNewCoins[0].Amount, positionData.Amount0), fmt.Sprintf("expected (%s), actual (%s)", expectedNewCoins[0].Amount, positionData.Amount0)) + s.Require().Equal(0, errTolerance.Compare(expectedNewCoins[1].Amount, positionData.Amount1), fmt.Sprintf("expected (%s), actual (%s)", expectedNewCoins[1].Amount, positionData.Amount1)) // Check the new lock. newLock, err := s.App.LockupKeeper.GetLockByID(ctx, newLockId) @@ -199,7 +199,7 @@ func (s *KeeperTestSuite) TestAddToConcentratedLiquiditySuperfluidPosition() { s.Require().Equal(expectedLockCoins.String(), newLock.Coins.String()) // Check that a new position and lock ID were generated. - s.Require().NotEqual(positionId, newPositionId) + s.Require().NotEqual(positionId, positionData.ID) s.Require().NotEqual(lockId, newLockId) // Check if intermediary account connection for the old lock ID is deleted. @@ -224,7 +224,7 @@ func (s *KeeperTestSuite) TestAddToConcentratedLiquiditySuperfluidPosition() { s.Require().False(found) // Check if the new intermediary account has expected delegation amount. - expectedDelegationAmt := superfluidKeeper.GetRiskAdjustedOsmoValue(ctx, finalAmount0) + expectedDelegationAmt := superfluidKeeper.GetRiskAdjustedOsmoValue(ctx, positionData.Amount0) delegationAmt, found := stakingKeeper.GetDelegation(ctx, newIntermediaryAcc, valAddr) s.Require().True(found) s.Require().Equal(expectedDelegationAmt, delegationAmt.Shares.TruncateInt()) @@ -263,8 +263,11 @@ func (s *KeeperTestSuite) SetupSuperfluidConcentratedPosition(ctx sdk.Context, s unbondingDuration := stakingKeeper.GetParams(ctx).UnbondingTime // Create a full range position in the concentrated liquidity pool. - positionId, amount0, amount1, _, lockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPoolId, poolJoinAcc, fullRangeCoins, unbondingDuration) + positionData, lockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPoolId, poolJoinAcc, fullRangeCoins, unbondingDuration) s.Require().NoError(err) + positionId = positionData.ID + amount0 = positionData.Amount0 + amount1 = positionData.Amount1 // Register the CL full range LP tokens as a superfluid asset. clPoolDenom := cltypes.GetConcentratedLockupDenomFromPoolId(clPoolId) diff --git a/x/superfluid/keeper/export_test.go b/x/superfluid/keeper/export_test.go index 662059c0feb..c0fad6b6d70 100644 --- a/x/superfluid/keeper/export_test.go +++ b/x/superfluid/keeper/export_test.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" + cltypes "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" lockuptypes "github.com/osmosis-labs/osmosis/v17/x/lockup/types" ) @@ -21,15 +22,15 @@ func (k Keeper) PrepareConcentratedLockForSlash(ctx sdk.Context, lock *lockuptyp return k.prepareConcentratedLockForSlash(ctx, lock, slashAmt) } -func (k Keeper) MigrateSuperfluidBondedBalancerToConcentrated(ctx sdk.Context, sender sdk.AccAddress, lockId uint64, sharesToMigrate sdk.Coin, synthDenomBeforeMigration string, tokenOutMins sdk.Coins) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, concentratedLockId, poolIdLeaving, poolIdEntering uint64, err error) { +func (k Keeper) MigrateSuperfluidBondedBalancerToConcentrated(ctx sdk.Context, sender sdk.AccAddress, lockId uint64, sharesToMigrate sdk.Coin, synthDenomBeforeMigration string, tokenOutMins sdk.Coins) (positionData cltypes.CreateFullRangePositionData, concentratedLockId, poolIdLeaving, poolIdEntering uint64, err error) { return k.migrateSuperfluidBondedBalancerToConcentrated(ctx, sender, lockId, sharesToMigrate, synthDenomBeforeMigration, tokenOutMins) } -func (k Keeper) MigrateSuperfluidUnbondingBalancerToConcentrated(ctx sdk.Context, sender sdk.AccAddress, lockId uint64, sharesToMigrate sdk.Coin, synthDenomBeforeMigration string, tokenOutMins sdk.Coins) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, concentratedLockId, poolIdLeaving, poolIdEntering uint64, err error) { +func (k Keeper) MigrateSuperfluidUnbondingBalancerToConcentrated(ctx sdk.Context, sender sdk.AccAddress, lockId uint64, sharesToMigrate sdk.Coin, synthDenomBeforeMigration string, tokenOutMins sdk.Coins) (positionData cltypes.CreateFullRangePositionData, concentratedLockId, poolIdLeaving, poolIdEntering uint64, err error) { return k.migrateSuperfluidUnbondingBalancerToConcentrated(ctx, sender, lockId, sharesToMigrate, synthDenomBeforeMigration, tokenOutMins) } -func (k Keeper) MigrateNonSuperfluidLockBalancerToConcentrated(ctx sdk.Context, sender sdk.AccAddress, lockId uint64, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, concentratedLockId, poolIdLeaving, poolIdEntering uint64, err error) { +func (k Keeper) MigrateNonSuperfluidLockBalancerToConcentrated(ctx sdk.Context, sender sdk.AccAddress, lockId uint64, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins) (positionData cltypes.CreateFullRangePositionData, concentratedLockId, poolIdLeaving, poolIdEntering uint64, err error) { return k.migrateNonSuperfluidLockBalancerToConcentrated(ctx, sender, lockId, sharesToMigrate, tokenOutMins) } @@ -45,7 +46,7 @@ func (k Keeper) ValidateMigration(ctx sdk.Context, sender sdk.AccAddress, lockId return k.validateMigration(ctx, sender, lockId, sharesToMigrate) } -func (k Keeper) AddToConcentratedLiquiditySuperfluidPosition(ctx sdk.Context, owner sdk.AccAddress, positionId uint64, amount0Added, amount1Added sdk.Int) (uint64, sdk.Int, sdk.Int, sdk.Dec, uint64, error) { +func (k Keeper) AddToConcentratedLiquiditySuperfluidPosition(ctx sdk.Context, owner sdk.AccAddress, positionId uint64, amount0Added, amount1Added sdk.Int) (cltypes.CreateFullRangePositionData, uint64, error) { return k.addToConcentratedLiquiditySuperfluidPosition(ctx, owner, positionId, amount0Added, amount1Added) } diff --git a/x/superfluid/keeper/grpc_query_test.go b/x/superfluid/keeper/grpc_query_test.go index f785b15f498..f2e3f79f25b 100644 --- a/x/superfluid/keeper/grpc_query_test.go +++ b/x/superfluid/keeper/grpc_query_test.go @@ -313,7 +313,7 @@ func (s *KeeperTestSuite) TestUserConcentratedSuperfluidPositionsBondedAndUnbond expectedBondedLockIds := []uint64{} expectedBondedTotalSharesLocked := sdk.Coins{} for i := 0; i < 4; i++ { - posId, _, _, _, lockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPoolId, s.TestAccs[0], coins, duration) + positionData, lockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPoolId, s.TestAccs[0], coins, duration) s.Require().NoError(err) lock, err := s.App.LockupKeeper.GetLockByID(s.Ctx, lockId) @@ -322,13 +322,13 @@ func (s *KeeperTestSuite) TestUserConcentratedSuperfluidPositionsBondedAndUnbond err = s.App.SuperfluidKeeper.SuperfluidDelegate(s.Ctx, lock.Owner, lock.ID, valAddrs[0].String()) s.Require().NoError(err) - expectedBondedPositionIds = append(expectedBondedPositionIds, posId) + expectedBondedPositionIds = append(expectedBondedPositionIds, positionData.ID) expectedBondedLockIds = append(expectedBondedLockIds, lockId) expectedBondedTotalSharesLocked = expectedBondedTotalSharesLocked.Add(lock.Coins[0]) } // Create 1 position in pool 1 that is not superfluid delegated. - _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, clPoolId, s.TestAccs[0], coins) + _, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, clPoolId, s.TestAccs[0], coins) s.Require().NoError(err) // Create 4 positions in pool 2 that are superfluid undelegating. @@ -336,7 +336,7 @@ func (s *KeeperTestSuite) TestUserConcentratedSuperfluidPositionsBondedAndUnbond expectedUnbondingLockIds := []uint64{} expectedUnbondingTotalSharesLocked := sdk.Coins{} for i := 0; i < 4; i++ { - posId, _, _, _, lockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPoolId2, s.TestAccs[0], coins, duration) + positionData, lockId, err := s.App.ConcentratedLiquidityKeeper.CreateFullRangePositionLocked(s.Ctx, clPoolId2, s.TestAccs[0], coins, duration) s.Require().NoError(err) lock, err := s.App.LockupKeeper.GetLockByID(s.Ctx, lockId) @@ -348,13 +348,13 @@ func (s *KeeperTestSuite) TestUserConcentratedSuperfluidPositionsBondedAndUnbond _, err = s.App.SuperfluidKeeper.SuperfluidUndelegateAndUnbondLock(s.Ctx, lockId, lock.Owner, lock.Coins[0].Amount) s.Require().NoError(err) - expectedUnbondingPositionIds = append(expectedUnbondingPositionIds, posId) + expectedUnbondingPositionIds = append(expectedUnbondingPositionIds, positionData.ID) expectedUnbondingLockIds = append(expectedUnbondingLockIds, lockId) expectedUnbondingTotalSharesLocked = expectedUnbondingTotalSharesLocked.Add(lock.Coins[0]) } // Create 1 position in pool 2 that is not superfluid delegated. - _, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, clPoolId2, s.TestAccs[0], coins) + _, err = s.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, clPoolId2, s.TestAccs[0], coins) s.Require().NoError(err) // Query the bonded positions. diff --git a/x/superfluid/keeper/migrate.go b/x/superfluid/keeper/migrate.go index a20d89d2787..1518ad892c1 100644 --- a/x/superfluid/keeper/migrate.go +++ b/x/superfluid/keeper/migrate.go @@ -46,10 +46,10 @@ const ( // - Create new CL lock and starts unlocking or unlocking where it left off. // // Errors if the lock is not found, if the lock is not a balancer pool lock, or if the lock is not owned by the sender. -func (k Keeper) RouteLockedBalancerToConcentratedMigration(ctx sdk.Context, sender sdk.AccAddress, providedLockId int64, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, poolIdLeaving, poolIdEntering, concentratedLockId uint64, err error) { +func (k Keeper) RouteLockedBalancerToConcentratedMigration(ctx sdk.Context, sender sdk.AccAddress, providedLockId int64, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins) (positionData cltypes.CreateFullRangePositionData, poolIdLeaving, poolIdEntering, concentratedLockId uint64, err error) { synthLockBeforeMigration, migrationType, err := k.routeMigration(ctx, sender, providedLockId, sharesToMigrate) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } // As a hack around to get frontend working, we decided to allow negative values for the provided lock ID to indicate that the user wants to migrate shares that are not locked. @@ -57,19 +57,19 @@ func (k Keeper) RouteLockedBalancerToConcentratedMigration(ctx sdk.Context, send switch migrationType { case SuperfluidBonded: - positionId, amount0, amount1, liquidity, concentratedLockId, poolIdLeaving, poolIdEntering, err = k.migrateSuperfluidBondedBalancerToConcentrated(ctx, sender, lockId, sharesToMigrate, synthLockBeforeMigration.SynthDenom, tokenOutMins) + positionData, concentratedLockId, poolIdLeaving, poolIdEntering, err = k.migrateSuperfluidBondedBalancerToConcentrated(ctx, sender, lockId, sharesToMigrate, synthLockBeforeMigration.SynthDenom, tokenOutMins) case SuperfluidUnbonding: - positionId, amount0, amount1, liquidity, concentratedLockId, poolIdLeaving, poolIdEntering, err = k.migrateSuperfluidUnbondingBalancerToConcentrated(ctx, sender, lockId, sharesToMigrate, synthLockBeforeMigration.SynthDenom, tokenOutMins) + positionData, concentratedLockId, poolIdLeaving, poolIdEntering, err = k.migrateSuperfluidUnbondingBalancerToConcentrated(ctx, sender, lockId, sharesToMigrate, synthLockBeforeMigration.SynthDenom, tokenOutMins) case NonSuperfluid: - positionId, amount0, amount1, liquidity, concentratedLockId, poolIdLeaving, poolIdEntering, err = k.migrateNonSuperfluidLockBalancerToConcentrated(ctx, sender, lockId, sharesToMigrate, tokenOutMins) + positionData, concentratedLockId, poolIdLeaving, poolIdEntering, err = k.migrateNonSuperfluidLockBalancerToConcentrated(ctx, sender, lockId, sharesToMigrate, tokenOutMins) case Unlocked: - positionId, amount0, amount1, liquidity, poolIdLeaving, poolIdEntering, err = k.gk.MigrateUnlockedPositionFromBalancerToConcentrated(ctx, sender, sharesToMigrate, tokenOutMins) + positionData, poolIdLeaving, poolIdEntering, err = k.gk.MigrateUnlockedPositionFromBalancerToConcentrated(ctx, sender, sharesToMigrate, tokenOutMins) concentratedLockId = 0 default: - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, fmt.Errorf("unsupported migration type") + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, fmt.Errorf("unsupported migration type") } - return positionId, amount0, amount1, liquidity, poolIdLeaving, poolIdEntering, concentratedLockId, err + return positionData, poolIdLeaving, poolIdEntering, concentratedLockId, err } // migrateSuperfluidBondedBalancerToConcentrated migrates a user's superfluid bonded balancer position to a superfluid bonded concentrated liquidity position. @@ -82,17 +82,17 @@ func (k Keeper) migrateSuperfluidBondedBalancerToConcentrated(ctx sdk.Context, sharesToMigrate sdk.Coin, synthDenomBeforeMigration string, tokenOutMins sdk.Coins, -) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, concentratedLockId, poolIdLeaving, poolIdEntering uint64, err error) { +) (positionData cltypes.CreateFullRangePositionData, concentratedLockId, poolIdLeaving, poolIdEntering uint64, err error) { poolIdLeaving, poolIdEntering, preMigrationLock, remainingLockTime, err := k.validateMigration(ctx, sender, originalLockId, sharesToMigrate) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } // Get the validator address from the synth denom and ensure it is a valid address. valAddr := strings.Split(synthDenomBeforeMigration, "/")[4] _, err = sdk.ValAddressFromBech32(valAddr) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } // Superfluid undelegate the portion of shares the user is migrating from the superfluid delegated position. @@ -101,7 +101,7 @@ func (k Keeper) migrateSuperfluidBondedBalancerToConcentrated(ctx sdk.Context, intermediateAccount, err = k.SuperfluidUndelegateToConcentratedPosition(ctx, sender.String(), originalLockId) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } // Force unlock, validate the provided sharesToMigrate, and exit the balancer pool. @@ -109,21 +109,21 @@ func (k Keeper) migrateSuperfluidBondedBalancerToConcentrated(ctx sdk.Context, // It also returns the lock object that contains the remaining shares that were not used in this migration. exitCoins, err := k.validateSharesToMigrateUnlockAndExitBalancerPool(ctx, sender, poolIdLeaving, preMigrationLock, sharesToMigrate, tokenOutMins) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } // Create a full range (min to max tick) concentrated liquidity position, lock it, and superfluid delegate it. - positionId, amount0, amount1, liquidity, concentratedLockId, err = k.clk.CreateFullRangePositionLocked(ctx, poolIdEntering, sender, exitCoins, remainingLockTime) + positionData, concentratedLockId, err = k.clk.CreateFullRangePositionLocked(ctx, poolIdEntering, sender, exitCoins, remainingLockTime) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } err = k.SuperfluidDelegate(ctx, sender.String(), concentratedLockId, intermediateAccount.ValAddr) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } - return positionId, amount0, amount1, liquidity, concentratedLockId, poolIdLeaving, poolIdEntering, nil + return positionData, concentratedLockId, poolIdLeaving, poolIdEntering, nil } // migrateSuperfluidUnbondingBalancerToConcentrated migrates a user's superfluid unbonding balancer position to a superfluid unbonding concentrated liquidity position. @@ -137,17 +137,17 @@ func (k Keeper) migrateSuperfluidUnbondingBalancerToConcentrated(ctx sdk.Context sharesToMigrate sdk.Coin, synthDenomBeforeMigration string, tokenOutMins sdk.Coins, -) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, concentratedLockId, poolIdLeaving, poolIdEntering uint64, err error) { +) (positionData cltypes.CreateFullRangePositionData, concentratedLockId, poolIdLeaving, poolIdEntering uint64, err error) { poolIdLeaving, poolIdEntering, preMigrationLock, remainingLockTime, err := k.validateMigration(ctx, sender, lockId, sharesToMigrate) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } // Get the validator address from the synth denom and ensure it is a valid address. valAddr := strings.Split(synthDenomBeforeMigration, "/")[4] _, err = sdk.ValAddressFromBech32(valAddr) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } // Force unlock, validate the provided sharesToMigrate, and exit the balancer pool. @@ -155,13 +155,13 @@ func (k Keeper) migrateSuperfluidUnbondingBalancerToConcentrated(ctx sdk.Context // It also returns the lock object that contains the remaining shares that were not used in this migration. exitCoins, err := k.validateSharesToMigrateUnlockAndExitBalancerPool(ctx, sender, poolIdLeaving, preMigrationLock, sharesToMigrate, tokenOutMins) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } // Create a full range (min to max tick) concentrated liquidity position. - positionId, amount0, amount1, liquidity, concentratedLockId, err = k.clk.CreateFullRangePositionUnlocking(ctx, poolIdEntering, sender, exitCoins, remainingLockTime) + positionData, concentratedLockId, err = k.clk.CreateFullRangePositionUnlocking(ctx, poolIdEntering, sender, exitCoins, remainingLockTime) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } // The previous gamm intermediary account is now invalid for the new lock, since the underlying denom has changed and intermediary accounts are @@ -170,17 +170,17 @@ func (k Keeper) migrateSuperfluidUnbondingBalancerToConcentrated(ctx sdk.Context concentratedLockupDenom := cltypes.GetConcentratedLockupDenomFromPoolId(poolIdEntering) clIntermediateAccount, err := k.GetOrCreateIntermediaryAccount(ctx, concentratedLockupDenom, valAddr) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } // Synthetic lock is created to indicate unbonding position. The synthetic lock will be in unbonding period for remainingLockTime. // Create a new synthetic lockup for the new intermediary account in an unlocking status for the remaining duration. err = k.createSyntheticLockupWithDuration(ctx, concentratedLockId, clIntermediateAccount, remainingLockTime, unlockingStatus) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } - return positionId, amount0, amount1, liquidity, concentratedLockId, poolIdLeaving, poolIdEntering, nil + return positionData, concentratedLockId, poolIdLeaving, poolIdEntering, nil } // migrateNonSuperfluidLockBalancerToConcentrated migrates a user's non-superfluid locked or unlocking balancer position to an unlocking concentrated liquidity position. @@ -192,10 +192,10 @@ func (k Keeper) migrateNonSuperfluidLockBalancerToConcentrated(ctx sdk.Context, lockId uint64, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins, -) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, concentratedLockId, poolIdLeaving, poolIdEntering uint64, err error) { +) (positionData cltypes.CreateFullRangePositionData, concentratedLockId, poolIdLeaving, poolIdEntering uint64, err error) { poolIdLeaving, poolIdEntering, preMigrationLock, remainingLockTime, err := k.validateMigration(ctx, sender, lockId, sharesToMigrate) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } // Force unlock, validate the provided sharesToMigrate, and exit the balancer pool. @@ -203,18 +203,18 @@ func (k Keeper) migrateNonSuperfluidLockBalancerToConcentrated(ctx sdk.Context, // It also returns the lock object that contains the remaining shares that were not used in this migration. exitCoins, err := k.validateSharesToMigrateUnlockAndExitBalancerPool(ctx, sender, poolIdLeaving, preMigrationLock, sharesToMigrate, tokenOutMins) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } // Create a new lock that is unlocking for the remaining time of the old lock. // Regardless of the previous lock's status, we create a new lock that is unlocking. // This is because locking without superfluid is pointless in the context of concentrated liquidity. - positionId, amount0, amount1, liquidity, concentratedLockId, err = k.clk.CreateFullRangePositionUnlocking(ctx, poolIdEntering, sender, exitCoins, remainingLockTime) + positionData, concentratedLockId, err = k.clk.CreateFullRangePositionUnlocking(ctx, poolIdEntering, sender, exitCoins, remainingLockTime) if err != nil { - return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err + return cltypes.CreateFullRangePositionData{}, 0, 0, 0, err } - return positionId, amount0, amount1, liquidity, concentratedLockId, poolIdLeaving, poolIdEntering, nil + return positionData, concentratedLockId, poolIdLeaving, poolIdEntering, nil } // routeMigration determines the status of the provided lock which is used to determine the method for migration. diff --git a/x/superfluid/keeper/migrate_test.go b/x/superfluid/keeper/migrate_test.go index 8411e503247..420f2d3b839 100644 --- a/x/superfluid/keeper/migrate_test.go +++ b/x/superfluid/keeper/migrate_test.go @@ -161,7 +161,7 @@ func (s *KeeperTestSuite) TestRouteLockedBalancerToConcentratedMigration() { balancerDelegationPre, _ := stakingKeeper.GetDelegation(s.Ctx, balancerIntermediaryAcc.GetAccAddress(), valAddr) // Run the migration logic. - positionId, amount0, amount1, liquidityMigrated, poolIdLeaving, poolIdEntering, concentratedLockId, err := superfluidKeeper.RouteLockedBalancerToConcentratedMigration(s.Ctx, poolJoinAcc, int64(originalGammLockId), coinsToMigrate, tc.minExitCoins) + positionData, poolIdLeaving, poolIdEntering, concentratedLockId, err := superfluidKeeper.RouteLockedBalancerToConcentratedMigration(s.Ctx, poolJoinAcc, int64(originalGammLockId), coinsToMigrate, tc.minExitCoins) if tc.expectedError != nil { s.Require().Error(err) s.Require().ErrorIs(err, tc.expectedError) @@ -171,12 +171,12 @@ func (s *KeeperTestSuite) TestRouteLockedBalancerToConcentratedMigration() { s.AssertEventEmitted(s.Ctx, gammtypes.TypeEvtPoolExited, 1) s.ValidateMigrateResult( - positionId, balancerPooId, poolIdLeaving, clPoolId, poolIdEntering, - tc.percentOfSharesToMigrate, liquidityMigrated, + positionData.ID, balancerPooId, poolIdLeaving, clPoolId, poolIdEntering, + tc.percentOfSharesToMigrate, positionData.Liquidity, *balancerLock, joinPoolAmt, balancerPoolShareOut, coinsToMigrate, - amount0, amount1, + positionData.Amount0, positionData.Amount1, ) // If the lock was superfluid delegated: @@ -324,7 +324,7 @@ func (s *KeeperTestSuite) TestMigrateSuperfluidBondedBalancerToConcentrated() { balancerDelegationPre, _ := stakingKeeper.GetDelegation(s.Ctx, balancerIntermediaryAcc.GetAccAddress(), valAddr) // System under test. - positionId, amount0, amount1, liquidityMigrated, concentratedLockId, poolIdLeaving, poolIdEntering, err := superfluidKeeper.MigrateSuperfluidBondedBalancerToConcentrated(s.Ctx, poolJoinAcc, originalGammLockId, coinsToMigrate, synthLockBeforeMigration.SynthDenom, tc.tokenOutMins) + positionData, concentratedLockId, poolIdLeaving, poolIdEntering, err := superfluidKeeper.MigrateSuperfluidBondedBalancerToConcentrated(s.Ctx, poolJoinAcc, originalGammLockId, coinsToMigrate, synthLockBeforeMigration.SynthDenom, tc.tokenOutMins) if tc.expectedError != nil { s.Require().Error(err) s.Require().ErrorContains(err, tc.expectedError.Error()) @@ -334,12 +334,12 @@ func (s *KeeperTestSuite) TestMigrateSuperfluidBondedBalancerToConcentrated() { s.AssertEventEmitted(s.Ctx, gammtypes.TypeEvtPoolExited, 1) s.ValidateMigrateResult( - positionId, balancerPooId, poolIdLeaving, clPoolId, poolIdEntering, - tc.percentOfSharesToMigrate, liquidityMigrated, + positionData.ID, balancerPooId, poolIdLeaving, clPoolId, poolIdEntering, + tc.percentOfSharesToMigrate, positionData.Liquidity, *balancerLock, joinPoolAmt, balancerPoolShareOut, coinsToMigrate, - amount0, amount1, + positionData.Amount0, positionData.Amount1, ) if tc.percentOfSharesToMigrate.Equal(sdk.OneDec()) { @@ -395,7 +395,7 @@ func (s *KeeperTestSuite) TestMigrateSuperfluidBondedBalancerToConcentrated() { concentratedLock, err := lockupKeeper.GetLockByID(s.Ctx, concentratedLockId) s.Require().NoError(err) - s.Require().Equal(liquidityMigrated.TruncateInt().String(), concentratedLock.Coins[0].Amount.String(), "expected %s shares, found %s shares", coinsToMigrate.Amount.String(), concentratedLock.Coins[0].Amount.String()) + s.Require().Equal(positionData.Liquidity.TruncateInt().String(), concentratedLock.Coins[0].Amount.String(), "expected %s shares, found %s shares", coinsToMigrate.Amount.String(), concentratedLock.Coins[0].Amount.String()) s.Require().Equal(balancerLock.Duration, concentratedLock.Duration) s.Require().Equal(balancerLock.EndTime, concentratedLock.EndTime) @@ -472,7 +472,7 @@ func (s *KeeperTestSuite) TestMigrateSuperfluidUnbondingBalancerToConcentrated() } // System under test. - positionId, amount0, amount1, liquidityMigrated, concentratedLockId, poolIdLeaving, poolIdEntering, err := superfluidKeeper.MigrateSuperfluidUnbondingBalancerToConcentrated(s.Ctx, poolJoinAcc, originalGammLockId, coinsToMigrate, synthLockBeforeMigration.SynthDenom, tc.tokenOutMins) + positionData, concentratedLockId, poolIdLeaving, poolIdEntering, err := superfluidKeeper.MigrateSuperfluidUnbondingBalancerToConcentrated(s.Ctx, poolJoinAcc, originalGammLockId, coinsToMigrate, synthLockBeforeMigration.SynthDenom, tc.tokenOutMins) if tc.expectedError != nil { s.Require().Error(err) s.Require().ErrorContains(err, tc.expectedError.Error()) @@ -482,12 +482,12 @@ func (s *KeeperTestSuite) TestMigrateSuperfluidUnbondingBalancerToConcentrated() s.AssertEventEmitted(s.Ctx, gammtypes.TypeEvtPoolExited, 1) s.ValidateMigrateResult( - positionId, balancerPooId, poolIdLeaving, clPoolId, poolIdEntering, - tc.percentOfSharesToMigrate, liquidityMigrated, + positionData.ID, balancerPooId, poolIdLeaving, clPoolId, poolIdEntering, + tc.percentOfSharesToMigrate, positionData.Liquidity, *balancerLock, joinPoolAmt, balancerPoolShareOut, coinsToMigrate, - amount0, amount1, + positionData.Amount0, positionData.Amount1, ) if tc.percentOfSharesToMigrate.Equal(sdk.OneDec()) { @@ -509,7 +509,7 @@ func (s *KeeperTestSuite) TestMigrateSuperfluidUnbondingBalancerToConcentrated() // Check newly created concentrated lock. concentratedLock, err := lockupKeeper.GetLockByID(s.Ctx, concentratedLockId) s.Require().NoError(err) - s.Require().Equal(liquidityMigrated.TruncateInt().String(), concentratedLock.Coins[0].Amount.String(), "expected %s shares, found %s shares", coinsToMigrate.Amount.String(), concentratedLock.Coins[0].Amount.String()) + s.Require().Equal(positionData.Liquidity.TruncateInt().String(), concentratedLock.Coins[0].Amount.String(), "expected %s shares, found %s shares", coinsToMigrate.Amount.String(), concentratedLock.Coins[0].Amount.String()) // If the original lock was not unlocking, then the new lock should have the same duration and end time (regardless of the fact that an hour has passed since the lock began superfluid unbonding). expectedConcentratedLockDuration := balancerLock.Duration expectedConcentratedLockEndTime := s.Ctx.BlockTime().Add(balancerLock.Duration) @@ -580,7 +580,7 @@ func (s *KeeperTestSuite) TestMigrateNonSuperfluidLockBalancerToConcentrated() { s.Require().Equal(migrationType, keeper.NonSuperfluid) // System under test. - positionId, amount0, amount1, liquidityMigrated, concentratedLockId, poolIdLeaving, poolIdEntering, err := superfluidKeeper.MigrateNonSuperfluidLockBalancerToConcentrated(s.Ctx, poolJoinAcc, originalGammLockId, coinsToMigrate, tc.tokenOutMins) + positionData, concentratedLockId, poolIdLeaving, poolIdEntering, err := superfluidKeeper.MigrateNonSuperfluidLockBalancerToConcentrated(s.Ctx, poolJoinAcc, originalGammLockId, coinsToMigrate, tc.tokenOutMins) if tc.expectedError != nil { s.Require().Error(err) s.Require().ErrorContains(err, tc.expectedError.Error()) @@ -590,18 +590,18 @@ func (s *KeeperTestSuite) TestMigrateNonSuperfluidLockBalancerToConcentrated() { s.AssertEventEmitted(s.Ctx, gammtypes.TypeEvtPoolExited, 1) s.ValidateMigrateResult( - positionId, balancerPooId, poolIdLeaving, clPoolId, poolIdEntering, - tc.percentOfSharesToMigrate, liquidityMigrated, + positionData.ID, balancerPooId, poolIdLeaving, clPoolId, poolIdEntering, + tc.percentOfSharesToMigrate, positionData.Liquidity, *balancerLock, joinPoolAmt, balancerPoolShareOut, coinsToMigrate, - amount0, amount1, + positionData.Amount0, positionData.Amount1, ) // Check newly created concentrated lock. concentratedLock, err := lockupKeeper.GetLockByID(s.Ctx, concentratedLockId) s.Require().NoError(err) - s.Require().Equal(liquidityMigrated.TruncateInt().String(), concentratedLock.Coins[0].Amount.String(), "expected %s shares, found %s shares", coinsToMigrate.Amount.String(), concentratedLock.Coins[0].Amount.String()) + s.Require().Equal(positionData.Liquidity.TruncateInt().String(), concentratedLock.Coins[0].Amount.String(), "expected %s shares, found %s shares", coinsToMigrate.Amount.String(), concentratedLock.Coins[0].Amount.String()) s.Require().Equal(balancerLock.Duration, concentratedLock.Duration) s.Require().Equal(s.Ctx.BlockTime().Add(balancerLock.Duration), concentratedLock.EndTime) @@ -663,7 +663,7 @@ func (s *KeeperTestSuite) TestMigrateUnlockedPositionFromBalancerToConcentrated( s.Require().Equal(migrationType, keeper.Unlocked) // System under test. - positionId, amount0, amount1, liquidityMigrated, poolIdLeaving, poolIdEntering, err := gammKeeper.MigrateUnlockedPositionFromBalancerToConcentrated(s.Ctx, poolJoinAcc, coinsToMigrate, tc.tokenOutMins) + positionData, poolIdLeaving, poolIdEntering, err := gammKeeper.MigrateUnlockedPositionFromBalancerToConcentrated(s.Ctx, poolJoinAcc, coinsToMigrate, tc.tokenOutMins) if tc.expectedError != nil { s.Require().ErrorContains(err, tc.expectedError.Error()) return @@ -672,12 +672,12 @@ func (s *KeeperTestSuite) TestMigrateUnlockedPositionFromBalancerToConcentrated( s.AssertEventEmitted(s.Ctx, gammtypes.TypeEvtPoolExited, 1) s.ValidateMigrateResult( - positionId, balancerPooId, poolIdLeaving, clPoolId, poolIdEntering, - tc.percentOfSharesToMigrate, liquidityMigrated, + positionData.ID, balancerPooId, poolIdLeaving, clPoolId, poolIdEntering, + tc.percentOfSharesToMigrate, positionData.Liquidity, *balancerLock, joinPoolAmt, balancerPoolShareOut, coinsToMigrate, - amount0, amount1, + positionData.Amount0, positionData.Amount1, ) }) } @@ -1343,11 +1343,11 @@ func (s *KeeperTestSuite) TestFunctional_VaryingPositions_Migrations() { preClaimBalancerPoolBalance := balancerPool.GetTotalPoolLiquidity(s.Ctx) // Run the migration. - _, amount0, amount1, _, _, _, _, err := s.App.SuperfluidKeeper.RouteLockedBalancerToConcentratedMigration(s.Ctx, s.TestAccs[i+1], int64(posInfo.lockId), posInfo.coin, sdk.Coins{}) + positionData, _, _, _, err := s.App.SuperfluidKeeper.RouteLockedBalancerToConcentratedMigration(s.Ctx, s.TestAccs[i+1], int64(posInfo.lockId), posInfo.coin, sdk.Coins{}) s.Require().NoError(err) // Note how much of amount0 and amount1 was actually created in the CL pool from the migration. - clJoinPoolAmt := sdk.NewCoins(sdk.NewCoin(clPool.GetToken0(), amount0), sdk.NewCoin(clPool.GetToken1(), amount1)) + clJoinPoolAmt := sdk.NewCoins(sdk.NewCoin(clPool.GetToken0(), positionData.Amount0), sdk.NewCoin(clPool.GetToken1(), positionData.Amount1)) // Note owner and balancer pool balances after migration. balancerPool, err = s.App.GAMMKeeper.GetCFMMPool(s.Ctx, balancerPoolId) @@ -1369,8 +1369,8 @@ func (s *KeeperTestSuite) TestFunctional_VaryingPositions_Migrations() { } // Add to the total amounts that were migrated and sent back to the owners. - totalAmount0Migrated = totalAmount0Migrated.Add(amount0) - totalAmount1Migrated = totalAmount1Migrated.Add(amount1) + totalAmount0Migrated = totalAmount0Migrated.Add(positionData.Amount0) + totalAmount1Migrated = totalAmount1Migrated.Add(positionData.Amount1) totalSentBackToOwnersAmount0 = totalSentBackToOwnersAmount0.Add(postClaimOwnerBalance.AmountOf(DefaultCoin0.Denom).Sub(preClaimOwnerBalance.AmountOf(DefaultCoin0.Denom))) totalSentBackToOwnersAmount1 = totalSentBackToOwnersAmount1.Add(postClaimOwnerBalance.AmountOf(DefaultCoin1.Denom).Sub(preClaimOwnerBalance.AmountOf(DefaultCoin1.Denom))) } diff --git a/x/superfluid/keeper/msg_server.go b/x/superfluid/keeper/msg_server.go index c29b02b800b..270e67b2fc3 100644 --- a/x/superfluid/keeper/msg_server.go +++ b/x/superfluid/keeper/msg_server.go @@ -172,7 +172,7 @@ func (server msgServer) CreateFullRangePositionAndSuperfluidDelegate(goCtx conte if err != nil { return &types.MsgCreateFullRangePositionAndSuperfluidDelegateResponse{}, err } - positionId, _, _, _, lockId, err := server.keeper.clk.CreateFullRangePositionLocked(ctx, msg.PoolId, address, msg.Coins, server.keeper.sk.GetParams(ctx).UnbondingTime) + positionData, lockId, err := server.keeper.clk.CreateFullRangePositionLocked(ctx, msg.PoolId, address, msg.Coins, server.keeper.sk.GetParams(ctx).UnbondingTime) if err != nil { return &types.MsgCreateFullRangePositionAndSuperfluidDelegateResponse{}, err } @@ -189,11 +189,11 @@ func (server msgServer) CreateFullRangePositionAndSuperfluidDelegate(goCtx conte return &types.MsgCreateFullRangePositionAndSuperfluidDelegateResponse{}, err } - events.EmitCreateFullRangePositionAndSuperfluidDelegateEvent(ctx, lockId, positionId, msg.ValAddr) + events.EmitCreateFullRangePositionAndSuperfluidDelegateEvent(ctx, lockId, positionData.ID, msg.ValAddr) return &types.MsgCreateFullRangePositionAndSuperfluidDelegateResponse{ LockID: lockId, - PositionID: positionId, + PositionID: positionData.ID, }, nil } @@ -205,7 +205,7 @@ func (server msgServer) UnlockAndMigrateSharesToFullRangeConcentratedPosition(go return nil, err } - positionId, amount0, amount1, liquidity, poolIdLeaving, poolIdEntering, clLockId, err := server.keeper.RouteLockedBalancerToConcentratedMigration(ctx, sender, msg.LockId, msg.SharesToMigrate, msg.TokenOutMins) + positionData, poolIdLeaving, poolIdEntering, clLockId, err := server.keeper.RouteLockedBalancerToConcentratedMigration(ctx, sender, msg.LockId, msg.SharesToMigrate, msg.TokenOutMins) if err != nil { return nil, err } @@ -217,14 +217,14 @@ func (server msgServer) UnlockAndMigrateSharesToFullRangeConcentratedPosition(go sdk.NewAttribute(types.AttributeKeyPoolIdLeaving, strconv.FormatUint(poolIdLeaving, 10)), sdk.NewAttribute(types.AttributeConcentratedLockId, strconv.FormatUint(clLockId, 10)), sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), - sdk.NewAttribute(types.AttributePositionId, strconv.FormatUint(positionId, 10)), - sdk.NewAttribute(types.AttributeAmount0, amount0.String()), - sdk.NewAttribute(types.AttributeAmount1, amount1.String()), - sdk.NewAttribute(types.AttributeLiquidity, liquidity.String()), + sdk.NewAttribute(types.AttributePositionId, strconv.FormatUint(positionData.ID, 10)), + sdk.NewAttribute(types.AttributeAmount0, positionData.Amount0.String()), + sdk.NewAttribute(types.AttributeAmount1, positionData.Amount1.String()), + sdk.NewAttribute(types.AttributeLiquidity, positionData.Liquidity.String()), ), }) - return &types.MsgUnlockAndMigrateSharesToFullRangeConcentratedPositionResponse{Amount0: amount0, Amount1: amount1, LiquidityCreated: liquidity}, err + return &types.MsgUnlockAndMigrateSharesToFullRangeConcentratedPositionResponse{Amount0: positionData.Amount0, Amount1: positionData.Amount1, LiquidityCreated: positionData.Liquidity}, err } func (server msgServer) AddToConcentratedLiquiditySuperfluidPosition(goCtx context.Context, msg *types.MsgAddToConcentratedLiquiditySuperfluidPosition) (*types.MsgAddToConcentratedLiquiditySuperfluidPositionResponse, error) { @@ -235,10 +235,10 @@ func (server msgServer) AddToConcentratedLiquiditySuperfluidPosition(goCtx conte return nil, err } - newPositionId, actualAmount0, actualAmount1, newLiquidity, newLockId, err := server.keeper.addToConcentratedLiquiditySuperfluidPosition(ctx, sender, msg.PositionId, msg.TokenDesired0.Amount, msg.TokenDesired1.Amount) + positionData, newLockId, err := server.keeper.addToConcentratedLiquiditySuperfluidPosition(ctx, sender, msg.PositionId, msg.TokenDesired0.Amount, msg.TokenDesired1.Amount) if err != nil { return nil, err } - return &types.MsgAddToConcentratedLiquiditySuperfluidPositionResponse{PositionId: newPositionId, Amount0: actualAmount0, Amount1: actualAmount1, LockId: newLockId, NewLiquidity: newLiquidity}, nil + return &types.MsgAddToConcentratedLiquiditySuperfluidPositionResponse{PositionId: positionData.ID, Amount0: positionData.Amount0, Amount1: positionData.Amount1, LockId: newLockId, NewLiquidity: positionData.Liquidity}, nil } diff --git a/x/superfluid/keeper/msg_server_test.go b/x/superfluid/keeper/msg_server_test.go index ae32057f71d..652c06b1c37 100644 --- a/x/superfluid/keeper/msg_server_test.go +++ b/x/superfluid/keeper/msg_server_test.go @@ -564,7 +564,7 @@ func (s *KeeperTestSuite) TestAddToConcentratedLiquiditySuperfluidPosition_Event if !tc.isLastPositionInPool { s.FundAcc(s.TestAccs[1], defaultFunds) - _, _, _, _, err := concentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, 1, s.TestAccs[1], defaultFunds) + _, err := concentratedLiquidityKeeper.CreateFullRangePosition(s.Ctx, 1, s.TestAccs[1], defaultFunds) s.Require().NoError(err) } diff --git a/x/superfluid/types/expected_keepers.go b/x/superfluid/types/expected_keepers.go index 9bb7b76d92f..ea5538b1967 100644 --- a/x/superfluid/types/expected_keepers.go +++ b/x/superfluid/types/expected_keepers.go @@ -56,7 +56,7 @@ type GammKeeper interface { ExitPool(ctx sdk.Context, sender sdk.AccAddress, poolId uint64, shareInAmount sdk.Int, tokenOutMins sdk.Coins) (exitCoins sdk.Coins, err error) GetAllMigrationInfo(ctx sdk.Context) (gammmigration.MigrationRecords, error) GetLinkedConcentratedPoolID(ctx sdk.Context, poolIdLeaving uint64) (poolIdEntering uint64, err error) - MigrateUnlockedPositionFromBalancerToConcentrated(ctx sdk.Context, sender sdk.AccAddress, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, poolIdLeaving, poolIdEntering uint64, err error) + MigrateUnlockedPositionFromBalancerToConcentrated(ctx sdk.Context, sender sdk.AccAddress, sharesToMigrate sdk.Coin, tokenOutMins sdk.Coins) (positionData cltypes.CreateFullRangePositionData, poolIdLeaving, poolIdEntering uint64, err error) } type BankKeeper interface { @@ -111,8 +111,8 @@ type ConcentratedKeeper interface { SetPosition(ctx sdk.Context, poolId uint64, owner sdk.AccAddress, lowerTick, upperTick int64, joinTime time.Time, liquidity sdk.Dec, positionId uint64, underlyingLockId uint64) error UpdatePosition(ctx sdk.Context, poolId uint64, owner sdk.AccAddress, lowerTick, upperTick int64, liquidityDelta sdk.Dec, joinTime time.Time, positionId uint64) (sdk.Int, sdk.Int, bool, bool, error) GetConcentratedPoolById(ctx sdk.Context, poolId uint64) (cltypes.ConcentratedPoolExtension, error) - CreateFullRangePositionLocked(ctx sdk.Context, clPoolId uint64, owner sdk.AccAddress, coins sdk.Coins, remainingLockDuration time.Duration) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, concentratedLockID uint64, err error) - CreateFullRangePositionUnlocking(ctx sdk.Context, clPoolId uint64, owner sdk.AccAddress, coins sdk.Coins, remainingLockDuration time.Duration) (positionId uint64, amount0, amount1 sdk.Int, liquidity sdk.Dec, concentratedLockID uint64, err error) + CreateFullRangePositionLocked(ctx sdk.Context, clPoolId uint64, owner sdk.AccAddress, coins sdk.Coins, remainingLockDuration time.Duration) (positionData cltypes.CreateFullRangePositionData, concentratedLockID uint64, err error) + CreateFullRangePositionUnlocking(ctx sdk.Context, clPoolId uint64, owner sdk.AccAddress, coins sdk.Coins, remainingLockDuration time.Duration) (positionData cltypes.CreateFullRangePositionData, concentratedLockID uint64, err error) GetPositionIdToLockId(ctx sdk.Context, underlyingLockId uint64) (uint64, error) GetFullRangeLiquidityInPool(ctx sdk.Context, poolId uint64) (sdk.Dec, error) PositionHasActiveUnderlyingLock(ctx sdk.Context, positionId uint64) (bool, uint64, error)