cosmos-sdk/x/bank/keeper/msg_server_test.go
2025-03-21 15:04:36 -07:00

360 lines
9.3 KiB
Go

package keeper_test
import (
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
)
var govAcc = authtypes.NewEmptyModuleAccount(govtypes.ModuleName, authtypes.Minter)
func (suite *KeeperTestSuite) TestMsgUpdateParams() {
// default params
params := banktypes.DefaultParams()
testCases := []struct {
name string
input *banktypes.MsgUpdateParams
expErr bool
expErrMsg string
}{
{
name: "invalid authority",
input: &banktypes.MsgUpdateParams{
Authority: "invalid",
Params: params,
},
expErr: true,
expErrMsg: "invalid authority",
},
{
name: "send enabled param",
input: &banktypes.MsgUpdateParams{
Authority: suite.bankKeeper.GetAuthority(),
Params: banktypes.Params{
SendEnabled: []*banktypes.SendEnabled{
{Denom: "foo", Enabled: true},
},
},
},
expErr: true,
expErrMsg: "use of send_enabled in params is no longer supported",
},
{
name: "all good",
input: &banktypes.MsgUpdateParams{
Authority: suite.bankKeeper.GetAuthority(),
Params: params,
},
expErr: false,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
_, err := suite.msgServer.UpdateParams(suite.ctx, tc.input)
if tc.expErr {
suite.Require().Error(err)
suite.Require().Contains(err.Error(), tc.expErrMsg)
} else {
suite.Require().NoError(err)
}
})
}
}
func (suite *KeeperTestSuite) TestMsgSend() {
origCoins := sdk.NewCoins(sdk.NewInt64Coin("sendableCoin", 100))
suite.bankKeeper.SetSendEnabled(suite.ctx, origCoins.Denoms()[0], true)
atom0 := sdk.NewCoins(sdk.NewInt64Coin("atom", 0))
atom123eth0 := sdk.Coins{sdk.NewInt64Coin("atom", 123), sdk.NewInt64Coin("eth", 0)}
testCases := []struct {
name string
input *banktypes.MsgSend
expErr bool
expErrMsg string
}{
{
name: "invalid send to blocked address",
input: &banktypes.MsgSend{
FromAddress: minterAcc.GetAddress().String(),
ToAddress: accAddrs[4].String(),
Amount: origCoins,
},
expErr: true,
expErrMsg: "is not allowed to receive funds",
},
{
name: "invalid coins",
input: &banktypes.MsgSend{
FromAddress: minterAcc.GetAddress().String(),
ToAddress: baseAcc.Address,
Amount: atom0,
},
expErr: true,
expErrMsg: "invalid coins",
},
{
name: "123atom,0eth: invalid coins",
input: &banktypes.MsgSend{
FromAddress: minterAcc.GetAddress().String(),
ToAddress: baseAcc.Address,
Amount: atom123eth0,
},
expErr: true,
expErrMsg: "123atom,0eth: invalid coins",
},
{
name: "invalid from address: empty address string is not allowed: invalid address",
input: &banktypes.MsgSend{
FromAddress: "",
ToAddress: baseAcc.Address,
Amount: origCoins,
},
expErr: true,
expErrMsg: "empty address string is not allowed",
},
{
name: "invalid to address: empty address string is not allowed: invalid address",
input: &banktypes.MsgSend{
FromAddress: minterAcc.GetAddress().String(),
ToAddress: "",
Amount: origCoins,
},
expErr: true,
expErrMsg: "empty address string is not allowed",
},
{
name: "all good",
input: &banktypes.MsgSend{
FromAddress: minterAcc.GetAddress().String(),
ToAddress: baseAcc.Address,
Amount: origCoins,
},
expErr: false,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.mockMintCoins(minterAcc)
_ = suite.bankKeeper.MintCoins(suite.ctx, minterAcc.Name, origCoins)
if !tc.expErr {
suite.mockSendCoins(suite.ctx, minterAcc, baseAcc.GetAddress())
}
_, err := suite.msgServer.Send(suite.ctx, tc.input)
if tc.expErr {
suite.Require().Error(err)
suite.Require().Contains(err.Error(), tc.expErrMsg)
} else {
suite.Require().NoError(err)
}
})
}
}
func (suite *KeeperTestSuite) TestMsgMultiSend() {
origDenom := "sendableCoin"
origCoins := sdk.NewCoins(sdk.NewInt64Coin(origDenom, 100))
sendCoins := sdk.NewCoins(sdk.NewInt64Coin(origDenom, 50))
suite.bankKeeper.SetSendEnabled(suite.ctx, origDenom, true)
testCases := []struct {
name string
input *banktypes.MsgMultiSend
expErr bool
expErrMsg string
}{
{
name: "no inputs to send transaction",
input: &banktypes.MsgMultiSend{},
expErr: true,
expErrMsg: "no inputs to send transaction",
},
{
name: "no inputs to send transaction",
input: &banktypes.MsgMultiSend{
Outputs: []banktypes.Output{
{Address: accAddrs[4].String(), Coins: sendCoins},
},
},
expErr: true,
expErrMsg: "no inputs to send transaction",
},
{
name: "more than one inputs to send transaction",
input: &banktypes.MsgMultiSend{
Inputs: []banktypes.Input{
{Address: minterAcc.GetAddress().String(), Coins: origCoins},
{Address: minterAcc.GetAddress().String(), Coins: origCoins},
},
},
expErr: true,
expErrMsg: "multiple senders not allowed",
},
{
name: "no outputs to send transaction",
input: &banktypes.MsgMultiSend{
Inputs: []banktypes.Input{
{Address: minterAcc.GetAddress().String(), Coins: origCoins},
},
},
expErr: true,
expErrMsg: "no outputs to send transaction",
},
{
name: "invalid send to blocked address",
input: &banktypes.MsgMultiSend{
Inputs: []banktypes.Input{
{Address: minterAcc.GetAddress().String(), Coins: origCoins},
},
Outputs: []banktypes.Output{
{Address: accAddrs[0].String(), Coins: sendCoins},
{Address: accAddrs[4].String(), Coins: sendCoins},
},
},
expErr: true,
expErrMsg: "is not allowed to receive funds",
},
{
name: "invalid send to blocked address",
input: &banktypes.MsgMultiSend{
Inputs: []banktypes.Input{
{Address: minterAcc.GetAddress().String(), Coins: origCoins},
},
Outputs: []banktypes.Output{
{Address: accAddrs[0].String(), Coins: sendCoins},
{Address: accAddrs[1].String(), Coins: sendCoins},
},
},
expErr: false,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.mockMintCoins(minterAcc)
_ = suite.bankKeeper.MintCoins(suite.ctx, minterAcc.Name, origCoins)
if !tc.expErr {
suite.mockInputOutputCoins([]sdk.AccountI{minterAcc}, accAddrs[:2])
}
_, err := suite.msgServer.MultiSend(suite.ctx, tc.input)
if tc.expErr {
suite.Require().Error(err)
suite.Require().Contains(err.Error(), tc.expErrMsg)
} else {
suite.Require().NoError(err)
}
})
}
}
func (suite *KeeperTestSuite) TestMsgSetSendEnabled() {
testCases := []struct {
name string
req *banktypes.MsgSetSendEnabled
isExpErr bool
errMsg string
}{
{
name: "all good",
req: banktypes.NewMsgSetSendEnabled(
govAcc.GetAddress().String(),
[]*banktypes.SendEnabled{
banktypes.NewSendEnabled("atom1", true),
},
[]string{},
),
},
{
name: "all good with two denoms",
req: banktypes.NewMsgSetSendEnabled(
govAcc.GetAddress().String(),
[]*banktypes.SendEnabled{
banktypes.NewSendEnabled("atom1", true),
banktypes.NewSendEnabled("atom2", true),
},
[]string{"defcoinc", "defcoind"},
),
},
{
name: "duplicate denoms",
req: banktypes.NewMsgSetSendEnabled(
govAcc.GetAddress().String(),
[]*banktypes.SendEnabled{
banktypes.NewSendEnabled("atom", true),
banktypes.NewSendEnabled("atom", true),
},
[]string{},
),
isExpErr: true,
errMsg: `duplicate denom entries found for "atom": invalid request`,
},
{
name: "bad first denom name, (invalid send enabled denom present in list)",
req: banktypes.NewMsgSetSendEnabled(
govAcc.GetAddress().String(),
[]*banktypes.SendEnabled{
banktypes.NewSendEnabled("not a denom", true),
banktypes.NewSendEnabled("somecoin", true),
},
[]string{},
),
isExpErr: true,
errMsg: `invalid SendEnabled denom "not a denom": invalid denom: not a denom: invalid request`,
},
{
name: "bad second denom name, (invalid send enabled denom present in list)",
req: banktypes.NewMsgSetSendEnabled(
govAcc.GetAddress().String(),
[]*banktypes.SendEnabled{
banktypes.NewSendEnabled("somecoin", true),
banktypes.NewSendEnabled("not a denom", true),
},
[]string{},
),
isExpErr: true,
errMsg: `invalid SendEnabled denom "not a denom": invalid denom: not a denom: invalid request`,
},
{
name: "invalid UseDefaultFor denom",
req: banktypes.NewMsgSetSendEnabled(
govAcc.GetAddress().String(),
[]*banktypes.SendEnabled{
banktypes.NewSendEnabled("atom", true),
},
[]string{"not a denom"},
),
isExpErr: true,
errMsg: `invalid UseDefaultFor denom "not a denom": invalid denom: not a denom: invalid request`,
},
{
name: "invalid authority",
req: banktypes.NewMsgSetSendEnabled(
"invalid",
[]*banktypes.SendEnabled{
banktypes.NewSendEnabled("atom", true),
},
[]string{},
),
isExpErr: true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
_, err := suite.msgServer.SetSendEnabled(suite.ctx, tc.req)
if tc.isExpErr {
suite.Require().Error(err)
suite.Require().Contains(err.Error(), tc.errMsg)
} else {
suite.Require().NoError(err)
}
})
}
}