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 }