github.com/Finschia/finschia-sdk@v0.48.1/x/bank/keeper/keeper_test.go (about) 1 package keeper_test 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/suite" 9 abci "github.com/tendermint/tendermint/abci/types" 10 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 11 12 osttime "github.com/Finschia/ostracon/types/time" 13 14 "github.com/Finschia/finschia-sdk/baseapp" 15 "github.com/Finschia/finschia-sdk/simapp" 16 sdk "github.com/Finschia/finschia-sdk/types" 17 "github.com/Finschia/finschia-sdk/types/query" 18 authkeeper "github.com/Finschia/finschia-sdk/x/auth/keeper" 19 authtypes "github.com/Finschia/finschia-sdk/x/auth/types" 20 "github.com/Finschia/finschia-sdk/x/auth/vesting/exported" 21 vesting "github.com/Finschia/finschia-sdk/x/auth/vesting/types" 22 "github.com/Finschia/finschia-sdk/x/bank/keeper" 23 "github.com/Finschia/finschia-sdk/x/bank/types" 24 minttypes "github.com/Finschia/finschia-sdk/x/mint/types" 25 ) 26 27 const ( 28 fooDenom = "foo" 29 barDenom = "bar" 30 initialPower = int64(100) 31 holder = "holder" 32 multiPerm = "multiple permissions account" 33 randomPerm = "random permission" 34 ) 35 36 var ( 37 holderAcc = authtypes.NewEmptyModuleAccount(holder) 38 burnerAcc = authtypes.NewEmptyModuleAccount(authtypes.Burner, authtypes.Burner) 39 minterAcc = authtypes.NewEmptyModuleAccount(authtypes.Minter, authtypes.Minter) 40 multiPermAcc = authtypes.NewEmptyModuleAccount(multiPerm, authtypes.Burner, authtypes.Minter, authtypes.Staking) 41 randomPermAcc = authtypes.NewEmptyModuleAccount(randomPerm, "random") 42 43 // The default power validators are initialized to have within tests 44 initTokens = sdk.TokensFromConsensusPower(initialPower, sdk.DefaultPowerReduction) 45 initCoins = sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)) 46 ) 47 48 func newFooCoin(amt int64) sdk.Coin { 49 return sdk.NewInt64Coin(fooDenom, amt) 50 } 51 52 func newBarCoin(amt int64) sdk.Coin { 53 return sdk.NewInt64Coin(barDenom, amt) 54 } 55 56 // nolint: interfacer 57 func getCoinsByName(ctx sdk.Context, bk keeper.Keeper, ak types.AccountKeeper, moduleName string) sdk.Coins { 58 moduleAddress := ak.GetModuleAddress(moduleName) 59 macc := ak.GetAccount(ctx, moduleAddress) 60 if macc == nil { 61 return sdk.Coins(nil) 62 } 63 64 return bk.GetAllBalances(ctx, macc.GetAddress()) 65 } 66 67 type IntegrationTestSuite struct { 68 suite.Suite 69 70 app *simapp.SimApp 71 ctx sdk.Context 72 queryClient types.QueryClient 73 } 74 75 func (suite *IntegrationTestSuite) initKeepersWithmAccPerms(blockedAddrs map[string]bool) (authkeeper.AccountKeeper, keeper.BaseKeeper) { 76 app := suite.app 77 maccPerms := simapp.GetMaccPerms() 78 appCodec := simapp.MakeTestEncodingConfig().Marshaler 79 80 maccPerms[holder] = nil 81 maccPerms[authtypes.Burner] = []string{authtypes.Burner} 82 maccPerms[authtypes.Minter] = []string{authtypes.Minter} 83 maccPerms[multiPerm] = []string{authtypes.Burner, authtypes.Minter, authtypes.Staking} 84 maccPerms[randomPerm] = []string{"random"} 85 authKeeper := authkeeper.NewAccountKeeper( 86 appCodec, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName), 87 authtypes.ProtoBaseAccount, maccPerms, 88 ) 89 keeper := keeper.NewBaseKeeper( 90 appCodec, app.GetKey(types.StoreKey), authKeeper, 91 app.GetSubspace(types.ModuleName), blockedAddrs, 92 ) 93 94 return authKeeper, keeper 95 } 96 97 func (suite *IntegrationTestSuite) SetupTest() { 98 app := simapp.Setup(false) 99 ctx := app.BaseApp.NewContext(false, tmproto.Header{Time: time.Now()}) 100 101 app.AccountKeeper.SetParams(ctx, authtypes.DefaultParams()) 102 app.BankKeeper.SetParams(ctx, types.DefaultParams()) 103 104 queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry()) 105 types.RegisterQueryServer(queryHelper, app.BankKeeper) 106 queryClient := types.NewQueryClient(queryHelper) 107 108 suite.app = app 109 suite.ctx = ctx 110 suite.queryClient = queryClient 111 } 112 113 func (suite *IntegrationTestSuite) TestSupply() { 114 ctx := suite.ctx 115 116 require := suite.Require() 117 118 // add module accounts to supply keeper 119 authKeeper, keeper := suite.initKeepersWithmAccPerms(make(map[string]bool)) 120 121 initialPower := int64(100) 122 initTokens := suite.app.StakingKeeper.TokensFromConsensusPower(ctx, initialPower) 123 totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)) 124 125 // set burnerAcc balance 126 authKeeper.SetModuleAccount(ctx, burnerAcc) 127 require.NoError(keeper.MintCoins(ctx, authtypes.Minter, totalSupply)) 128 require.NoError(keeper.SendCoinsFromModuleToAccount(ctx, authtypes.Minter, burnerAcc.GetAddress(), totalSupply)) 129 130 total, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) 131 require.NoError(err) 132 require.Equal(totalSupply, total) 133 134 // burning all supplied tokens 135 err = keeper.BurnCoins(ctx, authtypes.Burner, totalSupply) 136 require.NoError(err) 137 138 total, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) 139 require.NoError(err) 140 require.Equal(total.String(), "") 141 } 142 143 func (suite *IntegrationTestSuite) TestSendCoinsFromModuleToAccount_Blacklist() { 144 app := suite.app 145 ctx := app.BaseApp.NewContext(false, tmproto.Header{Height: 1}) 146 maccPerms := simapp.GetMaccPerms() 147 appCodec := app.AppCodec() 148 149 // add module accounts to supply keeper 150 maccPerms[holder] = nil 151 maccPerms[authtypes.Burner] = []string{authtypes.Burner} 152 maccPerms[authtypes.Minter] = []string{authtypes.Minter} 153 maccPerms[multiPerm] = []string{authtypes.Burner, authtypes.Minter, authtypes.Staking} 154 maccPerms[randomPerm] = []string{"random"} 155 156 addr1 := sdk.AccAddress([]byte("addr1_______________")) 157 158 authKeeper := authkeeper.NewAccountKeeper( 159 appCodec, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName), 160 authtypes.ProtoBaseAccount, maccPerms, 161 ) 162 keeper := keeper.NewBaseKeeper( 163 appCodec, app.GetKey(types.StoreKey), authKeeper, 164 app.GetSubspace(types.ModuleName), map[string]bool{addr1.String(): true}, 165 ) 166 167 suite.Require().NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins)) 168 suite.Require().Error(keeper.SendCoinsFromModuleToAccount( 169 ctx, minttypes.ModuleName, addr1, initCoins, 170 )) 171 } 172 173 func (suite *IntegrationTestSuite) TestSupply_SendCoins() { 174 ctx := suite.ctx 175 176 // add module accounts to supply keeper 177 authKeeper, keeper := suite.initKeepersWithmAccPerms(make(map[string]bool)) 178 179 baseAcc := authKeeper.NewAccountWithAddress(ctx, authtypes.NewModuleAddress("baseAcc")) 180 181 // set initial balances 182 suite. 183 Require(). 184 NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins)) 185 186 suite. 187 Require(). 188 NoError(keeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, holderAcc.GetAddress(), initCoins)) 189 190 authKeeper.SetModuleAccount(ctx, holderAcc) 191 authKeeper.SetModuleAccount(ctx, burnerAcc) 192 authKeeper.SetAccount(ctx, baseAcc) 193 194 suite.Require().Panics(func() { 195 _ = keeper.SendCoinsFromModuleToModule(ctx, "", holderAcc.GetName(), initCoins) // nolint:errcheck 196 }) 197 198 suite.Require().Panics(func() { 199 _ = keeper.SendCoinsFromModuleToModule(ctx, authtypes.Burner, "", initCoins) // nolint:errcheck 200 }) 201 202 suite.Require().Panics(func() { 203 _ = keeper.SendCoinsFromModuleToAccount(ctx, "", baseAcc.GetAddress(), initCoins) // nolint:errcheck 204 }) 205 206 suite.Require().Error( 207 keeper.SendCoinsFromModuleToAccount(ctx, holderAcc.GetName(), baseAcc.GetAddress(), initCoins.Add(initCoins...)), 208 ) 209 210 suite.Require().NoError( 211 keeper.SendCoinsFromModuleToModule(ctx, holderAcc.GetName(), authtypes.Burner, initCoins), 212 ) 213 suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, holderAcc.GetName()).String()) 214 suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner)) 215 216 suite.Require().NoError( 217 keeper.SendCoinsFromModuleToAccount(ctx, authtypes.Burner, baseAcc.GetAddress(), initCoins), 218 ) 219 suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner).String()) 220 suite.Require().Equal(initCoins, keeper.GetAllBalances(ctx, baseAcc.GetAddress())) 221 222 suite.Require().NoError(keeper.SendCoinsFromAccountToModule(ctx, baseAcc.GetAddress(), authtypes.Burner, initCoins)) 223 suite.Require().Equal(sdk.NewCoins().String(), keeper.GetAllBalances(ctx, baseAcc.GetAddress()).String()) 224 suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner)) 225 } 226 227 func (suite *IntegrationTestSuite) TestSupply_MintCoins() { 228 ctx := suite.ctx 229 230 // add module accounts to supply keeper 231 authKeeper, keeper := suite.initKeepersWithmAccPerms(make(map[string]bool)) 232 233 authKeeper.SetModuleAccount(ctx, burnerAcc) 234 authKeeper.SetModuleAccount(ctx, minterAcc) 235 authKeeper.SetModuleAccount(ctx, multiPermAcc) 236 authKeeper.SetModuleAccount(ctx, randomPermAcc) 237 238 initialSupply, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) 239 suite.Require().NoError(err) 240 241 suite.Require().Panics(func() { keeper.MintCoins(ctx, "", initCoins) }, "no module account") // nolint:errcheck 242 suite.Require().Panics(func() { keeper.MintCoins(ctx, authtypes.Burner, initCoins) }, "invalid permission") // nolint:errcheck 243 244 err = keeper.MintCoins(ctx, authtypes.Minter, sdk.Coins{sdk.Coin{Denom: "denom", Amount: sdk.NewInt(-10)}}) 245 suite.Require().Error(err, "insufficient coins") 246 247 suite.Require().Panics(func() { keeper.MintCoins(ctx, randomPerm, initCoins) }) // nolint:errcheck 248 249 err = keeper.MintCoins(ctx, authtypes.Minter, initCoins) 250 suite.Require().NoError(err) 251 252 suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Minter)) 253 totalSupply, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) 254 suite.Require().NoError(err) 255 256 suite.Require().Equal(initialSupply.Add(initCoins...), totalSupply) 257 258 // test same functionality on module account with multiple permissions 259 initialSupply, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) 260 suite.Require().NoError(err) 261 262 err = keeper.MintCoins(ctx, multiPermAcc.GetName(), initCoins) 263 suite.Require().NoError(err) 264 265 totalSupply, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) 266 suite.Require().NoError(err) 267 suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, multiPermAcc.GetName())) 268 suite.Require().Equal(initialSupply.Add(initCoins...), totalSupply) 269 suite.Require().Panics(func() { keeper.MintCoins(ctx, authtypes.Burner, initCoins) }) // nolint:errcheck 270 } 271 272 func (suite *IntegrationTestSuite) TestSupply_BurnCoins() { 273 ctx := suite.ctx 274 // add module accounts to supply keeper 275 authKeeper, keeper := suite.initKeepersWithmAccPerms(make(map[string]bool)) 276 277 // set burnerAcc balance 278 authKeeper.SetModuleAccount(ctx, burnerAcc) 279 suite. 280 Require(). 281 NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins)) 282 suite. 283 Require(). 284 NoError(keeper.SendCoinsFromModuleToAccount(ctx, authtypes.Minter, burnerAcc.GetAddress(), initCoins)) 285 286 // inflate supply 287 suite. 288 Require(). 289 NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins)) 290 supplyAfterInflation, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) 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 supplyAfterBurn, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) 317 suite.Require().NoError(err) 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 {"uatom", uint32(0), []string{"microatom"}}, 1131 {"matom", uint32(3), []string{"milliatom"}}, 1132 {"atom", uint32(6), 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 {"1token", uint32(5), []string{"decitoken"}}, 1143 {"2token", uint32(4), []string{"centitoken"}}, 1144 {"3token", uint32(7), []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 }