diff --git a/x/liquidity/keeper/swap.go b/x/liquidity/keeper/swap.go index 7c87c0718..937309edf 100644 --- a/x/liquidity/keeper/swap.go +++ b/x/liquidity/keeper/swap.go @@ -16,6 +16,13 @@ import ( // ValidateMsgLimitOrder validates types.MsgLimitOrder with state and returns // calculated offer coin and price that is fit into ticks. func (k Keeper) ValidateMsgLimitOrder(ctx sdk.Context, msg *types.MsgLimitOrder) (offerCoin sdk.Coin, price sdk.Dec, err error) { + spendable := k.bankKeeper.SpendableCoins(ctx, msg.GetOrderer()) + if spendableAmt := spendable.AmountOf(msg.OfferCoin.Denom); spendableAmt.LT(msg.OfferCoin.Amount) { + return sdk.Coin{}, sdk.Dec{}, sdkerrors.Wrapf( + sdkerrors.ErrInsufficientFunds, "%s is smaller than %s", + sdk.NewCoin(msg.OfferCoin.Denom, spendableAmt), msg.OfferCoin) + } + params := k.GetParams(ctx) if msg.OrderLifespan > params.MaxOrderLifespan { @@ -122,6 +129,13 @@ func (k Keeper) LimitOrder(ctx sdk.Context, msg *types.MsgLimitOrder) (types.Ord // ValidateMsgMarketOrder validates types.MsgMarketOrder with state and returns // calculated offer coin and price. func (k Keeper) ValidateMsgMarketOrder(ctx sdk.Context, msg *types.MsgMarketOrder) (offerCoin sdk.Coin, price sdk.Dec, err error) { + spendable := k.bankKeeper.SpendableCoins(ctx, msg.GetOrderer()) + if spendableAmt := spendable.AmountOf(msg.OfferCoin.Denom); spendableAmt.LT(msg.OfferCoin.Amount) { + return sdk.Coin{}, sdk.Dec{}, sdkerrors.Wrapf( + sdkerrors.ErrInsufficientFunds, "%s is smaller than %s", + sdk.NewCoin(msg.OfferCoin.Denom, spendableAmt), msg.OfferCoin) + } + params := k.GetParams(ctx) if msg.OrderLifespan > params.MaxOrderLifespan { diff --git a/x/liquidity/keeper/swap_test.go b/x/liquidity/keeper/swap_test.go index 6fdb665ba..4e0a7f8c6 100644 --- a/x/liquidity/keeper/swap_test.go +++ b/x/liquidity/keeper/swap_test.go @@ -4,6 +4,7 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" utils "github.com/cosmosquad-labs/squad/types" "github.com/cosmosquad-labs/squad/x/liquidity" @@ -113,6 +114,23 @@ func (s *KeeperTestSuite) TestLimitOrder() { } } +func (s *KeeperTestSuite) TestLimitOrderInsufficientOfferCoin() { + pair := s.createPair(s.addr(0), "denom1", "denom2", true) + + orderer := s.addr(1) + s.fundAddr(orderer, utils.ParseCoins("1000000denom2")) + _, err := s.keeper.LimitOrder(s.ctx, types.NewMsgLimitOrder( + orderer, pair.Id, types.OrderDirectionBuy, utils.ParseCoin("1000001denom2"), "denom1", + utils.ParseDec("1.0"), sdk.NewInt(1000000), 0)) + s.Require().ErrorIs(err, sdkerrors.ErrInsufficientFunds) + + s.fundAddr(orderer, utils.ParseCoins("1000000denom1")) + _, err = s.keeper.LimitOrder(s.ctx, types.NewMsgLimitOrder( + orderer, pair.Id, types.OrderDirectionSell, utils.ParseCoin("1000001denom1"), "denom2", + utils.ParseDec("1.0"), sdk.NewInt(1000000), 0)) + s.Require().ErrorIs(err, sdkerrors.ErrInsufficientFunds) +} + func (s *KeeperTestSuite) TestLimitOrderRefund() { pair := s.createPair(s.addr(0), "denom1", "denom2", true) orderer := s.addr(1) @@ -196,6 +214,23 @@ func (s *KeeperTestSuite) TestMarketOrder() { s.Require().True(coinsEq(utils.ParseCoins("10800denom2"), s.getBalances(s.addr(4)))) } +func (s *KeeperTestSuite) TestMarketOrderInsufficientOfferCoin() { + pair := s.createPair(s.addr(0), "denom1", "denom2", true) + + orderer := s.addr(1) + s.fundAddr(orderer, utils.ParseCoins("1000000denom2")) + _, err := s.keeper.MarketOrder(s.ctx, types.NewMsgMarketOrder( + orderer, pair.Id, types.OrderDirectionBuy, utils.ParseCoin("1000001denom2"), "denom1", + sdk.NewInt(1000000), 0)) + s.Require().ErrorIs(err, sdkerrors.ErrInsufficientFunds) + + s.fundAddr(orderer, utils.ParseCoins("1000000denom1")) + _, err = s.keeper.MarketOrder(s.ctx, types.NewMsgMarketOrder( + orderer, pair.Id, types.OrderDirectionSell, utils.ParseCoin("1000001denom1"), "denom2", + sdk.NewInt(1000000), 0)) + s.Require().ErrorIs(err, sdkerrors.ErrInsufficientFunds) +} + func (s *KeeperTestSuite) TestMarketOrderRefund() { pair := s.createPair(s.addr(0), "denom1", "denom2", true) p := utils.ParseDec("1.0")