github.com/cosmos/cosmos-sdk@v0.50.10/x/authz/keeper/msg_server_test.go (about) 1 package keeper_test 2 3 import ( 4 "time" 5 6 "github.com/golang/mock/gomock" 7 8 sdkmath "cosmossdk.io/math" 9 10 "github.com/cosmos/cosmos-sdk/codec/address" 11 simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" 12 sdk "github.com/cosmos/cosmos-sdk/types" 13 authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 14 "github.com/cosmos/cosmos-sdk/x/authz" 15 banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 16 ) 17 18 func (suite *TestSuite) createAccounts(accs int) []sdk.AccAddress { 19 addrs := simtestutil.CreateIncrementalAccounts(2) 20 suite.accountKeeper.EXPECT().GetAccount(gomock.Any(), suite.addrs[0]).Return(authtypes.NewBaseAccountWithAddress(suite.addrs[0])).AnyTimes() 21 suite.accountKeeper.EXPECT().GetAccount(gomock.Any(), suite.addrs[1]).Return(authtypes.NewBaseAccountWithAddress(suite.addrs[1])).AnyTimes() 22 return addrs 23 } 24 25 func (suite *TestSuite) TestGrant() { 26 ctx := suite.ctx.WithBlockTime(time.Now()) 27 addrs := suite.createAccounts(2) 28 curBlockTime := ctx.BlockTime() 29 30 suite.accountKeeper.EXPECT().AddressCodec().Return(address.NewBech32Codec("cosmos")).AnyTimes() 31 32 oneHour := curBlockTime.Add(time.Hour) 33 oneYear := curBlockTime.AddDate(1, 0, 0) 34 35 coins := sdk.NewCoins(sdk.NewCoin("steak", sdkmath.NewInt(10))) 36 37 grantee, granter := addrs[0], addrs[1] 38 39 testCases := []struct { 40 name string 41 malleate func() *authz.MsgGrant 42 expErr bool 43 errMsg string 44 }{ 45 { 46 name: "identical grantee and granter", 47 malleate: func() *authz.MsgGrant { 48 grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil), &oneYear) 49 suite.Require().NoError(err) 50 return &authz.MsgGrant{ 51 Granter: grantee.String(), 52 Grantee: grantee.String(), 53 Grant: grant, 54 } 55 }, 56 expErr: true, 57 errMsg: "grantee and granter should be different", 58 }, 59 { 60 name: "invalid granter", 61 malleate: func() *authz.MsgGrant { 62 grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil), &oneYear) 63 suite.Require().NoError(err) 64 return &authz.MsgGrant{ 65 Granter: "invalid", 66 Grantee: grantee.String(), 67 Grant: grant, 68 } 69 }, 70 expErr: true, 71 errMsg: "invalid bech32 string", 72 }, 73 { 74 name: "invalid grantee", 75 malleate: func() *authz.MsgGrant { 76 grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil), &oneYear) 77 suite.Require().NoError(err) 78 return &authz.MsgGrant{ 79 Granter: granter.String(), 80 Grantee: "invalid", 81 Grant: grant, 82 } 83 }, 84 expErr: true, 85 errMsg: "invalid bech32 string", 86 }, 87 { 88 name: "invalid grant", 89 malleate: func() *authz.MsgGrant { 90 return &authz.MsgGrant{ 91 Granter: granter.String(), 92 Grantee: grantee.String(), 93 Grant: authz.Grant{ 94 Expiration: &oneYear, 95 }, 96 } 97 }, 98 expErr: true, 99 errMsg: "authorization is nil: invalid type", 100 }, 101 { 102 name: "invalid grant, past time", 103 malleate: func() *authz.MsgGrant { 104 pastTime := curBlockTime.Add(-time.Hour) 105 grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil), &oneHour) // we only need the authorization 106 suite.Require().NoError(err) 107 return &authz.MsgGrant{ 108 Granter: granter.String(), 109 Grantee: grantee.String(), 110 Grant: authz.Grant{ 111 Authorization: grant.Authorization, 112 Expiration: &pastTime, 113 }, 114 } 115 }, 116 expErr: true, 117 errMsg: "expiration must be after the current block time", 118 }, 119 { 120 name: "grantee account does not exist on chain: valid grant", 121 malleate: func() *authz.MsgGrant { 122 newAcc := sdk.AccAddress("valid") 123 suite.accountKeeper.EXPECT().GetAccount(gomock.Any(), newAcc).Return(nil).AnyTimes() 124 acc := authtypes.NewBaseAccountWithAddress(newAcc) 125 suite.accountKeeper.EXPECT().NewAccountWithAddress(gomock.Any(), newAcc).Return(acc).AnyTimes() 126 suite.accountKeeper.EXPECT().SetAccount(gomock.Any(), acc).Return() 127 128 grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil), &oneYear) 129 suite.Require().NoError(err) 130 return &authz.MsgGrant{ 131 Granter: granter.String(), 132 Grantee: newAcc.String(), 133 Grant: grant, 134 } 135 }, 136 }, 137 { 138 name: "valid grant", 139 malleate: func() *authz.MsgGrant { 140 grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil), &oneYear) 141 suite.Require().NoError(err) 142 return &authz.MsgGrant{ 143 Granter: granter.String(), 144 Grantee: grantee.String(), 145 Grant: grant, 146 } 147 }, 148 }, 149 { 150 name: "valid grant, same grantee, granter pair but different msgType", 151 malleate: func() *authz.MsgGrant { 152 g, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil), &oneHour) 153 suite.Require().NoError(err) 154 _, err = suite.msgSrvr.Grant(suite.ctx, &authz.MsgGrant{ 155 Granter: granter.String(), 156 Grantee: grantee.String(), 157 Grant: g, 158 }) 159 suite.Require().NoError(err) 160 161 grant, err := authz.NewGrant(curBlockTime, authz.NewGenericAuthorization("/cosmos.bank.v1beta1.MsgUpdateParams"), &oneHour) 162 suite.Require().NoError(err) 163 return &authz.MsgGrant{ 164 Granter: granter.String(), 165 Grantee: grantee.String(), 166 Grant: grant, 167 } 168 }, 169 }, 170 { 171 name: "valid grant with allow list", 172 malleate: func() *authz.MsgGrant { 173 grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, []sdk.AccAddress{granter}), &oneYear) 174 suite.Require().NoError(err) 175 return &authz.MsgGrant{ 176 Granter: granter.String(), 177 Grantee: grantee.String(), 178 Grant: grant, 179 } 180 }, 181 }, 182 { 183 name: "valid grant with nil expiration time", 184 malleate: func() *authz.MsgGrant { 185 grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil), nil) 186 suite.Require().NoError(err) 187 return &authz.MsgGrant{ 188 Granter: granter.String(), 189 Grantee: grantee.String(), 190 Grant: grant, 191 } 192 }, 193 }, 194 } 195 196 for _, tc := range testCases { 197 suite.Run(tc.name, func() { 198 _, err := suite.msgSrvr.Grant(suite.ctx, tc.malleate()) 199 if tc.expErr { 200 suite.Require().Error(err) 201 suite.Require().Contains(err.Error(), tc.errMsg) 202 } else { 203 suite.Require().NoError(err) 204 } 205 }) 206 } 207 } 208 209 func (suite *TestSuite) TestRevoke() { 210 addrs := suite.createAccounts(2) 211 212 grantee, granter := addrs[0], addrs[1] 213 214 testCases := []struct { 215 name string 216 malleate func() *authz.MsgRevoke 217 expErr bool 218 errMsg string 219 }{ 220 { 221 name: "identical grantee and granter", 222 malleate: func() *authz.MsgRevoke { 223 return &authz.MsgRevoke{ 224 Granter: grantee.String(), 225 Grantee: grantee.String(), 226 MsgTypeUrl: bankSendAuthMsgType, 227 } 228 }, 229 expErr: true, 230 errMsg: "grantee and granter should be different", 231 }, 232 { 233 name: "invalid granter", 234 malleate: func() *authz.MsgRevoke { 235 return &authz.MsgRevoke{ 236 Granter: "invalid", 237 Grantee: grantee.String(), 238 MsgTypeUrl: bankSendAuthMsgType, 239 } 240 }, 241 expErr: true, 242 errMsg: "invalid bech32 string", 243 }, 244 { 245 name: "invalid grantee", 246 malleate: func() *authz.MsgRevoke { 247 return &authz.MsgRevoke{ 248 Granter: granter.String(), 249 Grantee: "invalid", 250 MsgTypeUrl: bankSendAuthMsgType, 251 } 252 }, 253 expErr: true, 254 errMsg: "invalid bech32 string", 255 }, 256 { 257 name: "no msg given", 258 malleate: func() *authz.MsgRevoke { 259 return &authz.MsgRevoke{ 260 Granter: granter.String(), 261 Grantee: grantee.String(), 262 MsgTypeUrl: "", 263 } 264 }, 265 expErr: true, 266 errMsg: "missing msg method name", 267 }, 268 { 269 name: "valid grant", 270 malleate: func() *authz.MsgRevoke { 271 suite.createSendAuthorization(grantee, granter) 272 273 return &authz.MsgRevoke{ 274 Granter: granter.String(), 275 Grantee: grantee.String(), 276 MsgTypeUrl: bankSendAuthMsgType, 277 } 278 }, 279 }, 280 { 281 name: "no existing grant to revoke", 282 malleate: func() *authz.MsgRevoke { 283 return &authz.MsgRevoke{ 284 Granter: granter.String(), 285 Grantee: grantee.String(), 286 MsgTypeUrl: bankSendAuthMsgType, 287 } 288 }, 289 expErr: true, 290 errMsg: "authorization not found", 291 }, 292 } 293 294 for _, tc := range testCases { 295 suite.Run(tc.name, func() { 296 _, err := suite.msgSrvr.Revoke(suite.ctx, tc.malleate()) 297 if tc.expErr { 298 suite.Require().Error(err) 299 suite.Require().Contains(err.Error(), tc.errMsg) 300 } else { 301 suite.Require().NoError(err) 302 } 303 }) 304 } 305 } 306 307 func (suite *TestSuite) TestExec() { 308 addrs := suite.createAccounts(2) 309 310 grantee, granter := addrs[0], addrs[1] 311 coins := sdk.NewCoins(sdk.NewCoin("steak", sdkmath.NewInt(10))) 312 313 msg := &banktypes.MsgSend{ 314 FromAddress: granter.String(), 315 ToAddress: grantee.String(), 316 Amount: coins, 317 } 318 319 testCases := []struct { 320 name string 321 malleate func() authz.MsgExec 322 expErr bool 323 errMsg string 324 }{ 325 { 326 name: "invalid grantee (empty)", 327 malleate: func() authz.MsgExec { 328 return authz.NewMsgExec(sdk.AccAddress{}, []sdk.Msg{msg}) 329 }, 330 expErr: true, 331 errMsg: "empty address string is not allowed", 332 }, 333 { 334 name: "non existing grant", 335 malleate: func() authz.MsgExec { 336 return authz.NewMsgExec(grantee, []sdk.Msg{msg}) 337 }, 338 expErr: true, 339 errMsg: "authorization not found", 340 }, 341 { 342 name: "no message case", 343 malleate: func() authz.MsgExec { 344 return authz.NewMsgExec(grantee, []sdk.Msg{}) 345 }, 346 expErr: true, 347 errMsg: "messages cannot be empty", 348 }, 349 { 350 name: "valid case", 351 malleate: func() authz.MsgExec { 352 suite.createSendAuthorization(grantee, granter) 353 return authz.NewMsgExec(grantee, []sdk.Msg{msg}) 354 }, 355 }, 356 } 357 358 for _, tc := range testCases { 359 suite.Run(tc.name, func() { 360 req := tc.malleate() 361 _, err := suite.msgSrvr.Exec(suite.ctx, &req) 362 if tc.expErr { 363 suite.Require().Error(err) 364 suite.Require().Contains(err.Error(), tc.errMsg) 365 } else { 366 suite.Require().NoError(err) 367 } 368 }) 369 } 370 }