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