github.com/cosmos/cosmos-sdk@v0.50.10/x/gov/keeper/msg_server_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"strings"
     5  	"time"
     6  
     7  	sdkmath "cosmossdk.io/math"
     8  
     9  	simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
    10  	"github.com/cosmos/cosmos-sdk/testutil/testdata"
    11  	sdk "github.com/cosmos/cosmos-sdk/types"
    12  	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
    13  	v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
    14  	"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
    15  )
    16  
    17  const (
    18  	abc = "abc"
    19  	o1  = "-0.1"
    20  )
    21  
    22  var longAddressError = "address max length is 255"
    23  
    24  func (suite *KeeperTestSuite) TestSubmitProposalReq() {
    25  	suite.reset()
    26  	govAcct := suite.govKeeper.GetGovernanceAccount(suite.ctx).GetAddress()
    27  	addrs := suite.addrs
    28  	proposer := addrs[0]
    29  
    30  	coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000)))
    31  	initialDeposit := coins
    32  	params, _ := suite.govKeeper.Params.Get(suite.ctx)
    33  	minDeposit := params.MinDeposit
    34  	bankMsg := &banktypes.MsgSend{
    35  		FromAddress: govAcct.String(),
    36  		ToAddress:   proposer.String(),
    37  		Amount:      coins,
    38  	}
    39  
    40  	cases := map[string]struct {
    41  		preRun    func() (*v1.MsgSubmitProposal, error)
    42  		expErr    bool
    43  		expErrMsg string
    44  	}{
    45  		"invalid addr": {
    46  			preRun: func() (*v1.MsgSubmitProposal, error) {
    47  				return v1.NewMsgSubmitProposal(
    48  					[]sdk.Msg{bankMsg},
    49  					initialDeposit,
    50  					"",
    51  					strings.Repeat("1", 300),
    52  					"Proposal",
    53  					"description of proposal",
    54  					false,
    55  				)
    56  			},
    57  			expErr:    true,
    58  			expErrMsg: "invalid proposer address",
    59  		},
    60  		"empty msgs and metadata": {
    61  			preRun: func() (*v1.MsgSubmitProposal, error) {
    62  				return v1.NewMsgSubmitProposal(
    63  					nil,
    64  					initialDeposit,
    65  					proposer.String(),
    66  					"",
    67  					"Proposal",
    68  					"description of proposal",
    69  					false,
    70  				)
    71  			},
    72  			expErr:    true,
    73  			expErrMsg: "no messages proposed",
    74  		},
    75  		"empty title": {
    76  			preRun: func() (*v1.MsgSubmitProposal, error) {
    77  				return v1.NewMsgSubmitProposal(
    78  					[]sdk.Msg{bankMsg},
    79  					initialDeposit,
    80  					proposer.String(),
    81  					"",
    82  					"",
    83  					"description of proposal",
    84  					false,
    85  				)
    86  			},
    87  			expErr:    true,
    88  			expErrMsg: "proposal title cannot be empty",
    89  		},
    90  		"empty description": {
    91  			preRun: func() (*v1.MsgSubmitProposal, error) {
    92  				return v1.NewMsgSubmitProposal(
    93  					[]sdk.Msg{bankMsg},
    94  					initialDeposit,
    95  					proposer.String(),
    96  					"",
    97  					"Proposal",
    98  					"",
    99  					false,
   100  				)
   101  			},
   102  			expErr:    true,
   103  			expErrMsg: "proposal summary cannot be empty",
   104  		},
   105  		"title != metadata.title": {
   106  			preRun: func() (*v1.MsgSubmitProposal, error) {
   107  				return v1.NewMsgSubmitProposal(
   108  					[]sdk.Msg{bankMsg},
   109  					initialDeposit,
   110  					proposer.String(),
   111  					"{\"title\":\"Proposal\", \"description\":\"description of proposal\"}",
   112  					"Proposal2",
   113  					"description of proposal",
   114  					false,
   115  				)
   116  			},
   117  			expErr:    true,
   118  			expErrMsg: "metadata title 'Proposal' must equal proposal title 'Proposal2",
   119  		},
   120  		"summary != metadata.summary": {
   121  			preRun: func() (*v1.MsgSubmitProposal, error) {
   122  				return v1.NewMsgSubmitProposal(
   123  					[]sdk.Msg{bankMsg},
   124  					initialDeposit,
   125  					proposer.String(),
   126  					"{\"title\":\"Proposal\", \"description\":\"description of proposal\"}",
   127  					"Proposal",
   128  					"description",
   129  					false,
   130  				)
   131  			},
   132  			expErr:    true,
   133  			expErrMsg: "metadata summary '' must equal proposal summary 'description'",
   134  		},
   135  		"metadata too long": {
   136  			preRun: func() (*v1.MsgSubmitProposal, error) {
   137  				return v1.NewMsgSubmitProposal(
   138  					[]sdk.Msg{bankMsg},
   139  					initialDeposit,
   140  					proposer.String(),
   141  					strings.Repeat("1", 300),
   142  					"Proposal",
   143  					"description of proposal",
   144  					false,
   145  				)
   146  			},
   147  			expErr:    true,
   148  			expErrMsg: "metadata too long",
   149  		},
   150  		"summary too long": {
   151  			preRun: func() (*v1.MsgSubmitProposal, error) {
   152  				return v1.NewMsgSubmitProposal(
   153  					[]sdk.Msg{bankMsg},
   154  					initialDeposit,
   155  					proposer.String(),
   156  					"",
   157  					"Proposal",
   158  					strings.Repeat("1", 300*40),
   159  					false,
   160  				)
   161  			},
   162  			expErr:    true,
   163  			expErrMsg: "summary too long",
   164  		},
   165  		"many signers": {
   166  			preRun: func() (*v1.MsgSubmitProposal, error) {
   167  				return v1.NewMsgSubmitProposal(
   168  					[]sdk.Msg{testdata.NewTestMsg(govAcct, addrs[0])},
   169  					initialDeposit,
   170  					proposer.String(),
   171  					"",
   172  					"Proposal",
   173  					"description of proposal",
   174  					false,
   175  				)
   176  			},
   177  			expErr:    true,
   178  			expErrMsg: "expected gov account as only signer for proposal message",
   179  		},
   180  		"signer isn't gov account": {
   181  			preRun: func() (*v1.MsgSubmitProposal, error) {
   182  				return v1.NewMsgSubmitProposal(
   183  					[]sdk.Msg{testdata.NewTestMsg(addrs[0])},
   184  					initialDeposit,
   185  					proposer.String(),
   186  					"",
   187  					"Proposal",
   188  					"description of proposal",
   189  					false,
   190  				)
   191  			},
   192  			expErr:    true,
   193  			expErrMsg: "expected gov account as only signer for proposal message",
   194  		},
   195  		"invalid msg handler": {
   196  			preRun: func() (*v1.MsgSubmitProposal, error) {
   197  				return v1.NewMsgSubmitProposal(
   198  					[]sdk.Msg{testdata.NewTestMsg(govAcct)},
   199  					initialDeposit,
   200  					proposer.String(),
   201  					"",
   202  					"Proposal",
   203  					"description of proposal",
   204  					false,
   205  				)
   206  			},
   207  			expErr:    true,
   208  			expErrMsg: "proposal message not recognized by router",
   209  		},
   210  		"invalid deposited coin": {
   211  			preRun: func() (*v1.MsgSubmitProposal, error) {
   212  				return v1.NewMsgSubmitProposal(
   213  					[]sdk.Msg{bankMsg},
   214  					[]sdk.Coin{sdk.NewCoin("invalid", sdkmath.NewInt(100))},
   215  					proposer.String(),
   216  					"",
   217  					"Proposal",
   218  					"description of proposal",
   219  					false,
   220  				)
   221  			},
   222  			expErr:    true,
   223  			expErrMsg: "deposited 100invalid, but gov accepts only the following denom(s): [stake]: invalid deposit denom",
   224  		},
   225  		"invalid deposited coin (multiple)": {
   226  			preRun: func() (*v1.MsgSubmitProposal, error) {
   227  				return v1.NewMsgSubmitProposal(
   228  					[]sdk.Msg{bankMsg},
   229  					initialDeposit.Add(sdk.NewCoin("invalid", sdkmath.NewInt(100))),
   230  					proposer.String(),
   231  					"",
   232  					"Proposal",
   233  					"description of proposal",
   234  					false,
   235  				)
   236  			},
   237  			expErr:    true,
   238  			expErrMsg: "deposited 100invalid,100000stake, but gov accepts only the following denom(s): [stake]: invalid deposit denom",
   239  		},
   240  		"all good": {
   241  			preRun: func() (*v1.MsgSubmitProposal, error) {
   242  				return v1.NewMsgSubmitProposal(
   243  					[]sdk.Msg{bankMsg},
   244  					initialDeposit,
   245  					proposer.String(),
   246  					"",
   247  					"Proposal",
   248  					"description of proposal",
   249  					false,
   250  				)
   251  			},
   252  			expErr: false,
   253  		},
   254  		"all good with min deposit": {
   255  			preRun: func() (*v1.MsgSubmitProposal, error) {
   256  				return v1.NewMsgSubmitProposal(
   257  					[]sdk.Msg{bankMsg},
   258  					minDeposit,
   259  					proposer.String(),
   260  					"",
   261  					"Proposal",
   262  					"description of proposal",
   263  					false,
   264  				)
   265  			},
   266  			expErr: false,
   267  		},
   268  	}
   269  
   270  	for name, tc := range cases {
   271  		suite.Run(name, func() {
   272  			msg, err := tc.preRun()
   273  			suite.Require().NoError(err)
   274  			res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
   275  			if tc.expErr {
   276  				suite.Require().Error(err)
   277  				suite.Require().Contains(err.Error(), tc.expErrMsg)
   278  			} else {
   279  				suite.Require().NoError(err)
   280  				suite.Require().NotNil(res.ProposalId)
   281  			}
   282  		})
   283  	}
   284  }
   285  
   286  func (suite *KeeperTestSuite) TestCancelProposalReq() {
   287  	govAcct := suite.govKeeper.GetGovernanceAccount(suite.ctx).GetAddress()
   288  	addrs := suite.addrs
   289  	proposer := addrs[0]
   290  
   291  	coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000)))
   292  	bankMsg := &banktypes.MsgSend{
   293  		FromAddress: govAcct.String(),
   294  		ToAddress:   proposer.String(),
   295  		Amount:      coins,
   296  	}
   297  
   298  	msg, err := v1.NewMsgSubmitProposal(
   299  		[]sdk.Msg{bankMsg},
   300  		coins,
   301  		proposer.String(),
   302  		"", "title", "summary",
   303  		false,
   304  	)
   305  	suite.Require().NoError(err)
   306  
   307  	res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
   308  	suite.Require().NoError(err)
   309  	suite.Require().NotNil(res.ProposalId)
   310  	proposalID := res.ProposalId
   311  
   312  	cases := map[string]struct {
   313  		preRun     func() uint64
   314  		expErr     bool
   315  		expErrMsg  string
   316  		proposalID uint64
   317  		depositor  sdk.AccAddress
   318  	}{
   319  		"wrong proposal id": {
   320  			preRun: func() uint64 {
   321  				return 0
   322  			},
   323  			depositor: proposer,
   324  			expErr:    true,
   325  			expErrMsg: "not found",
   326  		},
   327  		"valid proposal but invalid proposer": {
   328  			preRun: func() uint64 {
   329  				return proposalID
   330  			},
   331  			depositor: addrs[1],
   332  			expErr:    true,
   333  			expErrMsg: "invalid proposer",
   334  		},
   335  		"empty proposer": {
   336  			preRun: func() uint64 {
   337  				return proposalID
   338  			},
   339  			depositor: sdk.AccAddress{},
   340  			expErr:    true,
   341  			expErrMsg: "invalid proposer address: empty address string is not allowed",
   342  		},
   343  		"all good": {
   344  			preRun: func() uint64 {
   345  				msg, err := v1.NewMsgSubmitProposal(
   346  					[]sdk.Msg{bankMsg},
   347  					coins,
   348  					proposer.String(),
   349  					"",
   350  					"Proposal",
   351  					"description of proposal",
   352  					false,
   353  				)
   354  				suite.Require().NoError(err)
   355  
   356  				res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
   357  				suite.Require().NoError(err)
   358  				suite.Require().NotNil(res.ProposalId)
   359  				return res.ProposalId
   360  			},
   361  			depositor: proposer,
   362  			expErr:    false,
   363  		},
   364  	}
   365  
   366  	for name, tc := range cases {
   367  		suite.Run(name, func() {
   368  			proposalID := tc.preRun()
   369  			cancelProposalReq := v1.NewMsgCancelProposal(proposalID, tc.depositor.String())
   370  			_, err := suite.msgSrvr.CancelProposal(suite.ctx, cancelProposalReq)
   371  			if tc.expErr {
   372  				suite.Require().Error(err)
   373  				suite.Require().Contains(err.Error(), tc.expErrMsg)
   374  			} else {
   375  				suite.Require().NoError(err)
   376  			}
   377  		})
   378  	}
   379  }
   380  
   381  func (suite *KeeperTestSuite) TestVoteReq() {
   382  	suite.reset()
   383  	govAcct := suite.govKeeper.GetGovernanceAccount(suite.ctx).GetAddress()
   384  	addrs := suite.addrs
   385  	proposer := addrs[0]
   386  
   387  	coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000)))
   388  	params, _ := suite.govKeeper.Params.Get(suite.ctx)
   389  	minDeposit := params.MinDeposit
   390  	bankMsg := &banktypes.MsgSend{
   391  		FromAddress: govAcct.String(),
   392  		ToAddress:   proposer.String(),
   393  		Amount:      coins,
   394  	}
   395  
   396  	msg, err := v1.NewMsgSubmitProposal(
   397  		[]sdk.Msg{bankMsg},
   398  		minDeposit,
   399  		proposer.String(),
   400  		"",
   401  		"Proposal",
   402  		"description of proposal",
   403  		false,
   404  	)
   405  	suite.Require().NoError(err)
   406  
   407  	res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
   408  	suite.Require().NoError(err)
   409  	suite.Require().NotNil(res.ProposalId)
   410  	proposalID := res.ProposalId
   411  
   412  	cases := map[string]struct {
   413  		preRun    func() uint64
   414  		expErr    bool
   415  		expErrMsg string
   416  		option    v1.VoteOption
   417  		metadata  string
   418  		voter     sdk.AccAddress
   419  	}{
   420  		"empty voter": {
   421  			preRun: func() uint64 {
   422  				return proposalID
   423  			},
   424  			option:    v1.VoteOption_VOTE_OPTION_YES,
   425  			voter:     sdk.AccAddress{},
   426  			metadata:  "",
   427  			expErr:    true,
   428  			expErrMsg: "invalid voter address",
   429  		},
   430  		"wrong vote option": {
   431  			preRun: func() uint64 {
   432  				return proposalID
   433  			},
   434  			option:    v1.VoteOption(0x13),
   435  			voter:     proposer,
   436  			metadata:  "",
   437  			expErr:    true,
   438  			expErrMsg: "invalid vote option",
   439  		},
   440  		"vote on inactive proposal": {
   441  			preRun: func() uint64 {
   442  				msg, err := v1.NewMsgSubmitProposal(
   443  					[]sdk.Msg{bankMsg},
   444  					coins,
   445  					proposer.String(),
   446  					"",
   447  					"Proposal",
   448  					"description of proposal",
   449  					false,
   450  				)
   451  				suite.Require().NoError(err)
   452  
   453  				res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
   454  				suite.Require().NoError(err)
   455  				suite.Require().NotNil(res.ProposalId)
   456  				return res.ProposalId
   457  			},
   458  			option:    v1.VoteOption_VOTE_OPTION_YES,
   459  			voter:     proposer,
   460  			metadata:  "",
   461  			expErr:    true,
   462  			expErrMsg: "inactive proposal",
   463  		},
   464  		"metadata too long": {
   465  			preRun: func() uint64 {
   466  				return proposalID
   467  			},
   468  			option:    v1.VoteOption_VOTE_OPTION_YES,
   469  			voter:     proposer,
   470  			metadata:  strings.Repeat("a", 300),
   471  			expErr:    true,
   472  			expErrMsg: "metadata too long",
   473  		},
   474  		"voter error": {
   475  			preRun: func() uint64 {
   476  				return proposalID
   477  			},
   478  			option:    v1.VoteOption_VOTE_OPTION_YES,
   479  			voter:     sdk.AccAddress(strings.Repeat("a", 300)),
   480  			metadata:  "",
   481  			expErr:    true,
   482  			expErrMsg: longAddressError,
   483  		},
   484  		"all good": {
   485  			preRun: func() uint64 {
   486  				msg, err := v1.NewMsgSubmitProposal(
   487  					[]sdk.Msg{bankMsg},
   488  					minDeposit,
   489  					proposer.String(),
   490  					"",
   491  					"Proposal",
   492  					"description of proposal",
   493  					false,
   494  				)
   495  				suite.Require().NoError(err)
   496  
   497  				res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
   498  				suite.Require().NoError(err)
   499  				suite.Require().NotNil(res.ProposalId)
   500  				return res.ProposalId
   501  			},
   502  			option:   v1.VoteOption_VOTE_OPTION_YES,
   503  			voter:    proposer,
   504  			metadata: "",
   505  			expErr:   false,
   506  		},
   507  	}
   508  
   509  	for name, tc := range cases {
   510  		suite.Run(name, func() {
   511  			pID := tc.preRun()
   512  			voteReq := v1.NewMsgVote(tc.voter, pID, tc.option, tc.metadata)
   513  			_, err := suite.msgSrvr.Vote(suite.ctx, voteReq)
   514  			if tc.expErr {
   515  				suite.Require().Error(err)
   516  				suite.Require().Contains(err.Error(), tc.expErrMsg)
   517  			} else {
   518  				suite.Require().NoError(err)
   519  			}
   520  		})
   521  	}
   522  }
   523  
   524  func (suite *KeeperTestSuite) TestVoteWeightedReq() {
   525  	suite.reset()
   526  	govAcct := suite.govKeeper.GetGovernanceAccount(suite.ctx).GetAddress()
   527  
   528  	proposer := simtestutil.AddTestAddrsIncremental(suite.bankKeeper, suite.stakingKeeper, suite.ctx, 1, sdkmath.NewInt(50000000))[0]
   529  
   530  	coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000)))
   531  	params, _ := suite.govKeeper.Params.Get(suite.ctx)
   532  	minDeposit := params.MinDeposit
   533  	bankMsg := &banktypes.MsgSend{
   534  		FromAddress: govAcct.String(),
   535  		ToAddress:   proposer.String(),
   536  		Amount:      coins,
   537  	}
   538  
   539  	msg, err := v1.NewMsgSubmitProposal(
   540  		[]sdk.Msg{bankMsg},
   541  		minDeposit,
   542  		proposer.String(),
   543  		"",
   544  		"Proposal",
   545  		"description of proposal",
   546  		false,
   547  	)
   548  	suite.Require().NoError(err)
   549  
   550  	res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
   551  	suite.Require().NoError(err)
   552  	suite.Require().NotNil(res.ProposalId)
   553  	proposalID := res.ProposalId
   554  
   555  	cases := map[string]struct {
   556  		preRun    func() uint64
   557  		vote      *v1.MsgVote
   558  		expErr    bool
   559  		expErrMsg string
   560  		option    v1.WeightedVoteOptions
   561  		metadata  string
   562  		voter     sdk.AccAddress
   563  	}{
   564  		"empty voter": {
   565  			preRun: func() uint64 {
   566  				return proposalID
   567  			},
   568  			option: v1.WeightedVoteOptions{
   569  				v1.NewWeightedVoteOption(v1.OptionYes, sdkmath.LegacyNewDec(1)),
   570  			},
   571  			voter:     sdk.AccAddress{},
   572  			metadata:  "",
   573  			expErr:    true,
   574  			expErrMsg: "invalid voter address",
   575  		},
   576  		"weights sum > 1": {
   577  			preRun: func() uint64 {
   578  				return proposalID
   579  			},
   580  			option: v1.WeightedVoteOptions{
   581  				v1.NewWeightedVoteOption(v1.OptionYes, sdkmath.LegacyNewDec(1)),
   582  				v1.NewWeightedVoteOption(v1.OptionAbstain, sdkmath.LegacyNewDec(1)),
   583  			},
   584  			voter:     proposer,
   585  			metadata:  "",
   586  			expErr:    true,
   587  			expErrMsg: "total weight overflow 1.00: invalid vote option",
   588  		},
   589  		"duplicate vote options": {
   590  			preRun: func() uint64 {
   591  				return proposalID
   592  			},
   593  			option: v1.WeightedVoteOptions{
   594  				v1.NewWeightedVoteOption(v1.OptionYes, sdkmath.LegacyNewDecWithPrec(5, 1)),
   595  				v1.NewWeightedVoteOption(v1.OptionYes, sdkmath.LegacyNewDecWithPrec(5, 1)),
   596  			},
   597  			voter:     proposer,
   598  			metadata:  "",
   599  			expErr:    true,
   600  			expErrMsg: "duplicated vote option",
   601  		},
   602  		"zero weight": {
   603  			preRun: func() uint64 {
   604  				return proposalID
   605  			},
   606  			option: v1.WeightedVoteOptions{
   607  				v1.NewWeightedVoteOption(v1.OptionYes, sdkmath.LegacyNewDec(0)),
   608  			},
   609  			voter:     proposer,
   610  			metadata:  "",
   611  			expErr:    true,
   612  			expErrMsg: `option:VOTE_OPTION_YES weight:"0.000000000000000000" : invalid vote option`,
   613  		},
   614  		"negative weight": {
   615  			preRun: func() uint64 {
   616  				return proposalID
   617  			},
   618  			option: v1.WeightedVoteOptions{
   619  				v1.NewWeightedVoteOption(v1.OptionYes, sdkmath.LegacyNewDec(-1)),
   620  			},
   621  			voter:     proposer,
   622  			metadata:  "",
   623  			expErr:    true,
   624  			expErrMsg: `option:VOTE_OPTION_YES weight:"-1.000000000000000000" : invalid vote option`,
   625  		},
   626  		"empty options": {
   627  			preRun: func() uint64 {
   628  				return proposalID
   629  			},
   630  			option:    v1.WeightedVoteOptions{},
   631  			voter:     proposer,
   632  			metadata:  "",
   633  			expErr:    true,
   634  			expErrMsg: "invalid request",
   635  		},
   636  		"invalid vote option": {
   637  			preRun: func() uint64 {
   638  				return proposalID
   639  			},
   640  			option:    v1.NewNonSplitVoteOption(v1.VoteOption(0x13)),
   641  			voter:     proposer,
   642  			metadata:  "",
   643  			expErr:    true,
   644  			expErrMsg: "invalid vote option",
   645  		},
   646  		"weight sum < 1": {
   647  			preRun: func() uint64 {
   648  				return proposalID
   649  			},
   650  			option: v1.WeightedVoteOptions{ // weight sum <1
   651  				v1.NewWeightedVoteOption(v1.OptionYes, sdkmath.LegacyNewDecWithPrec(5, 1)),
   652  			},
   653  			voter:     proposer,
   654  			metadata:  "",
   655  			expErr:    true,
   656  			expErrMsg: "total weight lower than 1.00: invalid vote option",
   657  		},
   658  		"vote on inactive proposal": {
   659  			preRun: func() uint64 {
   660  				msg, err := v1.NewMsgSubmitProposal(
   661  					[]sdk.Msg{bankMsg},
   662  					coins,
   663  					proposer.String(),
   664  					"",
   665  					"Proposal",
   666  					"description of proposal",
   667  					false,
   668  				)
   669  				suite.Require().NoError(err)
   670  
   671  				res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
   672  				suite.Require().NoError(err)
   673  				suite.Require().NotNil(res.ProposalId)
   674  				return res.ProposalId
   675  			},
   676  			option:    v1.NewNonSplitVoteOption(v1.VoteOption_VOTE_OPTION_YES),
   677  			voter:     proposer,
   678  			metadata:  "",
   679  			expErr:    true,
   680  			expErrMsg: "inactive proposal",
   681  		},
   682  		"metadata too long": {
   683  			preRun: func() uint64 {
   684  				return proposalID
   685  			},
   686  			option:    v1.NewNonSplitVoteOption(v1.VoteOption_VOTE_OPTION_YES),
   687  			voter:     proposer,
   688  			metadata:  strings.Repeat("a", 300),
   689  			expErr:    true,
   690  			expErrMsg: "metadata too long",
   691  		},
   692  		"voter error": {
   693  			preRun: func() uint64 {
   694  				return proposalID
   695  			},
   696  			option:    v1.NewNonSplitVoteOption(v1.VoteOption_VOTE_OPTION_YES),
   697  			voter:     sdk.AccAddress(strings.Repeat("a", 300)),
   698  			metadata:  "",
   699  			expErr:    true,
   700  			expErrMsg: longAddressError,
   701  		},
   702  		"all good": {
   703  			preRun: func() uint64 {
   704  				msg, err := v1.NewMsgSubmitProposal(
   705  					[]sdk.Msg{bankMsg},
   706  					minDeposit,
   707  					proposer.String(),
   708  					"",
   709  					"Proposal",
   710  					"description of proposal",
   711  					false,
   712  				)
   713  				suite.Require().NoError(err)
   714  
   715  				res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
   716  				suite.Require().NoError(err)
   717  				suite.Require().NotNil(res.ProposalId)
   718  				return res.ProposalId
   719  			},
   720  			option:   v1.NewNonSplitVoteOption(v1.VoteOption_VOTE_OPTION_YES),
   721  			voter:    proposer,
   722  			metadata: "",
   723  			expErr:   false,
   724  		},
   725  		"all good with split votes": {
   726  			preRun: func() uint64 {
   727  				msg, err := v1.NewMsgSubmitProposal(
   728  					[]sdk.Msg{bankMsg},
   729  					minDeposit,
   730  					proposer.String(),
   731  					"",
   732  					"Proposal",
   733  					"description of proposal",
   734  					false,
   735  				)
   736  				suite.Require().NoError(err)
   737  
   738  				res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
   739  				suite.Require().NoError(err)
   740  				suite.Require().NotNil(res.ProposalId)
   741  				return res.ProposalId
   742  			},
   743  			option: v1.WeightedVoteOptions{
   744  				v1.NewWeightedVoteOption(v1.OptionYes, sdkmath.LegacyNewDecWithPrec(5, 1)),
   745  				v1.NewWeightedVoteOption(v1.OptionAbstain, sdkmath.LegacyNewDecWithPrec(5, 1)),
   746  			},
   747  			voter:    proposer,
   748  			metadata: "",
   749  			expErr:   false,
   750  		},
   751  	}
   752  
   753  	for name, tc := range cases {
   754  		suite.Run(name, func() {
   755  			pID := tc.preRun()
   756  			voteReq := v1.NewMsgVoteWeighted(tc.voter, pID, tc.option, tc.metadata)
   757  			_, err := suite.msgSrvr.VoteWeighted(suite.ctx, voteReq)
   758  			if tc.expErr {
   759  				suite.Require().Error(err)
   760  				suite.Require().Contains(err.Error(), tc.expErrMsg)
   761  			} else {
   762  				suite.Require().NoError(err)
   763  			}
   764  		})
   765  	}
   766  }
   767  
   768  func (suite *KeeperTestSuite) TestDepositReq() {
   769  	govAcct := suite.govKeeper.GetGovernanceAccount(suite.ctx).GetAddress()
   770  	addrs := suite.addrs
   771  	proposer := addrs[0]
   772  
   773  	coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000)))
   774  	params, _ := suite.govKeeper.Params.Get(suite.ctx)
   775  	minDeposit := sdk.Coins(params.MinDeposit)
   776  	bankMsg := &banktypes.MsgSend{
   777  		FromAddress: govAcct.String(),
   778  		ToAddress:   proposer.String(),
   779  		Amount:      coins,
   780  	}
   781  
   782  	msg, err := v1.NewMsgSubmitProposal(
   783  		[]sdk.Msg{bankMsg},
   784  		coins,
   785  		proposer.String(),
   786  		"",
   787  		"Proposal",
   788  		"description of proposal",
   789  		false,
   790  	)
   791  	suite.Require().NoError(err)
   792  
   793  	res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
   794  	suite.Require().NoError(err)
   795  	suite.Require().NotNil(res.ProposalId)
   796  	pID := res.ProposalId
   797  
   798  	cases := map[string]struct {
   799  		preRun     func() uint64
   800  		expErr     bool
   801  		proposalID uint64
   802  		depositor  sdk.AccAddress
   803  		deposit    sdk.Coins
   804  		expErrMsg  string
   805  	}{
   806  		"wrong proposal id": {
   807  			preRun: func() uint64 {
   808  				return 0
   809  			},
   810  			depositor: proposer,
   811  			deposit:   coins,
   812  			expErr:    true,
   813  			expErrMsg: "not found",
   814  		},
   815  		"empty depositor": {
   816  			preRun: func() uint64 {
   817  				return pID
   818  			},
   819  			depositor: sdk.AccAddress{},
   820  			deposit:   minDeposit,
   821  			expErr:    true,
   822  			expErrMsg: "invalid depositor address",
   823  		},
   824  		"invalid deposited coin ": {
   825  			preRun: func() uint64 {
   826  				return pID
   827  			},
   828  			depositor: proposer,
   829  			deposit:   []sdk.Coin{sdk.NewCoin("ibc/badcoin", sdkmath.NewInt(1000))},
   830  			expErr:    true,
   831  			expErrMsg: "deposited 1000ibc/badcoin, but gov accepts only the following denom(s): [stake]",
   832  		},
   833  		"invalid deposited coin (multiple)": {
   834  			preRun: func() uint64 {
   835  				return pID
   836  			},
   837  			depositor: proposer,
   838  			deposit:   minDeposit.Add(sdk.NewCoin("ibc/badcoin", sdkmath.NewInt(1000))),
   839  			expErr:    true,
   840  			expErrMsg: "deposited 1000ibc/badcoin,10000000stake, but gov accepts only the following denom(s): [stake]: invalid deposit denom",
   841  		},
   842  		"all good": {
   843  			preRun: func() uint64 {
   844  				return pID
   845  			},
   846  			depositor: proposer,
   847  			deposit:   minDeposit,
   848  			expErr:    false,
   849  		},
   850  	}
   851  
   852  	for name, tc := range cases {
   853  		suite.Run(name, func() {
   854  			proposalID := tc.preRun()
   855  			depositReq := v1.NewMsgDeposit(tc.depositor, proposalID, tc.deposit)
   856  			_, err := suite.msgSrvr.Deposit(suite.ctx, depositReq)
   857  			if tc.expErr {
   858  				suite.Require().Error(err)
   859  				suite.Require().Contains(err.Error(), tc.expErrMsg)
   860  			} else {
   861  				suite.Require().NoError(err)
   862  			}
   863  		})
   864  	}
   865  }
   866  
   867  // legacy msg server tests
   868  func (suite *KeeperTestSuite) TestLegacyMsgSubmitProposal() {
   869  	proposer := simtestutil.AddTestAddrsIncremental(suite.bankKeeper, suite.stakingKeeper, suite.ctx, 1, sdkmath.NewInt(50000000))[0]
   870  	coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000)))
   871  	initialDeposit := coins
   872  	params, _ := suite.govKeeper.Params.Get(suite.ctx)
   873  	minDeposit := params.MinDeposit
   874  
   875  	cases := map[string]struct {
   876  		preRun    func() (*v1beta1.MsgSubmitProposal, error)
   877  		expErr    bool
   878  		expErrMsg string
   879  	}{
   880  		"empty title": {
   881  			preRun: func() (*v1beta1.MsgSubmitProposal, error) {
   882  				content := v1beta1.NewTextProposal("", "I am test")
   883  				return v1beta1.NewMsgSubmitProposal(
   884  					content,
   885  					initialDeposit,
   886  					proposer,
   887  				)
   888  			},
   889  			expErr:    true,
   890  			expErrMsg: "proposal title cannot be blank",
   891  		},
   892  		"empty description": {
   893  			preRun: func() (*v1beta1.MsgSubmitProposal, error) {
   894  				content := v1beta1.NewTextProposal("test", "")
   895  				return v1beta1.NewMsgSubmitProposal(
   896  					content,
   897  					initialDeposit,
   898  					proposer,
   899  				)
   900  			},
   901  			expErr:    true,
   902  			expErrMsg: "proposal description cannot be blank",
   903  		},
   904  		"empty proposer": {
   905  			preRun: func() (*v1beta1.MsgSubmitProposal, error) {
   906  				content := v1beta1.NewTextProposal("test", "I am test")
   907  				return v1beta1.NewMsgSubmitProposal(
   908  					content,
   909  					initialDeposit,
   910  					sdk.AccAddress{},
   911  				)
   912  			},
   913  			expErr:    true,
   914  			expErrMsg: "invalid proposer address: empty address string is not allowed",
   915  		},
   916  		"title text length > max limit allowed": {
   917  			preRun: func() (*v1beta1.MsgSubmitProposal, error) {
   918  				content := v1beta1.NewTextProposal(strings.Repeat("#", v1beta1.MaxTitleLength*2), "I am test")
   919  				return v1beta1.NewMsgSubmitProposal(
   920  					content,
   921  					initialDeposit,
   922  					proposer,
   923  				)
   924  			},
   925  			expErr:    true,
   926  			expErrMsg: "proposal title is longer than max length of 140: invalid proposal content",
   927  		},
   928  		"description text length > max limit allowed": {
   929  			preRun: func() (*v1beta1.MsgSubmitProposal, error) {
   930  				content := v1beta1.NewTextProposal("test", strings.Repeat("#", v1beta1.MaxDescriptionLength*2))
   931  				return v1beta1.NewMsgSubmitProposal(
   932  					content,
   933  					initialDeposit,
   934  					proposer,
   935  				)
   936  			},
   937  			expErr:    true,
   938  			expErrMsg: "proposal description is longer than max length of 10000: invalid proposal content",
   939  		},
   940  		"all good": {
   941  			preRun: func() (*v1beta1.MsgSubmitProposal, error) {
   942  				return v1beta1.NewMsgSubmitProposal(
   943  					v1beta1.NewTextProposal("test", "I am test"),
   944  					initialDeposit,
   945  					proposer,
   946  				)
   947  			},
   948  			expErr: false,
   949  		},
   950  		"all good with min deposit": {
   951  			preRun: func() (*v1beta1.MsgSubmitProposal, error) {
   952  				return v1beta1.NewMsgSubmitProposal(
   953  					v1beta1.NewTextProposal("test", "I am test"),
   954  					minDeposit,
   955  					proposer,
   956  				)
   957  			},
   958  			expErr: false,
   959  		},
   960  	}
   961  
   962  	for name, c := range cases {
   963  		suite.Run(name, func() {
   964  			msg, err := c.preRun()
   965  			suite.Require().NoError(err)
   966  			res, err := suite.legacyMsgSrvr.SubmitProposal(suite.ctx, msg)
   967  			if c.expErr {
   968  				suite.Require().Error(err)
   969  				suite.Require().Contains(err.Error(), c.expErrMsg)
   970  			} else {
   971  				suite.Require().NoError(err)
   972  				suite.Require().NotNil(res.ProposalId)
   973  			}
   974  		})
   975  	}
   976  }
   977  
   978  func (suite *KeeperTestSuite) TestLegacyMsgVote() {
   979  	govAcct := suite.govKeeper.GetGovernanceAccount(suite.ctx).GetAddress()
   980  	addrs := suite.addrs
   981  	proposer := addrs[0]
   982  
   983  	coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000)))
   984  	params, _ := suite.govKeeper.Params.Get(suite.ctx)
   985  	minDeposit := params.MinDeposit
   986  	bankMsg := &banktypes.MsgSend{
   987  		FromAddress: govAcct.String(),
   988  		ToAddress:   proposer.String(),
   989  		Amount:      coins,
   990  	}
   991  
   992  	msg, err := v1.NewMsgSubmitProposal(
   993  		[]sdk.Msg{bankMsg},
   994  		minDeposit,
   995  		proposer.String(),
   996  		"",
   997  		"Proposal",
   998  		"description of proposal",
   999  		false,
  1000  	)
  1001  	suite.Require().NoError(err)
  1002  
  1003  	res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
  1004  	suite.Require().NoError(err)
  1005  	suite.Require().NotNil(res.ProposalId)
  1006  	proposalID := res.ProposalId
  1007  
  1008  	cases := map[string]struct {
  1009  		preRun    func() uint64
  1010  		expErr    bool
  1011  		expErrMsg string
  1012  		option    v1beta1.VoteOption
  1013  		metadata  string
  1014  		voter     sdk.AccAddress
  1015  	}{
  1016  		"empty voter": {
  1017  			preRun: func() uint64 {
  1018  				return proposalID
  1019  			},
  1020  			option:    v1beta1.OptionYes,
  1021  			voter:     sdk.AccAddress{},
  1022  			metadata:  "",
  1023  			expErr:    true,
  1024  			expErrMsg: "invalid voter address",
  1025  		},
  1026  		"wrong vote option": {
  1027  			preRun: func() uint64 {
  1028  				return proposalID
  1029  			},
  1030  			option:    v1beta1.VoteOption(0x13),
  1031  			voter:     proposer,
  1032  			metadata:  "",
  1033  			expErr:    true,
  1034  			expErrMsg: "invalid vote option",
  1035  		},
  1036  		"vote on inactive proposal": {
  1037  			preRun: func() uint64 {
  1038  				msg, err := v1.NewMsgSubmitProposal(
  1039  					[]sdk.Msg{bankMsg},
  1040  					coins,
  1041  					proposer.String(),
  1042  					"",
  1043  					"Proposal",
  1044  					"description of proposal",
  1045  					false,
  1046  				)
  1047  				suite.Require().NoError(err)
  1048  
  1049  				res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
  1050  				suite.Require().NoError(err)
  1051  				suite.Require().NotNil(res.ProposalId)
  1052  				return res.ProposalId
  1053  			},
  1054  			option:    v1beta1.OptionYes,
  1055  			voter:     proposer,
  1056  			metadata:  "",
  1057  			expErr:    true,
  1058  			expErrMsg: "inactive proposal",
  1059  		},
  1060  		"voter error": {
  1061  			preRun: func() uint64 {
  1062  				return proposalID
  1063  			},
  1064  			option:    v1beta1.OptionYes,
  1065  			voter:     sdk.AccAddress(strings.Repeat("a", 300)),
  1066  			metadata:  "",
  1067  			expErr:    true,
  1068  			expErrMsg: longAddressError,
  1069  		},
  1070  		"all good": {
  1071  			preRun: func() uint64 {
  1072  				msg, err := v1.NewMsgSubmitProposal(
  1073  					[]sdk.Msg{bankMsg},
  1074  					minDeposit,
  1075  					proposer.String(),
  1076  					"",
  1077  					"Proposal",
  1078  					"description of proposal",
  1079  					false,
  1080  				)
  1081  				suite.Require().NoError(err)
  1082  
  1083  				res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
  1084  				suite.Require().NoError(err)
  1085  				suite.Require().NotNil(res.ProposalId)
  1086  				return res.ProposalId
  1087  			},
  1088  			option:   v1beta1.OptionYes,
  1089  			voter:    proposer,
  1090  			metadata: "",
  1091  			expErr:   false,
  1092  		},
  1093  	}
  1094  
  1095  	for name, tc := range cases {
  1096  		suite.Run(name, func() {
  1097  			pID := tc.preRun()
  1098  			voteReq := v1beta1.NewMsgVote(tc.voter, pID, tc.option)
  1099  			_, err := suite.legacyMsgSrvr.Vote(suite.ctx, voteReq)
  1100  			if tc.expErr {
  1101  				suite.Require().Error(err)
  1102  				suite.Require().Contains(err.Error(), tc.expErrMsg)
  1103  			} else {
  1104  				suite.Require().NoError(err)
  1105  			}
  1106  		})
  1107  	}
  1108  }
  1109  
  1110  func (suite *KeeperTestSuite) TestLegacyVoteWeighted() {
  1111  	suite.reset()
  1112  	govAcct := suite.govKeeper.GetGovernanceAccount(suite.ctx).GetAddress()
  1113  	addrs := suite.addrs
  1114  	proposer := addrs[0]
  1115  
  1116  	coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000)))
  1117  	params, _ := suite.govKeeper.Params.Get(suite.ctx)
  1118  	minDeposit := params.MinDeposit
  1119  	bankMsg := &banktypes.MsgSend{
  1120  		FromAddress: govAcct.String(),
  1121  		ToAddress:   proposer.String(),
  1122  		Amount:      coins,
  1123  	}
  1124  
  1125  	msg, err := v1.NewMsgSubmitProposal(
  1126  		[]sdk.Msg{bankMsg},
  1127  		minDeposit,
  1128  		proposer.String(),
  1129  		"",
  1130  		"Proposal",
  1131  		"description of proposal",
  1132  		false,
  1133  	)
  1134  	suite.Require().NoError(err)
  1135  
  1136  	res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
  1137  	suite.Require().NoError(err)
  1138  	suite.Require().NotNil(res.ProposalId)
  1139  	proposalID := res.ProposalId
  1140  
  1141  	cases := map[string]struct {
  1142  		preRun    func() uint64
  1143  		vote      *v1beta1.MsgVote
  1144  		expErr    bool
  1145  		expErrMsg string
  1146  		option    v1beta1.WeightedVoteOptions
  1147  		metadata  string
  1148  		voter     sdk.AccAddress
  1149  	}{
  1150  		"empty voter": {
  1151  			preRun: func() uint64 {
  1152  				return proposalID
  1153  			},
  1154  			option: v1beta1.WeightedVoteOptions{
  1155  				v1beta1.WeightedVoteOption{
  1156  					Option: v1beta1.OptionYes,
  1157  					Weight: sdkmath.LegacyNewDec(1),
  1158  				},
  1159  			},
  1160  			voter:     sdk.AccAddress{},
  1161  			metadata:  "",
  1162  			expErr:    true,
  1163  			expErrMsg: "invalid voter address",
  1164  		},
  1165  		"weights sum > 1": {
  1166  			preRun: func() uint64 {
  1167  				return proposalID
  1168  			},
  1169  			option: v1beta1.WeightedVoteOptions{
  1170  				v1beta1.WeightedVoteOption{
  1171  					Option: v1beta1.OptionYes,
  1172  					Weight: sdkmath.LegacyNewDec(1),
  1173  				},
  1174  				v1beta1.WeightedVoteOption{
  1175  					Option: v1beta1.OptionAbstain,
  1176  					Weight: sdkmath.LegacyNewDec(1),
  1177  				},
  1178  			},
  1179  			voter:     proposer,
  1180  			metadata:  "",
  1181  			expErr:    true,
  1182  			expErrMsg: "total weight overflow 1.00: invalid vote option",
  1183  		},
  1184  		"duplicate vote options": {
  1185  			preRun: func() uint64 {
  1186  				return proposalID
  1187  			},
  1188  			option: v1beta1.WeightedVoteOptions{
  1189  				v1beta1.WeightedVoteOption{
  1190  					Option: v1beta1.OptionYes,
  1191  					Weight: sdkmath.LegacyNewDecWithPrec(5, 1),
  1192  				},
  1193  				v1beta1.WeightedVoteOption{
  1194  					Option: v1beta1.OptionYes,
  1195  					Weight: sdkmath.LegacyNewDecWithPrec(5, 1),
  1196  				},
  1197  			},
  1198  			voter:     proposer,
  1199  			metadata:  "",
  1200  			expErr:    true,
  1201  			expErrMsg: "duplicated vote option",
  1202  		},
  1203  		"zero weight": {
  1204  			preRun: func() uint64 {
  1205  				return proposalID
  1206  			},
  1207  			option: v1beta1.WeightedVoteOptions{
  1208  				v1beta1.WeightedVoteOption{
  1209  					Option: v1beta1.OptionYes,
  1210  					Weight: sdkmath.LegacyNewDec(0),
  1211  				},
  1212  			},
  1213  			voter:     proposer,
  1214  			metadata:  "",
  1215  			expErr:    true,
  1216  			expErrMsg: `option:VOTE_OPTION_YES weight:"0.000000000000000000" : invalid vote option`,
  1217  		},
  1218  		"negative weight": {
  1219  			preRun: func() uint64 {
  1220  				return proposalID
  1221  			},
  1222  			option: v1beta1.WeightedVoteOptions{
  1223  				v1beta1.WeightedVoteOption{
  1224  					Option: v1beta1.OptionYes,
  1225  					Weight: sdkmath.LegacyNewDec(-1),
  1226  				},
  1227  			},
  1228  			voter:     proposer,
  1229  			metadata:  "",
  1230  			expErr:    true,
  1231  			expErrMsg: `option:VOTE_OPTION_YES weight:"-1.000000000000000000" : invalid vote option`,
  1232  		},
  1233  		"empty options": {
  1234  			preRun: func() uint64 {
  1235  				return proposalID
  1236  			},
  1237  			option:    v1beta1.WeightedVoteOptions{},
  1238  			voter:     proposer,
  1239  			metadata:  "",
  1240  			expErr:    true,
  1241  			expErrMsg: "invalid request",
  1242  		},
  1243  		"invalid vote option": {
  1244  			preRun: func() uint64 {
  1245  				return proposalID
  1246  			},
  1247  			option: v1beta1.WeightedVoteOptions{
  1248  				v1beta1.WeightedVoteOption{
  1249  					Option: v1beta1.VoteOption(0x13),
  1250  					Weight: sdkmath.LegacyNewDecWithPrec(5, 1),
  1251  				},
  1252  			},
  1253  			voter:     proposer,
  1254  			metadata:  "",
  1255  			expErr:    true,
  1256  			expErrMsg: "invalid vote option",
  1257  		},
  1258  		"weight sum < 1": {
  1259  			preRun: func() uint64 {
  1260  				return proposalID
  1261  			},
  1262  			option: v1beta1.WeightedVoteOptions{
  1263  				v1beta1.WeightedVoteOption{
  1264  					Option: v1beta1.OptionYes,
  1265  					Weight: sdkmath.LegacyNewDecWithPrec(5, 1),
  1266  				},
  1267  			},
  1268  			voter:     proposer,
  1269  			metadata:  "",
  1270  			expErr:    true,
  1271  			expErrMsg: "total weight lower than 1.00: invalid vote option",
  1272  		},
  1273  		"vote on inactive proposal": {
  1274  			preRun: func() uint64 {
  1275  				msg, err := v1.NewMsgSubmitProposal(
  1276  					[]sdk.Msg{bankMsg},
  1277  					coins,
  1278  					proposer.String(),
  1279  					"",
  1280  					"Proposal",
  1281  					"description of proposal",
  1282  					false,
  1283  				)
  1284  				suite.Require().NoError(err)
  1285  
  1286  				res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
  1287  				suite.Require().NoError(err)
  1288  				suite.Require().NotNil(res.ProposalId)
  1289  				return res.ProposalId
  1290  			},
  1291  			option: v1beta1.WeightedVoteOptions{
  1292  				v1beta1.WeightedVoteOption{
  1293  					Option: v1beta1.OptionYes,
  1294  					Weight: sdkmath.LegacyNewDec(1),
  1295  				},
  1296  			},
  1297  			voter:     proposer,
  1298  			metadata:  "",
  1299  			expErr:    true,
  1300  			expErrMsg: "inactive proposal",
  1301  		},
  1302  		"voter error": {
  1303  			preRun: func() uint64 {
  1304  				return proposalID
  1305  			},
  1306  			option: v1beta1.WeightedVoteOptions{
  1307  				v1beta1.WeightedVoteOption{
  1308  					Option: v1beta1.OptionYes,
  1309  					Weight: sdkmath.LegacyNewDec(1),
  1310  				},
  1311  			},
  1312  			voter:     sdk.AccAddress(strings.Repeat("a", 300)),
  1313  			metadata:  "",
  1314  			expErr:    true,
  1315  			expErrMsg: longAddressError,
  1316  		},
  1317  		"all good": {
  1318  			preRun: func() uint64 {
  1319  				msg, err := v1.NewMsgSubmitProposal(
  1320  					[]sdk.Msg{bankMsg},
  1321  					minDeposit,
  1322  					proposer.String(),
  1323  					"",
  1324  					"Proposal",
  1325  					"description of proposal",
  1326  					false,
  1327  				)
  1328  				suite.Require().NoError(err)
  1329  
  1330  				res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
  1331  				suite.Require().NoError(err)
  1332  				suite.Require().NotNil(res.ProposalId)
  1333  				return res.ProposalId
  1334  			},
  1335  			option: v1beta1.WeightedVoteOptions{
  1336  				v1beta1.WeightedVoteOption{
  1337  					Option: v1beta1.OptionYes,
  1338  					Weight: sdkmath.LegacyNewDec(1),
  1339  				},
  1340  			},
  1341  			voter:    proposer,
  1342  			metadata: "",
  1343  			expErr:   false,
  1344  		},
  1345  	}
  1346  
  1347  	for name, tc := range cases {
  1348  		suite.Run(name, func() {
  1349  			pID := tc.preRun()
  1350  			voteReq := v1beta1.NewMsgVoteWeighted(tc.voter, pID, tc.option)
  1351  			_, err := suite.legacyMsgSrvr.VoteWeighted(suite.ctx, voteReq)
  1352  			if tc.expErr {
  1353  				suite.Require().Error(err)
  1354  				suite.Require().Contains(err.Error(), tc.expErrMsg)
  1355  			} else {
  1356  				suite.Require().NoError(err)
  1357  			}
  1358  		})
  1359  	}
  1360  }
  1361  
  1362  func (suite *KeeperTestSuite) TestLegacyMsgDeposit() {
  1363  	govAcct := suite.govKeeper.GetGovernanceAccount(suite.ctx).GetAddress()
  1364  	addrs := suite.addrs
  1365  	proposer := addrs[0]
  1366  
  1367  	coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(100000)))
  1368  	params, _ := suite.govKeeper.Params.Get(suite.ctx)
  1369  	minDeposit := params.MinDeposit
  1370  	bankMsg := &banktypes.MsgSend{
  1371  		FromAddress: govAcct.String(),
  1372  		ToAddress:   proposer.String(),
  1373  		Amount:      coins,
  1374  	}
  1375  
  1376  	msg, err := v1.NewMsgSubmitProposal(
  1377  		[]sdk.Msg{bankMsg},
  1378  		coins,
  1379  		proposer.String(),
  1380  		"",
  1381  		"Proposal",
  1382  		"description of proposal",
  1383  		false,
  1384  	)
  1385  	suite.Require().NoError(err)
  1386  
  1387  	res, err := suite.msgSrvr.SubmitProposal(suite.ctx, msg)
  1388  	suite.Require().NoError(err)
  1389  	suite.Require().NotNil(res.ProposalId)
  1390  	pID := res.ProposalId
  1391  
  1392  	cases := map[string]struct {
  1393  		preRun     func() uint64
  1394  		expErr     bool
  1395  		expErrMsg  string
  1396  		proposalID uint64
  1397  		depositor  sdk.AccAddress
  1398  		deposit    sdk.Coins
  1399  	}{
  1400  		"wrong proposal id": {
  1401  			preRun: func() uint64 {
  1402  				return 0
  1403  			},
  1404  			depositor: proposer,
  1405  			deposit:   coins,
  1406  			expErr:    true,
  1407  			expErrMsg: "not found",
  1408  		},
  1409  		"empty depositer": {
  1410  			preRun: func() uint64 {
  1411  				return pID
  1412  			},
  1413  			depositor: sdk.AccAddress{},
  1414  			deposit:   coins,
  1415  			expErr:    true,
  1416  			expErrMsg: "invalid depositor address: empty address string is not allowed",
  1417  		},
  1418  		"all good": {
  1419  			preRun: func() uint64 {
  1420  				return pID
  1421  			},
  1422  			depositor: proposer,
  1423  			deposit:   minDeposit,
  1424  			expErr:    false,
  1425  		},
  1426  	}
  1427  
  1428  	for name, tc := range cases {
  1429  		suite.Run(name, func() {
  1430  			proposalID := tc.preRun()
  1431  			depositReq := v1beta1.NewMsgDeposit(tc.depositor, proposalID, tc.deposit)
  1432  			_, err := suite.legacyMsgSrvr.Deposit(suite.ctx, depositReq)
  1433  			if tc.expErr {
  1434  				suite.Require().Error(err)
  1435  				suite.Require().Contains(err.Error(), tc.expErrMsg)
  1436  			} else {
  1437  				suite.Require().NoError(err)
  1438  			}
  1439  		})
  1440  	}
  1441  }
  1442  
  1443  func (suite *KeeperTestSuite) TestMsgUpdateParams() {
  1444  	authority := suite.govKeeper.GetAuthority()
  1445  	params := v1.DefaultParams()
  1446  	testCases := []struct {
  1447  		name      string
  1448  		input     func() *v1.MsgUpdateParams
  1449  		expErr    bool
  1450  		expErrMsg string
  1451  	}{
  1452  		{
  1453  			name: "valid",
  1454  			input: func() *v1.MsgUpdateParams {
  1455  				return &v1.MsgUpdateParams{
  1456  					Authority: authority,
  1457  					Params:    params,
  1458  				}
  1459  			},
  1460  			expErr: false,
  1461  		},
  1462  		{
  1463  			name: "invalid authority",
  1464  			input: func() *v1.MsgUpdateParams {
  1465  				return &v1.MsgUpdateParams{
  1466  					Authority: "authority",
  1467  					Params:    params,
  1468  				}
  1469  			},
  1470  			expErr:    true,
  1471  			expErrMsg: "invalid authority",
  1472  		},
  1473  		{
  1474  			name: "invalid min deposit",
  1475  			input: func() *v1.MsgUpdateParams {
  1476  				params1 := params
  1477  				params1.MinDeposit = nil
  1478  
  1479  				return &v1.MsgUpdateParams{
  1480  					Authority: authority,
  1481  					Params:    params1,
  1482  				}
  1483  			},
  1484  			expErr:    true,
  1485  			expErrMsg: "invalid minimum deposit",
  1486  		},
  1487  		{
  1488  			name: "negative deposit",
  1489  			input: func() *v1.MsgUpdateParams {
  1490  				params1 := params
  1491  				params1.MinDeposit = sdk.Coins{{
  1492  					Denom:  sdk.DefaultBondDenom,
  1493  					Amount: sdkmath.NewInt(-100),
  1494  				}}
  1495  
  1496  				return &v1.MsgUpdateParams{
  1497  					Authority: authority,
  1498  					Params:    params1,
  1499  				}
  1500  			},
  1501  			expErr:    true,
  1502  			expErrMsg: "invalid minimum deposit",
  1503  		},
  1504  		{
  1505  			name: "invalid max deposit period",
  1506  			input: func() *v1.MsgUpdateParams {
  1507  				params1 := params
  1508  				params1.MaxDepositPeriod = nil
  1509  
  1510  				return &v1.MsgUpdateParams{
  1511  					Authority: authority,
  1512  					Params:    params1,
  1513  				}
  1514  			},
  1515  			expErr:    true,
  1516  			expErrMsg: "maximum deposit period must not be nil",
  1517  		},
  1518  		{
  1519  			name: "zero max deposit period",
  1520  			input: func() *v1.MsgUpdateParams {
  1521  				params1 := params
  1522  				duration := time.Duration(0)
  1523  				params1.MaxDepositPeriod = &duration
  1524  
  1525  				return &v1.MsgUpdateParams{
  1526  					Authority: authority,
  1527  					Params:    params1,
  1528  				}
  1529  			},
  1530  			expErr:    true,
  1531  			expErrMsg: "maximum deposit period must be positive",
  1532  		},
  1533  		{
  1534  			name: "invalid quorum",
  1535  			input: func() *v1.MsgUpdateParams {
  1536  				params1 := params
  1537  				params1.Quorum = abc
  1538  
  1539  				return &v1.MsgUpdateParams{
  1540  					Authority: authority,
  1541  					Params:    params1,
  1542  				}
  1543  			},
  1544  			expErr:    true,
  1545  			expErrMsg: "invalid quorum string",
  1546  		},
  1547  		{
  1548  			name: "negative quorum",
  1549  			input: func() *v1.MsgUpdateParams {
  1550  				params1 := params
  1551  				params1.Quorum = o1
  1552  
  1553  				return &v1.MsgUpdateParams{
  1554  					Authority: authority,
  1555  					Params:    params1,
  1556  				}
  1557  			},
  1558  			expErr:    true,
  1559  			expErrMsg: "quorom cannot be negative",
  1560  		},
  1561  		{
  1562  			name: "quorum > 1",
  1563  			input: func() *v1.MsgUpdateParams {
  1564  				params1 := params
  1565  				params1.Quorum = "2"
  1566  
  1567  				return &v1.MsgUpdateParams{
  1568  					Authority: authority,
  1569  					Params:    params1,
  1570  				}
  1571  			},
  1572  			expErr:    true,
  1573  			expErrMsg: "quorom too large",
  1574  		},
  1575  		{
  1576  			name: "invalid threshold",
  1577  			input: func() *v1.MsgUpdateParams {
  1578  				params1 := params
  1579  				params1.Threshold = abc
  1580  
  1581  				return &v1.MsgUpdateParams{
  1582  					Authority: authority,
  1583  					Params:    params1,
  1584  				}
  1585  			},
  1586  			expErr:    true,
  1587  			expErrMsg: "invalid threshold string",
  1588  		},
  1589  		{
  1590  			name: "negative threshold",
  1591  			input: func() *v1.MsgUpdateParams {
  1592  				params1 := params
  1593  				params1.Threshold = o1
  1594  
  1595  				return &v1.MsgUpdateParams{
  1596  					Authority: authority,
  1597  					Params:    params1,
  1598  				}
  1599  			},
  1600  			expErr:    true,
  1601  			expErrMsg: "vote threshold must be positive",
  1602  		},
  1603  		{
  1604  			name: "threshold > 1",
  1605  			input: func() *v1.MsgUpdateParams {
  1606  				params1 := params
  1607  				params1.Threshold = "2"
  1608  
  1609  				return &v1.MsgUpdateParams{
  1610  					Authority: authority,
  1611  					Params:    params1,
  1612  				}
  1613  			},
  1614  			expErr:    true,
  1615  			expErrMsg: "vote threshold too large",
  1616  		},
  1617  		{
  1618  			name: "invalid veto threshold",
  1619  			input: func() *v1.MsgUpdateParams {
  1620  				params1 := params
  1621  				params1.VetoThreshold = abc
  1622  
  1623  				return &v1.MsgUpdateParams{
  1624  					Authority: authority,
  1625  					Params:    params1,
  1626  				}
  1627  			},
  1628  			expErr:    true,
  1629  			expErrMsg: "invalid vetoThreshold string",
  1630  		},
  1631  		{
  1632  			name: "negative veto threshold",
  1633  			input: func() *v1.MsgUpdateParams {
  1634  				params1 := params
  1635  				params1.VetoThreshold = o1
  1636  
  1637  				return &v1.MsgUpdateParams{
  1638  					Authority: authority,
  1639  					Params:    params1,
  1640  				}
  1641  			},
  1642  			expErr:    true,
  1643  			expErrMsg: "veto threshold must be positive",
  1644  		},
  1645  		{
  1646  			name: "veto threshold > 1",
  1647  			input: func() *v1.MsgUpdateParams {
  1648  				params1 := params
  1649  				params1.VetoThreshold = "2"
  1650  
  1651  				return &v1.MsgUpdateParams{
  1652  					Authority: authority,
  1653  					Params:    params1,
  1654  				}
  1655  			},
  1656  			expErr:    true,
  1657  			expErrMsg: "veto threshold too large",
  1658  		},
  1659  		{
  1660  			name: "invalid voting period",
  1661  			input: func() *v1.MsgUpdateParams {
  1662  				params1 := params
  1663  				params1.VotingPeriod = nil
  1664  
  1665  				return &v1.MsgUpdateParams{
  1666  					Authority: authority,
  1667  					Params:    params1,
  1668  				}
  1669  			},
  1670  			expErr:    true,
  1671  			expErrMsg: "voting period must not be nil",
  1672  		},
  1673  		{
  1674  			name: "zero voting period",
  1675  			input: func() *v1.MsgUpdateParams {
  1676  				params1 := params
  1677  				duration := time.Duration(0)
  1678  				params1.VotingPeriod = &duration
  1679  
  1680  				return &v1.MsgUpdateParams{
  1681  					Authority: authority,
  1682  					Params:    params1,
  1683  				}
  1684  			},
  1685  			expErr:    true,
  1686  			expErrMsg: "voting period must be positive",
  1687  		},
  1688  	}
  1689  
  1690  	for _, tc := range testCases {
  1691  		tc := tc
  1692  		suite.Run(tc.name, func() {
  1693  			msg := tc.input()
  1694  			exec := func(updateParams *v1.MsgUpdateParams) error {
  1695  				if _, err := suite.msgSrvr.UpdateParams(suite.ctx, updateParams); err != nil {
  1696  					return err
  1697  				}
  1698  				return nil
  1699  			}
  1700  
  1701  			err := exec(msg)
  1702  			if tc.expErr {
  1703  				suite.Require().Error(err)
  1704  				suite.Require().Contains(err.Error(), tc.expErrMsg)
  1705  			} else {
  1706  				suite.Require().NoError(err)
  1707  			}
  1708  		})
  1709  	}
  1710  }
  1711  
  1712  func (suite *KeeperTestSuite) TestSubmitProposal_InitialDeposit() {
  1713  	const meetsDepositValue = baseDepositTestAmount * baseDepositTestPercent / 100
  1714  	baseDepositRatioDec := sdkmath.LegacyNewDec(baseDepositTestPercent).Quo(sdkmath.LegacyNewDec(100))
  1715  
  1716  	testcases := map[string]struct {
  1717  		minDeposit             sdk.Coins
  1718  		minInitialDepositRatio sdkmath.LegacyDec
  1719  		initialDeposit         sdk.Coins
  1720  		accountBalance         sdk.Coins
  1721  
  1722  		expectError bool
  1723  	}{
  1724  		"meets initial deposit, enough balance - success": {
  1725  			minDeposit:             sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(baseDepositTestAmount))),
  1726  			minInitialDepositRatio: baseDepositRatioDec,
  1727  			initialDeposit:         sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(meetsDepositValue))),
  1728  			accountBalance:         sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(meetsDepositValue))),
  1729  		},
  1730  		"does not meet initial deposit, enough balance - error": {
  1731  			minDeposit:             sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(baseDepositTestAmount))),
  1732  			minInitialDepositRatio: baseDepositRatioDec,
  1733  			initialDeposit:         sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(meetsDepositValue-1))),
  1734  			accountBalance:         sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(meetsDepositValue))),
  1735  
  1736  			expectError: true,
  1737  		},
  1738  		"meets initial deposit, not enough balance - error": {
  1739  			minDeposit:             sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(baseDepositTestAmount))),
  1740  			minInitialDepositRatio: baseDepositRatioDec,
  1741  			initialDeposit:         sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(meetsDepositValue))),
  1742  			accountBalance:         sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(meetsDepositValue-1))),
  1743  
  1744  			expectError: true,
  1745  		},
  1746  		"does not meet initial deposit and not enough balance - error": {
  1747  			minDeposit:             sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(baseDepositTestAmount))),
  1748  			minInitialDepositRatio: baseDepositRatioDec,
  1749  			initialDeposit:         sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(meetsDepositValue-1))),
  1750  			accountBalance:         sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(meetsDepositValue-1))),
  1751  
  1752  			expectError: true,
  1753  		},
  1754  	}
  1755  
  1756  	for name, tc := range testcases {
  1757  		suite.Run(name, func() {
  1758  			// Setup
  1759  			govKeeper, ctx := suite.govKeeper, suite.ctx
  1760  			address := simtestutil.AddTestAddrs(suite.bankKeeper, suite.stakingKeeper, ctx, 1, tc.accountBalance[0].Amount)[0]
  1761  
  1762  			params := v1.DefaultParams()
  1763  			params.MinDeposit = tc.minDeposit
  1764  			params.MinInitialDepositRatio = tc.minInitialDepositRatio.String()
  1765  			govKeeper.Params.Set(ctx, params)
  1766  
  1767  			msg, err := v1.NewMsgSubmitProposal(TestProposal, tc.initialDeposit, address.String(), "test", "Proposal", "description of proposal", false)
  1768  			suite.Require().NoError(err)
  1769  
  1770  			// System under test
  1771  			_, err = suite.msgSrvr.SubmitProposal(ctx, msg)
  1772  
  1773  			// Assertions
  1774  			if tc.expectError {
  1775  				suite.Require().Error(err)
  1776  				return
  1777  			}
  1778  			suite.Require().NoError(err)
  1779  		})
  1780  	}
  1781  }