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 }