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

     1  package keeper_test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	osttime "github.com/Finschia/ostracon/types/time"
     9  	"github.com/stretchr/testify/suite"
    10  	abci "github.com/tendermint/tendermint/abci/types"
    11  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
    12  
    13  	"github.com/Finschia/finschia-sdk/baseapp"
    14  	"github.com/Finschia/finschia-sdk/simapp"
    15  	sdk "github.com/Finschia/finschia-sdk/types"
    16  	"github.com/Finschia/finschia-sdk/types/query"
    17  	authkeeper "github.com/Finschia/finschia-sdk/x/auth/keeper"
    18  	authtypes "github.com/Finschia/finschia-sdk/x/auth/types"
    19  	"github.com/Finschia/finschia-sdk/x/auth/vesting/exported"
    20  	vesting "github.com/Finschia/finschia-sdk/x/auth/vesting/types"
    21  	"github.com/Finschia/finschia-sdk/x/bank/keeper"
    22  	"github.com/Finschia/finschia-sdk/x/bank/types"
    23  	minttypes "github.com/Finschia/finschia-sdk/x/mint/types"
    24  )
    25  
    26  const (
    27  	fooDenom     = "foo"
    28  	barDenom     = "bar"
    29  	initialPower = int64(100)
    30  	holder       = "holder"
    31  	multiPerm    = "multiple permissions account"
    32  	randomPerm   = "random permission"
    33  )
    34  
    35  var (
    36  	holderAcc     = authtypes.NewEmptyModuleAccount(holder)
    37  	burnerAcc     = authtypes.NewEmptyModuleAccount(authtypes.Burner, authtypes.Burner)
    38  	minterAcc     = authtypes.NewEmptyModuleAccount(authtypes.Minter, authtypes.Minter)
    39  	multiPermAcc  = authtypes.NewEmptyModuleAccount(multiPerm, authtypes.Burner, authtypes.Minter, authtypes.Staking)
    40  	randomPermAcc = authtypes.NewEmptyModuleAccount(randomPerm, "random")
    41  
    42  	// The default power validators are initialized to have within tests
    43  	initTokens = sdk.TokensFromConsensusPower(initialPower, sdk.DefaultPowerReduction)
    44  	initCoins  = sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens))
    45  )
    46  
    47  func newFooCoin(amt int64) sdk.Coin {
    48  	return sdk.NewInt64Coin(fooDenom, amt)
    49  }
    50  
    51  func newBarCoin(amt int64) sdk.Coin {
    52  	return sdk.NewInt64Coin(barDenom, amt)
    53  }
    54  
    55  // nolint: interfacer
    56  func getCoinsByName(ctx sdk.Context, bk keeper.Keeper, ak types.AccountKeeper, moduleName string) sdk.Coins {
    57  	moduleAddress := ak.GetModuleAddress(moduleName)
    58  	macc := ak.GetAccount(ctx, moduleAddress)
    59  	if macc == nil {
    60  		return sdk.Coins(nil)
    61  	}
    62  
    63  	return bk.GetAllBalances(ctx, macc.GetAddress())
    64  }
    65  
    66  type IntegrationTestSuite struct {
    67  	suite.Suite
    68  
    69  	app         *simapp.SimApp
    70  	ctx         sdk.Context
    71  	queryClient types.QueryClient
    72  }
    73  
    74  func (suite *IntegrationTestSuite) initKeepersWithmAccPerms(blockedAddrs map[string]bool) (authkeeper.AccountKeeper, keeper.BaseKeeper) {
    75  	app := suite.app
    76  	maccPerms := simapp.GetMaccPerms()
    77  	appCodec := simapp.MakeTestEncodingConfig().Marshaler
    78  
    79  	maccPerms[holder] = nil
    80  	maccPerms[authtypes.Burner] = []string{authtypes.Burner}
    81  	maccPerms[authtypes.Minter] = []string{authtypes.Minter}
    82  	maccPerms[multiPerm] = []string{authtypes.Burner, authtypes.Minter, authtypes.Staking}
    83  	maccPerms[randomPerm] = []string{"random"}
    84  	authKeeper := authkeeper.NewAccountKeeper(
    85  		appCodec, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName),
    86  		authtypes.ProtoBaseAccount, maccPerms,
    87  	)
    88  	keeper := keeper.NewBaseKeeper(
    89  		appCodec, app.GetKey(types.StoreKey), authKeeper,
    90  		app.GetSubspace(types.ModuleName), blockedAddrs,
    91  	)
    92  
    93  	return authKeeper, keeper
    94  }
    95  
    96  func (suite *IntegrationTestSuite) SetupTest() {
    97  	app := simapp.Setup(false)
    98  	ctx := app.BaseApp.NewContext(false, tmproto.Header{Time: time.Now()})
    99  
   100  	app.AccountKeeper.SetParams(ctx, authtypes.DefaultParams())
   101  	app.BankKeeper.SetParams(ctx, types.DefaultParams())
   102  
   103  	queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry())
   104  	types.RegisterQueryServer(queryHelper, app.BankKeeper)
   105  	queryClient := types.NewQueryClient(queryHelper)
   106  
   107  	suite.app = app
   108  	suite.ctx = ctx
   109  	suite.queryClient = queryClient
   110  }
   111  
   112  func (suite *IntegrationTestSuite) TestSupply() {
   113  	ctx := suite.ctx
   114  
   115  	require := suite.Require()
   116  
   117  	// add module accounts to supply keeper
   118  	authKeeper, keeper := suite.initKeepersWithmAccPerms(make(map[string]bool))
   119  
   120  	initialPower := int64(100)
   121  	initTokens := suite.app.StakingKeeper.TokensFromConsensusPower(ctx, initialPower)
   122  	totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens))
   123  
   124  	// set burnerAcc balance
   125  	authKeeper.SetModuleAccount(ctx, burnerAcc)
   126  	require.NoError(keeper.MintCoins(ctx, authtypes.Minter, totalSupply))
   127  	require.NoError(keeper.SendCoinsFromModuleToAccount(ctx, authtypes.Minter, burnerAcc.GetAddress(), totalSupply))
   128  
   129  	total, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{})
   130  	require.NoError(err)
   131  	require.Equal(totalSupply, total)
   132  
   133  	// burning all supplied tokens
   134  	err = keeper.BurnCoins(ctx, authtypes.Burner, totalSupply)
   135  	require.NoError(err)
   136  
   137  	total, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{})
   138  	require.NoError(err)
   139  	require.Equal(total.String(), "")
   140  }
   141  
   142  func (suite *IntegrationTestSuite) TestSendCoinsFromModuleToAccount_Blacklist() {
   143  	app := suite.app
   144  	ctx := app.BaseApp.NewContext(false, tmproto.Header{Height: 1})
   145  	maccPerms := simapp.GetMaccPerms()
   146  	appCodec := app.AppCodec()
   147  
   148  	// add module accounts to supply keeper
   149  	maccPerms[holder] = nil
   150  	maccPerms[authtypes.Burner] = []string{authtypes.Burner}
   151  	maccPerms[authtypes.Minter] = []string{authtypes.Minter}
   152  	maccPerms[multiPerm] = []string{authtypes.Burner, authtypes.Minter, authtypes.Staking}
   153  	maccPerms[randomPerm] = []string{"random"}
   154  
   155  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   156  
   157  	authKeeper := authkeeper.NewAccountKeeper(
   158  		appCodec, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName),
   159  		authtypes.ProtoBaseAccount, maccPerms,
   160  	)
   161  	keeper := keeper.NewBaseKeeper(
   162  		appCodec, app.GetKey(types.StoreKey), authKeeper,
   163  		app.GetSubspace(types.ModuleName), map[string]bool{addr1.String(): true},
   164  	)
   165  
   166  	suite.Require().NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins))
   167  	suite.Require().Error(keeper.SendCoinsFromModuleToAccount(
   168  		ctx, minttypes.ModuleName, addr1, initCoins,
   169  	))
   170  }
   171  
   172  func (suite *IntegrationTestSuite) TestSupply_SendCoins() {
   173  	ctx := suite.ctx
   174  
   175  	// add module accounts to supply keeper
   176  	authKeeper, keeper := suite.initKeepersWithmAccPerms(make(map[string]bool))
   177  
   178  	baseAcc := authKeeper.NewAccountWithAddress(ctx, authtypes.NewModuleAddress("baseAcc"))
   179  
   180  	// set initial balances
   181  	suite.
   182  		Require().
   183  		NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins))
   184  
   185  	suite.
   186  		Require().
   187  		NoError(keeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, holderAcc.GetAddress(), initCoins))
   188  
   189  	authKeeper.SetModuleAccount(ctx, holderAcc)
   190  	authKeeper.SetModuleAccount(ctx, burnerAcc)
   191  	authKeeper.SetAccount(ctx, baseAcc)
   192  
   193  	suite.Require().Panics(func() {
   194  		_ = keeper.SendCoinsFromModuleToModule(ctx, "", holderAcc.GetName(), initCoins)
   195  	})
   196  
   197  	suite.Require().Panics(func() {
   198  		_ = keeper.SendCoinsFromModuleToModule(ctx, authtypes.Burner, "", initCoins)
   199  	})
   200  
   201  	suite.Require().Panics(func() {
   202  		_ = keeper.SendCoinsFromModuleToAccount(ctx, "", baseAcc.GetAddress(), initCoins)
   203  	})
   204  
   205  	suite.Require().Error(
   206  		keeper.SendCoinsFromModuleToAccount(ctx, holderAcc.GetName(), baseAcc.GetAddress(), initCoins.Add(initCoins...)),
   207  	)
   208  
   209  	suite.Require().NoError(
   210  		keeper.SendCoinsFromModuleToModule(ctx, holderAcc.GetName(), authtypes.Burner, initCoins),
   211  	)
   212  	suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, holderAcc.GetName()).String())
   213  	suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner))
   214  
   215  	suite.Require().NoError(
   216  		keeper.SendCoinsFromModuleToAccount(ctx, authtypes.Burner, baseAcc.GetAddress(), initCoins),
   217  	)
   218  	suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner).String())
   219  	suite.Require().Equal(initCoins, keeper.GetAllBalances(ctx, baseAcc.GetAddress()))
   220  
   221  	suite.Require().NoError(keeper.SendCoinsFromAccountToModule(ctx, baseAcc.GetAddress(), authtypes.Burner, initCoins))
   222  	suite.Require().Equal(sdk.NewCoins().String(), keeper.GetAllBalances(ctx, baseAcc.GetAddress()).String())
   223  	suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner))
   224  }
   225  
   226  func (suite *IntegrationTestSuite) TestSupply_MintCoins() {
   227  	ctx := suite.ctx
   228  
   229  	// add module accounts to supply keeper
   230  	authKeeper, keeper := suite.initKeepersWithmAccPerms(make(map[string]bool))
   231  
   232  	authKeeper.SetModuleAccount(ctx, burnerAcc)
   233  	authKeeper.SetModuleAccount(ctx, minterAcc)
   234  	authKeeper.SetModuleAccount(ctx, multiPermAcc)
   235  	authKeeper.SetModuleAccount(ctx, randomPermAcc)
   236  
   237  	initialSupply, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{})
   238  	suite.Require().NoError(err)
   239  
   240  	suite.Require().Panics(func() { keeper.MintCoins(ctx, "", initCoins) }, "no module account")                // nolint:errcheck
   241  	suite.Require().Panics(func() { keeper.MintCoins(ctx, authtypes.Burner, initCoins) }, "invalid permission") // nolint:errcheck
   242  
   243  	err = keeper.MintCoins(ctx, authtypes.Minter, sdk.Coins{sdk.Coin{Denom: "denom", Amount: sdk.NewInt(-10)}})
   244  	suite.Require().Error(err, "insufficient coins")
   245  
   246  	suite.Require().Panics(func() { keeper.MintCoins(ctx, randomPerm, initCoins) }) // nolint:errcheck
   247  
   248  	err = keeper.MintCoins(ctx, authtypes.Minter, initCoins)
   249  	suite.Require().NoError(err)
   250  
   251  	suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Minter))
   252  	totalSupply, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{})
   253  	suite.Require().NoError(err)
   254  
   255  	suite.Require().Equal(initialSupply.Add(initCoins...), totalSupply)
   256  
   257  	// test same functionality on module account with multiple permissions
   258  	initialSupply, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{})
   259  	suite.Require().NoError(err)
   260  
   261  	err = keeper.MintCoins(ctx, multiPermAcc.GetName(), initCoins)
   262  	suite.Require().NoError(err)
   263  
   264  	totalSupply, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{})
   265  	suite.Require().NoError(err)
   266  	suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, multiPermAcc.GetName()))
   267  	suite.Require().Equal(initialSupply.Add(initCoins...), totalSupply)
   268  	suite.Require().Panics(func() { keeper.MintCoins(ctx, authtypes.Burner, initCoins) }) // nolint:errcheck
   269  }
   270  
   271  func (suite *IntegrationTestSuite) TestSupply_BurnCoins() {
   272  	ctx := suite.ctx
   273  	// add module accounts to supply keeper
   274  	authKeeper, keeper := suite.initKeepersWithmAccPerms(make(map[string]bool))
   275  
   276  	// set burnerAcc balance
   277  	authKeeper.SetModuleAccount(ctx, burnerAcc)
   278  	suite.
   279  		Require().
   280  		NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins))
   281  	suite.
   282  		Require().
   283  		NoError(keeper.SendCoinsFromModuleToAccount(ctx, authtypes.Minter, burnerAcc.GetAddress(), initCoins))
   284  
   285  	// inflate supply
   286  	suite.
   287  		Require().
   288  		NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins))
   289  	supplyAfterInflation, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{})
   290  	suite.Require().NoError(err)
   291  
   292  	suite.Require().Panics(func() { keeper.BurnCoins(ctx, "", initCoins) }, "no module account")                    // nolint:errcheck
   293  	suite.Require().Panics(func() { keeper.BurnCoins(ctx, authtypes.Minter, initCoins) }, "invalid permission")     // nolint:errcheck
   294  	suite.Require().Panics(func() { keeper.BurnCoins(ctx, randomPerm, supplyAfterInflation) }, "random permission") // nolint:errcheck
   295  	err = keeper.BurnCoins(ctx, authtypes.Burner, supplyAfterInflation)
   296  	suite.Require().Error(err, "insufficient coins")
   297  
   298  	err = keeper.BurnCoins(ctx, authtypes.Burner, initCoins)
   299  	suite.Require().NoError(err)
   300  	supplyAfterBurn, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{})
   301  	suite.Require().NoError(err)
   302  	suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner).String())
   303  	suite.Require().Equal(supplyAfterInflation.Sub(initCoins), supplyAfterBurn)
   304  
   305  	// test same functionality on module account with multiple permissions
   306  	suite.
   307  		Require().
   308  		NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins))
   309  
   310  	supplyAfterInflation, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{})
   311  	suite.Require().NoError(err)
   312  	suite.Require().NoError(keeper.SendCoins(ctx, authtypes.NewModuleAddress(authtypes.Minter), multiPermAcc.GetAddress(), initCoins))
   313  	authKeeper.SetModuleAccount(ctx, multiPermAcc)
   314  
   315  	err = keeper.BurnCoins(ctx, multiPermAcc.GetName(), initCoins)
   316  	suite.Require().NoError(err)
   317  	supplyAfterBurn, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{})
   318  	suite.Require().NoError(err)
   319  	suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, multiPermAcc.GetName()).String())
   320  	suite.Require().Equal(supplyAfterInflation.Sub(initCoins), supplyAfterBurn)
   321  }
   322  
   323  func (suite *IntegrationTestSuite) TestSendCoinsNewAccount() {
   324  	app, ctx := suite.app, suite.ctx
   325  	balances := sdk.NewCoins(newFooCoin(100), newBarCoin(50))
   326  
   327  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   328  	acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
   329  	app.AccountKeeper.SetAccount(ctx, acc1)
   330  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, balances))
   331  
   332  	acc1Balances := app.BankKeeper.GetAllBalances(ctx, addr1)
   333  	suite.Require().Equal(balances, acc1Balances)
   334  
   335  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   336  
   337  	suite.Require().Nil(app.AccountKeeper.GetAccount(ctx, addr2))
   338  	app.BankKeeper.GetAllBalances(ctx, addr2)
   339  	suite.Require().Empty(app.BankKeeper.GetAllBalances(ctx, addr2))
   340  
   341  	sendAmt := sdk.NewCoins(newFooCoin(50), newBarCoin(50))
   342  	suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendAmt))
   343  
   344  	acc2Balances := app.BankKeeper.GetAllBalances(ctx, addr2)
   345  	acc1Balances = app.BankKeeper.GetAllBalances(ctx, addr1)
   346  	suite.Require().Equal(sendAmt, acc2Balances)
   347  	updatedAcc1Bal := balances.Sub(sendAmt)
   348  	suite.Require().Len(acc1Balances, len(updatedAcc1Bal))
   349  	suite.Require().Equal(acc1Balances, updatedAcc1Bal)
   350  	suite.Require().NotNil(app.AccountKeeper.GetAccount(ctx, addr2))
   351  }
   352  
   353  func (suite *IntegrationTestSuite) TestInputOutputNewAccount() {
   354  	app, ctx := suite.app, suite.ctx
   355  
   356  	balances := sdk.NewCoins(newFooCoin(100), newBarCoin(50))
   357  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   358  	acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
   359  	app.AccountKeeper.SetAccount(ctx, acc1)
   360  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, balances))
   361  
   362  	acc1Balances := app.BankKeeper.GetAllBalances(ctx, addr1)
   363  	suite.Require().Equal(balances, acc1Balances)
   364  
   365  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   366  
   367  	suite.Require().Nil(app.AccountKeeper.GetAccount(ctx, addr2))
   368  	suite.Require().Empty(app.BankKeeper.GetAllBalances(ctx, addr2))
   369  
   370  	inputs := []types.Input{
   371  		{Address: addr1.String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
   372  	}
   373  	outputs := []types.Output{
   374  		{Address: addr2.String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
   375  	}
   376  
   377  	suite.Require().NoError(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs))
   378  
   379  	expected := sdk.NewCoins(newFooCoin(30), newBarCoin(10))
   380  	acc2Balances := app.BankKeeper.GetAllBalances(ctx, addr2)
   381  	suite.Require().Equal(expected, acc2Balances)
   382  	suite.Require().NotNil(app.AccountKeeper.GetAccount(ctx, addr2))
   383  }
   384  
   385  func (suite *IntegrationTestSuite) TestInputOutputCoins() {
   386  	app, ctx := suite.app, suite.ctx
   387  	balances := sdk.NewCoins(newFooCoin(90), newBarCoin(30))
   388  
   389  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   390  	acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
   391  	app.AccountKeeper.SetAccount(ctx, acc1)
   392  
   393  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   394  	acc2 := app.AccountKeeper.NewAccountWithAddress(ctx, addr2)
   395  	app.AccountKeeper.SetAccount(ctx, acc2)
   396  
   397  	addr3 := sdk.AccAddress([]byte("addr3_______________"))
   398  	acc3 := app.AccountKeeper.NewAccountWithAddress(ctx, addr3)
   399  	app.AccountKeeper.SetAccount(ctx, acc3)
   400  
   401  	inputs := []types.Input{
   402  		{Address: addr1.String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
   403  		{Address: addr1.String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
   404  	}
   405  	outputs := []types.Output{
   406  		{Address: addr2.String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
   407  		{Address: addr3.String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
   408  	}
   409  
   410  	suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, []types.Output{}))
   411  	suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs))
   412  
   413  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, balances))
   414  
   415  	insufficientInputs := []types.Input{
   416  		{Address: addr1.String(), Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100))},
   417  		{Address: addr1.String(), Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100))},
   418  	}
   419  	insufficientOutputs := []types.Output{
   420  		{Address: addr2.String(), Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100))},
   421  		{Address: addr3.String(), Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100))},
   422  	}
   423  	suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, insufficientInputs, insufficientOutputs))
   424  	suite.Require().NoError(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs))
   425  
   426  	acc1Balances := app.BankKeeper.GetAllBalances(ctx, addr1)
   427  	expected := sdk.NewCoins(newFooCoin(30), newBarCoin(10))
   428  	suite.Require().Equal(expected, acc1Balances)
   429  
   430  	acc2Balances := app.BankKeeper.GetAllBalances(ctx, addr2)
   431  	suite.Require().Equal(expected, acc2Balances)
   432  
   433  	acc3Balances := app.BankKeeper.GetAllBalances(ctx, addr3)
   434  	suite.Require().Equal(expected, acc3Balances)
   435  }
   436  
   437  func (suite *IntegrationTestSuite) TestSendCoins() {
   438  	app, ctx := suite.app, suite.ctx
   439  	balances := sdk.NewCoins(newFooCoin(100), newBarCoin(50))
   440  
   441  	addr1 := sdk.AccAddress("addr1_______________")
   442  	acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
   443  	app.AccountKeeper.SetAccount(ctx, acc1)
   444  
   445  	addr2 := sdk.AccAddress("addr2_______________")
   446  	acc2 := app.AccountKeeper.NewAccountWithAddress(ctx, addr2)
   447  	app.AccountKeeper.SetAccount(ctx, acc2)
   448  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, balances))
   449  
   450  	sendAmt := sdk.NewCoins(newFooCoin(50), newBarCoin(25))
   451  	suite.Require().Error(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendAmt))
   452  
   453  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, balances))
   454  	suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendAmt))
   455  
   456  	acc1Balances := app.BankKeeper.GetAllBalances(ctx, addr1)
   457  	expected := sdk.NewCoins(newFooCoin(50), newBarCoin(25))
   458  	suite.Require().Equal(expected, acc1Balances)
   459  
   460  	acc2Balances := app.BankKeeper.GetAllBalances(ctx, addr2)
   461  	expected = sdk.NewCoins(newFooCoin(150), newBarCoin(75))
   462  	suite.Require().Equal(expected, acc2Balances)
   463  
   464  	// we sent all foo coins to acc2, so foo balance should be deleted for acc1 and bar should be still there
   465  	var coins []sdk.Coin
   466  	app.BankKeeper.IterateAccountBalances(ctx, addr1, func(c sdk.Coin) (stop bool) {
   467  		coins = append(coins, c)
   468  		return true
   469  	})
   470  	suite.Require().Len(coins, 1)
   471  	suite.Require().Equal(newBarCoin(25), coins[0], "expected only bar coins in the account balance, got: %v", coins)
   472  }
   473  
   474  func (suite *IntegrationTestSuite) TestValidateBalance() {
   475  	app, ctx := suite.app, suite.ctx
   476  	now := osttime.Now()
   477  	ctx = ctx.WithBlockHeader(tmproto.Header{Time: now})
   478  	endTime := now.Add(24 * time.Hour)
   479  
   480  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   481  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   482  
   483  	suite.Require().Error(app.BankKeeper.ValidateBalance(ctx, addr1))
   484  
   485  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
   486  	app.AccountKeeper.SetAccount(ctx, acc)
   487  
   488  	balances := sdk.NewCoins(newFooCoin(100))
   489  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, balances))
   490  	suite.Require().NoError(app.BankKeeper.ValidateBalance(ctx, addr1))
   491  
   492  	bacc := authtypes.NewBaseAccountWithAddress(addr2)
   493  	vacc := vesting.NewContinuousVestingAccount(bacc, balances.Add(balances...), now.Unix(), endTime.Unix())
   494  
   495  	app.AccountKeeper.SetAccount(ctx, vacc)
   496  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, balances))
   497  	suite.Require().Error(app.BankKeeper.ValidateBalance(ctx, addr2))
   498  }
   499  
   500  func (suite *IntegrationTestSuite) TestSendEnabled() {
   501  	app, ctx := suite.app, suite.ctx
   502  	enabled := true
   503  	params := types.DefaultParams()
   504  	suite.Require().Equal(enabled, params.DefaultSendEnabled)
   505  
   506  	app.BankKeeper.SetParams(ctx, params)
   507  
   508  	bondCoin := sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt())
   509  	fooCoin := sdk.NewCoin("foocoin", sdk.OneInt())
   510  	barCoin := sdk.NewCoin("barcoin", sdk.OneInt())
   511  
   512  	// assert with default (all denom) send enabled both Bar and Bond Denom are enabled
   513  	suite.Require().Equal(enabled, app.BankKeeper.IsSendEnabledCoin(ctx, barCoin))
   514  	suite.Require().Equal(enabled, app.BankKeeper.IsSendEnabledCoin(ctx, bondCoin))
   515  
   516  	// Both coins should be send enabled.
   517  	err := app.BankKeeper.IsSendEnabledCoins(ctx, fooCoin, bondCoin)
   518  	suite.Require().NoError(err)
   519  
   520  	// Set default send_enabled to !enabled, add a foodenom that overrides default as enabled
   521  	params.DefaultSendEnabled = !enabled
   522  	params = params.SetSendEnabledParam(fooCoin.Denom, enabled)
   523  	app.BankKeeper.SetParams(ctx, params)
   524  
   525  	// Expect our specific override to be enabled, others to be !enabled.
   526  	suite.Require().Equal(enabled, app.BankKeeper.IsSendEnabledCoin(ctx, fooCoin))
   527  	suite.Require().Equal(!enabled, app.BankKeeper.IsSendEnabledCoin(ctx, barCoin))
   528  	suite.Require().Equal(!enabled, app.BankKeeper.IsSendEnabledCoin(ctx, bondCoin))
   529  
   530  	// Foo coin should be send enabled.
   531  	err = app.BankKeeper.IsSendEnabledCoins(ctx, fooCoin)
   532  	suite.Require().NoError(err)
   533  
   534  	// Expect an error when one coin is not send enabled.
   535  	err = app.BankKeeper.IsSendEnabledCoins(ctx, fooCoin, bondCoin)
   536  	suite.Require().Error(err)
   537  
   538  	// Expect an error when all coins are not send enabled.
   539  	err = app.BankKeeper.IsSendEnabledCoins(ctx, bondCoin, barCoin)
   540  	suite.Require().Error(err)
   541  }
   542  
   543  func (suite *IntegrationTestSuite) TestHasBalance() {
   544  	app, ctx := suite.app, suite.ctx
   545  	addr := sdk.AccAddress([]byte("addr1_______________"))
   546  
   547  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
   548  	app.AccountKeeper.SetAccount(ctx, acc)
   549  
   550  	balances := sdk.NewCoins(newFooCoin(100))
   551  	suite.Require().False(app.BankKeeper.HasBalance(ctx, addr, newFooCoin(99)))
   552  
   553  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr, balances))
   554  	suite.Require().False(app.BankKeeper.HasBalance(ctx, addr, newFooCoin(101)))
   555  	suite.Require().True(app.BankKeeper.HasBalance(ctx, addr, newFooCoin(100)))
   556  	suite.Require().True(app.BankKeeper.HasBalance(ctx, addr, newFooCoin(1)))
   557  }
   558  
   559  func (suite *IntegrationTestSuite) TestMsgSendEvents() {
   560  	app, ctx := suite.app, suite.ctx
   561  	addr := sdk.AccAddress([]byte("addr1_______________"))
   562  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   563  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
   564  
   565  	app.AccountKeeper.SetAccount(ctx, acc)
   566  	newCoins := sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))
   567  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr, newCoins))
   568  
   569  	suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr, addr2, newCoins))
   570  	event1 := sdk.Event{
   571  		Type:       types.EventTypeTransfer,
   572  		Attributes: []abci.EventAttribute{},
   573  	}
   574  	event1.Attributes = append(
   575  		event1.Attributes,
   576  		abci.EventAttribute{Key: []byte(types.AttributeKeyRecipient), Value: []byte(addr2.String())},
   577  	)
   578  	event1.Attributes = append(
   579  		event1.Attributes,
   580  		abci.EventAttribute{Key: []byte(types.AttributeKeySender), Value: []byte(addr.String())},
   581  	)
   582  	event1.Attributes = append(
   583  		event1.Attributes,
   584  		abci.EventAttribute{Key: []byte(sdk.AttributeKeyAmount), Value: []byte(newCoins.String())},
   585  	)
   586  
   587  	// events are shifted due to the funding account events
   588  	events := ctx.EventManager().ABCIEvents()
   589  	suite.Require().Equal(8, len(events))
   590  	suite.Require().Equal(abci.Event(event1), events[7])
   591  }
   592  
   593  func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() {
   594  	app, ctx := suite.app, suite.ctx
   595  
   596  	app.BankKeeper.SetParams(ctx, types.DefaultParams())
   597  
   598  	addr := sdk.AccAddress([]byte("addr1_______________"))
   599  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   600  	addr3 := sdk.AccAddress([]byte("addr3_______________"))
   601  	addr4 := sdk.AccAddress([]byte("addr4_______________"))
   602  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
   603  	acc2 := app.AccountKeeper.NewAccountWithAddress(ctx, addr2)
   604  
   605  	app.AccountKeeper.SetAccount(ctx, acc)
   606  	app.AccountKeeper.SetAccount(ctx, acc2)
   607  
   608  	newCoins := sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))
   609  	newCoins2 := sdk.NewCoins(sdk.NewInt64Coin(barDenom, 100))
   610  	inputs := []types.Input{
   611  		{Address: addr.String(), Coins: newCoins},
   612  		{Address: addr2.String(), Coins: newCoins2},
   613  	}
   614  	outputs := []types.Output{
   615  		{Address: addr3.String(), Coins: newCoins},
   616  		{Address: addr4.String(), Coins: newCoins2},
   617  	}
   618  
   619  	suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs))
   620  
   621  	events := ctx.EventManager().ABCIEvents()
   622  	suite.Require().Equal(0, len(events))
   623  
   624  	// Set addr's coins but not addr2's coins
   625  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))))
   626  	suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs))
   627  
   628  	events = ctx.EventManager().ABCIEvents()
   629  	suite.Require().Equal(6, len(events)) // 6 events because account funding causes extra minting + coin_spent + coin_recv events
   630  
   631  	// Set addr's coins and addr2's coins
   632  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))))
   633  	newCoins = sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))
   634  
   635  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin(barDenom, 100))))
   636  	newCoins2 = sdk.NewCoins(sdk.NewInt64Coin(barDenom, 100))
   637  
   638  	suite.Require().NoError(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs))
   639  
   640  	events = ctx.EventManager().ABCIEvents()
   641  	suite.Require().Equal(22, len(events)) // 22 due to account funding + coin_spent + coin_recv events
   642  
   643  	event1 := sdk.Event{
   644  		Type:       types.EventTypeTransfer,
   645  		Attributes: []abci.EventAttribute{},
   646  	}
   647  	event1.Attributes = append(
   648  		event1.Attributes,
   649  		abci.EventAttribute{Key: []byte(types.AttributeKeyRecipient), Value: []byte(addr3.String())},
   650  	)
   651  	event1.Attributes = append(
   652  		event1.Attributes,
   653  		abci.EventAttribute{Key: []byte(sdk.AttributeKeyAmount), Value: []byte(newCoins.String())})
   654  	event2 := sdk.Event{
   655  		Type:       types.EventTypeTransfer,
   656  		Attributes: []abci.EventAttribute{},
   657  	}
   658  	event2.Attributes = append(
   659  		event2.Attributes,
   660  		abci.EventAttribute{Key: []byte(types.AttributeKeyRecipient), Value: []byte(addr4.String())},
   661  	)
   662  	event2.Attributes = append(
   663  		event2.Attributes,
   664  		abci.EventAttribute{Key: []byte(sdk.AttributeKeyAmount), Value: []byte(newCoins2.String())},
   665  	)
   666  	// events are shifted due to the funding account events
   667  	suite.Require().Equal(abci.Event(event1), events[19])
   668  	suite.Require().Equal(abci.Event(event2), events[21])
   669  }
   670  
   671  func (suite *IntegrationTestSuite) TestSpendableCoins() {
   672  	app, ctx := suite.app, suite.ctx
   673  	now := osttime.Now()
   674  	ctx = ctx.WithBlockHeader(tmproto.Header{Time: now})
   675  	endTime := now.Add(24 * time.Hour)
   676  
   677  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   678  	delCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   679  
   680  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   681  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   682  	addrModule := sdk.AccAddress([]byte("moduleAcc___________"))
   683  
   684  	macc := app.AccountKeeper.NewAccountWithAddress(ctx, addrModule)
   685  	bacc := authtypes.NewBaseAccountWithAddress(addr1)
   686  	vacc := vesting.NewContinuousVestingAccount(bacc, origCoins, ctx.BlockHeader().Time.Unix(), endTime.Unix())
   687  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr2)
   688  
   689  	app.AccountKeeper.SetAccount(ctx, macc)
   690  	app.AccountKeeper.SetAccount(ctx, vacc)
   691  	app.AccountKeeper.SetAccount(ctx, acc)
   692  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins))
   693  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, origCoins))
   694  
   695  	suite.Require().Equal(origCoins, app.BankKeeper.SpendableCoins(ctx, addr2))
   696  
   697  	ctx = ctx.WithBlockTime(now.Add(12 * time.Hour))
   698  	suite.Require().NoError(app.BankKeeper.DelegateCoins(ctx, addr2, addrModule, delCoins))
   699  	suite.Require().Equal(origCoins.Sub(delCoins), app.BankKeeper.SpendableCoins(ctx, addr1))
   700  }
   701  
   702  func (suite *IntegrationTestSuite) TestVestingAccountSend() {
   703  	app, ctx := suite.app, suite.ctx
   704  	now := osttime.Now()
   705  	ctx = ctx.WithBlockHeader(tmproto.Header{Time: now})
   706  	endTime := now.Add(24 * time.Hour)
   707  
   708  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   709  	sendCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   710  
   711  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   712  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   713  
   714  	bacc := authtypes.NewBaseAccountWithAddress(addr1)
   715  	vacc := vesting.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix())
   716  
   717  	app.AccountKeeper.SetAccount(ctx, vacc)
   718  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins))
   719  
   720  	// require that no coins be sendable at the beginning of the vesting schedule
   721  	suite.Require().Error(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins))
   722  
   723  	// receive some coins
   724  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, sendCoins))
   725  	// require that all vested coins are spendable plus any received
   726  	ctx = ctx.WithBlockTime(now.Add(12 * time.Hour))
   727  	suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins))
   728  	suite.Require().Equal(origCoins, app.BankKeeper.GetAllBalances(ctx, addr1))
   729  }
   730  
   731  func (suite *IntegrationTestSuite) TestPeriodicVestingAccountSend() {
   732  	app, ctx := suite.app, suite.ctx
   733  	now := osttime.Now()
   734  	ctx = ctx.WithBlockHeader(tmproto.Header{Time: now})
   735  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   736  	sendCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   737  
   738  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   739  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   740  	periods := vesting.Periods{
   741  		vesting.Period{Length: int64(12 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("stake", 50)}},
   742  		vesting.Period{Length: int64(6 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("stake", 25)}},
   743  		vesting.Period{Length: int64(6 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("stake", 25)}},
   744  	}
   745  
   746  	bacc := authtypes.NewBaseAccountWithAddress(addr1)
   747  	vacc := vesting.NewPeriodicVestingAccount(bacc, origCoins, ctx.BlockHeader().Time.Unix(), periods)
   748  
   749  	app.AccountKeeper.SetAccount(ctx, vacc)
   750  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins))
   751  
   752  	// require that no coins be sendable at the beginning of the vesting schedule
   753  	suite.Require().Error(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins))
   754  
   755  	// receive some coins
   756  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, sendCoins))
   757  
   758  	// require that all vested coins are spendable plus any received
   759  	ctx = ctx.WithBlockTime(now.Add(12 * time.Hour))
   760  	suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins))
   761  	suite.Require().Equal(origCoins, app.BankKeeper.GetAllBalances(ctx, addr1))
   762  }
   763  
   764  func (suite *IntegrationTestSuite) TestVestingAccountReceive() {
   765  	app, ctx := suite.app, suite.ctx
   766  	now := osttime.Now()
   767  	ctx = ctx.WithBlockHeader(tmproto.Header{Time: now})
   768  	endTime := now.Add(24 * time.Hour)
   769  
   770  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   771  	sendCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   772  
   773  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   774  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   775  
   776  	bacc := authtypes.NewBaseAccountWithAddress(addr1)
   777  	vacc := vesting.NewContinuousVestingAccount(bacc, origCoins, ctx.BlockHeader().Time.Unix(), endTime.Unix())
   778  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr2)
   779  
   780  	app.AccountKeeper.SetAccount(ctx, vacc)
   781  	app.AccountKeeper.SetAccount(ctx, acc)
   782  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins))
   783  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, origCoins))
   784  
   785  	// send some coins to the vesting account
   786  	suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr2, addr1, sendCoins))
   787  
   788  	// require the coins are spendable
   789  	vacc = app.AccountKeeper.GetAccount(ctx, addr1).(*vesting.ContinuousVestingAccount)
   790  	balances := app.BankKeeper.GetAllBalances(ctx, addr1)
   791  	suite.Require().Equal(origCoins.Add(sendCoins...), balances)
   792  	suite.Require().Equal(balances.Sub(vacc.LockedCoins(now)), sendCoins)
   793  
   794  	// require coins are spendable plus any that have vested
   795  	suite.Require().Equal(balances.Sub(vacc.LockedCoins(now.Add(12*time.Hour))), origCoins)
   796  }
   797  
   798  func (suite *IntegrationTestSuite) TestPeriodicVestingAccountReceive() {
   799  	app, ctx := suite.app, suite.ctx
   800  	now := osttime.Now()
   801  	ctx = ctx.WithBlockHeader(tmproto.Header{Time: now})
   802  
   803  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   804  	sendCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   805  
   806  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   807  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   808  
   809  	bacc := authtypes.NewBaseAccountWithAddress(addr1)
   810  	periods := vesting.Periods{
   811  		vesting.Period{Length: int64(12 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("stake", 50)}},
   812  		vesting.Period{Length: int64(6 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("stake", 25)}},
   813  		vesting.Period{Length: int64(6 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("stake", 25)}},
   814  	}
   815  
   816  	vacc := vesting.NewPeriodicVestingAccount(bacc, origCoins, ctx.BlockHeader().Time.Unix(), periods)
   817  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr2)
   818  
   819  	app.AccountKeeper.SetAccount(ctx, vacc)
   820  	app.AccountKeeper.SetAccount(ctx, acc)
   821  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins))
   822  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, origCoins))
   823  
   824  	// send some coins to the vesting account
   825  	suite.Require().NoError(app.BankKeeper.SendCoins(ctx, addr2, addr1, sendCoins))
   826  
   827  	// require the coins are spendable
   828  	vacc = app.AccountKeeper.GetAccount(ctx, addr1).(*vesting.PeriodicVestingAccount)
   829  	balances := app.BankKeeper.GetAllBalances(ctx, addr1)
   830  	suite.Require().Equal(origCoins.Add(sendCoins...), balances)
   831  	suite.Require().Equal(balances.Sub(vacc.LockedCoins(now)), sendCoins)
   832  
   833  	// require coins are spendable plus any that have vested
   834  	suite.Require().Equal(balances.Sub(vacc.LockedCoins(now.Add(12*time.Hour))), origCoins)
   835  }
   836  
   837  func (suite *IntegrationTestSuite) TestDelegateCoins() {
   838  	app, ctx := suite.app, suite.ctx
   839  	now := osttime.Now()
   840  	ctx = ctx.WithBlockHeader(tmproto.Header{Time: now})
   841  	endTime := now.Add(24 * time.Hour)
   842  
   843  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   844  	delCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   845  
   846  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   847  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   848  	addrModule := sdk.AccAddress([]byte("moduleAcc___________"))
   849  
   850  	macc := app.AccountKeeper.NewAccountWithAddress(ctx, addrModule) // we don't need to define an actual module account bc we just need the address for testing
   851  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr2)
   852  	bacc := authtypes.NewBaseAccountWithAddress(addr1)
   853  	vacc := vesting.NewContinuousVestingAccount(bacc, origCoins, ctx.BlockHeader().Time.Unix(), endTime.Unix())
   854  
   855  	app.AccountKeeper.SetAccount(ctx, vacc)
   856  	app.AccountKeeper.SetAccount(ctx, acc)
   857  	app.AccountKeeper.SetAccount(ctx, macc)
   858  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins))
   859  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, origCoins))
   860  
   861  	ctx = ctx.WithBlockTime(now.Add(12 * time.Hour))
   862  
   863  	// require the ability for a non-vesting account to delegate
   864  	suite.Require().NoError(app.BankKeeper.DelegateCoins(ctx, addr2, addrModule, delCoins))
   865  	suite.Require().Equal(origCoins.Sub(delCoins), app.BankKeeper.GetAllBalances(ctx, addr2))
   866  	suite.Require().Equal(delCoins, app.BankKeeper.GetAllBalances(ctx, addrModule))
   867  
   868  	// require the ability for a vesting account to delegate
   869  	suite.Require().NoError(app.BankKeeper.DelegateCoins(ctx, addr1, addrModule, delCoins))
   870  	suite.Require().Equal(delCoins, app.BankKeeper.GetAllBalances(ctx, addr1))
   871  
   872  	// require that delegated vesting amount is equal to what was delegated with DelegateCoins
   873  	acc = app.AccountKeeper.GetAccount(ctx, addr1)
   874  	vestingAcc, ok := acc.(exported.VestingAccount)
   875  	suite.Require().True(ok)
   876  	suite.Require().Equal(delCoins, vestingAcc.GetDelegatedVesting())
   877  }
   878  
   879  func (suite *IntegrationTestSuite) TestDelegateCoins_Invalid() {
   880  	app, ctx := suite.app, suite.ctx
   881  
   882  	origCoins := sdk.NewCoins(newFooCoin(100))
   883  	delCoins := sdk.NewCoins(newFooCoin(50))
   884  
   885  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   886  	addrModule := sdk.AccAddress([]byte("moduleAcc___________"))
   887  	macc := app.AccountKeeper.NewAccountWithAddress(ctx, addrModule) // we don't need to define an actual module account bc we just need the address for testing
   888  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
   889  
   890  	suite.Require().Error(app.BankKeeper.DelegateCoins(ctx, addr1, addrModule, delCoins))
   891  	invalidCoins := sdk.Coins{sdk.Coin{Denom: "fooDenom", Amount: sdk.NewInt(-50)}}
   892  	suite.Require().Error(app.BankKeeper.DelegateCoins(ctx, addr1, addrModule, invalidCoins))
   893  
   894  	app.AccountKeeper.SetAccount(ctx, macc)
   895  	suite.Require().Error(app.BankKeeper.DelegateCoins(ctx, addr1, addrModule, delCoins))
   896  	app.AccountKeeper.SetAccount(ctx, acc)
   897  	suite.Require().Error(app.BankKeeper.DelegateCoins(ctx, addr1, addrModule, origCoins.Add(origCoins...)))
   898  }
   899  
   900  func (suite *IntegrationTestSuite) TestUndelegateCoins() {
   901  	app, ctx := suite.app, suite.ctx
   902  	now := osttime.Now()
   903  	ctx = ctx.WithBlockHeader(tmproto.Header{Time: now})
   904  	endTime := now.Add(24 * time.Hour)
   905  
   906  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   907  	delCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   908  
   909  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   910  	addr2 := sdk.AccAddress([]byte("addr2_______________"))
   911  	addrModule := sdk.AccAddress([]byte("moduleAcc___________"))
   912  
   913  	bacc := authtypes.NewBaseAccountWithAddress(addr1)
   914  	macc := app.AccountKeeper.NewAccountWithAddress(ctx, addrModule) // we don't need to define an actual module account bc we just need the address for testing
   915  
   916  	vacc := vesting.NewContinuousVestingAccount(bacc, origCoins, ctx.BlockHeader().Time.Unix(), endTime.Unix())
   917  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr2)
   918  
   919  	app.AccountKeeper.SetAccount(ctx, vacc)
   920  	app.AccountKeeper.SetAccount(ctx, acc)
   921  	app.AccountKeeper.SetAccount(ctx, macc)
   922  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins))
   923  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr2, origCoins))
   924  
   925  	ctx = ctx.WithBlockTime(now.Add(12 * time.Hour))
   926  
   927  	// require the ability for a non-vesting account to delegate
   928  	err := app.BankKeeper.DelegateCoins(ctx, addr2, addrModule, delCoins)
   929  	suite.Require().NoError(err)
   930  
   931  	suite.Require().Equal(origCoins.Sub(delCoins), app.BankKeeper.GetAllBalances(ctx, addr2))
   932  	suite.Require().Equal(delCoins, app.BankKeeper.GetAllBalances(ctx, addrModule))
   933  
   934  	// require the ability for a non-vesting account to undelegate
   935  	suite.Require().NoError(app.BankKeeper.UndelegateCoins(ctx, addrModule, addr2, delCoins))
   936  
   937  	suite.Require().Equal(origCoins, app.BankKeeper.GetAllBalances(ctx, addr2))
   938  	suite.Require().True(app.BankKeeper.GetAllBalances(ctx, addrModule).Empty())
   939  
   940  	// require the ability for a vesting account to delegate
   941  	suite.Require().NoError(app.BankKeeper.DelegateCoins(ctx, addr1, addrModule, delCoins))
   942  
   943  	suite.Require().Equal(origCoins.Sub(delCoins), app.BankKeeper.GetAllBalances(ctx, addr1))
   944  	suite.Require().Equal(delCoins, app.BankKeeper.GetAllBalances(ctx, addrModule))
   945  
   946  	// require the ability for a vesting account to undelegate
   947  	suite.Require().NoError(app.BankKeeper.UndelegateCoins(ctx, addrModule, addr1, delCoins))
   948  
   949  	suite.Require().Equal(origCoins, app.BankKeeper.GetAllBalances(ctx, addr1))
   950  	suite.Require().True(app.BankKeeper.GetAllBalances(ctx, addrModule).Empty())
   951  
   952  	// require that delegated vesting amount is completely empty, since they were completely undelegated
   953  	acc = app.AccountKeeper.GetAccount(ctx, addr1)
   954  	vestingAcc, ok := acc.(exported.VestingAccount)
   955  	suite.Require().True(ok)
   956  	suite.Require().Empty(vestingAcc.GetDelegatedVesting())
   957  }
   958  
   959  func (suite *IntegrationTestSuite) TestUndelegateCoins_Invalid() {
   960  	app, ctx := suite.app, suite.ctx
   961  
   962  	origCoins := sdk.NewCoins(newFooCoin(100))
   963  	delCoins := sdk.NewCoins(newFooCoin(50))
   964  
   965  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   966  	addrModule := sdk.AccAddress([]byte("moduleAcc___________"))
   967  	macc := app.AccountKeeper.NewAccountWithAddress(ctx, addrModule) // we don't need to define an actual module account bc we just need the address for testing
   968  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
   969  
   970  	suite.Require().Error(app.BankKeeper.UndelegateCoins(ctx, addrModule, addr1, delCoins))
   971  
   972  	app.AccountKeeper.SetAccount(ctx, macc)
   973  	suite.Require().NoError(simapp.FundAccount(app, ctx, addr1, origCoins))
   974  
   975  	suite.Require().Error(app.BankKeeper.UndelegateCoins(ctx, addrModule, addr1, delCoins))
   976  	app.AccountKeeper.SetAccount(ctx, acc)
   977  
   978  	suite.Require().Error(app.BankKeeper.UndelegateCoins(ctx, addrModule, addr1, delCoins))
   979  }
   980  
   981  func (suite *IntegrationTestSuite) TestSetDenomMetaData() {
   982  	app, ctx := suite.app, suite.ctx
   983  
   984  	metadata := suite.getTestMetadata()
   985  
   986  	for i := range []int{1, 2} {
   987  		app.BankKeeper.SetDenomMetaData(ctx, metadata[i])
   988  	}
   989  
   990  	actualMetadata, found := app.BankKeeper.GetDenomMetaData(ctx, metadata[1].Base)
   991  	suite.Require().True(found)
   992  	suite.Require().Equal(metadata[1].GetBase(), actualMetadata.GetBase())
   993  	suite.Require().Equal(metadata[1].GetDisplay(), actualMetadata.GetDisplay())
   994  	suite.Require().Equal(metadata[1].GetDescription(), actualMetadata.GetDescription())
   995  	suite.Require().Equal(metadata[1].GetDenomUnits()[1].GetDenom(), actualMetadata.GetDenomUnits()[1].GetDenom())
   996  	suite.Require().Equal(metadata[1].GetDenomUnits()[1].GetExponent(), actualMetadata.GetDenomUnits()[1].GetExponent())
   997  	suite.Require().Equal(metadata[1].GetDenomUnits()[1].GetAliases(), actualMetadata.GetDenomUnits()[1].GetAliases())
   998  }
   999  
  1000  func (suite *IntegrationTestSuite) TestIterateAllDenomMetaData() {
  1001  	app, ctx := suite.app, suite.ctx
  1002  
  1003  	expectedMetadata := suite.getTestMetadata()
  1004  	// set metadata
  1005  	for i := range []int{1, 2} {
  1006  		app.BankKeeper.SetDenomMetaData(ctx, expectedMetadata[i])
  1007  	}
  1008  	// retrieve metadata
  1009  	actualMetadata := make([]types.Metadata, 0)
  1010  	app.BankKeeper.IterateAllDenomMetaData(ctx, func(metadata types.Metadata) bool {
  1011  		actualMetadata = append(actualMetadata, metadata)
  1012  		return false
  1013  	})
  1014  	// execute checks
  1015  	for i := range []int{1, 2} {
  1016  		suite.Require().Equal(expectedMetadata[i].GetBase(), actualMetadata[i].GetBase())
  1017  		suite.Require().Equal(expectedMetadata[i].GetDisplay(), actualMetadata[i].GetDisplay())
  1018  		suite.Require().Equal(expectedMetadata[i].GetDescription(), actualMetadata[i].GetDescription())
  1019  		suite.Require().Equal(expectedMetadata[i].GetDenomUnits()[1].GetDenom(), actualMetadata[i].GetDenomUnits()[1].GetDenom())
  1020  		suite.Require().Equal(expectedMetadata[i].GetDenomUnits()[1].GetExponent(), actualMetadata[i].GetDenomUnits()[1].GetExponent())
  1021  		suite.Require().Equal(expectedMetadata[i].GetDenomUnits()[1].GetAliases(), actualMetadata[i].GetDenomUnits()[1].GetAliases())
  1022  	}
  1023  }
  1024  
  1025  func (suite *IntegrationTestSuite) TestBalanceTrackingEvents() {
  1026  	// replace account keeper and bank keeper otherwise the account keeper won't be aware of the
  1027  	// existence of the new module account because GetModuleAccount checks for the existence via
  1028  	// permissions map and not via state... weird
  1029  	maccPerms := simapp.GetMaccPerms()
  1030  	maccPerms[multiPerm] = []string{authtypes.Burner, authtypes.Minter, authtypes.Staking}
  1031  
  1032  	suite.app.AccountKeeper = authkeeper.NewAccountKeeper(
  1033  		suite.app.AppCodec(), suite.app.GetKey(authtypes.StoreKey), suite.app.GetSubspace(authtypes.ModuleName),
  1034  		authtypes.ProtoBaseAccount, maccPerms,
  1035  	)
  1036  
  1037  	suite.app.BankKeeper = keeper.NewBaseKeeper(suite.app.AppCodec(), suite.app.GetKey(types.StoreKey),
  1038  		suite.app.AccountKeeper, suite.app.GetSubspace(types.ModuleName), nil)
  1039  
  1040  	// set account with multiple permissions
  1041  	suite.app.AccountKeeper.SetModuleAccount(suite.ctx, multiPermAcc)
  1042  	// mint coins
  1043  	suite.Require().NoError(
  1044  		suite.app.BankKeeper.MintCoins(
  1045  			suite.ctx,
  1046  			multiPermAcc.Name,
  1047  			sdk.NewCoins(sdk.NewCoin("utxo", sdk.NewInt(100000)))),
  1048  	)
  1049  	// send coins to address
  1050  	addr1 := sdk.AccAddress("addr1_______________")
  1051  	suite.Require().NoError(
  1052  		suite.app.BankKeeper.SendCoinsFromModuleToAccount(
  1053  			suite.ctx,
  1054  			multiPermAcc.Name,
  1055  			addr1,
  1056  			sdk.NewCoins(sdk.NewCoin("utxo", sdk.NewInt(50000))),
  1057  		),
  1058  	)
  1059  
  1060  	// burn coins from module account
  1061  	suite.Require().NoError(
  1062  		suite.app.BankKeeper.BurnCoins(
  1063  			suite.ctx,
  1064  			multiPermAcc.Name,
  1065  			sdk.NewCoins(sdk.NewInt64Coin("utxo", 1000)),
  1066  		),
  1067  	)
  1068  
  1069  	// process balances and supply from events
  1070  	supply := sdk.NewCoins()
  1071  
  1072  	balances := make(map[string]sdk.Coins)
  1073  
  1074  	for _, e := range suite.ctx.EventManager().ABCIEvents() {
  1075  		switch e.Type {
  1076  		case types.EventTypeCoinBurn:
  1077  			burnedCoins, err := sdk.ParseCoinsNormalized((string)(e.Attributes[1].Value))
  1078  			suite.Require().NoError(err)
  1079  			supply = supply.Sub(burnedCoins)
  1080  
  1081  		case types.EventTypeCoinMint:
  1082  			mintedCoins, err := sdk.ParseCoinsNormalized((string)(e.Attributes[1].Value))
  1083  			suite.Require().NoError(err)
  1084  			supply = supply.Add(mintedCoins...)
  1085  
  1086  		case types.EventTypeCoinSpent:
  1087  			coinsSpent, err := sdk.ParseCoinsNormalized((string)(e.Attributes[1].Value))
  1088  			suite.Require().NoError(err)
  1089  			spender, err := sdk.AccAddressFromBech32((string)(e.Attributes[0].Value))
  1090  			suite.Require().NoError(err)
  1091  			balances[spender.String()] = balances[spender.String()].Sub(coinsSpent)
  1092  
  1093  		case types.EventTypeCoinReceived:
  1094  			coinsRecv, err := sdk.ParseCoinsNormalized((string)(e.Attributes[1].Value))
  1095  			suite.Require().NoError(err)
  1096  			receiver, err := sdk.AccAddressFromBech32((string)(e.Attributes[0].Value))
  1097  			suite.Require().NoError(err)
  1098  			balances[receiver.String()] = balances[receiver.String()].Add(coinsRecv...)
  1099  		}
  1100  	}
  1101  
  1102  	// check balance and supply tracking
  1103  	suite.Require().True(suite.app.BankKeeper.HasSupply(suite.ctx, "utxo"))
  1104  	savedSupply := suite.app.BankKeeper.GetSupply(suite.ctx, "utxo")
  1105  	utxoSupply := savedSupply
  1106  	suite.Require().Equal(utxoSupply.Amount, supply.AmountOf("utxo"))
  1107  	// iterate accounts and check balances
  1108  	suite.app.BankKeeper.IterateAllBalances(suite.ctx, func(address sdk.AccAddress, coin sdk.Coin) (stop bool) {
  1109  		// if it's not utxo coin then skip
  1110  		if coin.Denom != "utxo" {
  1111  			return false
  1112  		}
  1113  
  1114  		balance, exists := balances[address.String()]
  1115  		suite.Require().True(exists)
  1116  
  1117  		expectedUtxo := sdk.NewCoin("utxo", balance.AmountOf(coin.Denom))
  1118  		suite.Require().Equal(expectedUtxo.String(), coin.String())
  1119  		return false
  1120  	})
  1121  }
  1122  
  1123  func (suite *IntegrationTestSuite) getTestMetadata() []types.Metadata {
  1124  	return []types.Metadata{
  1125  		{
  1126  			Name:        "Cosmos Hub Atom",
  1127  			Symbol:      "ATOM",
  1128  			Description: "The native staking token of the Cosmos Hub.",
  1129  			DenomUnits: []*types.DenomUnit{
  1130  				{Denom: "uatom", Exponent: uint32(0), Aliases: []string{"microatom"}},
  1131  				{Denom: "matom", Exponent: uint32(3), Aliases: []string{"milliatom"}},
  1132  				{Denom: "atom", Exponent: uint32(6), Aliases: nil},
  1133  			},
  1134  			Base:    "uatom",
  1135  			Display: "atom",
  1136  		},
  1137  		{
  1138  			Name:        "Token",
  1139  			Symbol:      "TOKEN",
  1140  			Description: "The native staking token of the Token Hub.",
  1141  			DenomUnits: []*types.DenomUnit{
  1142  				{Denom: "1token", Exponent: uint32(5), Aliases: []string{"decitoken"}},
  1143  				{Denom: "2token", Exponent: uint32(4), Aliases: []string{"centitoken"}},
  1144  				{Denom: "3token", Exponent: uint32(7), Aliases: []string{"dekatoken"}},
  1145  			},
  1146  			Base:    "utoken",
  1147  			Display: "token",
  1148  		},
  1149  	}
  1150  }
  1151  
  1152  func (suite *IntegrationTestSuite) TestMintCoinRestrictions() {
  1153  	type BankMintingRestrictionFn func(ctx sdk.Context, coins sdk.Coins) error
  1154  
  1155  	maccPerms := simapp.GetMaccPerms()
  1156  	maccPerms[multiPerm] = []string{authtypes.Burner, authtypes.Minter, authtypes.Staking}
  1157  
  1158  	suite.app.AccountKeeper = authkeeper.NewAccountKeeper(
  1159  		suite.app.AppCodec(), suite.app.GetKey(authtypes.StoreKey), suite.app.GetSubspace(authtypes.ModuleName),
  1160  		authtypes.ProtoBaseAccount, maccPerms,
  1161  	)
  1162  	suite.app.AccountKeeper.SetModuleAccount(suite.ctx, multiPermAcc)
  1163  
  1164  	type testCase struct {
  1165  		coinsToTry sdk.Coin
  1166  		expectPass bool
  1167  	}
  1168  
  1169  	tests := []struct {
  1170  		name          string
  1171  		restrictionFn BankMintingRestrictionFn
  1172  		testCases     []testCase
  1173  	}{
  1174  		{
  1175  			"restriction",
  1176  			func(ctx sdk.Context, coins sdk.Coins) error {
  1177  				for _, coin := range coins {
  1178  					if coin.Denom != fooDenom {
  1179  						return fmt.Errorf("Module %s only has perms for minting %s coins, tried minting %s coins", types.ModuleName, fooDenom, coin.Denom)
  1180  					}
  1181  				}
  1182  				return nil
  1183  			},
  1184  			[]testCase{
  1185  				{
  1186  					coinsToTry: newFooCoin(100),
  1187  					expectPass: true,
  1188  				},
  1189  				{
  1190  					coinsToTry: newBarCoin(100),
  1191  					expectPass: false,
  1192  				},
  1193  			},
  1194  		},
  1195  	}
  1196  
  1197  	for _, test := range tests {
  1198  		suite.app.BankKeeper = keeper.NewBaseKeeper(suite.app.AppCodec(), suite.app.GetKey(types.StoreKey),
  1199  			suite.app.AccountKeeper, suite.app.GetSubspace(types.ModuleName), nil).WithMintCoinsRestriction(keeper.MintingRestrictionFn(test.restrictionFn))
  1200  		for _, testCase := range test.testCases {
  1201  			if testCase.expectPass {
  1202  				suite.Require().NoError(
  1203  					suite.app.BankKeeper.MintCoins(
  1204  						suite.ctx,
  1205  						multiPermAcc.Name,
  1206  						sdk.NewCoins(testCase.coinsToTry),
  1207  					),
  1208  				)
  1209  			} else {
  1210  				suite.Require().Error(
  1211  					suite.app.BankKeeper.MintCoins(
  1212  						suite.ctx,
  1213  						multiPermAcc.Name,
  1214  						sdk.NewCoins(testCase.coinsToTry),
  1215  					),
  1216  				)
  1217  			}
  1218  		}
  1219  	}
  1220  }
  1221  
  1222  func TestKeeperTestSuite(t *testing.T) {
  1223  	suite.Run(t, new(IntegrationTestSuite))
  1224  }