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

     1  package internal_test
     2  
     3  import (
     4  	"time"
     5  
     6  	abci "github.com/tendermint/tendermint/abci/types"
     7  
     8  	"github.com/Finschia/finschia-sdk/testutil/testdata"
     9  	sdk "github.com/Finschia/finschia-sdk/types"
    10  	"github.com/Finschia/finschia-sdk/x/foundation"
    11  )
    12  
    13  func (s *KeeperTestSuite) TestMsgFundTreasury() {
    14  	testCases := map[string]struct {
    15  		amount sdk.Int
    16  		valid  bool
    17  		events sdk.Events
    18  	}{
    19  		"valid request": {
    20  			amount: s.balance,
    21  			valid:  true,
    22  			events: sdk.Events{{Type: "coin_spent", Attributes: []abci.EventAttribute{{Key: []uint8{0x73, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34}, Index: false}, {Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x73, 0x74, 0x61, 0x6b, 0x65}, Index: false}}}, {Type: "coin_received", Attributes: []abci.EventAttribute{{Key: []uint8{0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x6d, 0x61, 0x66, 0x6c, 0x38, 0x66, 0x33, 0x73, 0x36, 0x75, 0x75, 0x7a, 0x77, 0x6e, 0x78, 0x6b, 0x71, 0x7a, 0x30, 0x65, 0x7a, 0x61, 0x34, 0x37, 0x76, 0x36, 0x65, 0x63, 0x6e, 0x30, 0x74, 0x75, 0x77, 0x72, 0x36, 0x79, 0x6b}, Index: false}, {Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x73, 0x74, 0x61, 0x6b, 0x65}, Index: false}}}, {Type: "transfer", Attributes: []abci.EventAttribute{{Key: []uint8{0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x6d, 0x61, 0x66, 0x6c, 0x38, 0x66, 0x33, 0x73, 0x36, 0x75, 0x75, 0x7a, 0x77, 0x6e, 0x78, 0x6b, 0x71, 0x7a, 0x30, 0x65, 0x7a, 0x61, 0x34, 0x37, 0x76, 0x36, 0x65, 0x63, 0x6e, 0x30, 0x74, 0x75, 0x77, 0x72, 0x36, 0x79, 0x6b}, Index: false}, {Key: []uint8{0x73, 0x65, 0x6e, 0x64, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34}, Index: false}, {Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x73, 0x74, 0x61, 0x6b, 0x65}, Index: false}}}, {Type: "lbm.foundation.v1.EventFundTreasury", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x5b, 0x7b, 0x22, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x22, 0x3a, 0x22, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x22, 0x7d, 0x5d}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34, 0x22}, Index: false}}}},
    23  		},
    24  		"insufficient funds": {
    25  			amount: s.balance.Add(sdk.OneInt()),
    26  		},
    27  	}
    28  
    29  	for name, tc := range testCases {
    30  		s.Run(name, func() {
    31  			ctx, _ := s.ctx.CacheContext()
    32  
    33  			req := &foundation.MsgFundTreasury{
    34  				From:   s.stranger.String(),
    35  				Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, tc.amount)),
    36  			}
    37  			res, err := s.msgServer.FundTreasury(sdk.WrapSDKContext(ctx), req)
    38  			if !tc.valid {
    39  				s.Require().Error(err)
    40  				return
    41  			}
    42  			s.Require().NoError(err)
    43  
    44  			s.Require().NotNil(res)
    45  
    46  			if s.deterministic {
    47  				s.Require().Equal(tc.events, ctx.EventManager().Events())
    48  			}
    49  		})
    50  	}
    51  }
    52  
    53  func (s *KeeperTestSuite) TestMsgWithdrawFromTreasury() {
    54  	testCases := map[string]struct {
    55  		authority sdk.AccAddress
    56  		to        sdk.AccAddress
    57  		amount    sdk.Int
    58  		valid     bool
    59  		events    sdk.Events
    60  	}{
    61  		"valid request": {
    62  			authority: s.authority,
    63  			to:        s.stranger,
    64  			amount:    s.balance,
    65  			valid:     true,
    66  			events:    sdk.Events{{Type: "coin_spent", Attributes: []abci.EventAttribute{{Key: []uint8{0x73, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x6d, 0x61, 0x66, 0x6c, 0x38, 0x66, 0x33, 0x73, 0x36, 0x75, 0x75, 0x7a, 0x77, 0x6e, 0x78, 0x6b, 0x71, 0x7a, 0x30, 0x65, 0x7a, 0x61, 0x34, 0x37, 0x76, 0x36, 0x65, 0x63, 0x6e, 0x30, 0x74, 0x75, 0x77, 0x72, 0x36, 0x79, 0x6b}, Index: false}, {Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x73, 0x74, 0x61, 0x6b, 0x65}, Index: false}}}, {Type: "coin_received", Attributes: []abci.EventAttribute{{Key: []uint8{0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34}, Index: false}, {Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x73, 0x74, 0x61, 0x6b, 0x65}, Index: false}}}, {Type: "transfer", Attributes: []abci.EventAttribute{{Key: []uint8{0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34}, Index: false}, {Key: []uint8{0x73, 0x65, 0x6e, 0x64, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x6d, 0x61, 0x66, 0x6c, 0x38, 0x66, 0x33, 0x73, 0x36, 0x75, 0x75, 0x7a, 0x77, 0x6e, 0x78, 0x6b, 0x71, 0x7a, 0x30, 0x65, 0x7a, 0x61, 0x34, 0x37, 0x76, 0x36, 0x65, 0x63, 0x6e, 0x30, 0x74, 0x75, 0x77, 0x72, 0x36, 0x79, 0x6b}, Index: false}, {Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x73, 0x74, 0x61, 0x6b, 0x65}, Index: false}}}, {Type: "lbm.foundation.v1.EventWithdrawFromTreasury", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x5b, 0x7b, 0x22, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x22, 0x3a, 0x22, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x22, 0x7d, 0x5d}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34, 0x22}, Index: false}}}},
    67  		},
    68  		"authority not authorized": {
    69  			authority: s.stranger,
    70  			to:        s.stranger,
    71  			amount:    s.balance,
    72  		},
    73  		"receiver not authorized": {
    74  			authority: s.authority,
    75  			to:        s.members[0],
    76  			amount:    s.balance,
    77  		},
    78  		"insufficient funds": {
    79  			authority: s.authority,
    80  			to:        s.stranger,
    81  			amount:    s.balance.Add(sdk.OneInt()),
    82  		},
    83  	}
    84  
    85  	for name, tc := range testCases {
    86  		s.Run(name, func() {
    87  			ctx, _ := s.ctx.CacheContext()
    88  
    89  			req := &foundation.MsgWithdrawFromTreasury{
    90  				Authority: tc.authority.String(),
    91  				To:        tc.to.String(),
    92  				Amount:    sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, tc.amount)),
    93  			}
    94  			res, err := s.msgServer.WithdrawFromTreasury(sdk.WrapSDKContext(ctx), req)
    95  			if !tc.valid {
    96  				s.Require().Error(err)
    97  				return
    98  			}
    99  			s.Require().NoError(err)
   100  
   101  			s.Require().NotNil(res)
   102  
   103  			if s.deterministic {
   104  				s.Require().Equal(tc.events, ctx.EventManager().Events())
   105  			}
   106  		})
   107  	}
   108  }
   109  
   110  func (s *KeeperTestSuite) TestMsgUpdateDecisionPolicy() {
   111  	testCases := map[string]struct {
   112  		authority sdk.AccAddress
   113  		policy    foundation.DecisionPolicy
   114  		valid     bool
   115  		events    sdk.Events
   116  	}{
   117  		"valid request": {
   118  			authority: s.authority,
   119  			policy: &foundation.ThresholdDecisionPolicy{
   120  				Threshold: sdk.OneDec(),
   121  				Windows:   &foundation.DecisionPolicyWindows{},
   122  			},
   123  			valid:  true,
   124  			events: sdk.Events{{Type: "lbm.foundation.v1.EventUpdateDecisionPolicy", Attributes: []abci.EventAttribute{{Key: []uint8{0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79}, Value: []uint8{0x7b, 0x22, 0x40, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x2f, 0x6c, 0x62, 0x6d, 0x2e, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x2c, 0x22, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x76, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x73, 0x22, 0x2c, 0x22, 0x6d, 0x69, 0x6e, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x73, 0x22, 0x7d, 0x7d}, Index: false}}}},
   125  		},
   126  		"not authorized": {
   127  			authority: s.stranger,
   128  			policy: &foundation.ThresholdDecisionPolicy{
   129  				Threshold: sdk.OneDec(),
   130  				Windows:   &foundation.DecisionPolicyWindows{},
   131  			},
   132  		},
   133  		"invalid policy": {
   134  			authority: s.authority,
   135  			policy: &foundation.ThresholdDecisionPolicy{
   136  				Threshold: sdk.OneDec(),
   137  				Windows: &foundation.DecisionPolicyWindows{
   138  					VotingPeriod:       time.Hour,
   139  					MinExecutionPeriod: foundation.DefaultConfig().MaxExecutionPeriod + time.Hour,
   140  				},
   141  			},
   142  		},
   143  	}
   144  
   145  	for name, tc := range testCases {
   146  		s.Run(name, func() {
   147  			ctx, _ := s.ctx.CacheContext()
   148  
   149  			req := &foundation.MsgUpdateDecisionPolicy{
   150  				Authority: tc.authority.String(),
   151  			}
   152  			err := req.SetDecisionPolicy(tc.policy)
   153  			s.Require().NoError(err)
   154  
   155  			res, err := s.msgServer.UpdateDecisionPolicy(sdk.WrapSDKContext(ctx), req)
   156  			if !tc.valid {
   157  				s.Require().Error(err)
   158  				return
   159  			}
   160  			s.Require().NoError(err)
   161  
   162  			s.Require().NotNil(res)
   163  
   164  			if s.deterministic {
   165  				s.Require().Equal(tc.events, ctx.EventManager().Events())
   166  			}
   167  		})
   168  	}
   169  }
   170  
   171  func (s *KeeperTestSuite) TestMsgUpdateMembers() {
   172  	testCases := map[string]struct {
   173  		authority sdk.AccAddress
   174  		member    foundation.MemberRequest
   175  		valid     bool
   176  		events    sdk.Events
   177  	}{
   178  		"valid request": {
   179  			authority: s.authority,
   180  			member: foundation.MemberRequest{
   181  				Address: s.members[0].String(),
   182  			},
   183  			valid:  true,
   184  			events: sdk.Events{{Type: "lbm.foundation.v1.EventUpdateMembers", Attributes: []abci.EventAttribute{{Key: []uint8{0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73}, Value: []uint8{0x5b, 0x7b, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22, 0x2c, 0x22, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x7d, 0x5d}, Index: false}}}},
   185  		},
   186  		"not authorized": {
   187  			authority: s.stranger,
   188  			member: foundation.MemberRequest{
   189  				Address: s.members[0].String(),
   190  			},
   191  		},
   192  		"remove a non-member": {
   193  			authority: s.authority,
   194  			member: foundation.MemberRequest{
   195  				Address: s.stranger.String(),
   196  				Remove:  true,
   197  			},
   198  		},
   199  	}
   200  
   201  	for name, tc := range testCases {
   202  		s.Run(name, func() {
   203  			ctx, _ := s.ctx.CacheContext()
   204  
   205  			req := &foundation.MsgUpdateMembers{
   206  				Authority:     tc.authority.String(),
   207  				MemberUpdates: []foundation.MemberRequest{tc.member},
   208  			}
   209  			res, err := s.msgServer.UpdateMembers(sdk.WrapSDKContext(ctx), req)
   210  			if !tc.valid {
   211  				s.Require().Error(err)
   212  				return
   213  			}
   214  			s.Require().NoError(err)
   215  
   216  			s.Require().NotNil(res)
   217  
   218  			if s.deterministic {
   219  				s.Require().Equal(tc.events, ctx.EventManager().Events())
   220  			}
   221  		})
   222  	}
   223  }
   224  
   225  func (s *KeeperTestSuite) TestMsgSubmitProposal() {
   226  	members := make([]string, len(s.members))
   227  	for i, member := range s.members {
   228  		members[i] = member.String()
   229  	}
   230  
   231  	testCases := map[string]struct {
   232  		malleate  func(ctx sdk.Context)
   233  		proposers []string
   234  		metadata  string
   235  		msg       sdk.Msg
   236  		exec      foundation.Exec
   237  		valid     bool
   238  		events    sdk.Events
   239  	}{
   240  		"valid request (submit)": {
   241  			proposers: members,
   242  			msg:       testdata.NewTestMsg(s.authority),
   243  			valid:     true,
   244  			events:    sdk.Events{{Type: "lbm.foundation.v1.EventSubmitProposal", Attributes: []abci.EventAttribute{{Key: []uint8{0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c}, Value: []uint8{0x7b, 0x22, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x77, 0x30, 0x38, 0x70, 0x36, 0x74, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x78, 0x70, 0x39, 0x39, 0x38, 0x34, 0x33, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x67, 0x72, 0x37, 0x7a, 0x77, 0x68, 0x6d, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x32, 0x73, 0x6d, 0x72, 0x64, 0x79, 0x6b, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x76, 0x76, 0x35, 0x71, 0x67, 0x63, 0x70, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x77, 0x6c, 0x33, 0x70, 0x74, 0x74, 0x76, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x73, 0x67, 0x74, 0x77, 0x36, 0x75, 0x34, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x6a, 0x6d, 0x77, 0x30, 0x65, 0x30, 0x63, 0x22, 0x5d, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x2c, 0x22, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3a, 0x22, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x42, 0x4d, 0x49, 0x54, 0x54, 0x45, 0x44, 0x22, 0x2c, 0x22, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x74, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x79, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x22, 0x61, 0x62, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x6f, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x6f, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x76, 0x65, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x7d, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x38, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x2c, 0x22, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x22, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x52, 0x55, 0x4e, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x40, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x22, 0x2c, 0x22, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x39, 0x30, 0x76, 0x74, 0x30, 0x76, 0x78, 0x63, 0x38, 0x63, 0x38, 0x76, 0x6a, 0x32, 0x34, 0x61, 0x37, 0x6d, 0x6d, 0x33, 0x66, 0x6a, 0x73, 0x65, 0x6e, 0x66, 0x75, 0x38, 0x66, 0x35, 0x79, 0x78, 0x78, 0x6a, 0x37, 0x36, 0x63, 0x70, 0x22, 0x5d, 0x7d, 0x5d, 0x7d}, Index: false}}}},
   245  		},
   246  		"valid request (submit & execute)": {
   247  			proposers: members,
   248  			msg:       testdata.NewTestMsg(s.authority),
   249  			exec:      foundation.Exec_EXEC_TRY,
   250  			valid:     true,
   251  			events:    sdk.Events{{Type: "lbm.foundation.v1.EventSubmitProposal", Attributes: []abci.EventAttribute{{Key: []uint8{0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c}, Value: []uint8{0x7b, 0x22, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x77, 0x30, 0x38, 0x70, 0x36, 0x74, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x78, 0x70, 0x39, 0x39, 0x38, 0x34, 0x33, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x67, 0x72, 0x37, 0x7a, 0x77, 0x68, 0x6d, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x32, 0x73, 0x6d, 0x72, 0x64, 0x79, 0x6b, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x76, 0x76, 0x35, 0x71, 0x67, 0x63, 0x70, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x77, 0x6c, 0x33, 0x70, 0x74, 0x74, 0x76, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x73, 0x67, 0x74, 0x77, 0x36, 0x75, 0x34, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x6a, 0x6d, 0x77, 0x30, 0x65, 0x30, 0x63, 0x22, 0x5d, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x2c, 0x22, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3a, 0x22, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x42, 0x4d, 0x49, 0x54, 0x54, 0x45, 0x44, 0x22, 0x2c, 0x22, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x74, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x79, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x22, 0x61, 0x62, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x6f, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x6f, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x76, 0x65, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x7d, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x38, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x2c, 0x22, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x22, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x52, 0x55, 0x4e, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x40, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x22, 0x2c, 0x22, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x39, 0x30, 0x76, 0x74, 0x30, 0x76, 0x78, 0x63, 0x38, 0x63, 0x38, 0x76, 0x6a, 0x32, 0x34, 0x61, 0x37, 0x6d, 0x6d, 0x33, 0x66, 0x6a, 0x73, 0x65, 0x6e, 0x66, 0x75, 0x38, 0x66, 0x35, 0x79, 0x78, 0x78, 0x6a, 0x37, 0x36, 0x63, 0x70, 0x22, 0x5d, 0x7d, 0x5d, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x77, 0x30, 0x38, 0x70, 0x36, 0x74, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x78, 0x70, 0x39, 0x39, 0x38, 0x34, 0x33, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x67, 0x72, 0x37, 0x7a, 0x77, 0x68, 0x6d, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x32, 0x73, 0x6d, 0x72, 0x64, 0x79, 0x6b, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x76, 0x76, 0x35, 0x71, 0x67, 0x63, 0x70, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x77, 0x6c, 0x33, 0x70, 0x74, 0x74, 0x76, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x73, 0x67, 0x74, 0x77, 0x36, 0x75, 0x34, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x6a, 0x6d, 0x77, 0x30, 0x65, 0x30, 0x63, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventExec", Attributes: []abci.EventAttribute{{Key: []uint8{0x6c, 0x6f, 0x67, 0x73}, Value: []uint8{0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x20, 0x36, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x5c, 0x22, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x5c, 0x22, 0x3a, 0x20, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22}, Index: false}, {Key: []uint8{0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x36, 0x22}, Index: false}, {Key: []uint8{0x72, 0x65, 0x73, 0x75, 0x6c, 0x74}, Value: []uint8{0x22, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x22}, Index: false}}}},
   252  		},
   253  		"valid request (submit & unable to reach quorum)": {
   254  			proposers: []string{members[0]},
   255  			msg:       testdata.NewTestMsg(s.authority),
   256  			exec:      foundation.Exec_EXEC_TRY,
   257  			valid:     true,
   258  			events:    sdk.Events{{Type: "lbm.foundation.v1.EventSubmitProposal", Attributes: []abci.EventAttribute{{Key: []uint8{0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c}, Value: []uint8{0x7b, 0x22, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22, 0x5d, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x2c, 0x22, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3a, 0x22, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x42, 0x4d, 0x49, 0x54, 0x54, 0x45, 0x44, 0x22, 0x2c, 0x22, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x74, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x79, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x22, 0x61, 0x62, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x6f, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x6f, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x76, 0x65, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x7d, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x38, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x2c, 0x22, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x22, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x52, 0x55, 0x4e, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x40, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x22, 0x2c, 0x22, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x39, 0x30, 0x76, 0x74, 0x30, 0x76, 0x78, 0x63, 0x38, 0x63, 0x38, 0x76, 0x6a, 0x32, 0x34, 0x61, 0x37, 0x6d, 0x6d, 0x33, 0x66, 0x6a, 0x73, 0x65, 0x6e, 0x66, 0x75, 0x38, 0x66, 0x35, 0x79, 0x78, 0x78, 0x6a, 0x37, 0x36, 0x63, 0x70, 0x22, 0x5d, 0x7d, 0x5d, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x36, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}, {Type: "lbm.foundation.v1.EventExec", Attributes: []abci.EventAttribute{{Key: []uint8{0x6c, 0x6f, 0x67, 0x73}, Value: []uint8{0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x20, 0x36, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x5c, 0x22, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x5c, 0x22, 0x3a, 0x20, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22}, Index: false}, {Key: []uint8{0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x36, 0x22}, Index: false}, {Key: []uint8{0x72, 0x65, 0x73, 0x75, 0x6c, 0x74}, Value: []uint8{0x22, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x22}, Index: false}}}},
   259  		},
   260  		"not a member": {
   261  			proposers: []string{s.stranger.String()},
   262  			msg:       testdata.NewTestMsg(s.authority),
   263  		},
   264  		"unauthorized msg": {
   265  			proposers: []string{members[0]},
   266  			msg:       testdata.NewTestMsg(s.stranger),
   267  		},
   268  		"exec fails": {
   269  			malleate: func(ctx sdk.Context) {
   270  				// try exec will fail because of a non-zero MinExecutionPeriod.
   271  				err := s.impl.UpdateDecisionPolicy(ctx, &foundation.ThresholdDecisionPolicy{
   272  					Threshold: sdk.OneDec(),
   273  					Windows: &foundation.DecisionPolicyWindows{
   274  						VotingPeriod:       time.Hour,
   275  						MinExecutionPeriod: time.Second,
   276  					},
   277  				})
   278  				s.Require().NoError(err)
   279  			},
   280  			proposers: members,
   281  			msg:       testdata.NewTestMsg(s.authority),
   282  			exec:      foundation.Exec_EXEC_TRY,
   283  		},
   284  	}
   285  
   286  	for name, tc := range testCases {
   287  		s.Run(name, func() {
   288  			ctx, _ := s.ctx.CacheContext()
   289  			if tc.malleate != nil {
   290  				tc.malleate(ctx)
   291  			}
   292  
   293  			req := &foundation.MsgSubmitProposal{
   294  				Proposers: tc.proposers,
   295  				Metadata:  tc.metadata,
   296  				Exec:      tc.exec,
   297  			}
   298  			err := req.SetMsgs([]sdk.Msg{tc.msg})
   299  			s.Require().NoError(err)
   300  
   301  			res, err := s.msgServer.SubmitProposal(sdk.WrapSDKContext(ctx), req)
   302  			if !tc.valid {
   303  				s.Require().Error(err)
   304  				return
   305  			}
   306  			s.Require().NoError(err)
   307  
   308  			s.Require().NotNil(res)
   309  
   310  			if s.deterministic {
   311  				s.Require().Equal(tc.events, ctx.EventManager().Events())
   312  			}
   313  		})
   314  	}
   315  }
   316  
   317  func (s *KeeperTestSuite) TestMsgWithdrawProposal() {
   318  	testCases := map[string]struct {
   319  		proposalID uint64
   320  		address    sdk.AccAddress
   321  		valid      bool
   322  		events     sdk.Events
   323  	}{
   324  		"valid request (proposer)": {
   325  			proposalID: s.activeProposal,
   326  			address:    s.members[0],
   327  			valid:      true,
   328  			events:     sdk.Events{{Type: "lbm.foundation.v1.EventWithdrawProposal", Attributes: []abci.EventAttribute{{Key: []uint8{0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x22}, Index: false}}}},
   329  		},
   330  		"valid request (authority)": {
   331  			proposalID: s.activeProposal,
   332  			address:    s.authority,
   333  			valid:      true,
   334  			events:     sdk.Events{{Type: "lbm.foundation.v1.EventWithdrawProposal", Attributes: []abci.EventAttribute{{Key: []uint8{0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x22}, Index: false}}}},
   335  		},
   336  		"not authorized": {
   337  			proposalID: s.activeProposal,
   338  			address:    s.stranger,
   339  		},
   340  		"inactive proposal": {
   341  			proposalID: s.withdrawnProposal,
   342  			address:    s.members[0],
   343  		},
   344  	}
   345  
   346  	for name, tc := range testCases {
   347  		s.Run(name, func() {
   348  			ctx, _ := s.ctx.CacheContext()
   349  
   350  			req := &foundation.MsgWithdrawProposal{
   351  				ProposalId: tc.proposalID,
   352  				Address:    tc.address.String(),
   353  			}
   354  			res, err := s.msgServer.WithdrawProposal(sdk.WrapSDKContext(ctx), req)
   355  			if !tc.valid {
   356  				s.Require().Error(err)
   357  				return
   358  			}
   359  			s.Require().NoError(err)
   360  
   361  			s.Require().NotNil(res)
   362  
   363  			if s.deterministic {
   364  				s.Require().Equal(tc.events, ctx.EventManager().Events())
   365  			}
   366  		})
   367  	}
   368  }
   369  
   370  func (s *KeeperTestSuite) TestMsgVote() {
   371  	testCases := map[string]struct {
   372  		malleate   func(ctx sdk.Context)
   373  		proposalID uint64
   374  		voter      sdk.AccAddress
   375  		msg        sdk.Msg
   376  		exec       foundation.Exec
   377  		valid      bool
   378  		events     sdk.Events
   379  	}{
   380  		"valid request (vote)": {
   381  			proposalID: s.activeProposal,
   382  			voter:      s.members[0],
   383  			valid:      true,
   384  			events:     sdk.Events{{Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}},
   385  		},
   386  		"valid request (vote & execute)": {
   387  			proposalID: s.activeProposal,
   388  			voter:      s.members[0],
   389  			exec:       foundation.Exec_EXEC_TRY,
   390  			valid:      true,
   391  			events:     sdk.Events{{Type: "lbm.foundation.v1.EventVote", Attributes: []abci.EventAttribute{{Key: []uint8{0x76, 0x6f, 0x74, 0x65}, Value: []uint8{0x7b, 0x22, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x2c, 0x22, 0x76, 0x6f, 0x74, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22, 0x2c, 0x22, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x56, 0x4f, 0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59, 0x45, 0x53, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x31, 0x54, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x5a, 0x22, 0x7d}, Index: false}}}, {Type: "coin_spent", Attributes: []abci.EventAttribute{{Key: []uint8{0x73, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x6d, 0x61, 0x66, 0x6c, 0x38, 0x66, 0x33, 0x73, 0x36, 0x75, 0x75, 0x7a, 0x77, 0x6e, 0x78, 0x6b, 0x71, 0x7a, 0x30, 0x65, 0x7a, 0x61, 0x34, 0x37, 0x76, 0x36, 0x65, 0x63, 0x6e, 0x30, 0x74, 0x75, 0x77, 0x72, 0x36, 0x79, 0x6b}, Index: false}, {Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x73, 0x74, 0x61, 0x6b, 0x65}, Index: false}}}, {Type: "coin_received", Attributes: []abci.EventAttribute{{Key: []uint8{0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34}, Index: false}, {Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x73, 0x74, 0x61, 0x6b, 0x65}, Index: false}}}, {Type: "transfer", Attributes: []abci.EventAttribute{{Key: []uint8{0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34}, Index: false}, {Key: []uint8{0x73, 0x65, 0x6e, 0x64, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x6d, 0x61, 0x66, 0x6c, 0x38, 0x66, 0x33, 0x73, 0x36, 0x75, 0x75, 0x7a, 0x77, 0x6e, 0x78, 0x6b, 0x71, 0x7a, 0x30, 0x65, 0x7a, 0x61, 0x34, 0x37, 0x76, 0x36, 0x65, 0x63, 0x6e, 0x30, 0x74, 0x75, 0x77, 0x72, 0x36, 0x79, 0x6b}, Index: false}, {Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x73, 0x74, 0x61, 0x6b, 0x65}, Index: false}}}, {Type: "lbm.foundation.v1.EventWithdrawFromTreasury", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x5b, 0x7b, 0x22, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x22, 0x3a, 0x22, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x22, 0x7d, 0x5d}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34, 0x22}, Index: false}}}, {Type: "lbm.foundation.v1.EventExec", Attributes: []abci.EventAttribute{{Key: []uint8{0x6c, 0x6f, 0x67, 0x73}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x22}, Index: false}, {Key: []uint8{0x72, 0x65, 0x73, 0x75, 0x6c, 0x74}, Value: []uint8{0x22, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x22}, Index: false}}}},
   392  		},
   393  		"not authorized": {
   394  			proposalID: s.activeProposal,
   395  			voter:      s.stranger,
   396  		},
   397  		"already voted": {
   398  			proposalID: s.votedProposal,
   399  			voter:      s.members[0],
   400  		},
   401  		"exec fails": {
   402  			malleate: func(ctx sdk.Context) {
   403  				// try exec will fail because of a non-zero MinExecutionPeriod.
   404  				err := s.impl.UpdateDecisionPolicy(ctx, &foundation.ThresholdDecisionPolicy{
   405  					Threshold: sdk.OneDec(),
   406  					Windows: &foundation.DecisionPolicyWindows{
   407  						VotingPeriod:       time.Hour,
   408  						MinExecutionPeriod: time.Second,
   409  					},
   410  				})
   411  				s.Require().NoError(err)
   412  
   413  				// submit a proposal
   414  				proposers := make([]string, len(s.members))
   415  				for i, member := range s.members {
   416  					proposers[i] = member.String()
   417  				}
   418  				req := &foundation.MsgSubmitProposal{
   419  					Proposers: proposers,
   420  				}
   421  				err = req.SetMsgs([]sdk.Msg{testdata.NewTestMsg(s.authority)})
   422  				s.Require().NoError(err)
   423  
   424  				res, err := s.msgServer.SubmitProposal(sdk.WrapSDKContext(ctx), req)
   425  				s.Require().NoError(err)
   426  				s.Require().NotNil(res)
   427  
   428  				s.Require().Equal(s.nextProposal, res.ProposalId)
   429  			},
   430  			proposalID: s.nextProposal,
   431  			voter:      s.members[0],
   432  			exec:       foundation.Exec_EXEC_TRY,
   433  		},
   434  	}
   435  
   436  	for name, tc := range testCases {
   437  		s.Run(name, func() {
   438  			ctx, _ := s.ctx.CacheContext()
   439  			if tc.malleate != nil {
   440  				tc.malleate(ctx)
   441  			}
   442  
   443  			req := &foundation.MsgVote{
   444  				ProposalId: tc.proposalID,
   445  				Voter:      tc.voter.String(),
   446  				Option:     foundation.VOTE_OPTION_YES,
   447  				Exec:       tc.exec,
   448  			}
   449  			res, err := s.msgServer.Vote(sdk.WrapSDKContext(ctx), req)
   450  			if !tc.valid {
   451  				s.Require().Error(err)
   452  				return
   453  			}
   454  			s.Require().NoError(err)
   455  
   456  			s.Require().NotNil(res)
   457  
   458  			if s.deterministic {
   459  				s.Require().Equal(tc.events, ctx.EventManager().Events())
   460  			}
   461  		})
   462  	}
   463  }
   464  
   465  func (s *KeeperTestSuite) TestMsgExec() {
   466  	testCases := map[string]struct {
   467  		malleate   func(ctx sdk.Context)
   468  		proposalID uint64
   469  		signer     sdk.AccAddress
   470  		valid      bool
   471  		events     sdk.Events
   472  	}{
   473  		"valid request (execute)": {
   474  			proposalID: s.activeProposal,
   475  			signer:     s.members[0],
   476  			valid:      true,
   477  			events:     sdk.Events{{Type: "coin_spent", Attributes: []abci.EventAttribute{{Key: []uint8{0x73, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x6d, 0x61, 0x66, 0x6c, 0x38, 0x66, 0x33, 0x73, 0x36, 0x75, 0x75, 0x7a, 0x77, 0x6e, 0x78, 0x6b, 0x71, 0x7a, 0x30, 0x65, 0x7a, 0x61, 0x34, 0x37, 0x76, 0x36, 0x65, 0x63, 0x6e, 0x30, 0x74, 0x75, 0x77, 0x72, 0x36, 0x79, 0x6b}, Index: false}, {Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x73, 0x74, 0x61, 0x6b, 0x65}, Index: false}}}, {Type: "coin_received", Attributes: []abci.EventAttribute{{Key: []uint8{0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34}, Index: false}, {Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x73, 0x74, 0x61, 0x6b, 0x65}, Index: false}}}, {Type: "transfer", Attributes: []abci.EventAttribute{{Key: []uint8{0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34}, Index: false}, {Key: []uint8{0x73, 0x65, 0x6e, 0x64, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x6d, 0x61, 0x66, 0x6c, 0x38, 0x66, 0x33, 0x73, 0x36, 0x75, 0x75, 0x7a, 0x77, 0x6e, 0x78, 0x6b, 0x71, 0x7a, 0x30, 0x65, 0x7a, 0x61, 0x34, 0x37, 0x76, 0x36, 0x65, 0x63, 0x6e, 0x30, 0x74, 0x75, 0x77, 0x72, 0x36, 0x79, 0x6b}, Index: false}, {Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x73, 0x74, 0x61, 0x6b, 0x65}, Index: false}}}, {Type: "lbm.foundation.v1.EventWithdrawFromTreasury", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x5b, 0x7b, 0x22, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x22, 0x3a, 0x22, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x22, 0x7d, 0x5d}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34, 0x22}, Index: false}}}, {Type: "lbm.foundation.v1.EventExec", Attributes: []abci.EventAttribute{{Key: []uint8{0x6c, 0x6f, 0x67, 0x73}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x22}, Index: false}, {Key: []uint8{0x72, 0x65, 0x73, 0x75, 0x6c, 0x74}, Value: []uint8{0x22, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x22}, Index: false}}}},
   478  		},
   479  		"valid request (not finalized)": {
   480  			proposalID: s.votedProposal,
   481  			signer:     s.members[0],
   482  			valid:      true,
   483  			events:     sdk.Events{{Type: "lbm.foundation.v1.EventExec", Attributes: []abci.EventAttribute{{Key: []uint8{0x6c, 0x6f, 0x67, 0x73}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x32, 0x22}, Index: false}, {Key: []uint8{0x72, 0x65, 0x73, 0x75, 0x6c, 0x74}, Value: []uint8{0x22, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x52, 0x55, 0x4e, 0x22}, Index: false}}}},
   484  		},
   485  		"not authorized": {
   486  			proposalID: s.votedProposal,
   487  			signer:     s.stranger,
   488  		},
   489  		"no such a proposal": {
   490  			proposalID: s.nextProposal,
   491  			signer:     s.members[0],
   492  		},
   493  	}
   494  
   495  	for name, tc := range testCases {
   496  		s.Run(name, func() {
   497  			ctx, _ := s.ctx.CacheContext()
   498  
   499  			req := &foundation.MsgExec{
   500  				ProposalId: tc.proposalID,
   501  				Signer:     tc.signer.String(),
   502  			}
   503  			res, err := s.msgServer.Exec(sdk.WrapSDKContext(ctx), req)
   504  			if !tc.valid {
   505  				s.Require().Error(err)
   506  				return
   507  			}
   508  			s.Require().NoError(err)
   509  
   510  			s.Require().NotNil(res)
   511  
   512  			if s.deterministic {
   513  				s.Require().Equal(tc.events, ctx.EventManager().Events())
   514  			}
   515  		})
   516  	}
   517  }
   518  
   519  func (s *KeeperTestSuite) TestMsgLeaveFoundation() {
   520  	testCases := map[string]struct {
   521  		malleate func(ctx sdk.Context)
   522  		address  sdk.AccAddress
   523  		valid    bool
   524  		events   sdk.Events
   525  	}{
   526  		"valid request": {
   527  			address: s.members[0],
   528  			valid:   true,
   529  			events:  sdk.Events{{Type: "lbm.foundation.v1.EventLeaveFoundation", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}}}},
   530  		},
   531  		"not authorized": {
   532  			address: s.stranger,
   533  		},
   534  		"policy violation": {
   535  			malleate: func(ctx sdk.Context) {
   536  				// remove all members but the first one
   537  				// preset policy is a threshold policy with its threshold 1
   538  				requests := make([]foundation.MemberRequest, len(s.members)-1)
   539  				for i, member := range s.members[1:] {
   540  					requests[i] = foundation.MemberRequest{
   541  						Address: member.String(),
   542  						Remove:  true,
   543  					}
   544  				}
   545  				err := s.impl.UpdateMembers(ctx, requests)
   546  				s.Require().NoError(err)
   547  			},
   548  			address: s.members[0],
   549  		},
   550  	}
   551  
   552  	for name, tc := range testCases {
   553  		s.Run(name, func() {
   554  			ctx, _ := s.ctx.CacheContext()
   555  			if tc.malleate != nil {
   556  				tc.malleate(ctx)
   557  			}
   558  
   559  			req := &foundation.MsgLeaveFoundation{
   560  				Address: tc.address.String(),
   561  			}
   562  			res, err := s.msgServer.LeaveFoundation(sdk.WrapSDKContext(ctx), req)
   563  			if !tc.valid {
   564  				s.Require().Error(err)
   565  				return
   566  			}
   567  			s.Require().NoError(err)
   568  
   569  			s.Require().NotNil(res)
   570  
   571  			if s.deterministic {
   572  				s.Require().Equal(tc.events, ctx.EventManager().Events())
   573  			}
   574  		})
   575  	}
   576  }
   577  
   578  func (s *KeeperTestSuite) TestMsgUpdateCensorship() {
   579  	testCases := map[string]struct {
   580  		authority  sdk.AccAddress
   581  		censorship foundation.Censorship
   582  		valid      bool
   583  		events     sdk.Events
   584  	}{
   585  		"valid request": {
   586  			authority: s.authority,
   587  			censorship: foundation.Censorship{
   588  				MsgTypeUrl: sdk.MsgTypeURL((*foundation.MsgWithdrawFromTreasury)(nil)),
   589  				Authority:  foundation.CensorshipAuthorityGovernance,
   590  			},
   591  			valid:  true,
   592  			events: sdk.Events{{Type: "lbm.foundation.v1.EventUpdateCensorship", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70}, Value: []uint8{0x7b, 0x22, 0x6d, 0x73, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x22, 0x3a, 0x22, 0x2f, 0x6c, 0x62, 0x6d, 0x2e, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x6f, 0x6d, 0x54, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x79, 0x22, 0x2c, 0x22, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x43, 0x45, 0x4e, 0x53, 0x4f, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x47, 0x4f, 0x56, 0x45, 0x52, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x22, 0x7d}, Index: false}}}},
   593  		},
   594  		"invalid authority": {
   595  			authority: s.stranger,
   596  			censorship: foundation.Censorship{
   597  				MsgTypeUrl: sdk.MsgTypeURL((*foundation.MsgWithdrawFromTreasury)(nil)),
   598  				Authority:  foundation.CensorshipAuthorityGovernance,
   599  			},
   600  		},
   601  		"enabling feature": {
   602  			authority: s.authority,
   603  			censorship: foundation.Censorship{
   604  				MsgTypeUrl: sdk.MsgTypeURL((*testdata.TestMsg)(nil)),
   605  				Authority:  foundation.CensorshipAuthorityFoundation,
   606  			},
   607  		},
   608  	}
   609  
   610  	for name, tc := range testCases {
   611  		s.Run(name, func() {
   612  			ctx, _ := s.ctx.CacheContext()
   613  
   614  			req := &foundation.MsgUpdateCensorship{
   615  				Authority:  tc.authority.String(),
   616  				Censorship: tc.censorship,
   617  			}
   618  			res, err := s.msgServer.UpdateCensorship(sdk.WrapSDKContext(ctx), req)
   619  			if !tc.valid {
   620  				s.Require().Error(err)
   621  				return
   622  			}
   623  			s.Require().NoError(err)
   624  
   625  			s.Require().NotNil(res)
   626  
   627  			if s.deterministic {
   628  				s.Require().Equal(tc.events, ctx.EventManager().Events())
   629  			}
   630  		})
   631  	}
   632  }
   633  
   634  func (s *KeeperTestSuite) TestMsgGrant() {
   635  	testCases := map[string]struct {
   636  		authority     sdk.AccAddress
   637  		grantee       sdk.AccAddress
   638  		authorization foundation.Authorization
   639  		valid         bool
   640  		events        sdk.Events
   641  	}{
   642  		"valid request": {
   643  			authority:     s.authority,
   644  			grantee:       s.members[0],
   645  			authorization: &foundation.ReceiveFromTreasuryAuthorization{},
   646  			valid:         true,
   647  			events:        sdk.Events{{Type: "lbm.foundation.v1.EventGrant", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e}, Value: []uint8{0x7b, 0x22, 0x40, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x2f, 0x6c, 0x62, 0x6d, 0x2e, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x54, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x79, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x7d}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}}}},
   648  		},
   649  		"not authorized": {
   650  			authority:     s.stranger,
   651  			grantee:       s.members[0],
   652  			authorization: &foundation.ReceiveFromTreasuryAuthorization{},
   653  		},
   654  		"already granted": {
   655  			authority:     s.authority,
   656  			grantee:       s.stranger,
   657  			authorization: &foundation.ReceiveFromTreasuryAuthorization{},
   658  		},
   659  	}
   660  
   661  	for name, tc := range testCases {
   662  		s.Run(name, func() {
   663  			ctx, _ := s.ctx.CacheContext()
   664  
   665  			req := &foundation.MsgGrant{
   666  				Authority: tc.authority.String(),
   667  				Grantee:   tc.grantee.String(),
   668  			}
   669  			err := req.SetAuthorization(tc.authorization)
   670  			s.Require().NoError(err)
   671  
   672  			res, err := s.msgServer.Grant(sdk.WrapSDKContext(ctx), req)
   673  			if !tc.valid {
   674  				s.Require().Error(err)
   675  				return
   676  			}
   677  			s.Require().NoError(err)
   678  
   679  			s.Require().NotNil(res)
   680  
   681  			if s.deterministic {
   682  				s.Require().Equal(tc.events, ctx.EventManager().Events())
   683  			}
   684  		})
   685  	}
   686  }
   687  
   688  func (s *KeeperTestSuite) TestMsgRevoke() {
   689  	testCases := map[string]struct {
   690  		authority  sdk.AccAddress
   691  		grantee    sdk.AccAddress
   692  		msgTypeURL string
   693  		valid      bool
   694  		events     sdk.Events
   695  	}{
   696  		"valid request": {
   697  			authority:  s.authority,
   698  			grantee:    s.stranger,
   699  			msgTypeURL: foundation.ReceiveFromTreasuryAuthorization{}.MsgTypeURL(),
   700  			valid:      true,
   701  			events:     sdk.Events{{Type: "lbm.foundation.v1.EventRevoke", Attributes: []abci.EventAttribute{{Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x76, 0x71, 0x78, 0x6c, 0x68, 0x74, 0x66, 0x34, 0x22}, Index: false}, {Key: []uint8{0x6d, 0x73, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x72, 0x6c}, Value: []uint8{0x22, 0x2f, 0x6c, 0x62, 0x6d, 0x2e, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x6f, 0x6d, 0x54, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x79, 0x22}, Index: false}}}},
   702  		},
   703  		"not authorized": {
   704  			authority:  s.stranger,
   705  			grantee:    s.stranger,
   706  			msgTypeURL: foundation.ReceiveFromTreasuryAuthorization{}.MsgTypeURL(),
   707  		},
   708  		"no grant": {
   709  			authority:  s.authority,
   710  			grantee:    s.members[0],
   711  			msgTypeURL: foundation.ReceiveFromTreasuryAuthorization{}.MsgTypeURL(),
   712  		},
   713  	}
   714  
   715  	for name, tc := range testCases {
   716  		s.Run(name, func() {
   717  			ctx, _ := s.ctx.CacheContext()
   718  
   719  			req := &foundation.MsgRevoke{
   720  				Authority:  tc.authority.String(),
   721  				Grantee:    tc.grantee.String(),
   722  				MsgTypeUrl: tc.msgTypeURL,
   723  			}
   724  			res, err := s.msgServer.Revoke(sdk.WrapSDKContext(ctx), req)
   725  			if !tc.valid {
   726  				s.Require().Error(err)
   727  				return
   728  			}
   729  			s.Require().NoError(err)
   730  
   731  			s.Require().NotNil(res)
   732  
   733  			if s.deterministic {
   734  				s.Require().Equal(tc.events, ctx.EventManager().Events())
   735  			}
   736  		})
   737  	}
   738  }