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

v15 upgrade handler #941

Merged
merged 9 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
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(
sampocs marked this conversation as resolved.
Show resolved Hide resolved
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)
}
}