Skip to content

Commit

Permalink
feat!: add MultiSend deactivation (#876)
Browse files Browse the repository at this point in the history
* feat!: add MultiSend deactivation

* add CHANGELOG

* emit error instead of panic
  • Loading branch information
tkxkd0159 authored Feb 6, 2023
1 parent 561b7f0 commit a7557b1
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 17 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Breaking Changes
* (rest) [\#807](https://github.com/line/lbm-sdk/pull/807) remove legacy REST API
* (codec) [\#833](https://github.com/line/lbm-sdk/pull/833) Fix foundation amino codec
* (x/bank) [\#876](https://github.com/line/lbm-sdk/pull/876) Add `MultiSend` deactivation


### Build, CI
* (ci) [\#829](https://github.com/line/lbm-sdk/pull/829) automate release process
Expand Down
2 changes: 1 addition & 1 deletion simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ func NewSimApp(
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms,
)
app.BankKeeper = bankpluskeeper.NewBaseKeeper(
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs())
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(), false)
stakingKeeper := stakingkeeper.NewKeeper(
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName),
)
Expand Down
2 changes: 1 addition & 1 deletion x/bankplus/keeper/inactive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func setupKeeper(storeKey *sdk.KVStoreKey) BaseKeeper {
accountKeeper := accountkeeper.NewAccountKeeper(cdc, accountStoreKey, accountSubspace, accounttypes.ProtoBaseAccount, nil)

bankSubspace := paramtypes.NewSubspace(cdc, amino, storeKey, testTransientStoreKey, banktypes.StoreKey)
return NewBaseKeeper(cdc, storeKey, accountKeeper, bankSubspace, nil)
return NewBaseKeeper(cdc, storeKey, accountKeeper, bankSubspace, nil, false)
}

func setupContext(t *testing.T, storeKey *sdk.KVStoreKey) sdk.Context {
Expand Down
36 changes: 26 additions & 10 deletions x/bankplus/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,24 @@ type Keeper interface {
type BaseKeeper struct {
bankkeeper.BaseKeeper

ak types.AccountKeeper
cdc codec.Codec
storeKey sdk.StoreKey
inactiveAddrs map[string]bool
ak types.AccountKeeper
cdc codec.Codec
storeKey sdk.StoreKey
inactiveAddrs map[string]bool
deactMultiSend bool
}

func NewBaseKeeper(
cdc codec.Codec, storeKey sdk.StoreKey, ak types.AccountKeeper, paramSpace paramtypes.Subspace,
blockedAddr map[string]bool,
blockedAddr map[string]bool, deactMultiSend bool,
) BaseKeeper {
return BaseKeeper{
BaseKeeper: bankkeeper.NewBaseKeeper(cdc, storeKey, ak, paramSpace, blockedAddr),
ak: ak,
cdc: cdc,
storeKey: storeKey,
inactiveAddrs: map[string]bool{},
BaseKeeper: bankkeeper.NewBaseKeeper(cdc, storeKey, ak, paramSpace, blockedAddr),
ak: ak,
cdc: cdc,
storeKey: storeKey,
inactiveAddrs: map[string]bool{},
deactMultiSend: deactMultiSend,
}
}

Expand Down Expand Up @@ -133,3 +135,17 @@ func (keeper BaseKeeper) DeleteFromInactiveAddr(ctx sdk.Context, address sdk.Acc
func (keeper BaseKeeper) IsInactiveAddr(address sdk.AccAddress) bool {
return keeper.inactiveAddrs[address.String()]
}

func (keeper BaseKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error {
if keeper.deactMultiSend {
return sdkerrors.ErrNotSupported.Wrap("MultiSend was deactivated")
}

for _, out := range outputs {
if keeper.inactiveAddrs[out.Address] {
return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", out.Address)
}
}

return keeper.BaseSendKeeper.InputOutputCoins(ctx, inputs, outputs)
}
84 changes: 79 additions & 5 deletions x/bankplus/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (suite *IntegrationTestSuite) TestSupply_SendCoins() {
)
keeper := bankpluskeeper.NewBaseKeeper(
appCodec, app.GetKey(types.StoreKey), authKeeper,
app.GetSubspace(types.ModuleName), make(map[string]bool),
app.GetSubspace(types.ModuleName), make(map[string]bool), false,
)

baseAcc := authKeeper.NewAccountWithAddress(ctx, authtypes.NewModuleAddress("baseAcc"))
Expand Down Expand Up @@ -134,7 +134,7 @@ func (suite *IntegrationTestSuite) TestInactiveAddrOfSendCoins() {

keeper := bankpluskeeper.NewBaseKeeper(
appCodec, app.GetKey(types.StoreKey), authKeeper,
app.GetSubspace(types.ModuleName), make(map[string]bool),
app.GetSubspace(types.ModuleName), make(map[string]bool), false,
)

// set initial balances
Expand Down Expand Up @@ -186,7 +186,7 @@ func (suite *IntegrationTestSuite) TestInitializeBankPlus() {
{
keeper := bankpluskeeper.NewBaseKeeper(
appCodec, app.GetKey(types.StoreKey), authKeeper,
app.GetSubspace(types.ModuleName), make(map[string]bool),
app.GetSubspace(types.ModuleName), make(map[string]bool), false,
)

// add blocked address
Expand All @@ -197,7 +197,7 @@ func (suite *IntegrationTestSuite) TestInitializeBankPlus() {
{
keeper := bankpluskeeper.NewBaseKeeper(
appCodec, app.GetKey(types.StoreKey), authKeeper,
app.GetSubspace(types.ModuleName), make(map[string]bool),
app.GetSubspace(types.ModuleName), make(map[string]bool), false,
)
keeper.InitializeBankPlus(ctx)
suite.Require().True(keeper.IsInactiveAddr(blockedAcc.GetAddress()))
Expand All @@ -223,14 +223,88 @@ func (suite *IntegrationTestSuite) TestSendCoinsFromModuleToAccount_Blacklist()
)
keeper := bankpluskeeper.NewBaseKeeper(
appCodec, app.GetKey(types.StoreKey), authKeeper,
app.GetSubspace(types.ModuleName), map[string]bool{addr1.String(): true})
app.GetSubspace(types.ModuleName), map[string]bool{addr1.String(): true}, false)

suite.Require().NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins))
suite.Require().Error(keeper.SendCoinsFromModuleToAccount(
ctx, minttypes.ModuleName, addr1, initCoins,
))
}

func (suite *IntegrationTestSuite) TestInputOutputCoins() {
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), false,
)

baseAcc := authKeeper.NewAccountWithAddress(ctx, authtypes.NewModuleAddress("baseAcc"))
authKeeper.SetModuleAccount(ctx, holderAcc)
authKeeper.SetModuleAccount(ctx, burnerAcc)
authKeeper.SetAccount(ctx, baseAcc)

// set initial balances
suite.
Require().
NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins))
suite.
Require().
NoError(keeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, baseAcc.GetAddress(), initCoins))
suite.
Require().
NoError(keeper.MintCoins(ctx, minttypes.ModuleName, initCoins))
suite.
Require().
NoError(keeper.SendCoinsFromModuleToModule(ctx, minttypes.ModuleName, holderAcc.GetName(), initCoins))

input := []types.Input{types.NewInput(baseAcc.GetAddress(), initCoins), types.NewInput(holderAcc.GetAddress(), initCoins)}
output := []types.Output{types.NewOutput(burnerAcc.GetAddress(), initCoins), types.NewOutput(burnerAcc.GetAddress(), initCoins)}

targetKeeper := func(isDeact bool) bankpluskeeper.BaseKeeper {
return bankpluskeeper.NewBaseKeeper(
appCodec, app.GetKey(types.StoreKey), authKeeper,
app.GetSubspace(types.ModuleName), make(map[string]bool), isDeact,
)
}
tcs := map[string]struct {
deactMultiSend bool
}{
"MultiSend Off": {
true,
},
"MultiSend On": {
false,
},
}

for name, tc := range tcs {
tc := tc
suite.T().Run(name, func(t *testing.T) {
if tc.deactMultiSend {
suite.Panics(func() {
_ = targetKeeper(tc.deactMultiSend).InputOutputCoins(ctx, input, output)
})
} else {
err := targetKeeper(tc.deactMultiSend).InputOutputCoins(ctx, input, output)
suite.Assert().NoError(err)
}
})
}
}

func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(IntegrationTestSuite))
}

0 comments on commit a7557b1

Please sign in to comment.