diff --git a/CHANGELOG.md b/CHANGELOG.md index cac2c35063..105028e1e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * (x/feegrant) [\#380] (https://github.com/line/lbm-sdk/pull/380) Feegrant module * (x/wasm) [\#395] (https://github.com/line/lbm-sdk/pull/395) Add the instantiate_permission in the CodeInfoResponse * (x/consortium) [\#406] (https://github.com/line/lbm-sdk/pull/406) Add CreateValidator access control feature +* (x/bank) [\#400] (https://github.com/line/lbm-sdk/pull/400) add `bankplus` function to restrict to send coin to inactive smart contract. ### Improvements * (slashing) [\#347](https://github.com/line/lbm-sdk/pull/347) Introduce VoterSetCounter diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index d9ec62f02e..2b6141ce33 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -296,6 +296,9 @@ - [Msg](#lbm.bank.v1.Msg) +- [lbm/bankplus/v1/bankplus.proto](#lbm/bankplus/v1/bankplus.proto) + - [InactiveAddr](#lbm.bankplus.v1.InactiveAddr) + - [lbm/base/abci/v1/abci.proto](#lbm/base/abci/v1/abci.proto) - [ABCIMessageLog](#lbm.base.abci.v1.ABCIMessageLog) - [Attribute](#lbm.base.abci.v1.Attribute) @@ -4853,6 +4856,37 @@ Msg defines the bank Msg service. + +

Top

+ +## lbm/bankplus/v1/bankplus.proto + + + + + +### InactiveAddr +InactiveAddr models the blocked address for the bankplus module + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | | + + + + + + + + + + + + + + +

Top

diff --git a/proto/lbm/bankplus/v1/bankplus.proto b/proto/lbm/bankplus/v1/bankplus.proto new file mode 100644 index 0000000000..32a0f720d7 --- /dev/null +++ b/proto/lbm/bankplus/v1/bankplus.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; +package lbm.bankplus.v1; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/line/lbm-sdk/x/bankplus/types"; + +// InactiveAddr models the blocked address for the bankplus module +message InactiveAddr { + option (gogoproto.equal) = true; + + string address = 1; +} diff --git a/simapp/app.go b/simapp/app.go index b0d26cf988..bca0d2a526 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -44,6 +44,8 @@ import ( "github.com/line/lbm-sdk/x/bank" bankkeeper "github.com/line/lbm-sdk/x/bank/keeper" banktypes "github.com/line/lbm-sdk/x/bank/types" + "github.com/line/lbm-sdk/x/bankplus" + bankpluskeeper "github.com/line/lbm-sdk/x/bankplus/keeper" "github.com/line/lbm-sdk/x/capability" capabilitykeeper "github.com/line/lbm-sdk/x/capability/keeper" capabilitytypes "github.com/line/lbm-sdk/x/capability/types" @@ -146,6 +148,11 @@ var ( govtypes.ModuleName: {authtypes.Burner}, ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, } + + // module accounts that are allowed to receive tokens + allowedReceivingModAcc = map[string]bool{ + distrtypes.ModuleName: true, + } ) var ( @@ -263,9 +270,8 @@ func NewSimApp( app.AccountKeeper = authkeeper.NewAccountKeeper( appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms, ) - app.BankKeeper = bankkeeper.NewBaseKeeper( - appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.ModuleAccountAddrs(), - ) + app.BankKeeper = bankpluskeeper.NewBaseKeeper( + appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs()) stakingKeeper := stakingkeeper.NewKeeper( appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName), ) @@ -352,7 +358,7 @@ func NewSimApp( ), auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), vesting.NewAppModule(app.AccountKeeper, app.BankKeeper), - bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), + bankplus.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), capability.NewAppModule(appCodec, *app.CapabilityKeeper), crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants), feegrant.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), @@ -405,7 +411,7 @@ func NewSimApp( // transactions app.sm = module.NewSimulationManager( auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), - bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), + bankplus.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), capability.NewAppModule(appCodec, *app.CapabilityKeeper), feegrant.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), @@ -450,6 +456,9 @@ func NewSimApp( // `loadLatest` is set to true. ctx := app.BaseApp.NewUncachedContext(true, ocproto.Header{}) app.CapabilityKeeper.InitializeAndSeal(ctx) + + // Initialize the keeper of bankkeeper + app.BankKeeper.(bankpluskeeper.Keeper).InitializeBankPlus(ctx) } app.ScopedIBCKeeper = scopedIBCKeeper @@ -508,6 +517,17 @@ func (app *SimApp) ModuleAccountAddrs() map[string]bool { return modAccAddrs } +// BlockedAddrs returns all the app's module account addresses that are not +// allowed to receive external tokens. +func (app *SimApp) BlockedAddrs() map[string]bool { + blockedAddrs := make(map[string]bool) + for acc := range maccPerms { + blockedAddrs[authtypes.NewModuleAddress(acc).String()] = !allowedReceivingModAcc[acc] + } + + return blockedAddrs +} + // LegacyAmino returns SimApp's amino codec. // // NOTE: This is solely to be used for testing purposes as it may be desirable diff --git a/simapp/app_test.go b/simapp/app_test.go index 2e6cad9c0b..489d0272cd 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -42,11 +42,11 @@ func TestSimAppExportAndBlockedAddrs(t *testing.T) { app := NewSimApp(log.NewOCLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) for acc := range maccPerms { - require.True( - t, + ex, _ := allowedReceivingModAcc[acc] + require.Equal(t, + !ex, app.BankKeeper.BlockedAddr(app.AccountKeeper.GetModuleAddress(acc)), - "ensure that blocked addresses are properly set in bank keeper", - ) + "ensure that blocked addresses are properly set in bank keeper") } genesisState := NewDefaultGenesisState(encCfg.Marshaler) diff --git a/x/bankplus/keeper/inactive.go b/x/bankplus/keeper/inactive.go new file mode 100644 index 0000000000..03637581dc --- /dev/null +++ b/x/bankplus/keeper/inactive.go @@ -0,0 +1,52 @@ +package keeper + +import ( + sdk "github.com/line/lbm-sdk/types" + "github.com/line/lbm-sdk/x/bankplus/types" +) + +// Keys for bankplus store but this prefix must not be overlap with bank key prefix. +var inactiveAddrsKeyPrefix = []byte{0xa0} + +// inactiveAddrKey key of a specific inactiveAddr from store +func inactiveAddrKey(addr sdk.AccAddress) []byte { + return append(inactiveAddrsKeyPrefix, addr.Bytes()...) +} + +//nolint:deadcode,unused +// isStoredInactiveAddr checks if the address is stored or not as blocked address +func (keeper BaseKeeper) isStoredInactiveAddr(ctx sdk.Context, address sdk.AccAddress) bool { + store := ctx.KVStore(keeper.storeKey) + bz := store.Get(inactiveAddrKey(address)) + return bz != nil +} + +// addToInactiveAddr adds a blocked address to the store. +func (keeper BaseKeeper) addToInactiveAddr(ctx sdk.Context, address sdk.AccAddress) { + store := ctx.KVStore(keeper.storeKey) + blockedCAddr := types.InactiveAddr{Address: address.String()} + bz := keeper.cdc.MustMarshalBinaryBare(&blockedCAddr) + store.Set(inactiveAddrKey(address), bz) +} + +// deleteFromInactiveAddr deletes blocked address from store +func (keeper BaseKeeper) deleteFromInactiveAddr(ctx sdk.Context, address sdk.AccAddress) { + store := ctx.KVStore(keeper.storeKey) + store.Delete(inactiveAddrKey(address)) +} + +// loadAllInactiveAddrs loads all blocked address and set to `inactiveAddr`. +// This function is executed when the app is initiated and save all inactive address in caches +// in order to prevent to query to store in every time to send +func (keeper BaseKeeper) loadAllInactiveAddrs(ctx sdk.Context) { + store := ctx.KVStore(keeper.storeKey) + iterator := sdk.KVStorePrefixIterator(store, inactiveAddrsKeyPrefix) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var bAddr types.InactiveAddr + keeper.cdc.MustUnmarshalBinaryBare(iterator.Value(), &bAddr) + + keeper.inactiveAddrs[bAddr.Address] = true + } +} diff --git a/x/bankplus/keeper/inactive_test.go b/x/bankplus/keeper/inactive_test.go new file mode 100644 index 0000000000..6205ed7202 --- /dev/null +++ b/x/bankplus/keeper/inactive_test.go @@ -0,0 +1,79 @@ +package keeper + +import ( + "github.com/line/lbm-sdk/codec" + codectypes "github.com/line/lbm-sdk/codec/types" + "github.com/line/lbm-sdk/store" + sdk "github.com/line/lbm-sdk/types" + accountkeeper "github.com/line/lbm-sdk/x/auth/keeper" + accounttypes "github.com/line/lbm-sdk/x/auth/types" + banktypes "github.com/line/lbm-sdk/x/bank/types" + paramtypes "github.com/line/lbm-sdk/x/params/types" + "github.com/line/ostracon/libs/log" + ostproto "github.com/line/ostracon/proto/ostracon/types" + "github.com/line/tm-db/v2/memdb" + "github.com/stretchr/testify/require" + "math/rand" + "testing" +) + +func genAddress() sdk.AccAddress { + b := make([]byte, 20) + rand.Read(b) + return sdk.BytesToAccAddress(b) +} + +func setupKeeper(storeKey *sdk.KVStoreKey) BaseKeeper { + registry := codectypes.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(registry) + amino := codec.NewLegacyAmino() + + accountStoreKey := sdk.NewKVStoreKey(accounttypes.StoreKey) + accountSubspace := paramtypes.NewSubspace(cdc, amino, accountStoreKey, accounttypes.ModuleName) + accountKeeper := accountkeeper.NewAccountKeeper(cdc, accountStoreKey, accountSubspace, accounttypes.ProtoBaseAccount, nil) + + bankSubspace := paramtypes.NewSubspace(cdc, amino, storeKey, banktypes.StoreKey) + return NewBaseKeeper(cdc, storeKey, accountKeeper, bankSubspace, nil) +} + +func setupContext(t *testing.T, storeKey *sdk.KVStoreKey) sdk.Context { + db := memdb.NewDB() + stateStore := store.NewCommitMultiStore(db) + stateStore.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db) + require.NoError(t, stateStore.LoadLatestVersion()) + + return sdk.NewContext(stateStore, ostproto.Header{}, false, log.NewNopLogger()) +} + +func TestInactiveAddr(t *testing.T) { + storeKey := sdk.NewKVStoreKey(banktypes.StoreKey) + bankKeeper := setupKeeper(storeKey) + ctx := setupContext(t, storeKey) + + addr := genAddress() + + require.Equal(t, 0, len(bankKeeper.inactiveAddrs)) + + bankKeeper.addToInactiveAddr(ctx, addr) + require.True(t, bankKeeper.isStoredInactiveAddr(ctx, addr)) + + // duplicate addition, no error expects. + bankKeeper.addToInactiveAddr(ctx, addr) + require.True(t, bankKeeper.isStoredInactiveAddr(ctx, addr)) + + bankKeeper.deleteFromInactiveAddr(ctx, addr) + require.False(t, bankKeeper.isStoredInactiveAddr(ctx, addr)) + + addr2 := genAddress() + require.False(t, bankKeeper.isStoredInactiveAddr(ctx, addr2)) + + // expect no error + bankKeeper.deleteFromInactiveAddr(ctx, addr2) + + // test loadAllInactiveAddrs + bankKeeper.addToInactiveAddr(ctx, addr) + bankKeeper.addToInactiveAddr(ctx, addr2) + require.Equal(t, 0, len(bankKeeper.inactiveAddrs)) + bankKeeper.loadAllInactiveAddrs(ctx) + require.Equal(t, 2, len(bankKeeper.inactiveAddrs)) +} diff --git a/x/bankplus/keeper/keeper.go b/x/bankplus/keeper/keeper.go new file mode 100644 index 0000000000..70f628dce7 --- /dev/null +++ b/x/bankplus/keeper/keeper.go @@ -0,0 +1,131 @@ +package keeper + +import ( + "github.com/line/lbm-sdk/codec" + sdk "github.com/line/lbm-sdk/types" + sdkerrors "github.com/line/lbm-sdk/types/errors" + bankkeeper "github.com/line/lbm-sdk/x/bank/keeper" + "github.com/line/lbm-sdk/x/bank/types" + paramtypes "github.com/line/lbm-sdk/x/params/types" +) + +var _ Keeper = (*BaseKeeper)(nil) + +type Keeper interface { + bankkeeper.Keeper + + AddToInactiveAddr(ctx sdk.Context, address sdk.AccAddress) + DeleteFromInactiveAddr(ctx sdk.Context, address sdk.AccAddress) + IsInactiveAddr(address sdk.AccAddress) bool + + InitializeBankPlus(ctx sdk.Context) +} + +type BaseKeeper struct { + bankkeeper.BaseKeeper + + ak types.AccountKeeper + cdc codec.BinaryMarshaler + storeKey sdk.StoreKey + inactiveAddrs map[string]bool +} + +func NewBaseKeeper( + cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, ak types.AccountKeeper, paramSpace *paramtypes.Subspace, + blockedAddr map[string]bool, +) BaseKeeper { + return BaseKeeper{ + BaseKeeper: bankkeeper.NewBaseKeeper(cdc, storeKey, ak, paramSpace, blockedAddr), + ak: ak, + cdc: cdc, + storeKey: storeKey, + inactiveAddrs: map[string]bool{}, + } +} + +func (keeper BaseKeeper) InitializeBankPlus(ctx sdk.Context) { + keeper.loadAllInactiveAddrs(ctx) +} + +// SendCoinsFromModuleToAccount transfers coins from a ModuleAccount to an AccAddress. +// It will panic if the module account does not exist. +func (keeper BaseKeeper) SendCoinsFromModuleToAccount( + ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins, +) error { + senderAddr := keeper.ak.GetModuleAddress(senderModule) + if senderAddr.Empty() { + panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)) + } + + return keeper.SendCoins(ctx, senderAddr, recipientAddr, amt) +} + +// SendCoinsFromModuleToModule transfers coins from a ModuleAccount to another. +// It will panic if either module account does not exist. +func (keeper BaseKeeper) SendCoinsFromModuleToModule( + ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins, +) error { + senderAddr := keeper.ak.GetModuleAddress(senderModule) + if senderAddr.Empty() { + panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)) + } + + recipientAcc := keeper.ak.GetModuleAccount(ctx, recipientModule) + if recipientAcc == nil { + panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)) + } + + return keeper.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt) +} + +// SendCoinsFromAccountToModule transfers coins from an AccAddress to a ModuleAccount. +// It will panic if the module account does not exist. +func (keeper BaseKeeper) SendCoinsFromAccountToModule( + ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins, +) error { + recipientAcc := keeper.ak.GetModuleAccount(ctx, recipientModule) + if recipientAcc == nil { + panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)) + } + + return keeper.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt) +} + +func (keeper BaseKeeper) isInactiveAddr(addr sdk.AccAddress) bool { + return keeper.inactiveAddrs[addr.String()] +} + +// SendCoins transfers amt coins from a sending account to a receiving account. +// This is wrapped bank the `SendKeeper` interface of `bank` module, +// and checks if `toAddr` is a inactiveAddr managed by the module. +func (keeper BaseKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { + // if toAddr is smart contract, check the status of contract. + if keeper.isInactiveAddr(toAddr) { + return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", toAddr) + } + + return keeper.BaseSendKeeper.SendCoins(ctx, fromAddr, toAddr, amt) +} + +// AddToInactiveAddr adds the address to `inactiveAddr`. +func (keeper BaseKeeper) AddToInactiveAddr(ctx sdk.Context, address sdk.AccAddress) { + if !keeper.inactiveAddrs[address.String()] { + keeper.inactiveAddrs[address.String()] = true + + keeper.addToInactiveAddr(ctx, address) + } +} + +// DeleteFromInactiveAddr removes the address from `inactiveAddr`. +func (keeper BaseKeeper) DeleteFromInactiveAddr(ctx sdk.Context, address sdk.AccAddress) { + if keeper.inactiveAddrs[address.String()] { + delete(keeper.inactiveAddrs, address.String()) + + keeper.deleteFromInactiveAddr(ctx, address) + } +} + +// IsInactiveAddr returns if the address is added in inactiveAddr. +func (keeper BaseKeeper) IsInactiveAddr(address sdk.AccAddress) bool { + return keeper.inactiveAddrs[address.String()] +} diff --git a/x/bankplus/keeper/keeper_test.go b/x/bankplus/keeper/keeper_test.go new file mode 100644 index 0000000000..613535954e --- /dev/null +++ b/x/bankplus/keeper/keeper_test.go @@ -0,0 +1,194 @@ +package keeper_test + +import ( + "github.com/line/lbm-sdk/simapp" + sdk "github.com/line/lbm-sdk/types" + authkeeper "github.com/line/lbm-sdk/x/auth/keeper" + authtypes "github.com/line/lbm-sdk/x/auth/types" + "testing" + + "github.com/line/lbm-sdk/x/bank/types" + bankpluskeeper "github.com/line/lbm-sdk/x/bankplus/keeper" + ocproto "github.com/line/ostracon/proto/ostracon/types" + "github.com/stretchr/testify/suite" +) + +const ( + initialPower = int64(100) + holder = "holder" + blocker = "blocker" +) + +var ( + holderAcc = authtypes.NewEmptyModuleAccount(holder) + blockedAcc = authtypes.NewEmptyModuleAccount(blocker) + burnerAcc = authtypes.NewEmptyModuleAccount(authtypes.Burner, authtypes.Burner) + + initTokens = sdk.TokensFromConsensusPower(initialPower) + initCoins = sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)) +) + +// nolint: interfacer +func getCoinsByName(ctx sdk.Context, bk bankpluskeeper.Keeper, ak types.AccountKeeper, moduleName string) sdk.Coins { + moduleAddress := ak.GetModuleAddress(moduleName) + macc := ak.GetAccount(ctx, moduleAddress) + if macc == nil { + return sdk.Coins(nil) + } + + return bk.GetAllBalances(ctx, macc.GetAddress()) +} + +type IntegrationTestSuite struct { + suite.Suite + + app *simapp.SimApp + ctx sdk.Context + queryClient types.QueryClient +} + +func (suite *IntegrationTestSuite) TestSupply_SendCoins() { + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, ocproto.Header{Height: 1}) + appCodec := app.AppCodec() + + // add module accounts to supply keeper + maccPerms := simapp.GetMaccPerms() + maccPerms[holder] = nil + maccPerms[authtypes.Burner] = []string{authtypes.Burner} + maccPerms[authtypes.Minter] = []string{authtypes.Minter} + + authKeeper := authkeeper.NewAccountKeeper( + appCodec, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName), + authtypes.ProtoBaseAccount, maccPerms, + ) + keeper := bankpluskeeper.NewBaseKeeper( + appCodec, app.GetKey(types.StoreKey), authKeeper, + app.GetSubspace(types.ModuleName), make(map[string]bool), + ) + + baseAcc := authKeeper.NewAccountWithAddress(ctx, authtypes.NewModuleAddress("baseAcc")) + suite.Require().NoError(keeper.SetBalances(ctx, holderAcc.GetAddress(), initCoins)) + + keeper.SetSupply(ctx, types.NewSupply(initCoins)) + authKeeper.SetModuleAccount(ctx, holderAcc) + authKeeper.SetModuleAccount(ctx, burnerAcc) + authKeeper.SetAccount(ctx, baseAcc) + + suite.Require().Panics(func() { + keeper.SendCoinsFromModuleToModule(ctx, "", holderAcc.GetName(), initCoins) // nolint:errcheck + }) + + suite.Require().Panics(func() { + keeper.SendCoinsFromModuleToModule(ctx, authtypes.Burner, "", initCoins) // nolint:errcheck + }) + + suite.Require().Panics(func() { + keeper.SendCoinsFromModuleToAccount(ctx, "", baseAcc.GetAddress(), initCoins) // nolint:errcheck + }) + + // not enough balance (100stake - 200stake) + suite.Require().Error( + keeper.SendCoinsFromModuleToAccount(ctx, holderAcc.GetName(), baseAcc.GetAddress(), initCoins.Add(initCoins...)), + ) + + suite.Require().NoError( + keeper.SendCoinsFromModuleToModule(ctx, holderAcc.GetName(), authtypes.Burner, initCoins), + ) + suite.Require().Equal(sdk.Coins(nil), getCoinsByName(ctx, keeper, authKeeper, holderAcc.GetName())) + suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner)) + + suite.Require().NoError( + keeper.SendCoinsFromModuleToAccount(ctx, authtypes.Burner, baseAcc.GetAddress(), initCoins), + ) + suite.Require().Equal(sdk.Coins(nil), getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner)) + suite.Require().Equal(initCoins, keeper.GetAllBalances(ctx, baseAcc.GetAddress())) + + suite.Require().NoError(keeper.SendCoinsFromAccountToModule(ctx, baseAcc.GetAddress(), authtypes.Burner, initCoins)) + suite.Require().Equal(sdk.Coins(nil), keeper.GetAllBalances(ctx, baseAcc.GetAddress())) + suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner)) +} + +func (suite *IntegrationTestSuite) TestInactiveAddrOfSendCoins() { + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, ocproto.Header{Height: 1}) + appCodec := app.AppCodec() + + // add module accounts to supply keeper + maccPerms := simapp.GetMaccPerms() + maccPerms[holder] = nil + maccPerms[authtypes.Burner] = []string{authtypes.Burner} + maccPerms[authtypes.Minter] = []string{authtypes.Minter} + + authKeeper := authkeeper.NewAccountKeeper( + appCodec, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName), + authtypes.ProtoBaseAccount, maccPerms, + ) + + keeper := bankpluskeeper.NewBaseKeeper( + appCodec, app.GetKey(types.StoreKey), authKeeper, + app.GetSubspace(types.ModuleName), make(map[string]bool), + ) + + suite.Require().NoError(keeper.SetBalances(ctx, holderAcc.GetAddress(), initCoins)) + keeper.SetSupply(ctx, types.NewSupply(initCoins)) + suite.Require().Equal(initCoins, keeper.GetAllBalances(ctx, holderAcc.GetAddress())) + + suite.Require().False(keeper.IsInactiveAddr(blockedAcc.GetAddress())) + + // add blocked address + keeper.AddToInactiveAddr(ctx, blockedAcc.GetAddress()) + suite.Require().True(keeper.IsInactiveAddr(blockedAcc.GetAddress())) + + err := keeper.SendCoins(ctx, holderAcc.GetAddress(), blockedAcc.GetAddress(), initCoins) + suite.Require().Contains(err.Error(), "is not allowed to receive funds") + suite.Require().Equal(initCoins, keeper.GetAllBalances(ctx, holderAcc.GetAddress())) + + // delete blocked address + keeper.DeleteFromInactiveAddr(ctx, blockedAcc.GetAddress()) + suite.Require().False(keeper.IsInactiveAddr(blockedAcc.GetAddress())) + + suite.Require().NoError(keeper.SendCoins(ctx, holderAcc.GetAddress(), blockedAcc.GetAddress(), initCoins)) + suite.Require().Equal(sdk.Coins(nil), keeper.GetAllBalances(ctx, holderAcc.GetAddress())) +} + +func (suite *IntegrationTestSuite) TestInitializeBankPlus() { + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, ocproto.Header{Height: 1}) + appCodec := app.AppCodec() + + // add module accounts to supply keeper + maccPerms := simapp.GetMaccPerms() + maccPerms[holder] = nil + maccPerms[authtypes.Burner] = []string{authtypes.Burner} + maccPerms[authtypes.Minter] = []string{authtypes.Minter} + + authKeeper := authkeeper.NewAccountKeeper( + appCodec, app.GetKey(types.StoreKey), app.GetSubspace(types.ModuleName), + authtypes.ProtoBaseAccount, maccPerms, + ) + + { + keeper := bankpluskeeper.NewBaseKeeper( + appCodec, app.GetKey(types.StoreKey), authKeeper, + app.GetSubspace(types.ModuleName), make(map[string]bool), + ) + + // add blocked address + keeper.AddToInactiveAddr(ctx, blockedAcc.GetAddress()) + suite.Require().True(keeper.IsInactiveAddr(blockedAcc.GetAddress())) + } + + { + keeper := bankpluskeeper.NewBaseKeeper( + appCodec, app.GetKey(types.StoreKey), authKeeper, + app.GetSubspace(types.ModuleName), make(map[string]bool), + ) + keeper.InitializeBankPlus(ctx) + suite.Require().True(keeper.IsInactiveAddr(blockedAcc.GetAddress())) + } +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/bankplus/module.go b/x/bankplus/module.go new file mode 100644 index 0000000000..7c140cb89a --- /dev/null +++ b/x/bankplus/module.go @@ -0,0 +1,36 @@ +package bankplus + +import ( + "fmt" + + "github.com/line/lbm-sdk/codec" + "github.com/line/lbm-sdk/types/module" + accountkeeper "github.com/line/lbm-sdk/x/auth/keeper" + "github.com/line/lbm-sdk/x/bank" + bankkeeper "github.com/line/lbm-sdk/x/bank/keeper" + banktypes "github.com/line/lbm-sdk/x/bank/types" + "github.com/line/lbm-sdk/x/bankplus/keeper" +) + +type AppModule struct { + bank.AppModule + + bankKeeper bankkeeper.Keeper +} + +func NewAppModule(cdc codec.Marshaler, keeper bankkeeper.Keeper, accountKeeper accountkeeper.AccountKeeper) AppModule { + return AppModule{ + AppModule: bank.NewAppModule(cdc, keeper, accountKeeper), + bankKeeper: keeper, + } +} + +func (am AppModule) RegisterServices(cfg module.Configurator) { + banktypes.RegisterMsgServer(cfg.MsgServer(), bankkeeper.NewMsgServerImpl(am.bankKeeper)) + banktypes.RegisterQueryServer(cfg.QueryServer(), am.bankKeeper) + + m := bankkeeper.NewMigrator(am.bankKeeper.(keeper.BaseKeeper).BaseKeeper) + if err := cfg.RegisterMigration(banktypes.ModuleName, 1, m.Migrate1to2); err != nil { + panic(fmt.Sprintf("failed to migrate x/bank from version 1 to 2: %v", err)) + } +} diff --git a/x/bankplus/types/bankplus.pb.go b/x/bankplus/types/bankplus.pb.go new file mode 100644 index 0000000000..b96f94855c --- /dev/null +++ b/x/bankplus/types/bankplus.pb.go @@ -0,0 +1,342 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: lbm/bankplus/v1/bankplus.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// InactiveAddr models the blocked address for the bankplus module +type InactiveAddr struct { + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (m *InactiveAddr) Reset() { *m = InactiveAddr{} } +func (m *InactiveAddr) String() string { return proto.CompactTextString(m) } +func (*InactiveAddr) ProtoMessage() {} +func (*InactiveAddr) Descriptor() ([]byte, []int) { + return fileDescriptor_79e8c66834b4419a, []int{0} +} +func (m *InactiveAddr) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *InactiveAddr) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_InactiveAddr.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *InactiveAddr) XXX_Merge(src proto.Message) { + xxx_messageInfo_InactiveAddr.Merge(m, src) +} +func (m *InactiveAddr) XXX_Size() int { + return m.Size() +} +func (m *InactiveAddr) XXX_DiscardUnknown() { + xxx_messageInfo_InactiveAddr.DiscardUnknown(m) +} + +var xxx_messageInfo_InactiveAddr proto.InternalMessageInfo + +func (m *InactiveAddr) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func init() { + proto.RegisterType((*InactiveAddr)(nil), "lbm.bankplus.v1.InactiveAddr") +} + +func init() { proto.RegisterFile("lbm/bankplus/v1/bankplus.proto", fileDescriptor_79e8c66834b4419a) } + +var fileDescriptor_79e8c66834b4419a = []byte{ + // 180 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcb, 0x49, 0xca, 0xd5, + 0x4f, 0x4a, 0xcc, 0xcb, 0x2e, 0xc8, 0x29, 0x2d, 0xd6, 0x2f, 0x33, 0x84, 0xb3, 0xf5, 0x0a, 0x8a, + 0xf2, 0x4b, 0xf2, 0x85, 0xf8, 0x73, 0x92, 0x72, 0xf5, 0xe0, 0x62, 0x65, 0x86, 0x52, 0x22, 0xe9, + 0xf9, 0xe9, 0xf9, 0x60, 0x39, 0x7d, 0x10, 0x0b, 0xa2, 0x4c, 0x49, 0x8f, 0x8b, 0xc7, 0x33, 0x2f, + 0x31, 0xb9, 0x24, 0xb3, 0x2c, 0xd5, 0x31, 0x25, 0xa5, 0x48, 0x48, 0x82, 0x8b, 0x3d, 0x31, 0x25, + 0xa5, 0x28, 0xb5, 0xb8, 0x58, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, 0x08, 0xc6, 0xb5, 0x62, 0x79, + 0xb1, 0x40, 0x9e, 0xd1, 0xc9, 0xe9, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, + 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, + 0x34, 0xd2, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x73, 0x32, 0xf3, 0x52, + 0xf5, 0x73, 0x92, 0x72, 0x75, 0x8b, 0x53, 0xb2, 0xf5, 0x2b, 0x10, 0xce, 0x2c, 0xa9, 0x2c, 0x48, + 0x2d, 0x4e, 0x62, 0x03, 0x5b, 0x6d, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x57, 0x32, 0x20, 0x7a, + 0xc3, 0x00, 0x00, 0x00, +} + +func (this *InactiveAddr) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*InactiveAddr) + if !ok { + that2, ok := that.(InactiveAddr) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Address != that1.Address { + return false + } + return true +} +func (m *InactiveAddr) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *InactiveAddr) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *InactiveAddr) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintBankplus(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintBankplus(dAtA []byte, offset int, v uint64) int { + offset -= sovBankplus(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *InactiveAddr) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovBankplus(uint64(l)) + } + return n +} + +func sovBankplus(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozBankplus(x uint64) (n int) { + return sovBankplus(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *InactiveAddr) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBankplus + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: InactiveAddr: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: InactiveAddr: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBankplus + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthBankplus + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBankplus + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipBankplus(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBankplus + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipBankplus(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBankplus + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBankplus + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBankplus + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthBankplus + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupBankplus + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthBankplus + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthBankplus = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowBankplus = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupBankplus = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/wasm/keeper/genesis_test.go b/x/wasm/keeper/genesis_test.go index 744883f822..22c23c2cf3 100644 --- a/x/wasm/keeper/genesis_test.go +++ b/x/wasm/keeper/genesis_test.go @@ -6,6 +6,7 @@ import ( "encoding/base64" "errors" "fmt" + bankpluskeeper "github.com/line/lbm-sdk/x/bankplus/keeper" "io/ioutil" "math/rand" "os" @@ -669,7 +670,7 @@ func setupKeeper(t *testing.T) (*Keeper, sdk.Context, []sdk.StoreKey) { wasmConfig := wasmTypes.DefaultWasmConfig() pk := paramskeeper.NewKeeper(encodingConfig.Marshaler, encodingConfig.Amino, keyParams) - srcKeeper := NewKeeper(encodingConfig.Marshaler, keyWasm, pk.Subspace(wasmTypes.DefaultParamspace), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, nil, tempDir, wasmConfig, SupportedFeatures, nil, nil) + srcKeeper := NewKeeper(encodingConfig.Marshaler, keyWasm, pk.Subspace(wasmTypes.DefaultParamspace), authkeeper.AccountKeeper{}, bankpluskeeper.BaseKeeper{}, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, nil, tempDir, wasmConfig, SupportedFeatures, nil, nil) return &srcKeeper, ctx, []sdk.StoreKey{keyWasm, keyParams} } diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 976ad7d728..03f007d92c 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -12,6 +12,7 @@ import ( sdk "github.com/line/lbm-sdk/types" sdkerrors "github.com/line/lbm-sdk/types/errors" authkeeper "github.com/line/lbm-sdk/x/auth/keeper" + bankpluskeeper "github.com/line/lbm-sdk/x/bankplus/keeper" paramtypes "github.com/line/lbm-sdk/x/params/types" "github.com/line/lbm-sdk/x/wasm/types" "github.com/line/ostracon/crypto" @@ -38,6 +39,8 @@ type WasmVMQueryHandler interface { type CoinTransferrer interface { // TransferCoins sends the coin amounts from the source to the destination with rules applied. TransferCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error + AddToInactiveAddr(ctx sdk.Context, address sdk.AccAddress) + DeleteFromInactiveAddr(ctx sdk.Context, address sdk.AccAddress) } // WasmVMResponseHandler is an extension point to handles the response data returned by a contract call. @@ -574,6 +577,13 @@ func (k Keeper) setContractStatus(ctx sdk.Context, contractAddress sdk.AccAddres if contractInfo.Status != status { contractInfo.Status = status k.storeContractInfo(ctx, contractAddress, contractInfo) + + switch status { + case types.ContractStatusInactive: + k.bank.AddToInactiveAddr(ctx, contractAddress) + case types.ContractStatusActive: + k.bank.DeleteFromInactiveAddr(ctx, contractAddress) + } } return nil } @@ -1000,12 +1010,13 @@ func (k Keeper) QueryGasLimit() sdk.Gas { // lbm-sdk's x/bank/keeper/msg_server.go Send // (https://github.com/line/lbm-sdk/blob/2a5a2d2c885b03e278bcd67546d4f21e74614ead/x/bank/keeper/msg_server.go#L26) type BankCoinTransferrer struct { - keeper types.BankKeeper + keeper bankpluskeeper.Keeper } func NewBankCoinTransferrer(keeper types.BankKeeper) BankCoinTransferrer { + bankPlusKeeper := keeper.(bankpluskeeper.Keeper) return BankCoinTransferrer{ - keeper: keeper, + keeper: bankPlusKeeper, } } @@ -1015,6 +1026,7 @@ func (c BankCoinTransferrer) TransferCoins(ctx sdk.Context, fromAddr sdk.AccAddr if err := c.keeper.SendEnabledCoins(ctx, amt...); err != nil { return err } + if c.keeper.BlockedAddr(fromAddr) { return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "blocked address can not be used") } @@ -1025,6 +1037,14 @@ func (c BankCoinTransferrer) TransferCoins(ctx sdk.Context, fromAddr sdk.AccAddr return nil } +func (c BankCoinTransferrer) AddToInactiveAddr(ctx sdk.Context, address sdk.AccAddress) { + c.keeper.AddToInactiveAddr(ctx, address) +} + +func (c BankCoinTransferrer) DeleteFromInactiveAddr(ctx sdk.Context, address sdk.AccAddress) { + c.keeper.DeleteFromInactiveAddr(ctx, address) +} + type msgDispatcher interface { DispatchMessages(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.CosmosMsg) error DispatchSubmessages(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error) diff --git a/x/wasm/keeper/options_test.go b/x/wasm/keeper/options_test.go index c76daa99b5..1a62fa88ca 100644 --- a/x/wasm/keeper/options_test.go +++ b/x/wasm/keeper/options_test.go @@ -1,6 +1,7 @@ package keeper import ( + bankpluskeeper "github.com/line/lbm-sdk/x/bankplus/keeper" "testing" authkeeper "github.com/line/lbm-sdk/x/auth/keeper" @@ -44,7 +45,7 @@ func TestConstructorOptions(t *testing.T) { } for name, spec := range specs { t.Run(name, func(t *testing.T) { - k := NewKeeper(nil, nil, paramtypes.NewSubspace(nil, nil, nil, ""), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, nil, "tempDir", types.DefaultWasmConfig(), SupportedFeatures, nil, nil, spec.srcOpt) + k := NewKeeper(nil, nil, paramtypes.NewSubspace(nil, nil, nil, ""), authkeeper.AccountKeeper{}, bankpluskeeper.BaseKeeper{}, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, nil, "tempDir", types.DefaultWasmConfig(), SupportedFeatures, nil, nil, spec.srcOpt) spec.verify(k) }) } diff --git a/x/wasm/keeper/test_common.go b/x/wasm/keeper/test_common.go index 0f78e3a717..b0f9101466 100644 --- a/x/wasm/keeper/test_common.go +++ b/x/wasm/keeper/test_common.go @@ -24,6 +24,7 @@ import ( "github.com/line/lbm-sdk/x/bank" bankkeeper "github.com/line/lbm-sdk/x/bank/keeper" banktypes "github.com/line/lbm-sdk/x/bank/types" + bankpluskeeper "github.com/line/lbm-sdk/x/bankplus/keeper" "github.com/line/lbm-sdk/x/capability" capabilitykeeper "github.com/line/lbm-sdk/x/capability/keeper" capabilitytypes "github.com/line/lbm-sdk/x/capability/types" @@ -233,7 +234,7 @@ func createTestInput( } bankSubsp, _ := paramsKeeper.GetSubspace(banktypes.ModuleName) - bankKeeper := bankkeeper.NewBaseKeeper( + bankKeeper := bankpluskeeper.NewBaseKeeper( appCodec, keyBank, authKeeper, diff --git a/x/wasm/keeper/wasmtesting/coin_transferrer.go b/x/wasm/keeper/wasmtesting/coin_transferrer.go index df639450be..4164ee4046 100644 --- a/x/wasm/keeper/wasmtesting/coin_transferrer.go +++ b/x/wasm/keeper/wasmtesting/coin_transferrer.go @@ -1,11 +1,21 @@ package wasmtesting -import sdk "github.com/line/lbm-sdk/types" +import ( + sdk "github.com/line/lbm-sdk/types" +) type MockCoinTransferrer struct { TransferCoinsFn func(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error } +func (m *MockCoinTransferrer) AddToInactiveAddr(ctx sdk.Context, address sdk.AccAddress) { + panic("implement me") +} + +func (m *MockCoinTransferrer) DeleteFromInactiveAddr(ctx sdk.Context, address sdk.AccAddress) { + panic("implement me") +} + func (m *MockCoinTransferrer) TransferCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { if m.TransferCoinsFn == nil { panic("not expected to be called")