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  }