Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

migrate stXXX/XXX constant product pool -> stableswap pool #4384

Merged
merged 22 commits into from
Feb 23, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/upgrades/v15/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ import (
// UpgradeName defines the on-chain upgrade name for the Osmosis v15 upgrade.
const UpgradeName = "v15"

// pool ids to migrate
const stOSMO_OSMOPoolId = 833
const stJUNO_JUNOPoolId = 817
const stSTARS_STARSPoolId = 810

mattverse marked this conversation as resolved.
Show resolved Hide resolved
var Upgrade = upgrades.Upgrade{
UpgradeName: UpgradeName,
CreateUpgradeHandler: CreateUpgradeHandler,
Expand Down
5 changes: 5 additions & 0 deletions app/upgrades/v15/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"

gammkeeper "github.com/osmosis-labs/osmosis/v14/x/gamm/keeper"
"github.com/osmosis-labs/osmosis/v14/x/poolmanager"
poolmanagerkeeper "github.com/osmosis-labs/osmosis/v14/x/poolmanager"
)

Expand All @@ -21,3 +22,7 @@ func RegisterOsmoIonMetadata(ctx sdk.Context, bankKeeper bankkeeper.Keeper) {
func SetICQParams(ctx sdk.Context, icqKeeper *icqkeeper.Keeper) {
setICQParams(ctx, icqKeeper)
}

func MigrateBalancerPoolToSolidlyStable(ctx sdk.Context, gammKeeper *gammkeeper.Keeper, poolmanagerKeeper *poolmanager.Keeper, poolId uint64) {
migrateBalancerPoolToSolidlyStable(ctx, gammKeeper, poolmanagerKeeper, poolId)
}
70 changes: 68 additions & 2 deletions app/upgrades/v15/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,28 @@ import (
"reflect"
"testing"

gamm "github.com/osmosis-labs/osmosis/v14/x/gamm/keeper"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/suite"

"github.com/osmosis-labs/osmosis/v14/app/apptesting"
v15 "github.com/osmosis-labs/osmosis/v14/app/upgrades/v15"
gamm "github.com/osmosis-labs/osmosis/v14/x/gamm/keeper"
balancer "github.com/osmosis-labs/osmosis/v14/x/gamm/pool-models/balancer"
balancertypes "github.com/osmosis-labs/osmosis/v14/x/gamm/pool-models/balancer"
poolmanagertypes "github.com/osmosis-labs/osmosis/v14/x/poolmanager/types"
)

type UpgradeTestSuite struct {
apptesting.KeeperTestHelper
}

var DefaultAcctFunds sdk.Coins = sdk.NewCoins(
sdk.NewCoin("uosmo", sdk.NewInt(10000000000)),
sdk.NewCoin("foo", sdk.NewInt(10000000)),
sdk.NewCoin("bar", sdk.NewInt(10000000)),
sdk.NewCoin("baz", sdk.NewInt(10000000)),
)

func (suite *UpgradeTestSuite) SetupTest() {
suite.Setup()
}
Expand Down Expand Up @@ -67,6 +77,62 @@ func (suite *UpgradeTestSuite) TestMigrateNextPoolIdAndCreatePool() {
suite.Require().Equal(gammPoolCreationFee, poolmanagerPoolCreationFee)
}


func (suite *UpgradeTestSuite) TestMigrateBalancerToStablePools() {
suite.SetupTest() // reset

ctx := suite.Ctx
gammKeeper := suite.App.GAMMKeeper
poolmanagerKeeper := suite.App.PoolManagerKeeper
// bankKeeper := suite.App.BankKeeper
testAccount := suite.TestAccs[0]

// Mint some assets to the accounts.
suite.FundAcc(testAccount, DefaultAcctFunds)

// Create the balancer pool
swapFee, err := sdk.NewDecFromStr("0.003")
exitFee, err := sdk.NewDecFromStr("0.025")
poolID, err := suite.App.PoolManagerKeeper.CreatePool(
suite.Ctx,
balancer.NewMsgCreateBalancerPool(suite.TestAccs[0],
balancer.PoolParams{
SwapFee: swapFee,
ExitFee: exitFee,
},
[]balancertypes.PoolAsset{
{
Weight: sdk.NewInt(100),
Token: sdk.NewCoin("foo", sdk.NewInt(5000000)),
},
{
Weight: sdk.NewInt(200),
Token: sdk.NewCoin("bar", sdk.NewInt(5000000)),
},
},
""),
)
_ = poolID
suite.Require().NoError(err)

// create the pool
balancerPool, err := gammKeeper.GetPool(suite.Ctx, poolID)
suite.Require().NoError(err)
balancerShares := balancerPool.GetTotalShares()
p0mvn marked this conversation as resolved.
Show resolved Hide resolved

// test migrating the balancer pool to a stable pool
v15.MigrateBalancerPoolToSolidlyStable(ctx, gammKeeper, poolmanagerKeeper, poolID)

// check that the pool is now a stable pool
stablepool, err := gammKeeper.GetPool(ctx, poolID)
suite.Require().NoError(err)
suite.Require().Equal(stablepool.GetType(), poolmanagertypes.Stableswap)

// check that the number of stableswap LP shares is the same as the number of balancer LP shares
suite.Require().Equal(balancerShares.String(), stablepool.GetTotalShares().String())
p0mvn marked this conversation as resolved.
Show resolved Hide resolved

}

func (suite *UpgradeTestSuite) TestRegisterOsmoIonMetadata() {
suite.SetupTest() // reset

Expand Down
51 changes: 50 additions & 1 deletion app/upgrades/v15/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
"github.com/osmosis-labs/osmosis/v14/wasmbinding"
icqkeeper "github.com/strangelove-ventures/async-icq/v4/keeper"
icqtypes "github.com/strangelove-ventures/async-icq/v4/types"
packetforwardtypes "github.com/strangelove-ventures/packet-forward-middleware/v4/router/types"

"github.com/osmosis-labs/osmosis/v14/wasmbinding"

banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"

bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
Expand All @@ -17,6 +18,8 @@ import (
appParams "github.com/osmosis-labs/osmosis/v14/app/params"
"github.com/osmosis-labs/osmosis/v14/app/upgrades"
gammkeeper "github.com/osmosis-labs/osmosis/v14/x/gamm/keeper"
"github.com/osmosis-labs/osmosis/v14/x/gamm/pool-models/stableswap"
gammtypes "github.com/osmosis-labs/osmosis/v14/x/gamm/types"
"github.com/osmosis-labs/osmosis/v14/x/poolmanager"
poolmanagertypes "github.com/osmosis-labs/osmosis/v14/x/poolmanager/types"
)
Expand Down Expand Up @@ -47,6 +50,10 @@ func CreateUpgradeHandler(
// They are added in this upgrade.
registerOsmoIonMetadata(ctx, keepers.BankKeeper)

// Stride stXXX/XXX pools are being migrated from the standard balancer curve to the
// solidly stable curve.
migrateBalancerPoolsToSolidlyStable(ctx, keepers.GAMMKeeper, keepers.PoolManagerKeeper)

return mm.RunMigrations(ctx, configurator, fromVM)
}
}
Expand All @@ -59,6 +66,48 @@ func setICQParams(ctx sdk.Context, icqKeeper *icqkeeper.Keeper) {
icqKeeper.SetParams(ctx, icqparams)
}

func migrateBalancerPoolsToSolidlyStable(ctx sdk.Context, gammKeeper *gammkeeper.Keeper, poolmanagerKeeper *poolmanager.Keeper) {
// migrate stOSMO_OSMOPoolId, stJUNO_JUNOPoolId, stSTARS_STARSPoolId
pools := []uint64{stOSMO_OSMOPoolId, stJUNO_JUNOPoolId, stSTARS_STARSPoolId}
for _, poolId := range pools {
migrateBalancerPoolToSolidlyStable(ctx, gammKeeper, poolmanagerKeeper, poolId)
}
}

func migrateBalancerPoolToSolidlyStable(ctx sdk.Context, gammKeeper *gammkeeper.Keeper, poolmanagerKeeper *poolmanager.Keeper, poolId uint64) {
// fetch the pool with the given poolId
balancerPool, err := gammKeeper.GetPool(ctx, poolId)
if err != nil {
panic(err)
}

// initialize the stableswap pool
stableswapPool, err := stableswap.NewStableswapPool(
poolId,
stableswap.PoolParams{SwapFee: balancerPool.GetSwapFee(ctx), ExitFee: balancerPool.GetExitFee(ctx)},
balancerPool.GetTotalPoolLiquidity(ctx),
[]uint64{1, 1},
"osmo1k8c2m5cn322akk5wy8lpt87dd2f4yh9afcd7af", // Stride Foundation 2/3 multisig
asalzmann marked this conversation as resolved.
Show resolved Hide resolved
p0mvn marked this conversation as resolved.
Show resolved Hide resolved
"",
)
if err != nil {
panic(err)
}

// ensure the number of stableswap LP shares is the same as the number of balancer LP shares
totalShares := sdk.NewCoin(
gammtypes.GetPoolShareDenom(poolId),
balancerPool.GetTotalShares(),
)
stableswapPool.TotalShares = totalShares
p0mvn marked this conversation as resolved.
Show resolved Hide resolved

// overwrite the balancer pool with the new stableswap pool
asalzmann marked this conversation as resolved.
Show resolved Hide resolved
err = gammKeeper.OverwritePool(ctx, &stableswapPool)
mattverse marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
panic(err)
}
}

func migrateNextPoolId(ctx sdk.Context, gammKeeper *gammkeeper.Keeper, poolmanagerKeeper *poolmanager.Keeper) {
// N.B: pool id in gamm is to be deprecated in the future
// Instead,it is moved to poolmanager.
Expand Down
17 changes: 17 additions & 0 deletions tests/e2e/configurer/chain/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,23 @@ func (n *NodeConfig) SwapExactAmountIn(tokenInCoin, tokenOutMinAmountInt string,
n.LogActionF("successfully swapped")
}

// osmosisd tx gamm join-pool max-amounts-in pool-id share-amount-out --from <address>
func (n *NodeConfig) JoinPool(maxAmountsIn string, poolId string, shareAmountOut string, from string) {
n.LogActionF("joining pool %s with maxAmountsIn %s to get shareAmountOut (%s) from (%s)", poolId, maxAmountsIn, shareAmountOut, from)
cmd := []string{"osmosisd", "tx", "gamm", "swap-exact-amount-in", maxAmountsIn, poolId, shareAmountOut, fmt.Sprintf("--from=%s", from)}
_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
require.NoError(n.t, err)
n.LogActionF("successfully joined pool")
}

func (n *NodeConfig) ExitPool(from, minAmountsOut string, poolId string, shareAmountIn string) {
n.LogActionF("exiting gamm pool")
cmd := []string{"osmosisd", "tx", "gamm", "exit-pool", minAmountsOut, poolId, shareAmountIn, fmt.Sprintf("--from=%s", from)}
_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
require.NoError(n.t, err)
n.LogActionF("successfully exited pool %s, minAmountsOut %s, shareAmountIn %s", poolId, minAmountsOut, shareAmountIn)
}

func (n *NodeConfig) SubmitUpgradeProposal(upgradeVersion string, upgradeHeight int64, initialDeposit sdk.Coin) {
n.LogActionF("submitting upgrade proposal %s for height %d", upgradeVersion, upgradeHeight)
cmd := []string{"osmosisd", "tx", "gov", "submit-proposal", "software-upgrade", upgradeVersion, fmt.Sprintf("--title=\"%s upgrade\"", upgradeVersion), "--description=\"upgrade proposal submission\"", fmt.Sprintf("--upgrade-height=%d", upgradeHeight), "--upgrade-info=\"\"", "--from=val", fmt.Sprintf("--deposit=%s", initialDeposit)}
Expand Down
19 changes: 19 additions & 0 deletions tests/e2e/configurer/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"os"
"strconv"
"testing"
"time"

Expand Down Expand Up @@ -108,6 +109,7 @@ func (uc *UpgradeConfigurer) ConfigureChain(chainConfig *chain.Config) error {
func (uc *UpgradeConfigurer) CreatePreUpgradeState() error {
const lockupWallet = "lockup-wallet"
const lockupWalletSuperfluid = "lockup-wallet-superfluid"
const lpWallet = "lp-wallet"

chainA := uc.chainConfigs[0]
chainANode, err := chainA.GetDefaultNode()
Expand Down Expand Up @@ -140,6 +142,23 @@ func (uc *UpgradeConfigurer) CreatePreUpgradeState() error {
// test lock and add to existing lock for both regular and superfluid lockups (only chainA)
chainA.LockAndAddToExistingLock(sdk.NewInt(1000000000000000000), poolShareDenom, lockupWalletAddrA, lockupWalletSuperfluidAddrA)

// LP to pools 833, 817, 810
// initialize lp wallets
lpWalletAddr := chainANode.CreateWallet(lpWallet)
// JoinPool 833 from lpWallet
// TODO: updaet the amounts based on the pool initialization
p0mvn marked this conversation as resolved.
Show resolved Hide resolved
maxAmountsIn833 := strconv.Itoa(1000000000000000000)
shareAmountOut833 := strconv.Itoa(1000000000000000000)
chainANode.JoinPool(maxAmountsIn833, strconv.Itoa(833), shareAmountOut833, lpWalletAddr)
// JoinPool 817 from lpWallet
maxAmountsIn817 := strconv.Itoa(1000000000000000000)
shareAmountOut817 := strconv.Itoa(1000000000000000000)
chainANode.JoinPool(maxAmountsIn817, strconv.Itoa(817), shareAmountOut817, lpWalletAddr)
// JoinPool 810 from lpWallet
maxAmountsIn810 := strconv.Itoa(1000000000000000000)
shareAmountOut810 := strconv.Itoa(1000000000000000000)
chainANode.JoinPool(maxAmountsIn810, strconv.Itoa(810), shareAmountOut810, lpWalletAddr)

return nil
}

Expand Down
36 changes: 36 additions & 0 deletions tests/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,42 @@ func (s *IntegrationTestSuite) TestGeometricTwapMigration() {
node.SwapExactAmountIn(uosmoIn, minAmountOut, fmt.Sprintf("%d", config.PreUpgradePoolId), otherDenom, swapWalletAddr)
}

// TestMigrateBalancerToStable tests that balancer to stable swap
// pool migrations run successfully. It does so by attempting to
// execute swaps and exit the pool for an account that is LPing
// the pool post-upgrade.
func (s *IntegrationTestSuite) TestMigrateBalancerToStable() {
if s.skipUpgrade {
s.T().Skip("Skipping upgrade tests")
}

const (
// This pool gets initialized pre-upgrade and migrated in the upgrade.
// TODO: Update these amounts to reflect the genesis initialization
swapAmountIn = "1000000uosmo"
swapMinAmountOut = "1"
otherDenom = "ibc/ED07A3391A112B175915CD8FAF43A2DA8E4790EDE12566649D0C2F97716B8518"
lpWallet = "lp-wallet"
exitMinAmountOut = "1"
exitShareAmountIn = "1"
)

chainA := s.configurer.GetChainConfig(0)
node, err := chainA.GetDefaultNode()
s.Require().NoError(err)

// pools migrated to stable swap
pools := []uint{833, 817, 810}
lpWalletAddr := node.CreateWallet(lpWallet)

for _, poolID := range pools {
// execute a swap on the pool
node.SwapExactAmountIn(swapAmountIn, swapMinAmountOut, fmt.Sprintf("%d", poolID), otherDenom, lpWalletAddr)
// exit the pool
node.ExitPool(lpWalletAddr, exitMinAmountOut, fmt.Sprintf("%d", poolID), exitShareAmountIn)
asalzmann marked this conversation as resolved.
Show resolved Hide resolved
}
}

// TestIBCTokenTransfer tests that IBC token transfers work as expected.
// Additionally, it attempst to create a pool with IBC denoms.
func (s *IntegrationTestSuite) TestIBCTokenTransferAndCreatePool() {
Expand Down
5 changes: 5 additions & 0 deletions x/gamm/keeper/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ func (k Keeper) setPool(ctx sdk.Context, pool poolmanagertypes.PoolI) error {
return nil
}

// Is this the preferred way to call setPool from the upgrade handler?
func (k Keeper) OverwritePool(ctx sdk.Context, pool poolmanagertypes.PoolI) error {
asalzmann marked this conversation as resolved.
Show resolved Hide resolved
return k.setPool(ctx, pool)
}

func (k Keeper) DeletePool(ctx sdk.Context, poolId uint64) error {
store := ctx.KVStore(k.storeKey)
poolKey := types.GetKeyPrefixPools(poolId)
Expand Down