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  }