github.com/Finschia/finschia-sdk@v0.48.1/x/bankplus/keeper/keeper_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/suite"
     7  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
     8  
     9  	"github.com/Finschia/finschia-sdk/simapp"
    10  	sdk "github.com/Finschia/finschia-sdk/types"
    11  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
    12  	authkeeper "github.com/Finschia/finschia-sdk/x/auth/keeper"
    13  	authtypes "github.com/Finschia/finschia-sdk/x/auth/types"
    14  	"github.com/Finschia/finschia-sdk/x/bank/types"
    15  	bankpluskeeper "github.com/Finschia/finschia-sdk/x/bankplus/keeper"
    16  	minttypes "github.com/Finschia/finschia-sdk/x/mint/types"
    17  )
    18  
    19  const (
    20  	initialPower = int64(100)
    21  	holder       = "holder"
    22  	blocker      = "blocker"
    23  )
    24  
    25  var (
    26  	holderAcc  = authtypes.NewEmptyModuleAccount(holder)
    27  	blockedAcc = authtypes.NewEmptyModuleAccount(blocker)
    28  	burnerAcc  = authtypes.NewEmptyModuleAccount(authtypes.Burner, authtypes.Burner)
    29  
    30  	initTokens = sdk.TokensFromConsensusPower(initialPower, sdk.DefaultPowerReduction)
    31  	initCoins  = sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens))
    32  )
    33  
    34  // nolint: interfacer
    35  func getCoinsByName(ctx sdk.Context, bk bankpluskeeper.Keeper, ak types.AccountKeeper, moduleName string) sdk.Coins {
    36  	moduleAddress := ak.GetModuleAddress(moduleName)
    37  	macc := ak.GetAccount(ctx, moduleAddress)
    38  	if macc == nil {
    39  		return sdk.NewCoins()
    40  	}
    41  
    42  	return bk.GetAllBalances(ctx, macc.GetAddress())
    43  }
    44  
    45  type IntegrationTestSuite struct {
    46  	suite.Suite
    47  }
    48  
    49  func (suite *IntegrationTestSuite) TestSupply_SendCoins() {
    50  	app := simapp.Setup(false)
    51  	ctx := app.BaseApp.NewContext(false, tmproto.Header{Height: 1})
    52  	appCodec := app.AppCodec()
    53  
    54  	// add module accounts to supply keeper
    55  	maccPerms := simapp.GetMaccPerms()
    56  	maccPerms[holder] = nil
    57  	maccPerms[authtypes.Burner] = []string{authtypes.Burner}
    58  	maccPerms[authtypes.Minter] = []string{authtypes.Minter}
    59  
    60  	authKeeper := authkeeper.NewAccountKeeper(
    61  		appCodec, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName),
    62  		authtypes.ProtoBaseAccount, maccPerms,
    63  	)
    64  	keeper := bankpluskeeper.NewBaseKeeper(
    65  		appCodec, app.GetKey(types.StoreKey), authKeeper,
    66  		app.GetSubspace(types.ModuleName), make(map[string]bool), false,
    67  	)
    68  
    69  	baseAcc := authKeeper.NewAccountWithAddress(ctx, authtypes.NewModuleAddress("baseAcc"))
    70  
    71  	// set initial balances
    72  	suite.
    73  		Require().
    74  		NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins))
    75  
    76  	suite.
    77  		Require().
    78  		NoError(keeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, holderAcc.GetAddress(), initCoins))
    79  
    80  	suite.Require().NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins))
    81  	authKeeper.SetModuleAccount(ctx, holderAcc)
    82  	authKeeper.SetModuleAccount(ctx, burnerAcc)
    83  	authKeeper.SetAccount(ctx, baseAcc)
    84  
    85  	suite.Require().Panics(func() {
    86  		keeper.SendCoinsFromModuleToModule(ctx, "", holderAcc.GetName(), initCoins) // nolint:errcheck
    87  	})
    88  
    89  	suite.Require().Panics(func() {
    90  		keeper.SendCoinsFromModuleToModule(ctx, authtypes.Burner, "", initCoins) // nolint:errcheck
    91  	})
    92  
    93  	suite.Require().Panics(func() {
    94  		keeper.SendCoinsFromModuleToAccount(ctx, "", baseAcc.GetAddress(), initCoins) // nolint:errcheck
    95  	})
    96  
    97  	// not enough balance (100stake - 200stake)
    98  	suite.Require().Error(
    99  		keeper.SendCoinsFromModuleToAccount(ctx, holderAcc.GetName(), baseAcc.GetAddress(), initCoins.Add(initCoins...)),
   100  	)
   101  
   102  	suite.Require().NoError(
   103  		keeper.SendCoinsFromModuleToModule(ctx, holderAcc.GetName(), authtypes.Burner, initCoins),
   104  	)
   105  	suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, holderAcc.GetName()).String())
   106  	suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner))
   107  
   108  	suite.Require().NoError(
   109  		keeper.SendCoinsFromModuleToAccount(ctx, authtypes.Burner, baseAcc.GetAddress(), initCoins),
   110  	)
   111  	suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner).String())
   112  	suite.Require().Equal(initCoins, keeper.GetAllBalances(ctx, baseAcc.GetAddress()))
   113  
   114  	suite.Require().NoError(keeper.SendCoinsFromAccountToModule(ctx, baseAcc.GetAddress(), authtypes.Burner, initCoins))
   115  	suite.Require().Equal(sdk.NewCoins().String(), keeper.GetAllBalances(ctx, baseAcc.GetAddress()).String())
   116  	suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner))
   117  }
   118  
   119  func (suite *IntegrationTestSuite) TestInactiveAddrOfSendCoins() {
   120  	app := simapp.Setup(false)
   121  	ctx := app.BaseApp.NewContext(false, tmproto.Header{Height: 1})
   122  	appCodec := app.AppCodec()
   123  
   124  	// add module accounts to supply keeper
   125  	maccPerms := simapp.GetMaccPerms()
   126  	maccPerms[holder] = nil
   127  	maccPerms[authtypes.Burner] = []string{authtypes.Burner}
   128  	maccPerms[authtypes.Minter] = []string{authtypes.Minter}
   129  
   130  	authKeeper := authkeeper.NewAccountKeeper(
   131  		appCodec, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName),
   132  		authtypes.ProtoBaseAccount, maccPerms,
   133  	)
   134  
   135  	keeper := bankpluskeeper.NewBaseKeeper(
   136  		appCodec, app.GetKey(types.StoreKey), authKeeper,
   137  		app.GetSubspace(types.ModuleName), make(map[string]bool), false,
   138  	)
   139  
   140  	// set initial balances
   141  	suite.
   142  		Require().
   143  		NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins))
   144  
   145  	suite.
   146  		Require().
   147  		NoError(keeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, holderAcc.GetAddress(), initCoins))
   148  
   149  	suite.Require().NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins))
   150  	suite.Require().Equal(initCoins, keeper.GetAllBalances(ctx, holderAcc.GetAddress()))
   151  
   152  	suite.Require().False(keeper.IsInactiveAddr(blockedAcc.GetAddress()))
   153  
   154  	// add blocked address
   155  	keeper.AddToInactiveAddr(ctx, blockedAcc.GetAddress())
   156  	suite.Require().True(keeper.IsInactiveAddr(blockedAcc.GetAddress()))
   157  
   158  	err := keeper.SendCoins(ctx, holderAcc.GetAddress(), blockedAcc.GetAddress(), initCoins)
   159  	suite.Require().Contains(err.Error(), "is not allowed to receive funds")
   160  	suite.Require().Equal(initCoins, keeper.GetAllBalances(ctx, holderAcc.GetAddress()))
   161  
   162  	// delete blocked address
   163  	keeper.DeleteFromInactiveAddr(ctx, blockedAcc.GetAddress())
   164  	suite.Require().False(keeper.IsInactiveAddr(blockedAcc.GetAddress()))
   165  
   166  	suite.Require().NoError(keeper.SendCoins(ctx, holderAcc.GetAddress(), blockedAcc.GetAddress(), initCoins))
   167  	suite.Require().Equal(sdk.NewCoins().String(), keeper.GetAllBalances(ctx, holderAcc.GetAddress()).String())
   168  }
   169  
   170  func (suite *IntegrationTestSuite) TestInitializeBankPlus() {
   171  	app := simapp.Setup(false)
   172  	ctx := app.BaseApp.NewContext(false, tmproto.Header{Height: 1})
   173  	appCodec := app.AppCodec()
   174  
   175  	// add module accounts to supply keeper
   176  	maccPerms := simapp.GetMaccPerms()
   177  	maccPerms[holder] = nil
   178  	maccPerms[authtypes.Burner] = []string{authtypes.Burner}
   179  	maccPerms[authtypes.Minter] = []string{authtypes.Minter}
   180  
   181  	authKeeper := authkeeper.NewAccountKeeper(
   182  		appCodec, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName),
   183  		authtypes.ProtoBaseAccount, maccPerms,
   184  	)
   185  
   186  	{
   187  		keeper := bankpluskeeper.NewBaseKeeper(
   188  			appCodec, app.GetKey(types.StoreKey), authKeeper,
   189  			app.GetSubspace(types.ModuleName), make(map[string]bool), false,
   190  		)
   191  
   192  		// add blocked address
   193  		keeper.AddToInactiveAddr(ctx, blockedAcc.GetAddress())
   194  		suite.Require().True(keeper.IsInactiveAddr(blockedAcc.GetAddress()))
   195  	}
   196  
   197  	{
   198  		keeper := bankpluskeeper.NewBaseKeeper(
   199  			appCodec, app.GetKey(types.StoreKey), authKeeper,
   200  			app.GetSubspace(types.ModuleName), make(map[string]bool), false,
   201  		)
   202  		keeper.InitializeBankPlus(ctx)
   203  		suite.Require().True(keeper.IsInactiveAddr(blockedAcc.GetAddress()))
   204  	}
   205  }
   206  
   207  func (suite *IntegrationTestSuite) TestSendCoinsFromModuleToAccount_Blacklist() {
   208  	app := simapp.Setup(false)
   209  	ctx := app.BaseApp.NewContext(false, tmproto.Header{Height: 1})
   210  	appCodec := app.AppCodec()
   211  
   212  	// add module accounts to supply keeper
   213  	maccPerms := simapp.GetMaccPerms()
   214  	maccPerms[holder] = nil
   215  	maccPerms[authtypes.Burner] = []string{authtypes.Burner}
   216  	maccPerms[authtypes.Minter] = []string{authtypes.Minter}
   217  
   218  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   219  
   220  	authKeeper := authkeeper.NewAccountKeeper(
   221  		appCodec, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName),
   222  		authtypes.ProtoBaseAccount, maccPerms,
   223  	)
   224  	keeper := bankpluskeeper.NewBaseKeeper(
   225  		appCodec, app.GetKey(types.StoreKey), authKeeper,
   226  		app.GetSubspace(types.ModuleName), map[string]bool{addr1.String(): true}, false)
   227  
   228  	suite.Require().NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins))
   229  	suite.Require().Error(keeper.SendCoinsFromModuleToAccount(
   230  		ctx, minttypes.ModuleName, addr1, initCoins,
   231  	))
   232  }
   233  
   234  func (suite *IntegrationTestSuite) TestInputOutputCoins() {
   235  	app := simapp.Setup(false)
   236  	ctx := app.BaseApp.NewContext(false, tmproto.Header{Height: 1})
   237  	appCodec := app.AppCodec()
   238  
   239  	// add module accounts to supply keeper
   240  	maccPerms := simapp.GetMaccPerms()
   241  	maccPerms[holder] = nil
   242  	maccPerms[authtypes.Burner] = []string{authtypes.Burner}
   243  	maccPerms[authtypes.Minter] = []string{authtypes.Minter}
   244  
   245  	authKeeper := authkeeper.NewAccountKeeper(
   246  		appCodec, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName),
   247  		authtypes.ProtoBaseAccount, maccPerms,
   248  	)
   249  	keeper := bankpluskeeper.NewBaseKeeper(
   250  		appCodec, app.GetKey(types.StoreKey), authKeeper,
   251  		app.GetSubspace(types.ModuleName), make(map[string]bool), false,
   252  	)
   253  
   254  	baseAcc := authKeeper.NewAccountWithAddress(ctx, authtypes.NewModuleAddress("baseAcc"))
   255  	authKeeper.SetModuleAccount(ctx, holderAcc)
   256  	authKeeper.SetModuleAccount(ctx, burnerAcc)
   257  	authKeeper.SetAccount(ctx, baseAcc)
   258  
   259  	// set initial balances
   260  	suite.
   261  		Require().
   262  		NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins))
   263  	suite.
   264  		Require().
   265  		NoError(keeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, baseAcc.GetAddress(), initCoins))
   266  	suite.
   267  		Require().
   268  		NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins))
   269  	suite.
   270  		Require().
   271  		NoError(keeper.SendCoinsFromModuleToModule(ctx, minttypes.ModuleName, holderAcc.GetName(), initCoins))
   272  
   273  	input := []types.Input{types.NewInput(baseAcc.GetAddress(), initCoins), types.NewInput(holderAcc.GetAddress(), initCoins)}
   274  	output := []types.Output{types.NewOutput(burnerAcc.GetAddress(), initCoins), types.NewOutput(burnerAcc.GetAddress(), initCoins)}
   275  
   276  	targetKeeper := func(isDeact bool) bankpluskeeper.BaseKeeper {
   277  		return bankpluskeeper.NewBaseKeeper(
   278  			appCodec, app.GetKey(types.StoreKey), authKeeper,
   279  			app.GetSubspace(types.ModuleName), make(map[string]bool), isDeact,
   280  		)
   281  	}
   282  	tcs := map[string]struct {
   283  		deactMultiSend bool
   284  		err            error
   285  	}{
   286  		"MultiSend Off": {
   287  			true,
   288  			sdkerrors.ErrNotSupported.Wrap("MultiSend was deactivated"),
   289  		},
   290  		"MultiSend On": {
   291  			false,
   292  			nil,
   293  		},
   294  	}
   295  
   296  	for name, tc := range tcs {
   297  		tc := tc
   298  		suite.T().Run(name, func(t *testing.T) {
   299  			if tc.err != nil {
   300  				suite.EqualError(targetKeeper(tc.deactMultiSend).InputOutputCoins(ctx, input, output), tc.err.Error())
   301  			} else {
   302  				err := targetKeeper(tc.deactMultiSend).InputOutputCoins(ctx, input, output)
   303  				suite.Assert().NoError(err)
   304  			}
   305  		})
   306  	}
   307  }
   308  
   309  func TestKeeperTestSuite(t *testing.T) {
   310  	suite.Run(t, new(IntegrationTestSuite))
   311  }