From 7ec3d7754a96735c1ec4f9b6f16ac58a5016bff4 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Thu, 3 Aug 2023 21:52:15 -0500 Subject: [PATCH 01/41] multi-network upgrade handler --- app/upgrades/v17/upgrades.go | 274 ++++++++++++++++++++++-------- app/upgrades/v17/upgrades_test.go | 211 ++++++++++++++++++++++- 2 files changed, 415 insertions(+), 70 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index f01cb002a83..945e97095fa 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -12,6 +12,7 @@ import ( cltypes "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" gammmigration "github.com/osmosis-labs/osmosis/v17/x/gamm/types/migration" + poolManagerTypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" superfluidtypes "github.com/osmosis-labs/osmosis/v17/x/superfluid/types" "github.com/osmosis-labs/osmosis/v17/app/keepers" @@ -19,6 +20,14 @@ import ( "github.com/osmosis-labs/osmosis/v17/x/protorev/types" ) +const ( + mainnetChainID = "osmosis-1" + balancerWeight = 1 + stableWeight = 4 + concentratedWeight = 300 + cosmwasmWeight = 300 +) + func CreateUpgradeHandler( mm *module.Manager, configurator module.Configurator, @@ -26,6 +35,9 @@ func CreateUpgradeHandler( keepers *keepers.AppKeepers, ) upgradetypes.UpgradeHandler { return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + poolLinks := []gammmigration.BalancerToConcentratedPoolLink{} + fullRangeCoinsUsed := sdk.Coins{} + // Run migrations before applying any other state changes. // NOTE: DO NOT PUT ANY STATE CHANGES BEFORE RunMigrations(). migrations, err := mm.RunMigrations(ctx, configurator, fromVM) @@ -33,73 +45,19 @@ func CreateUpgradeHandler( return nil, err } - // Get community pool address. communityPoolAddress := keepers.AccountKeeper.GetModuleAddress(distrtypes.ModuleName) - // fullRangeCoinsUsed tracks the coins we use in the below for loop from the community pool to create the full range position for each new pool. - fullRangeCoinsUsed := sdk.NewCoins() - - poolLinks := []gammmigration.BalancerToConcentratedPoolLink{} - - assetPairs := InitializeAssetPairs(ctx, keepers) - - for _, assetPair := range assetPairs { - // Create a concentrated liquidity pool for asset pair. - clPool, err := keepers.GAMMKeeper.CreateConcentratedPoolFromCFMM(ctx, assetPair.LinkedClassicPool, assetPair.BaseAsset, assetPair.SpreadFactor, TickSpacing) - if err != nil { - return nil, err - } - clPoolId := clPool.GetId() - clPoolDenom := cltypes.GetConcentratedLockupDenomFromPoolId(clPoolId) - - // Add the pool link to the list of pool links (we set them all at once later) - poolLinks = append(poolLinks, gammmigration.BalancerToConcentratedPoolLink{ - BalancerPoolId: assetPair.LinkedClassicPool, - ClPoolId: clPoolId, - }) - - // Determine the amount of baseAsset that can be bought with 1 OSMO. - oneOsmo := sdk.NewCoin(QuoteAsset, sdk.NewInt(1000000)) - linkedClassicPool, err := keepers.PoolManagerKeeper.GetPool(ctx, assetPair.LinkedClassicPool) - if err != nil { - return nil, err - } - respectiveBaseAsset, err := keepers.GAMMKeeper.CalcOutAmtGivenIn(ctx, linkedClassicPool, oneOsmo, assetPair.BaseAsset, sdk.ZeroDec()) - if err != nil { - return nil, err - } - - // 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) - 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))...) - - // If pair was previously superfluid enabled, add the cl pool's full range denom as an authorized superfluid asset. - if assetPair.Superfluid { - superfluidAsset := superfluidtypes.SuperfluidAsset{ - Denom: clPoolDenom, - AssetType: superfluidtypes.SuperfluidAssetTypeConcentratedShare, - } - err = keepers.SuperfluidKeeper.AddNewSuperfluidAsset(ctx, superfluidAsset) - if err != nil { - return nil, err - } - } - - clPoolTwapRecords, err := keepers.TwapKeeper.GetAllMostRecentRecordsForPool(ctx, clPoolId) - if err != nil { - return nil, err - } - - for _, twapRecord := range clPoolTwapRecords { - twapRecord.LastErrorTime = time.Time{} - keepers.TwapKeeper.StoreNewRecord(ctx, twapRecord) - } + if ctx.ChainID() == mainnetChainID { + // Upgrades specific balancer pools to concentrated liquidity pools and links them to their CL equivalent. + ctx.Logger().Info("Chain ID is %s, running mainnet upgrade handler", ctx.ChainID()) + err = mainnetUpgradeHandler(ctx, keepers, communityPoolAddress, &poolLinks, &fullRangeCoinsUsed) + } else { + // Upgrades all existing balancer pools to concentrated liquidity pools and links them to their CL equivalent. + ctx.Logger().Info("Chain ID is %s, running testnet upgrade handler", ctx.ChainID()) + err = testnetUpgradeHandler(ctx, keepers, communityPoolAddress, &poolLinks, &fullRangeCoinsUsed) + } + if err != nil { + return nil, err } // Set the migration links in x/gamm. @@ -124,12 +82,190 @@ func CreateUpgradeHandler( // Reset the pool weights upon upgrade. This will add support for CW pools on ProtoRev. keepers.ProtoRevKeeper.SetPoolWeights(ctx, types.PoolWeights{ - BalancerWeight: 1, - StableWeight: 4, - ConcentratedWeight: 300, - CosmwasmWeight: 300, + BalancerWeight: balancerWeight, + StableWeight: stableWeight, + ConcentratedWeight: concentratedWeight, + CosmwasmWeight: cosmwasmWeight, }) return migrations, nil } } + +// mainnetUpgradeHandler creates CL pools for all balancer pools defined in the asset pairs struct. It also links the CL pools to their balancer pool counterpart, creates a full range position with the community pool, +// authorizes superfluid for the CL pool if the balancer pool is superfluid enabled, and manually sets the TWAP records for the CL pool. +func mainnetUpgradeHandler(ctx sdk.Context, keepers *keepers.AppKeepers, communityPoolAddress sdk.AccAddress, poolLinks *[]gammmigration.BalancerToConcentratedPoolLink, fullRangeCoinsUsed *sdk.Coins) error { + assetPairs := InitializeAssetPairs(ctx, keepers) + + for _, assetPair := range assetPairs { + clPoolDenom, clPoolId, err := createCLPoolWithCommunityPoolPosition(ctx, keepers, assetPair.LinkedClassicPool, assetPair.BaseAsset, assetPair.SpreadFactor, communityPoolAddress, poolLinks, fullRangeCoinsUsed) + if err != nil { + return err + } + + err = authorizeSuperfluidIfEnabled(ctx, keepers, assetPair.LinkedClassicPool, clPoolDenom) + if err != nil { + return err + } + + err = manuallySetTWAPRecords(ctx, keepers, clPoolId) + if err != nil { + return err + } + } + + return nil +} + +// testnetUpgradeHandler creates CL pools for all existing balancer pools. It also links the CL pools to their balancer pool counterpart, creates a full range position with the community pool, +// authorizes superfluid for the CL pool if the balancer pool is superfluid enabled, and manually sets the TWAP records for the CL pool. +func testnetUpgradeHandler(ctx sdk.Context, keepers *keepers.AppKeepers, communityPoolAddress sdk.AccAddress, poolLinks *[]gammmigration.BalancerToConcentratedPoolLink, fullRangeCoinsUsed *sdk.Coins) error { + // Retrieve all GAMM pools on the testnet. + pools, err := keepers.GAMMKeeper.GetPools(ctx) + if err != nil { + return err + } + + for _, pool := range pools { + skipPool, gammPoolId, baseAsset, spreadFactor, err := testnetParsePoolRecord(ctx, pool, keepers) + if err != nil { + return err + } + if skipPool { + continue + } + + clPoolDenom, clPoolId, err := createCLPoolWithCommunityPoolPosition(ctx, keepers, gammPoolId, baseAsset, spreadFactor, communityPoolAddress, poolLinks, fullRangeCoinsUsed) + if err != nil { + return err + } + + err = authorizeSuperfluidIfEnabled(ctx, keepers, gammPoolId, clPoolDenom) + if err != nil { + return err + } + + err = manuallySetTWAPRecords(ctx, keepers, clPoolId) + if err != nil { + return err + } + } + return nil +} + +// createCLPoolWithCommunityPoolPosition creates a CL pool for a given balancer pool and adds a full range position with the community pool. +// There must be 1 OSMO worth baseAsset in the community pool for this to work. +func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.AppKeepers, gammPoolId uint64, baseAsset string, spreadFactor sdk.Dec, communityPoolAddress sdk.AccAddress, poolLinks *[]gammmigration.BalancerToConcentratedPoolLink, fullRangeCoinsUsed *sdk.Coins) (clPoolDenom string, clPoolId uint64, err error) { + // Create a concentrated liquidity pool for asset pair. + clPool, err := keepers.GAMMKeeper.CreateConcentratedPoolFromCFMM(ctx, gammPoolId, baseAsset, spreadFactor, TickSpacing) + if err != nil { + return "", 0, err + } + clPoolId = clPool.GetId() + clPoolDenom = cltypes.GetConcentratedLockupDenomFromPoolId(clPoolId) + + // Add the pool link to the list of pool links (we set them all at once later) + *poolLinks = append(*poolLinks, gammmigration.BalancerToConcentratedPoolLink{ + BalancerPoolId: gammPoolId, + ClPoolId: clPoolId, + }) + + // Determine the amount of baseAsset that can be bought with 1 OSMO. + oneOsmo := sdk.NewCoin(QuoteAsset, sdk.NewInt(1000000)) + linkedClassicPool, err := keepers.PoolManagerKeeper.GetPool(ctx, gammPoolId) + if err != nil { + return "", 0, err + } + respectiveBaseAsset, err := keepers.GAMMKeeper.CalcOutAmtGivenIn(ctx, linkedClassicPool, oneOsmo, baseAsset, sdk.ZeroDec()) + if err != nil { + return "", 0, err + } + + // 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) + if err != nil { + return "", 0, 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(baseAsset, actualBaseAmtUsed))...) + + return clPoolDenom, clPoolId, nil +} + +// authorizeSuperfluidIfEnabled authorizes superfluid for a CL pool if the balancer pool is superfluid enabled. +func authorizeSuperfluidIfEnabled(ctx sdk.Context, keepers *keepers.AppKeepers, gammPoolId uint64, clPoolDenom string) (err error) { + // If pair was previously superfluid enabled, add the cl pool's full range denom as an authorized superfluid asset. + poolShareDenom := fmt.Sprintf("gamm/pool/%d", gammPoolId) + _, err = keepers.SuperfluidKeeper.GetSuperfluidAsset(ctx, poolShareDenom) + if err == nil { + superfluidAsset := superfluidtypes.SuperfluidAsset{ + Denom: clPoolDenom, + AssetType: superfluidtypes.SuperfluidAssetTypeConcentratedShare, + } + err = keepers.SuperfluidKeeper.AddNewSuperfluidAsset(ctx, superfluidAsset) + if err != nil { + return err + } + } + return nil +} + +// manuallySetTWAPRecords manually sets the TWAP records for a CL pool. This prevents a panic when the CL pool is first used. +func manuallySetTWAPRecords(ctx sdk.Context, keepers *keepers.AppKeepers, clPoolId uint64) error { + clPoolTwapRecords, err := keepers.TwapKeeper.GetAllMostRecentRecordsForPool(ctx, clPoolId) + if err != nil { + return err + } + + for _, twapRecord := range clPoolTwapRecords { + twapRecord.LastErrorTime = time.Time{} + keepers.TwapKeeper.StoreNewRecord(ctx, twapRecord) + } + return nil +} + +// testnetParsePoolRecord parses a pool record and returns whether or not to skip the pool, the pool's gammPoolId, the pool's base asset, and the pool's spread factor. +func testnetParsePoolRecord(ctx sdk.Context, pool poolManagerTypes.PoolI, keepers *keepers.AppKeepers) (bool, uint64, string, sdk.Dec, error) { + // We only want to upgrade balancer pools. + if pool.GetType() != poolManagerTypes.Balancer { + return true, 0, "", sdk.Dec{}, nil + } + + gammPoolId := pool.GetId() + cfmmPool, err := keepers.GAMMKeeper.GetCFMMPool(ctx, gammPoolId) + if err != nil { + return true, 0, "", sdk.Dec{}, err + } + + poolCoins := cfmmPool.GetTotalPoolLiquidity(ctx) + + // We only want to upgrade pools paired with OSMO. OSMO will be the quote asset. + quoteAsset, baseAsset := "", "" + for _, coin := range poolCoins { + if coin.Denom == QuoteAsset { + quoteAsset = coin.Denom + } else { + baseAsset = coin.Denom + } + } + if quoteAsset == "" || baseAsset == "" { + return true, 0, "", sdk.Dec{}, nil + } + + // Set the spread factor to the same spread factor the GAMM pool was. + // If its spread factor is not authorized, set it to the first authorized spread factor. + spreadFactor := cfmmPool.GetSpreadFactor(ctx) + authorizedSpreadFactors := keepers.ConcentratedLiquidityKeeper.GetParams(ctx).AuthorizedSpreadFactors + spreadFactorAuthorized := false + for _, authorizedSpreadFactor := range authorizedSpreadFactors { + if authorizedSpreadFactor == spreadFactor { + spreadFactorAuthorized = true + } + } + if !spreadFactorAuthorized { + spreadFactor = authorizedSpreadFactors[0] + } + return false, gammPoolId, baseAsset, spreadFactor, nil +} diff --git a/app/upgrades/v17/upgrades_test.go b/app/upgrades/v17/upgrades_test.go index 20f72d2f832..fa924a5d10a 100644 --- a/app/upgrades/v17/upgrades_test.go +++ b/app/upgrades/v17/upgrades_test.go @@ -18,7 +18,9 @@ import ( "github.com/osmosis-labs/osmosis/v17/app/keepers" v17 "github.com/osmosis-labs/osmosis/v17/app/upgrades/v17" cltypes "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" + poolManagerTypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" poolmanagertypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" + superfluidtypes "github.com/osmosis-labs/osmosis/v17/x/superfluid/types" ) type UpgradeTestSuite struct { @@ -74,7 +76,7 @@ func (suite *UpgradeTestSuite) TestUpgrade() { upgrade func(sdk.Context, *keepers.AppKeepers, sdk.Coins, uint64) }{ { - "Test that the upgrade succeeds", + "Test that the upgrade succeeds: mainnet", func(ctx sdk.Context, keepers *keepers.AppKeepers) (sdk.Coins, uint64) { upgradeSetup() @@ -121,6 +123,16 @@ func (suite *UpgradeTestSuite) TestUpgrade() { // Add the amount of baseAsset that will be used to the expectedCoinsUsedInUpgradeHandler. expectedCoinsUsedInUpgradeHandler = expectedCoinsUsedInUpgradeHandler.Add(respectiveBaseAsset) + // Enable the GAMM pool for superfluid if the record says so. + if assetPair.Superfluid { + poolShareDenom := fmt.Sprintf("gamm/pool/%d", assetPair.LinkedClassicPool) + superfluidAsset := superfluidtypes.SuperfluidAsset{ + Denom: poolShareDenom, + AssetType: superfluidtypes.SuperfluidAssetTypeLPShare, + } + suite.App.SuperfluidKeeper.SetSuperfluidAsset(suite.Ctx, superfluidAsset) + } + // Update the lastPoolID to the current pool ID. lastPoolID = poolID } @@ -137,6 +149,8 @@ func (suite *UpgradeTestSuite) TestUpgrade() { communityPoolAddress := suite.App.AccountKeeper.GetModuleAddress(distrtypes.ModuleName) communityPoolBalancePre := suite.App.BankKeeper.GetAllBalances(suite.Ctx, communityPoolAddress) + numPoolPreUpgrade := suite.App.PoolManagerKeeper.GetNextPoolId(suite.Ctx) - 1 + // Run upgrade handler. dummyUpgrade(suite) suite.Require().NotPanics(func() { @@ -192,6 +206,11 @@ func (suite *UpgradeTestSuite) TestUpgrade() { lastPoolID++ } + numPoolPostUpgrade := suite.App.PoolManagerKeeper.GetNextPoolId(suite.Ctx) - 1 + + // Number of pools created should be equal to the number of records in the asset pairs. + suite.Require().Equal(len(assetPairs), int(numPoolPostUpgrade-numPoolPreUpgrade)) + // Check osmo balance (was used in every pool creation) suite.Require().Equal(0, multiplicativeTolerance.Compare(communityPoolBalancePre.AmountOf(v17.QuoteAsset), communityPoolBalancePost.AmountOf(v17.QuoteAsset).Sub(expectedCoinsUsedInUpgradeHandler.AmountOf(v17.QuoteAsset)))) suite.Require().Equal(communityPoolBalancePost.AmountOf(v17.QuoteAsset).String(), feePoolCommunityPoolPost.AmountOf(v17.QuoteAsset).TruncateInt().String()) @@ -203,6 +222,196 @@ func (suite *UpgradeTestSuite) TestUpgrade() { }, }, + { + "Test that the upgrade succeeds: testnet", + func(ctx sdk.Context, keepers *keepers.AppKeepers) (sdk.Coins, uint64) { + upgradeSetup() + suite.Ctx = suite.Ctx.WithChainID("osmo-test-5") + + var lastPoolID uint64 // To keep track of the last assigned pool ID + + sort.Sort(ByLinkedClassicPool(v17.AssetPairsForTestsOnly)) + sort.Sort(ByLinkedClassicPool(v17.AssetPairs)) + + expectedCoinsUsedInUpgradeHandler := sdk.NewCoins() + + // Create earlier pools or dummy pools if needed + for _, assetPair := range v17.AssetPairsForTestsOnly { + poolID := assetPair.LinkedClassicPool + + // For testnet, we create a CL pool for ANY balancer pool. + // The only thing we use the assetPair list here for to select some pools to enable superfluid for. + for lastPoolID+1 < poolID { + poolCoins := sdk.NewCoins(sdk.NewCoin(assetPair.BaseAsset, sdk.NewInt(10000000000)), sdk.NewCoin(v17.QuoteAsset, sdk.NewInt(10000000000))) + poolId := suite.PrepareBalancerPoolWithCoins(poolCoins...) + + // Send two of the base asset to the community pool. + twoBaseAsset := sdk.NewCoins(sdk.NewCoin(assetPair.BaseAsset, sdk.NewInt(2000000))) + suite.FundAcc(suite.TestAccs[0], twoBaseAsset) + err := suite.App.DistrKeeper.FundCommunityPool(suite.Ctx, twoBaseAsset, suite.TestAccs[0]) + suite.Require().NoError(err) + + // Determine approx how much baseAsset will be used from community pool when 1 OSMO used. + oneOsmo := sdk.NewCoin(v17.QuoteAsset, sdk.NewInt(1000000)) + pool, err := suite.App.PoolManagerKeeper.GetPool(suite.Ctx, poolId) + suite.Require().NoError(err) + respectiveBaseAsset, err := suite.App.GAMMKeeper.CalcOutAmtGivenIn(suite.Ctx, pool, oneOsmo, assetPair.BaseAsset, sdk.ZeroDec()) + suite.Require().NoError(err) + + // Add the amount of baseAsset that will be used to the expectedCoinsUsedInUpgradeHandler. + expectedCoinsUsedInUpgradeHandler = expectedCoinsUsedInUpgradeHandler.Add(respectiveBaseAsset) + + lastPoolID++ + } + + // Enable the GAMM pool for superfluid if the asset pair is marked as superfluid. + if assetPair.Superfluid { + poolShareDenom := fmt.Sprintf("gamm/pool/%d", assetPair.LinkedClassicPool) + superfluidAsset := superfluidtypes.SuperfluidAsset{ + Denom: poolShareDenom, + AssetType: superfluidtypes.SuperfluidAssetTypeLPShare, + } + suite.App.SuperfluidKeeper.SetSuperfluidAsset(suite.Ctx, superfluidAsset) + } + } + + // We now create various pools that are not balancer pools. + // This is to test if the testnet upgrade handler properly handles pools that are not of type balancer (i.e. should ignore them and move on). + + // Stableswap pool + suite.CreatePoolFromType(poolmanagertypes.Stableswap) + // Cosmwasm pool + suite.CreatePoolFromType(poolmanagertypes.CosmWasm) + // CL pool + suite.CreatePoolFromType(poolmanagertypes.Concentrated) + + lastPoolID += 3 + + return expectedCoinsUsedInUpgradeHandler, lastPoolID + + }, + func(ctx sdk.Context, keepers *keepers.AppKeepers, expectedCoinsUsedInUpgradeHandler sdk.Coins, lastPoolID uint64) { + stakingParams := suite.App.StakingKeeper.GetParams(suite.Ctx) + stakingParams.BondDenom = "uosmo" + suite.App.StakingKeeper.SetParams(suite.Ctx, stakingParams) + + // Retrieve the community pool balance before the upgrade + communityPoolAddress := suite.App.AccountKeeper.GetModuleAddress(distrtypes.ModuleName) + communityPoolBalancePre := suite.App.BankKeeper.GetAllBalances(suite.Ctx, communityPoolAddress) + + numPoolPreUpgrade := suite.App.PoolManagerKeeper.GetNextPoolId(suite.Ctx) - 1 + + gammPoolsPreUpgrade, err := suite.App.GAMMKeeper.GetPools(suite.Ctx) + suite.Require().NoError(err) + + // Run upgrade handler. + dummyUpgrade(suite) + suite.Require().NotPanics(func() { + suite.App.BeginBlocker(suite.Ctx, abci.RequestBeginBlock{}) + }) + + // Retrieve the community pool balance (and the feePool balance) after the upgrade + communityPoolBalancePost := suite.App.BankKeeper.GetAllBalances(suite.Ctx, communityPoolAddress) + feePoolCommunityPoolPost := suite.App.DistrKeeper.GetFeePool(suite.Ctx).CommunityPool + + indexOffset := int(0) + assetListIndex := int(0) + + // For testnet, we run through all gamm pools (not just the asset list) + for i, pool := range gammPoolsPreUpgrade { + // Skip pools that are not balancer pools + if pool.GetType() != poolManagerTypes.Balancer { + indexOffset++ + continue + } + + gammPoolId := pool.GetId() + cfmmPool, err := keepers.GAMMKeeper.GetCFMMPool(ctx, gammPoolId) + suite.Require().NoError(err) + + poolCoins := cfmmPool.GetTotalPoolLiquidity(ctx) + + // Retrieve quoteAsset and baseAsset from the poolCoins + quoteAsset, baseAsset := "", "" + for _, coin := range poolCoins { + if coin.Denom == v17.QuoteAsset { + quoteAsset = coin.Denom + } else { + baseAsset = coin.Denom + } + } + if quoteAsset == "" || baseAsset == "" { + indexOffset++ + continue + } + + // Validate that the community pool balance has been reduced by the amount of baseAsset that was used to create the pool. + suite.Require().Equal(communityPoolBalancePre.AmountOf(baseAsset).Sub(expectedCoinsUsedInUpgradeHandler.AmountOf(baseAsset)).String(), communityPoolBalancePost.AmountOf(baseAsset).String()) + + // Validate that the fee pool community pool balance has been decreased by the amount of baseAsset that was used to create the pool. + suite.Require().Equal(communityPoolBalancePost.AmountOf(baseAsset).String(), feePoolCommunityPoolPost.AmountOf(baseAsset).TruncateInt().String()) + + // Get balancer pool's spot price. + balancerSpotPrice, err := suite.App.GAMMKeeper.CalculateSpotPrice(suite.Ctx, gammPoolId, v17.QuoteAsset, baseAsset) + suite.Require().NoError(err) + + // Validate CL pool was created. + concentratedPool, err := suite.App.PoolManagerKeeper.GetPool(suite.Ctx, lastPoolID+1) + suite.Require().NoError(err) + suite.Require().Equal(poolmanagertypes.Concentrated, concentratedPool.GetType()) + + // Validate that denom0 and denom1 were set correctly + concentratedTypePool, ok := concentratedPool.(cltypes.ConcentratedPoolExtension) + suite.Require().True(ok) + suite.Require().Equal(baseAsset, concentratedTypePool.GetToken0()) + suite.Require().Equal(v17.QuoteAsset, concentratedTypePool.GetToken1()) + + // Validate that the spot price of the CL pool is what we expect + suite.Require().Equal(0, multiplicativeTolerance.CompareBigDec(concentratedTypePool.GetCurrentSqrtPrice().PowerInteger(2), osmomath.BigDecFromSDKDec(balancerSpotPrice))) + + // Validate that the link is correct. + migrationInfo, err := suite.App.GAMMKeeper.GetAllMigrationInfo(suite.Ctx) + link := migrationInfo.BalancerToConcentratedPoolLinks[i-indexOffset] + suite.Require().Equal(gammPoolId, link.BalancerPoolId) + suite.Require().Equal(concentratedPool.GetId(), link.ClPoolId) + + // Validate the sfs status. + // If the poolId matches a poolId on that asset list that had superfluid enabled, this pool should also be superfluid enabled. + // Otherwise, it should not be superfluid enabled. + assetListPoolId := v17.AssetPairsForTestsOnly[assetListIndex].LinkedClassicPool + clPoolDenom := cltypes.GetConcentratedLockupDenomFromPoolId(concentratedPool.GetId()) + _, err = suite.App.SuperfluidKeeper.GetSuperfluidAsset(suite.Ctx, clPoolDenom) + if assetListPoolId == gammPoolId { + suite.Require().NoError(err) + assetListIndex++ + for assetListIndex < len(v17.AssetPairsForTestsOnly)-1 && v17.AssetPairsForTestsOnly[assetListIndex].Superfluid == false { + assetListIndex++ + } + } else { + suite.Require().Error(err) + } + + lastPoolID++ + } + + numPoolPostUpgrade := suite.App.PoolManagerKeeper.GetNextPoolId(suite.Ctx) - 1 + numPoolsCreated := numPoolPostUpgrade - numPoolPreUpgrade + + // Number of pools created should be equal to the number of pools preUpgrade minus the number of pools that were not eligible for migration. + numPoolsEligibleForMigration := numPoolPreUpgrade - 3 + suite.Require().Equal(int(numPoolsEligibleForMigration), int(numPoolsCreated)) + + // Check osmo balance (was used in every pool creation) + suite.Require().Equal(0, multiplicativeTolerance.Compare(communityPoolBalancePre.AmountOf(v17.QuoteAsset), communityPoolBalancePost.AmountOf(v17.QuoteAsset).Sub(expectedCoinsUsedInUpgradeHandler.AmountOf(v17.QuoteAsset)))) + suite.Require().Equal(communityPoolBalancePost.AmountOf(v17.QuoteAsset).String(), feePoolCommunityPoolPost.AmountOf(v17.QuoteAsset).TruncateInt().String()) + + //Validate that all links were created. + migrationInfo, err := suite.App.GAMMKeeper.GetAllMigrationInfo(suite.Ctx) + suite.Require().Equal(int(numPoolsEligibleForMigration), len(migrationInfo.BalancerToConcentratedPoolLinks)) + suite.Require().NoError(err) + + }, + }, { "Fails because CFMM pool is not found", func(ctx sdk.Context, keepers *keepers.AppKeepers) (sdk.Coins, uint64) { From 3e0650a2e9a69efb3f54504d17960acc2d256e1a Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Thu, 3 Aug 2023 22:30:47 -0500 Subject: [PATCH 02/41] run mainnet upgrade handler for e2e network IDs --- app/upgrades/v17/upgrades.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 945e97095fa..222a028d424 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -22,6 +22,8 @@ import ( const ( mainnetChainID = "osmosis-1" + e2eChainA = "osmo-test-a" + e2eChainB = "osmo-test-b" balancerWeight = 1 stableWeight = 4 concentratedWeight = 300 @@ -47,13 +49,13 @@ func CreateUpgradeHandler( communityPoolAddress := keepers.AccountKeeper.GetModuleAddress(distrtypes.ModuleName) - if ctx.ChainID() == mainnetChainID { + if ctx.ChainID() == mainnetChainID || ctx.ChainID() == e2eChainA || ctx.ChainID() == e2eChainB { // Upgrades specific balancer pools to concentrated liquidity pools and links them to their CL equivalent. - ctx.Logger().Info("Chain ID is %s, running mainnet upgrade handler", ctx.ChainID()) + ctx.Logger().Info(fmt.Sprintf("Chain ID is %s, running mainnet upgrade handler", ctx.ChainID())) err = mainnetUpgradeHandler(ctx, keepers, communityPoolAddress, &poolLinks, &fullRangeCoinsUsed) } else { // Upgrades all existing balancer pools to concentrated liquidity pools and links them to their CL equivalent. - ctx.Logger().Info("Chain ID is %s, running testnet upgrade handler", ctx.ChainID()) + ctx.Logger().Info(fmt.Sprintf("Chain ID is %s, running testnet upgrade handler", ctx.ChainID())) err = testnetUpgradeHandler(ctx, keepers, communityPoolAddress, &poolLinks, &fullRangeCoinsUsed) } if err != nil { From c697de22d5a526cc5dd39f503f0f725c07e1a214 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 4 Aug 2023 11:09:38 -0500 Subject: [PATCH 03/41] fixes --- app/upgrades/v17/upgrades.go | 21 ++++++++++++--------- tests/e2e/configurer/chain/commands.go | 2 +- tests/e2e/containers/config.go | 4 ++-- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 222a028d424..d1216ea361a 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -172,26 +172,28 @@ func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.App ClPoolId: clPoolId, }) - // Determine the amount of baseAsset that can be bought with 1 OSMO. - oneOsmo := sdk.NewCoin(QuoteAsset, sdk.NewInt(1000000)) + // Swap 0.1 OSMO for baseAsset from the community pool. + osmoIn := sdk.NewCoin(QuoteAsset, sdk.NewInt(100000)) linkedClassicPool, err := keepers.PoolManagerKeeper.GetPool(ctx, gammPoolId) if err != nil { return "", 0, err } - respectiveBaseAsset, err := keepers.GAMMKeeper.CalcOutAmtGivenIn(ctx, linkedClassicPool, oneOsmo, baseAsset, sdk.ZeroDec()) + respectiveBaseAssetInt, err := keepers.GAMMKeeper.SwapExactAmountIn(ctx, communityPoolAddress, linkedClassicPool, osmoIn, baseAsset, sdk.ZeroInt(), linkedClassicPool.GetSpreadFactor(ctx)) if err != nil { return "", 0, err } + respectiveBaseAsset := sdk.NewCoin(baseAsset, respectiveBaseAssetInt) + // 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) + fullRangeCoins := sdk.NewCoins(respectiveBaseAsset, osmoIn) + _, _, _, _, err = keepers.ConcentratedLiquidityKeeper.CreateFullRangePosition(ctx, clPoolId, communityPoolAddress, fullRangeCoins) if err != nil { return "", 0, 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(baseAsset, actualBaseAmtUsed))...) + *fullRangeCoinsUsed = fullRangeCoinsUsed.Add(sdk.NewCoins(osmoIn)...) return clPoolDenom, clPoolId, nil } @@ -257,17 +259,18 @@ func testnetParsePoolRecord(ctx sdk.Context, pool poolManagerTypes.PoolI, keeper } // Set the spread factor to the same spread factor the GAMM pool was. - // If its spread factor is not authorized, set it to the first authorized spread factor. + // If its spread factor is not authorized, set it to the first authorized non-zero spread factor. spreadFactor := cfmmPool.GetSpreadFactor(ctx) authorizedSpreadFactors := keepers.ConcentratedLiquidityKeeper.GetParams(ctx).AuthorizedSpreadFactors spreadFactorAuthorized := false for _, authorizedSpreadFactor := range authorizedSpreadFactors { - if authorizedSpreadFactor == spreadFactor { + if authorizedSpreadFactor.Equal(spreadFactor) { spreadFactorAuthorized = true + break } } if !spreadFactorAuthorized { - spreadFactor = authorizedSpreadFactors[0] + spreadFactor = authorizedSpreadFactors[1] } return false, gammPoolId, baseAsset, spreadFactor, nil } diff --git a/tests/e2e/configurer/chain/commands.go b/tests/e2e/configurer/chain/commands.go index 419cde40ada..c8dfe6facce 100644 --- a/tests/e2e/configurer/chain/commands.go +++ b/tests/e2e/configurer/chain/commands.go @@ -689,7 +689,7 @@ func (n *NodeConfig) SendIBC(dstChain *Config, recipient string, token sdk.Coin) return false } }, - time.Minute, + 3*time.Minute, 10*time.Millisecond, "tx not received on destination chain", ) diff --git a/tests/e2e/containers/config.go b/tests/e2e/containers/config.go index 8746ddd5946..2f8ac5f4463 100644 --- a/tests/e2e/containers/config.go +++ b/tests/e2e/containers/config.go @@ -24,10 +24,10 @@ const ( // It should be uploaded to Docker Hub. OSMOSIS_E2E_SKIP_UPGRADE should be unset // for this functionality to be used. previousVersionOsmoRepository = "osmolabs/osmosis-dev" - previousVersionOsmoTag = "16.0" + previousVersionOsmoTag = "16.0-alpine" // Pre-upgrade repo/tag for osmosis initialization (this should be one version below upgradeVersion) previousVersionInitRepository = "osmolabs/osmosis-e2e-init-chain" - previousVersionInitTag = "v16.x-f34d07f8-1690568248" + previousVersionInitTag = "v16-all-gauges-2" // Hermes repo/version for relayer relayerRepository = "informalsystems/hermes" relayerTag = "1.5.1" From bbb644bad272269e011bf79a4afdfb27fd4f1e9f Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 4 Aug 2023 12:16:10 -0500 Subject: [PATCH 04/41] fix --- app/upgrades/v17/upgrades.go | 3 ++ app/upgrades/v17/upgrades_test.go | 73 ++++++++++--------------------- tests/e2e/configurer/upgrade.go | 12 +---- 3 files changed, 26 insertions(+), 62 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index d1216ea361a..83db1ed71e1 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -192,6 +192,9 @@ func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.App return "", 0, err } + // 0.1 OSMO used for the swap, 0.1 OSMO used for the full range position. + osmoIn.Amount = osmoIn.Amount.MulRaw(2) + // 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(osmoIn)...) diff --git a/app/upgrades/v17/upgrades_test.go b/app/upgrades/v17/upgrades_test.go index fa924a5d10a..8aa222137e8 100644 --- a/app/upgrades/v17/upgrades_test.go +++ b/app/upgrades/v17/upgrades_test.go @@ -104,24 +104,13 @@ func (suite *UpgradeTestSuite) TestUpgrade() { // Now create the pool with the correct pool ID. poolCoins := sdk.NewCoins(sdk.NewCoin(assetPair.BaseAsset, sdk.NewInt(10000000000)), sdk.NewCoin(v17.QuoteAsset, sdk.NewInt(10000000000))) - poolId := suite.PrepareBalancerPoolWithCoins(poolCoins...) + suite.PrepareBalancerPoolWithCoins(poolCoins...) - // Send two of the base asset to the community pool. - twoBaseAsset := sdk.NewCoins(sdk.NewCoin(assetPair.BaseAsset, sdk.NewInt(2000000))) - suite.FundAcc(suite.TestAccs[0], twoBaseAsset) + // 0.1 OSMO used to get the respective base asset amount, 0.1 OSMO used to create the position + osmoIn := sdk.NewCoin(v17.QuoteAsset, sdk.NewInt(100000).MulRaw(2)) - err := suite.App.DistrKeeper.FundCommunityPool(suite.Ctx, twoBaseAsset, suite.TestAccs[0]) - suite.Require().NoError(err) - - // Determine approx how much baseAsset will be used from community pool when 1 OSMO used. - oneOsmo := sdk.NewCoin(v17.QuoteAsset, sdk.NewInt(1000000)) - pool, err := suite.App.PoolManagerKeeper.GetPool(suite.Ctx, poolId) - suite.Require().NoError(err) - respectiveBaseAsset, err := suite.App.GAMMKeeper.CalcOutAmtGivenIn(suite.Ctx, pool, oneOsmo, assetPair.BaseAsset, sdk.ZeroDec()) - suite.Require().NoError(err) - - // Add the amount of baseAsset that will be used to the expectedCoinsUsedInUpgradeHandler. - expectedCoinsUsedInUpgradeHandler = expectedCoinsUsedInUpgradeHandler.Add(respectiveBaseAsset) + // Add the amount of osmo that will be used to the expectedCoinsUsedInUpgradeHandler. + expectedCoinsUsedInUpgradeHandler = expectedCoinsUsedInUpgradeHandler.Add(osmoIn) // Enable the GAMM pool for superfluid if the record says so. if assetPair.Superfluid { @@ -164,12 +153,6 @@ func (suite *UpgradeTestSuite) TestUpgrade() { assetPairs := v17.InitializeAssetPairs(ctx, keepers) for i, assetPair := range assetPairs { - // Validate that the community pool balance has been reduced by the amount of baseAsset that was used to create the pool. - suite.Require().Equal(communityPoolBalancePre.AmountOf(assetPair.BaseAsset).Sub(expectedCoinsUsedInUpgradeHandler.AmountOf(assetPair.BaseAsset)).String(), communityPoolBalancePost.AmountOf(assetPair.BaseAsset).String()) - - // Validate that the fee pool community pool balance has been decreased by the amount of baseAsset that was used to create the pool. - suite.Require().Equal(communityPoolBalancePost.AmountOf(assetPair.BaseAsset).String(), feePoolCommunityPoolPost.AmountOf(assetPair.BaseAsset).TruncateInt().String()) - // Get balancer pool's spot price. balancerSpotPrice, err := suite.App.GAMMKeeper.CalculateSpotPrice(suite.Ctx, assetPair.LinkedClassicPool, v17.QuoteAsset, assetPair.BaseAsset) suite.Require().NoError(err) @@ -206,15 +189,17 @@ func (suite *UpgradeTestSuite) TestUpgrade() { lastPoolID++ } + // Validate that the community pool balance has been reduced by the amount of osmo that was used to create the pool. + suite.Require().Equal(communityPoolBalancePre.Sub(expectedCoinsUsedInUpgradeHandler).String(), communityPoolBalancePost.String()) + + // Validate that the fee pool community pool balance has been decreased by the amount of osmo that was used to create the pool. + suite.Require().Equal(sdk.NewDecCoinsFromCoins(communityPoolBalancePost...).String(), feePoolCommunityPoolPost.String()) + numPoolPostUpgrade := suite.App.PoolManagerKeeper.GetNextPoolId(suite.Ctx) - 1 // Number of pools created should be equal to the number of records in the asset pairs. suite.Require().Equal(len(assetPairs), int(numPoolPostUpgrade-numPoolPreUpgrade)) - // Check osmo balance (was used in every pool creation) - suite.Require().Equal(0, multiplicativeTolerance.Compare(communityPoolBalancePre.AmountOf(v17.QuoteAsset), communityPoolBalancePost.AmountOf(v17.QuoteAsset).Sub(expectedCoinsUsedInUpgradeHandler.AmountOf(v17.QuoteAsset)))) - suite.Require().Equal(communityPoolBalancePost.AmountOf(v17.QuoteAsset).String(), feePoolCommunityPoolPost.AmountOf(v17.QuoteAsset).TruncateInt().String()) - // Validate that all links were created. migrationInfo, err := suite.App.GAMMKeeper.GetAllMigrationInfo(suite.Ctx) suite.Require().Equal(len(assetPairs), len(migrationInfo.BalancerToConcentratedPoolLinks)) @@ -243,23 +228,13 @@ func (suite *UpgradeTestSuite) TestUpgrade() { // The only thing we use the assetPair list here for to select some pools to enable superfluid for. for lastPoolID+1 < poolID { poolCoins := sdk.NewCoins(sdk.NewCoin(assetPair.BaseAsset, sdk.NewInt(10000000000)), sdk.NewCoin(v17.QuoteAsset, sdk.NewInt(10000000000))) - poolId := suite.PrepareBalancerPoolWithCoins(poolCoins...) - - // Send two of the base asset to the community pool. - twoBaseAsset := sdk.NewCoins(sdk.NewCoin(assetPair.BaseAsset, sdk.NewInt(2000000))) - suite.FundAcc(suite.TestAccs[0], twoBaseAsset) - err := suite.App.DistrKeeper.FundCommunityPool(suite.Ctx, twoBaseAsset, suite.TestAccs[0]) - suite.Require().NoError(err) + suite.PrepareBalancerPoolWithCoins(poolCoins...) - // Determine approx how much baseAsset will be used from community pool when 1 OSMO used. - oneOsmo := sdk.NewCoin(v17.QuoteAsset, sdk.NewInt(1000000)) - pool, err := suite.App.PoolManagerKeeper.GetPool(suite.Ctx, poolId) - suite.Require().NoError(err) - respectiveBaseAsset, err := suite.App.GAMMKeeper.CalcOutAmtGivenIn(suite.Ctx, pool, oneOsmo, assetPair.BaseAsset, sdk.ZeroDec()) - suite.Require().NoError(err) + // 0.1 OSMO used to get the respective base asset amount, 0.1 OSMO used to create the position + osmoIn := sdk.NewCoin(v17.QuoteAsset, sdk.NewInt(100000).MulRaw(2)) - // Add the amount of baseAsset that will be used to the expectedCoinsUsedInUpgradeHandler. - expectedCoinsUsedInUpgradeHandler = expectedCoinsUsedInUpgradeHandler.Add(respectiveBaseAsset) + // Add the amount of osmo that will be used to the expectedCoinsUsedInUpgradeHandler. + expectedCoinsUsedInUpgradeHandler = expectedCoinsUsedInUpgradeHandler.Add(osmoIn) lastPoolID++ } @@ -345,12 +320,6 @@ func (suite *UpgradeTestSuite) TestUpgrade() { continue } - // Validate that the community pool balance has been reduced by the amount of baseAsset that was used to create the pool. - suite.Require().Equal(communityPoolBalancePre.AmountOf(baseAsset).Sub(expectedCoinsUsedInUpgradeHandler.AmountOf(baseAsset)).String(), communityPoolBalancePost.AmountOf(baseAsset).String()) - - // Validate that the fee pool community pool balance has been decreased by the amount of baseAsset that was used to create the pool. - suite.Require().Equal(communityPoolBalancePost.AmountOf(baseAsset).String(), feePoolCommunityPoolPost.AmountOf(baseAsset).TruncateInt().String()) - // Get balancer pool's spot price. balancerSpotPrice, err := suite.App.GAMMKeeper.CalculateSpotPrice(suite.Ctx, gammPoolId, v17.QuoteAsset, baseAsset) suite.Require().NoError(err) @@ -394,6 +363,12 @@ func (suite *UpgradeTestSuite) TestUpgrade() { lastPoolID++ } + // Validate that the community pool balance has been reduced by the amount of osmo that was used to create the pool. + suite.Require().Equal(communityPoolBalancePre.Sub(expectedCoinsUsedInUpgradeHandler).String(), communityPoolBalancePost.String()) + + // Validate that the fee pool community pool balance has been decreased by the amount of osmo that was used to create the pool. + suite.Require().Equal(sdk.NewDecCoinsFromCoins(communityPoolBalancePost...).String(), feePoolCommunityPoolPost.String()) + numPoolPostUpgrade := suite.App.PoolManagerKeeper.GetNextPoolId(suite.Ctx) - 1 numPoolsCreated := numPoolPostUpgrade - numPoolPreUpgrade @@ -401,10 +376,6 @@ func (suite *UpgradeTestSuite) TestUpgrade() { numPoolsEligibleForMigration := numPoolPreUpgrade - 3 suite.Require().Equal(int(numPoolsEligibleForMigration), int(numPoolsCreated)) - // Check osmo balance (was used in every pool creation) - suite.Require().Equal(0, multiplicativeTolerance.Compare(communityPoolBalancePre.AmountOf(v17.QuoteAsset), communityPoolBalancePost.AmountOf(v17.QuoteAsset).Sub(expectedCoinsUsedInUpgradeHandler.AmountOf(v17.QuoteAsset)))) - suite.Require().Equal(communityPoolBalancePost.AmountOf(v17.QuoteAsset).String(), feePoolCommunityPoolPost.AmountOf(v17.QuoteAsset).TruncateInt().String()) - //Validate that all links were created. migrationInfo, err := suite.App.GAMMKeeper.GetAllMigrationInfo(suite.Ctx) suite.Require().Equal(int(numPoolsEligibleForMigration), len(migrationInfo.BalancerToConcentratedPoolLinks)) diff --git a/tests/e2e/configurer/upgrade.go b/tests/e2e/configurer/upgrade.go index bdddce8015d..858c5971f29 100644 --- a/tests/e2e/configurer/upgrade.go +++ b/tests/e2e/configurer/upgrade.go @@ -143,17 +143,7 @@ func (uc *UpgradeConfigurer) CreatePreUpgradeState() error { v17SuperfluidAssets := v17GetSuperfluidAssets() - wg.Add(4) - - go func() { - defer wg.Done() - chainANode.FundCommunityPool(initialization.ValidatorWalletName, strAllUpgradeBaseDenoms()) - }() - - go func() { - defer wg.Done() - chainBNode.FundCommunityPool(initialization.ValidatorWalletName, strAllUpgradeBaseDenoms()) - }() + wg.Add(2) go func() { defer wg.Done() From ab52240092bd5d61e8b8479d0767f49681b38ab1 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 4 Aug 2023 12:25:34 -0500 Subject: [PATCH 05/41] widen tolerance --- tests/e2e/e2e_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 9361cb5a981..c92b94b938b 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1800,9 +1800,9 @@ func (s *IntegrationTestSuite) ConcentratedLiquidity_CanonicalPools() { expectedSpotPrice, err := balancerPool.SpotPrice(sdk.Context{}, v17.QuoteAsset, assetPair.BaseAsset) s.Require().NoError(err) - // Allow 0.1% margin of error. + // Allow 1% margin of error (due to low pool liquidity being used for OSMO swap to base asset) multiplicativeTolerance := osmomath.ErrTolerance{ - MultiplicativeTolerance: sdk.MustNewDecFromStr("0.001"), + MultiplicativeTolerance: sdk.MustNewDecFromStr("0.01"), } s.Require().Equal(0, multiplicativeTolerance.CompareBigDec(osmomath.BigDecFromSDKDec(expectedSpotPrice), concentratedPool.GetCurrentSqrtPrice().PowerInteger(2))) From da6324c952f8e340bf6737e7a27e74a5cd879706 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 4 Aug 2023 12:44:52 -0500 Subject: [PATCH 06/41] more resilient way to calculate coins used --- app/upgrades/v17/upgrades.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 83db1ed71e1..d60a6067b35 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -172,6 +172,9 @@ func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.App ClPoolId: clPoolId, }) + // Get community pool balance before swap and position creation + commPoolBalancePre := keepers.BankKeeper.GetAllBalances(ctx, communityPoolAddress) + // Swap 0.1 OSMO for baseAsset from the community pool. osmoIn := sdk.NewCoin(QuoteAsset, sdk.NewInt(100000)) linkedClassicPool, err := keepers.PoolManagerKeeper.GetPool(ctx, gammPoolId) @@ -192,11 +195,16 @@ func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.App return "", 0, err } - // 0.1 OSMO used for the swap, 0.1 OSMO used for the full range position. - osmoIn.Amount = osmoIn.Amount.MulRaw(2) + // Get community pool balance after swap and position creation + commPoolBalancePost := keepers.BankKeeper.GetAllBalances(ctx, communityPoolAddress) + + // While we can be fairly certain the diff between these two is 0.2 OSMO, if for whatever reason + // some baseAsset dust remains in the community pool and we don't account for it, when updating the + // fee pool balance later, we will be off by that amount and will cause a panic. + coinsUsed := commPoolBalancePre.Sub(commPoolBalancePost) // 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(osmoIn)...) + *fullRangeCoinsUsed = fullRangeCoinsUsed.Add(coinsUsed...) return clPoolDenom, clPoolId, nil } From f8498257adaf75283ec5f835ddc262ed901d4afd Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 4 Aug 2023 12:56:28 -0500 Subject: [PATCH 07/41] add logs to upgrade handler --- app/upgrades/v17/upgrades.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index d60a6067b35..6176415f556 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -159,6 +159,7 @@ func testnetUpgradeHandler(ctx sdk.Context, keepers *keepers.AppKeepers, communi // There must be 1 OSMO worth baseAsset in the community pool for this to work. func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.AppKeepers, gammPoolId uint64, baseAsset string, spreadFactor sdk.Dec, communityPoolAddress sdk.AccAddress, poolLinks *[]gammmigration.BalancerToConcentratedPoolLink, fullRangeCoinsUsed *sdk.Coins) (clPoolDenom string, clPoolId uint64, err error) { // Create a concentrated liquidity pool for asset pair. + ctx.Logger().Info(fmt.Sprintf("Creating CL pool from poolID (%d), baseAsset (%s), spreadFactor (%s), tickSpacing (%d)", gammPoolId, baseAsset, spreadFactor, TickSpacing)) clPool, err := keepers.GAMMKeeper.CreateConcentratedPoolFromCFMM(ctx, gammPoolId, baseAsset, spreadFactor, TickSpacing) if err != nil { return "", 0, err @@ -185,6 +186,7 @@ func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.App if err != nil { return "", 0, err } + ctx.Logger().Info(fmt.Sprintf("Swapped %s for %s%s from the community pool", osmoIn.String(), respectiveBaseAssetInt.String(), baseAsset)) respectiveBaseAsset := sdk.NewCoin(baseAsset, respectiveBaseAssetInt) @@ -215,6 +217,7 @@ func authorizeSuperfluidIfEnabled(ctx sdk.Context, keepers *keepers.AppKeepers, poolShareDenom := fmt.Sprintf("gamm/pool/%d", gammPoolId) _, err = keepers.SuperfluidKeeper.GetSuperfluidAsset(ctx, poolShareDenom) if err == nil { + ctx.Logger().Info(fmt.Sprintf("%s is superfluid enabled, enabling %s as a superfluid asset", poolShareDenom, clPoolDenom)) superfluidAsset := superfluidtypes.SuperfluidAsset{ Denom: clPoolDenom, AssetType: superfluidtypes.SuperfluidAssetTypeConcentratedShare, @@ -224,11 +227,13 @@ func authorizeSuperfluidIfEnabled(ctx sdk.Context, keepers *keepers.AppKeepers, return err } } + ctx.Logger().Info(fmt.Sprintf("%s is not superfluid enabled, not enabling %s as a superfluid asset", poolShareDenom, clPoolDenom)) return nil } // manuallySetTWAPRecords manually sets the TWAP records for a CL pool. This prevents a panic when the CL pool is first used. func manuallySetTWAPRecords(ctx sdk.Context, keepers *keepers.AppKeepers, clPoolId uint64) error { + ctx.Logger().Info(fmt.Sprintf("manually setting twap record for newly created CL poolID %d", clPoolId)) clPoolTwapRecords, err := keepers.TwapKeeper.GetAllMostRecentRecordsForPool(ctx, clPoolId) if err != nil { return err From d70423c9cfc9556779bda2d7af4f791ed869579d Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 4 Aug 2023 13:33:13 -0500 Subject: [PATCH 08/41] scale error tolerance with spread factor --- app/upgrades/v17/upgrades.go | 1 - tests/e2e/e2e_test.go | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 6176415f556..372fc9fd1eb 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -156,7 +156,6 @@ func testnetUpgradeHandler(ctx sdk.Context, keepers *keepers.AppKeepers, communi } // createCLPoolWithCommunityPoolPosition creates a CL pool for a given balancer pool and adds a full range position with the community pool. -// There must be 1 OSMO worth baseAsset in the community pool for this to work. func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.AppKeepers, gammPoolId uint64, baseAsset string, spreadFactor sdk.Dec, communityPoolAddress sdk.AccAddress, poolLinks *[]gammmigration.BalancerToConcentratedPoolLink, fullRangeCoinsUsed *sdk.Coins) (clPoolDenom string, clPoolId uint64, err error) { // Create a concentrated liquidity pool for asset pair. ctx.Logger().Info(fmt.Sprintf("Creating CL pool from poolID (%d), baseAsset (%s), spreadFactor (%s), tickSpacing (%d)", gammPoolId, baseAsset, spreadFactor, TickSpacing)) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index c92b94b938b..3508314096c 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1800,9 +1800,11 @@ func (s *IntegrationTestSuite) ConcentratedLiquidity_CanonicalPools() { expectedSpotPrice, err := balancerPool.SpotPrice(sdk.Context{}, v17.QuoteAsset, assetPair.BaseAsset) s.Require().NoError(err) - // Allow 1% margin of error (due to low pool liquidity being used for OSMO swap to base asset) + // Margin of error should be slightly larger than the gamm pool's spread factor, as the gamm pool is used to + // swap through when creating the initial position. The below implies a 0.1% margin of error. + tollerance := expectedSpreadFactor.Add(sdk.MustNewDecFromStr("0.0001")) multiplicativeTolerance := osmomath.ErrTolerance{ - MultiplicativeTolerance: sdk.MustNewDecFromStr("0.01"), + MultiplicativeTolerance: tollerance, } s.Require().Equal(0, multiplicativeTolerance.CompareBigDec(osmomath.BigDecFromSDKDec(expectedSpotPrice), concentratedPool.GetCurrentSqrtPrice().PowerInteger(2))) From 7145a25969710909e60e8301994831676f1a10d4 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 4 Aug 2023 14:09:17 -0500 Subject: [PATCH 09/41] change back init tag --- tests/e2e/containers/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/containers/config.go b/tests/e2e/containers/config.go index 2f8ac5f4463..dfa7de46924 100644 --- a/tests/e2e/containers/config.go +++ b/tests/e2e/containers/config.go @@ -27,7 +27,7 @@ const ( previousVersionOsmoTag = "16.0-alpine" // Pre-upgrade repo/tag for osmosis initialization (this should be one version below upgradeVersion) previousVersionInitRepository = "osmolabs/osmosis-e2e-init-chain" - previousVersionInitTag = "v16-all-gauges-2" + previousVersionInitTag = "v16.x-f34d07f8-1690568248" // Hermes repo/version for relayer relayerRepository = "informalsystems/hermes" relayerTag = "1.5.1" From 146faa50576502c50e26c5224000831c19d82006 Mon Sep 17 00:00:00 2001 From: devbot-wizard <141283918+devbot-wizard@users.noreply.github.com> Date: Sat, 5 Aug 2023 14:56:55 +0000 Subject: [PATCH 10/41] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d78d7d99a3c..b215b429153 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#5923] (https://github.com/osmosis-labs/osmosis/pull/5923) CL: Lower gas for initializing ticks * [#5927] (https://github.com/osmosis-labs/osmosis/pull/5927) Add gas metering to x/tokenfactory trackBeforeSend hook * [#5890](https://github.com/osmosis-labs/osmosis/pull/5890) feat: CreateCLPool & LinkCFMMtoCL pool into one gov-prop +* [#5959](https://github.com/osmosis-labs/osmosis/pull/5959) allow testing with different chain-id's in E2E testing ### Minor improvements & Bug Fixes From 7d7695b605f2936653d9af17d28230ba461e61dd Mon Sep 17 00:00:00 2001 From: devbot-wizard <141283918+devbot-wizard@users.noreply.github.com> Date: Sat, 5 Aug 2023 15:05:26 +0000 Subject: [PATCH 11/41] Fix imports --- CHANGELOG.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4249e89083..3cc51b9edb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,11 +71,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#5923] (https://github.com/osmosis-labs/osmosis/pull/5923) CL: Lower gas for initializing ticks * [#5927] (https://github.com/osmosis-labs/osmosis/pull/5927) Add gas metering to x/tokenfactory trackBeforeSend hook * [#5890](https://github.com/osmosis-labs/osmosis/pull/5890) feat: CreateCLPool & LinkCFMMtoCL pool into one gov-prop -<<<<<<< HEAD * [#5959](https://github.com/osmosis-labs/osmosis/pull/5959) allow testing with different chain-id's in E2E testing -======= * [#5964](https://github.com/osmosis-labs/osmosis/pull/5964) fix e2e test concurrency bugs ->>>>>>> main ### Minor improvements & Bug Fixes From b334722a58567561bde6b2e712b8efce125d7dbb Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Sat, 5 Aug 2023 12:18:30 -0500 Subject: [PATCH 12/41] check liquidity prior to creating pool --- app/upgrades/v17/upgrades.go | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 372fc9fd1eb..a8172d1f12c 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -1,9 +1,11 @@ package v17 import ( + "errors" "fmt" "time" + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" @@ -11,6 +13,7 @@ import ( distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" cltypes "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" + gammtypes "github.com/osmosis-labs/osmosis/v17/x/gamm/types" gammmigration "github.com/osmosis-labs/osmosis/v17/x/gamm/types/migration" poolManagerTypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" superfluidtypes "github.com/osmosis-labs/osmosis/v17/x/superfluid/types" @@ -30,6 +33,8 @@ const ( cosmwasmWeight = 300 ) +var notEnoughLiquidityForSwapErr = errorsmod.Wrapf(gammtypes.ErrInvalidMathApprox, "token amount must be positive") + func CreateUpgradeHandler( mm *module.Manager, configurator module.Configurator, @@ -138,7 +143,9 @@ func testnetUpgradeHandler(ctx sdk.Context, keepers *keepers.AppKeepers, communi } clPoolDenom, clPoolId, err := createCLPoolWithCommunityPoolPosition(ctx, keepers, gammPoolId, baseAsset, spreadFactor, communityPoolAddress, poolLinks, fullRangeCoinsUsed) - if err != nil { + if errors.Is(err, notEnoughLiquidityForSwapErr) { + continue + } else if err != nil { return err } @@ -157,6 +164,18 @@ func testnetUpgradeHandler(ctx sdk.Context, keepers *keepers.AppKeepers, communi // createCLPoolWithCommunityPoolPosition creates a CL pool for a given balancer pool and adds a full range position with the community pool. func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.AppKeepers, gammPoolId uint64, baseAsset string, spreadFactor sdk.Dec, communityPoolAddress sdk.AccAddress, poolLinks *[]gammmigration.BalancerToConcentratedPoolLink, fullRangeCoinsUsed *sdk.Coins) (clPoolDenom string, clPoolId uint64, err error) { + // Check if classic pool has enough liquidity to support a 0.1 OSMO swap before creating a CL pool. + // If not, skip the pool. + osmoIn := sdk.NewCoin(QuoteAsset, sdk.NewInt(100000)) + linkedClassicPool, err := keepers.PoolManagerKeeper.GetPool(ctx, gammPoolId) + if err != nil { + return "", 0, err + } + _, err = keepers.GAMMKeeper.CalcOutAmtGivenIn(ctx, linkedClassicPool, osmoIn, baseAsset, spreadFactor) + if err != nil { + return "", 0, err + } + // Create a concentrated liquidity pool for asset pair. ctx.Logger().Info(fmt.Sprintf("Creating CL pool from poolID (%d), baseAsset (%s), spreadFactor (%s), tickSpacing (%d)", gammPoolId, baseAsset, spreadFactor, TickSpacing)) clPool, err := keepers.GAMMKeeper.CreateConcentratedPoolFromCFMM(ctx, gammPoolId, baseAsset, spreadFactor, TickSpacing) @@ -176,11 +195,6 @@ func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.App commPoolBalancePre := keepers.BankKeeper.GetAllBalances(ctx, communityPoolAddress) // Swap 0.1 OSMO for baseAsset from the community pool. - osmoIn := sdk.NewCoin(QuoteAsset, sdk.NewInt(100000)) - linkedClassicPool, err := keepers.PoolManagerKeeper.GetPool(ctx, gammPoolId) - if err != nil { - return "", 0, err - } respectiveBaseAssetInt, err := keepers.GAMMKeeper.SwapExactAmountIn(ctx, communityPoolAddress, linkedClassicPool, osmoIn, baseAsset, sdk.ZeroInt(), linkedClassicPool.GetSpreadFactor(ctx)) if err != nil { return "", 0, err From bdb5741f64e858e7c8303ee349c9c1d6b181d22f Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Sat, 5 Aug 2023 12:53:42 -0500 Subject: [PATCH 13/41] check base/quote rather than all denoms --- app/upgrades/v17/upgrades.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index a8172d1f12c..f847fb75aa1 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -192,7 +192,9 @@ func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.App }) // Get community pool balance before swap and position creation - commPoolBalancePre := keepers.BankKeeper.GetAllBalances(ctx, communityPoolAddress) + commPoolBalanceBaseAssetPre := keepers.BankKeeper.GetBalance(ctx, communityPoolAddress, baseAsset) + commPoolBalanceQuoteAssetPre := keepers.BankKeeper.GetBalance(ctx, communityPoolAddress, QuoteAsset) + commPoolBalancePre := sdk.NewCoins(commPoolBalanceBaseAssetPre, commPoolBalanceQuoteAssetPre) // Swap 0.1 OSMO for baseAsset from the community pool. respectiveBaseAssetInt, err := keepers.GAMMKeeper.SwapExactAmountIn(ctx, communityPoolAddress, linkedClassicPool, osmoIn, baseAsset, sdk.ZeroInt(), linkedClassicPool.GetSpreadFactor(ctx)) @@ -211,7 +213,9 @@ func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.App } // Get community pool balance after swap and position creation - commPoolBalancePost := keepers.BankKeeper.GetAllBalances(ctx, communityPoolAddress) + commPoolBalanceBaseAssetPost := keepers.BankKeeper.GetBalance(ctx, communityPoolAddress, baseAsset) + commPoolBalanceQuoteAssetPost := keepers.BankKeeper.GetBalance(ctx, communityPoolAddress, QuoteAsset) + commPoolBalancePost := sdk.NewCoins(commPoolBalanceBaseAssetPost, commPoolBalanceQuoteAssetPost) // While we can be fairly certain the diff between these two is 0.2 OSMO, if for whatever reason // some baseAsset dust remains in the community pool and we don't account for it, when updating the From 2d02cea926cabd5e875ac4304e74580876ab9fa0 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Sun, 6 Aug 2023 11:52:28 -0500 Subject: [PATCH 14/41] check if pool only has 2 assets --- app/upgrades/v17/upgrades.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index f847fb75aa1..8372bf9fe23 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -276,6 +276,10 @@ func testnetParsePoolRecord(ctx sdk.Context, pool poolManagerTypes.PoolI, keeper return true, 0, "", sdk.Dec{}, err } + if len(cfmmPool.GetTotalPoolLiquidity(ctx)) != 2 { + return true, 0, "", sdk.Dec{}, nil + } + poolCoins := cfmmPool.GetTotalPoolLiquidity(ctx) // We only want to upgrade pools paired with OSMO. OSMO will be the quote asset. From a1f3bbe681cd3c0b9de3764d1503f0dd41865a7a Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 07:28:45 -0500 Subject: [PATCH 15/41] skip pools that are already linked --- app/upgrades/v17/upgrades.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 8372bf9fe23..e8ab7f8d7ad 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -271,6 +271,13 @@ func testnetParsePoolRecord(ctx sdk.Context, pool poolManagerTypes.PoolI, keeper } gammPoolId := pool.GetId() + + // Skip pools that are already linked. + _, err := keepers.GAMMKeeper.GetLinkedConcentratedPoolID(ctx, gammPoolId) + if err != nil { + return true, 0, "", sdk.Dec{}, nil + } + cfmmPool, err := keepers.GAMMKeeper.GetCFMMPool(ctx, gammPoolId) if err != nil { return true, 0, "", sdk.Dec{}, err From 3a21bd5479e0db82536bd7691157ad43ae04bbe7 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 07:51:46 -0500 Subject: [PATCH 16/41] add log and fix issue --- app/upgrades/v17/upgrades.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index e8ab7f8d7ad..f667486bcc7 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -273,8 +273,9 @@ func testnetParsePoolRecord(ctx sdk.Context, pool poolManagerTypes.PoolI, keeper gammPoolId := pool.GetId() // Skip pools that are already linked. - _, err := keepers.GAMMKeeper.GetLinkedConcentratedPoolID(ctx, gammPoolId) - if err != nil { + clPoolId, err := keepers.GAMMKeeper.GetLinkedConcentratedPoolID(ctx, gammPoolId) + if err == nil && clPoolId != 0 { + ctx.Logger().Info(fmt.Sprintf("gammPoolId %d is already linked to CL pool %d, skipping", gammPoolId, clPoolId)) return true, 0, "", sdk.Dec{}, nil } From cbedf7a24ee0833875cd74da4e68b8bae7726dad Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 08:23:23 -0500 Subject: [PATCH 17/41] add an additional log --- app/upgrades/v17/upgrades.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index f667486bcc7..d28da81c50c 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -279,6 +279,8 @@ func testnetParsePoolRecord(ctx sdk.Context, pool poolManagerTypes.PoolI, keeper return true, 0, "", sdk.Dec{}, nil } + ctx.Logger().Info(fmt.Sprintf("parsing gamm pool %d", gammPoolId)) + cfmmPool, err := keepers.GAMMKeeper.GetCFMMPool(ctx, gammPoolId) if err != nil { return true, 0, "", sdk.Dec{}, err From d0eba58990a1d5aab8b33f6ae36882a578206c72 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 08:39:53 -0500 Subject: [PATCH 18/41] more logs --- app/upgrades/v17/upgrades.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index d28da81c50c..7990cd7606e 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -67,6 +67,8 @@ func CreateUpgradeHandler( return nil, err } + ctx.Logger().Info(fmt.Sprintf("Pool links: %v", poolLinks)) + // Set the migration links in x/gamm. // This will also migrate the CFMM distribution records to point to the new CL pools. err = keepers.GAMMKeeper.UpdateMigrationRecords(ctx, poolLinks) From 1454538e7f8099f33ff4f7b751b2fb6449431b43 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 08:54:52 -0500 Subject: [PATCH 19/41] more prints --- x/gamm/keeper/migrate.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/x/gamm/keeper/migrate.go b/x/gamm/keeper/migrate.go index 0b5edfc304c..28fb00ef8e8 100644 --- a/x/gamm/keeper/migrate.go +++ b/x/gamm/keeper/migrate.go @@ -326,6 +326,9 @@ func (k Keeper) UpdateMigrationRecords(ctx sdk.Context, records []gammmigration. recordsMap[existingRecord.BalancerPoolId] = existingRecord } + fmt.Println("existing records: ", migrationInfos) + fmt.Println() + // Update the map with the new records for _, record := range records { recordsMap[record.BalancerPoolId] = record @@ -346,6 +349,9 @@ func (k Keeper) UpdateMigrationRecords(ctx sdk.Context, records []gammmigration. return newRecords[i].BalancerPoolId < newRecords[j].BalancerPoolId }) + fmt.Println("new records: ", newRecords) + fmt.Println() + // We now have a list of all previous records, as well as records that have been updated. // We can now remove all previous records and replace them with the new ones. err = k.OverwriteMigrationRecordsAndRedirectDistrRecords(ctx, gammmigration.MigrationRecords{ From f04b9c81dc891f395d3fa4a0fd978213169b3654 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 11:28:39 -0500 Subject: [PATCH 20/41] skip if incentive gauge duration does not exist --- x/gamm/keeper/migrate.go | 6 +++++- x/pool-incentives/keeper/keeper.go | 13 +++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/x/gamm/keeper/migrate.go b/x/gamm/keeper/migrate.go index 28fb00ef8e8..77e043001f6 100644 --- a/x/gamm/keeper/migrate.go +++ b/x/gamm/keeper/migrate.go @@ -1,6 +1,7 @@ package keeper import ( + "errors" "fmt" "sort" @@ -9,6 +10,7 @@ import ( cltypes "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" "github.com/osmosis-labs/osmosis/v17/x/gamm/types" gammmigration "github.com/osmosis-labs/osmosis/v17/x/gamm/types/migration" + poolincentivestypes "github.com/osmosis-labs/osmosis/v17/x/pool-incentives/types" poolmanagertypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" "github.com/cosmos/cosmos-sdk/store/prefix" @@ -176,7 +178,9 @@ func (k Keeper) redirectDistributionRecord(ctx sdk.Context, cfmmPoolId, clPoolId // Get concentrated gauge corresponding to the distribution epoch duration. concentratedGaugeId, err := k.poolIncentivesKeeper.GetPoolGaugeId(ctx, clPoolId, distributionEpochDuration) - if err != nil { + if concentratedGaugeId == 0 && errors.Is(err, poolincentivestypes.NoGaugeAssociatedWithPoolError{PoolId: clPoolId, Duration: distributionEpochDuration}) { + return nil + } else if err != nil { return err } diff --git a/x/pool-incentives/keeper/keeper.go b/x/pool-incentives/keeper/keeper.go index a84c1f5fe38..a3150186694 100644 --- a/x/pool-incentives/keeper/keeper.go +++ b/x/pool-incentives/keeper/keeper.go @@ -6,6 +6,8 @@ import ( "github.com/tendermint/tendermint/libs/log" + "google.golang.org/protobuf/types/known/wrapperspb" + "github.com/osmosis-labs/osmosis/osmoutils" gammtypes "github.com/osmosis-labs/osmosis/v17/x/gamm/types" incentivestypes "github.com/osmosis-labs/osmosis/v17/x/incentives/types" @@ -183,15 +185,18 @@ func (k Keeper) GetPoolGaugeId(ctx sdk.Context, poolId uint64, lockableDuration return 0, fmt.Errorf("cannot get gauge id from pool id without a lockable duration. There can be many gauges for pool id %d and duration 0", poolId) } + uint64Value := &wrapperspb.UInt64Value{} key := types.GetPoolGaugeIdInternalStoreKey(poolId, lockableDuration) store := ctx.KVStore(k.storeKey) - bz := store.Get(key) - - if len(bz) == 0 { + found, err := osmoutils.Get(store, key, uint64Value) + if err != nil { + return 0, err + } + if !found { return 0, types.NoGaugeAssociatedWithPoolError{PoolId: poolId, Duration: lockableDuration} } - return sdk.BigEndianToUint64(bz), nil + return uint64Value.Value, nil } // GetNoLockGaugeIdsFromPool returns all the NoLock gauge ids associated with the pool id. From 3ce1f417238f6b362cb76979017d2258fe7c5591 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 11:35:56 -0500 Subject: [PATCH 21/41] use gogotypes --- x/pool-incentives/keeper/keeper.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x/pool-incentives/keeper/keeper.go b/x/pool-incentives/keeper/keeper.go index a3150186694..e4d9eaffc32 100644 --- a/x/pool-incentives/keeper/keeper.go +++ b/x/pool-incentives/keeper/keeper.go @@ -6,7 +6,7 @@ import ( "github.com/tendermint/tendermint/libs/log" - "google.golang.org/protobuf/types/known/wrapperspb" + gogotypes "github.com/gogo/protobuf/types" "github.com/osmosis-labs/osmosis/osmoutils" gammtypes "github.com/osmosis-labs/osmosis/v17/x/gamm/types" @@ -185,10 +185,10 @@ func (k Keeper) GetPoolGaugeId(ctx sdk.Context, poolId uint64, lockableDuration return 0, fmt.Errorf("cannot get gauge id from pool id without a lockable duration. There can be many gauges for pool id %d and duration 0", poolId) } - uint64Value := &wrapperspb.UInt64Value{} + uint64Value := gogotypes.UInt64Value{} key := types.GetPoolGaugeIdInternalStoreKey(poolId, lockableDuration) store := ctx.KVStore(k.storeKey) - found, err := osmoutils.Get(store, key, uint64Value) + found, err := osmoutils.Get(store, key, &uint64Value) if err != nil { return 0, err } From 9318fd89141d7a4623b6c0836c64bf112588a09b Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 11:46:29 -0500 Subject: [PATCH 22/41] use store.Has --- x/pool-incentives/keeper/keeper.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/x/pool-incentives/keeper/keeper.go b/x/pool-incentives/keeper/keeper.go index e4d9eaffc32..ebfc443d1c6 100644 --- a/x/pool-incentives/keeper/keeper.go +++ b/x/pool-incentives/keeper/keeper.go @@ -6,8 +6,6 @@ import ( "github.com/tendermint/tendermint/libs/log" - gogotypes "github.com/gogo/protobuf/types" - "github.com/osmosis-labs/osmosis/osmoutils" gammtypes "github.com/osmosis-labs/osmosis/v17/x/gamm/types" incentivestypes "github.com/osmosis-labs/osmosis/v17/x/incentives/types" @@ -185,18 +183,16 @@ func (k Keeper) GetPoolGaugeId(ctx sdk.Context, poolId uint64, lockableDuration return 0, fmt.Errorf("cannot get gauge id from pool id without a lockable duration. There can be many gauges for pool id %d and duration 0", poolId) } - uint64Value := gogotypes.UInt64Value{} key := types.GetPoolGaugeIdInternalStoreKey(poolId, lockableDuration) store := ctx.KVStore(k.storeKey) - found, err := osmoutils.Get(store, key, &uint64Value) - if err != nil { - return 0, err - } - if !found { + + if !store.Has(key) { return 0, types.NoGaugeAssociatedWithPoolError{PoolId: poolId, Duration: lockableDuration} } - return uint64Value.Value, nil + bz := store.Get(key) + gaugeId := sdk.BigEndianToUint64(bz) + return gaugeId, nil } // GetNoLockGaugeIdsFromPool returns all the NoLock gauge ids associated with the pool id. From cf87cded831b3198536c39317b238750d8a30da9 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 12:41:24 -0500 Subject: [PATCH 23/41] error instead of panic on getgaugeId from poolId --- x/gamm/keeper/migrate.go | 6 +----- x/gamm/keeper/migrate_test.go | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/x/gamm/keeper/migrate.go b/x/gamm/keeper/migrate.go index 77e043001f6..28fb00ef8e8 100644 --- a/x/gamm/keeper/migrate.go +++ b/x/gamm/keeper/migrate.go @@ -1,7 +1,6 @@ package keeper import ( - "errors" "fmt" "sort" @@ -10,7 +9,6 @@ import ( cltypes "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" "github.com/osmosis-labs/osmosis/v17/x/gamm/types" gammmigration "github.com/osmosis-labs/osmosis/v17/x/gamm/types/migration" - poolincentivestypes "github.com/osmosis-labs/osmosis/v17/x/pool-incentives/types" poolmanagertypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" "github.com/cosmos/cosmos-sdk/store/prefix" @@ -178,9 +176,7 @@ func (k Keeper) redirectDistributionRecord(ctx sdk.Context, cfmmPoolId, clPoolId // Get concentrated gauge corresponding to the distribution epoch duration. concentratedGaugeId, err := k.poolIncentivesKeeper.GetPoolGaugeId(ctx, clPoolId, distributionEpochDuration) - if concentratedGaugeId == 0 && errors.Is(err, poolincentivestypes.NoGaugeAssociatedWithPoolError{PoolId: clPoolId, Duration: distributionEpochDuration}) { - return nil - } else if err != nil { + if err != nil { return err } diff --git a/x/gamm/keeper/migrate_test.go b/x/gamm/keeper/migrate_test.go index 8d9f9771c6c..c1db01535df 100644 --- a/x/gamm/keeper/migrate_test.go +++ b/x/gamm/keeper/migrate_test.go @@ -1035,7 +1035,7 @@ func (s *KeeperTestSuite) TestCreateConcentratedPoolFromCFMM() { poolLiquidity: sdk.NewCoins(desiredDenom0Coin, daiCoin), cfmmPoolIdToLinkWith: validPoolId, desiredDenom0: USDCIBCDenom, - expectError: types.NoDesiredDenomInPoolError{USDCIBCDenom}, + expectError: types.NoDesiredDenomInPoolError{DesiredDenom: USDCIBCDenom}, }, "error: pool with 3 assets, must have two": { poolLiquidity: sdk.NewCoins(desiredDenom0Coin, daiCoin, usdcCoin), @@ -1124,7 +1124,7 @@ func (s *KeeperTestSuite) TestCreateCanonicalConcentratedLiquidityPoolAndMigrati poolLiquidity: sdk.NewCoins(desiredDenom0Coin, daiCoin), cfmmPoolIdToLinkWith: validPoolId, desiredDenom0: USDCIBCDenom, - expectError: types.NoDesiredDenomInPoolError{USDCIBCDenom}, + expectError: types.NoDesiredDenomInPoolError{DesiredDenom: USDCIBCDenom}, }, "error: pool with 3 assets, must have two": { poolLiquidity: sdk.NewCoins(desiredDenom0Coin, daiCoin, usdcCoin), From b9f28f3b46862ba5d6962b03828c80bb0241fce5 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 12:42:38 -0500 Subject: [PATCH 24/41] Update app/upgrades/v17/upgrades_test.go Co-authored-by: Roman --- app/upgrades/v17/upgrades_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/upgrades/v17/upgrades_test.go b/app/upgrades/v17/upgrades_test.go index 8aa222137e8..9366e1bf2e8 100644 --- a/app/upgrades/v17/upgrades_test.go +++ b/app/upgrades/v17/upgrades_test.go @@ -376,7 +376,7 @@ func (suite *UpgradeTestSuite) TestUpgrade() { numPoolsEligibleForMigration := numPoolPreUpgrade - 3 suite.Require().Equal(int(numPoolsEligibleForMigration), int(numPoolsCreated)) - //Validate that all links were created. + // Validate that all links were created. migrationInfo, err := suite.App.GAMMKeeper.GetAllMigrationInfo(suite.Ctx) suite.Require().Equal(int(numPoolsEligibleForMigration), len(migrationInfo.BalancerToConcentratedPoolLinks)) suite.Require().NoError(err) From d793a36b99c0f3b40504e4b28d347854ff0dad14 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 12:43:21 -0500 Subject: [PATCH 25/41] remove extra prints --- x/gamm/keeper/migrate.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/x/gamm/keeper/migrate.go b/x/gamm/keeper/migrate.go index 28fb00ef8e8..0b5edfc304c 100644 --- a/x/gamm/keeper/migrate.go +++ b/x/gamm/keeper/migrate.go @@ -326,9 +326,6 @@ func (k Keeper) UpdateMigrationRecords(ctx sdk.Context, records []gammmigration. recordsMap[existingRecord.BalancerPoolId] = existingRecord } - fmt.Println("existing records: ", migrationInfos) - fmt.Println() - // Update the map with the new records for _, record := range records { recordsMap[record.BalancerPoolId] = record @@ -349,9 +346,6 @@ func (k Keeper) UpdateMigrationRecords(ctx sdk.Context, records []gammmigration. return newRecords[i].BalancerPoolId < newRecords[j].BalancerPoolId }) - fmt.Println("new records: ", newRecords) - fmt.Println() - // We now have a list of all previous records, as well as records that have been updated. // We can now remove all previous records and replace them with the new ones. err = k.OverwriteMigrationRecordsAndRedirectDistrRecords(ctx, gammmigration.MigrationRecords{ From 68cd7738881ea8e3085238af512defd294d2ee1b Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 13:06:09 -0500 Subject: [PATCH 26/41] remove old logs --- app/upgrades/v17/upgrades.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 7990cd7606e..f667486bcc7 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -67,8 +67,6 @@ func CreateUpgradeHandler( return nil, err } - ctx.Logger().Info(fmt.Sprintf("Pool links: %v", poolLinks)) - // Set the migration links in x/gamm. // This will also migrate the CFMM distribution records to point to the new CL pools. err = keepers.GAMMKeeper.UpdateMigrationRecords(ctx, poolLinks) @@ -281,8 +279,6 @@ func testnetParsePoolRecord(ctx sdk.Context, pool poolManagerTypes.PoolI, keeper return true, 0, "", sdk.Dec{}, nil } - ctx.Logger().Info(fmt.Sprintf("parsing gamm pool %d", gammPoolId)) - cfmmPool, err := keepers.GAMMKeeper.GetCFMMPool(ctx, gammPoolId) if err != nil { return true, 0, "", sdk.Dec{}, err From 449d9a2dda8458dfe50c22132c34090c24cc8cee Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 16:01:07 -0500 Subject: [PATCH 27/41] enable superfluid assets both chains --- tests/e2e/configurer/upgrade.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/e2e/configurer/upgrade.go b/tests/e2e/configurer/upgrade.go index 64509b16c58..9424aad7204 100644 --- a/tests/e2e/configurer/upgrade.go +++ b/tests/e2e/configurer/upgrade.go @@ -145,13 +145,15 @@ func (uc *UpgradeConfigurer) CreatePreUpgradeState() error { wg.Add(2) - // Chain B + // Chain A go func() { defer wg.Done() - chainBNode.FundCommunityPool(initialization.ValidatorWalletName, strAllUpgradeBaseDenoms()) + chainANode.EnableSuperfluidAsset(chainA, v17SuperfluidAssets) }() + // Chain B + go func() { defer wg.Done() chainBNode.EnableSuperfluidAsset(chainB, v17SuperfluidAssets) From da5d1ee35a15f1fd413deba8ce029bee5dcc235c Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Mon, 7 Aug 2023 16:26:33 -0500 Subject: [PATCH 28/41] remove unused func --- tests/e2e/configurer/upgrade.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/e2e/configurer/upgrade.go b/tests/e2e/configurer/upgrade.go index 9424aad7204..f8d43db4ef2 100644 --- a/tests/e2e/configurer/upgrade.go +++ b/tests/e2e/configurer/upgrade.go @@ -442,18 +442,6 @@ func (uc *UpgradeConfigurer) upgradeContainers(chainConfig *chain.Config, propHe // START: CAN REMOVE POST v17 UPGRADE -func strAllUpgradeBaseDenoms() string { - upgradeBaseDenoms := "" - n := len(v17.AssetPairsForTestsOnly) - for i, assetPair := range v17.AssetPairsForTestsOnly { - upgradeBaseDenoms += "2000000" + assetPair.BaseAsset - if i < n-1 { // Check if it's not the last iteration - upgradeBaseDenoms += "," - } - } - return upgradeBaseDenoms -} - func v17GetSuperfluidAssets() string { assets := "" for _, assetPair := range v17.AssetPairsForTestsOnly { From bedf1a5ee3a80a7f956f15cdaec09c3a99e39c0d Mon Sep 17 00:00:00 2001 From: Nicolas Lara Date: Tue, 8 Aug 2023 12:16:00 +0200 Subject: [PATCH 29/41] setting the default ibc-hooks params --- app/upgrades/v17/upgrades.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 49224c50a04..213be151133 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -3,6 +3,7 @@ package v17 import ( "errors" "fmt" + ibchookstypes "github.com/osmosis-labs/osmosis/x/ibc-hooks/types" "time" errorsmod "cosmossdk.io/errors" @@ -48,6 +49,9 @@ func CreateUpgradeHandler( return nil, err } + // Set ibc-hooks params + keepers.IBCHooksKeeper.SetParams(ctx, ibchookstypes.DefaultParams()) + communityPoolAddress := keepers.AccountKeeper.GetModuleAddress(distrtypes.ModuleName) if ctx.ChainID() == mainnetChainID || ctx.ChainID() == e2eChainA || ctx.ChainID() == e2eChainB { From 0c2b1e7b267ae32358f7f834eae270079fbd8eba Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Tue, 8 Aug 2023 11:06:16 -0500 Subject: [PATCH 30/41] separate method for enable superfluid for testnet --- app/upgrades/v17/upgrades.go | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 213be151133..e183b47bdcc 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -3,9 +3,10 @@ package v17 import ( "errors" "fmt" - ibchookstypes "github.com/osmosis-labs/osmosis/x/ibc-hooks/types" "time" + ibchookstypes "github.com/osmosis-labs/osmosis/x/ibc-hooks/types" + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" @@ -105,9 +106,12 @@ func mainnetUpgradeHandler(ctx sdk.Context, keepers *keepers.AppKeepers, communi return err } - err = authorizeSuperfluidIfEnabled(ctx, keepers, assetPair.LinkedClassicPool, clPoolDenom) - if err != nil { - return err + if assetPair.Superfluid { + ctx.Logger().Info(fmt.Sprintf("gammPoolId %d is superfluid enabled, enabling %s as a superfluid asset", assetPair.LinkedClassicPool, clPoolDenom)) + err := authorizeSuperfluid(ctx, keepers, clPoolDenom) + if err != nil { + return err + } } err = manuallySetTWAPRecords(ctx, keepers, clPoolId) @@ -144,7 +148,7 @@ func testnetUpgradeHandler(ctx sdk.Context, keepers *keepers.AppKeepers, communi return err } - err = authorizeSuperfluidIfEnabled(ctx, keepers, gammPoolId, clPoolDenom) + err = authorizeSuperfluidIfEnabledTestnet(ctx, keepers, gammPoolId, clPoolDenom) if err != nil { return err } @@ -223,8 +227,18 @@ func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.App return clPoolDenom, clPoolId, nil } -// authorizeSuperfluidIfEnabled authorizes superfluid for a CL pool if the balancer pool is superfluid enabled. -func authorizeSuperfluidIfEnabled(ctx sdk.Context, keepers *keepers.AppKeepers, gammPoolId uint64, clPoolDenom string) (err error) { +// authorizeSuperfluid authorizes superfluid for the provided CL pool. +func authorizeSuperfluid(ctx sdk.Context, keepers *keepers.AppKeepers, clPoolDenom string) (err error) { + superfluidAsset := superfluidtypes.SuperfluidAsset{ + Denom: clPoolDenom, + AssetType: superfluidtypes.SuperfluidAssetTypeConcentratedShare, + } + return keepers.SuperfluidKeeper.AddNewSuperfluidAsset(ctx, superfluidAsset) +} + +// authorizeSuperfluidIfEnabledTestnet authorizes superfluid for a CL pool if the balancer pool is superfluid enabled. +// Since there is no assetList for testnet, we manually check each pool we are iterating over, so a different method for testnet must be used. +func authorizeSuperfluidIfEnabledTestnet(ctx sdk.Context, keepers *keepers.AppKeepers, gammPoolId uint64, clPoolDenom string) (err error) { // If pair was previously superfluid enabled, add the cl pool's full range denom as an authorized superfluid asset. poolShareDenom := fmt.Sprintf("gamm/pool/%d", gammPoolId) _, err = keepers.SuperfluidKeeper.GetSuperfluidAsset(ctx, poolShareDenom) From 34cff152f94a197bd18b28f5a92d1d60f1f2a103 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Tue, 8 Aug 2023 11:47:15 -0500 Subject: [PATCH 31/41] drastically simplify the upgrade handler --- app/upgrades/v17/constants.go | 83 +++++++++++++++ app/upgrades/v17/upgrades.go | 183 ++++++---------------------------- 2 files changed, 114 insertions(+), 152 deletions(-) diff --git a/app/upgrades/v17/constants.go b/app/upgrades/v17/constants.go index b1a8a292c01..f37f2ee9ad3 100644 --- a/app/upgrades/v17/constants.go +++ b/app/upgrades/v17/constants.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/osmosis-labs/osmosis/v17/app/upgrades" + poolManagerTypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" store "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -295,3 +296,85 @@ var AssetPairsForTestsOnly = []AssetPair{ Superfluid: false, }, } + +// InitializeAssetPairsTestnet initializes the asset pairs for the testnet, which is every osmo paired gamm pool with exactly 2 tokens. +func InitializeAssetPairsTestnet(ctx sdk.Context, keepers *keepers.AppKeepers) ([]AssetPair, error) { + superfluidKeeper := keepers.SuperfluidKeeper + testnetAssetPairs := []AssetPair{} + + // Retrieve all GAMM pools on the testnet. + pools, err := keepers.GAMMKeeper.GetPools(ctx) + if err != nil { + return nil, err + } + + for _, pool := range pools { + if pool.GetType() != poolManagerTypes.Balancer { + continue + } + + gammPoolId := pool.GetId() + + // Skip pools that are already linked. + clPoolId, err := keepers.GAMMKeeper.GetLinkedConcentratedPoolID(ctx, gammPoolId) + if err == nil && clPoolId != 0 { + ctx.Logger().Info(fmt.Sprintf("gammPoolId %d is already linked to CL pool %d, skipping", gammPoolId, clPoolId)) + continue + } + + cfmmPool, err := keepers.GAMMKeeper.GetCFMMPool(ctx, gammPoolId) + if err != nil { + return nil, err + } + + if len(cfmmPool.GetTotalPoolLiquidity(ctx)) != 2 { + continue + } + + poolCoins := cfmmPool.GetTotalPoolLiquidity(ctx) + + // We only want to upgrade pools paired with OSMO. OSMO will be the quote asset. + quoteAsset, baseAsset := "", "" + for _, coin := range poolCoins { + if coin.Denom == QuoteAsset { + quoteAsset = coin.Denom + } else { + baseAsset = coin.Denom + } + } + if quoteAsset == "" || baseAsset == "" { + continue + } + + // Set the spread factor to the same spread factor the GAMM pool was. + // If its spread factor is not authorized, set it to the first authorized non-zero spread factor. + spreadFactor := cfmmPool.GetSpreadFactor(ctx) + authorizedSpreadFactors := keepers.ConcentratedLiquidityKeeper.GetParams(ctx).AuthorizedSpreadFactors + spreadFactorAuthorized := false + for _, authorizedSpreadFactor := range authorizedSpreadFactors { + if authorizedSpreadFactor.Equal(spreadFactor) { + spreadFactorAuthorized = true + break + } + } + if !spreadFactorAuthorized { + spreadFactor = authorizedSpreadFactors[1] + } + + isSuperfluid := false + poolShareDenom := fmt.Sprintf("gamm/pool/%d", gammPoolId) + _, err = superfluidKeeper.GetSuperfluidAsset(ctx, poolShareDenom) + if err == nil { + isSuperfluid = true + } + + internalAssetPair := AssetPair{ + BaseAsset: baseAsset, + SpreadFactor: spreadFactor, + LinkedClassicPool: gammPoolId, + Superfluid: isSuperfluid, + } + testnetAssetPairs = append(testnetAssetPairs, internalAssetPair) + } + return testnetAssetPairs, nil +} diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index e183b47bdcc..1732e612b8d 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -17,7 +17,6 @@ import ( cltypes "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" gammtypes "github.com/osmosis-labs/osmosis/v17/x/gamm/types" gammmigration "github.com/osmosis-labs/osmosis/v17/x/gamm/types/migration" - poolManagerTypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" superfluidtypes "github.com/osmosis-labs/osmosis/v17/x/superfluid/types" "github.com/osmosis-labs/osmosis/v17/app/keepers" @@ -40,6 +39,7 @@ func CreateUpgradeHandler( keepers *keepers.AppKeepers, ) upgradetypes.UpgradeHandler { return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + var assetPairs []AssetPair poolLinks := []gammmigration.BalancerToConcentratedPoolLink{} fullRangeCoinsUsed := sdk.Coins{} @@ -50,24 +50,44 @@ func CreateUpgradeHandler( return nil, err } - // Set ibc-hooks params - keepers.IBCHooksKeeper.SetParams(ctx, ibchookstypes.DefaultParams()) - - communityPoolAddress := keepers.AccountKeeper.GetModuleAddress(distrtypes.ModuleName) - + // Set the asset pair list depending on the chain ID. if ctx.ChainID() == mainnetChainID || ctx.ChainID() == e2eChainA || ctx.ChainID() == e2eChainB { // Upgrades specific balancer pools to concentrated liquidity pools and links them to their CL equivalent. ctx.Logger().Info(fmt.Sprintf("Chain ID is %s, running mainnet upgrade handler", ctx.ChainID())) - err = mainnetUpgradeHandler(ctx, keepers, communityPoolAddress, &poolLinks, &fullRangeCoinsUsed) + assetPairs = InitializeAssetPairs(ctx, keepers) } else { // Upgrades all existing balancer pools to concentrated liquidity pools and links them to their CL equivalent. ctx.Logger().Info(fmt.Sprintf("Chain ID is %s, running testnet upgrade handler", ctx.ChainID())) - err = testnetUpgradeHandler(ctx, keepers, communityPoolAddress, &poolLinks, &fullRangeCoinsUsed) + assetPairs, err = InitializeAssetPairsTestnet(ctx, keepers) } if err != nil { return nil, err } + communityPoolAddress := keepers.AccountKeeper.GetModuleAddress(distrtypes.ModuleName) + + for _, assetPair := range assetPairs { + clPoolDenom, clPoolId, err := createCLPoolWithCommunityPoolPosition(ctx, keepers, assetPair.LinkedClassicPool, assetPair.BaseAsset, assetPair.SpreadFactor, communityPoolAddress, &poolLinks, &fullRangeCoinsUsed) + if errors.Is(err, notEnoughLiquidityForSwapErr) { + continue + } else if err != nil { + return nil, err + } + + if assetPair.Superfluid { + ctx.Logger().Info(fmt.Sprintf("gammPoolId %d is superfluid enabled, enabling %s as a superfluid asset", assetPair.LinkedClassicPool, clPoolDenom)) + err := authorizeSuperfluid(ctx, keepers, clPoolDenom) + if err != nil { + return nil, err + } + } + + err = manuallySetTWAPRecords(ctx, keepers, clPoolId) + if err != nil { + return nil, err + } + } + // Set the migration links in x/gamm. // This will also migrate the CFMM distribution records to point to the new CL pools. err = keepers.GAMMKeeper.UpdateMigrationRecords(ctx, poolLinks) @@ -88,6 +108,9 @@ func CreateUpgradeHandler( feePool.CommunityPool = newPool keepers.DistrKeeper.SetFeePool(ctx, feePool) + // Set ibc-hooks params + keepers.IBCHooksKeeper.SetParams(ctx, ibchookstypes.DefaultParams()) + // Reset the pool weights upon upgrade. This will add support for CW pools on ProtoRev. keepers.ProtoRevKeeper.SetInfoByPoolType(ctx, types.DefaultPoolTypeInfo) @@ -95,72 +118,6 @@ func CreateUpgradeHandler( } } -// mainnetUpgradeHandler creates CL pools for all balancer pools defined in the asset pairs struct. It also links the CL pools to their balancer pool counterpart, creates a full range position with the community pool, -// authorizes superfluid for the CL pool if the balancer pool is superfluid enabled, and manually sets the TWAP records for the CL pool. -func mainnetUpgradeHandler(ctx sdk.Context, keepers *keepers.AppKeepers, communityPoolAddress sdk.AccAddress, poolLinks *[]gammmigration.BalancerToConcentratedPoolLink, fullRangeCoinsUsed *sdk.Coins) error { - assetPairs := InitializeAssetPairs(ctx, keepers) - - for _, assetPair := range assetPairs { - clPoolDenom, clPoolId, err := createCLPoolWithCommunityPoolPosition(ctx, keepers, assetPair.LinkedClassicPool, assetPair.BaseAsset, assetPair.SpreadFactor, communityPoolAddress, poolLinks, fullRangeCoinsUsed) - if err != nil { - return err - } - - if assetPair.Superfluid { - ctx.Logger().Info(fmt.Sprintf("gammPoolId %d is superfluid enabled, enabling %s as a superfluid asset", assetPair.LinkedClassicPool, clPoolDenom)) - err := authorizeSuperfluid(ctx, keepers, clPoolDenom) - if err != nil { - return err - } - } - - err = manuallySetTWAPRecords(ctx, keepers, clPoolId) - if err != nil { - return err - } - } - - return nil -} - -// testnetUpgradeHandler creates CL pools for all existing balancer pools. It also links the CL pools to their balancer pool counterpart, creates a full range position with the community pool, -// authorizes superfluid for the CL pool if the balancer pool is superfluid enabled, and manually sets the TWAP records for the CL pool. -func testnetUpgradeHandler(ctx sdk.Context, keepers *keepers.AppKeepers, communityPoolAddress sdk.AccAddress, poolLinks *[]gammmigration.BalancerToConcentratedPoolLink, fullRangeCoinsUsed *sdk.Coins) error { - // Retrieve all GAMM pools on the testnet. - pools, err := keepers.GAMMKeeper.GetPools(ctx) - if err != nil { - return err - } - - for _, pool := range pools { - skipPool, gammPoolId, baseAsset, spreadFactor, err := testnetParsePoolRecord(ctx, pool, keepers) - if err != nil { - return err - } - if skipPool { - continue - } - - clPoolDenom, clPoolId, err := createCLPoolWithCommunityPoolPosition(ctx, keepers, gammPoolId, baseAsset, spreadFactor, communityPoolAddress, poolLinks, fullRangeCoinsUsed) - if errors.Is(err, notEnoughLiquidityForSwapErr) { - continue - } else if err != nil { - return err - } - - err = authorizeSuperfluidIfEnabledTestnet(ctx, keepers, gammPoolId, clPoolDenom) - if err != nil { - return err - } - - err = manuallySetTWAPRecords(ctx, keepers, clPoolId) - if err != nil { - return err - } - } - return nil -} - // createCLPoolWithCommunityPoolPosition creates a CL pool for a given balancer pool and adds a full range position with the community pool. func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.AppKeepers, gammPoolId uint64, baseAsset string, spreadFactor sdk.Dec, communityPoolAddress sdk.AccAddress, poolLinks *[]gammmigration.BalancerToConcentratedPoolLink, fullRangeCoinsUsed *sdk.Coins) (clPoolDenom string, clPoolId uint64, err error) { // Check if classic pool has enough liquidity to support a 0.1 OSMO swap before creating a CL pool. @@ -236,27 +193,6 @@ func authorizeSuperfluid(ctx sdk.Context, keepers *keepers.AppKeepers, clPoolDen return keepers.SuperfluidKeeper.AddNewSuperfluidAsset(ctx, superfluidAsset) } -// authorizeSuperfluidIfEnabledTestnet authorizes superfluid for a CL pool if the balancer pool is superfluid enabled. -// Since there is no assetList for testnet, we manually check each pool we are iterating over, so a different method for testnet must be used. -func authorizeSuperfluidIfEnabledTestnet(ctx sdk.Context, keepers *keepers.AppKeepers, gammPoolId uint64, clPoolDenom string) (err error) { - // If pair was previously superfluid enabled, add the cl pool's full range denom as an authorized superfluid asset. - poolShareDenom := fmt.Sprintf("gamm/pool/%d", gammPoolId) - _, err = keepers.SuperfluidKeeper.GetSuperfluidAsset(ctx, poolShareDenom) - if err == nil { - ctx.Logger().Info(fmt.Sprintf("%s is superfluid enabled, enabling %s as a superfluid asset", poolShareDenom, clPoolDenom)) - superfluidAsset := superfluidtypes.SuperfluidAsset{ - Denom: clPoolDenom, - AssetType: superfluidtypes.SuperfluidAssetTypeConcentratedShare, - } - err = keepers.SuperfluidKeeper.AddNewSuperfluidAsset(ctx, superfluidAsset) - if err != nil { - return err - } - } - ctx.Logger().Info(fmt.Sprintf("%s is not superfluid enabled, not enabling %s as a superfluid asset", poolShareDenom, clPoolDenom)) - return nil -} - // manuallySetTWAPRecords manually sets the TWAP records for a CL pool. This prevents a panic when the CL pool is first used. func manuallySetTWAPRecords(ctx sdk.Context, keepers *keepers.AppKeepers, clPoolId uint64) error { ctx.Logger().Info(fmt.Sprintf("manually setting twap record for newly created CL poolID %d", clPoolId)) @@ -271,60 +207,3 @@ func manuallySetTWAPRecords(ctx sdk.Context, keepers *keepers.AppKeepers, clPool } return nil } - -// testnetParsePoolRecord parses a pool record and returns whether or not to skip the pool, the pool's gammPoolId, the pool's base asset, and the pool's spread factor. -func testnetParsePoolRecord(ctx sdk.Context, pool poolManagerTypes.PoolI, keepers *keepers.AppKeepers) (bool, uint64, string, sdk.Dec, error) { - // We only want to upgrade balancer pools. - if pool.GetType() != poolManagerTypes.Balancer { - return true, 0, "", sdk.Dec{}, nil - } - - gammPoolId := pool.GetId() - - // Skip pools that are already linked. - clPoolId, err := keepers.GAMMKeeper.GetLinkedConcentratedPoolID(ctx, gammPoolId) - if err == nil && clPoolId != 0 { - ctx.Logger().Info(fmt.Sprintf("gammPoolId %d is already linked to CL pool %d, skipping", gammPoolId, clPoolId)) - return true, 0, "", sdk.Dec{}, nil - } - - cfmmPool, err := keepers.GAMMKeeper.GetCFMMPool(ctx, gammPoolId) - if err != nil { - return true, 0, "", sdk.Dec{}, err - } - - if len(cfmmPool.GetTotalPoolLiquidity(ctx)) != 2 { - return true, 0, "", sdk.Dec{}, nil - } - - poolCoins := cfmmPool.GetTotalPoolLiquidity(ctx) - - // We only want to upgrade pools paired with OSMO. OSMO will be the quote asset. - quoteAsset, baseAsset := "", "" - for _, coin := range poolCoins { - if coin.Denom == QuoteAsset { - quoteAsset = coin.Denom - } else { - baseAsset = coin.Denom - } - } - if quoteAsset == "" || baseAsset == "" { - return true, 0, "", sdk.Dec{}, nil - } - - // Set the spread factor to the same spread factor the GAMM pool was. - // If its spread factor is not authorized, set it to the first authorized non-zero spread factor. - spreadFactor := cfmmPool.GetSpreadFactor(ctx) - authorizedSpreadFactors := keepers.ConcentratedLiquidityKeeper.GetParams(ctx).AuthorizedSpreadFactors - spreadFactorAuthorized := false - for _, authorizedSpreadFactor := range authorizedSpreadFactors { - if authorizedSpreadFactor.Equal(spreadFactor) { - spreadFactorAuthorized = true - break - } - } - if !spreadFactorAuthorized { - spreadFactor = authorizedSpreadFactors[1] - } - return false, gammPoolId, baseAsset, spreadFactor, nil -} From 1801232756ce051df14f682dc28f09c9385d2e1b Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Tue, 8 Aug 2023 12:03:04 -0500 Subject: [PATCH 32/41] check superfluid error type directly --- app/upgrades/v17/constants.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/upgrades/v17/constants.go b/app/upgrades/v17/constants.go index f37f2ee9ad3..a11568c86d0 100644 --- a/app/upgrades/v17/constants.go +++ b/app/upgrades/v17/constants.go @@ -1,10 +1,14 @@ package v17 import ( + "errors" "fmt" + errorsmod "cosmossdk.io/errors" + "github.com/osmosis-labs/osmosis/v17/app/upgrades" poolManagerTypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" + "github.com/osmosis-labs/osmosis/v17/x/superfluid/types" store "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -364,7 +368,9 @@ func InitializeAssetPairsTestnet(ctx sdk.Context, keepers *keepers.AppKeepers) ( isSuperfluid := false poolShareDenom := fmt.Sprintf("gamm/pool/%d", gammPoolId) _, err = superfluidKeeper.GetSuperfluidAsset(ctx, poolShareDenom) - if err == nil { + if err != nil && !errors.Is(err, errorsmod.Wrapf(types.ErrNonSuperfluidAsset, "denom: %s", poolShareDenom)) { + return nil, err + } else if err == nil { isSuperfluid = true } From 3cd0af5b8d6f4be9dfce2864426b18507317903f Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Tue, 8 Aug 2023 13:10:22 -0500 Subject: [PATCH 33/41] remove use of pointer of coinsUsed and poolLinks --- app/upgrades/v17/upgrades.go | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 1732e612b8d..cf5e8bff309 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -40,8 +40,6 @@ func CreateUpgradeHandler( ) upgradetypes.UpgradeHandler { return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { var assetPairs []AssetPair - poolLinks := []gammmigration.BalancerToConcentratedPoolLink{} - fullRangeCoinsUsed := sdk.Coins{} // Run migrations before applying any other state changes. // NOTE: DO NOT PUT ANY STATE CHANGES BEFORE RunMigrations(). @@ -65,15 +63,21 @@ func CreateUpgradeHandler( } communityPoolAddress := keepers.AccountKeeper.GetModuleAddress(distrtypes.ModuleName) + poolLinks := []gammmigration.BalancerToConcentratedPoolLink{} + fullRangeCoinsUsed := sdk.Coins{} for _, assetPair := range assetPairs { - clPoolDenom, clPoolId, err := createCLPoolWithCommunityPoolPosition(ctx, keepers, assetPair.LinkedClassicPool, assetPair.BaseAsset, assetPair.SpreadFactor, communityPoolAddress, &poolLinks, &fullRangeCoinsUsed) + clPoolDenom, clPoolId, poolLink, coinsUser, err := createCLPoolWithCommunityPoolPosition(ctx, keepers, assetPair.LinkedClassicPool, assetPair.BaseAsset, assetPair.SpreadFactor, communityPoolAddress) if errors.Is(err, notEnoughLiquidityForSwapErr) { continue } else if err != nil { return nil, err } + // Track pool link created and coins used for the community pool. + poolLinks = append(poolLinks, poolLink) + fullRangeCoinsUsed = fullRangeCoinsUsed.Add(coinsUser...) + if assetPair.Superfluid { ctx.Logger().Info(fmt.Sprintf("gammPoolId %d is superfluid enabled, enabling %s as a superfluid asset", assetPair.LinkedClassicPool, clPoolDenom)) err := authorizeSuperfluid(ctx, keepers, clPoolDenom) @@ -119,33 +123,33 @@ func CreateUpgradeHandler( } // createCLPoolWithCommunityPoolPosition creates a CL pool for a given balancer pool and adds a full range position with the community pool. -func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.AppKeepers, gammPoolId uint64, baseAsset string, spreadFactor sdk.Dec, communityPoolAddress sdk.AccAddress, poolLinks *[]gammmigration.BalancerToConcentratedPoolLink, fullRangeCoinsUsed *sdk.Coins) (clPoolDenom string, clPoolId uint64, err error) { +func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.AppKeepers, gammPoolId uint64, baseAsset string, spreadFactor sdk.Dec, communityPoolAddress sdk.AccAddress) (clPoolDenom string, clPoolId uint64, poolLink gammmigration.BalancerToConcentratedPoolLink, coinsUsed sdk.Coins, err error) { // Check if classic pool has enough liquidity to support a 0.1 OSMO swap before creating a CL pool. // If not, skip the pool. osmoIn := sdk.NewCoin(QuoteAsset, sdk.NewInt(100000)) linkedClassicPool, err := keepers.PoolManagerKeeper.GetPool(ctx, gammPoolId) if err != nil { - return "", 0, err + return "", 0, gammmigration.BalancerToConcentratedPoolLink{}, nil, err } _, err = keepers.GAMMKeeper.CalcOutAmtGivenIn(ctx, linkedClassicPool, osmoIn, baseAsset, spreadFactor) if err != nil { - return "", 0, err + return "", 0, gammmigration.BalancerToConcentratedPoolLink{}, nil, err } // Create a concentrated liquidity pool for asset pair. ctx.Logger().Info(fmt.Sprintf("Creating CL pool from poolID (%d), baseAsset (%s), spreadFactor (%s), tickSpacing (%d)", gammPoolId, baseAsset, spreadFactor, TickSpacing)) clPool, err := keepers.GAMMKeeper.CreateConcentratedPoolFromCFMM(ctx, gammPoolId, baseAsset, spreadFactor, TickSpacing) if err != nil { - return "", 0, err + return "", 0, gammmigration.BalancerToConcentratedPoolLink{}, nil, err } clPoolId = clPool.GetId() clPoolDenom = cltypes.GetConcentratedLockupDenomFromPoolId(clPoolId) - // Add the pool link to the list of pool links (we set them all at once later) - *poolLinks = append(*poolLinks, gammmigration.BalancerToConcentratedPoolLink{ + // Create pool link object. + poolLink = gammmigration.BalancerToConcentratedPoolLink{ BalancerPoolId: gammPoolId, ClPoolId: clPoolId, - }) + } // Get community pool balance before swap and position creation commPoolBalanceBaseAssetPre := keepers.BankKeeper.GetBalance(ctx, communityPoolAddress, baseAsset) @@ -155,7 +159,7 @@ func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.App // Swap 0.1 OSMO for baseAsset from the community pool. respectiveBaseAssetInt, err := keepers.GAMMKeeper.SwapExactAmountIn(ctx, communityPoolAddress, linkedClassicPool, osmoIn, baseAsset, sdk.ZeroInt(), linkedClassicPool.GetSpreadFactor(ctx)) if err != nil { - return "", 0, err + return "", 0, gammmigration.BalancerToConcentratedPoolLink{}, nil, err } ctx.Logger().Info(fmt.Sprintf("Swapped %s for %s%s from the community pool", osmoIn.String(), respectiveBaseAssetInt.String(), baseAsset)) @@ -165,7 +169,7 @@ func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.App fullRangeCoins := sdk.NewCoins(respectiveBaseAsset, osmoIn) _, _, _, _, err = keepers.ConcentratedLiquidityKeeper.CreateFullRangePosition(ctx, clPoolId, communityPoolAddress, fullRangeCoins) if err != nil { - return "", 0, err + return "", 0, gammmigration.BalancerToConcentratedPoolLink{}, nil, err } // Get community pool balance after swap and position creation @@ -176,12 +180,9 @@ func createCLPoolWithCommunityPoolPosition(ctx sdk.Context, keepers *keepers.App // While we can be fairly certain the diff between these two is 0.2 OSMO, if for whatever reason // some baseAsset dust remains in the community pool and we don't account for it, when updating the // fee pool balance later, we will be off by that amount and will cause a panic. - coinsUsed := commPoolBalancePre.Sub(commPoolBalancePost) - - // Track the coins used to create the full range position (we manually update the fee pool later all at once). - *fullRangeCoinsUsed = fullRangeCoinsUsed.Add(coinsUsed...) + coinsUsed = commPoolBalancePre.Sub(commPoolBalancePost) - return clPoolDenom, clPoolId, nil + return clPoolDenom, clPoolId, poolLink, coinsUsed, nil } // authorizeSuperfluid authorizes superfluid for the provided CL pool. From 85abff8b834860ca2b4263e4a05fdf76a16f2c7a Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 9 Aug 2023 15:06:55 +0200 Subject: [PATCH 34/41] Update app/upgrades/v17/upgrades.go --- app/upgrades/v17/upgrades.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 11e5cb59f0e..88c00ba13c2 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -82,7 +82,7 @@ func CreateUpgradeHandler( fullRangeCoinsUsed := sdk.Coins{} for _, assetPair := range assetPairs { - clPoolDenom, clPoolId, poolLink, coinsUser, err := createCLPoolWithCommunityPoolPosition(ctx, keepers, assetPair.LinkedClassicPool, assetPair.BaseAsset, assetPair.SpreadFactor, communityPoolAddress) + clPoolDenom, clPoolId, poolLink, coinsUsed, err := createCLPoolWithCommunityPoolPosition(ctx, keepers, assetPair.LinkedClassicPool, assetPair.BaseAsset, assetPair.SpreadFactor, communityPoolAddress) if errors.Is(err, notEnoughLiquidityForSwapErr) { continue } else if err != nil { From 27e07ca37399c9b3c01251bbfd1738bc2a67fb27 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 9 Aug 2023 15:07:04 +0200 Subject: [PATCH 35/41] Update app/upgrades/v17/upgrades.go --- app/upgrades/v17/upgrades.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 88c00ba13c2..b70a0a711d0 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -91,7 +91,7 @@ func CreateUpgradeHandler( // Track pool link created and coins used for the community pool. poolLinks = append(poolLinks, poolLink) - fullRangeCoinsUsed = fullRangeCoinsUsed.Add(coinsUser...) + fullRangeCoinsUsed = fullRangeCoinsUsed.Add(coinsUsed...) if assetPair.Superfluid { ctx.Logger().Info(fmt.Sprintf("gammPoolId %d is superfluid enabled, enabling %s as a superfluid asset", assetPair.LinkedClassicPool, clPoolDenom)) From d400d36335710478001722270b25f0d86f9e32ea Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 9 Aug 2023 09:59:53 -0500 Subject: [PATCH 36/41] add spot price check when adding testnet assets --- app/upgrades/v17/constants.go | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/app/upgrades/v17/constants.go b/app/upgrades/v17/constants.go index a11568c86d0..84c1539d54d 100644 --- a/app/upgrades/v17/constants.go +++ b/app/upgrades/v17/constants.go @@ -7,6 +7,7 @@ import ( errorsmod "cosmossdk.io/errors" "github.com/osmosis-labs/osmosis/v17/app/upgrades" + cltypes "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" poolManagerTypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" "github.com/osmosis-labs/osmosis/v17/x/superfluid/types" @@ -331,15 +332,16 @@ func InitializeAssetPairsTestnet(ctx sdk.Context, keepers *keepers.AppKeepers) ( return nil, err } - if len(cfmmPool.GetTotalPoolLiquidity(ctx)) != 2 { + totalPoolLiquidity := cfmmPool.GetTotalPoolLiquidity(ctx) + + // Skip pools that are not paired with exactly 2 tokens. + if len(totalPoolLiquidity) != 2 { continue } - poolCoins := cfmmPool.GetTotalPoolLiquidity(ctx) - - // We only want to upgrade pools paired with OSMO. OSMO will be the quote asset. + // Skip pools that aren't paired with OSMO. OSMO will be the quote asset. quoteAsset, baseAsset := "", "" - for _, coin := range poolCoins { + for _, coin := range totalPoolLiquidity { if coin.Denom == QuoteAsset { quoteAsset = coin.Denom } else { @@ -350,9 +352,19 @@ func InitializeAssetPairsTestnet(ctx sdk.Context, keepers *keepers.AppKeepers) ( continue } + // Check if swapping 0.1 OSMO results in a spot price less than the min or greater than the max + spreadFactor := cfmmPool.GetSpreadFactor(ctx) + respectiveBaseAsset, err := keepers.GAMMKeeper.CalcOutAmtGivenIn(ctx, cfmmPool, sdk.NewCoin(QuoteAsset, sdk.NewInt(10000000000)), baseAsset, spreadFactor) + if err != nil { + return nil, err + } + expectedSpotPriceFromSwap := sdk.NewDec(10000000000).Quo(respectiveBaseAsset.Amount.ToDec()) + if expectedSpotPriceFromSwap.LT(cltypes.MinSpotPrice) || expectedSpotPriceFromSwap.GT(cltypes.MaxSpotPrice) { + continue + } + // Set the spread factor to the same spread factor the GAMM pool was. // If its spread factor is not authorized, set it to the first authorized non-zero spread factor. - spreadFactor := cfmmPool.GetSpreadFactor(ctx) authorizedSpreadFactors := keepers.ConcentratedLiquidityKeeper.GetParams(ctx).AuthorizedSpreadFactors spreadFactorAuthorized := false for _, authorizedSpreadFactor := range authorizedSpreadFactors { From 2886d7a859abb7d7251b89912bee8470094f9626 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 9 Aug 2023 10:27:19 -0500 Subject: [PATCH 37/41] fix osmo amount --- app/upgrades/v17/constants.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/upgrades/v17/constants.go b/app/upgrades/v17/constants.go index 84c1539d54d..bd5f000e44e 100644 --- a/app/upgrades/v17/constants.go +++ b/app/upgrades/v17/constants.go @@ -354,11 +354,11 @@ func InitializeAssetPairsTestnet(ctx sdk.Context, keepers *keepers.AppKeepers) ( // Check if swapping 0.1 OSMO results in a spot price less than the min or greater than the max spreadFactor := cfmmPool.GetSpreadFactor(ctx) - respectiveBaseAsset, err := keepers.GAMMKeeper.CalcOutAmtGivenIn(ctx, cfmmPool, sdk.NewCoin(QuoteAsset, sdk.NewInt(10000000000)), baseAsset, spreadFactor) + respectiveBaseAsset, err := keepers.GAMMKeeper.CalcOutAmtGivenIn(ctx, cfmmPool, sdk.NewCoin(QuoteAsset, sdk.NewInt(100000)), baseAsset, spreadFactor) if err != nil { return nil, err } - expectedSpotPriceFromSwap := sdk.NewDec(10000000000).Quo(respectiveBaseAsset.Amount.ToDec()) + expectedSpotPriceFromSwap := sdk.NewDec(100000).Quo(respectiveBaseAsset.Amount.ToDec()) if expectedSpotPriceFromSwap.LT(cltypes.MinSpotPrice) || expectedSpotPriceFromSwap.GT(cltypes.MaxSpotPrice) { continue } From d778f12fa66b5a57cbd55c5af602d47332e1f99c Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 9 Aug 2023 10:31:17 -0500 Subject: [PATCH 38/41] add error check --- app/upgrades/v17/constants.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/upgrades/v17/constants.go b/app/upgrades/v17/constants.go index bd5f000e44e..5370ae19f02 100644 --- a/app/upgrades/v17/constants.go +++ b/app/upgrades/v17/constants.go @@ -8,6 +8,7 @@ import ( "github.com/osmosis-labs/osmosis/v17/app/upgrades" cltypes "github.com/osmosis-labs/osmosis/v17/x/concentrated-liquidity/types" + gammtypes "github.com/osmosis-labs/osmosis/v17/x/gamm/types" poolManagerTypes "github.com/osmosis-labs/osmosis/v17/x/poolmanager/types" "github.com/osmosis-labs/osmosis/v17/x/superfluid/types" @@ -355,7 +356,11 @@ func InitializeAssetPairsTestnet(ctx sdk.Context, keepers *keepers.AppKeepers) ( // Check if swapping 0.1 OSMO results in a spot price less than the min or greater than the max spreadFactor := cfmmPool.GetSpreadFactor(ctx) respectiveBaseAsset, err := keepers.GAMMKeeper.CalcOutAmtGivenIn(ctx, cfmmPool, sdk.NewCoin(QuoteAsset, sdk.NewInt(100000)), baseAsset, spreadFactor) - if err != nil { + if errors.Is(err, gammtypes.ErrInvalidMathApprox) { + // Result is zero, which means 0.1 osmo was too much for the swap to handle. + // This is likely because the pool liquidity is too small, so we skip it. + continue + } else if err != nil { return nil, err } expectedSpotPriceFromSwap := sdk.NewDec(100000).Quo(respectiveBaseAsset.Amount.ToDec()) From 5fdb4150706958bc48bf9873ed6d29e18006fd3a Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 9 Aug 2023 16:26:21 -0500 Subject: [PATCH 39/41] add additional check from testnet to mainnet --- app/upgrades/v17/constants.go | 37 ++++++++++++++++++++++--------- app/upgrades/v17/upgrades.go | 8 +++---- app/upgrades/v17/upgrades_test.go | 3 ++- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/app/upgrades/v17/constants.go b/app/upgrades/v17/constants.go index 5370ae19f02..c45580700d6 100644 --- a/app/upgrades/v17/constants.go +++ b/app/upgrades/v17/constants.go @@ -75,13 +75,13 @@ var AssetPairs = []AssetPair{ } // AssetPairs contract: all AssetPairs being initialized in this upgrade handler all have the same quote asset (OSMO). -func InitializeAssetPairs(ctx sdk.Context, keepers *keepers.AppKeepers) []AssetPair { +func InitializeAssetPairs(ctx sdk.Context, keepers *keepers.AppKeepers) ([]AssetPair, error) { gammKeeper := keepers.GAMMKeeper superfluidKeeper := keepers.SuperfluidKeeper for i, assetPair := range AssetPairs { pool, err := gammKeeper.GetCFMMPool(ctx, assetPair.LinkedClassicPool) if err != nil { - panic(err) + return nil, err } // Set the base asset as the non-osmo asset in the pool @@ -93,6 +93,13 @@ func InitializeAssetPairs(ctx sdk.Context, keepers *keepers.AppKeepers) []AssetP } } + // Check if pool's resulting spot price will fall within min and max spot price bounds. + spreadFactor := pool.GetSpreadFactor(ctx) + err = validateSpotPriceFallsInBounds(ctx, pool, keepers, AssetPairs[i].BaseAsset, spreadFactor) + if err != nil { + return nil, err + } + // If the spread factor is not manually set above, set it to the the same value as the pool's spread factor. if assetPair.SpreadFactor.IsNil() { AssetPairs[i].SpreadFactor = pool.GetSpreadFactor(ctx) @@ -107,7 +114,7 @@ func InitializeAssetPairs(ctx sdk.Context, keepers *keepers.AppKeepers) []AssetP } AssetPairs[i].Superfluid = true } - return AssetPairs + return AssetPairs, nil } // The values below this comment are used strictly for testing. @@ -353,20 +360,15 @@ func InitializeAssetPairsTestnet(ctx sdk.Context, keepers *keepers.AppKeepers) ( continue } - // Check if swapping 0.1 OSMO results in a spot price less than the min or greater than the max spreadFactor := cfmmPool.GetSpreadFactor(ctx) - respectiveBaseAsset, err := keepers.GAMMKeeper.CalcOutAmtGivenIn(ctx, cfmmPool, sdk.NewCoin(QuoteAsset, sdk.NewInt(100000)), baseAsset, spreadFactor) + err = validateSpotPriceFallsInBounds(ctx, cfmmPool, keepers, baseAsset, spreadFactor) if errors.Is(err, gammtypes.ErrInvalidMathApprox) { // Result is zero, which means 0.1 osmo was too much for the swap to handle. - // This is likely because the pool liquidity is too small, so we skip it. + // This is likely because the pool liquidity is too small, so since this just testnet, we skip it. continue } else if err != nil { return nil, err } - expectedSpotPriceFromSwap := sdk.NewDec(100000).Quo(respectiveBaseAsset.Amount.ToDec()) - if expectedSpotPriceFromSwap.LT(cltypes.MinSpotPrice) || expectedSpotPriceFromSwap.GT(cltypes.MaxSpotPrice) { - continue - } // Set the spread factor to the same spread factor the GAMM pool was. // If its spread factor is not authorized, set it to the first authorized non-zero spread factor. @@ -401,3 +403,18 @@ func InitializeAssetPairsTestnet(ctx sdk.Context, keepers *keepers.AppKeepers) ( } return testnetAssetPairs, nil } + +// validateSpotPriceFallsInBounds ensures that after swapping in the OSMO for the baseAsset, the resulting spot price is within the +// min and max spot price bounds of the concentrated liquidity module. +func validateSpotPriceFallsInBounds(ctx sdk.Context, cfmmPool gammtypes.CFMMPoolI, keepers *keepers.AppKeepers, baseAsset string, spreadFactor sdk.Dec) error { + // Check if swapping 0.1 OSMO results in a spot price less than the min or greater than the max + respectiveBaseAsset, err := keepers.GAMMKeeper.CalcOutAmtGivenIn(ctx, cfmmPool, sdk.NewCoin(QuoteAsset, sdk.NewInt(100000)), baseAsset, spreadFactor) + if err != nil { + return err + } + expectedSpotPriceFromSwap := sdk.NewDec(100000).Quo(respectiveBaseAsset.Amount.ToDec()) + if expectedSpotPriceFromSwap.LT(cltypes.MinSpotPrice) || expectedSpotPriceFromSwap.GT(cltypes.MaxSpotPrice) { + return err + } + return nil +} diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index c4e21c79573..4ba71db2828 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -66,14 +66,14 @@ func CreateUpgradeHandler( if ctx.ChainID() == mainnetChainID || ctx.ChainID() == e2eChainA || ctx.ChainID() == e2eChainB { // Upgrades specific balancer pools to concentrated liquidity pools and links them to their CL equivalent. ctx.Logger().Info(fmt.Sprintf("Chain ID is %s, running mainnet upgrade handler", ctx.ChainID())) - assetPairs = InitializeAssetPairs(ctx, keepers) + assetPairs, err = InitializeAssetPairs(ctx, keepers) } else { // Upgrades all existing balancer pools to concentrated liquidity pools and links them to their CL equivalent. ctx.Logger().Info(fmt.Sprintf("Chain ID is %s, running testnet upgrade handler", ctx.ChainID())) assetPairs, err = InitializeAssetPairsTestnet(ctx, keepers) - if err != nil { - return nil, err - } + } + if err != nil { + return nil, err } // Get community pool address. diff --git a/app/upgrades/v17/upgrades_test.go b/app/upgrades/v17/upgrades_test.go index 21cdf4fa0ce..1ceeb08fdb4 100644 --- a/app/upgrades/v17/upgrades_test.go +++ b/app/upgrades/v17/upgrades_test.go @@ -287,7 +287,8 @@ func (suite *UpgradeTestSuite) TestUpgrade() { communityPoolBalancePost := suite.App.BankKeeper.GetAllBalances(suite.Ctx, communityPoolAddress) feePoolCommunityPoolPost := suite.App.DistrKeeper.GetFeePool(suite.Ctx).CommunityPool - assetPairs := v17.InitializeAssetPairs(ctx, keepers) + assetPairs, err := v17.InitializeAssetPairs(ctx, keepers) + suite.Require().NoError(err) for i, assetPair := range assetPairs { // Get balancer pool's spot price. From ffd220d4d283955623037f12d318fdafdf0c26f2 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 9 Aug 2023 16:33:16 -0500 Subject: [PATCH 40/41] remove this check from mainnet handler --- app/upgrades/v17/constants.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/upgrades/v17/constants.go b/app/upgrades/v17/constants.go index c45580700d6..d9c099a32ae 100644 --- a/app/upgrades/v17/constants.go +++ b/app/upgrades/v17/constants.go @@ -93,13 +93,6 @@ func InitializeAssetPairs(ctx sdk.Context, keepers *keepers.AppKeepers) ([]Asset } } - // Check if pool's resulting spot price will fall within min and max spot price bounds. - spreadFactor := pool.GetSpreadFactor(ctx) - err = validateSpotPriceFallsInBounds(ctx, pool, keepers, AssetPairs[i].BaseAsset, spreadFactor) - if err != nil { - return nil, err - } - // If the spread factor is not manually set above, set it to the the same value as the pool's spread factor. if assetPair.SpreadFactor.IsNil() { AssetPairs[i].SpreadFactor = pool.GetSpreadFactor(ctx) From 4b63216293be2aa307843e26bb9142e03c670827 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 9 Aug 2023 16:37:05 -0500 Subject: [PATCH 41/41] fix lingering merge conflict --- tests/cl-genesis-positions/convert.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cl-genesis-positions/convert.go b/tests/cl-genesis-positions/convert.go index ecf0b8311e2..3e3cdb7e862 100644 --- a/tests/cl-genesis-positions/convert.go +++ b/tests/cl-genesis-positions/convert.go @@ -111,7 +111,7 @@ func ConvertSubgraphToOsmosisGenesis(positionCreatorAddresses []sdk.AccAddress, // Initialize first position to be 1:1 price // this is because the first position must have non-zero token0 and token1 to initialize the price // however, our data has first position with non-zero amount. - _, _, _, _, err = osmosis.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(osmosis.Ctx, pool.GetId(), osmosis.TestAccs[0], sdk.NewCoins(sdk.NewCoin(msgCreatePool.Denom0, sdk.NewInt(100)), sdk.NewCoin(msgCreatePool.Denom1, sdk.NewInt(100)))) + _, err = osmosis.App.ConcentratedLiquidityKeeper.CreateFullRangePosition(osmosis.Ctx, pool.GetId(), osmosis.TestAccs[0], sdk.NewCoins(sdk.NewCoin(msgCreatePool.Denom0, sdk.NewInt(100)), sdk.NewCoin(msgCreatePool.Denom1, sdk.NewInt(100)))) if err != nil { panic(err) }