refactor(x/gov): Audit gov changes (backport #21454) (#21567)

Co-authored-by: son trinh <trinhleson2000@gmail.com>
This commit is contained in:
mergify[bot] 2024-09-05 17:31:06 +00:00 committed by GitHub
parent 68ec945293
commit 9adce9e987
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 357 additions and 90 deletions

View File

@ -2204,8 +2204,6 @@ Example Output:
The `params` endpoint allows users to query all parameters for the `gov` module.
<!-- TODO: #10197 Querying governance params outputs nil values -->
Using legacy v1beta1:
```bash
@ -2225,16 +2223,6 @@ Example Output:
"voting_params": {
"voting_period": "172800s"
},
"deposit_params": {
"min_deposit": [
],
"max_deposit_period": "0s"
},
"tally_params": {
"quorum": "0.000000000000000000",
"threshold": "0.000000000000000000",
"veto_threshold": "0.000000000000000000"
}
}
```
@ -2270,6 +2258,8 @@ Example Output:
}
```
Note: `params_type` are deprecated in v1 since all params are stored in Params.
#### deposits
The `deposits` endpoint allows users to query a deposit for a given proposal from a given depositor.

View File

@ -2,6 +2,9 @@ package utils_test
import (
"context"
"fmt"
"strconv"
"strings"
"testing"
"github.com/cometbft/cometbft/rpc/client/mock"
@ -13,6 +16,7 @@ import (
"cosmossdk.io/x/gov"
"cosmossdk.io/x/gov/client/utils"
v1 "cosmossdk.io/x/gov/types/v1"
"cosmossdk.io/x/gov/types/v1beta1"
"github.com/cosmos/cosmos-sdk/client"
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
@ -24,9 +28,12 @@ type TxSearchMock struct {
txConfig client.TxConfig
mock.Client
txs []cmttypes.Tx
// use for filter tx with query conditions
msgsSet [][]sdk.Msg
}
func (mock TxSearchMock) TxSearch(ctx context.Context, query string, prove bool, page, perPage *int, orderBy string) (*coretypes.ResultTxSearch, error) {
func (mock TxSearchMock) TxSearch(ctx context.Context, query string, _ bool, page, perPage *int, _ string) (*coretypes.ResultTxSearch, error) {
if page == nil {
*page = 0
}
@ -40,8 +47,11 @@ func (mock TxSearchMock) TxSearch(ctx context.Context, query string, prove bool,
// nil result with nil error crashes utils.QueryTxsByEvents
return &coretypes.ResultTxSearch{}, nil
}
txs, err := mock.filterTxs(query, start, end)
if err != nil {
return nil, err
}
txs := mock.txs[start:end]
rst := &coretypes.ResultTxSearch{Txs: make([]*coretypes.ResultTx, len(txs)), TotalCount: len(txs)}
for i := range txs {
rst.Txs[i] = &coretypes.ResultTx{Tx: txs[i]}
@ -54,6 +64,74 @@ func (mock TxSearchMock) Block(ctx context.Context, height *int64) (*coretypes.R
return &coretypes.ResultBlock{Block: &cmttypes.Block{}}, nil
}
// mock applying the query string in TxSearch
func (mock TxSearchMock) filterTxs(query string, start, end int) ([]cmttypes.Tx, error) {
filterTxs := []cmttypes.Tx{}
proposalIdStr, senderAddr := getQueryAttributes(query)
if senderAddr != "" {
proposalId, err := strconv.ParseUint(proposalIdStr, 10, 64)
if err != nil {
return nil, err
}
for i, msgs := range mock.msgsSet {
for _, msg := range msgs {
if voteMsg, ok := msg.(*v1beta1.MsgVote); ok {
if voteMsg.Voter == senderAddr && voteMsg.ProposalId == proposalId {
filterTxs = append(filterTxs, mock.txs[i])
continue
}
}
if voteMsg, ok := msg.(*v1.MsgVote); ok {
if voteMsg.Voter == senderAddr && voteMsg.ProposalId == proposalId {
filterTxs = append(filterTxs, mock.txs[i])
continue
}
}
if voteWeightedMsg, ok := msg.(*v1beta1.MsgVoteWeighted); ok {
if voteWeightedMsg.Voter == senderAddr && voteWeightedMsg.ProposalId == proposalId {
filterTxs = append(filterTxs, mock.txs[i])
continue
}
}
if voteWeightedMsg, ok := msg.(*v1.MsgVoteWeighted); ok {
if voteWeightedMsg.Voter == senderAddr && voteWeightedMsg.ProposalId == proposalId {
filterTxs = append(filterTxs, mock.txs[i])
continue
}
}
}
}
} else {
filterTxs = append(filterTxs, mock.txs...)
}
if len(filterTxs) < end {
return filterTxs, nil
}
return filterTxs[start:end], nil
}
// getQueryAttributes extracts value from query string
func getQueryAttributes(q string) (proposalId, senderAddr string) {
splitStr := strings.Split(q, " OR ")
if len(splitStr) >= 2 {
keySender := strings.Trim(splitStr[1], ")")
senderAddr = strings.Trim(strings.Split(keySender, "=")[1], "'")
keyProposal := strings.Split(q, " AND ")[0]
proposalId = strings.Trim(strings.Split(keyProposal, "=")[1], "'")
} else {
proposalId = strings.Trim(strings.Split(splitStr[0], "=")[1], "'")
}
return proposalId, senderAddr
}
func TestGetPaginatedVotes(t *testing.T) {
cdcOpts := codectestutil.CodecOptions{}
encCfg := moduletestutil.MakeTestEncodingConfig(cdcOpts, gov.AppModule{})
@ -178,3 +256,113 @@ func TestGetPaginatedVotes(t *testing.T) {
})
}
}
func TestGetSingleVote(t *testing.T) {
cdcOpts := codectestutil.CodecOptions{}
encCfg := moduletestutil.MakeTestEncodingConfig(cdcOpts, gov.AppModule{})
type testCase struct {
description string
msgs [][]sdk.Msg
votes []v1.Vote
expErr string
}
acc1 := make(sdk.AccAddress, 20)
acc1[0] = 1
acc1Str, err := cdcOpts.GetAddressCodec().BytesToString(acc1)
require.NoError(t, err)
acc2 := make(sdk.AccAddress, 20)
acc2[0] = 2
acc2Str, err := cdcOpts.GetAddressCodec().BytesToString(acc2)
require.NoError(t, err)
acc1Msgs := []sdk.Msg{
v1.NewMsgVote(acc1Str, 0, v1.OptionYes, ""),
v1.NewMsgVote(acc1Str, 0, v1.OptionYes, ""),
v1.NewMsgDeposit(acc1Str, 0, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10)))), // should be ignored
}
acc2Msgs := []sdk.Msg{
v1.NewMsgVote(acc2Str, 0, v1.OptionYes, ""),
v1.NewMsgVoteWeighted(acc2Str, 0, v1.NewNonSplitVoteOption(v1.OptionYes), ""),
v1beta1.NewMsgVoteWeighted(acc2Str, 0, v1beta1.NewNonSplitVoteOption(v1beta1.OptionYes)),
}
for _, tc := range []testCase{
{
description: "no vote found: no msgVote",
msgs: [][]sdk.Msg{
acc1Msgs[:1],
},
votes: []v1.Vote{},
expErr: "did not vote on proposalID",
},
{
description: "no vote found: wrong proposal ID",
msgs: [][]sdk.Msg{
acc1Msgs[:1],
},
votes: []v1.Vote{},
expErr: "did not vote on proposalID",
},
{
description: "query 2 voter vote",
msgs: [][]sdk.Msg{
acc1Msgs,
acc2Msgs[:1],
},
votes: []v1.Vote{
v1.NewVote(0, acc1Str, v1.NewNonSplitVoteOption(v1.OptionYes), ""),
v1.NewVote(0, acc2Str, v1.NewNonSplitVoteOption(v1.OptionYes), ""),
},
},
{
description: "query 2 voter vote with v1beta1",
msgs: [][]sdk.Msg{
acc1Msgs,
acc2Msgs[2:],
},
votes: []v1.Vote{
v1.NewVote(0, acc1Str, v1.NewNonSplitVoteOption(v1.OptionYes), ""),
v1.NewVote(0, acc2Str, v1.NewNonSplitVoteOption(v1.OptionYes), ""),
},
},
} {
tc := tc
t.Run(tc.description, func(t *testing.T) {
marshaled := make([]cmttypes.Tx, len(tc.msgs))
cli := TxSearchMock{txs: marshaled, txConfig: encCfg.TxConfig, msgsSet: tc.msgs}
clientCtx := client.Context{}.
WithLegacyAmino(encCfg.Amino).
WithClient(cli).
WithTxConfig(encCfg.TxConfig).
WithAddressCodec(cdcOpts.GetAddressCodec()).
WithCodec(encCfg.Codec)
for i := range tc.msgs {
txBuilder := clientCtx.TxConfig.NewTxBuilder()
err := txBuilder.SetMsgs(tc.msgs[i]...)
require.NoError(t, err)
tx, err := clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
require.NoError(t, err)
marshaled[i] = tx
}
// testing query single vote
for i, v := range tc.votes {
accAddr, err := clientCtx.AddressCodec.StringToBytes(v.Voter)
require.NoError(t, err)
voteParams := utils.QueryVoteParams{ProposalID: 0, Voter: accAddr}
voteData, err := utils.QueryVoteByTxQuery(clientCtx, voteParams)
if tc.expErr != "" {
require.Error(t, err)
require.True(t, strings.Contains(err.Error(), tc.expErr))
continue
}
require.NoError(t, err)
vote := v1.Vote{}
require.NoError(t, clientCtx.Codec.UnmarshalJSON(voteData, &vote))
require.Equal(t, v, vote, fmt.Sprintf("vote should be equal at entry %v", i))
}
})
}
}

View File

@ -1,13 +0,0 @@
package gov_test
import (
"cosmossdk.io/math"
"cosmossdk.io/x/gov/types/v1beta1"
stakingtypes "cosmossdk.io/x/staking/types"
)
var (
TestProposal = v1beta1.NewTextProposal("Test", "description")
TestDescription = stakingtypes.NewDescription("T", "E", "S", "T", "Z")
TestCommissionRates = stakingtypes.NewCommissionRates(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec())
)

View File

@ -157,6 +157,11 @@ func (k Keeper) AddDeposit(ctx context.Context, proposalID uint64, depositorAddr
activatedVotingPeriod = true
}
addr, err := k.authKeeper.AddressCodec().BytesToString(depositorAddr)
if err != nil {
return false, err
}
// Add or update deposit object
deposit, err := k.Deposits.Get(ctx, collections.Join(proposalID, depositorAddr))
switch {
@ -165,10 +170,6 @@ func (k Keeper) AddDeposit(ctx context.Context, proposalID uint64, depositorAddr
deposit.Amount = sdk.NewCoins(deposit.Amount...).Add(depositAmount...)
case errors.IsOf(err, collections.ErrNotFound):
// deposit doesn't exist
addr, err := k.authKeeper.AddressCodec().BytesToString(depositorAddr)
if err != nil {
return false, err
}
deposit = v1.NewDeposit(proposalID, addr, depositAmount)
default:
// failed to get deposit
@ -181,14 +182,9 @@ func (k Keeper) AddDeposit(ctx context.Context, proposalID uint64, depositorAddr
return false, err
}
depositorStrAddr, err := k.authKeeper.AddressCodec().BytesToString(depositorAddr)
if err != nil {
return false, err
}
if err := k.EventService.EventManager(ctx).EmitKV(
types.EventTypeProposalDeposit,
event.NewAttribute(types.AttributeKeyDepositor, depositorStrAddr),
event.NewAttribute(types.AttributeKeyDepositor, addr),
event.NewAttribute(sdk.AttributeKeyAmount, depositAmount.String()),
event.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)),
); err != nil {

View File

@ -27,11 +27,15 @@ func (k Keeper) SubmitProposal(ctx context.Context, messages []sdk.Msg, metadata
return v1.Proposal{}, err
}
proposerAddr, err := k.authKeeper.AddressCodec().BytesToString(proposer)
if err != nil {
return v1.Proposal{}, err
}
// additional checks per proposal types
switch proposalType {
case v1.ProposalType_PROPOSAL_TYPE_OPTIMISTIC:
proposerStr, _ := k.authKeeper.AddressCodec().BytesToString(proposer)
if len(params.OptimisticAuthorizedAddresses) > 0 && !slices.Contains(params.OptimisticAuthorizedAddresses, proposerStr) {
if len(params.OptimisticAuthorizedAddresses) > 0 && !slices.Contains(params.OptimisticAuthorizedAddresses, proposerAddr) {
return v1.Proposal{}, errorsmod.Wrap(types.ErrInvalidProposer, "proposer is not authorized to submit optimistic proposal")
}
case v1.ProposalType_PROPOSAL_TYPE_MULTIPLE_CHOICE:
@ -43,20 +47,35 @@ func (k Keeper) SubmitProposal(ctx context.Context, messages []sdk.Msg, metadata
msgs := make([]string, 0, len(messages)) // will hold a string slice of all Msg type URLs.
// Loop through all messages and confirm that each has a handler and the gov module account as the only signer
var currentMessagedBasedParams *v1.MessageBasedParams
for _, msg := range messages {
msgs = append(msgs, sdk.MsgTypeURL(msg))
// check if any of the message has message based params
hasMessagedBasedParams, err := k.MessageBasedParams.Has(ctx, sdk.MsgTypeURL(msg))
hasMessagedBasedParams := true
messagedBasedParams, err := k.MessageBasedParams.Get(ctx, sdk.MsgTypeURL(msg))
if err != nil {
return v1.Proposal{}, err
if !errorsmod.IsOf(err, collections.ErrNotFound) {
return v1.Proposal{}, err
}
hasMessagedBasedParams = false
}
if hasMessagedBasedParams {
// TODO(@julienrbrt), in the future, we can check if all messages have the same params
// and if so, we can allow the proposal.
if len(messages) > 1 {
return v1.Proposal{}, errorsmod.Wrap(types.ErrInvalidProposalMsg, "cannot submit multiple messages proposal with message based params")
// set initial value for currentMessagedBasedParams
if currentMessagedBasedParams == nil {
currentMessagedBasedParams = &messagedBasedParams
}
// check if newly fetched messagedBasedParams is different from the previous fetched params
isEqual, err := currentMessagedBasedParams.Equal(&messagedBasedParams)
if err != nil {
return v1.Proposal{}, err
}
if len(messages) > 1 && !isEqual {
return v1.Proposal{}, errorsmod.Wrap(types.ErrInvalidProposalMsg, "cannot submit multiple messages proposal with different message based params")
}
if proposalType != v1.ProposalType_PROPOSAL_TYPE_STANDARD {
@ -131,10 +150,6 @@ func (k Keeper) SubmitProposal(ctx context.Context, messages []sdk.Msg, metadata
return v1.Proposal{}, err
}
proposerAddr, err := k.authKeeper.AddressCodec().BytesToString(proposer)
if err != nil {
return v1.Proposal{}, err
}
submitTime := k.HeaderService.HeaderInfo(ctx).Time
proposal, err := v1.NewProposal(messages, proposalID, submitTime, submitTime.Add(*params.MaxDepositPeriod), metadata, title, summary, proposerAddr, proposalType)
if err != nil {

View File

@ -1,6 +1,7 @@
package keeper_test
import (
"errors"
"fmt"
"strings"
"testing"
@ -18,38 +19,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// TODO(tip): remove this
func (suite *KeeperTestSuite) TestDeleteProposal() {
testCases := map[string]struct {
proposalType v1.ProposalType
}{
"unspecified proposal type": {},
"regular proposal": {
proposalType: v1.ProposalType_PROPOSAL_TYPE_STANDARD,
},
"expedited proposal": {
proposalType: v1.ProposalType_PROPOSAL_TYPE_EXPEDITED,
},
}
for _, tc := range testCases {
// delete non-existing proposal
suite.Require().ErrorIs(suite.govKeeper.DeleteProposal(suite.ctx, 10), collections.ErrNotFound)
tp := TestProposal
proposal, err := suite.govKeeper.SubmitProposal(suite.ctx, tp, "", "test", "summary", suite.addrs[0], tc.proposalType)
suite.Require().NoError(err)
proposalID := proposal.Id
err = suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal)
suite.Require().NoError(err)
suite.Require().NotPanics(func() {
err := suite.govKeeper.DeleteProposal(suite.ctx, proposalID)
suite.Require().NoError(err)
}, "")
}
}
func (suite *KeeperTestSuite) TestActivateVotingPeriod() {
testCases := []struct {
name string
@ -147,6 +116,24 @@ func (suite *KeeperTestSuite) TestSubmitProposal() {
})
suite.Require().NoError(err)
// add 1 more messageBasedParams with the same value as above
err = suite.govKeeper.MessageBasedParams.Set(suite.ctx, sdk.MsgTypeURL(&v1.MsgSudoExec{}), v1.MessageBasedParams{
VotingPeriod: func() *time.Duration { t := time.Hour * 24 * 7; return &t }(),
Quorum: "0.4",
Threshold: "0.50",
VetoThreshold: "0.66",
})
suite.Require().NoError(err)
// add 1 more messageBasedParams with different value as above
err = suite.govKeeper.MessageBasedParams.Set(suite.ctx, sdk.MsgTypeURL(&v1.MsgCancelProposal{}), v1.MessageBasedParams{
VotingPeriod: func() *time.Duration { t := time.Hour * 24 * 7; return &t }(),
Quorum: "0.2",
Threshold: "0.4",
VetoThreshold: "0.7",
})
suite.Require().NoError(err)
testCases := []struct {
msgs []sdk.Msg
metadata string
@ -156,6 +143,12 @@ func (suite *KeeperTestSuite) TestSubmitProposal() {
{legacyProposal(&tp, govAcct), "", v1.ProposalType_PROPOSAL_TYPE_STANDARD, nil},
// normal proposal with msg with custom params
{[]sdk.Msg{&v1.MsgUpdateParams{Authority: govAcct}}, "", v1.ProposalType_PROPOSAL_TYPE_STANDARD, nil},
// normal proposal with 2 identical msgs with custom params
{[]sdk.Msg{&v1.MsgUpdateParams{Authority: govAcct}, &v1.MsgUpdateParams{Authority: govAcct}}, "", v1.ProposalType_PROPOSAL_TYPE_STANDARD, nil},
// normal proposal with 2 msgs with custom params shared the same value
{[]sdk.Msg{&v1.MsgUpdateParams{Authority: govAcct}, &v1.MsgSudoExec{Authority: govAcct}}, "", v1.ProposalType_PROPOSAL_TYPE_STANDARD, nil},
// normal proposal with 2 msgs with different custom params
{[]sdk.Msg{&v1.MsgUpdateParams{Authority: govAcct}, &v1.MsgCancelProposal{}}, "", v1.ProposalType_PROPOSAL_TYPE_STANDARD, errors.New("cannot submit multiple messages proposal with different message based params")},
{legacyProposal(&tp, govAcct), "", v1.ProposalType_PROPOSAL_TYPE_EXPEDITED, nil},
{nil, "", v1.ProposalType_PROPOSAL_TYPE_MULTIPLE_CHOICE, nil},
// Keeper does not check the validity of title and description, no error

View File

@ -98,7 +98,7 @@ func (k Keeper) tallyStandard(ctx context.Context, proposal v1.Proposal, totalVo
}
// If no one votes (everyone abstains), proposal fails
if totalVoterPower.Sub(results[v1.OptionAbstain]).Equal(math.LegacyZeroDec()) {
if totalVoterPower.Equal(results[v1.OptionAbstain]) {
return false, false, tallyResults, nil
}
@ -142,7 +142,7 @@ func (k Keeper) tallyExpedited(totalVoterPower math.LegacyDec, totalBonded math.
}
// If no one votes (everyone abstains), proposal fails
if totalVoterPower.Sub(results[v1.OptionAbstain]).Equal(math.LegacyZeroDec()) {
if totalVoterPower.Equal(results[v1.OptionAbstain]) {
return false, false, tallyResults, nil
}
@ -160,7 +160,6 @@ func (k Keeper) tallyExpedited(totalVoterPower math.LegacyDec, totalBonded math.
// If more than 2/3 of non-abstaining voters vote Yes, proposal passes
threshold, _ := math.LegacyNewDecFromStr(params.GetExpeditedThreshold())
if results[v1.OptionYes].Quo(totalVoterPower.Sub(results[v1.OptionAbstain])).GT(threshold) {
return true, false, tallyResults, nil
}
@ -206,7 +205,6 @@ func (k Keeper) tallyMultipleChoice(totalVoterPower math.LegacyDec, totalBonded
}
// a multiple choice proposal always passes unless it was spam or quorum was not reached.
return true, false, tallyResults, nil
}

View File

@ -57,9 +57,9 @@ func (k Keeper) AddVote(ctx context.Context, proposalID uint64, voterAddr sdk.Ac
}
// verify votes only on existing votes
if proposalOptionsStr.OptionOne == "" && option.Option == v1.OptionOne { // should never trigger option one is always mandatory
if proposalOptionsStr.OptionOne == "" && option.Option == v1.OptionOne {
return errors.Wrap(types.ErrInvalidVote, "invalid vote option")
} else if proposalOptionsStr.OptionTwo == "" && option.Option == v1.OptionTwo { // should never trigger option two is always mandatory
} else if proposalOptionsStr.OptionTwo == "" && option.Option == v1.OptionTwo {
return errors.Wrap(types.ErrInvalidVote, "invalid vote option")
} else if proposalOptionsStr.OptionThree == "" && option.Option == v1.OptionThree {
return errors.Wrap(types.ErrInvalidVote, "invalid vote option")

View File

@ -5,6 +5,7 @@ import (
"time"
"cosmossdk.io/core/address"
"cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -332,3 +333,104 @@ func (p MessageBasedParams) ValidateBasic() error {
return nil
}
func (p MessageBasedParams) Equal(params *MessageBasedParams) (bool, error) {
if p.VotingPeriod != nil && params.VotingPeriod != nil {
if p.VotingPeriod.Seconds() != params.VotingPeriod.Seconds() {
return false, nil
}
} else if p.VotingPeriod == nil && params.VotingPeriod != nil ||
p.VotingPeriod != nil && params.VotingPeriod == nil {
return false, nil
}
quorum1, err := sdkmath.LegacyNewDecFromStr(p.Quorum)
if err != nil {
if !errors.IsOf(err, sdkmath.ErrLegacyEmptyDecimalStr) {
return false, fmt.Errorf("invalid quorum string: %w", err)
}
quorum1 = sdkmath.LegacyZeroDec()
}
quorum2, err := sdkmath.LegacyNewDecFromStr(params.Quorum)
if err != nil {
if !errors.IsOf(err, sdkmath.ErrLegacyEmptyDecimalStr) {
return false, fmt.Errorf("invalid compared quorum string: %w", err)
}
quorum2 = sdkmath.LegacyZeroDec()
}
if !quorum1.Equal(quorum2) {
return false, nil
}
yesQuorum1, err := sdkmath.LegacyNewDecFromStr(p.YesQuorum)
if err != nil {
if !errors.IsOf(err, sdkmath.ErrLegacyEmptyDecimalStr) {
return false, fmt.Errorf("invalid yes quorum string: %w", err)
}
yesQuorum1 = sdkmath.LegacyZeroDec()
}
yesQuorum2, err := sdkmath.LegacyNewDecFromStr(params.YesQuorum)
if err != nil {
if !errors.IsOf(err, sdkmath.ErrLegacyEmptyDecimalStr) {
return false, fmt.Errorf("invalid compared yes quorum string: %w", err)
}
yesQuorum2 = sdkmath.LegacyZeroDec()
}
if !yesQuorum1.Equal(yesQuorum2) {
return false, nil
}
threshold1, err := sdkmath.LegacyNewDecFromStr(p.Threshold)
if err != nil {
if !errors.IsOf(err, sdkmath.ErrLegacyEmptyDecimalStr) {
return false, fmt.Errorf("invalid vote threshold string: %w", err)
}
threshold1 = sdkmath.LegacyZeroDec()
}
threshold2, err := sdkmath.LegacyNewDecFromStr(params.Threshold)
if err != nil {
if !errors.IsOf(err, sdkmath.ErrLegacyEmptyDecimalStr) {
return false, fmt.Errorf("invalid compared vote threshold string: %w", err)
}
threshold2 = sdkmath.LegacyZeroDec()
}
if !threshold1.Equal(threshold2) {
return false, nil
}
vetoThreshold1, err := sdkmath.LegacyNewDecFromStr(p.VetoThreshold)
if err != nil {
if !errors.IsOf(err, sdkmath.ErrLegacyEmptyDecimalStr) {
return false, fmt.Errorf("invalid veto threshold string: %w", err)
}
vetoThreshold1 = sdkmath.LegacyZeroDec()
}
vetoThreshold2, err := sdkmath.LegacyNewDecFromStr(params.VetoThreshold)
if err != nil {
if !errors.IsOf(err, sdkmath.ErrLegacyEmptyDecimalStr) {
return false, fmt.Errorf("invalid compared veto threshold string: %w", err)
}
vetoThreshold2 = sdkmath.LegacyZeroDec()
}
if !vetoThreshold1.Equal(vetoThreshold2) {
return false, nil
}
return true, nil
}

View File

@ -68,7 +68,7 @@ func (p Proposal) GetMsgs() ([]sdk.Msg, error) {
// the proposal is expedited. Otherwise, returns the regular min deposit from
// gov params.
func (p Proposal) GetMinDepositFromParams(params Params) sdk.Coins {
if p.Expedited {
if p.ProposalType == ProposalType_PROPOSAL_TYPE_EXPEDITED {
return params.ExpeditedMinDeposit
}
return params.MinDeposit

View File

@ -9,8 +9,6 @@ import (
var _ Router = (*router)(nil)
// Router implements a governance Handler router.
//
// TODO: Use generic router (ref #3976).
type Router interface {
AddRoute(r string, h Handler) (rtr Router)
HasRoute(r string) bool