-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
feat(x/staking): update validators min commission rate after MsgUpdateParams
#19537
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ package keeper | |
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"slices" | ||
"strconv" | ||
"time" | ||
|
@@ -598,11 +599,43 @@ func (k msgServer) UpdateParams(ctx context.Context, msg *types.MsgUpdateParams) | |
return nil, err | ||
} | ||
|
||
// get previous params params | ||
previousParams, err := k.Params.Get(ctx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// store params | ||
if err := k.Params.Set(ctx, msg.Params); err != nil { | ||
return nil, err | ||
} | ||
|
||
// when min comission rate is updated, we need to update the commission rate of all validators | ||
if !previousParams.MinCommissionRate.Equal(msg.Params.MinCommissionRate) { | ||
minRate := msg.Params.MinCommissionRate | ||
|
||
vals, err := k.GetAllValidators(ctx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, val := range vals { | ||
// set the commission rate to min rate | ||
if val.Commission.CommissionRates.Rate.LT(minRate) { | ||
val.Commission.CommissionRates.Rate = minRate | ||
// set the max rate to minRate if it is less than min rate | ||
if val.Commission.CommissionRates.MaxRate.LT(minRate) { | ||
val.Commission.CommissionRates.MaxRate = minRate | ||
} | ||
|
||
val.Commission.UpdateTime = k.environment.HeaderService.GetHeaderInfo(ctx).Time | ||
if err := k.SetValidator(ctx, val); err != nil { | ||
return nil, fmt.Errorf("failed to set validator after MinCommissionRate param change: %w", err) | ||
} | ||
} | ||
} | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The logic to update all validators' commission rates when the
Overall, the implementation meets the objectives, but consider the above points for potential refinement. |
||
return &types.MsgUpdateParamsResponse{}, nil | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1027,10 +1027,22 @@ func (s *KeeperTestSuite) TestMsgUpdateParams() { | |
ctx, keeper, msgServer := s.ctx, s.stakingKeeper, s.msgServer | ||
require := s.Require() | ||
|
||
// create validator to test commission rate | ||
pk := ed25519.GenPrivKey().PubKey() | ||
require.NotNil(pk) | ||
comm := types.NewCommissionRates(math.LegacyNewDec(0), math.LegacyNewDec(0), math.LegacyNewDec(0)) | ||
s.bankKeeper.EXPECT().DelegateCoinsFromAccountToModule(gomock.Any(), Addr, types.NotBondedPoolName, gomock.Any()).AnyTimes() | ||
msg, err := types.NewMsgCreateValidator(ValAddr.String(), pk, sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(10)), types.Description{Moniker: "NewVal"}, comm, math.OneInt()) | ||
require.NoError(err) | ||
_, err = msgServer.CreateValidator(ctx, msg) | ||
require.NoError(err) | ||
paramsWithUpdatedMinCommissionRate := types.DefaultParams() | ||
paramsWithUpdatedMinCommissionRate.MinCommissionRate = math.LegacyNewDecWithPrec(5, 2) | ||
|
||
testCases := []struct { | ||
name string | ||
input *types.MsgUpdateParams | ||
expErr bool | ||
postCheck func() | ||
expErrMsg string | ||
}{ | ||
{ | ||
|
@@ -1039,15 +1051,35 @@ func (s *KeeperTestSuite) TestMsgUpdateParams() { | |
Authority: keeper.GetAuthority(), | ||
Params: types.DefaultParams(), | ||
}, | ||
expErr: false, | ||
postCheck: func() { | ||
// verify that the commission isn't changed | ||
vals, err := keeper.GetAllValidators(ctx) | ||
require.NoError(err) | ||
require.Len(vals, 1) | ||
require.True(vals[0].Commission.Rate.Equal(comm.Rate)) | ||
require.True(vals[0].Commission.MaxRate.GTE(comm.MaxRate)) | ||
}, | ||
}, | ||
{ | ||
name: "valid params with updated min commission rate", | ||
input: &types.MsgUpdateParams{ | ||
Authority: keeper.GetAuthority(), | ||
Params: paramsWithUpdatedMinCommissionRate, | ||
}, | ||
postCheck: func() { | ||
vals, err := keeper.GetAllValidators(ctx) | ||
require.NoError(err) | ||
require.Len(vals, 1) | ||
require.True(vals[0].Commission.Rate.GTE(paramsWithUpdatedMinCommissionRate.MinCommissionRate)) | ||
require.True(vals[0].Commission.MaxRate.GTE(paramsWithUpdatedMinCommissionRate.MinCommissionRate)) | ||
}, | ||
}, | ||
{ | ||
name: "invalid authority", | ||
input: &types.MsgUpdateParams{ | ||
Authority: "invalid", | ||
Params: types.DefaultParams(), | ||
}, | ||
expErr: true, | ||
expErrMsg: "invalid authority", | ||
}, | ||
{ | ||
Comment on lines
1051
to
1085
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
While the test cases for // Suggested test case addition:
// Test automatic adjustment of validators' commission rates when the MinCommissionRate is updated.
func (s *KeeperTestSuite) TestAutomaticCommissionRateAdjustment() {
// Setup: Create multiple validators with varying commission rates.
// Action: Update the MinCommissionRate through MsgUpdateParams.
// Assert: All validators have their commission rates adjusted to at least the new MinCommissionRate.
} |
||
|
@@ -1063,7 +1095,6 @@ func (s *KeeperTestSuite) TestMsgUpdateParams() { | |
BondDenom: types.BondStatusBonded, | ||
}, | ||
}, | ||
expErr: true, | ||
expErrMsg: "minimum commission rate cannot be negative", | ||
}, | ||
{ | ||
|
@@ -1079,7 +1110,6 @@ func (s *KeeperTestSuite) TestMsgUpdateParams() { | |
BondDenom: types.BondStatusBonded, | ||
}, | ||
}, | ||
expErr: true, | ||
expErrMsg: "minimum commission rate cannot be greater than 100%", | ||
}, | ||
{ | ||
|
@@ -1095,7 +1125,6 @@ func (s *KeeperTestSuite) TestMsgUpdateParams() { | |
BondDenom: "", | ||
}, | ||
}, | ||
expErr: true, | ||
expErrMsg: "bond denom cannot be blank", | ||
}, | ||
{ | ||
|
@@ -1111,7 +1140,6 @@ func (s *KeeperTestSuite) TestMsgUpdateParams() { | |
BondDenom: types.BondStatusBonded, | ||
}, | ||
}, | ||
expErr: true, | ||
expErrMsg: "max validators must be positive", | ||
}, | ||
{ | ||
|
@@ -1127,7 +1155,6 @@ func (s *KeeperTestSuite) TestMsgUpdateParams() { | |
BondDenom: types.BondStatusBonded, | ||
}, | ||
}, | ||
expErr: true, | ||
expErrMsg: "max entries must be positive", | ||
}, | ||
{ | ||
|
@@ -1143,7 +1170,6 @@ func (s *KeeperTestSuite) TestMsgUpdateParams() { | |
BondDenom: "denom", | ||
}, | ||
}, | ||
expErr: true, | ||
expErrMsg: "unbonding time must be positive", | ||
}, | ||
} | ||
|
@@ -1152,11 +1178,15 @@ func (s *KeeperTestSuite) TestMsgUpdateParams() { | |
tc := tc | ||
s.T().Run(tc.name, func(t *testing.T) { | ||
_, err := msgServer.UpdateParams(ctx, tc.input) | ||
if tc.expErr { | ||
if tc.expErrMsg != "" { | ||
require.Error(err) | ||
require.Contains(err.Error(), tc.expErrMsg) | ||
} else { | ||
require.NoError(err) | ||
|
||
if tc.postCheck != nil { | ||
tc.postCheck() | ||
} | ||
} | ||
}) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: