github.com/Finschia/finschia-sdk@v0.49.1/x/authz/keeper/keeper_test.go (about) 1 package keeper_test 2 3 import ( 4 "testing" 5 "time" 6 7 octime "github.com/Finschia/ostracon/types/time" 8 "github.com/stretchr/testify/suite" 9 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 10 11 "github.com/Finschia/finschia-sdk/baseapp" 12 "github.com/Finschia/finschia-sdk/simapp" 13 sdk "github.com/Finschia/finschia-sdk/types" 14 "github.com/Finschia/finschia-sdk/x/authz" 15 banktypes "github.com/Finschia/finschia-sdk/x/bank/types" 16 ) 17 18 var bankSendAuthMsgType = banktypes.SendAuthorization{}.MsgTypeURL() 19 20 type TestSuite struct { 21 suite.Suite 22 23 app *simapp.SimApp 24 ctx sdk.Context 25 addrs []sdk.AccAddress 26 queryClient authz.QueryClient 27 } 28 29 func (s *TestSuite) SetupTest() { 30 app := simapp.Setup(false) 31 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 32 now := octime.Now() 33 ctx = ctx.WithBlockHeader(tmproto.Header{Time: now}) 34 queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry()) 35 authz.RegisterQueryServer(queryHelper, app.AuthzKeeper) 36 queryClient := authz.NewQueryClient(queryHelper) 37 s.queryClient = queryClient 38 39 s.app = app 40 s.ctx = ctx 41 s.queryClient = queryClient 42 s.addrs = simapp.AddTestAddrsIncremental(app, ctx, 3, sdk.NewInt(30000000)) 43 } 44 45 func (s *TestSuite) TestKeeper() { 46 app, ctx, addrs := s.app, s.ctx, s.addrs 47 48 granterAddr := addrs[0] 49 granteeAddr := addrs[1] 50 recipientAddr := addrs[2] 51 52 s.T().Log("verify that no authorization returns nil") 53 authorization, expiration := app.AuthzKeeper.GetCleanAuthorization(ctx, granteeAddr, granterAddr, bankSendAuthMsgType) 54 s.Require().Nil(authorization) 55 s.Require().Equal(expiration, time.Time{}) 56 now := s.ctx.BlockHeader().Time 57 s.Require().NotNil(now) 58 59 newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) 60 s.T().Log("verify if expired authorization is rejected") 61 x := &banktypes.SendAuthorization{SpendLimit: newCoins} 62 err := app.AuthzKeeper.SaveGrant(ctx, granterAddr, granteeAddr, x, now.Add(-1*time.Hour)) 63 s.Require().Error(err) 64 authorization, _ = app.AuthzKeeper.GetCleanAuthorization(ctx, granteeAddr, granterAddr, bankSendAuthMsgType) 65 s.Require().Nil(authorization) 66 67 s.T().Log("verify if authorization is accepted") 68 x = &banktypes.SendAuthorization{SpendLimit: newCoins} 69 err = app.AuthzKeeper.SaveGrant(ctx, granteeAddr, granterAddr, x, now.Add(time.Hour)) 70 s.Require().NoError(err) 71 authorization, _ = app.AuthzKeeper.GetCleanAuthorization(ctx, granteeAddr, granterAddr, bankSendAuthMsgType) 72 s.Require().NotNil(authorization) 73 s.Require().Equal(authorization.MsgTypeURL(), bankSendAuthMsgType) 74 75 s.T().Log("verify fetching authorization with wrong msg type fails") 76 authorization, _ = app.AuthzKeeper.GetCleanAuthorization(ctx, granteeAddr, granterAddr, sdk.MsgTypeURL(&banktypes.MsgMultiSend{})) 77 s.Require().Nil(authorization) 78 79 s.T().Log("verify fetching authorization with wrong grantee fails") 80 authorization, _ = app.AuthzKeeper.GetCleanAuthorization(ctx, recipientAddr, granterAddr, bankSendAuthMsgType) 81 s.Require().Nil(authorization) 82 83 s.T().Log("verify revoke fails with wrong information") 84 err = app.AuthzKeeper.DeleteGrant(ctx, recipientAddr, granterAddr, bankSendAuthMsgType) 85 s.Require().Error(err) 86 authorization, _ = app.AuthzKeeper.GetCleanAuthorization(ctx, recipientAddr, granterAddr, bankSendAuthMsgType) 87 s.Require().Nil(authorization) 88 89 s.T().Log("verify revoke executes with correct information") 90 err = app.AuthzKeeper.DeleteGrant(ctx, granteeAddr, granterAddr, bankSendAuthMsgType) 91 s.Require().NoError(err) 92 authorization, _ = app.AuthzKeeper.GetCleanAuthorization(ctx, granteeAddr, granterAddr, bankSendAuthMsgType) 93 s.Require().Nil(authorization) 94 } 95 96 func (s *TestSuite) TestKeeperIter() { 97 app, ctx, addrs := s.app, s.ctx, s.addrs 98 99 granterAddr := addrs[0] 100 granteeAddr := addrs[1] 101 102 s.T().Log("verify that no authorization returns nil") 103 authorization, expiration := app.AuthzKeeper.GetCleanAuthorization(ctx, granteeAddr, granterAddr, "Abcd") 104 s.Require().Nil(authorization) 105 s.Require().Equal(time.Time{}, expiration) 106 now := s.ctx.BlockHeader().Time.Add(time.Second) 107 s.Require().NotNil(now) 108 109 newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) 110 s.T().Log("verify if expired authorization is rejected") 111 x := &banktypes.SendAuthorization{SpendLimit: newCoins} 112 err := app.AuthzKeeper.SaveGrant(ctx, granteeAddr, granterAddr, x, now.Add(-1*time.Hour)) 113 s.Require().Error(err) 114 authorization, _ = app.AuthzKeeper.GetCleanAuthorization(ctx, granteeAddr, granterAddr, "abcd") 115 s.Require().Nil(authorization) 116 117 app.AuthzKeeper.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant authz.Grant) bool { 118 s.Require().Equal(granter, granterAddr) 119 s.Require().Equal(grantee, granteeAddr) 120 return true 121 }) 122 } 123 124 func (s *TestSuite) TestKeeperFees() { 125 app, addrs := s.app, s.addrs 126 127 granterAddr := addrs[0] 128 granteeAddr := addrs[1] 129 recipientAddr := addrs[2] 130 s.Require().NoError(simapp.FundAccount(app, s.ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000)))) 131 expiration := s.ctx.BlockHeader().Time.Add(1 * time.Second) 132 133 smallCoin := sdk.NewCoins(sdk.NewInt64Coin("steak", 20)) 134 someCoin := sdk.NewCoins(sdk.NewInt64Coin("steak", 123)) 135 136 msgs := authz.NewMsgExec(granteeAddr, []sdk.Msg{ 137 &banktypes.MsgSend{ 138 Amount: sdk.NewCoins(sdk.NewInt64Coin("steak", 2)), 139 FromAddress: granterAddr.String(), 140 ToAddress: recipientAddr.String(), 141 }, 142 }) 143 144 s.Require().NoError(msgs.UnpackInterfaces(app.AppCodec())) 145 146 s.T().Log("verify dispatch fails with invalid authorization") 147 executeMsgs, err := msgs.GetMessages() 148 s.Require().NoError(err) 149 result, err := app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs) 150 151 s.Require().Nil(result) 152 s.Require().NotNil(err) 153 154 s.T().Log("verify dispatch executes with correct information") 155 // grant authorization 156 err = app.AuthzKeeper.SaveGrant(s.ctx, granteeAddr, granterAddr, &banktypes.SendAuthorization{SpendLimit: smallCoin}, expiration) 157 s.Require().NoError(err) 158 authorization, _ := app.AuthzKeeper.GetCleanAuthorization(s.ctx, granteeAddr, granterAddr, bankSendAuthMsgType) 159 s.Require().NotNil(authorization) 160 161 s.Require().Equal(authorization.MsgTypeURL(), bankSendAuthMsgType) 162 163 executeMsgs, err = msgs.GetMessages() 164 s.Require().NoError(err) 165 166 result, err = app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs) 167 s.Require().NoError(err) 168 s.Require().NotNil(result) 169 170 authorization, _ = app.AuthzKeeper.GetCleanAuthorization(s.ctx, granteeAddr, granterAddr, bankSendAuthMsgType) 171 s.Require().NotNil(authorization) 172 173 s.T().Log("verify dispatch fails with overlimit") 174 // grant authorization 175 176 msgs = authz.NewMsgExec(granteeAddr, []sdk.Msg{ 177 &banktypes.MsgSend{ 178 Amount: someCoin, 179 FromAddress: granterAddr.String(), 180 ToAddress: recipientAddr.String(), 181 }, 182 }) 183 184 s.Require().NoError(msgs.UnpackInterfaces(app.AppCodec())) 185 executeMsgs, err = msgs.GetMessages() 186 s.Require().NoError(err) 187 188 result, err = app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs) 189 s.Require().Nil(result) 190 s.Require().NotNil(err) 191 192 authorization, _ = app.AuthzKeeper.GetCleanAuthorization(s.ctx, granteeAddr, granterAddr, bankSendAuthMsgType) 193 s.Require().NotNil(authorization) 194 } 195 196 // Tests that all msg events included in an authz MsgExec tx 197 // Ref: https://github.com/cosmos/cosmos-sdk/issues/9501 198 func (s *TestSuite) TestDispatchedEvents() { 199 require := s.Require() 200 app, addrs := s.app, s.addrs 201 granterAddr := addrs[0] 202 granteeAddr := addrs[1] 203 recipientAddr := addrs[2] 204 require.NoError(simapp.FundAccount(app, s.ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000)))) 205 expiration := s.ctx.BlockHeader().Time.Add(1 * time.Second) // must be in the future 206 207 smallCoin := sdk.NewCoins(sdk.NewInt64Coin("steak", 20)) 208 msgs := authz.NewMsgExec(granteeAddr, []sdk.Msg{ 209 &banktypes.MsgSend{ 210 Amount: sdk.NewCoins(sdk.NewInt64Coin("steak", 2)), 211 FromAddress: granterAddr.String(), 212 ToAddress: recipientAddr.String(), 213 }, 214 }) 215 216 // grant authorization 217 err := app.AuthzKeeper.SaveGrant(s.ctx, granteeAddr, granterAddr, &banktypes.SendAuthorization{SpendLimit: smallCoin}, expiration) 218 require.NoError(err) 219 authorization, _ := app.AuthzKeeper.GetCleanAuthorization(s.ctx, granteeAddr, granterAddr, bankSendAuthMsgType) 220 require.NotNil(authorization) 221 require.Equal(authorization.MsgTypeURL(), bankSendAuthMsgType) 222 223 executeMsgs, err := msgs.GetMessages() 224 require.NoError(err) 225 226 result, err := app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs) 227 require.NoError(err) 228 require.NotNil(result) 229 230 events := s.ctx.EventManager().Events() 231 232 // get last 3 events (events that occur *after* the grant) 233 events = events[len(events)-3:] 234 235 requiredEvents := map[string]bool{ 236 "coin_spent": false, 237 "coin_received": false, 238 "transfer": false, 239 } 240 for _, e := range events { 241 requiredEvents[e.Type] = true 242 } 243 for _, v := range requiredEvents { 244 require.True(v) 245 } 246 } 247 248 func TestTestSuite(t *testing.T) { 249 suite.Run(t, new(TestSuite)) 250 }