From 7e7e15d6c67c5e5b3a59c39383ca8d362defa1d8 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 14:53:21 +0000 Subject: [PATCH] fix(bank): avoid empty spendable error message on send coins (backport #17170) (#17179) Co-authored-by: mmsqe --- CHANGELOG.md | 1 + x/bank/keeper/keeper_test.go | 28 ++++++++++++++++++++++++++++ x/bank/keeper/send.go | 4 ++++ 3 files changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca732d6788d1..e1c699f3c324 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (baseapp) [#17159](https://github.com/cosmos/cosmos-sdk/pull/17159) Validators can propose blocks that exceed the gas limit. * (x/group) [#17146](https://github.com/cosmos/cosmos-sdk/pull/17146) Rename x/group legacy ORM package's error codespace from "orm" to "legacy_orm", preventing collisions with ORM's error codespace "orm". +* (x/bank) [#17170](https://github.com/cosmos/cosmos-sdk/pull/17170) Avoid empty spendable error message on send coins. ### API Breaking Changes diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 383b89880ce5..6f175de3612a 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -15,6 +15,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/suite" + errorsmod "cosmossdk.io/errors" "cosmossdk.io/log" "cosmossdk.io/math" storetypes "cosmossdk.io/store/types" @@ -24,6 +25,7 @@ import ( "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" "github.com/cosmos/cosmos-sdk/types/query" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -704,6 +706,32 @@ func (suite *KeeperTestSuite) TestSendCoins_Invalid_SendLockedCoins() { suite.Require().Error(suite.bankKeeper.SendCoins(suite.ctx, accAddrs[0], accAddrs[1], sendCoins)) } +func (suite *KeeperTestSuite) TestSendCoins_Invalid_NoSpendableCoins() { + coin := sdk.NewInt64Coin("stake", 10) + coins := sdk.NewCoins(coin) + balances := coins + + now := cmttime.Now() + endTime := now.Add(24 * time.Hour) + + origCoins := coins + sendCoins := coins + + acc0 := authtypes.NewBaseAccountWithAddress(accAddrs[0]) + suite.mockFundAccount(accAddrs[0]) + suite.Require().NoError(banktestutil.FundAccount(suite.ctx, suite.bankKeeper, accAddrs[0], balances)) + vacc, err := vesting.NewContinuousVestingAccount(acc0, origCoins, now.Unix(), endTime.Unix()) + suite.Require().NoError(err) + + suite.authKeeper.EXPECT().GetAccount(suite.ctx, accAddrs[0]).Return(vacc) + e := errorsmod.Wrapf( + sdkerrors.ErrInsufficientFunds, + "spendable balance 0stake is smaller than %s", + coin, + ) + suite.Require().EqualError(suite.bankKeeper.SendCoins(suite.ctx, accAddrs[0], accAddrs[1], sendCoins), e.Error()) +} + func (suite *KeeperTestSuite) TestValidateBalance() { ctx := suite.ctx require := suite.Require() diff --git a/x/bank/keeper/send.go b/x/bank/keeper/send.go index c334a9641273..5ba51deb58de 100644 --- a/x/bank/keeper/send.go +++ b/x/bank/keeper/send.go @@ -8,6 +8,7 @@ import ( "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" "cosmossdk.io/log" + "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/telemetry" @@ -237,6 +238,9 @@ func (k BaseSendKeeper) subUnlockedCoins(ctx context.Context, addr sdk.AccAddres } if _, hasNeg := spendable.SafeSub(coin); hasNeg { + if len(spendable) == 0 { + spendable = sdk.Coins{sdk.NewCoin(coin.Denom, math.ZeroInt())} + } return errorsmod.Wrapf( sdkerrors.ErrInsufficientFunds, "spendable balance %s is smaller than %s",