github.com/Finschia/finschia-sdk@v0.48.1/x/foundation/msgs_test.go (about)

     1  package foundation_test
     2  
     3  import (
     4  	"fmt"
     5  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/Finschia/finschia-sdk/crypto/keys/secp256k1"
    12  	"github.com/Finschia/finschia-sdk/testutil/testdata"
    13  	sdk "github.com/Finschia/finschia-sdk/types"
    14  	"github.com/Finschia/finschia-sdk/x/auth/legacy/legacytx"
    15  	"github.com/Finschia/finschia-sdk/x/foundation"
    16  )
    17  
    18  func TestMsgUpdateParams(t *testing.T) {
    19  	addrs := make([]sdk.AccAddress, 1)
    20  	for i := range addrs {
    21  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
    22  	}
    23  
    24  	testCases := map[string]struct {
    25  		authority sdk.AccAddress
    26  		params    foundation.Params
    27  		valid     bool
    28  	}{
    29  		"handler for MsgUpdateParams removed, ValidateBasic should throw error always": {
    30  			authority: addrs[0],
    31  			params: foundation.Params{
    32  				FoundationTax: sdk.ZeroDec(),
    33  			},
    34  			valid: false,
    35  		},
    36  	}
    37  
    38  	for name, tc := range testCases {
    39  		t.Run(name, func(t *testing.T) {
    40  			msg := foundation.MsgUpdateParams{
    41  				Authority: tc.authority.String(),
    42  				Params:    tc.params,
    43  			}
    44  
    45  			err := msg.ValidateBasic()
    46  			require.Error(t, err)
    47  			require.ErrorIs(t, err, sdkerrors.ErrUnknownRequest)
    48  		})
    49  		msg := foundation.MsgUpdateParams{
    50  			addrs[0].String(),
    51  			foundation.Params{},
    52  		}
    53  		// Note: Dummy test for coverage of deprecated message
    54  		_ = msg.GetSigners()
    55  		_ = msg.String()
    56  		_, _ = msg.Descriptor()
    57  		_ = msg.GetSignBytes()
    58  		_, _ = msg.Marshal()
    59  		msg.ProtoMessage()
    60  		msg.Reset()
    61  		_ = msg.Route()
    62  		_ = msg.Size()
    63  		_ = msg.Type()
    64  		_ = msg.XXX_Size()
    65  	}
    66  }
    67  
    68  func TestMsgFundTreasury(t *testing.T) {
    69  	addrs := make([]sdk.AccAddress, 1)
    70  	for i := range addrs {
    71  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
    72  	}
    73  
    74  	testCases := map[string]struct {
    75  		from   sdk.AccAddress
    76  		amount sdk.Int
    77  		valid  bool
    78  	}{
    79  		"valid msg": {
    80  			from:   addrs[0],
    81  			amount: sdk.OneInt(),
    82  			valid:  true,
    83  		},
    84  		"empty from": {
    85  			amount: sdk.OneInt(),
    86  		},
    87  		"zero amount": {
    88  			from:   addrs[0],
    89  			amount: sdk.ZeroInt(),
    90  		},
    91  	}
    92  
    93  	for name, tc := range testCases {
    94  		t.Run(name, func(t *testing.T) {
    95  			msg := foundation.MsgFundTreasury{
    96  				From:   tc.from.String(),
    97  				Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, tc.amount)),
    98  			}
    99  
   100  			err := msg.ValidateBasic()
   101  			if !tc.valid {
   102  				require.Error(t, err)
   103  				return
   104  			}
   105  			require.NoError(t, err)
   106  
   107  			require.Equal(t, []sdk.AccAddress{tc.from}, msg.GetSigners())
   108  		})
   109  	}
   110  }
   111  
   112  func TestMsgWithdrawFromTreasury(t *testing.T) {
   113  	addrs := make([]sdk.AccAddress, 2)
   114  	for i := range addrs {
   115  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   116  	}
   117  
   118  	testCases := map[string]struct {
   119  		authority sdk.AccAddress
   120  		to        sdk.AccAddress
   121  		amount    sdk.Int
   122  		valid     bool
   123  	}{
   124  		"valid msg": {
   125  			authority: addrs[0],
   126  			to:        addrs[1],
   127  			amount:    sdk.OneInt(),
   128  			valid:     true,
   129  		},
   130  		"empty authority": {
   131  			to:     addrs[1],
   132  			amount: sdk.OneInt(),
   133  		},
   134  		"empty to": {
   135  			authority: addrs[0],
   136  			amount:    sdk.OneInt(),
   137  		},
   138  		"zero amount": {
   139  			authority: addrs[0],
   140  			to:        addrs[1],
   141  			amount:    sdk.ZeroInt(),
   142  		},
   143  	}
   144  
   145  	for name, tc := range testCases {
   146  		t.Run(name, func(t *testing.T) {
   147  			msg := foundation.MsgWithdrawFromTreasury{
   148  				Authority: tc.authority.String(),
   149  				To:        tc.to.String(),
   150  				Amount:    sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, tc.amount)),
   151  			}
   152  
   153  			err := msg.ValidateBasic()
   154  			if !tc.valid {
   155  				require.Error(t, err)
   156  				return
   157  			}
   158  			require.NoError(t, err)
   159  
   160  			require.Equal(t, []sdk.AccAddress{tc.authority}, msg.GetSigners())
   161  		})
   162  	}
   163  }
   164  
   165  func TestMsgUpdateMembers(t *testing.T) {
   166  	addrs := make([]sdk.AccAddress, 2)
   167  	for i := range addrs {
   168  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   169  	}
   170  
   171  	testCases := map[string]struct {
   172  		authority sdk.AccAddress
   173  		members   []foundation.MemberRequest
   174  		valid     bool
   175  	}{
   176  		"valid msg": {
   177  			authority: addrs[0],
   178  			members: []foundation.MemberRequest{{
   179  				Address: addrs[1].String(),
   180  			}},
   181  			valid: true,
   182  		},
   183  		"empty authority": {
   184  			members: []foundation.MemberRequest{{
   185  				Address: addrs[1].String(),
   186  			}},
   187  		},
   188  		"empty requests": {
   189  			authority: addrs[0],
   190  		},
   191  		"invalid requests": {
   192  			authority: addrs[0],
   193  			members:   []foundation.MemberRequest{{}},
   194  		},
   195  	}
   196  
   197  	for name, tc := range testCases {
   198  		t.Run(name, func(t *testing.T) {
   199  			msg := foundation.MsgUpdateMembers{
   200  				Authority:     tc.authority.String(),
   201  				MemberUpdates: tc.members,
   202  			}
   203  
   204  			err := msg.ValidateBasic()
   205  			if !tc.valid {
   206  				require.Error(t, err)
   207  				return
   208  			}
   209  			require.NoError(t, err)
   210  
   211  			require.Equal(t, []sdk.AccAddress{tc.authority}, msg.GetSigners())
   212  		})
   213  	}
   214  }
   215  
   216  func TestMsgUpdateDecisionPolicy(t *testing.T) {
   217  	addrs := make([]sdk.AccAddress, 1)
   218  	for i := range addrs {
   219  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   220  	}
   221  
   222  	testCases := map[string]struct {
   223  		authority sdk.AccAddress
   224  		policy    foundation.DecisionPolicy
   225  		valid     bool
   226  	}{
   227  		"valid threshold policy": {
   228  			authority: addrs[0],
   229  			policy: &foundation.ThresholdDecisionPolicy{
   230  				Threshold: sdk.OneDec(),
   231  				Windows: &foundation.DecisionPolicyWindows{
   232  					VotingPeriod: time.Hour,
   233  				},
   234  			},
   235  			valid: true,
   236  		},
   237  		"valid percentage policy": {
   238  			authority: addrs[0],
   239  			policy: &foundation.PercentageDecisionPolicy{
   240  				Percentage: sdk.OneDec(),
   241  				Windows: &foundation.DecisionPolicyWindows{
   242  					VotingPeriod: time.Hour,
   243  				},
   244  			},
   245  			valid: true,
   246  		},
   247  		"empty authority": {
   248  			policy: &foundation.ThresholdDecisionPolicy{
   249  				Threshold: sdk.OneDec(),
   250  				Windows: &foundation.DecisionPolicyWindows{
   251  					VotingPeriod: time.Hour,
   252  				},
   253  			},
   254  		},
   255  		"empty policy": {
   256  			authority: addrs[0],
   257  		},
   258  		"zero threshold": {
   259  			authority: addrs[0],
   260  			policy: &foundation.ThresholdDecisionPolicy{
   261  				Threshold: sdk.ZeroDec(),
   262  				Windows: &foundation.DecisionPolicyWindows{
   263  					VotingPeriod: time.Hour,
   264  				},
   265  			},
   266  		},
   267  		"zero voting period": {
   268  			authority: addrs[0],
   269  			policy: &foundation.ThresholdDecisionPolicy{
   270  				Threshold: sdk.OneDec(),
   271  				Windows:   &foundation.DecisionPolicyWindows{},
   272  			},
   273  		},
   274  		"invalid percentage": {
   275  			authority: addrs[0],
   276  			policy: &foundation.PercentageDecisionPolicy{
   277  				Percentage: sdk.NewDec(2),
   278  				Windows: &foundation.DecisionPolicyWindows{
   279  					VotingPeriod: time.Hour,
   280  				},
   281  			},
   282  		},
   283  	}
   284  
   285  	for name, tc := range testCases {
   286  		t.Run(name, func(t *testing.T) {
   287  			msg := foundation.MsgUpdateDecisionPolicy{
   288  				Authority: tc.authority.String(),
   289  			}
   290  			if tc.policy != nil {
   291  				err := msg.SetDecisionPolicy(tc.policy)
   292  				require.NoError(t, err)
   293  			}
   294  
   295  			err := msg.ValidateBasic()
   296  			if !tc.valid {
   297  				require.Error(t, err)
   298  				return
   299  			}
   300  			require.NoError(t, err)
   301  
   302  			require.Equal(t, []sdk.AccAddress{tc.authority}, msg.GetSigners())
   303  		})
   304  	}
   305  }
   306  
   307  func TestMsgSubmitProposal(t *testing.T) {
   308  	addrs := make([]sdk.AccAddress, 1)
   309  	for i := range addrs {
   310  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   311  	}
   312  
   313  	testCases := map[string]struct {
   314  		proposers []sdk.AccAddress
   315  		msgs      []sdk.Msg
   316  		exec      foundation.Exec
   317  		valid     bool
   318  	}{
   319  		"valid msg": {
   320  			proposers: []sdk.AccAddress{addrs[0]},
   321  			msgs:      []sdk.Msg{testdata.NewTestMsg()},
   322  			valid:     true,
   323  		},
   324  		"empty proposers": {
   325  			msgs: []sdk.Msg{testdata.NewTestMsg()},
   326  		},
   327  		"invalid proposer": {
   328  			proposers: []sdk.AccAddress{nil},
   329  			msgs:      []sdk.Msg{testdata.NewTestMsg()},
   330  		},
   331  		"duplicate proposers": {
   332  			proposers: []sdk.AccAddress{addrs[0], addrs[0]},
   333  			msgs:      []sdk.Msg{testdata.NewTestMsg()},
   334  		},
   335  		"empty msgs": {
   336  			proposers: []sdk.AccAddress{addrs[0]},
   337  		},
   338  		"invalid msg": {
   339  			proposers: []sdk.AccAddress{addrs[0]},
   340  			msgs:      []sdk.Msg{&foundation.MsgWithdrawFromTreasury{}},
   341  		},
   342  		"invalid exec": {
   343  			proposers: []sdk.AccAddress{addrs[0]},
   344  			msgs:      []sdk.Msg{testdata.NewTestMsg()},
   345  			exec:      -1,
   346  		},
   347  	}
   348  
   349  	for name, tc := range testCases {
   350  		t.Run(name, func(t *testing.T) {
   351  			var proposers []string
   352  			for _, proposer := range tc.proposers {
   353  				proposers = append(proposers, proposer.String())
   354  			}
   355  
   356  			msg := foundation.MsgSubmitProposal{
   357  				Proposers: proposers,
   358  				Exec:      tc.exec,
   359  			}
   360  			err := msg.SetMsgs(tc.msgs)
   361  			require.NoError(t, err)
   362  
   363  			err = msg.ValidateBasic()
   364  			if !tc.valid {
   365  				require.Error(t, err)
   366  				return
   367  			}
   368  			require.NoError(t, err)
   369  
   370  			require.Equal(t, tc.proposers, msg.GetSigners())
   371  		})
   372  	}
   373  }
   374  
   375  func TestMsgWithdrawProposal(t *testing.T) {
   376  	addrs := make([]sdk.AccAddress, 1)
   377  	for i := range addrs {
   378  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   379  	}
   380  
   381  	testCases := map[string]struct {
   382  		id      uint64
   383  		address sdk.AccAddress
   384  		valid   bool
   385  	}{
   386  		"valid msg": {
   387  			id:      1,
   388  			address: addrs[0],
   389  			valid:   true,
   390  		},
   391  		"empty proposal id": {
   392  			address: addrs[0],
   393  		},
   394  		"empty address": {
   395  			id: 1,
   396  		},
   397  	}
   398  
   399  	for name, tc := range testCases {
   400  		t.Run(name, func(t *testing.T) {
   401  			msg := foundation.MsgWithdrawProposal{
   402  				ProposalId: tc.id,
   403  				Address:    tc.address.String(),
   404  			}
   405  
   406  			err := msg.ValidateBasic()
   407  			if !tc.valid {
   408  				require.Error(t, err)
   409  				return
   410  			}
   411  			require.NoError(t, err)
   412  
   413  			require.Equal(t, []sdk.AccAddress{tc.address}, msg.GetSigners())
   414  		})
   415  	}
   416  }
   417  
   418  func TestMsgVote(t *testing.T) {
   419  	addrs := make([]sdk.AccAddress, 1)
   420  	for i := range addrs {
   421  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   422  	}
   423  
   424  	testCases := map[string]struct {
   425  		id     uint64
   426  		voter  sdk.AccAddress
   427  		option foundation.VoteOption
   428  		exec   foundation.Exec
   429  		valid  bool
   430  	}{
   431  		"valid msg": {
   432  			id:     1,
   433  			voter:  addrs[0],
   434  			option: foundation.VOTE_OPTION_YES,
   435  			valid:  true,
   436  		},
   437  		"empty proposal id": {
   438  			voter:  addrs[0],
   439  			option: foundation.VOTE_OPTION_YES,
   440  		},
   441  		"empty voter": {
   442  			id:     1,
   443  			option: foundation.VOTE_OPTION_YES,
   444  		},
   445  		"empty option": {
   446  			id:    1,
   447  			voter: addrs[0],
   448  		},
   449  		"invalid option": {
   450  			id:     1,
   451  			voter:  addrs[0],
   452  			option: -1,
   453  		},
   454  		"invalid exec": {
   455  			id:     1,
   456  			voter:  addrs[0],
   457  			option: foundation.VOTE_OPTION_YES,
   458  			exec:   -1,
   459  		},
   460  	}
   461  
   462  	for name, tc := range testCases {
   463  		t.Run(name, func(t *testing.T) {
   464  			msg := foundation.MsgVote{
   465  				ProposalId: tc.id,
   466  				Voter:      tc.voter.String(),
   467  				Option:     tc.option,
   468  				Exec:       tc.exec,
   469  			}
   470  
   471  			err := msg.ValidateBasic()
   472  			if !tc.valid {
   473  				require.Error(t, err)
   474  				return
   475  			}
   476  			require.NoError(t, err)
   477  
   478  			require.Equal(t, []sdk.AccAddress{tc.voter}, msg.GetSigners())
   479  		})
   480  	}
   481  }
   482  
   483  func TestMsgExec(t *testing.T) {
   484  	addrs := make([]sdk.AccAddress, 1)
   485  	for i := range addrs {
   486  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   487  	}
   488  
   489  	testCases := map[string]struct {
   490  		id     uint64
   491  		signer sdk.AccAddress
   492  		valid  bool
   493  	}{
   494  		"valid msg": {
   495  			id:     1,
   496  			signer: addrs[0],
   497  			valid:  true,
   498  		},
   499  		"empty proposal id": {
   500  			signer: addrs[0],
   501  		},
   502  		"empty signer": {
   503  			id: 1,
   504  		},
   505  	}
   506  
   507  	for name, tc := range testCases {
   508  		t.Run(name, func(t *testing.T) {
   509  			msg := foundation.MsgExec{
   510  				ProposalId: tc.id,
   511  				Signer:     tc.signer.String(),
   512  			}
   513  
   514  			err := msg.ValidateBasic()
   515  			if !tc.valid {
   516  				require.Error(t, err)
   517  				return
   518  			}
   519  			require.NoError(t, err)
   520  
   521  			require.Equal(t, []sdk.AccAddress{tc.signer}, msg.GetSigners())
   522  		})
   523  	}
   524  }
   525  
   526  func TestMsgLeaveFoundation(t *testing.T) {
   527  	addrs := make([]sdk.AccAddress, 1)
   528  	for i := range addrs {
   529  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   530  	}
   531  
   532  	testCases := map[string]struct {
   533  		address sdk.AccAddress
   534  		valid   bool
   535  	}{
   536  		"valid msg": {
   537  			address: addrs[0],
   538  			valid:   true,
   539  		},
   540  		"empty address": {},
   541  	}
   542  
   543  	for name, tc := range testCases {
   544  		t.Run(name, func(t *testing.T) {
   545  			msg := foundation.MsgLeaveFoundation{
   546  				Address: tc.address.String(),
   547  			}
   548  
   549  			err := msg.ValidateBasic()
   550  			if !tc.valid {
   551  				require.Error(t, err)
   552  				return
   553  			}
   554  			require.NoError(t, err)
   555  
   556  			require.Equal(t, []sdk.AccAddress{tc.address}, msg.GetSigners())
   557  		})
   558  	}
   559  }
   560  
   561  func TestMsgGrant(t *testing.T) {
   562  	addrs := make([]sdk.AccAddress, 2)
   563  	for i := range addrs {
   564  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   565  	}
   566  
   567  	testCases := map[string]struct {
   568  		authority     sdk.AccAddress
   569  		grantee       sdk.AccAddress
   570  		authorization foundation.Authorization
   571  		valid         bool
   572  	}{
   573  		"valid msg": {
   574  			authority:     addrs[0],
   575  			grantee:       addrs[1],
   576  			authorization: &foundation.ReceiveFromTreasuryAuthorization{},
   577  			valid:         true,
   578  		},
   579  		"empty authority": {
   580  			grantee:       addrs[1],
   581  			authorization: &foundation.ReceiveFromTreasuryAuthorization{},
   582  		},
   583  		"empty grantee": {
   584  			authority:     addrs[0],
   585  			authorization: &foundation.ReceiveFromTreasuryAuthorization{},
   586  		},
   587  		"empty authorization": {
   588  			authority: addrs[0],
   589  			grantee:   addrs[1],
   590  		},
   591  	}
   592  
   593  	for name, tc := range testCases {
   594  		t.Run(name, func(t *testing.T) {
   595  			msg := foundation.MsgGrant{
   596  				Authority: tc.authority.String(),
   597  				Grantee:   tc.grantee.String(),
   598  			}
   599  			if tc.authorization != nil {
   600  				msg.SetAuthorization(tc.authorization)
   601  			}
   602  
   603  			err := msg.ValidateBasic()
   604  			if !tc.valid {
   605  				require.Error(t, err)
   606  				return
   607  			}
   608  			require.NoError(t, err)
   609  
   610  			require.Equal(t, []sdk.AccAddress{tc.authority}, msg.GetSigners())
   611  		})
   612  	}
   613  }
   614  
   615  func TestMsgRevoke(t *testing.T) {
   616  	addrs := make([]sdk.AccAddress, 2)
   617  	for i := range addrs {
   618  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   619  	}
   620  
   621  	testCases := map[string]struct {
   622  		authority  sdk.AccAddress
   623  		grantee    sdk.AccAddress
   624  		msgTypeURL string
   625  		valid      bool
   626  	}{
   627  		"valid msg": {
   628  			authority:  addrs[0],
   629  			grantee:    addrs[1],
   630  			msgTypeURL: foundation.ReceiveFromTreasuryAuthorization{}.MsgTypeURL(),
   631  			valid:      true,
   632  		},
   633  		"empty authority": {
   634  			grantee:    addrs[1],
   635  			msgTypeURL: foundation.ReceiveFromTreasuryAuthorization{}.MsgTypeURL(),
   636  		},
   637  		"empty grantee": {
   638  			authority:  addrs[0],
   639  			msgTypeURL: foundation.ReceiveFromTreasuryAuthorization{}.MsgTypeURL(),
   640  		},
   641  		"empty url": {
   642  			authority: addrs[0],
   643  			grantee:   addrs[1],
   644  		},
   645  	}
   646  
   647  	for name, tc := range testCases {
   648  		t.Run(name, func(t *testing.T) {
   649  			msg := foundation.MsgRevoke{
   650  				Authority:  tc.authority.String(),
   651  				Grantee:    tc.grantee.String(),
   652  				MsgTypeUrl: tc.msgTypeURL,
   653  			}
   654  
   655  			err := msg.ValidateBasic()
   656  			if !tc.valid {
   657  				require.Error(t, err)
   658  				return
   659  			}
   660  			require.NoError(t, err)
   661  
   662  			require.Equal(t, []sdk.AccAddress{tc.authority}, msg.GetSigners())
   663  		})
   664  	}
   665  }
   666  
   667  func TestAminoJSON(t *testing.T) {
   668  	addrs := make([]sdk.AccAddress, 3)
   669  	for i := range addrs {
   670  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   671  	}
   672  
   673  	testCases := map[string]struct {
   674  		msg      legacytx.LegacyMsg
   675  		expected string
   676  	}{
   677  		"MsgFundTreasury": {
   678  			&foundation.MsgFundTreasury{
   679  				From:   addrs[0].String(),
   680  				Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt())),
   681  			},
   682  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgFundTreasury\",\"value\":{\"amount\":[{\"amount\":\"1\",\"denom\":\"stake\"}],\"from\":\"%s\"}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", addrs[0].String()),
   683  		},
   684  		"MsgVote": {
   685  			&foundation.MsgVote{
   686  				ProposalId: 1,
   687  				Voter:      addrs[0].String(),
   688  				Option:     foundation.VOTE_OPTION_YES,
   689  				Metadata:   "I'm YES",
   690  				Exec:       foundation.Exec_EXEC_UNSPECIFIED,
   691  			},
   692  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgVote\",\"value\":{\"metadata\":\"I'm YES\",\"option\":1,\"proposal_id\":\"1\",\"voter\":\"%s\"}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", addrs[0].String()),
   693  		},
   694  		"MsgExec": {
   695  			&foundation.MsgExec{
   696  				ProposalId: 1,
   697  				Signer:     addrs[0].String(),
   698  			},
   699  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgExec\",\"value\":{\"proposal_id\":\"1\",\"signer\":\"%s\"}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", addrs[0].String()),
   700  		},
   701  		"MsgLeaveFoundation": {
   702  			&foundation.MsgLeaveFoundation{Address: addrs[0].String()},
   703  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgLeaveFoundation\",\"value\":{\"address\":\"%s\"}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", addrs[0].String()),
   704  		},
   705  		"MsgWithdrawProposal": {
   706  			&foundation.MsgWithdrawProposal{
   707  				ProposalId: 1,
   708  				Address:    addrs[0].String(),
   709  			},
   710  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgWithdrawProposal\",\"value\":{\"address\":\"%s\",\"proposal_id\":\"1\"}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", addrs[0].String()),
   711  		},
   712  	}
   713  
   714  	for name, tc := range testCases {
   715  		tc := tc
   716  
   717  		t.Run(name, func(t *testing.T) {
   718  			require.Equal(t, tc.expected, string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{tc.msg}, "memo")))
   719  		})
   720  	}
   721  }
   722  
   723  func TestMsgSubmitProposalAminoJSON(t *testing.T) {
   724  	addrs := make([]sdk.AccAddress, 2)
   725  	for i := range addrs {
   726  		addrs[i] = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   727  	}
   728  
   729  	var proposer = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   730  
   731  	testCases := map[string]struct {
   732  		msg      sdk.Msg
   733  		expected string
   734  	}{
   735  		"MsgUpdateParams": {
   736  			&foundation.MsgUpdateParams{
   737  				Authority: addrs[0].String(),
   738  				Params:    foundation.Params{FoundationTax: sdk.ZeroDec()},
   739  			},
   740  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgSubmitProposal\",\"value\":{\"exec\":1,\"messages\":[{\"type\":\"lbm-sdk/MsgUpdateParams\",\"value\":{\"authority\":\"%s\",\"params\":{\"foundation_tax\":\"0.000000000000000000\"}}}],\"metadata\":\"MsgUpdateParams\",\"proposers\":[\"%s\"]}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", addrs[0].String(), proposer.String()),
   741  		},
   742  		"MsgWithdrawFromTreasury": {
   743  			&foundation.MsgWithdrawFromTreasury{
   744  				Authority: addrs[0].String(),
   745  				To:        addrs[1].String(),
   746  				Amount:    sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000000))),
   747  			},
   748  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgSubmitProposal\",\"value\":{\"exec\":1,\"messages\":[{\"type\":\"lbm-sdk/MsgWithdrawFromTreasury\",\"value\":{\"amount\":[{\"amount\":\"1000000\",\"denom\":\"stake\"}],\"authority\":\"%s\",\"to\":\"%s\"}}],\"metadata\":\"MsgWithdrawFromTreasury\",\"proposers\":[\"%s\"]}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", addrs[0].String(), addrs[1].String(), proposer.String()),
   749  		},
   750  		"MsgUpdateMembers": {
   751  			&foundation.MsgUpdateMembers{
   752  				Authority: addrs[0].String(),
   753  				MemberUpdates: []foundation.MemberRequest{{
   754  					Address: addrs[1].String(),
   755  				}},
   756  			},
   757  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgSubmitProposal\",\"value\":{\"exec\":1,\"messages\":[{\"type\":\"lbm-sdk/MsgUpdateMembers\",\"value\":{\"authority\":\"%s\",\"member_updates\":[{\"address\":\"%s\"}]}}],\"metadata\":\"MsgUpdateMembers\",\"proposers\":[\"%s\"]}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", addrs[0].String(), addrs[1].String(), proposer.String()),
   758  		},
   759  		"MsgUpdateCensorship": {
   760  			&foundation.MsgUpdateCensorship{
   761  				Authority: addrs[0].String(),
   762  				Censorship: foundation.Censorship{
   763  					MsgTypeUrl: sdk.MsgTypeURL((*foundation.MsgWithdrawFromTreasury)(nil)),
   764  					Authority:  foundation.CensorshipAuthorityGovernance,
   765  				},
   766  			},
   767  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgSubmitProposal\",\"value\":{\"exec\":1,\"messages\":[{\"type\":\"lbm-sdk/MsgUpdateCensorship\",\"value\":{\"authority\":\"%s\",\"censorship\":{\"authority\":1,\"msg_type_url\":\"/lbm.foundation.v1.MsgWithdrawFromTreasury\"}}}],\"metadata\":\"MsgUpdateCensorship\",\"proposers\":[\"%s\"]}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", addrs[0].String(), proposer.String()),
   768  		},
   769  		"MsgRevoke": {
   770  			&foundation.MsgRevoke{
   771  				Authority:  addrs[0].String(),
   772  				Grantee:    addrs[1].String(),
   773  				MsgTypeUrl: foundation.ReceiveFromTreasuryAuthorization{}.MsgTypeURL(),
   774  			},
   775  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgSubmitProposal\",\"value\":{\"exec\":1,\"messages\":[{\"type\":\"lbm-sdk/MsgRevoke\",\"value\":{\"authority\":\"%s\",\"grantee\":\"%s\",\"msg_type_url\":\"/lbm.foundation.v1.MsgWithdrawFromTreasury\"}}],\"metadata\":\"MsgRevoke\",\"proposers\":[\"%s\"]}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", addrs[0].String(), addrs[1].String(), proposer.String()),
   776  		},
   777  	}
   778  
   779  	for name, tc := range testCases {
   780  		tc := tc
   781  
   782  		t.Run(name, func(t *testing.T) {
   783  			proposalMsg := &foundation.MsgSubmitProposal{
   784  				Proposers: []string{proposer.String()},
   785  				Metadata:  name,
   786  				Exec:      foundation.Exec_EXEC_TRY,
   787  			}
   788  			err := proposalMsg.SetMsgs([]sdk.Msg{tc.msg})
   789  			require.NoError(t, err)
   790  			require.Equal(t, tc.expected, string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{proposalMsg}, "memo")))
   791  		})
   792  	}
   793  }
   794  
   795  func TestMsgUpdateDecisionPolicyAminoJson(t *testing.T) {
   796  	var (
   797  		authority = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   798  		proposer  = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   799  	)
   800  
   801  	testCases := map[string]struct {
   802  		policy   foundation.DecisionPolicy
   803  		expected string
   804  	}{
   805  		"ThresholdDecisionPolicy": {
   806  			&foundation.ThresholdDecisionPolicy{
   807  				Threshold: sdk.OneDec(),
   808  				Windows: &foundation.DecisionPolicyWindows{
   809  					VotingPeriod: time.Hour,
   810  				},
   811  			},
   812  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgSubmitProposal\",\"value\":{\"exec\":1,\"messages\":[{\"type\":\"lbm-sdk/MsgUpdateDecisionPolicy\",\"value\":{\"authority\":\"%s\",\"decision_policy\":{\"type\":\"lbm-sdk/ThresholdDecisionPolicy\",\"value\":{\"threshold\":\"1.000000000000000000\",\"windows\":{\"min_execution_period\":\"0\",\"voting_period\":\"3600000000000\"}}}}}],\"metadata\":\"ThresholdDecisionPolicy\",\"proposers\":[\"%s\"]}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", authority, proposer),
   813  		},
   814  		"PercentageDecisionPolicy": {
   815  			&foundation.PercentageDecisionPolicy{
   816  				Percentage: sdk.OneDec(),
   817  				Windows: &foundation.DecisionPolicyWindows{
   818  					VotingPeriod: time.Hour,
   819  				},
   820  			},
   821  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgSubmitProposal\",\"value\":{\"exec\":1,\"messages\":[{\"type\":\"lbm-sdk/MsgUpdateDecisionPolicy\",\"value\":{\"authority\":\"%s\",\"decision_policy\":{\"type\":\"lbm-sdk/PercentageDecisionPolicy\",\"value\":{\"percentage\":\"1.000000000000000000\",\"windows\":{\"min_execution_period\":\"0\",\"voting_period\":\"3600000000000\"}}}}}],\"metadata\":\"PercentageDecisionPolicy\",\"proposers\":[\"%s\"]}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", authority, proposer),
   822  		},
   823  	}
   824  
   825  	for name, tc := range testCases {
   826  		tc := tc
   827  
   828  		t.Run(name, func(t *testing.T) {
   829  			policyMsg := &foundation.MsgUpdateDecisionPolicy{
   830  				Authority: authority.String(),
   831  			}
   832  			err := policyMsg.SetDecisionPolicy(tc.policy)
   833  			require.NoError(t, err)
   834  
   835  			err = policyMsg.ValidateBasic()
   836  			require.NoError(t, err)
   837  
   838  			proposalMsg := &foundation.MsgSubmitProposal{
   839  				Proposers: []string{proposer.String()},
   840  				Metadata:  name,
   841  				Exec:      foundation.Exec_EXEC_TRY,
   842  			}
   843  			err = proposalMsg.SetMsgs([]sdk.Msg{policyMsg})
   844  			require.NoError(t, err)
   845  
   846  			require.Equal(t, tc.expected, string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{proposalMsg}, "memo")))
   847  		})
   848  	}
   849  }
   850  
   851  func TestMsgGrantAminoJson(t *testing.T) {
   852  	var (
   853  		operator = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   854  		grantee  = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   855  		proposer = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
   856  	)
   857  
   858  	testCases := map[string]struct {
   859  		authorization foundation.Authorization
   860  		expected      string
   861  	}{
   862  		"ReceiveFromTreasuryAuthorization": {
   863  			&foundation.ReceiveFromTreasuryAuthorization{},
   864  			fmt.Sprintf("{\"account_number\":\"1\",\"chain_id\":\"foo\",\"fee\":{\"amount\":[],\"gas\":\"0\"},\"memo\":\"memo\",\"msgs\":[{\"type\":\"lbm-sdk/MsgSubmitProposal\",\"value\":{\"exec\":1,\"messages\":[{\"type\":\"lbm-sdk/MsgGrant\",\"value\":{\"authority\":\"%s\",\"authorization\":{\"type\":\"lbm-sdk/ReceiveFromTreasuryAuthorization\",\"value\":{}},\"grantee\":\"%s\"}}],\"metadata\":\"ReceiveFromTreasuryAuthorization\",\"proposers\":[\"%s\"]}}],\"sequence\":\"1\",\"timeout_height\":\"1\"}", operator.String(), grantee.String(), proposer.String()),
   865  		},
   866  	}
   867  
   868  	for name, tc := range testCases {
   869  		tc := tc
   870  
   871  		t.Run(name, func(t *testing.T) {
   872  			grantMsg := &foundation.MsgGrant{
   873  				Authority: operator.String(),
   874  				Grantee:   grantee.String(),
   875  			}
   876  			err := grantMsg.SetAuthorization(tc.authorization)
   877  			require.NoError(t, err)
   878  
   879  			err = grantMsg.ValidateBasic()
   880  			require.NoError(t, err)
   881  
   882  			proposalMsg := &foundation.MsgSubmitProposal{
   883  				Proposers: []string{proposer.String()},
   884  				Metadata:  name,
   885  				Exec:      foundation.Exec_EXEC_TRY,
   886  			}
   887  			err = proposalMsg.SetMsgs([]sdk.Msg{grantMsg})
   888  			require.NoError(t, err)
   889  
   890  			require.Equal(t, tc.expected, string(legacytx.StdSignBytes("foo", 1, 1, 1, legacytx.StdFee{}, []sdk.Msg{proposalMsg}, "memo")))
   891  		})
   892  	}
   893  }