Community Param Updates (#1741)

* refactor param validation test cases to be shared by genesis and params
tests

* add additional test case for zero staking rewards in order to ensure
no regressions in support for turning off rewards

* add test case to ensure default params are valid -- prevent regression
if defaults change to an invalid state during updates of validation or
defaults

* zero out parameters in migration -- this module will be used with
existing chains and parameters should be set after migrations in
each upgrade handler

* update StakingRewardsPerSecond to an 18 decimal type in order to
reduce error

* add community grpc rest endpoints to swagger

* Fix copy pasta query name to refer to correct Community module

Co-authored-by: drklee3 <derrick@dlee.dev>

* generate swagger changes from previous commit

---------

Co-authored-by: drklee3 <derrick@dlee.dev>
This commit is contained in:
Nick DeLuca 2023-09-26 10:08:26 -07:00 committed by GitHub
parent bc260d8091
commit 57a1a4b10d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 374 additions and 114 deletions

View File

@ -233,6 +233,23 @@
]
}
},
{
"url": "./out/swagger/kava/community/v1beta1/query.swagger.json",
"tags": {
"rename": {
"Query": "Community"
}
},
"operationIds": {
"rename": [
{
"type": "regex",
"from": "(.*)",
"to": "Community$1"
}
]
}
},
{
"url": "./client/docs/cosmos-swagger.yml",
"dereference": {

View File

@ -12991,6 +12991,176 @@ paths:
format: byte
tags:
- Savings
/kava/community/v1beta1/balance:
get:
summary: Balance queries the balance of all coins of x/community module.
operationId: CommunityBalance
responses:
'200':
description: A successful response.
schema:
type: object
properties:
coins:
type: array
items:
type: object
properties:
denom:
type: string
amount:
type: string
description: >-
Coin defines a token with a denomination and an amount.
NOTE: The amount field is an Int which implements the custom
method
signatures required by gogoproto.
description: >-
QueryBalanceResponse defines the response type for querying
x/community balance.
default:
description: An unexpected error response.
schema:
type: object
properties:
error:
type: string
code:
type: integer
format: int32
message:
type: string
details:
type: array
items:
type: object
properties:
type_url:
type: string
value:
type: string
format: byte
tags:
- Community
/kava/community/v1beta1/params:
get:
summary: Params queires the module params.
operationId: CommunityParams
responses:
'200':
description: A successful response.
schema:
type: object
properties:
params:
title: params represents the community module parameters
type: object
properties:
upgrade_time_disable_inflation:
type: string
format: date-time
description: >-
upgrade_time_disable_inflation is the time at which to
disable mint and kavadist module inflation.
If set to 0, inflation will be disabled from block 1.
staking_rewards_per_second:
type: string
title: >-
staking_rewards_per_second is the amount paid out to
delegators each block from the community account
description: Params defines the parameters of the community module.
description: >-
QueryParamsResponse defines the response type for querying
x/community params.
default:
description: An unexpected error response.
schema:
type: object
properties:
error:
type: string
code:
type: integer
format: int32
message:
type: string
details:
type: array
items:
type: object
properties:
type_url:
type: string
value:
type: string
format: byte
tags:
- Community
/kava/community/v1beta1/total_balance:
get:
summary: |-
TotalBalance queries the balance of all coins, including x/distribution,
x/community, and supplied balances.
operationId: CommunityTotalBalance
responses:
'200':
description: A successful response.
schema:
type: object
properties:
pool:
type: array
items:
type: object
properties:
denom:
type: string
amount:
type: string
description: >-
DecCoin defines a token with a denomination and a decimal
amount.
NOTE: The amount field is an Dec which implements the custom
method
signatures required by gogoproto.
description: pool defines community pool's coins.
description: >-
QueryTotalBalanceResponse defines the response type for querying
total
community pool balance. This matches the x/distribution
CommunityPool query response.
default:
description: An unexpected error response.
schema:
type: object
properties:
error:
type: string
code:
type: integer
format: int32
message:
type: string
details:
type: array
items:
type: object
properties:
type_url:
type: string
value:
type: string
format: byte
tags:
- Community
/cosmos/auth/v1beta1/accounts:
get:
summary: Accounts returns all the existing accounts
@ -56830,6 +57000,102 @@ definitions:
description: >-
TotalSupplyResponse defines the response type for the Query/TotalSupply
method.
cosmos.base.v1beta1.DecCoin:
type: object
properties:
denom:
type: string
amount:
type: string
description: |-
DecCoin defines a token with a denomination and a decimal amount.
NOTE: The amount field is an Dec which implements the custom method
signatures required by gogoproto.
kava.community.v1beta1.Params:
type: object
properties:
upgrade_time_disable_inflation:
type: string
format: date-time
description: >-
upgrade_time_disable_inflation is the time at which to disable mint
and kavadist module inflation.
If set to 0, inflation will be disabled from block 1.
staking_rewards_per_second:
type: string
title: >-
staking_rewards_per_second is the amount paid out to delegators each
block from the community account
description: Params defines the parameters of the community module.
kava.community.v1beta1.QueryBalanceResponse:
type: object
properties:
coins:
type: array
items:
type: object
properties:
denom:
type: string
amount:
type: string
description: |-
Coin defines a token with a denomination and an amount.
NOTE: The amount field is an Int which implements the custom method
signatures required by gogoproto.
description: >-
QueryBalanceResponse defines the response type for querying x/community
balance.
kava.community.v1beta1.QueryParamsResponse:
type: object
properties:
params:
title: params represents the community module parameters
type: object
properties:
upgrade_time_disable_inflation:
type: string
format: date-time
description: >-
upgrade_time_disable_inflation is the time at which to disable
mint and kavadist module inflation.
If set to 0, inflation will be disabled from block 1.
staking_rewards_per_second:
type: string
title: >-
staking_rewards_per_second is the amount paid out to delegators
each block from the community account
description: Params defines the parameters of the community module.
description: >-
QueryParamsResponse defines the response type for querying x/community
params.
kava.community.v1beta1.QueryTotalBalanceResponse:
type: object
properties:
pool:
type: array
items:
type: object
properties:
denom:
type: string
amount:
type: string
description: |-
DecCoin defines a token with a denomination and a decimal amount.
NOTE: The amount field is an Dec which implements the custom method
signatures required by gogoproto.
description: pool defines community pool's coins.
description: >-
QueryTotalBalanceResponse defines the response type for querying total
community pool balance. This matches the x/distribution CommunityPool
query response.
cosmos.auth.v1beta1.AddressBytesToStringResponse:
type: object
properties:
@ -64281,18 +64547,6 @@ definitions:
application's
state transition machine.
cosmos.base.v1beta1.DecCoin:
type: object
properties:
denom:
type: string
amount:
type: string
description: |-
DecCoin defines a token with a denomination and a decimal amount.
NOTE: The amount field is an Dec which implements the custom method
signatures required by gogoproto.
cosmos.distribution.v1beta1.DelegationDelegatorReward:
type: object
properties:

View File

@ -18,8 +18,8 @@ message Params {
// staking_rewards_per_second is the amount paid out to delegators each block from the community account
string staking_rewards_per_second = 2 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];
}

View File

@ -33,7 +33,7 @@ func (suite *genesisTestSuite) TestInitGenesis() {
genesisState := types.NewGenesisState(
types.NewParams(
time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC),
sdkmath.NewInt(1000),
sdkmath.LegacyNewDec(1000),
),
)
@ -55,7 +55,7 @@ func (suite *genesisTestSuite) TestInitGenesis() {
func (suite *genesisTestSuite) TestExportGenesis() {
params := types.NewParams(
time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC),
sdkmath.NewInt(1000),
sdkmath.LegacyNewDec(1000),
)
suite.Keeper.SetParams(suite.Ctx, params)
@ -68,7 +68,7 @@ func (suite *genesisTestSuite) TestInitExportIsLossless() {
genesisState := types.NewGenesisState(
types.NewParams(
time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC),
sdkmath.NewInt(1000),
sdkmath.LegacyNewDec(1000),
),
)

View File

@ -36,7 +36,7 @@ func TestGrpcQueryTestSuite(t *testing.T) {
func (suite *grpcQueryTestSuite) TestGrpcQueryParams() {
p := types.NewParams(
time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC),
sdkmath.NewInt(1000),
sdkmath.LegacyNewDec(1000),
)
suite.Keeper.SetParams(suite.Ctx, p)

View File

@ -62,7 +62,7 @@ func (suite *StoreTestSuite) TestGetSetParams() {
params := types.NewParams(
time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC),
sdkmath.NewInt(1000),
sdkmath.LegacyNewDec(1000),
)
suite.Keeper.SetParams(suite.Ctx, params)

View File

@ -5,6 +5,7 @@ import (
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/community/types"
@ -22,9 +23,8 @@ func Migrate(
cdc codec.BinaryCodec,
) error {
params := types.NewParams(
// 2023-11-01T00:00:00Z
time.Date(2023, 11, 1, 0, 0, 0, 0, time.UTC),
sdk.NewInt(744191),
time.Time{},
sdkmath.LegacyNewDec(0),
)
if err := params.Validate(); err != nil {

View File

@ -4,6 +4,7 @@ import (
"testing"
"time"
sdkmath "cosmossdk.io/math"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/testutil"
@ -39,8 +40,8 @@ func TestMigrateStore(t *testing.T) {
require.Equal(
t,
types.NewParams(
time.Date(2023, 11, 1, 0, 0, 0, 0, time.UTC),
sdk.NewInt(744191),
time.Time{},
sdkmath.LegacyNewDec(0),
),
params,
"params should be correct after migration",

View File

@ -2,12 +2,9 @@ package types_test
import (
"testing"
"time"
"github.com/stretchr/testify/require"
sdkmath "cosmossdk.io/math"
"github.com/kava-labs/kava/x/community/types"
)
@ -18,37 +15,12 @@ func TestDefaultGenesisState(t *testing.T) {
require.Equal(t, types.DefaultParams(), defaultGen.Params)
}
func TestGenesisState_Validate(t *testing.T) {
testCases := []struct {
name string
genesis types.GenesisState
expectedErr string
}{
{
name: "valid state",
genesis: types.GenesisState{
Params: types.Params{
UpgradeTimeDisableInflation: time.Time{},
StakingRewardsPerSecond: sdkmath.NewInt(1000),
},
},
expectedErr: "",
},
{
name: "invalid params",
genesis: types.GenesisState{
Params: types.Params{
UpgradeTimeDisableInflation: time.Time{},
StakingRewardsPerSecond: sdkmath.Int{},
},
},
expectedErr: "StakingRewardsPerSecond should not be nil",
},
}
for _, tc := range testCases {
func TestGenesisState_ValidateParams(t *testing.T) {
for _, tc := range paramTestCases {
t.Run(tc.name, func(t *testing.T) {
err := tc.genesis.Validate()
genState := types.NewGenesisState(tc.params)
err := genState.Validate()
if tc.expectedErr == "" {
require.NoError(t, err)

View File

@ -11,13 +11,13 @@ import (
var (
DefaultUpgradeTimeDisableInflation = time.Time{}
// DefaultStakingRewardsPerSecond is ~4.6 KAVA per block, 6.3s block time
DefaultStakingRewardsPerSecond = sdkmath.NewInt(744191)
DefaultStakingRewardsPerSecond = sdkmath.LegacyNewDec(744191)
)
// NewParams returns a new params object
func NewParams(
upgradeTime time.Time,
stakingRewardsPerSecond sdkmath.Int,
stakingRewardsPerSecond sdkmath.LegacyDec,
) Params {
return Params{
UpgradeTimeDisableInflation: upgradeTime,

View File

@ -35,7 +35,7 @@ type Params struct {
// If set to 0, inflation will be disabled from block 1.
UpgradeTimeDisableInflation time.Time `protobuf:"bytes,1,opt,name=upgrade_time_disable_inflation,json=upgradeTimeDisableInflation,proto3,stdtime" json:"upgrade_time_disable_inflation"`
// staking_rewards_per_second is the amount paid out to delegators each block from the community account
StakingRewardsPerSecond cosmossdk_io_math.Int `protobuf:"bytes,2,opt,name=staking_rewards_per_second,json=stakingRewardsPerSecond,proto3,customtype=cosmossdk.io/math.Int" json:"staking_rewards_per_second"`
StakingRewardsPerSecond cosmossdk_io_math.LegacyDec `protobuf:"bytes,2,opt,name=staking_rewards_per_second,json=stakingRewardsPerSecond,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"staking_rewards_per_second"`
}
func (m *Params) Reset() { *m = Params{} }
@ -87,28 +87,29 @@ func init() {
}
var fileDescriptor_0a48475520900507 = []byte{
// 336 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x91, 0xcf, 0x4e, 0x2a, 0x31,
0x14, 0x87, 0xa7, 0x77, 0x41, 0xae, 0xe3, 0x8e, 0xf8, 0x07, 0xc7, 0x64, 0x86, 0xe8, 0x86, 0x84,
0xd0, 0x06, 0x7d, 0x03, 0xa2, 0x0b, 0x76, 0x04, 0x5d, 0xb9, 0x69, 0x3a, 0x4c, 0x29, 0x0d, 0xd3,
0x76, 0xd2, 0x76, 0x50, 0xde, 0x82, 0x87, 0xf1, 0x21, 0x58, 0x12, 0x57, 0xc6, 0x44, 0x34, 0xf0,
0x22, 0xa6, 0xd3, 0xc1, 0xb8, 0x3b, 0xe7, 0xf4, 0xeb, 0xd7, 0xfc, 0x4e, 0xc3, 0xeb, 0x39, 0x59,
0x10, 0x34, 0x51, 0x42, 0x94, 0x92, 0xdb, 0x25, 0x5a, 0xf4, 0x53, 0x6a, 0x49, 0x1f, 0x15, 0x44,
0x13, 0x61, 0x60, 0xa1, 0x95, 0x55, 0xcd, 0x33, 0x07, 0xc1, 0x5f, 0x08, 0xd6, 0x50, 0x74, 0x31,
0x51, 0x46, 0x28, 0x83, 0x2b, 0x0a, 0xf9, 0xc6, 0x5f, 0x89, 0x4e, 0x98, 0x62, 0xca, 0xcf, 0x5d,
0x55, 0x4f, 0x13, 0xa6, 0x14, 0xcb, 0x29, 0xaa, 0xba, 0xb4, 0x9c, 0x22, 0xcb, 0x05, 0x35, 0x96,
0x88, 0xc2, 0x03, 0x57, 0x9f, 0x20, 0x6c, 0x8c, 0xaa, 0xa7, 0x9b, 0x3c, 0x8c, 0xcb, 0x82, 0x69,
0x92, 0x51, 0xec, 0x28, 0x9c, 0x71, 0x43, 0xd2, 0x9c, 0x62, 0x2e, 0xa7, 0x39, 0xb1, 0x5c, 0xc9,
0x16, 0x68, 0x83, 0xce, 0xf1, 0x4d, 0x04, 0xbd, 0x14, 0x1e, 0xa4, 0xf0, 0xf1, 0x20, 0x1d, 0xfc,
0x5f, 0x6f, 0x93, 0x60, 0xf5, 0x95, 0x80, 0xf1, 0x65, 0xed, 0x72, 0x67, 0x77, 0xde, 0x34, 0x3c,
0x88, 0x9a, 0xb3, 0x30, 0x32, 0x96, 0xcc, 0xb9, 0x64, 0x58, 0xd3, 0x67, 0xa2, 0x33, 0x83, 0x0b,
0xaa, 0xb1, 0xa1, 0x13, 0x25, 0xb3, 0xd6, 0xbf, 0x36, 0xe8, 0x1c, 0x0d, 0xba, 0x4e, 0xf5, 0xb1,
0x4d, 0x4e, 0x7d, 0x4c, 0x93, 0xcd, 0x21, 0x57, 0x48, 0x10, 0x3b, 0x83, 0x43, 0x69, 0xdf, 0x5e,
0x7b, 0x61, 0x9d, 0x7f, 0x28, 0xed, 0xf8, 0xbc, 0xd6, 0x8d, 0xbd, 0x6d, 0x44, 0xf5, 0x43, 0xe5,
0x1a, 0xdc, 0xaf, 0x77, 0x31, 0xd8, 0xec, 0x62, 0xf0, 0xbd, 0x8b, 0xc1, 0x6a, 0x1f, 0x07, 0x9b,
0x7d, 0x1c, 0xbc, 0xef, 0xe3, 0xe0, 0xa9, 0xcb, 0xb8, 0x9d, 0x95, 0xa9, 0xdb, 0x32, 0x72, 0xeb,
0xee, 0xe5, 0x24, 0x35, 0x55, 0x85, 0x5e, 0xfe, 0xfc, 0x8f, 0x5d, 0x16, 0xd4, 0xa4, 0x8d, 0x2a,
0xeb, 0xed, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc5, 0xad, 0xf1, 0xc6, 0xbe, 0x01, 0x00, 0x00,
// 339 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x91, 0x31, 0x4e, 0xc3, 0x30,
0x14, 0x86, 0x63, 0x86, 0x0a, 0xc2, 0x56, 0x21, 0x28, 0xa9, 0x94, 0x54, 0xb0, 0x54, 0x42, 0xb5,
0x55, 0xb8, 0x41, 0x55, 0x06, 0x24, 0x86, 0xaa, 0x30, 0xb1, 0x44, 0x2f, 0x89, 0xeb, 0x5a, 0x4d,
0xe2, 0xc8, 0x76, 0x0a, 0xbd, 0x45, 0x0f, 0xc3, 0x21, 0x3a, 0x56, 0x4c, 0x88, 0xa1, 0xa0, 0xe6,
0x22, 0xc8, 0x71, 0x8a, 0xd8, 0xde, 0x7b, 0xfe, 0xfc, 0x59, 0xef, 0xb7, 0x7b, 0xbd, 0x80, 0x25,
0x90, 0x58, 0x64, 0x59, 0x99, 0x73, 0xbd, 0x22, 0xcb, 0x61, 0x44, 0x35, 0x0c, 0x49, 0x01, 0x12,
0x32, 0x85, 0x0b, 0x29, 0xb4, 0x68, 0x9f, 0x1b, 0x08, 0xff, 0x41, 0xb8, 0x81, 0xbc, 0xcb, 0x58,
0xa8, 0x4c, 0xa8, 0xb0, 0xa6, 0x88, 0x6d, 0xec, 0x15, 0xef, 0x8c, 0x09, 0x26, 0xec, 0xdc, 0x54,
0xcd, 0x34, 0x60, 0x42, 0xb0, 0x94, 0x92, 0xba, 0x8b, 0xca, 0x19, 0xd1, 0x3c, 0xa3, 0x4a, 0x43,
0x56, 0x58, 0xe0, 0xaa, 0x42, 0x6e, 0x6b, 0x52, 0x3f, 0xdd, 0xe6, 0xae, 0x5f, 0x16, 0x4c, 0x42,
0x42, 0x43, 0x43, 0x85, 0x09, 0x57, 0x10, 0xa5, 0x34, 0xe4, 0xf9, 0x2c, 0x05, 0xcd, 0x45, 0xde,
0x41, 0x3d, 0xd4, 0x3f, 0xbd, 0xf5, 0xb0, 0x95, 0xe2, 0x83, 0x14, 0x3f, 0x1f, 0xa4, 0xa3, 0xe3,
0xcd, 0x2e, 0x70, 0xd6, 0xdf, 0x01, 0x9a, 0x76, 0x1b, 0x97, 0x39, 0x1b, 0x5b, 0xd3, 0xc3, 0x41,
0xd4, 0xce, 0x5d, 0x4f, 0x69, 0x58, 0xf0, 0x9c, 0x85, 0x92, 0xbe, 0x82, 0x4c, 0x54, 0x58, 0x50,
0x19, 0x2a, 0x1a, 0x8b, 0x3c, 0xe9, 0x1c, 0xf5, 0x50, 0xff, 0x64, 0x34, 0x34, 0xaa, 0xaf, 0x5d,
0xd0, 0xb5, 0x6b, 0xaa, 0x64, 0x81, 0xb9, 0x20, 0x19, 0xe8, 0x39, 0x7e, 0xa4, 0x0c, 0xe2, 0xd5,
0x98, 0xc6, 0x1f, 0xef, 0x03, 0xb7, 0x49, 0x61, 0x4c, 0xe3, 0xe9, 0x45, 0x23, 0x9d, 0x5a, 0xe7,
0x84, 0xca, 0xa7, 0xda, 0x38, 0xba, 0xdf, 0xec, 0x7d, 0xb4, 0xdd, 0xfb, 0xe8, 0x67, 0xef, 0xa3,
0x75, 0xe5, 0x3b, 0xdb, 0xca, 0x77, 0x3e, 0x2b, 0xdf, 0x79, 0xb9, 0x61, 0x5c, 0xcf, 0xcb, 0xc8,
0x64, 0x4d, 0x4c, 0xe8, 0x83, 0x14, 0x22, 0x55, 0x57, 0xe4, 0xed, 0xdf, 0x2f, 0xe9, 0x55, 0x41,
0x55, 0xd4, 0xaa, 0x37, 0xbe, 0xfb, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xa1, 0x87, 0x19, 0x27, 0xc4,
0x01, 0x00, 0x00,
}
func (m *Params) Marshal() (dAtA []byte, err error) {

View File

@ -10,39 +10,54 @@ import (
"github.com/kava-labs/kava/x/community/types"
)
func TestParamsValidate(t *testing.T) {
testCases := []struct {
name string
params types.Params
expectedErr string
}{
{
name: "valid parms",
params: types.Params{
UpgradeTimeDisableInflation: time.Time{},
StakingRewardsPerSecond: sdkmath.NewInt(1000),
},
expectedErr: "",
},
{
name: "nil rewards per second",
params: types.Params{
UpgradeTimeDisableInflation: time.Time{},
StakingRewardsPerSecond: sdkmath.Int{},
},
expectedErr: "StakingRewardsPerSecond should not be nil",
},
{
name: "negative rewards per second",
params: types.Params{
UpgradeTimeDisableInflation: time.Time{},
StakingRewardsPerSecond: sdkmath.NewInt(-5),
},
expectedErr: "StakingRewardsPerSecond should not be negative",
},
}
type paramTestCase struct {
name string
params types.Params
expectedErr string
}
for _, tc := range testCases {
var paramTestCases = []paramTestCase{
{
name: "default params are valid",
params: types.DefaultParams(),
expectedErr: "",
},
{
name: "valid params",
params: types.Params{
UpgradeTimeDisableInflation: time.Time{},
StakingRewardsPerSecond: sdkmath.LegacyNewDec(1000),
},
expectedErr: "",
},
{
name: "rewards per second are allowed to be zero",
params: types.Params{
UpgradeTimeDisableInflation: time.Time{},
StakingRewardsPerSecond: sdkmath.LegacyNewDec(0),
},
expectedErr: "",
},
{
name: "nil rewards per second",
params: types.Params{
UpgradeTimeDisableInflation: time.Time{},
StakingRewardsPerSecond: sdkmath.LegacyDec{},
},
expectedErr: "StakingRewardsPerSecond should not be nil",
},
{
name: "negative rewards per second",
params: types.Params{
UpgradeTimeDisableInflation: time.Time{},
StakingRewardsPerSecond: sdkmath.LegacyNewDec(-5),
},
expectedErr: "StakingRewardsPerSecond should not be negative",
},
}
func TestParamsValidate(t *testing.T) {
for _, tc := range paramTestCases {
t.Run(tc.name, func(t *testing.T) {
err := tc.params.Validate()