diff --git a/x/gov/types/v1/genesis.go b/x/gov/types/v1/genesis.go index 97b8ded8..40f0bd74 100644 --- a/x/gov/types/v1/genesis.go +++ b/x/gov/types/v1/genesis.go @@ -6,6 +6,8 @@ import ( "golang.org/x/sync/errgroup" + "cosmossdk.io/math" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkgovtypes "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -49,6 +51,16 @@ func ValidateGenesis(data *GenesisState) error { return errors.New("starting proposal id must be greater than 0") } + if err := validateParticipationEma(data.ParticipationEma, "participation_ema"); err != nil { + return err + } + if err := validateParticipationEma(data.ConstitutionAmendmentParticipationEma, "constitution_amendment_participation_ema"); err != nil { + return err + } + if err := validateParticipationEma(data.LawParticipationEma, "law_participation_ema"); err != nil { + return err + } + var errGroup errgroup.Group // weed out duplicate proposals @@ -152,6 +164,20 @@ func ValidateGenesis(data *GenesisState) error { return errGroup.Wait() } +func validateParticipationEma(value, field string) error { + dec, err := math.LegacyNewDecFromStr(value) + if err != nil { + return fmt.Errorf("invalid %s: %w", field, err) + } + if dec.IsNegative() { + return fmt.Errorf("%s must not be negative: %s", field, value) + } + if dec.GT(math.LegacyOneDec()) { + return fmt.Errorf("%s must not be greater than 1: %s", field, value) + } + return nil +} + var _ codectypes.UnpackInterfacesMessage = GenesisState{} // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces diff --git a/x/gov/types/v1/genesis_test.go b/x/gov/types/v1/genesis_test.go index 17fc5cf6..09400076 100644 --- a/x/gov/types/v1/genesis_test.go +++ b/x/gov/types/v1/genesis_test.go @@ -393,6 +393,54 @@ func TestValidateGenesis(t *testing.T) { }, expErrMsg: "duplicate deposit: proposal_id:1 depositor:\"depositor\"", }, + { + name: "invalid participation_ema - not a decimal", + genesisState: func() *v1.GenesisState { + params := v1.DefaultParams() + return v1.NewGenesisState(v1.DefaultStartingProposalID, "notadecimal", v1.DefaultParticipationEma, v1.DefaultParticipationEma, params) + }, + expErrMsg: "invalid participation_ema", + }, + { + name: "negative participation_ema", + genesisState: func() *v1.GenesisState { + params := v1.DefaultParams() + return v1.NewGenesisState(v1.DefaultStartingProposalID, "-0.1", v1.DefaultParticipationEma, v1.DefaultParticipationEma, params) + }, + expErrMsg: "participation_ema must not be negative", + }, + { + name: "participation_ema greater than 1", + genesisState: func() *v1.GenesisState { + params := v1.DefaultParams() + return v1.NewGenesisState(v1.DefaultStartingProposalID, "1.1", v1.DefaultParticipationEma, v1.DefaultParticipationEma, params) + }, + expErrMsg: "participation_ema must not be greater than 1", + }, + { + name: "invalid constitution_amendment_participation_ema", + genesisState: func() *v1.GenesisState { + params := v1.DefaultParams() + return v1.NewGenesisState(v1.DefaultStartingProposalID, v1.DefaultParticipationEma, "notadecimal", v1.DefaultParticipationEma, params) + }, + expErrMsg: "invalid constitution_amendment_participation_ema", + }, + { + name: "negative constitution_amendment_participation_ema", + genesisState: func() *v1.GenesisState { + params := v1.DefaultParams() + return v1.NewGenesisState(v1.DefaultStartingProposalID, v1.DefaultParticipationEma, "-0.5", v1.DefaultParticipationEma, params) + }, + expErrMsg: "constitution_amendment_participation_ema must not be negative", + }, + { + name: "invalid law_participation_ema", + genesisState: func() *v1.GenesisState { + params := v1.DefaultParams() + return v1.NewGenesisState(v1.DefaultStartingProposalID, v1.DefaultParticipationEma, v1.DefaultParticipationEma, "2.0", params) + }, + expErrMsg: "law_participation_ema must not be greater than 1", + }, { name: "non-existent proposal id in votes", genesisState: func() *v1.GenesisState {