Skip to content

Commit

Permalink
v15 upgrade handler (#941)
Browse files Browse the repository at this point in the history
  • Loading branch information
sampocs authored Sep 18, 2023
1 parent 40a3853 commit 75ca920
Show file tree
Hide file tree
Showing 3 changed files with 234 additions and 0 deletions.
13 changes: 13 additions & 0 deletions app/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
v12 "github.com/Stride-Labs/stride/v14/app/upgrades/v12"
v13 "github.com/Stride-Labs/stride/v14/app/upgrades/v13"
v14 "github.com/Stride-Labs/stride/v14/app/upgrades/v14"
v15 "github.com/Stride-Labs/stride/v14/app/upgrades/v15"
v2 "github.com/Stride-Labs/stride/v14/app/upgrades/v2"
v3 "github.com/Stride-Labs/stride/v14/app/upgrades/v3"
v4 "github.com/Stride-Labs/stride/v14/app/upgrades/v4"
Expand Down Expand Up @@ -172,6 +173,7 @@ func (app *StrideApp) setupUpgradeHandlers(appOpts servertypes.AppOptions) {
app.StakeibcKeeper,
),
)

// v14 upgrade handler
app.UpgradeKeeper.SetUpgradeHandler(
v14.UpgradeName,
Expand All @@ -191,6 +193,17 @@ func (app *StrideApp) setupUpgradeHandlers(appOpts servertypes.AppOptions) {
),
)

// v15 upgrade handler
app.UpgradeKeeper.SetUpgradeHandler(
v15.UpgradeName,
v15.CreateUpgradeHandler(
app.mm,
app.configurator,
app.InterchainqueryKeeper,
app.StakeibcKeeper,
),
)

upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk()
if err != nil {
panic(fmt.Errorf("Failed to read upgrade info from disk: %w", err))
Expand Down
76 changes: 76 additions & 0 deletions app/upgrades/v15/upgrades.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package v15

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"

icqkeeper "github.com/Stride-Labs/stride/v14/x/interchainquery/keeper"
stakeibckeeper "github.com/Stride-Labs/stride/v14/x/stakeibc/keeper"
)

var (
UpgradeName = "v15"

EvmosChainId = "evmos_9001-2"
EvmosOuterMinRedemptionRate = sdk.MustNewDecFromStr("1.290")
EvmosInnerMinRedemptionRate = sdk.MustNewDecFromStr("1.318")
EvmosMaxRedemptionRate = sdk.MustNewDecFromStr("1.500")

RedemptionRateOuterMinAdjustment = sdk.MustNewDecFromStr("0.05")
RedemptionRateInnerMinAdjustment = sdk.MustNewDecFromStr("0.03")
RedemptionRateInnerMaxAdjustment = sdk.MustNewDecFromStr("0.05")
RedemptionRateOuterMaxAdjustment = sdk.MustNewDecFromStr("0.10")
)

// CreateUpgradeHandler creates an SDK upgrade handler for v15
func CreateUpgradeHandler(
mm *module.Manager,
configurator module.Configurator,
icqKeeper icqkeeper.Keeper,
stakeibcKeeper stakeibckeeper.Keeper,
) upgradetypes.UpgradeHandler {
return func(ctx sdk.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
ctx.Logger().Info("Starting upgrade v15...")

// Set host zone redemption rate bounds based on a percentage of their current rate
ctx.Logger().Info("Updating redemption rate bounds...")
for _, hostZone := range stakeibcKeeper.GetAllHostZone(ctx) {
if hostZone.ChainId == EvmosChainId {
hostZone.MinRedemptionRate = EvmosOuterMinRedemptionRate
hostZone.MinInnerRedemptionRate = EvmosInnerMinRedemptionRate
hostZone.MaxInnerRedemptionRate = EvmosMaxRedemptionRate
hostZone.MaxRedemptionRate = EvmosMaxRedemptionRate

stakeibcKeeper.SetHostZone(ctx, hostZone)
} else {
outerMinDelta := hostZone.RedemptionRate.Mul(RedemptionRateOuterMinAdjustment)
innerMinDelta := hostZone.RedemptionRate.Mul(RedemptionRateInnerMinAdjustment)
innerMaxDelta := hostZone.RedemptionRate.Mul(RedemptionRateInnerMaxAdjustment)
outerMaxDelta := hostZone.RedemptionRate.Mul(RedemptionRateOuterMaxAdjustment)

outerMin := hostZone.RedemptionRate.Sub(outerMinDelta)
innerMin := hostZone.RedemptionRate.Sub(innerMinDelta)
innerMax := hostZone.RedemptionRate.Add(innerMaxDelta)
outerMax := hostZone.RedemptionRate.Add(outerMaxDelta)

hostZone.MinRedemptionRate = outerMin
hostZone.MinInnerRedemptionRate = innerMin
hostZone.MaxInnerRedemptionRate = innerMax
hostZone.MaxRedemptionRate = outerMax

stakeibcKeeper.SetHostZone(ctx, hostZone)
}
}

// Clear all stale delegator shares queries
ctx.Logger().Info("Deleting stale ICQs...")
for _, query := range icqKeeper.AllQueries(ctx) {
if query.CallbackId == stakeibckeeper.ICQCallbackID_Delegation {
icqKeeper.DeleteQuery(ctx, query.Id)
}
}

return mm.RunMigrations(ctx, configurator, vm)
}
}
145 changes: 145 additions & 0 deletions app/upgrades/v15/upgrades_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package v15_test

import (
"fmt"
"testing"

"github.com/stretchr/testify/suite"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/Stride-Labs/stride/v14/app/apptesting"
v15 "github.com/Stride-Labs/stride/v14/app/upgrades/v15"
icqtypes "github.com/Stride-Labs/stride/v14/x/interchainquery/types"
stakeibckeeper "github.com/Stride-Labs/stride/v14/x/stakeibc/keeper"
stakeibctypes "github.com/Stride-Labs/stride/v14/x/stakeibc/types"
)

type UpgradeTestSuite struct {
apptesting.AppTestHelper
}

func (s *UpgradeTestSuite) SetupTest() {
s.Setup()
}

func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(UpgradeTestSuite))
}

type UpdateRedemptionRateBounds struct {
CurrentRedemptionRate sdk.Dec
ExpectedMinOuterRedemptionRate sdk.Dec
ExpectedMinInnerRedemptionRate sdk.Dec
ExpectedMaxInnerRedemptionRate sdk.Dec
ExpectedMaxOuterRedemptionRate sdk.Dec
}

func (s *UpgradeTestSuite) TestUpgrade() {
dummyUpgradeHeight := int64(5)

// Setup the store before the ugprade
checkRedemptionRatesAfterUpgrade := s.SetupRedemptionRatesBeforeUpgrade()
checkQueriesAfterUpgrade := s.SetupQueriesBeforeUpgrade()

// Run the upgrade to set the bounds and clear pending queries
s.ConfirmUpgradeSucceededs("v15", dummyUpgradeHeight)

// Check the store after the upgrade
checkRedemptionRatesAfterUpgrade()
checkQueriesAfterUpgrade()
}

func (s *UpgradeTestSuite) SetupRedemptionRatesBeforeUpgrade() func() {
// Define test cases consisting of an initial redemption rate and expected bounds
testCases := []UpdateRedemptionRateBounds{
{
CurrentRedemptionRate: sdk.MustNewDecFromStr("1.0"),
ExpectedMinOuterRedemptionRate: sdk.MustNewDecFromStr("0.95"), // 1 - 5% = 0.95
ExpectedMinInnerRedemptionRate: sdk.MustNewDecFromStr("0.97"), // 1 - 3% = 0.97
ExpectedMaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.05"), // 1 + 5% = 1.05
ExpectedMaxOuterRedemptionRate: sdk.MustNewDecFromStr("1.10"), // 1 + 10% = 1.1
},
{
CurrentRedemptionRate: sdk.MustNewDecFromStr("1.1"),
ExpectedMinOuterRedemptionRate: sdk.MustNewDecFromStr("1.045"), // 1.1 - 5% = 1.045
ExpectedMinInnerRedemptionRate: sdk.MustNewDecFromStr("1.067"), // 1.1 - 3% = 1.067
ExpectedMaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.155"), // 1.1 + 5% = 1.155
ExpectedMaxOuterRedemptionRate: sdk.MustNewDecFromStr("1.210"), // 1.1 + 10% = 1.21
},
{
CurrentRedemptionRate: sdk.MustNewDecFromStr("1.25"),
ExpectedMinOuterRedemptionRate: sdk.MustNewDecFromStr("1.1875"), // 1.25 - 5% = 1.1875
ExpectedMinInnerRedemptionRate: sdk.MustNewDecFromStr("1.2125"), // 1.25 - 3% = 1.2125
ExpectedMaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.3125"), // 1.25 + 5% = 1.3125
ExpectedMaxOuterRedemptionRate: sdk.MustNewDecFromStr("1.3750"), // 1.25 + 10% = 1.375
},
}

// Create a host zone for each test case
for i, tc := range testCases {
chainId := fmt.Sprintf("chain-%d", i)

hostZone := stakeibctypes.HostZone{
ChainId: chainId,
RedemptionRate: tc.CurrentRedemptionRate,
}
s.App.StakeibcKeeper.SetHostZone(s.Ctx, hostZone)
}

// Create an evmos host zone
s.App.StakeibcKeeper.SetHostZone(s.Ctx, stakeibctypes.HostZone{
ChainId: v15.EvmosChainId,
})

// Return callback function to chck that bounds were set
return func() {
// Confirm the correct bounds were set
for i, tc := range testCases {
chainId := fmt.Sprintf("chain-%d", i)

hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, chainId)
s.Require().True(found)

s.Require().Equal(tc.ExpectedMinOuterRedemptionRate, hostZone.MinRedemptionRate, "min outer")
s.Require().Equal(tc.ExpectedMinInnerRedemptionRate, hostZone.MinInnerRedemptionRate, "min inner")
s.Require().Equal(tc.ExpectedMaxInnerRedemptionRate, hostZone.MaxInnerRedemptionRate, "max inner")
s.Require().Equal(tc.ExpectedMaxOuterRedemptionRate, hostZone.MaxRedemptionRate, "max outer")
}

// Confirm evmos' custom bounds were set
evmosHostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, v15.EvmosChainId)
s.Require().True(found)

s.Require().Equal(v15.EvmosOuterMinRedemptionRate, evmosHostZone.MinRedemptionRate, "min outer")
s.Require().Equal(v15.EvmosInnerMinRedemptionRate, evmosHostZone.MinInnerRedemptionRate, "min inner")
s.Require().Equal(v15.EvmosMaxRedemptionRate, evmosHostZone.MaxInnerRedemptionRate, "max inner")
s.Require().Equal(v15.EvmosMaxRedemptionRate, evmosHostZone.MaxRedemptionRate, "max outer")
}
}

func (s *UpgradeTestSuite) SetupQueriesBeforeUpgrade() func() {
// Set pending queries of different types
queries := []icqtypes.Query{
{Id: "1", CallbackId: stakeibckeeper.ICQCallbackID_Validator},
{Id: "2", CallbackId: stakeibckeeper.ICQCallbackID_Delegation}, // deleted
{Id: "3", CallbackId: stakeibckeeper.ICQCallbackID_Delegation}, // deleted
{Id: "4", CallbackId: stakeibckeeper.ICQCallbackID_WithdrawalBalance},
}
expectedQueriesAfterUpgrade := []string{"1", "4"}

for _, query := range queries {
s.App.InterchainqueryKeeper.SetQuery(s.Ctx, query)
}

// Return callback function to check that queries were removed
return func() {
queryIds := []string{}
for _, query := range s.App.InterchainqueryKeeper.AllQueries(s.Ctx) {
queryIds = append(queryIds, query.Id)
}

s.Require().Len(queryIds, 2)
s.Require().ElementsMatch(queryIds, expectedQueriesAfterUpgrade)
}
}

0 comments on commit 75ca920

Please sign in to comment.