mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-04-04 15:55:23 +00:00 
			
		
		
		
	Hard Audit: decrement total borrowed on liquidation (#823)
* decrement total borrow on liquidation * copy kevin's decrement changes * check error in liquidation * extend decrement borrowed changes * mimic negative check on the supplied coins side * update liquidation test
This commit is contained in:
		
							parent
							
								
									7e39c1d0a8
								
							
						
					
					
						commit
						a5b72363d0
					
				| @ -240,9 +240,15 @@ func (k Keeper) DecrementBorrowedCoins(ctx sdk.Context, coins sdk.Coins) error { | ||||
| 		return sdkerrors.Wrapf(types.ErrBorrowedCoinsNotFound, "cannot repay coins if no coins are currently borrowed") | ||||
| 	} | ||||
| 
 | ||||
| 	updatedBorrowedCoins, isAnyNegative := borrowedCoins.SafeSub(coins) | ||||
| 	if isAnyNegative { | ||||
| 		return types.ErrNegativeBorrowedCoins | ||||
| 	updatedBorrowedCoins := sdk.NewCoins() | ||||
| 	for _, coin := range coins { | ||||
| 		// If amount is greater than total borrowed amount due to rounding, set total borrowed amount to 0
 | ||||
| 		// by skipping the coin such that it's not included in the updatedBorrowedCoins object
 | ||||
| 		if coin.Amount.GTE(borrowedCoins.AmountOf(coin.Denom)) { | ||||
| 			continue | ||||
| 		} | ||||
| 		updatedBorrowCoin := sdk.NewCoin(coin.Denom, borrowedCoins.AmountOf(coin.Denom).Sub(coin.Amount)) | ||||
| 		updatedBorrowedCoins = updatedBorrowedCoins.Add(updatedBorrowCoin) | ||||
| 	} | ||||
| 
 | ||||
| 	k.SetBorrowedCoins(ctx, updatedBorrowedCoins) | ||||
|  | ||||
| @ -145,9 +145,15 @@ func (k Keeper) DecrementSuppliedCoins(ctx sdk.Context, coins sdk.Coins) error { | ||||
| 		return sdkerrors.Wrapf(types.ErrSuppliedCoinsNotFound, "cannot withdraw if no coins are deposited") | ||||
| 	} | ||||
| 
 | ||||
| 	updatedSuppliedCoins, isAnyNegative := suppliedCoins.SafeSub(coins) | ||||
| 	if isAnyNegative { | ||||
| 		return types.ErrNegativeSuppliedCoins | ||||
| 	updatedSuppliedCoins := sdk.NewCoins() | ||||
| 	for _, coin := range coins { | ||||
| 		// If amount is greater than total supplied amount due to rounding, set total supplied amount to 0
 | ||||
| 		// by skipping the coin such that it's not included in the updatedSuppliedCoins object
 | ||||
| 		if coin.Amount.GTE(suppliedCoins.AmountOf(coin.Denom)) { | ||||
| 			continue | ||||
| 		} | ||||
| 		updatedSupplyCoin := sdk.NewCoin(coin.Denom, suppliedCoins.AmountOf(coin.Denom).Sub(coin.Amount)) | ||||
| 		updatedSuppliedCoins = updatedSuppliedCoins.Add(updatedSupplyCoin) | ||||
| 	} | ||||
| 
 | ||||
| 	k.SetSuppliedCoins(ctx, updatedSuppliedCoins) | ||||
|  | ||||
| @ -180,9 +180,15 @@ func (k Keeper) StartAuctions(ctx sdk.Context, borrower sdk.AccAddress, borrows, | ||||
| 				if err != nil { | ||||
| 					return liquidatedCoins, err | ||||
| 				} | ||||
| 				// Decrement supplied coins and increment borrowed coins optimistically
 | ||||
| 				k.DecrementSuppliedCoins(ctx, sdk.Coins{lot}) | ||||
| 				k.IncrementBorrowedCoins(ctx, sdk.Coins{bid}) | ||||
| 				// Decrement supplied coins and decrement borrowed coins optimistically
 | ||||
| 				err = k.DecrementSuppliedCoins(ctx, sdk.Coins{lot}) | ||||
| 				if err != nil { | ||||
| 					return liquidatedCoins, err | ||||
| 				} | ||||
| 				err = k.DecrementBorrowedCoins(ctx, sdk.Coins{bid}) | ||||
| 				if err != nil { | ||||
| 					return liquidatedCoins, err | ||||
| 				} | ||||
| 
 | ||||
| 				// Add lot to liquidated coins
 | ||||
| 				liquidatedCoins = liquidatedCoins.Add(lot) | ||||
| @ -225,9 +231,15 @@ func (k Keeper) StartAuctions(ctx sdk.Context, borrower sdk.AccAddress, borrows, | ||||
| 				if err != nil { | ||||
| 					return liquidatedCoins, err | ||||
| 				} | ||||
| 				// Decrement supplied coins and increment borrowed coins optimistically
 | ||||
| 				k.DecrementSuppliedCoins(ctx, sdk.Coins{lot}) | ||||
| 				k.IncrementBorrowedCoins(ctx, sdk.Coins{bid}) | ||||
| 				// Decrement supplied coins and decrement borrowed coins optimistically
 | ||||
| 				err = k.DecrementSuppliedCoins(ctx, sdk.Coins{lot}) | ||||
| 				if err != nil { | ||||
| 					return liquidatedCoins, err | ||||
| 				} | ||||
| 				err = k.DecrementBorrowedCoins(ctx, sdk.Coins{bid}) | ||||
| 				if err != nil { | ||||
| 					return liquidatedCoins, err | ||||
| 				} | ||||
| 
 | ||||
| 				// Add lot to liquidated coins
 | ||||
| 				liquidatedCoins = liquidatedCoins.Add(lot) | ||||
|  | ||||
| @ -18,20 +18,20 @@ import ( | ||||
| 
 | ||||
| func (suite *KeeperTestSuite) TestKeeperLiquidation() { | ||||
| 	type args struct { | ||||
| 		borrower                sdk.AccAddress | ||||
| 		keeper                  sdk.AccAddress | ||||
| 		keeperRewardPercent     sdk.Dec | ||||
| 		initialModuleCoins      sdk.Coins | ||||
| 		initialBorrowerCoins    sdk.Coins | ||||
| 		initialKeeperCoins      sdk.Coins | ||||
| 		depositCoins            []sdk.Coin | ||||
| 		borrowCoins             sdk.Coins | ||||
| 		liquidateAfter          int64 | ||||
| 		expectedLiquidatedCoins sdk.Coins | ||||
| 		expectedBidCoins        sdk.Coins | ||||
| 		expectedKeeperCoins     sdk.Coins         // coins keeper address should have after successfully liquidating position
 | ||||
| 		expectedBorrowerCoins   sdk.Coins         // additional coins (if any) the borrower address should have after successfully liquidating position
 | ||||
| 		expectedAuctions        auctypes.Auctions // the auctions we should expect to find have been started
 | ||||
| 		borrower                   sdk.AccAddress | ||||
| 		keeper                     sdk.AccAddress | ||||
| 		keeperRewardPercent        sdk.Dec | ||||
| 		initialModuleCoins         sdk.Coins | ||||
| 		initialBorrowerCoins       sdk.Coins | ||||
| 		initialKeeperCoins         sdk.Coins | ||||
| 		depositCoins               []sdk.Coin | ||||
| 		borrowCoins                sdk.Coins | ||||
| 		liquidateAfter             int64 | ||||
| 		expectedTotalSuppliedCoins sdk.Coins | ||||
| 		expectedTotalBorrowedCoins sdk.Coins | ||||
| 		expectedKeeperCoins        sdk.Coins         // coins keeper address should have after successfully liquidating position
 | ||||
| 		expectedBorrowerCoins      sdk.Coins         // additional coins (if any) the borrower address should have after successfully liquidating position
 | ||||
| 		expectedAuctions           auctypes.Auctions // the auctions we should expect to find have been started
 | ||||
| 	} | ||||
| 
 | ||||
| 	type errArgs struct { | ||||
| @ -63,19 +63,19 @@ func (suite *KeeperTestSuite) TestKeeperLiquidation() { | ||||
| 		{ | ||||
| 			"valid: keeper liquidates borrow", | ||||
| 			args{ | ||||
| 				borrower:                borrower, | ||||
| 				keeper:                  keeper, | ||||
| 				keeperRewardPercent:     sdk.MustNewDecFromStr("0.05"), | ||||
| 				initialModuleCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				initialBorrowerCoins:    sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				initialKeeperCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				depositCoins:            sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF))), | ||||
| 				borrowCoins:             sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(8*KAVA_CF))), | ||||
| 				liquidateAfter:          oneMonthInSeconds, | ||||
| 				expectedLiquidatedCoins: sdk.NewCoins(sdk.NewInt64Coin("ukava", 9500390)), | ||||
| 				expectedBidCoins:        sdk.NewCoins(sdk.NewInt64Coin("ukava", 8004766)), | ||||
| 				expectedKeeperCoins:     sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100500020))), | ||||
| 				expectedBorrowerCoins:   sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(98000001))), // initial - deposit + borrow + liquidation leftovers
 | ||||
| 				borrower:                   borrower, | ||||
| 				keeper:                     keeper, | ||||
| 				keeperRewardPercent:        sdk.MustNewDecFromStr("0.05"), | ||||
| 				initialModuleCoins:         sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				initialBorrowerCoins:       sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				initialKeeperCoins:         sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				depositCoins:               sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF))), | ||||
| 				borrowCoins:                sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(8*KAVA_CF))), | ||||
| 				liquidateAfter:             oneMonthInSeconds, | ||||
| 				expectedTotalSuppliedCoins: sdk.NewCoins(sdk.NewInt64Coin("ukava", 504138)), | ||||
| 				expectedTotalBorrowedCoins: nil, | ||||
| 				expectedKeeperCoins:        sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100500020))), | ||||
| 				expectedBorrowerCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(98000001))), // initial - deposit + borrow + liquidation leftovers
 | ||||
| 				expectedAuctions: auctypes.Auctions{ | ||||
| 					auctypes.CollateralAuction{ | ||||
| 						BaseAuction: auctypes.BaseAuction{ | ||||
| @ -102,19 +102,19 @@ func (suite *KeeperTestSuite) TestKeeperLiquidation() { | ||||
| 		{ | ||||
| 			"valid: single deposit, multiple borrows", | ||||
| 			args{ | ||||
| 				borrower:                borrower, | ||||
| 				keeper:                  keeper, | ||||
| 				keeperRewardPercent:     sdk.MustNewDecFromStr("0.05"), | ||||
| 				initialModuleCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(1000*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(1000*BTCB_CF))), | ||||
| 				initialBorrowerCoins:    sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				initialKeeperCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				depositCoins:            sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),                                                                                                                                     // $100 * 0.8 = $80 borrowable
 | ||||
| 				borrowCoins:             sdk.NewCoins(sdk.NewCoin("usdc", sdk.NewInt(20*KAVA_CF)), sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(2*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(0.2*BTCB_CF))), // $20+$20+$20 = $80 borrowed
 | ||||
| 				liquidateAfter:          oneMonthInSeconds, | ||||
| 				expectedLiquidatedCoins: sdk.NewCoins(sdk.NewInt64Coin("ukava", 47500032)), | ||||
| 				expectedBidCoins:        sdk.NewCoins(sdk.NewInt64Coin("bnb", 200003287), sdk.NewInt64Coin("btc", 20000032), sdk.NewInt64Coin("ukava", 10000782), sdk.NewInt64Coin("usdc", 20003284)), | ||||
| 				expectedKeeperCoins:     sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(102500001))), | ||||
| 				expectedBorrowerCoins:   sdk.NewCoins(sdk.NewCoin("usdc", sdk.NewInt(20*KAVA_CF)), sdk.NewCoin("ukava", sdk.NewInt(60000002)), sdk.NewCoin("bnb", sdk.NewInt(2*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(0.2*BTCB_CF))), // initial - deposit + borrow + liquidation leftovers
 | ||||
| 				borrower:                   borrower, | ||||
| 				keeper:                     keeper, | ||||
| 				keeperRewardPercent:        sdk.MustNewDecFromStr("0.05"), | ||||
| 				initialModuleCoins:         sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(1000*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(1000*BTCB_CF))), | ||||
| 				initialBorrowerCoins:       sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				initialKeeperCoins:         sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				depositCoins:               sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF))),                                                                                                                                     // $100 * 0.8 = $80 borrowable
 | ||||
| 				borrowCoins:                sdk.NewCoins(sdk.NewCoin("usdc", sdk.NewInt(20*KAVA_CF)), sdk.NewCoin("ukava", sdk.NewInt(10*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(2*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(0.2*BTCB_CF))), // $20+$20+$20 = $80 borrowed
 | ||||
| 				liquidateAfter:             oneMonthInSeconds, | ||||
| 				expectedTotalSuppliedCoins: sdk.NewCoins(sdk.NewInt64Coin("ukava", 2500711)), | ||||
| 				expectedTotalBorrowedCoins: nil, | ||||
| 				expectedKeeperCoins:        sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(102500001))), | ||||
| 				expectedBorrowerCoins:      sdk.NewCoins(sdk.NewCoin("usdc", sdk.NewInt(20*KAVA_CF)), sdk.NewCoin("ukava", sdk.NewInt(60000002)), sdk.NewCoin("bnb", sdk.NewInt(2*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(0.2*BTCB_CF))), // initial - deposit + borrow + liquidation leftovers
 | ||||
| 				expectedAuctions: auctypes.Auctions{ | ||||
| 					auctypes.CollateralAuction{ | ||||
| 						BaseAuction: auctypes.BaseAuction{ | ||||
| @ -186,19 +186,19 @@ func (suite *KeeperTestSuite) TestKeeperLiquidation() { | ||||
| 		{ | ||||
| 			"valid: multiple deposits, single borrow", | ||||
| 			args{ | ||||
| 				borrower:                borrower, | ||||
| 				keeper:                  keeper, | ||||
| 				keeperRewardPercent:     sdk.MustNewDecFromStr("0.05"), | ||||
| 				initialModuleCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF))), | ||||
| 				initialBorrowerCoins:    sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(100*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(100*BTCB_CF))), | ||||
| 				initialKeeperCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				depositCoins:            sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(10*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(1*BTCB_CF))), // $100 + $100 + $100 = $300 * 0.8 = $240 borrowable                                                                                                                                       // $100 * 0.8 = $80 borrowable
 | ||||
| 				borrowCoins:             sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(120*KAVA_CF))),                                                                                      // $240 borrowed
 | ||||
| 				liquidateAfter:          oneMonthInSeconds, | ||||
| 				expectedLiquidatedCoins: sdk.NewCoins(sdk.NewInt64Coin("bnb", 950000000), sdk.NewInt64Coin("btc", 95000000), sdk.NewInt64Coin("ukava", 47504818)), | ||||
| 				expectedBidCoins:        sdk.NewCoins(sdk.NewInt64Coin("ukava", 120112133)), | ||||
| 				expectedKeeperCoins:     sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(102500253)), sdk.NewCoin("bnb", sdk.NewInt(0.5*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(0.05*BTCB_CF))), // 5% of each seized coin + initial balances
 | ||||
| 				expectedBorrowerCoins:   sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(170.000001*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(90*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(99*BTCB_CF))), | ||||
| 				borrower:                   borrower, | ||||
| 				keeper:                     keeper, | ||||
| 				keeperRewardPercent:        sdk.MustNewDecFromStr("0.05"), | ||||
| 				initialModuleCoins:         sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF))), | ||||
| 				initialBorrowerCoins:       sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(100*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(100*BTCB_CF))), | ||||
| 				initialKeeperCoins:         sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				depositCoins:               sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(50*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(10*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(1*BTCB_CF))), // $100 + $100 + $100 = $300 * 0.8 = $240 borrowable                                                                                                                                       // $100 * 0.8 = $80 borrowable
 | ||||
| 				borrowCoins:                sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(120*KAVA_CF))),                                                                                      // $240 borrowed
 | ||||
| 				liquidateAfter:             oneMonthInSeconds, | ||||
| 				expectedTotalSuppliedCoins: nil, | ||||
| 				expectedTotalBorrowedCoins: nil, | ||||
| 				expectedKeeperCoins:        sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(102500253)), sdk.NewCoin("bnb", sdk.NewInt(0.5*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(0.05*BTCB_CF))), // 5% of each seized coin + initial balances
 | ||||
| 				expectedBorrowerCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(170.000001*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(90*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(99*BTCB_CF))), | ||||
| 				expectedAuctions: auctypes.Auctions{ | ||||
| 					auctypes.CollateralAuction{ | ||||
| 						BaseAuction: auctypes.BaseAuction{ | ||||
| @ -256,19 +256,19 @@ func (suite *KeeperTestSuite) TestKeeperLiquidation() { | ||||
| 			"valid: mutliple stablecoin deposits, multiple variable coin borrows", | ||||
| 			// Auctions: total lot value = $285 ($300 of deposits - $15 keeper reward), total max bid value = $270
 | ||||
| 			args{ | ||||
| 				borrower:                borrower, | ||||
| 				keeper:                  keeper, | ||||
| 				keeperRewardPercent:     sdk.MustNewDecFromStr("0.05"), | ||||
| 				initialModuleCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(1000*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(1000*BTCB_CF))), | ||||
| 				initialBorrowerCoins:    sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(100*KAVA_CF))), | ||||
| 				initialKeeperCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				depositCoins:            sdk.NewCoins(sdk.NewCoin("usdc", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(100*KAVA_CF))), // $100 + $100 + $100 = $300 * 0.9 = $270 borrowable
 | ||||
| 				borrowCoins:             sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(35*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(10*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(1*BTCB_CF))),       // $270 borrowed
 | ||||
| 				liquidateAfter:          oneMonthInSeconds, | ||||
| 				expectedLiquidatedCoins: sdk.NewCoins(sdk.NewInt64Coin("usdc", 95000000), sdk.NewInt64Coin("usdt", 95000000), sdk.NewInt64Coin("usdx", 94999999)), | ||||
| 				expectedBidCoins:        sdk.NewCoins(sdk.NewInt64Coin("bnb", 1000082154), sdk.NewInt64Coin("btc", 100000821), sdk.NewInt64Coin("ukava", 35010052)), | ||||
| 				expectedKeeperCoins:     sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(5*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(5*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(5*KAVA_CF))), // 5% of each seized coin + initial balances
 | ||||
| 				expectedBorrowerCoins:   sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(135*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(10*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(1*BTCB_CF)), sdk.NewCoin("usdx", sdk.NewInt(0.000001*KAVA_CF))), | ||||
| 				borrower:                   borrower, | ||||
| 				keeper:                     keeper, | ||||
| 				keeperRewardPercent:        sdk.MustNewDecFromStr("0.05"), | ||||
| 				initialModuleCoins:         sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(1000*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(1000*BTCB_CF))), | ||||
| 				initialBorrowerCoins:       sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(100*KAVA_CF))), | ||||
| 				initialKeeperCoins:         sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				depositCoins:               sdk.NewCoins(sdk.NewCoin("usdc", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(100*KAVA_CF))), // $100 + $100 + $100 = $300 * 0.9 = $270 borrowable
 | ||||
| 				borrowCoins:                sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(35*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(10*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(1*BTCB_CF))),       // $270 borrowed
 | ||||
| 				liquidateAfter:             oneMonthInSeconds, | ||||
| 				expectedTotalSuppliedCoins: nil, | ||||
| 				expectedTotalBorrowedCoins: nil, | ||||
| 				expectedKeeperCoins:        sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(5*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(5*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(5*KAVA_CF))), // 5% of each seized coin + initial balances
 | ||||
| 				expectedBorrowerCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(135*KAVA_CF)), sdk.NewCoin("bnb", sdk.NewInt(10*BNB_CF)), sdk.NewCoin("btc", sdk.NewInt(1*BTCB_CF)), sdk.NewCoin("usdx", sdk.NewInt(0.000001*KAVA_CF))), | ||||
| 				expectedAuctions: auctypes.Auctions{ | ||||
| 					auctypes.CollateralAuction{ | ||||
| 						BaseAuction: auctypes.BaseAuction{ | ||||
| @ -355,19 +355,19 @@ func (suite *KeeperTestSuite) TestKeeperLiquidation() { | ||||
| 		{ | ||||
| 			"valid: multiple stablecoin deposits, multiple stablecoin borrows", | ||||
| 			args{ | ||||
| 				borrower:                borrower, | ||||
| 				keeper:                  keeper, | ||||
| 				keeperRewardPercent:     sdk.MustNewDecFromStr("0.05"), | ||||
| 				initialModuleCoins:      sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("dai", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(1000*KAVA_CF))), | ||||
| 				initialBorrowerCoins:    sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("dai", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(1000*KAVA_CF))), | ||||
| 				initialKeeperCoins:      sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("dai", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(1000*KAVA_CF))), | ||||
| 				depositCoins:            sdk.NewCoins(sdk.NewCoin("dai", sdk.NewInt(350*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(200*KAVA_CF))), | ||||
| 				borrowCoins:             sdk.NewCoins(sdk.NewCoin("usdt", sdk.NewInt(250*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(245*KAVA_CF))), | ||||
| 				liquidateAfter:          oneMonthInSeconds, | ||||
| 				expectedLiquidatedCoins: sdk.NewCoins(sdk.NewInt64Coin("dai", 332500000), sdk.NewInt64Coin("usdc", 189999999)), | ||||
| 				expectedBidCoins:        sdk.NewCoins(sdk.NewInt64Coin("usdx", 245487894), sdk.NewInt64Coin("usdt", 250507897)), | ||||
| 				expectedKeeperCoins:     sdk.NewCoins(sdk.NewCoin("dai", sdk.NewInt(1017.50*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(1010*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*KAVA_CF))), | ||||
| 				expectedBorrowerCoins:   sdk.NewCoins(sdk.NewCoin("dai", sdk.NewInt(650*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(800000001)), sdk.NewCoin("usdt", sdk.NewInt(1250*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1245*KAVA_CF))), | ||||
| 				borrower:                   borrower, | ||||
| 				keeper:                     keeper, | ||||
| 				keeperRewardPercent:        sdk.MustNewDecFromStr("0.05"), | ||||
| 				initialModuleCoins:         sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("dai", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(1000*KAVA_CF))), | ||||
| 				initialBorrowerCoins:       sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("dai", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(1000*KAVA_CF))), | ||||
| 				initialKeeperCoins:         sdk.NewCoins(sdk.NewCoin("usdx", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("dai", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(1000*KAVA_CF))), | ||||
| 				depositCoins:               sdk.NewCoins(sdk.NewCoin("dai", sdk.NewInt(350*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(200*KAVA_CF))), | ||||
| 				borrowCoins:                sdk.NewCoins(sdk.NewCoin("usdt", sdk.NewInt(250*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(245*KAVA_CF))), | ||||
| 				liquidateAfter:             oneMonthInSeconds, | ||||
| 				expectedTotalSuppliedCoins: nil, | ||||
| 				expectedTotalBorrowedCoins: nil, | ||||
| 				expectedKeeperCoins:        sdk.NewCoins(sdk.NewCoin("dai", sdk.NewInt(1017.50*KAVA_CF)), sdk.NewCoin("usdt", sdk.NewInt(1000*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(1010*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1000*KAVA_CF))), | ||||
| 				expectedBorrowerCoins:      sdk.NewCoins(sdk.NewCoin("dai", sdk.NewInt(650*KAVA_CF)), sdk.NewCoin("usdc", sdk.NewInt(800000001)), sdk.NewCoin("usdt", sdk.NewInt(1250*KAVA_CF)), sdk.NewCoin("usdx", sdk.NewInt(1245*KAVA_CF))), | ||||
| 				expectedAuctions: auctypes.Auctions{ | ||||
| 					auctypes.CollateralAuction{ | ||||
| 						BaseAuction: auctypes.BaseAuction{ | ||||
| @ -424,20 +424,20 @@ func (suite *KeeperTestSuite) TestKeeperLiquidation() { | ||||
| 		{ | ||||
| 			"invalid: borrow not liquidatable", | ||||
| 			args{ | ||||
| 				borrower:                borrower, | ||||
| 				keeper:                  keeper, | ||||
| 				keeperRewardPercent:     sdk.MustNewDecFromStr("0.05"), | ||||
| 				initialModuleCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				initialBorrowerCoins:    sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				initialKeeperCoins:      sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				depositCoins:            sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(20*KAVA_CF))), // Deposit 20 KAVA
 | ||||
| 				borrowCoins:             sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(5*KAVA_CF))),  // Borrow 5 KAVA
 | ||||
| 				liquidateAfter:          oneMonthInSeconds, | ||||
| 				expectedLiquidatedCoins: sdk.Coins{}, | ||||
| 				expectedBidCoins:        sdk.Coins{}, | ||||
| 				expectedKeeperCoins:     sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100.5*KAVA_CF))), | ||||
| 				expectedBorrowerCoins:   sdk.NewCoins(), | ||||
| 				expectedAuctions:        auctypes.Auctions{}, | ||||
| 				borrower:                   borrower, | ||||
| 				keeper:                     keeper, | ||||
| 				keeperRewardPercent:        sdk.MustNewDecFromStr("0.05"), | ||||
| 				initialModuleCoins:         sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				initialBorrowerCoins:       sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				initialKeeperCoins:         sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100*KAVA_CF))), | ||||
| 				depositCoins:               sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(20*KAVA_CF))), // Deposit 20 KAVA
 | ||||
| 				borrowCoins:                sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(5*KAVA_CF))),  // Borrow 5 KAVA
 | ||||
| 				liquidateAfter:             oneMonthInSeconds, | ||||
| 				expectedTotalSuppliedCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(20001624))), | ||||
| 				expectedTotalBorrowedCoins: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(5001709))), | ||||
| 				expectedKeeperCoins:        sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(100.5*KAVA_CF))), | ||||
| 				expectedBorrowerCoins:      sdk.NewCoins(), | ||||
| 				expectedAuctions:           auctypes.Auctions{}, | ||||
| 			}, | ||||
| 			errArgs{ | ||||
| 				expectPass: false, | ||||
| @ -650,10 +650,9 @@ func (suite *KeeperTestSuite) TestKeeperLiquidation() { | ||||
| 
 | ||||
| 				// Check that supplied and borrowed coins have been updated post-liquidation
 | ||||
| 				suppliedCoinsPost, _ := suite.keeper.GetSuppliedCoins(liqCtx) | ||||
| 				suite.Require().Equal(suppliedCoinsPre.Sub(tc.args.expectedLiquidatedCoins), suppliedCoinsPost) | ||||
| 				suite.Require().Equal(tc.args.expectedTotalSuppliedCoins, suppliedCoinsPost) | ||||
| 				borrowedCoinsPost, _ := suite.keeper.GetBorrowedCoins(liqCtx) | ||||
| 
 | ||||
| 				suite.Require().Equal(borrowedCoinsPre.Add(tc.args.expectedBidCoins...), borrowedCoinsPost) | ||||
| 				suite.Require().Equal(tc.args.expectedTotalBorrowedCoins, borrowedCoinsPost) | ||||
| 			} else { | ||||
| 				suite.Require().Error(err) | ||||
| 				suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) | ||||
| @ -668,6 +667,10 @@ func (suite *KeeperTestSuite) TestKeeperLiquidation() { | ||||
| 				// Check that no auctions have been created
 | ||||
| 				auctions := suite.auctionKeeper.GetAllAuctions(liqCtx) | ||||
| 				suite.Require().True(len(auctions) == 0) | ||||
| 
 | ||||
| 				// Check that supplied and borrowed coins have not been updated post-liquidation
 | ||||
| 				suite.Require().Equal(tc.args.expectedTotalSuppliedCoins, suppliedCoinsPre) | ||||
| 				suite.Require().Equal(tc.args.expectedTotalBorrowedCoins, borrowedCoinsPre) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| @ -58,7 +58,10 @@ func (k Keeper) Repay(ctx sdk.Context, sender, owner sdk.AccAddress, coins sdk.C | ||||
| 	} | ||||
| 
 | ||||
| 	// Update total borrowed amount
 | ||||
| 	k.DecrementBorrowedCoins(ctx, payment) | ||||
| 	err = k.DecrementBorrowedCoins(ctx, payment) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// Call incentive hook
 | ||||
| 	if !borrow.Amount.Empty() { | ||||
|  | ||||
| @ -64,8 +64,12 @@ func (k Keeper) Withdraw(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Co | ||||
| 	} else { | ||||
| 		k.SetDeposit(ctx, deposit) | ||||
| 	} | ||||
| 
 | ||||
| 	// Update total supplied amount
 | ||||
| 	k.DecrementSuppliedCoins(ctx, amount) | ||||
| 	err = k.DecrementSuppliedCoins(ctx, amount) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// Call incentive hook
 | ||||
| 	k.AfterDepositModified(ctx, deposit) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Denali Marsh
						Denali Marsh