github.com/cosmos/cosmos-sdk@v0.50.10/x/authz/client/cli/tx_test.go (about)

     1  package cli_test
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"testing"
     7  	"time"
     8  
     9  	abci "github.com/cometbft/cometbft/abci/types"
    10  	rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock"
    11  	"github.com/cosmos/gogoproto/proto"
    12  	"github.com/stretchr/testify/suite"
    13  
    14  	_ "cosmossdk.io/api/cosmos/authz/v1beta1"
    15  	"cosmossdk.io/core/address"
    16  	sdkmath "cosmossdk.io/math"
    17  
    18  	"github.com/cosmos/cosmos-sdk/client"
    19  	"github.com/cosmos/cosmos-sdk/client/flags"
    20  	addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
    21  	"github.com/cosmos/cosmos-sdk/crypto/hd"
    22  	"github.com/cosmos/cosmos-sdk/crypto/keyring"
    23  	"github.com/cosmos/cosmos-sdk/testutil"
    24  	clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
    25  	sdk "github.com/cosmos/cosmos-sdk/types"
    26  	testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil"
    27  	"github.com/cosmos/cosmos-sdk/x/authz/client/cli"
    28  	authzclitestutil "github.com/cosmos/cosmos-sdk/x/authz/client/testutil"
    29  	"github.com/cosmos/cosmos-sdk/x/bank"
    30  	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
    31  	"github.com/cosmos/cosmos-sdk/x/gov"
    32  	govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli"
    33  	govclitestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil"
    34  	govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
    35  	govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
    36  )
    37  
    38  var (
    39  	typeMsgSend           = banktypes.SendAuthorization{}.MsgTypeURL()
    40  	typeMsgVote           = sdk.MsgTypeURL(&govv1.MsgVote{})
    41  	typeMsgSubmitProposal = sdk.MsgTypeURL(&govv1.MsgSubmitProposal{})
    42  )
    43  
    44  type CLITestSuite struct {
    45  	suite.Suite
    46  
    47  	kr        keyring.Keyring
    48  	encCfg    testutilmod.TestEncodingConfig
    49  	baseCtx   client.Context
    50  	clientCtx client.Context
    51  	grantee   []sdk.AccAddress
    52  	addrs     []sdk.AccAddress
    53  
    54  	ac address.Codec
    55  }
    56  
    57  func TestCLITestSuite(t *testing.T) {
    58  	suite.Run(t, new(CLITestSuite))
    59  }
    60  
    61  func (s *CLITestSuite) SetupSuite() {
    62  	s.encCfg = testutilmod.MakeTestEncodingConfig(gov.AppModuleBasic{}, bank.AppModuleBasic{})
    63  	s.kr = keyring.NewInMemory(s.encCfg.Codec)
    64  	s.baseCtx = client.Context{}.
    65  		WithKeyring(s.kr).
    66  		WithTxConfig(s.encCfg.TxConfig).
    67  		WithCodec(s.encCfg.Codec).
    68  		WithClient(clitestutil.MockCometRPC{Client: rpcclientmock.Client{}}).
    69  		WithAccountRetriever(client.MockAccountRetriever{}).
    70  		WithOutput(io.Discard).
    71  		WithChainID("test-chain")
    72  
    73  	s.ac = addresscodec.NewBech32Codec("cosmos")
    74  
    75  	ctxGen := func() client.Context {
    76  		bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{})
    77  		c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
    78  			Value: bz,
    79  		})
    80  		return s.baseCtx.WithClient(c)
    81  	}
    82  	s.clientCtx = ctxGen()
    83  
    84  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
    85  	s.grantee = make([]sdk.AccAddress, 6)
    86  
    87  	s.addrs = make([]sdk.AccAddress, 1)
    88  	s.addrs[0] = s.createAccount("validator address")
    89  
    90  	// Send some funds to the new account.
    91  	// Create new account in the keyring.
    92  	s.grantee[0] = s.createAccount("grantee1")
    93  	s.msgSendExec(s.grantee[0])
    94  
    95  	// create a proposal with deposit
    96  	_, err := govclitestutil.MsgSubmitLegacyProposal(s.clientCtx, val[0].Address.String(),
    97  		"Text Proposal 1", "Where is the title!?", govv1beta1.ProposalTypeText,
    98  		fmt.Sprintf("--%s=%s", govcli.FlagDeposit, sdk.NewCoin("stake", govv1.DefaultMinDepositTokens).String()))
    99  	s.Require().NoError(err)
   100  
   101  	// Create new account in the keyring.
   102  	s.grantee[1] = s.createAccount("grantee2")
   103  	// Send some funds to the new account.
   104  	s.msgSendExec(s.grantee[1])
   105  
   106  	// grant send authorization to grantee2
   107  	out, err := authzclitestutil.CreateGrant(s.clientCtx, []string{
   108  		s.grantee[1].String(),
   109  		"send",
   110  		fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
   111  		fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   112  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   113  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   114  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(10))).String()),
   115  		fmt.Sprintf("--%s=%d", cli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix()),
   116  	})
   117  	s.Require().NoError(err)
   118  
   119  	var response sdk.TxResponse
   120  	s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
   121  
   122  	// Create new account in the keyring.
   123  	s.grantee[2] = s.createAccount("grantee3")
   124  
   125  	// grant send authorization to grantee3
   126  	_, err = authzclitestutil.CreateGrant(s.clientCtx, []string{
   127  		s.grantee[2].String(),
   128  		"send",
   129  		fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
   130  		fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   131  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   132  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   133  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(10))).String()),
   134  		fmt.Sprintf("--%s=%d", cli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix()),
   135  	})
   136  	s.Require().NoError(err)
   137  
   138  	// Create new accounts in the keyring.
   139  	s.grantee[3] = s.createAccount("grantee4")
   140  	s.msgSendExec(s.grantee[3])
   141  
   142  	s.grantee[4] = s.createAccount("grantee5")
   143  	s.grantee[5] = s.createAccount("grantee6")
   144  
   145  	// grant send authorization with allow list to grantee4
   146  	out, err = authzclitestutil.CreateGrant(s.clientCtx,
   147  		[]string{
   148  			s.grantee[3].String(),
   149  			"send",
   150  			fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
   151  			fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   152  			fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   153  			fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   154  			fmt.Sprintf("--%s=%d", cli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix()),
   155  			fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   156  			fmt.Sprintf("--%s=%s", cli.FlagAllowList, s.grantee[4]),
   157  		},
   158  	)
   159  	s.Require().NoError(err)
   160  	s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
   161  }
   162  
   163  func (s *CLITestSuite) createAccount(uid string) sdk.AccAddress {
   164  	// Create new account in the keyring.
   165  	k, _, err := s.clientCtx.Keyring.NewMnemonic(uid, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
   166  	s.Require().NoError(err)
   167  
   168  	addr, err := k.GetAddress()
   169  	s.Require().NoError(err)
   170  
   171  	return addr
   172  }
   173  
   174  func (s *CLITestSuite) msgSendExec(grantee sdk.AccAddress) {
   175  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
   176  	// Send some funds to the new account.
   177  	s.ac.StringToBytes("cosmos16zex22087zs656t0vedytv5wqhm6axxd5679ry")
   178  	out, err := clitestutil.MsgSendExec(
   179  		s.clientCtx,
   180  		val[0].Address,
   181  		grantee,
   182  		sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(200))),
   183  		s.ac,
   184  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   185  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   186  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   187  	)
   188  	s.Require().NoError(err)
   189  	s.Require().Contains(out.String(), `"code":0`)
   190  }
   191  
   192  func (s *CLITestSuite) TestCLITxGrantAuthorization() {
   193  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
   194  
   195  	grantee := s.grantee[0]
   196  
   197  	twoHours := time.Now().Add(time.Minute * 120).Unix()
   198  	pastHour := time.Now().Add(-time.Minute * 60).Unix()
   199  
   200  	testCases := []struct {
   201  		name      string
   202  		args      []string
   203  		expectErr bool
   204  		expErrMsg string
   205  	}{
   206  		{
   207  			"Invalid granter Address",
   208  			[]string{
   209  				"grantee_addr",
   210  				"send",
   211  				fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
   212  				fmt.Sprintf("--%s=%s", flags.FlagFrom, "granter"),
   213  				fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
   214  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   215  			},
   216  			true,
   217  			"key not found",
   218  		},
   219  		{
   220  			"Invalid grantee Address",
   221  			[]string{
   222  				"grantee_addr",
   223  				"send",
   224  				fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
   225  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   226  				fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
   227  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   228  			},
   229  			true,
   230  			"invalid separator index",
   231  		},
   232  		{
   233  			"Invalid spend limit",
   234  			[]string{
   235  				grantee.String(),
   236  				"send",
   237  				fmt.Sprintf("--%s=0stake", cli.FlagSpendLimit),
   238  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   239  				fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
   240  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   241  			},
   242  			true,
   243  			"spend-limit should be greater than zero",
   244  		},
   245  		{
   246  			"Invalid expiration time",
   247  			[]string{
   248  				grantee.String(),
   249  				"send",
   250  				fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
   251  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   252  				fmt.Sprintf("--%s=true", flags.FlagBroadcastMode),
   253  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, pastHour),
   254  			},
   255  			true,
   256  			"",
   257  		},
   258  		{
   259  			"fail with error invalid msg-type",
   260  			[]string{
   261  				grantee.String(),
   262  				"generic",
   263  				fmt.Sprintf("--%s=invalid-msg-type", cli.FlagMsgType),
   264  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   265  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   266  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   267  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   268  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   269  			},
   270  			false,
   271  			"",
   272  		},
   273  		{
   274  			"invalid bond denom for tx delegate authorization allowed validators",
   275  			[]string{
   276  				grantee.String(),
   277  				"delegate",
   278  				fmt.Sprintf("--%s=100xyz", cli.FlagSpendLimit),
   279  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   280  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   281  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   282  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   283  				fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, sdk.ValAddress(s.addrs[0]).String()),
   284  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   285  			},
   286  			true,
   287  			"invalid denom",
   288  		},
   289  		{
   290  			"invalid bond denom for tx delegate authorization deny validators",
   291  			[]string{
   292  				grantee.String(),
   293  				"delegate",
   294  				fmt.Sprintf("--%s=100xyz", cli.FlagSpendLimit),
   295  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   296  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   297  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   298  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   299  				fmt.Sprintf("--%s=%s", cli.FlagDenyValidators, sdk.ValAddress(s.addrs[0]).String()),
   300  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   301  			},
   302  			true,
   303  			"invalid denom",
   304  		},
   305  		{
   306  			"invalid bond denom for tx undelegate authorization",
   307  			[]string{
   308  				grantee.String(),
   309  				"unbond",
   310  				fmt.Sprintf("--%s=100xyz", cli.FlagSpendLimit),
   311  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   312  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   313  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   314  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   315  				fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, sdk.ValAddress(s.addrs[0]).String()),
   316  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   317  			},
   318  			true,
   319  			"invalid denom",
   320  		},
   321  		{
   322  			"invalid bond denom for tx redelegate authorization",
   323  			[]string{
   324  				grantee.String(),
   325  				"redelegate",
   326  				fmt.Sprintf("--%s=100xyz", cli.FlagSpendLimit),
   327  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   328  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   329  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   330  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   331  				fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, sdk.ValAddress(s.addrs[0]).String()),
   332  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   333  			},
   334  			true,
   335  			"invalid denom",
   336  		},
   337  		{
   338  			"invalid decimal coin expression with more than single coin",
   339  			[]string{
   340  				grantee.String(),
   341  				"delegate",
   342  				fmt.Sprintf("--%s=100stake,20xyz", cli.FlagSpendLimit),
   343  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   344  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   345  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   346  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   347  				fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, sdk.ValAddress(s.addrs[0]).String()),
   348  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   349  			},
   350  			true,
   351  			"invalid decimal coin expression",
   352  		},
   353  		{
   354  			"invalid authorization type",
   355  			[]string{
   356  				grantee.String(),
   357  				"invalid authz type",
   358  			},
   359  			true,
   360  			"invalid authorization type",
   361  		},
   362  		{
   363  			"Valid tx send authorization",
   364  			[]string{
   365  				grantee.String(),
   366  				"send",
   367  				fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
   368  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   369  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   370  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   371  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   372  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   373  			},
   374  			false,
   375  			"",
   376  		},
   377  		{
   378  			"Valid tx send authorization with allow list",
   379  			[]string{
   380  				grantee.String(),
   381  				"send",
   382  				fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
   383  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   384  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   385  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   386  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   387  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   388  				fmt.Sprintf("--%s=%s", cli.FlagAllowList, s.grantee[1]),
   389  			},
   390  			false,
   391  			"",
   392  		},
   393  		{
   394  			"Invalid tx send authorization with duplicate allow list",
   395  			[]string{
   396  				grantee.String(),
   397  				"send",
   398  				fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
   399  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   400  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   401  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   402  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   403  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   404  				fmt.Sprintf("--%s=%s", cli.FlagAllowList, fmt.Sprintf("%s,%s", s.grantee[1], s.grantee[1])),
   405  			},
   406  			true,
   407  			"duplicate address",
   408  		},
   409  		{
   410  			"Valid tx generic authorization",
   411  			[]string{
   412  				grantee.String(),
   413  				"generic",
   414  				fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote),
   415  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   416  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   417  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   418  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   419  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   420  			},
   421  			false,
   422  			"",
   423  		},
   424  		{
   425  			"fail when granter = grantee",
   426  			[]string{
   427  				grantee.String(),
   428  				"generic",
   429  				fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote),
   430  				fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()),
   431  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   432  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   433  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   434  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   435  			},
   436  			true,
   437  			"grantee and granter should be different",
   438  		},
   439  		{
   440  			"Valid tx with amino",
   441  			[]string{
   442  				grantee.String(),
   443  				"generic",
   444  				fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote),
   445  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   446  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   447  				fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   448  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   449  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   450  				fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
   451  			},
   452  			false,
   453  			"",
   454  		},
   455  	}
   456  
   457  	for _, tc := range testCases {
   458  		s.Run(tc.name, func() {
   459  			out, err := authzclitestutil.CreateGrant(s.clientCtx,
   460  				tc.args,
   461  			)
   462  			if tc.expectErr {
   463  				s.Require().Error(err, out)
   464  				s.Require().Contains(err.Error(), tc.expErrMsg)
   465  			} else {
   466  				var txResp sdk.TxResponse
   467  				s.Require().NoError(err)
   468  				s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String())
   469  			}
   470  		})
   471  	}
   472  }
   473  
   474  func (s *CLITestSuite) TestCmdRevokeAuthorizations() {
   475  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
   476  
   477  	grantee := s.grantee[0]
   478  	twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix()
   479  
   480  	// send-authorization
   481  	_, err := authzclitestutil.CreateGrant(s.clientCtx,
   482  		[]string{
   483  			grantee.String(),
   484  			"send",
   485  			fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
   486  			fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   487  			fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address),
   488  			fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   489  			fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   490  			fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   491  		},
   492  	)
   493  	s.Require().NoError(err)
   494  
   495  	// generic-authorization
   496  	_, err = authzclitestutil.CreateGrant(s.clientCtx,
   497  		[]string{
   498  			grantee.String(),
   499  			"generic",
   500  			fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote),
   501  			fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   502  			fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address),
   503  			fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   504  			fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   505  			fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   506  		},
   507  	)
   508  	s.Require().NoError(err)
   509  
   510  	// generic-authorization used for amino testing
   511  	_, err = authzclitestutil.CreateGrant(s.clientCtx,
   512  		[]string{
   513  			grantee.String(),
   514  			"generic",
   515  			fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgSubmitProposal),
   516  			fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   517  			fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address),
   518  			fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   519  			fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   520  			fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   521  			fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
   522  		},
   523  	)
   524  	s.Require().NoError(err)
   525  	testCases := []struct {
   526  		name      string
   527  		args      []string
   528  		respType  proto.Message
   529  		expectErr bool
   530  	}{
   531  		{
   532  			"invalid grantee address",
   533  			[]string{
   534  				"invalid grantee",
   535  				typeMsgSend,
   536  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   537  				fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
   538  			},
   539  			nil,
   540  			true,
   541  		},
   542  		{
   543  			"invalid granter address",
   544  			[]string{
   545  				grantee.String(),
   546  				typeMsgSend,
   547  				fmt.Sprintf("--%s=%s", flags.FlagFrom, "granter"),
   548  				fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
   549  			},
   550  			nil,
   551  			true,
   552  		},
   553  		{
   554  			"Valid tx send authorization",
   555  			[]string{
   556  				grantee.String(),
   557  				typeMsgSend,
   558  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   559  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   560  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   561  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   562  			},
   563  			&sdk.TxResponse{},
   564  			false,
   565  		},
   566  		{
   567  			"Valid tx generic authorization",
   568  			[]string{
   569  				grantee.String(),
   570  				typeMsgVote,
   571  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   572  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   573  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   574  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   575  			},
   576  			&sdk.TxResponse{},
   577  			false,
   578  		},
   579  		{
   580  			"Valid tx with amino",
   581  			[]string{
   582  				grantee.String(),
   583  				typeMsgSubmitProposal,
   584  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   585  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   586  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   587  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   588  				fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
   589  			},
   590  			&sdk.TxResponse{},
   591  			false,
   592  		},
   593  	}
   594  	for _, tc := range testCases {
   595  		tc := tc
   596  		s.Run(tc.name, func() {
   597  			cmd := cli.NewCmdRevokeAuthorization(addresscodec.NewBech32Codec("cosmos"))
   598  
   599  			out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
   600  			if tc.expectErr {
   601  				s.Require().Error(err)
   602  			} else {
   603  				s.Require().NoError(err)
   604  				s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   605  			}
   606  		})
   607  	}
   608  }
   609  
   610  func (s *CLITestSuite) TestExecAuthorizationWithExpiration() {
   611  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
   612  
   613  	grantee := s.grantee[0]
   614  	tenSeconds := time.Now().Add(time.Second * time.Duration(10)).Unix()
   615  
   616  	_, err := authzclitestutil.CreateGrant(s.clientCtx,
   617  		[]string{
   618  			grantee.String(),
   619  			"generic",
   620  			fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote),
   621  			fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   622  			fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   623  			fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   624  			fmt.Sprintf("--%s=%d", cli.FlagExpiration, tenSeconds),
   625  			fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   626  		},
   627  	)
   628  	s.Require().NoError(err)
   629  	// msg vote
   630  	voteTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.gov.v1.MsgVote","proposal_id":"1","voter":"%s","option":"VOTE_OPTION_YES"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val[0].Address.String())
   631  	execMsg := testutil.WriteToNewTempFile(s.T(), voteTx)
   632  	defer execMsg.Close()
   633  
   634  	// waiting for authorization to expire
   635  	time.Sleep(12 * time.Second)
   636  
   637  	cmd := cli.NewCmdExecAuthorization()
   638  
   639  	out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, []string{
   640  		execMsg.Name(),
   641  		fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()),
   642  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   643  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   644  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   645  	})
   646  	s.Require().NoError(err)
   647  	var response sdk.TxResponse
   648  	s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
   649  }
   650  
   651  func (s *CLITestSuite) TestNewExecGenericAuthorized() {
   652  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
   653  	grantee := s.grantee[0]
   654  	twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix()
   655  
   656  	_, err := authzclitestutil.CreateGrant(s.clientCtx,
   657  		[]string{
   658  			grantee.String(),
   659  			"generic",
   660  			fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote),
   661  			fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   662  			fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   663  			fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   664  			fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   665  			fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   666  		},
   667  	)
   668  	s.Require().NoError(err)
   669  
   670  	// msg vote
   671  	voteTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.gov.v1.MsgVote","proposal_id":"1","voter":"%s","option":"VOTE_OPTION_YES"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val[0].Address.String())
   672  	execMsg := testutil.WriteToNewTempFile(s.T(), voteTx)
   673  	defer execMsg.Close()
   674  
   675  	testCases := []struct {
   676  		name      string
   677  		args      []string
   678  		respType  proto.Message
   679  		expectErr bool
   680  	}{
   681  		{
   682  			"fail invalid grantee",
   683  			[]string{
   684  				execMsg.Name(),
   685  				fmt.Sprintf("--%s=%s", flags.FlagFrom, "grantee"),
   686  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   687  				fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
   688  			},
   689  			nil,
   690  			true,
   691  		},
   692  		{
   693  			"fail invalid json path",
   694  			[]string{
   695  				"/invalid/file.txt",
   696  				fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()),
   697  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   698  			},
   699  			nil,
   700  			true,
   701  		},
   702  		{
   703  			"valid txn",
   704  			[]string{
   705  				execMsg.Name(),
   706  				fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()),
   707  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   708  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   709  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   710  			},
   711  			&sdk.TxResponse{},
   712  			false,
   713  		},
   714  		{
   715  			"valid tx with amino",
   716  			[]string{
   717  				execMsg.Name(),
   718  				fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()),
   719  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   720  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   721  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   722  				fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
   723  			},
   724  			&sdk.TxResponse{},
   725  			false,
   726  		},
   727  	}
   728  
   729  	for _, tc := range testCases {
   730  		tc := tc
   731  		s.Run(tc.name, func() {
   732  			cmd := cli.NewCmdExecAuthorization()
   733  
   734  			out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
   735  			if tc.expectErr {
   736  				s.Require().Error(err)
   737  			} else {
   738  				s.Require().NoError(err)
   739  				s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   740  			}
   741  		})
   742  	}
   743  }
   744  
   745  func (s *CLITestSuite) TestNewExecGrantAuthorized() {
   746  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
   747  	grantee := s.grantee[0]
   748  	twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix()
   749  
   750  	_, err := authzclitestutil.CreateGrant(s.clientCtx,
   751  		[]string{
   752  			grantee.String(),
   753  			"send",
   754  			fmt.Sprintf("--%s=12testtoken", cli.FlagSpendLimit),
   755  			fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   756  			fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   757  			fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   758  			fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   759  			fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   760  		},
   761  	)
   762  	s.Require().NoError(err)
   763  
   764  	tokens := sdk.NewCoins(
   765  		sdk.NewCoin("testtoken", sdkmath.NewInt(12)),
   766  	)
   767  	normalGeneratedTx, err := clitestutil.MsgSendExec(
   768  		s.clientCtx,
   769  		val[0].Address,
   770  		grantee,
   771  		tokens,
   772  		s.ac,
   773  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   774  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   775  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   776  		fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
   777  	)
   778  	s.Require().NoError(err)
   779  	execMsg := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String())
   780  	defer execMsg.Close()
   781  
   782  	testCases := []struct {
   783  		name         string
   784  		args         []string
   785  		expectErr    bool
   786  		expectErrMsg string
   787  	}{
   788  		{
   789  			"valid txn",
   790  			[]string{
   791  				execMsg.Name(),
   792  				fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()),
   793  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   794  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   795  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   796  			},
   797  			false,
   798  			"",
   799  		},
   800  		{
   801  			"error over spent",
   802  			[]string{
   803  				execMsg.Name(),
   804  				fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()),
   805  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   806  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   807  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   808  			},
   809  			false,
   810  			"",
   811  		},
   812  	}
   813  
   814  	for _, tc := range testCases {
   815  		tc := tc
   816  		s.Run(tc.name, func() {
   817  			cmd := cli.NewCmdExecAuthorization()
   818  			clientCtx := s.clientCtx
   819  
   820  			var response sdk.TxResponse
   821  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   822  			switch {
   823  			case tc.expectErrMsg != "":
   824  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
   825  				s.Require().Contains(response.RawLog, tc.expectErrMsg)
   826  
   827  			case tc.expectErr:
   828  				s.Require().Error(err)
   829  
   830  			default:
   831  				s.Require().NoError(err)
   832  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
   833  			}
   834  		})
   835  	}
   836  }
   837  
   838  func (s *CLITestSuite) TestExecSendAuthzWithAllowList() {
   839  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
   840  	grantee := s.grantee[3]
   841  
   842  	allowedAddr := s.grantee[4]
   843  	notAllowedAddr := s.grantee[5]
   844  	twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix()
   845  
   846  	_, err := authzclitestutil.CreateGrant(s.clientCtx,
   847  		[]string{
   848  			grantee.String(),
   849  			"send",
   850  			fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
   851  			fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   852  			fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   853  			fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   854  			fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
   855  			fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   856  			fmt.Sprintf("--%s=%s", cli.FlagAllowList, allowedAddr),
   857  		},
   858  	)
   859  	s.Require().NoError(err)
   860  
   861  	tokens := sdk.NewCoins(
   862  		sdk.NewCoin("stake", sdkmath.NewInt(12)),
   863  	)
   864  
   865  	validGeneratedTx, err := clitestutil.MsgSendExec(
   866  		s.clientCtx,
   867  		val[0].Address,
   868  		allowedAddr,
   869  		tokens,
   870  		s.ac,
   871  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   872  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   873  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   874  		fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
   875  	)
   876  	s.Require().NoError(err)
   877  	execMsg := testutil.WriteToNewTempFile(s.T(), validGeneratedTx.String())
   878  	defer execMsg.Close()
   879  
   880  	invalidGeneratedTx, err := clitestutil.MsgSendExec(
   881  		s.clientCtx,
   882  		val[0].Address,
   883  		notAllowedAddr,
   884  		tokens,
   885  		s.ac,
   886  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   887  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   888  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   889  		fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
   890  	)
   891  	s.Require().NoError(err)
   892  	execMsg1 := testutil.WriteToNewTempFile(s.T(), invalidGeneratedTx.String())
   893  	defer execMsg1.Close()
   894  
   895  	// test sending to allowed address
   896  	args := []string{
   897  		execMsg.Name(),
   898  		fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()),
   899  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   900  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   901  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   902  	}
   903  	var response sdk.TxResponse
   904  	cmd := cli.NewCmdExecAuthorization()
   905  	out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, args)
   906  	s.Require().NoError(err)
   907  	s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
   908  
   909  	// test sending to not allowed address
   910  	args = []string{
   911  		execMsg1.Name(),
   912  		fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()),
   913  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   914  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   915  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   916  	}
   917  	out, err = clitestutil.ExecTestCLICmd(s.clientCtx, cmd, args)
   918  	s.Require().NoError(err)
   919  	s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String())
   920  }