mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-10-31 23:08:32 +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
 | ||||
| 	borrow, _ = k.GetBorrow(ctx, owner) | ||||
| 
 | ||||
| 	// Validate that sender holds coins for repayment
 | ||||
| 	err := k.ValidateRepay(ctx, sender, owner, coins) | ||||
| 	// cap the repayment by what's available to repay (the borrow amount)
 | ||||
| 	payment, err := k.CalculatePaymentAmount(borrow.Amount, coins) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	payment, err := k.CalculatePaymentAmount(borrow.Amount, coins) | ||||
| 	// Validate that sender holds coins for repayment
 | ||||
| 	err = k.ValidateRepay(ctx, sender, owner, payment) | ||||
| 	if err != nil { | ||||
| 		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.
 | ||||
| 	// 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
 | ||||
| 	// Unless the user is fully repaying their loan
 | ||||
| 	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)) | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,6 @@ | ||||
| package keeper_test | ||||
| 
 | ||||
| import ( | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| @ -17,14 +16,14 @@ import ( | ||||
| 
 | ||||
| func (suite *KeeperTestSuite) TestRepay() { | ||||
| 	type args struct { | ||||
| 		borrower                  sdk.AccAddress | ||||
| 		initialBorrowerCoins      sdk.Coins | ||||
| 		initialModuleCoins        sdk.Coins | ||||
| 		depositCoins              []sdk.Coin | ||||
| 		borrowCoins               sdk.Coins | ||||
| 		repayCoins                sdk.Coins | ||||
| 		expectedAccountBalance    sdk.Coins | ||||
| 		expectedModAccountBalance sdk.Coins | ||||
| 		borrower             sdk.AccAddress | ||||
| 		repayer              sdk.AccAddress | ||||
| 		initialBorrowerCoins sdk.Coins | ||||
| 		initialRepayerCoins  sdk.Coins | ||||
| 		initialModuleCoins   sdk.Coins | ||||
| 		depositCoins         []sdk.Coin | ||||
| 		borrowCoins          sdk.Coins | ||||
| 		repayCoins           sdk.Coins | ||||
| 	} | ||||
| 
 | ||||
| 	type errArgs struct { | ||||
| @ -45,10 +44,30 @@ func (suite *KeeperTestSuite) TestRepay() { | ||||
| 		{ | ||||
| 			"valid: partial repay", | ||||
| 			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))), | ||||
| 				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.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))), | ||||
| 				repayCoins:           sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF))), | ||||
| 			}, | ||||
| @ -61,10 +80,12 @@ func (suite *KeeperTestSuite) TestRepay() { | ||||
| 		{ | ||||
| 			"valid: repay in full", | ||||
| 			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))), | ||||
| 				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.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(50*KAVA_CF))), | ||||
| 			}, | ||||
| @ -77,10 +98,12 @@ func (suite *KeeperTestSuite) TestRepay() { | ||||
| 		{ | ||||
| 			"valid: overpayment is adjusted", | ||||
| 			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))), | ||||
| 				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.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))), | ||||
| 				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", | ||||
| 			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))), | ||||
| 				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.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)), sdk.NewCoin("bnb", sdk.NewInt(10*KAVA_CF))), | ||||
| 			}, | ||||
| 			errArgs{ | ||||
| 				expectPass:   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{ | ||||
| 				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))), | ||||
| 				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))), | ||||
| 				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(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{ | ||||
| 				expectPass:   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", | ||||
| 			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))), | ||||
| 				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))), | ||||
| 				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))), | ||||
| 				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", | ||||
| 			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))), | ||||
| 				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.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
 | ||||
| 				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{ | ||||
| 				expectPass:   false, | ||||
| @ -154,6 +185,24 @@ func (suite *KeeperTestSuite) TestRepay() { | ||||
| 				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 { | ||||
| @ -163,9 +212,11 @@ func (suite *KeeperTestSuite) TestRepay() { | ||||
| 			ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()}) | ||||
| 
 | ||||
| 			// Auth module genesis state
 | ||||
| 			authGS := app.NewAuthGenState( | ||||
| 				[]sdk.AccAddress{tc.args.borrower}, | ||||
| 				[]sdk.Coins{tc.args.initialBorrowerCoins}) | ||||
| 			addrs, coinses := uniqueAddressCoins( | ||||
| 				[]sdk.AccAddress{tc.args.borrower, tc.args.repayer}, | ||||
| 				[]sdk.Coins{tc.args.initialBorrowerCoins, tc.args.initialRepayerCoins}, | ||||
| 			) | ||||
| 			authGS := app.NewAuthGenState(addrs, coinses) | ||||
| 
 | ||||
| 			// Hard module genesis state
 | ||||
| 			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) | ||||
| 			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 { | ||||
| 				suite.Require().NoError(err) | ||||
| 				// If we overpaid expect an adjustment
 | ||||
| 				repaymentCoins, err := suite.keeper.CalculatePaymentAmount(tc.args.borrowCoins, tc.args.repayCoins) | ||||
| 				suite.Require().NoError(err) | ||||
| 
 | ||||
| 				// Check borrower balance
 | ||||
| 				expectedBorrowerCoins := tc.args.initialBorrowerCoins.Sub(tc.args.depositCoins).Add(tc.args.borrowCoins...).Sub(repaymentCoins) | ||||
| 				acc := suite.getAccount(tc.args.borrower) | ||||
| 				suite.Require().Equal(expectedBorrowerCoins, acc.GetCoins()) | ||||
| 				// Check repayer balance
 | ||||
| 				expectedRepayerCoins := previousRepayerCoins.Sub(repaymentCoins) | ||||
| 				acc := suite.getAccount(tc.args.repayer) | ||||
| 				suite.Require().Equal(expectedRepayerCoins, acc.GetCoins()) | ||||
| 
 | ||||
| 				// Check module account balance
 | ||||
| 				expectedModuleCoins := tc.args.initialModuleCoins.Add(tc.args.depositCoins...).Sub(tc.args.borrowCoins).Add(repaymentCoins...) | ||||
| @ -271,12 +324,11 @@ func (suite *KeeperTestSuite) TestRepay() { | ||||
| 				} | ||||
| 			} else { | ||||
| 				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)
 | ||||
| 				expectedBorrowerCoins := tc.args.initialBorrowerCoins.Sub(tc.args.depositCoins).Add(tc.args.borrowCoins...) | ||||
| 				acc := suite.getAccount(tc.args.borrower) | ||||
| 				suite.Require().Equal(expectedBorrowerCoins, acc.GetCoins()) | ||||
| 				// Check repayer balance (no repay coins)
 | ||||
| 				acc := suite.getAccount(tc.args.repayer) | ||||
| 				suite.Require().Equal(previousRepayerCoins, acc.GetCoins()) | ||||
| 
 | ||||
| 				// Check module account balance (no repay coins)
 | ||||
| 				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
	 Ruaridh
						Ruaridh