Skip to content

Commit

Permalink
feat: multi-network upgrade handler (#5959)
Browse files Browse the repository at this point in the history
* multi-network upgrade handler

* run mainnet upgrade handler for e2e network IDs

* fixes

* fix

* widen tolerance

* more resilient way to calculate coins used

* add logs to upgrade handler

* scale error tolerance with spread factor

* change back init tag

* update changelog

* Fix imports

* check liquidity prior to creating pool

* check base/quote rather than all denoms

* check if pool only has 2 assets

* skip pools that are already linked

* add log and fix issue

* add an additional log

* more logs

* more prints

* skip if incentive gauge duration does not exist

* use gogotypes

* use store.Has

* error instead of panic on getgaugeId from poolId

* Update app/upgrades/v17/upgrades_test.go

Co-authored-by: Roman <[email protected]>

* remove extra prints

* remove old logs

* enable superfluid assets both chains

* remove unused func

* setting the default ibc-hooks params

* separate method for enable superfluid for testnet

* drastically simplify the upgrade handler

* check superfluid error type directly

* remove use of pointer of coinsUsed and poolLinks

* Update app/upgrades/v17/upgrades.go

* Update app/upgrades/v17/upgrades.go

* add spot price check when adding testnet assets

* fix osmo amount

* add error check

* add additional check from testnet to mainnet

* remove this check from mainnet handler

* fix lingering merge conflict

---------

Co-authored-by: devbot-wizard <[email protected]>
Co-authored-by: Roman <[email protected]>
Co-authored-by: Nicolas Lara <[email protected]>
  • Loading branch information
4 people authored Aug 10, 2023
1 parent af41714 commit a0bfd58
Show file tree
Hide file tree
Showing 10 changed files with 472 additions and 114 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,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
* [#5964](https://github.com/osmosis-labs/osmosis/pull/5964) fix e2e test concurrency bugs
* [#5948] (https://github.com/osmosis-labs/osmosis/pull/5948) Parameterizing Pool Type Information in Protorev
* [#6001](https://github.com/osmosis-labs/osmosis/pull/6001) feat: improve set-env CLI cmd
Expand Down
122 changes: 119 additions & 3 deletions app/upgrades/v17/constants.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package v17

import (
"errors"
"fmt"

errorsmod "cosmossdk.io/errors"

"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"

store "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -68,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
Expand All @@ -100,7 +107,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.
Expand Down Expand Up @@ -295,3 +302,112 @@ 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
}

totalPoolLiquidity := cfmmPool.GetTotalPoolLiquidity(ctx)

// Skip pools that are not paired with exactly 2 tokens.
if len(totalPoolLiquidity) != 2 {
continue
}

// Skip pools that aren't paired with OSMO. OSMO will be the quote asset.
quoteAsset, baseAsset := "", ""
for _, coin := range totalPoolLiquidity {
if coin.Denom == QuoteAsset {
quoteAsset = coin.Denom
} else {
baseAsset = coin.Denom
}
}
if quoteAsset == "" || baseAsset == "" {
continue
}

spreadFactor := cfmmPool.GetSpreadFactor(ctx)
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 since this just testnet, we skip it.
continue
} else if err != nil {
return nil, err
}

// 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.
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 && !errors.Is(err, errorsmod.Wrapf(types.ErrNonSuperfluidAsset, "denom: %s", poolShareDenom)) {
return nil, err
} else if err == nil {
isSuperfluid = true
}

internalAssetPair := AssetPair{
BaseAsset: baseAsset,
SpreadFactor: spreadFactor,
LinkedClassicPool: gammPoolId,
Superfluid: isSuperfluid,
}
testnetAssetPairs = append(testnetAssetPairs, internalAssetPair)
}
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
}
Loading

0 comments on commit a0bfd58

Please sign in to comment.