diff --git a/.changelog/unreleased/state-breaking/2855-migrate-min-commission-rate.md b/.changelog/unreleased/state-breaking/2855-migrate-min-commission-rate.md new file mode 100644 index 00000000000..f8706e9e616 --- /dev/null +++ b/.changelog/unreleased/state-breaking/2855-migrate-min-commission-rate.md @@ -0,0 +1,7 @@ +Migrate min commission rate migration rate staking parameter to 5% + ([prop 826](https://www.mintscan.io/cosmos/proposals/826)) + and updates the commission rate for all validators that have a commission + rate less than 5% ([\#2855](https://github.com/cosmos/gaia/pull/2855)) + + + diff --git a/app/upgrades/v15/upgrades.go b/app/upgrades/v15/upgrades.go index ee9c0b485d4..b14797dfeda 100644 --- a/app/upgrades/v15/upgrades.go +++ b/app/upgrades/v15/upgrades.go @@ -3,6 +3,7 @@ package v15 import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/cosmos/gaia/v15/app/keepers" @@ -21,7 +22,38 @@ func CreateUpgradeHandler( return vm, err } - ctx.Logger().Info("Upgrade complete") + UpgradeMinCommissionRate(ctx, *keepers.StakingKeeper) + + ctx.Logger().Info("Upgrade v15 complete") return vm, err } } + +// UpgradeMinCommissionRate sets the minimum commission rate staking parameter to 5% +// and updates the commission rate for all validators that have a commission rate less than 5% +// adhere to prop 826 which sets the minimum commission rate to 5% for all validators +// https://www.mintscan.io/cosmos/proposals/826 +func UpgradeMinCommissionRate(ctx sdk.Context, sk stakingkeeper.Keeper) { + ctx.Logger().Info("Migrating min commission rate...") + + params := sk.GetParams(ctx) + params.MinCommissionRate = sdk.NewDecWithPrec(5, 2) + err := sk.SetParams(ctx, params) + if err != nil { + panic(err) + } + + for _, val := range sk.GetAllValidators(ctx) { + if val.Commission.CommissionRates.Rate.LT(sdk.NewDecWithPrec(5, 2)) { + // set the commission rate to 5% + val.Commission.CommissionRates.Rate = sdk.NewDecWithPrec(5, 2) + // set the max rate to 5% if it is less than 5% + if val.Commission.CommissionRates.MaxRate.LT(sdk.NewDecWithPrec(5, 2)) { + val.Commission.CommissionRates.MaxRate = sdk.NewDecWithPrec(5, 2) + } + val.Commission.UpdateTime = ctx.BlockHeader().Time + sk.SetValidator(ctx, val) + } + } + ctx.Logger().Info("Finished migrating min commission rate") +} diff --git a/app/upgrades/v15/upgrades_test.go b/app/upgrades/v15/upgrades_test.go new file mode 100644 index 00000000000..b381be91009 --- /dev/null +++ b/app/upgrades/v15/upgrades_test.go @@ -0,0 +1,63 @@ +package v15_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + tmrand "github.com/cometbft/cometbft/libs/rand" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/cosmos/gaia/v15/app/helpers" + v15 "github.com/cosmos/gaia/v15/app/upgrades/v15" +) + +func TestUpgradeMinCommissionRate(t *testing.T) { + gaiaApp := helpers.Setup(t) + ctx := gaiaApp.NewUncachedContext(true, tmproto.Header{}) + + // set min commission rate to 0 + stakingParams := gaiaApp.StakingKeeper.GetParams(ctx) + stakingParams.MinCommissionRate = sdk.ZeroDec() + err := gaiaApp.StakingKeeper.SetParams(ctx, stakingParams) + require.NoError(t, err) + + stakingKeeper := gaiaApp.StakingKeeper + valNum := len(stakingKeeper.GetAllValidators(ctx)) + + // create 3 new validators + for i := 0; i < 3; i++ { + pk := ed25519.GenPrivKeyFromSecret([]byte{uint8(i)}).PubKey() + val, err := stakingtypes.NewValidator( + sdk.ValAddress(pk.Address()), + pk, + stakingtypes.Description{}, + ) + require.NoError(t, err) + // set random commission rate + val.Commission.CommissionRates.Rate = sdk.NewDecWithPrec(tmrand.Int63n(100), 2) + stakingKeeper.SetValidator(ctx, val) + valNum++ + } + + validators := stakingKeeper.GetAllValidators(ctx) + require.Equal(t, valNum, len(validators)) + + // pre-test min commission rate is 0 + require.Equal(t, stakingKeeper.GetParams(ctx).MinCommissionRate, sdk.ZeroDec(), "non-zero previous min commission rate") + + // run the test and confirm the values have been updated + v15.UpgradeMinCommissionRate(ctx, *stakingKeeper) + + newStakingParams := stakingKeeper.GetParams(ctx) + require.NotEqual(t, newStakingParams.MinCommissionRate, sdk.ZeroDec(), "failed to update min commission rate") + require.Equal(t, newStakingParams.MinCommissionRate, sdk.NewDecWithPrec(5, 2), "failed to update min commission rate") + + for _, val := range stakingKeeper.GetAllValidators(ctx) { + require.True(t, val.Commission.CommissionRates.Rate.GTE(newStakingParams.MinCommissionRate), "failed to update update commission rate for validator %s", val.GetOperator()) + } +}