From cfb1905ad3add8561a7fb09f09a5ad624f3da025 Mon Sep 17 00:00:00 2001 From: Denali Marsh Date: Wed, 11 Nov 2020 16:05:17 +0100 Subject: [PATCH] Harvest: borrows capped by utilization (#714) * wrap error borrow exceeds mod acc balance * address revisions --- x/harvest/keeper/borrow.go | 15 ++++++++++++++- x/harvest/keeper/borrow_test.go | 21 +++++++++++++++++++++ x/harvest/types/errors.go | 2 ++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/x/harvest/keeper/borrow.go b/x/harvest/keeper/borrow.go index 58977471..f56a6b69 100644 --- a/x/harvest/keeper/borrow.go +++ b/x/harvest/keeper/borrow.go @@ -1,6 +1,8 @@ package keeper import ( + "strings" + sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -16,7 +18,18 @@ func (k Keeper) Borrow(ctx sdk.Context, borrower sdk.AccAddress, coins sdk.Coins err = k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleAccountName, borrower, coins) if err != nil { - return err + if strings.Contains(err.Error(), "insufficient account funds") { + modAccCoins := k.supplyKeeper.GetModuleAccount(ctx, types.ModuleAccountName).GetCoins() + for _, coin := range coins { + _, isNegative := modAccCoins.SafeSub(sdk.NewCoins(coin)) + if isNegative { + return sdkerrors.Wrapf(types.ErrBorrowExceedsAvailableBalance, + "the requested borrow amount of %s exceeds the total amount of %s%s available to borrow", + coin, modAccCoins.AmountOf(coin.Denom), coin.Denom, + ) + } + } + } } borrow, found := k.GetBorrow(ctx, borrower) diff --git a/x/harvest/keeper/borrow_test.go b/x/harvest/keeper/borrow_test.go index 3e1de3bb..bb8fa330 100644 --- a/x/harvest/keeper/borrow_test.go +++ b/x/harvest/keeper/borrow_test.go @@ -192,6 +192,27 @@ func (suite *KeeperTestSuite) TestBorrow() { contains: "no price found for market", }, }, + { + "invalid: borrow exceed module account balance", + args{ + priceKAVA: sdk.MustNewDecFromStr("2.00"), + loanToValueKAVA: sdk.MustNewDecFromStr("0.8"), + priceBTCB: sdk.MustNewDecFromStr("0.00"), + loanToValueBTCB: sdk.MustNewDecFromStr("0.01"), + priceBNB: sdk.MustNewDecFromStr("0.00"), + loanToValueBNB: sdk.MustNewDecFromStr("0.01"), + borrower: sdk.AccAddress(crypto.AddressHash([]byte("test"))), + depositCoins: []sdk.Coin{sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))}, + previousBorrowCoins: sdk.NewCoins(), + borrowCoins: sdk.NewCoins(sdk.NewCoin("busd", sdk.NewInt(101*BUSD_CF))), + expectedAccountBalance: sdk.NewCoins(), + expectedModAccountBalance: sdk.NewCoins(), + }, + errArgs{ + expectPass: false, + contains: "exceeds module account balance:", + }, + }, } for _, tc := range testCases { suite.Run(tc.name, func() { diff --git a/x/harvest/types/errors.go b/x/harvest/types/errors.go index 55ea0d83..9c09cb17 100644 --- a/x/harvest/types/errors.go +++ b/x/harvest/types/errors.go @@ -45,4 +45,6 @@ var ( ErrMarketNotFound = sdkerrors.Register(ModuleName, 19, "no market found for denom") // ErrPriceNotFound error for when a price for the input market is not found ErrPriceNotFound = sdkerrors.Register(ModuleName, 20, "no price found for market") + // ErrBorrowExceedsAvailableBalance for when a requested borrow exceeds available module acc balances + ErrBorrowExceedsAvailableBalance = sdkerrors.Register(ModuleName, 21, "exceeds module account balance") )