diff --git a/protocol/app/upgrades.go b/protocol/app/upgrades.go index 8936e3da2f..00725c3070 100644 --- a/protocol/app/upgrades.go +++ b/protocol/app/upgrades.go @@ -3,7 +3,7 @@ package app import ( "fmt" - v_9_3 "github.com/dydxprotocol/v4-chain/protocol/app/upgrades/v9.3" + v_9_4 "github.com/dydxprotocol/v4-chain/protocol/app/upgrades/v9.4" upgradetypes "cosmossdk.io/x/upgrade/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -14,7 +14,7 @@ var ( // `Upgrades` defines the upgrade handlers and store loaders for the application. // New upgrades should be added to this slice after they are implemented. Upgrades = []upgrades.Upgrade{ - v_9_3.Upgrade, + v_9_4.Upgrade, } Forks = []upgrades.Fork{} ) @@ -22,13 +22,14 @@ var ( // setupUpgradeHandlers registers the upgrade handlers to perform custom upgrade // logic and state migrations for software upgrades. func (app *App) setupUpgradeHandlers() { - if app.UpgradeKeeper.HasHandler(v_9_3.UpgradeName) { - panic(fmt.Sprintf("Cannot register duplicate upgrade handler '%s'", v_9_3.UpgradeName)) + if app.UpgradeKeeper.HasHandler(v_9_4.UpgradeName) { + panic(fmt.Sprintf("Cannot register duplicate upgrade handler '%s'", v_9_4.UpgradeName)) } app.UpgradeKeeper.SetUpgradeHandler( - v_9_3.UpgradeName, - v_9_3.CreateUpgradeHandler( + v_9_4.UpgradeName, + v_9_4.CreateUpgradeHandler( app.ModuleManager, + app.AffiliatesKeeper, app.configurator, ), ) diff --git a/protocol/app/upgrades/v9.3/upgrade_container_test.go b/protocol/app/upgrades/v9.3/upgrade_container_test.go deleted file mode 100644 index 2be8429dcb..0000000000 --- a/protocol/app/upgrades/v9.3/upgrade_container_test.go +++ /dev/null @@ -1,37 +0,0 @@ -//go:build all || container_test - -package v_9_3_test - -import ( - "testing" - - v_9_3 "github.com/dydxprotocol/v4-chain/protocol/app/upgrades/v9.3" - - "github.com/dydxprotocol/v4-chain/protocol/testing/containertest" - "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" - "github.com/stretchr/testify/require" -) - -func TestStateUpgrade(t *testing.T) { - testnet, err := containertest.NewTestnetWithPreupgradeGenesis() - require.NoError(t, err, "failed to create testnet - is docker daemon running?") - err = testnet.Start() - require.NoError(t, err) - defer testnet.MustCleanUp() - node := testnet.Nodes["alice"] - nodeAddress := constants.AliceAccAddress.String() - - preUpgradeSetups(node, t) - preUpgradeChecks(node, t) - - err = containertest.UpgradeTestnet(nodeAddress, t, node, v_9_3.UpgradeName) - require.NoError(t, err) - - postUpgradeChecks(node, t) -} - -func preUpgradeSetups(node *containertest.Node, t *testing.T) {} - -func preUpgradeChecks(node *containertest.Node, t *testing.T) {} - -func postUpgradeChecks(node *containertest.Node, t *testing.T) {} diff --git a/protocol/app/upgrades/v9.4/constants.go b/protocol/app/upgrades/v9.4/constants.go new file mode 100644 index 0000000000..cf41d73786 --- /dev/null +++ b/protocol/app/upgrades/v9.4/constants.go @@ -0,0 +1,82 @@ +package v_9_4 + +import ( + store "cosmossdk.io/store/types" + "github.com/dydxprotocol/v4-chain/protocol/app/upgrades" + affiliatetypes "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types" +) + +const ( + UpgradeName = "v9.4" +) + +var ( + Upgrade = upgrades.Upgrade{ + UpgradeName: UpgradeName, + StoreUpgrades: store.StoreUpgrades{}, + } + + PreviousAffilliateTiers = affiliatetypes.AffiliateTiers{ + Tiers: []affiliatetypes.AffiliateTiers_Tier{ + { + ReqReferredVolumeQuoteQuantums: 0, + ReqStakedWholeCoins: 0, + TakerFeeSharePpm: 50_000, + }, + { + ReqReferredVolumeQuoteQuantums: 1_000_000_000_000, // 1M volume + ReqStakedWholeCoins: 200, + TakerFeeSharePpm: 100_000, + }, + { + ReqReferredVolumeQuoteQuantums: 5_000_000_000_000, // 5M volume + ReqStakedWholeCoins: 1_000, + TakerFeeSharePpm: 125_000, + }, + { + ReqReferredVolumeQuoteQuantums: 25_000_000_000_000, // 25M volume + ReqStakedWholeCoins: 5_000, + TakerFeeSharePpm: 150_000, + }, + }, + } + + PreviousAffiliateParameters = affiliatetypes.AffiliateParameters{ + Maximum_30DAffiliateRevenuePerReferredUserQuoteQuantums: 1_000_000_000_000, // 10M volume + RefereeMinimumFeeTierIdx: 1, + Maximum_30DAttributableVolumePerReferredUserQuoteQuantums: 1_000_000_000, // 10k volume + } + + PreviousAffiliateWhitelist = affiliatetypes.AffiliateWhitelist{ + Tiers: []affiliatetypes.AffiliateWhitelist_Tier{ + { + Addresses: []string{ + "dydx199tqg4wdlnu4qjlxchpd7seg454937hjrknju4", // Carl + "dydx10fx7sy6ywd5senxae9dwytf8jxek3t2gcen2vs", // Dave + }, + TakerFeeSharePpm: 200_000, + }, + }, + } + + DefaultAffiliateTiers = affiliatetypes.AffiliateTiers{ + Tiers: []affiliatetypes.AffiliateTiers_Tier{ + { + ReqReferredVolumeQuoteQuantums: 0, + ReqStakedWholeCoins: 0, + TakerFeeSharePpm: 400_000, + }, + { + ReqReferredVolumeQuoteQuantums: 1_000_000_000_000, // 1M volume + ReqStakedWholeCoins: 200, + TakerFeeSharePpm: 400_000, + }, + }, + } + + DefaultAffiliateParameters = affiliatetypes.AffiliateParameters{ + Maximum_30DAffiliateRevenuePerReferredUserQuoteQuantums: 10_000_000_000_000, // 10M volume + RefereeMinimumFeeTierIdx: 2, + Maximum_30DAttributableVolumePerReferredUserQuoteQuantums: 10_000_000_000, // 10k volume + } +) diff --git a/protocol/app/upgrades/v9.4/upgrade.go b/protocol/app/upgrades/v9.4/upgrade.go new file mode 100644 index 0000000000..545a17006e --- /dev/null +++ b/protocol/app/upgrades/v9.4/upgrade.go @@ -0,0 +1,74 @@ +package v_9_4 + +import ( + "context" + "fmt" + + upgradetypes "cosmossdk.io/x/upgrade/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/dydxprotocol/v4-chain/protocol/lib" + + affiliatekeeper "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/keeper" + affiliatetypes "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types" +) + +func setDefaultAffiliateTiersForSlidingAffiliates(ctx sdk.Context, affiliateKeeper affiliatekeeper.Keeper) { + err := affiliateKeeper.UpdateAffiliateTiers(ctx, DefaultAffiliateTiers) + + if err != nil { + panic(fmt.Sprintf("failed to set default affiliate tiers: %s", err)) + } +} + +func setDefaultAffiliateParameters(ctx sdk.Context, affiliateKeeper affiliatekeeper.Keeper) { + err := affiliateKeeper.UpdateAffiliateParameters(ctx, &affiliatetypes.MsgUpdateAffiliateParameters{ + AffiliateParameters: DefaultAffiliateParameters, + }) + + if err != nil { + panic(fmt.Sprintf("failed to set default affiliate parameters: %s", err)) + } +} + +func migrateAffiliateOverrides(ctx sdk.Context, affiliateKeeper affiliatekeeper.Keeper) { + // Get all whitelist + whitelist, err := affiliateKeeper.GetAffiliateWhitelist(ctx) + if err != nil { + panic(fmt.Sprintf("failed to get affiliate whitelist: %s", err)) + } + // Create overrides for all whitelist addresses + overrides := affiliatetypes.AffiliateOverrides{} + var overridesList []string + for _, addr := range whitelist.Tiers { + overridesList = append(overridesList, addr.Addresses...) + } + overrides.Addresses = overridesList + // Update affiliate overrides + err = affiliateKeeper.SetAffiliateOverrides(ctx, overrides) + if err != nil { + panic(fmt.Sprintf("failed to set affiliate overrides: %s", err)) + } +} + +func CreateUpgradeHandler( + mm *module.Manager, + affiliateKeeper affiliatekeeper.Keeper, + configurator module.Configurator, +) upgradetypes.UpgradeHandler { + return func(ctx context.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + sdkCtx := lib.UnwrapSDKContext(ctx, "app/upgrades") + sdkCtx.Logger().Info(fmt.Sprintf("Running %s Upgrade...", UpgradeName)) + + // Set default affiliate tiers and parameters. + setDefaultAffiliateTiersForSlidingAffiliates(sdkCtx, affiliateKeeper) + + // Set default affiliate parameters. + setDefaultAffiliateParameters(sdkCtx, affiliateKeeper) + + // Migrate affiliate overrides. + migrateAffiliateOverrides(sdkCtx, affiliateKeeper) + + return mm.RunMigrations(ctx, configurator, vm) + } +} diff --git a/protocol/app/upgrades/v9.4/upgrade_container_test.go b/protocol/app/upgrades/v9.4/upgrade_container_test.go new file mode 100644 index 0000000000..21b8065edc --- /dev/null +++ b/protocol/app/upgrades/v9.4/upgrade_container_test.go @@ -0,0 +1,97 @@ +//go:build all || container_test + +package v_9_4_test + +import ( + "testing" + + "github.com/cosmos/gogoproto/proto" + v_9_4 "github.com/dydxprotocol/v4-chain/protocol/app/upgrades/v9.4" + "github.com/dydxprotocol/v4-chain/protocol/testing/containertest" + "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" + affiliatetypes "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types" + "github.com/stretchr/testify/require" +) + +func TestStateUpgrade(t *testing.T) { + testnet, err := containertest.NewTestnetWithPreupgradeGenesis() + require.NoError(t, err, "failed to create testnet - is docker daemon running?") + err = testnet.Start() + require.NoError(t, err) + defer testnet.MustCleanUp() + node := testnet.Nodes["alice"] + nodeAddress := constants.AliceAccAddress.String() + + preUpgradeSetups(node, t) + preUpgradeChecks(node, t) + + err = containertest.UpgradeTestnet(nodeAddress, t, node, v_9_4.UpgradeName) + require.NoError(t, err) + + postUpgradeChecks(node, t) +} + +func preUpgradeSetups(node *containertest.Node, t *testing.T) {} + +func preUpgradeChecks(node *containertest.Node, t *testing.T) { + // Verify affiliate tiers are set to default values + tiersResp := &affiliatetypes.AllAffiliateTiersResponse{} + resp, err := containertest.Query( + node, + affiliatetypes.NewQueryClient, + affiliatetypes.QueryClient.AllAffiliateTiers, + &affiliatetypes.AllAffiliateTiersRequest{}, + ) + require.NoError(t, err) + err = proto.UnmarshalText(resp.String(), tiersResp) + require.NoError(t, err) + require.Equal(t, v_9_4.PreviousAffilliateTiers, tiersResp.Tiers) +} + +func postUpgradeChecks(node *containertest.Node, t *testing.T) { + // Verify affiliate tiers are set to default values + tiersResp := &affiliatetypes.AllAffiliateTiersResponse{} + resp, err := containertest.Query( + node, + affiliatetypes.NewQueryClient, + affiliatetypes.QueryClient.AllAffiliateTiers, + &affiliatetypes.AllAffiliateTiersRequest{}, + ) + require.NoError(t, err) + err = proto.UnmarshalText(resp.String(), tiersResp) + require.NoError(t, err) + require.Equal(t, v_9_4.DefaultAffiliateTiers, tiersResp.Tiers) + + // Verify affiliate parameters are set to default values + paramsResp := &affiliatetypes.AffiliateParametersResponse{} + resp, err = containertest.Query( + node, + affiliatetypes.NewQueryClient, + affiliatetypes.QueryClient.AffiliateParameters, + &affiliatetypes.AffiliateParametersRequest{}, + ) + require.NoError(t, err) + err = proto.UnmarshalText(resp.String(), paramsResp) + require.NoError(t, err) + require.Equal(t, v_9_4.DefaultAffiliateParameters, paramsResp.Parameters) + + // Verify affiliate overrides were migrated from whitelist + overridesResp := &affiliatetypes.AffiliateOverridesResponse{} + resp, err = containertest.Query( + node, + affiliatetypes.NewQueryClient, + affiliatetypes.QueryClient.AffiliateOverrides, + &affiliatetypes.AffiliateOverridesRequest{}, + ) + require.NoError(t, err) + err = proto.UnmarshalText(resp.String(), overridesResp) + require.NoError(t, err) + // Overrides should contain addresses from the pre-upgrade whitelist + expectedOverrides := affiliatetypes.AffiliateOverrides{ + Addresses: []string{ + "dydx199tqg4wdlnu4qjlxchpd7seg454937hjrknju4", // Carl + "dydx10fx7sy6ywd5senxae9dwytf8jxek3t2gcen2vs", // Dave + }, + } + require.Equal(t, expectedOverrides, overridesResp.Overrides) +} diff --git a/protocol/testing/version/VERSION_CURRENT b/protocol/testing/version/VERSION_CURRENT index a26c2c72d5..d3b4227d55 100644 --- a/protocol/testing/version/VERSION_CURRENT +++ b/protocol/testing/version/VERSION_CURRENT @@ -1 +1 @@ -v9.3 \ No newline at end of file +v9.4 \ No newline at end of file diff --git a/protocol/testing/version/VERSION_FULL_NAME_PREUPGRADE b/protocol/testing/version/VERSION_FULL_NAME_PREUPGRADE index 065a19ae0c..a26c2c72d5 100644 --- a/protocol/testing/version/VERSION_FULL_NAME_PREUPGRADE +++ b/protocol/testing/version/VERSION_FULL_NAME_PREUPGRADE @@ -1 +1 @@ -v9.2.1 \ No newline at end of file +v9.3 \ No newline at end of file diff --git a/protocol/testing/version/VERSION_PREUPGRADE b/protocol/testing/version/VERSION_PREUPGRADE index 22dada6e0b..a26c2c72d5 100644 --- a/protocol/testing/version/VERSION_PREUPGRADE +++ b/protocol/testing/version/VERSION_PREUPGRADE @@ -1 +1 @@ -v9.2 \ No newline at end of file +v9.3 \ No newline at end of file