mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 00:05:18 +00:00
fix bug that skipped minimum borrow check (#870)
add tests for non-borrower repayer address
This commit is contained in:
parent
e21a04ca57
commit
509d2edbca
@ -23,13 +23,13 @@ func (k Keeper) Repay(ctx sdk.Context, sender, owner sdk.AccAddress, coins sdk.C
|
|||||||
// Refresh borrow after syncing interest
|
// Refresh borrow after syncing interest
|
||||||
borrow, _ = k.GetBorrow(ctx, owner)
|
borrow, _ = k.GetBorrow(ctx, owner)
|
||||||
|
|
||||||
// Validate that sender holds coins for repayment
|
// cap the repayment by what's available to repay (the borrow amount)
|
||||||
err := k.ValidateRepay(ctx, sender, owner, coins)
|
payment, err := k.CalculatePaymentAmount(borrow.Amount, coins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// Validate that sender holds coins for repayment
|
||||||
payment, err := k.CalculatePaymentAmount(borrow.Amount, coins)
|
err = k.ValidateRepay(ctx, sender, owner, payment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -144,8 +144,10 @@ func (k Keeper) ValidateRepay(ctx sdk.Context, sender, owner sdk.AccAddress, coi
|
|||||||
// If the proposed repayment would results in a borrowed USD value below the minimum borrow USD value, reject it.
|
// If the proposed repayment would results in a borrowed USD value below the minimum borrow USD value, reject it.
|
||||||
// User can overpay their loan to close it out, but underpaying by such a margin that the USD value is in an
|
// User can overpay their loan to close it out, but underpaying by such a margin that the USD value is in an
|
||||||
// invalid range is not allowed
|
// invalid range is not allowed
|
||||||
|
// Unless the user is fully repaying their loan
|
||||||
proposedBorrowNewUSDValue := existingBorrowUSDValue.Sub(repayTotalUSDValue)
|
proposedBorrowNewUSDValue := existingBorrowUSDValue.Sub(repayTotalUSDValue)
|
||||||
if proposedBorrowNewUSDValue.IsPositive() && proposedBorrowNewUSDValue.LT(k.GetMinimumBorrowUSDValue(ctx)) {
|
isFullRepayment := coins.IsEqual(existingBorrow.Amount)
|
||||||
|
if proposedBorrowNewUSDValue.LT(k.GetMinimumBorrowUSDValue(ctx)) && !isFullRepayment {
|
||||||
return sdkerrors.Wrapf(types.ErrBelowMinimumBorrowValue, "the proposed borrow's USD value $%s is below the minimum borrow limit $%s", proposedBorrowNewUSDValue, k.GetMinimumBorrowUSDValue(ctx))
|
return sdkerrors.Wrapf(types.ErrBelowMinimumBorrowValue, "the proposed borrow's USD value $%s is below the minimum borrow limit $%s", proposedBorrowNewUSDValue, k.GetMinimumBorrowUSDValue(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package keeper_test
|
package keeper_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
@ -17,14 +16,14 @@ import (
|
|||||||
|
|
||||||
func (suite *KeeperTestSuite) TestRepay() {
|
func (suite *KeeperTestSuite) TestRepay() {
|
||||||
type args struct {
|
type args struct {
|
||||||
borrower sdk.AccAddress
|
borrower sdk.AccAddress
|
||||||
initialBorrowerCoins sdk.Coins
|
repayer sdk.AccAddress
|
||||||
initialModuleCoins sdk.Coins
|
initialBorrowerCoins sdk.Coins
|
||||||
depositCoins []sdk.Coin
|
initialRepayerCoins sdk.Coins
|
||||||
borrowCoins sdk.Coins
|
initialModuleCoins sdk.Coins
|
||||||
repayCoins sdk.Coins
|
depositCoins []sdk.Coin
|
||||||
expectedAccountBalance sdk.Coins
|
borrowCoins sdk.Coins
|
||||||
expectedModAccountBalance sdk.Coins
|
repayCoins sdk.Coins
|
||||||
}
|
}
|
||||||
|
|
||||||
type errArgs struct {
|
type errArgs struct {
|
||||||
@ -45,10 +44,30 @@ func (suite *KeeperTestSuite) TestRepay() {
|
|||||||
{
|
{
|
||||||
"valid: partial repay",
|
"valid: partial repay",
|
||||||
args{
|
args{
|
||||||
borrower: sdk.AccAddress(crypto.AddressHash([]byte("test"))),
|
borrower: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
|
repayer: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
|
initialRepayerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
||||||
depositCoins: []sdk.Coin{sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))},
|
depositCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
|
borrowCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
||||||
|
repayCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF))),
|
||||||
|
},
|
||||||
|
errArgs{
|
||||||
|
expectPass: true,
|
||||||
|
expectDelete: false,
|
||||||
|
contains: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid: partial repay by non borrower",
|
||||||
|
args{
|
||||||
|
borrower: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
|
repayer: sdk.AccAddress(crypto.AddressHash([]byte("repayer"))),
|
||||||
|
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
|
initialRepayerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
|
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
||||||
|
depositCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
borrowCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
borrowCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
||||||
repayCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF))),
|
repayCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF))),
|
||||||
},
|
},
|
||||||
@ -61,10 +80,12 @@ func (suite *KeeperTestSuite) TestRepay() {
|
|||||||
{
|
{
|
||||||
"valid: repay in full",
|
"valid: repay in full",
|
||||||
args{
|
args{
|
||||||
borrower: sdk.AccAddress(crypto.AddressHash([]byte("test"))),
|
borrower: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
|
repayer: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
|
initialRepayerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
||||||
depositCoins: []sdk.Coin{sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))},
|
depositCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
borrowCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
borrowCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
||||||
repayCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
repayCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
||||||
},
|
},
|
||||||
@ -77,10 +98,12 @@ func (suite *KeeperTestSuite) TestRepay() {
|
|||||||
{
|
{
|
||||||
"valid: overpayment is adjusted",
|
"valid: overpayment is adjusted",
|
||||||
args{
|
args{
|
||||||
borrower: sdk.AccAddress(crypto.AddressHash([]byte("test"))),
|
borrower: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
|
repayer: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
|
initialRepayerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
||||||
depositCoins: []sdk.Coin{sdk.NewCoin("ukava", sdk.NewInt(80*KAVA_CF))}, // Deposit less so user still has some KAVA
|
depositCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(80*KAVA_CF))), // Deposit less so user still has some KAVA
|
||||||
borrowCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
borrowCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
||||||
repayCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(60*KAVA_CF))), // Exceeds borrowed coins but not user's balance
|
repayCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(60*KAVA_CF))), // Exceeds borrowed coins but not user's balance
|
||||||
},
|
},
|
||||||
@ -93,42 +116,48 @@ func (suite *KeeperTestSuite) TestRepay() {
|
|||||||
{
|
{
|
||||||
"invalid: attempt to repay non-supplied coin",
|
"invalid: attempt to repay non-supplied coin",
|
||||||
args{
|
args{
|
||||||
borrower: sdk.AccAddress(crypto.AddressHash([]byte("test"))),
|
borrower: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
|
repayer: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
|
initialRepayerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
||||||
depositCoins: []sdk.Coin{sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))},
|
depositCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
borrowCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
borrowCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
||||||
repayCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(10*KAVA_CF))),
|
repayCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(10*KAVA_CF))),
|
||||||
},
|
},
|
||||||
errArgs{
|
errArgs{
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
expectDelete: false,
|
expectDelete: false,
|
||||||
contains: "account can only repay up to 0bnb",
|
contains: "no coins of this type borrowed",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid: insufficent balance for repay",
|
"invalid: insufficient balance for repay",
|
||||||
args{
|
args{
|
||||||
borrower: sdk.AccAddress(crypto.AddressHash([]byte("test"))),
|
borrower: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
|
repayer: sdk.AccAddress(crypto.AddressHash([]byte("repayer"))),
|
||||||
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
|
initialRepayerCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(49*KAVA_CF))),
|
||||||
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
||||||
depositCoins: []sdk.Coin{sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))},
|
depositCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
borrowCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
borrowCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),
|
||||||
repayCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(51*KAVA_CF))), // Exceeds user's KAVA balance
|
repayCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))), // Exceeds repayer's balance, but not borrow amount
|
||||||
},
|
},
|
||||||
errArgs{
|
errArgs{
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
expectDelete: false,
|
expectDelete: false,
|
||||||
contains: "account can only repay up to 50000000ukava",
|
contains: "account can only repay up to 49000000ukava",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid: repaying a single coin type results in borrow position below the minimum USD value",
|
"invalid: repaying a single coin type results in borrow position below the minimum USD value",
|
||||||
args{
|
args{
|
||||||
borrower: sdk.AccAddress(crypto.AddressHash([]byte("test"))),
|
borrower: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
|
repayer: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF))),
|
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF))),
|
||||||
|
initialRepayerCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF))),
|
||||||
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
||||||
depositCoins: []sdk.Coin{sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF))},
|
depositCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF))),
|
||||||
borrowCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(50*USDX_CF))),
|
borrowCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(50*USDX_CF))),
|
||||||
repayCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(45*USDX_CF))),
|
repayCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(45*USDX_CF))),
|
||||||
},
|
},
|
||||||
@ -141,12 +170,14 @@ func (suite *KeeperTestSuite) TestRepay() {
|
|||||||
{
|
{
|
||||||
"invalid: repaying multiple coin types results in borrow position below the minimum USD value",
|
"invalid: repaying multiple coin types results in borrow position below the minimum USD value",
|
||||||
args{
|
args{
|
||||||
borrower: sdk.AccAddress(crypto.AddressHash([]byte("test"))),
|
borrower: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
|
repayer: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF))),
|
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF))),
|
||||||
|
initialRepayerCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF)), sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
||||||
depositCoins: []sdk.Coin{sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF))},
|
depositCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF))),
|
||||||
borrowCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(50*USDX_CF)), sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF))), // (50*$1)+(10*$2) = $70
|
borrowCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(50*USDX_CF)), sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF))), // (50*$1)+(10*$2) = $70
|
||||||
repayCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(45*USDX_CF)), sdk.NewCoin("ukava", sdk.NewInt(8*KAVA_CF))), // (45*$1)+(8*2) = $61
|
repayCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(45*USDX_CF)), sdk.NewCoin("ukava", sdk.NewInt(8*KAVA_CF))), // (45*$1)+(8*$2) = $61
|
||||||
},
|
},
|
||||||
errArgs{
|
errArgs{
|
||||||
expectPass: false,
|
expectPass: false,
|
||||||
@ -154,6 +185,24 @@ func (suite *KeeperTestSuite) TestRepay() {
|
|||||||
contains: "proposed borrow's USD value $9.000000000000000000 is below the minimum borrow limit",
|
contains: "proposed borrow's USD value $9.000000000000000000 is below the minimum borrow limit",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"invalid: overpaying multiple coin types results in borrow position below the minimum USD value",
|
||||||
|
args{
|
||||||
|
borrower: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
|
repayer: sdk.AccAddress(crypto.AddressHash([]byte("borrower"))),
|
||||||
|
initialBorrowerCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF))),
|
||||||
|
initialRepayerCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF)), sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))),
|
||||||
|
initialModuleCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*USDX_CF))),
|
||||||
|
depositCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(100*USDX_CF))),
|
||||||
|
borrowCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(50*USDX_CF)), sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF))), // (50*$1)+(10*$2) = $70
|
||||||
|
repayCoins: sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(500*USDX_CF)), sdk.NewCoin("ukava", sdk.NewInt(8*KAVA_CF))), // (500*$1)+(8*$2) = $516, or capping to borrowed amount, (50*$1)+(8*$2) = $66
|
||||||
|
},
|
||||||
|
errArgs{
|
||||||
|
expectPass: false,
|
||||||
|
expectDelete: false,
|
||||||
|
contains: "proposed borrow's USD value $4.000000000000000000 is below the minimum borrow limit",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
@ -163,9 +212,11 @@ func (suite *KeeperTestSuite) TestRepay() {
|
|||||||
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()})
|
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()})
|
||||||
|
|
||||||
// Auth module genesis state
|
// Auth module genesis state
|
||||||
authGS := app.NewAuthGenState(
|
addrs, coinses := uniqueAddressCoins(
|
||||||
[]sdk.AccAddress{tc.args.borrower},
|
[]sdk.AccAddress{tc.args.borrower, tc.args.repayer},
|
||||||
[]sdk.Coins{tc.args.initialBorrowerCoins})
|
[]sdk.Coins{tc.args.initialBorrowerCoins, tc.args.initialRepayerCoins},
|
||||||
|
)
|
||||||
|
authGS := app.NewAuthGenState(addrs, coinses)
|
||||||
|
|
||||||
// Hard module genesis state
|
// Hard module genesis state
|
||||||
hardGS := types.NewGenesisState(types.NewParams(
|
hardGS := types.NewGenesisState(types.NewParams(
|
||||||
@ -242,17 +293,19 @@ func (suite *KeeperTestSuite) TestRepay() {
|
|||||||
err = suite.keeper.Borrow(suite.ctx, tc.args.borrower, tc.args.borrowCoins)
|
err = suite.keeper.Borrow(suite.ctx, tc.args.borrower, tc.args.borrowCoins)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
err = suite.keeper.Repay(suite.ctx, tc.args.borrower, tc.args.borrower, tc.args.repayCoins)
|
previousRepayerCoins := suite.getAccount(tc.args.repayer).GetCoins()
|
||||||
|
|
||||||
|
err = suite.keeper.Repay(suite.ctx, tc.args.repayer, tc.args.borrower, tc.args.repayCoins)
|
||||||
if tc.errArgs.expectPass {
|
if tc.errArgs.expectPass {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
// If we overpaid expect an adjustment
|
// If we overpaid expect an adjustment
|
||||||
repaymentCoins, err := suite.keeper.CalculatePaymentAmount(tc.args.borrowCoins, tc.args.repayCoins)
|
repaymentCoins, err := suite.keeper.CalculatePaymentAmount(tc.args.borrowCoins, tc.args.repayCoins)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
// Check borrower balance
|
// Check repayer balance
|
||||||
expectedBorrowerCoins := tc.args.initialBorrowerCoins.Sub(tc.args.depositCoins).Add(tc.args.borrowCoins...).Sub(repaymentCoins)
|
expectedRepayerCoins := previousRepayerCoins.Sub(repaymentCoins)
|
||||||
acc := suite.getAccount(tc.args.borrower)
|
acc := suite.getAccount(tc.args.repayer)
|
||||||
suite.Require().Equal(expectedBorrowerCoins, acc.GetCoins())
|
suite.Require().Equal(expectedRepayerCoins, acc.GetCoins())
|
||||||
|
|
||||||
// Check module account balance
|
// Check module account balance
|
||||||
expectedModuleCoins := tc.args.initialModuleCoins.Add(tc.args.depositCoins...).Sub(tc.args.borrowCoins).Add(repaymentCoins...)
|
expectedModuleCoins := tc.args.initialModuleCoins.Add(tc.args.depositCoins...).Sub(tc.args.borrowCoins).Add(repaymentCoins...)
|
||||||
@ -271,12 +324,11 @@ func (suite *KeeperTestSuite) TestRepay() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
suite.Require().Error(err)
|
suite.Require().Error(err)
|
||||||
suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains))
|
suite.Require().Contains(err.Error(), tc.errArgs.contains)
|
||||||
|
|
||||||
// Check borrower balance (no repay coins)
|
// Check repayer balance (no repay coins)
|
||||||
expectedBorrowerCoins := tc.args.initialBorrowerCoins.Sub(tc.args.depositCoins).Add(tc.args.borrowCoins...)
|
acc := suite.getAccount(tc.args.repayer)
|
||||||
acc := suite.getAccount(tc.args.borrower)
|
suite.Require().Equal(previousRepayerCoins, acc.GetCoins())
|
||||||
suite.Require().Equal(expectedBorrowerCoins, acc.GetCoins())
|
|
||||||
|
|
||||||
// Check module account balance (no repay coins)
|
// Check module account balance (no repay coins)
|
||||||
expectedModuleCoins := tc.args.initialModuleCoins.Add(tc.args.depositCoins...).Sub(tc.args.borrowCoins)
|
expectedModuleCoins := tc.args.initialModuleCoins.Add(tc.args.depositCoins...).Sub(tc.args.borrowCoins)
|
||||||
@ -291,3 +343,19 @@ func (suite *KeeperTestSuite) TestRepay() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// uniqueAddressCoins removes duplicate addresses, and the corresponding elements in a list of coins.
|
||||||
|
func uniqueAddressCoins(addresses []sdk.AccAddress, coinses []sdk.Coins) ([]sdk.AccAddress, []sdk.Coins) {
|
||||||
|
uniqueAddresses := []sdk.AccAddress{}
|
||||||
|
filteredCoins := []sdk.Coins{}
|
||||||
|
|
||||||
|
addrMap := map[string]bool{}
|
||||||
|
for i, a := range addresses {
|
||||||
|
if !addrMap[a.String()] {
|
||||||
|
uniqueAddresses = append(uniqueAddresses, a)
|
||||||
|
filteredCoins = append(filteredCoins, coinses[i])
|
||||||
|
}
|
||||||
|
addrMap[a.String()] = true
|
||||||
|
}
|
||||||
|
return uniqueAddresses, filteredCoins
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user