From ac918acc77d77d934e4dff134dcc53b9f83e3370 Mon Sep 17 00:00:00 2001 From: Youngtaek Yoon Date: Thu, 2 Jun 2022 01:36:57 +0000 Subject: [PATCH] fix: fix genesis and support abstain (#545) * test: replace hardcoded literal * fix: fix init genesis * fix: support abstain * docs: update CHANGELOG.md * test: add tests on ReceiveFromTreasuryAuthorization * fix: fix under estimation of undecided count --- CHANGELOG.md | 1 + x/foundation/authz_test.go | 39 ++++ x/foundation/foundation.go | 171 ++++++++------- x/foundation/foundation_test.go | 308 +++++++++++++++++++++++++++ x/foundation/genesis.go | 9 +- x/foundation/genesis_test.go | 23 ++ x/foundation/keeper/genesis_test.go | 6 +- x/foundation/keeper/member_test.go | 2 +- x/foundation/keeper/proposal.go | 2 +- x/foundation/keeper/proposal_test.go | 2 +- x/foundation/keeper/tally.go | 12 +- x/foundation/keeper/vote_test.go | 2 +- x/foundation/module/module.go | 4 +- 13 files changed, 483 insertions(+), 98 deletions(-) create mode 100644 x/foundation/authz_test.go create mode 100644 x/foundation/foundation_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 892e93c56f..23576f9d06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (client) [\#476](https://github.com/line/lbm-sdk/pull/476) change the default value of the client output format in the config * (server/grpc) [\#516](https://github.com/line/lbm-sdk/pull/516) restore build norace flag * (genesis) [\#517](https://github.com/line/lbm-sdk/pull/517) fix genesis auth account format(cosmos-sdk style -> lbm-sdk style) +* (x/foundation) [\#545](https://github.com/line/lbm-sdk/pull/545) fix genesis and support abstain ### Breaking Changes diff --git a/x/foundation/authz_test.go b/x/foundation/authz_test.go new file mode 100644 index 0000000000..fa3342f24c --- /dev/null +++ b/x/foundation/authz_test.go @@ -0,0 +1,39 @@ +package foundation_test + +import ( + "testing" + + sdk "github.com/line/lbm-sdk/types" + "github.com/line/lbm-sdk/x/foundation" + "github.com/stretchr/testify/require" +) + +func TestReceiveFromTreasuryAuthorization(t *testing.T) { + testCases := map[string]struct{ + msg sdk.Msg + valid bool + accept bool + }{ + "valid": { + msg: &foundation.MsgWithdrawFromTreasury{}, + valid: true, + accept: true, + }, + "msg mismatch": { + msg: &foundation.MsgVote{}, + }, + } + + for name, tc := range testCases { + authorization := &foundation.ReceiveFromTreasuryAuthorization{} + + resp, err := authorization.Accept(sdk.Context{}, tc.msg) + if !tc.valid { + require.Error(t, err, name) + continue + } + require.NoError(t, err, name) + + require.Equal(t, tc.accept, resp.Accept) + } +} diff --git a/x/foundation/foundation.go b/x/foundation/foundation.go index bd1d856457..ee0b9e579d 100644 --- a/x/foundation/foundation.go +++ b/x/foundation/foundation.go @@ -13,22 +13,12 @@ import ( ) func DefaultDecisionPolicy(config Config) DecisionPolicy { - policy := &ThresholdDecisionPolicy{ + return &ThresholdDecisionPolicy{ Threshold: config.MinThreshold, Windows: &DecisionPolicyWindows{ VotingPeriod: 24 * time.Hour, }, } - - // check whether the default policy is valid - if err := policy.ValidateBasic(); err != nil { - panic(err) - } - if err := policy.Validate(config); err != nil { - panic(err) - } - - return policy } func validateProposers(proposers []string) error { @@ -119,6 +109,20 @@ type DecisionPolicy interface { Validate(config Config) error } +// DefaultTallyResult returns a TallyResult with all counts set to 0. +func DefaultTallyResult() TallyResult { + return NewTallyResult(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) +} + +func NewTallyResult(yes, abstain, no, veto sdk.Dec) TallyResult { + return TallyResult{ + YesCount: yes, + AbstainCount: abstain, + NoCount: no, + NoWithVetoCount: veto, + } +} + func (t *TallyResult) Add(option VoteOption) error { weight := sdk.OneDec() @@ -221,49 +225,6 @@ func SetMsgs(msgs []sdk.Msg) ([]*codectypes.Any, error) { return anys, nil } -var _ codectypes.UnpackInterfacesMessage = (*FoundationInfo)(nil) - -func (i FoundationInfo) GetDecisionPolicy() DecisionPolicy { - if i.DecisionPolicy == nil { - return nil - } - - policy, ok := i.DecisionPolicy.GetCachedValue().(DecisionPolicy) - if !ok { - return nil - } - return policy -} - -func (i *FoundationInfo) SetDecisionPolicy(policy DecisionPolicy) error { - msg, ok := policy.(proto.Message) - if !ok { - return sdkerrors.ErrInvalidType.Wrapf("can't proto marshal %T", msg) - } - - any, err := codectypes.NewAnyWithValue(msg) - if err != nil { - return err - } - i.DecisionPolicy = any - - return nil -} - -// for the tests -func (i FoundationInfo) WithDecisionPolicy(policy DecisionPolicy) *FoundationInfo { - info := i - if err := info.SetDecisionPolicy(policy); err != nil { - return nil - } - return &info -} - -func (i *FoundationInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - var policy DecisionPolicy - return unpacker.UnpackAny(i.DecisionPolicy, &policy) -} - var _ DecisionPolicy = (*ThresholdDecisionPolicy)(nil) func validateDecisionPolicyWindows(windows DecisionPolicyWindows, config Config) error { @@ -273,13 +234,9 @@ func validateDecisionPolicyWindows(windows DecisionPolicyWindows, config Config) return nil } -func (p ThresholdDecisionPolicy) Validate(config Config) error { - if p.Threshold.LT(config.MinThreshold) { - return sdkerrors.ErrInvalidRequest.Wrap("threshold must be greater than or equal to min_threshold") - } - - if err := validateDecisionPolicyWindows(*p.Windows, config); err != nil { - return err +func validateDecisionPolicyWindowsBasic(windows *DecisionPolicyWindows) error { + if windows == nil || windows.VotingPeriod == 0 { + return sdkerrors.ErrInvalidRequest.Wrap("voting period cannot be zero") } return nil @@ -307,10 +264,10 @@ func (p ThresholdDecisionPolicy) Allow(result TallyResult, totalWeight sdk.Dec, // plus all undecided count (supposing they all vote yes). maxYesCount := result.YesCount.Add(undecided) if maxYesCount.LT(realThreshold) { - return &DecisionPolicyResult{Allow: false, Final: true}, nil + return &DecisionPolicyResult{Final: true}, nil } - return &DecisionPolicyResult{Final: false}, nil + return &DecisionPolicyResult{}, nil } func (p ThresholdDecisionPolicy) GetVotingPeriod() time.Duration { @@ -322,18 +279,15 @@ func (p ThresholdDecisionPolicy) ValidateBasic() error { return sdkerrors.ErrInvalidRequest.Wrap("threshold must be a positive number") } - if p.Windows == nil || p.Windows.VotingPeriod == 0 { - return sdkerrors.ErrInvalidRequest.Wrap("voting period cannot be zero") + if err := validateDecisionPolicyWindowsBasic(p.Windows); err != nil { + return err } - return nil } -var _ DecisionPolicy = (*PercentageDecisionPolicy)(nil) - -func (p PercentageDecisionPolicy) Validate(config Config) error { - if p.Percentage.LT(config.MinPercentage) { - return sdkerrors.ErrInvalidRequest.Wrap("percentage must be greater than or equal to min_percentage") +func (p ThresholdDecisionPolicy) Validate(config Config) error { + if p.Threshold.LT(config.MinThreshold) { + return sdkerrors.ErrInvalidRequest.Wrap("threshold must be greater than or equal to min_threshold") } if err := validateDecisionPolicyWindows(*p.Windows, config); err != nil { @@ -343,12 +297,20 @@ func (p PercentageDecisionPolicy) Validate(config Config) error { return nil } +var _ DecisionPolicy = (*PercentageDecisionPolicy)(nil) + func (p PercentageDecisionPolicy) Allow(result TallyResult, totalWeight sdk.Dec, sinceSubmission time.Duration) (*DecisionPolicyResult, error) { if sinceSubmission < p.Windows.MinExecutionPeriod { return nil, sdkerrors.ErrUnauthorized.Wrapf("must wait %s after submission before execution, currently at %s", p.Windows.MinExecutionPeriod, sinceSubmission) } - yesPercentage := result.YesCount.Quo(totalWeight) + notAbstaining := totalWeight.Sub(result.AbstainCount) + // If no one votes (everyone abstains), proposal fails + if notAbstaining.IsZero() { + return &DecisionPolicyResult{Final: true}, nil + } + + yesPercentage := result.YesCount.Quo(notAbstaining) if yesPercentage.GTE(p.Percentage) { return &DecisionPolicyResult{Allow: true, Final: true}, nil } @@ -356,12 +318,12 @@ func (p PercentageDecisionPolicy) Allow(result TallyResult, totalWeight sdk.Dec, totalCounts := result.TotalCounts() undecided := totalWeight.Sub(totalCounts) maxYesCount := result.YesCount.Add(undecided) - maxYesPercentage := maxYesCount.Quo(totalWeight) + maxYesPercentage := maxYesCount.Quo(notAbstaining) if maxYesPercentage.LT(p.Percentage) { - return &DecisionPolicyResult{Allow: false, Final: true}, nil + return &DecisionPolicyResult{Final: true}, nil } - return &DecisionPolicyResult{Allow: false, Final: false}, nil + return &DecisionPolicyResult{}, nil } func (p PercentageDecisionPolicy) GetVotingPeriod() time.Duration { @@ -369,8 +331,8 @@ func (p PercentageDecisionPolicy) GetVotingPeriod() time.Duration { } func (p PercentageDecisionPolicy) ValidateBasic() error { - if p.Windows == nil || p.Windows.VotingPeriod == 0 { - return sdkerrors.ErrInvalidRequest.Wrap("voting period cannot be zero") + if err := validateDecisionPolicyWindowsBasic(p.Windows); err != nil { + return err } if err := validateRatio(p.Percentage, "percentage"); err != nil { @@ -380,6 +342,18 @@ func (p PercentageDecisionPolicy) ValidateBasic() error { return nil } +func (p PercentageDecisionPolicy) Validate(config Config) error { + if p.Percentage.LT(config.MinPercentage) { + return sdkerrors.ErrInvalidRequest.Wrap("percentage must be greater than or equal to min_percentage") + } + + if err := validateDecisionPolicyWindows(*p.Windows, config); err != nil { + return err + } + + return nil +} + func validateRatio(ratio sdk.Dec, name string) error { if ratio.IsNil() { return sdkerrors.ErrInvalidRequest.Wrapf("%s is nil", name) @@ -391,6 +365,49 @@ func validateRatio(ratio sdk.Dec, name string) error { return nil } +var _ codectypes.UnpackInterfacesMessage = (*FoundationInfo)(nil) + +func (i FoundationInfo) GetDecisionPolicy() DecisionPolicy { + if i.DecisionPolicy == nil { + return nil + } + + policy, ok := i.DecisionPolicy.GetCachedValue().(DecisionPolicy) + if !ok { + return nil + } + return policy +} + +func (i *FoundationInfo) SetDecisionPolicy(policy DecisionPolicy) error { + msg, ok := policy.(proto.Message) + if !ok { + return sdkerrors.ErrInvalidType.Wrapf("can't proto marshal %T", msg) + } + + any, err := codectypes.NewAnyWithValue(msg) + if err != nil { + return err + } + i.DecisionPolicy = any + + return nil +} + +// for the tests +func (i FoundationInfo) WithDecisionPolicy(policy DecisionPolicy) *FoundationInfo { + info := i + if err := info.SetDecisionPolicy(policy); err != nil { + return nil + } + return &info +} + +func (i *FoundationInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + var policy DecisionPolicy + return unpacker.UnpackAny(i.DecisionPolicy, &policy) +} + func GetAuthorization(any *codectypes.Any, name string) (Authorization, error) { cached := any.GetCachedValue() if cached == nil { diff --git a/x/foundation/foundation_test.go b/x/foundation/foundation_test.go new file mode 100644 index 0000000000..f1046ec9d2 --- /dev/null +++ b/x/foundation/foundation_test.go @@ -0,0 +1,308 @@ +package foundation_test + +import ( + "testing" + "time" + + sdk "github.com/line/lbm-sdk/types" + "github.com/line/lbm-sdk/x/foundation" + "github.com/stretchr/testify/require" +) + +func TestDecisionPolicy(t *testing.T) { + config := foundation.DefaultConfig() + policy := foundation.DefaultDecisionPolicy(config) + + require.NoError(t, policy.ValidateBasic()) + require.NoError(t, policy.Validate(config)) +} + +func TestTallyResult(t *testing.T) { + result := foundation.DefaultTallyResult() + + err := result.Add(foundation.VOTE_OPTION_UNSPECIFIED) + require.Error(t, err) + + err = result.Add(foundation.VOTE_OPTION_YES) + require.NoError(t, err) + require.Equal(t, sdk.OneDec(), result.YesCount) + + result.Add(foundation.VOTE_OPTION_ABSTAIN) + require.NoError(t, err) + require.Equal(t, sdk.OneDec(), result.AbstainCount) + + result.Add(foundation.VOTE_OPTION_NO) + require.NoError(t, err) + require.Equal(t, sdk.OneDec(), result.NoCount) + + result.Add(foundation.VOTE_OPTION_NO_WITH_VETO) + require.NoError(t, err) + require.Equal(t, sdk.OneDec(), result.NoWithVetoCount) + + require.Equal(t, sdk.NewDec(4), result.TotalCounts()) +} + +func TestThresholdDecisionPolicy(t *testing.T) { + config := foundation.DefaultConfig() + + testCases := map[string]struct{ + threshold sdk.Dec + votingPeriod time.Duration + minExecutionPeriod time.Duration + validBasic bool + valid bool + }{ + "valid policy": { + threshold: config.MinThreshold, + votingPeriod: time.Hour, + minExecutionPeriod: config.MaxExecutionPeriod + time.Hour - time.Nanosecond, + validBasic: true, + valid: true, + }, + "invalid policy (basic)": { + threshold: config.MinThreshold, + minExecutionPeriod: config.MaxExecutionPeriod - time.Nanosecond, + }, + "invalid policy": { + threshold: config.MinThreshold.Sub(sdk.SmallestDec()), + votingPeriod: time.Hour, + minExecutionPeriod: config.MaxExecutionPeriod + time.Hour - time.Nanosecond, + validBasic: true, + }, + "invalid policy (windows)": { + threshold: config.MinThreshold, + votingPeriod: time.Hour, + minExecutionPeriod: config.MaxExecutionPeriod + time.Hour, + validBasic: true, + }, + } + + for name, tc := range testCases { + policy := foundation.ThresholdDecisionPolicy{ + Threshold: tc.threshold, + Windows: &foundation.DecisionPolicyWindows{ + VotingPeriod: tc.votingPeriod, + MinExecutionPeriod: tc.minExecutionPeriod, + }, + } + require.Equal(t, tc.votingPeriod, policy.GetVotingPeriod()) + + err := policy.ValidateBasic() + if !tc.validBasic { + require.Error(t, err, name) + continue + } + require.NoError(t, err, name) + + err = policy.Validate(config) + if !tc.valid { + require.Error(t, err, name) + continue + } + require.NoError(t, err, name) + } +} + +func TestThresholdDecisionPolicyAllow(t *testing.T) { + config := foundation.DefaultConfig() + policy := foundation.ThresholdDecisionPolicy{ + Threshold: sdk.NewDec(10), + Windows: &foundation.DecisionPolicyWindows{ + VotingPeriod: time.Hour, + }, + } + require.NoError(t, policy.ValidateBasic()) + require.NoError(t, policy.Validate(config)) + require.Equal(t, time.Hour, policy.GetVotingPeriod()) + + testCases := map[string]struct{ + sinceSubmission time.Duration + totalWeight sdk.Dec + tally foundation.TallyResult + valid bool + final bool + allow bool + }{ + "allow": { + sinceSubmission: policy.Windows.MinExecutionPeriod, + totalWeight: policy.Threshold, + tally: foundation.NewTallyResult(policy.Threshold, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), + valid: true, + final: true, + allow: true, + }, + "allow (member size < threshold)": { + sinceSubmission: policy.Windows.MinExecutionPeriod, + totalWeight: config.MinThreshold, + tally: foundation.NewTallyResult(config.MinThreshold, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), + valid: true, + final: true, + allow: true, + }, + "not final": { + sinceSubmission: policy.Windows.MinExecutionPeriod, + totalWeight: policy.Threshold, + tally: foundation.NewTallyResult(policy.Threshold.Sub(sdk.OneDec()), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), + valid: true, + }, + "deny": { + sinceSubmission: policy.Windows.MinExecutionPeriod, + totalWeight: policy.Threshold.Add(sdk.OneDec()), + tally: foundation.NewTallyResult(sdk.ZeroDec(), sdk.OneDec(), sdk.OneDec(), sdk.ZeroDec()), + valid: true, + final: true, + }, + "too early": { + sinceSubmission: policy.Windows.MinExecutionPeriod - time.Nanosecond, + totalWeight: policy.Threshold, + tally: foundation.NewTallyResult(policy.Threshold, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), + }, + } + + for name, tc := range testCases { + result, err := policy.Allow(tc.tally, tc.totalWeight, tc.sinceSubmission) + if !tc.valid { + require.Error(t, err, name) + continue + } + require.NoError(t, err, name) + + require.Equal(t, tc.final, result.Final, name) + if tc.final { + require.Equal(t, tc.allow, result.Allow, name) + } + } +} + +func TestPercentageDecisionPolicy(t *testing.T) { + config := foundation.DefaultConfig() + + testCases := map[string]struct{ + percentage sdk.Dec + votingPeriod time.Duration + minExecutionPeriod time.Duration + validBasic bool + valid bool + }{ + "valid policy": { + percentage: config.MinPercentage, + votingPeriod: time.Hour, + minExecutionPeriod: config.MaxExecutionPeriod + time.Hour - time.Nanosecond, + validBasic: true, + valid: true, + }, + "invalid policy (basic)": { + percentage: config.MinPercentage, + minExecutionPeriod: config.MaxExecutionPeriod - time.Nanosecond, + }, + "invalid policy": { + percentage: config.MinPercentage.Sub(sdk.SmallestDec()), + votingPeriod: time.Hour, + minExecutionPeriod: config.MaxExecutionPeriod + time.Hour - time.Nanosecond, + validBasic: true, + }, + "invalid policy (windows)": { + percentage: config.MinPercentage, + votingPeriod: time.Hour, + minExecutionPeriod: config.MaxExecutionPeriod + time.Hour, + validBasic: true, + }, + } + + for name, tc := range testCases { + policy := foundation.PercentageDecisionPolicy{ + Percentage: tc.percentage, + Windows: &foundation.DecisionPolicyWindows{ + VotingPeriod: tc.votingPeriod, + MinExecutionPeriod: tc.minExecutionPeriod, + }, + } + require.Equal(t, tc.votingPeriod, policy.GetVotingPeriod()) + + err := policy.ValidateBasic() + if !tc.validBasic { + require.Error(t, err, name) + continue + } + require.NoError(t, err, name) + + err = policy.Validate(config) + if !tc.valid { + require.Error(t, err, name) + continue + } + require.NoError(t, err, name) + } +} + +func TestPercentageDecisionPolicyAllow(t *testing.T) { + config := foundation.DefaultConfig() + policy := foundation.PercentageDecisionPolicy{ + Percentage: sdk.MustNewDecFromStr("0.8"), + Windows: &foundation.DecisionPolicyWindows{ + VotingPeriod: time.Hour, + }, + } + require.NoError(t, policy.ValidateBasic()) + require.NoError(t, policy.Validate(config)) + require.Equal(t, time.Hour, policy.GetVotingPeriod()) + + totalWeight := sdk.NewDec(10) + testCases := map[string]struct{ + sinceSubmission time.Duration + tally foundation.TallyResult + valid bool + final bool + allow bool + }{ + "allow": { + sinceSubmission: policy.Windows.MinExecutionPeriod, + tally: foundation.NewTallyResult(sdk.NewDec(8), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), + valid: true, + final: true, + allow: true, + }, + "allow (abstain)": { + sinceSubmission: policy.Windows.MinExecutionPeriod, + tally: foundation.NewTallyResult(sdk.NewDec(4), sdk.NewDec(5), sdk.ZeroDec(), sdk.ZeroDec()), + valid: true, + final: true, + allow: true, + }, + "not final": { + sinceSubmission: policy.Windows.MinExecutionPeriod, + tally: foundation.NewTallyResult(sdk.ZeroDec(), sdk.NewDec(5), sdk.NewDec(1), sdk.ZeroDec()), + valid: true, + }, + "deny": { + sinceSubmission: policy.Windows.MinExecutionPeriod, + tally: foundation.NewTallyResult(sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDec(3), sdk.ZeroDec()), + valid: true, + final: true, + }, + "deny (all abstain)": { + sinceSubmission: policy.Windows.MinExecutionPeriod, + tally: foundation.NewTallyResult(sdk.ZeroDec(), sdk.NewDec(10), sdk.ZeroDec(), sdk.ZeroDec()), + valid: true, + final: true, + }, + "too early": { + sinceSubmission: policy.Windows.MinExecutionPeriod - time.Nanosecond, + tally: foundation.NewTallyResult(sdk.NewDec(8), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), + }, + } + + for name, tc := range testCases { + result, err := policy.Allow(tc.tally, totalWeight, tc.sinceSubmission) + if !tc.valid { + require.Error(t, err, name) + continue + } + require.NoError(t, err, name) + + require.Equal(t, tc.final, result.Final, name) + if tc.final { + require.Equal(t, tc.allow, result.Allow, name) + } + } +} diff --git a/x/foundation/genesis.go b/x/foundation/genesis.go index 5d1e393159..5ec0afebce 100644 --- a/x/foundation/genesis.go +++ b/x/foundation/genesis.go @@ -22,9 +22,14 @@ func DefaultParams() *Params { } func (data GenesisState) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + if data.Foundation != nil { + if err := data.Foundation.UnpackInterfaces(unpacker); err != nil { + return err + } + } + for _, ga := range data.Authorizations { - err := ga.UnpackInterfaces(unpacker) - if err != nil { + if err := ga.UnpackInterfaces(unpacker); err != nil { return err } } diff --git a/x/foundation/genesis_test.go b/x/foundation/genesis_test.go index 035f44763f..582c7e4ba5 100644 --- a/x/foundation/genesis_test.go +++ b/x/foundation/genesis_test.go @@ -11,6 +11,12 @@ import ( "github.com/line/lbm-sdk/x/foundation" ) +func TestDefaultGenesisState(t *testing.T) { + gs := foundation.DefaultGenesisState() + require.Equal(t, false, gs.Params.Enabled) + require.Equal(t, sdk.ZeroDec(), gs.Params.FoundationTax) +} + func TestValidateGenesis(t *testing.T) { createAddress := func() sdk.AccAddress { return sdk.BytesToAccAddress(secp256k1.GenPrivKey().PubKey().Address()) @@ -210,6 +216,23 @@ func TestValidateGenesis(t *testing.T) { }, }, }, + "invalid authorization": { + data: foundation.GenesisState{ + Authorizations: []foundation.GrantAuthorization{{ + Granter: foundation.ModuleName, + Grantee: createAddress().String(), + }}, + }, + }, + "invalid grantee": { + data: foundation.GenesisState{ + Authorizations: []foundation.GrantAuthorization{ + *foundation.GrantAuthorization{ + Granter: foundation.ModuleName, + }.WithAuthorization(&foundation.ReceiveFromTreasuryAuthorization{}), + }, + }, + }, } for name, tc := range testCases { diff --git a/x/foundation/keeper/genesis_test.go b/x/foundation/keeper/genesis_test.go index c3889d5acb..070258f78c 100644 --- a/x/foundation/keeper/genesis_test.go +++ b/x/foundation/keeper/genesis_test.go @@ -192,7 +192,7 @@ func (s *KeeperTestSuite) TestImportExportGenesis() { { Address: s.members[0].String(), Participating: true, - Metadata: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + Metadata: string(make([]rune, 256)), }, }, }, @@ -202,7 +202,7 @@ func (s *KeeperTestSuite) TestImportExportGenesis() { Proposals: []foundation.Proposal{ *foundation.Proposal{ Id: 1, - Metadata: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + Metadata: string(make([]rune, 256)), Proposers: []string{s.members[0].String()}, FoundationVersion: 1, }.WithMsgs([]sdk.Msg{&foundation.MsgWithdrawFromTreasury{ @@ -231,7 +231,7 @@ func (s *KeeperTestSuite) TestImportExportGenesis() { ProposalId: 1, Voter: s.members[0].String(), Option: foundation.VOTE_OPTION_YES, - Metadata: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + Metadata: string(make([]rune, 256)), }, }, }, diff --git a/x/foundation/keeper/member_test.go b/x/foundation/keeper/member_test.go index 60000698f8..20d99812c4 100644 --- a/x/foundation/keeper/member_test.go +++ b/x/foundation/keeper/member_test.go @@ -115,7 +115,7 @@ func (s *KeeperTestSuite) TestUpdateMembers() { { Address: s.stranger.String(), Participating: true, - Metadata: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + Metadata: string(make([]rune, 256)), }, }, }, diff --git a/x/foundation/keeper/proposal.go b/x/foundation/keeper/proposal.go index 47c5c51b4d..c98a5fafbd 100644 --- a/x/foundation/keeper/proposal.go +++ b/x/foundation/keeper/proposal.go @@ -89,7 +89,7 @@ func (k Keeper) SubmitProposal(ctx sdk.Context, proposers []string, metadata str Status: foundation.PROPOSAL_STATUS_SUBMITTED, ExecutorResult: foundation.PROPOSAL_EXECUTOR_RESULT_NOT_RUN, VotingPeriodEnd: ctx.BlockTime().Add(foundationInfo.GetDecisionPolicy().GetVotingPeriod()), - FinalTallyResult: DefaultTallyResult(), + FinalTallyResult: foundation.DefaultTallyResult(), } if err := proposal.SetMsgs(msgs); err != nil { return 0, err diff --git a/x/foundation/keeper/proposal_test.go b/x/foundation/keeper/proposal_test.go index 66141b0a6a..61017df1c1 100644 --- a/x/foundation/keeper/proposal_test.go +++ b/x/foundation/keeper/proposal_test.go @@ -106,7 +106,7 @@ func (s *KeeperTestSuite) TestSubmitProposal() { }, "long metadata": { proposers: []string{s.members[0].String()}, - metadata: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + metadata: string(make([]rune, 256)), msg: &foundation.MsgWithdrawFromTreasury{ Operator: s.operator.String(), To: s.stranger.String(), diff --git a/x/foundation/keeper/tally.go b/x/foundation/keeper/tally.go index 20296f9dc3..f919822144 100644 --- a/x/foundation/keeper/tally.go +++ b/x/foundation/keeper/tally.go @@ -8,16 +8,6 @@ import ( "github.com/line/lbm-sdk/x/foundation" ) -// DefaultTallyResult returns a TallyResult with all counts set to 0. -func DefaultTallyResult() foundation.TallyResult { - return foundation.TallyResult{ - YesCount: sdk.ZeroDec(), - NoCount: sdk.ZeroDec(), - NoWithVetoCount: sdk.ZeroDec(), - AbstainCount: sdk.ZeroDec(), - } -} - // doTallyAndUpdate performs a tally, and updates the proposal's // `FinalTallyResult` field only if the tally is final. func (k Keeper) doTallyAndUpdate(ctx sdk.Context, p *foundation.Proposal) error { @@ -65,7 +55,7 @@ func (k Keeper) tally(ctx sdk.Context, p foundation.Proposal) (foundation.TallyR return p.FinalTallyResult, nil } - tallyResult := DefaultTallyResult() + tallyResult := foundation.DefaultTallyResult() var errors []error k.iterateVotes(ctx, p.Id, func(vote foundation.Vote) (stop bool) { _, err := k.GetMember(ctx, sdk.AccAddress(vote.Voter)) diff --git a/x/foundation/keeper/vote_test.go b/x/foundation/keeper/vote_test.go index 907059781f..00f3600701 100644 --- a/x/foundation/keeper/vote_test.go +++ b/x/foundation/keeper/vote_test.go @@ -42,7 +42,7 @@ func (s *KeeperTestSuite) TestVote() { proposalID: s.activeProposal, voter: s.members[0], option: foundation.VOTE_OPTION_YES, - metadata: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + metadata: string(make([]rune, 256)), }, "voting too late": { proposalID: s.activeProposal, diff --git a/x/foundation/module/module.go b/x/foundation/module/module.go index 7f517f41f8..3308dfc187 100644 --- a/x/foundation/module/module.go +++ b/x/foundation/module/module.go @@ -127,7 +127,9 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { var genesisState foundation.GenesisState cdc.MustUnmarshalJSON(data, &genesisState) - am.keeper.InitGenesis(ctx, am.stakingKeeper, &genesisState) + if err := am.keeper.InitGenesis(ctx, am.stakingKeeper, &genesisState); err != nil { + panic(err) + } return []abci.ValidatorUpdate{} }