mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-04-04 15:55:23 +00:00 
			
		
		
		
	Hard Audit: remove LTV index from Hard module (#800)
* remove LTV index * remove LTV param * remove LTV param from tests * remove LTV index from tests * fix incentive hook not called before sync
This commit is contained in:
		
							parent
							
								
									c8d4c02fb7
								
							
						
					
					
						commit
						1b2cfa6d1a
					
				| @ -7,5 +7,4 @@ import ( | ||||
| // BeginBlocker updates interest rates and attempts liquidations
 | ||||
| func BeginBlocker(ctx sdk.Context, k Keeper) { | ||||
| 	k.ApplyInterestRateUpdates(ctx) | ||||
| 	k.AttemptIndexLiquidations(ctx) | ||||
| } | ||||
|  | ||||
| @ -55,7 +55,6 @@ var ( | ||||
| 	DefaultGenesisState           = types.DefaultGenesisState | ||||
| 	DefaultParams                 = types.DefaultParams | ||||
| 	DepositTypeIteratorKey        = types.DepositTypeIteratorKey | ||||
| 	GetBorrowByLtvKey             = types.GetBorrowByLtvKey | ||||
| 	GetTotalVestingPeriodLength   = types.GetTotalVestingPeriodLength | ||||
| 	NewBorrow                     = types.NewBorrow | ||||
| 	NewBorrowInterestFactor       = types.NewBorrowInterestFactor | ||||
| @ -89,7 +88,6 @@ var ( | ||||
| 	BorrowsKeyPrefix                 = types.BorrowsKeyPrefix | ||||
| 	DefaultAccumulationTimes         = types.DefaultAccumulationTimes | ||||
| 	DefaultBorrows                   = types.DefaultBorrows | ||||
| 	DefaultCheckLtvIndexCount        = types.DefaultCheckLtvIndexCount | ||||
| 	DefaultDeposits                  = types.DefaultDeposits | ||||
| 	DefaultMoneyMarkets              = types.DefaultMoneyMarkets | ||||
| 	DefaultTotalBorrowed             = types.DefaultTotalBorrowed | ||||
| @ -124,9 +122,7 @@ var ( | ||||
| 	ErrPriceNotFound                 = types.ErrPriceNotFound | ||||
| 	ErrSuppliedCoinsNotFound         = types.ErrSuppliedCoinsNotFound | ||||
| 	GovDenom                         = types.GovDenom | ||||
| 	KeyCheckLtvIndexCount            = types.KeyCheckLtvIndexCount | ||||
| 	KeyMoneyMarkets                  = types.KeyMoneyMarkets | ||||
| 	LtvIndexPrefix                   = types.LtvIndexPrefix | ||||
| 	ModuleCdc                        = types.ModuleCdc | ||||
| 	MoneyMarketsPrefix               = types.MoneyMarketsPrefix | ||||
| 	PreviousAccrualTimePrefix        = types.PreviousAccrualTimePrefix | ||||
|  | ||||
| @ -142,8 +142,6 @@ func queryDepositsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { | ||||
| 				owner = depositOwner | ||||
| 			} | ||||
| 
 | ||||
| 			// Note: The 10 users with the lowest LTV ratio have their outstanding interest applied each block, so if
 | ||||
| 			// testing with 10 or less addresses they'll all show their latest balance including outstanding interest.
 | ||||
| 			page := viper.GetInt(flags.FlagPage) | ||||
| 			limit := viper.GetInt(flags.FlagLimit) | ||||
| 
 | ||||
| @ -203,8 +201,6 @@ func queryBorrowsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { | ||||
| 				owner = borrowOwner | ||||
| 			} | ||||
| 
 | ||||
| 			// Note: The 10 users with the lowest LTV ratio have their outstanding debt applied each block, so if
 | ||||
| 			// testing with 10 or less addresses they'll all show their latest balance including outstanding debt.
 | ||||
| 			page := viper.GetInt(flags.FlagPage) | ||||
| 			limit := viper.GetInt(flags.FlagLimit) | ||||
| 
 | ||||
|  | ||||
| @ -22,13 +22,11 @@ func (k Keeper) Borrow(ctx sdk.Context, borrower sdk.AccAddress, coins sdk.Coins | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Get current stored LTV based on stored borrows/deposits
 | ||||
| 	prevLtv, err := k.GetStoreLTV(ctx, borrower) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	// Call incentive hooks
 | ||||
| 	existingDeposit, hasExistingDeposit := k.GetDeposit(ctx, borrower) | ||||
| 	if hasExistingDeposit { | ||||
| 		k.BeforeDepositModified(ctx, existingDeposit) | ||||
| 	} | ||||
| 
 | ||||
| 	// Call incentive hook
 | ||||
| 	existingBorrow, hasExistingBorrow := k.GetBorrow(ctx, borrower) | ||||
| 	if hasExistingBorrow { | ||||
| 		k.BeforeBorrowModified(ctx, existingBorrow) | ||||
| @ -38,7 +36,7 @@ func (k Keeper) Borrow(ctx sdk.Context, borrower sdk.AccAddress, coins sdk.Coins | ||||
| 	k.SyncBorrowInterest(ctx, borrower) | ||||
| 
 | ||||
| 	// Validate borrow amount within user and protocol limits
 | ||||
| 	err = k.ValidateBorrow(ctx, borrower, coins) | ||||
| 	err := k.ValidateBorrow(ctx, borrower, coins) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @ -79,20 +77,14 @@ func (k Keeper) Borrow(ctx sdk.Context, borrower sdk.AccAddress, coins sdk.Coins | ||||
| 	} else { | ||||
| 		amount = coins | ||||
| 	} | ||||
| 
 | ||||
| 	// Construct the user's new/updated borrow with amount and interest factors
 | ||||
| 	borrow := types.NewBorrow(borrower, amount, interestFactors) | ||||
| 
 | ||||
| 	// Calculate the new Loan-to-Value ratio of Deposit-to-Borrow
 | ||||
| 	deposit, foundDeposit := k.GetDeposit(ctx, borrower) | ||||
| 	if !foundDeposit { | ||||
| 		return types.ErrDepositNotFound | ||||
| 	if borrow.Amount.Empty() { | ||||
| 		k.DeleteBorrow(ctx, borrow) | ||||
| 	} else { | ||||
| 		k.SetBorrow(ctx, borrow) | ||||
| 	} | ||||
| 	newLtv, err := k.CalculateLtv(ctx, deposit, borrow) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	k.UpdateBorrowAndLtvIndex(ctx, borrow, newLtv, prevLtv) | ||||
| 
 | ||||
| 	// Update total borrowed amount by newly borrowed coins. Don't add user's pending interest as
 | ||||
| 	// it has already been included in the total borrowed coins by the BeginBlocker.
 | ||||
|  | ||||
| @ -269,7 +269,6 @@ func (suite *KeeperTestSuite) TestBorrow() { | ||||
| 					types.NewMoneyMarket("bnb", types.NewBorrowLimit(false, sdk.NewDec(100000000*BNB_CF), tc.args.loanToValueBNB), "bnb:usd", sdk.NewInt(BNB_CF), sdk.NewInt(BNB_CF*1000), types.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()), | ||||
| 					types.NewMoneyMarket("xyz", types.NewBorrowLimit(false, sdk.NewDec(1), tc.args.loanToValueBNB), "xyz:usd", sdk.NewInt(1), sdk.NewInt(1), types.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()), | ||||
| 				}, | ||||
| 				0, // LTV counter
 | ||||
| 			), types.DefaultAccumulationTimes, types.DefaultDeposits, types.DefaultBorrows, | ||||
| 				types.DefaultTotalSupplied, types.DefaultTotalBorrowed, types.DefaultTotalReserves, | ||||
| 			) | ||||
|  | ||||
| @ -23,12 +23,6 @@ func (k Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Coi | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Get current stored LTV based on stored borrows/deposits
 | ||||
| 	prevLtv, err := k.GetStoreLTV(ctx, depositor) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// Call incentive hook
 | ||||
| 	existingDeposit, hasExistingDeposit := k.GetDeposit(ctx, depositor) | ||||
| 	if hasExistingDeposit { | ||||
| @ -39,7 +33,7 @@ func (k Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Coi | ||||
| 	k.SyncBorrowInterest(ctx, depositor) | ||||
| 	k.SyncSupplyInterest(ctx, depositor) | ||||
| 
 | ||||
| 	err = k.ValidateDeposit(ctx, coins) | ||||
| 	err := k.ValidateDeposit(ctx, coins) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @ -85,14 +79,12 @@ func (k Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Coi | ||||
| 	// Update the depositer's amount and supply interest factors in the store
 | ||||
| 	deposit := types.NewDeposit(depositor, amount, interestFactors) | ||||
| 
 | ||||
| 	// Calculate the new Loan-to-Value ratio of Deposit-to-Borrow
 | ||||
| 	borrow, _ := k.GetBorrow(ctx, depositor) | ||||
| 	newLtv, err := k.CalculateLtv(ctx, deposit, borrow) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	if deposit.Amount.Empty() { | ||||
| 		k.DeleteDeposit(ctx, deposit) | ||||
| 	} else { | ||||
| 		k.SetDeposit(ctx, deposit) | ||||
| 	} | ||||
| 
 | ||||
| 	k.UpdateDepositAndLtvIndex(ctx, deposit, newLtv, prevLtv) | ||||
| 	k.IncrementSuppliedCoins(ctx, coins) | ||||
| 	if !foundDeposit { // User's first deposit
 | ||||
| 		k.AfterDepositCreated(ctx, deposit) | ||||
|  | ||||
| @ -111,7 +111,6 @@ func (suite *KeeperTestSuite) TestDeposit() { | ||||
| 					types.NewMoneyMarket("bnb", types.NewBorrowLimit(false, sdk.NewDec(1000000000000000), loanToValue), "bnb:usd", sdk.NewInt(1000000), sdk.NewInt(BNB_CF*1000), types.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()), | ||||
| 					types.NewMoneyMarket("btcb", types.NewBorrowLimit(false, sdk.NewDec(1000000000000000), loanToValue), "btcb:usd", sdk.NewInt(1000000), sdk.NewInt(BTCB_CF*1000), types.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()), | ||||
| 				}, | ||||
| 				0, // LTV counter
 | ||||
| 			), types.DefaultAccumulationTimes, types.DefaultDeposits, types.DefaultBorrows, | ||||
| 				types.DefaultTotalSupplied, types.DefaultTotalBorrowed, types.DefaultTotalReserves, | ||||
| 			) | ||||
|  | ||||
| @ -721,7 +721,6 @@ func (suite *KeeperTestSuite) TestBorrowInterest() { | ||||
| 						tc.args.reserveFactor,     // Reserve Factor
 | ||||
| 						sdk.ZeroDec()),            // Keeper Reward Percentage
 | ||||
| 				}, | ||||
| 				0, // LTV counter
 | ||||
| 			), types.DefaultAccumulationTimes, types.DefaultDeposits, types.DefaultBorrows, | ||||
| 				types.DefaultTotalSupplied, types.DefaultTotalBorrowed, types.DefaultTotalReserves, | ||||
| 			) | ||||
| @ -1137,7 +1136,6 @@ func (suite *KeeperTestSuite) TestSupplyInterest() { | ||||
| 						tc.args.reserveFactor,     // Reserve Factor
 | ||||
| 						sdk.ZeroDec()),            // Keeper Reward Percentage
 | ||||
| 				}, | ||||
| 				0, // LTV counter
 | ||||
| 			), types.DefaultAccumulationTimes, types.DefaultDeposits, types.DefaultBorrows, | ||||
| 				types.DefaultTotalSupplied, types.DefaultTotalBorrowed, types.DefaultTotalReserves, | ||||
| 			) | ||||
|  | ||||
| @ -315,46 +315,3 @@ func (k Keeper) SetSupplyInterestFactor(ctx sdk.Context, denom string, supplyInt | ||||
| 	bz := k.cdc.MustMarshalBinaryBare(supplyInterestFactor) | ||||
| 	store.Set([]byte(denom), bz) | ||||
| } | ||||
| 
 | ||||
| // InsertIntoLtvIndex indexes a user's borrow object by its current LTV
 | ||||
| func (k Keeper) InsertIntoLtvIndex(ctx sdk.Context, ltv sdk.Dec, borrower sdk.AccAddress) { | ||||
| 	store := prefix.NewStore(ctx.KVStore(k.key), types.LtvIndexPrefix) | ||||
| 	store.Set(types.GetBorrowByLtvKey(ltv, borrower), borrower) | ||||
| } | ||||
| 
 | ||||
| // RemoveFromLtvIndex removes a user's borrow object from the LTV index
 | ||||
| func (k Keeper) RemoveFromLtvIndex(ctx sdk.Context, ltv sdk.Dec, borrower sdk.AccAddress) { | ||||
| 	store := prefix.NewStore(ctx.KVStore(k.key), types.LtvIndexPrefix) | ||||
| 	store.Delete(types.GetBorrowByLtvKey(ltv, borrower)) | ||||
| } | ||||
| 
 | ||||
| // IterateLtvIndex provides an iterator over the borrowers ordered by LTV.
 | ||||
| // For results found before the cutoff count, the cb will be called and the item returned.
 | ||||
| func (k Keeper) IterateLtvIndex(ctx sdk.Context, cutoffCount int, | ||||
| 	cb func(addr sdk.AccAddress) (stop bool)) { | ||||
| 	store := prefix.NewStore(ctx.KVStore(k.key), types.LtvIndexPrefix) | ||||
| 	iterator := store.ReverseIterator(nil, nil) | ||||
| 	count := 0 | ||||
| 
 | ||||
| 	defer iterator.Close() | ||||
| 	for ; iterator.Valid(); iterator.Next() { | ||||
| 
 | ||||
| 		// Stop iteration after first 10 items
 | ||||
| 		count = count + 1 | ||||
| 		if count > cutoffCount { | ||||
| 			break | ||||
| 		} | ||||
| 
 | ||||
| 		id := iterator.Value() | ||||
| 		cb(id) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // GetLtvIndexSlice returns the first 10 items in the LTV index from the store
 | ||||
| func (k Keeper) GetLtvIndexSlice(ctx sdk.Context, count int) (addrs []sdk.AccAddress) { | ||||
| 	k.IterateLtvIndex(ctx, count, func(addr sdk.AccAddress) bool { | ||||
| 		addrs = append(addrs, addr) | ||||
| 		return false | ||||
| 	}) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| @ -134,69 +134,6 @@ func (suite *KeeperTestSuite) TestIterateInterestRateModels() { | ||||
| 	suite.Require().Equal(setDenoms, seenDenoms) | ||||
| } | ||||
| 
 | ||||
| func (suite *KeeperTestSuite) TestSetDeleteLtvIndex() { | ||||
| 	// LTV index should have 0 items
 | ||||
| 	firstAddrs := suite.keeper.GetLtvIndexSlice(suite.ctx, 10) | ||||
| 	suite.Require().Equal(0, len(firstAddrs)) | ||||
| 
 | ||||
| 	// Add an item to the LTV index
 | ||||
| 	addr := sdk.AccAddress("test") | ||||
| 	ltv := sdk.MustNewDecFromStr("1.1") | ||||
| 	suite.Require().NotPanics(func() { suite.keeper.InsertIntoLtvIndex(suite.ctx, ltv, addr) }) | ||||
| 
 | ||||
| 	// LTV index should have 1 item
 | ||||
| 	secondAddrs := suite.keeper.GetLtvIndexSlice(suite.ctx, 10) | ||||
| 	suite.Require().Equal(1, len(secondAddrs)) | ||||
| 
 | ||||
| 	// Attempt to remove invalid item from LTV index
 | ||||
| 	fakeLtv := sdk.MustNewDecFromStr("1.2") | ||||
| 	suite.Require().NotPanics(func() { suite.keeper.RemoveFromLtvIndex(suite.ctx, fakeLtv, addr) }) | ||||
| 
 | ||||
| 	// LTV index should still have 1 item
 | ||||
| 	thirdAddrs := suite.keeper.GetLtvIndexSlice(suite.ctx, 10) | ||||
| 	suite.Require().Equal(1, len(thirdAddrs)) | ||||
| 
 | ||||
| 	// Attempt to remove valid item from LTV index
 | ||||
| 	suite.Require().NotPanics(func() { suite.keeper.RemoveFromLtvIndex(suite.ctx, ltv, addr) }) | ||||
| 
 | ||||
| 	// LTV index should still have 0 items
 | ||||
| 	fourthAddrs := suite.keeper.GetLtvIndexSlice(suite.ctx, 10) | ||||
| 	suite.Require().Equal(0, len(fourthAddrs)) | ||||
| } | ||||
| 
 | ||||
| func (suite *KeeperTestSuite) TestIterateLtvIndex() { | ||||
| 	var setAddrs []sdk.AccAddress | ||||
| 	for i := 1; i <= 20; i++ { | ||||
| 		addr := sdk.AccAddress("test" + fmt.Sprint(i)) | ||||
| 		incrementalDec := sdk.NewDec(int64(i)).Quo(sdk.NewDec(10)) | ||||
| 		ltv := sdk.OneDec().Add(incrementalDec) | ||||
| 
 | ||||
| 		// Set the ltv-address pair in the store
 | ||||
| 		suite.Require().NotPanics(func() { suite.keeper.InsertIntoLtvIndex(suite.ctx, ltv, addr) }) | ||||
| 
 | ||||
| 		setAddrs = append(setAddrs, addr) | ||||
| 	} | ||||
| 
 | ||||
| 	// Only the first 10 addresses should be returned
 | ||||
| 	sliceAddrs := suite.keeper.GetLtvIndexSlice(suite.ctx, 10) | ||||
| 	suite.Require().Equal(addressSort(setAddrs[10:20]), addressSort(sliceAddrs)) | ||||
| 
 | ||||
| 	// Insert an additional item into the LTV index that should be returned in the first 10 elements
 | ||||
| 	addr := sdk.AccAddress("test" + fmt.Sprint(21)) | ||||
| 	ltv := sdk.OneDec().Add(sdk.MustNewDecFromStr("15").Quo(sdk.NewDec(10))) | ||||
| 	suite.Require().NotPanics(func() { suite.keeper.InsertIntoLtvIndex(suite.ctx, ltv, addr) }) | ||||
| 
 | ||||
| 	// Fetch the updated LTV index
 | ||||
| 	updatedSliceAddrs := suite.keeper.GetLtvIndexSlice(suite.ctx, 10) | ||||
| 	sawAddr := false | ||||
| 	for _, updatedSliceAddr := range updatedSliceAddrs { | ||||
| 		if updatedSliceAddr.Equals(addr) { | ||||
| 			sawAddr = true | ||||
| 		} | ||||
| 	} | ||||
| 	suite.Require().Equal(true, sawAddr) | ||||
| } | ||||
| 
 | ||||
| func (suite *KeeperTestSuite) getAccount(addr sdk.AccAddress) authexported.Account { | ||||
| 	ak := suite.app.GetAccountKeeper() | ||||
| 	return ak.GetAccount(suite.ctx, addr) | ||||
|  | ||||
| @ -1,8 +1,6 @@ | ||||
| package keeper | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 
 | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | ||||
| 
 | ||||
| @ -16,29 +14,8 @@ type LiqData struct { | ||||
| 	conversionFactor sdk.Int | ||||
| } | ||||
| 
 | ||||
| // AttemptIndexLiquidations attempts to liquidate the lowest LTV borrows
 | ||||
| func (k Keeper) AttemptIndexLiquidations(ctx sdk.Context) error { | ||||
| 	params := k.GetParams(ctx) | ||||
| 	borrowers := k.GetLtvIndexSlice(ctx, params.CheckLtvIndexCount) | ||||
| 
 | ||||
| 	for _, borrower := range borrowers { | ||||
| 		err := k.AttemptKeeperLiquidation(ctx, sdk.AccAddress(types.LiquidatorAccount), borrower) | ||||
| 		if err != nil { | ||||
| 			if !errors.Is(err, types.ErrBorrowNotLiquidatable) && !errors.Is(err, types.ErrBorrowNotFound) { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // AttemptKeeperLiquidation enables a keeper to liquidate an individual borrower's position
 | ||||
| func (k Keeper) AttemptKeeperLiquidation(ctx sdk.Context, keeper sdk.AccAddress, borrower sdk.AccAddress) error { | ||||
| 	prevLtv, err := k.GetStoreLTV(ctx, borrower) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	deposit, found := k.GetDeposit(ctx, borrower) | ||||
| 	if !found { | ||||
| 		return types.ErrDepositNotFound | ||||
| @ -82,7 +59,8 @@ func (k Keeper) AttemptKeeperLiquidation(ctx sdk.Context, keeper sdk.AccAddress, | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	k.DeleteDepositBorrowAndLtvIndex(ctx, deposit, borrow, prevLtv) | ||||
| 	k.DeleteDeposit(ctx, deposit) | ||||
| 	k.DeleteBorrow(ctx, borrow) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| @ -321,35 +299,6 @@ func (k Keeper) IsWithinValidLtvRange(ctx sdk.Context, deposit types.Deposit, bo | ||||
| 	return true, nil | ||||
| } | ||||
| 
 | ||||
| // UpdateBorrowAndLtvIndex updates a borrow and its LTV index value in the store
 | ||||
| func (k Keeper) UpdateBorrowAndLtvIndex(ctx sdk.Context, borrow types.Borrow, newLtv, oldLtv sdk.Dec) { | ||||
| 	k.RemoveFromLtvIndex(ctx, oldLtv, borrow.Borrower) | ||||
| 	if borrow.Amount.Empty() { | ||||
| 		k.DeleteBorrow(ctx, borrow) | ||||
| 		return | ||||
| 	} | ||||
| 	k.SetBorrow(ctx, borrow) | ||||
| 	k.InsertIntoLtvIndex(ctx, newLtv, borrow.Borrower) | ||||
| } | ||||
| 
 | ||||
| // UpdateDepositAndLtvIndex updates a deposit and its LTV index value in the store
 | ||||
| func (k Keeper) UpdateDepositAndLtvIndex(ctx sdk.Context, deposit types.Deposit, newLtv, oldLtv sdk.Dec) { | ||||
| 	k.RemoveFromLtvIndex(ctx, oldLtv, deposit.Depositor) | ||||
| 	if deposit.Amount.Empty() { | ||||
| 		k.DeleteDeposit(ctx, deposit) | ||||
| 		return | ||||
| 	} | ||||
| 	k.SetDeposit(ctx, deposit) | ||||
| 	k.InsertIntoLtvIndex(ctx, newLtv, deposit.Depositor) | ||||
| } | ||||
| 
 | ||||
| // DeleteDepositBorrowAndLtvIndex deletes deposit, borrow, and ltv index
 | ||||
| func (k Keeper) DeleteDepositBorrowAndLtvIndex(ctx sdk.Context, deposit types.Deposit, borrow types.Borrow, oldLtv sdk.Dec) { | ||||
| 	k.RemoveFromLtvIndex(ctx, oldLtv, deposit.Depositor) | ||||
| 	k.DeleteDeposit(ctx, deposit) | ||||
| 	k.DeleteBorrow(ctx, borrow) | ||||
| } | ||||
| 
 | ||||
| // GetStoreLTV calculates the user's current LTV based on their deposits/borrows in the store
 | ||||
| // and does not include any outsanding interest.
 | ||||
| func (k Keeper) GetStoreLTV(ctx sdk.Context, addr sdk.AccAddress) (sdk.Dec, error) { | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -9,12 +9,6 @@ import ( | ||||
| 
 | ||||
| // Repay borrowed funds
 | ||||
| func (k Keeper) Repay(ctx sdk.Context, sender sdk.AccAddress, coins sdk.Coins) error { | ||||
| 	// Get current stored LTV based on stored borrows/deposits
 | ||||
| 	prevLtv, err := k.GetStoreLTV(ctx, sender) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// Check borrow exists here to avoid duplicating store read in ValidateRepay
 | ||||
| 	borrow, found := k.GetBorrow(ctx, sender) | ||||
| 	if !found { | ||||
| @ -27,7 +21,7 @@ func (k Keeper) Repay(ctx sdk.Context, sender sdk.AccAddress, coins sdk.Coins) e | ||||
| 	k.SyncBorrowInterest(ctx, sender) | ||||
| 
 | ||||
| 	// Validate requested repay
 | ||||
| 	err = k.ValidateRepay(ctx, sender, coins) | ||||
| 	err := k.ValidateRepay(ctx, sender, coins) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @ -57,17 +51,11 @@ func (k Keeper) Repay(ctx sdk.Context, sender sdk.AccAddress, coins sdk.Coins) e | ||||
| 	// Update user's borrow in store
 | ||||
| 	borrow.Amount = borrow.Amount.Sub(payment) | ||||
| 
 | ||||
| 	// Calculate the new Loan-to-Value ratio of Deposit-to-Borrow
 | ||||
| 	deposit, foundDeposit := k.GetDeposit(ctx, sender) | ||||
| 	if !foundDeposit { | ||||
| 		return types.ErrDepositNotFound | ||||
| 	if borrow.Amount.Empty() { | ||||
| 		k.DeleteBorrow(ctx, borrow) | ||||
| 	} else { | ||||
| 		k.SetBorrow(ctx, borrow) | ||||
| 	} | ||||
| 	newLtv, err := k.CalculateLtv(ctx, deposit, borrow) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	k.UpdateBorrowAndLtvIndex(ctx, borrow, newLtv, prevLtv) | ||||
| 
 | ||||
| 	// Update total borrowed amount
 | ||||
| 	k.DecrementBorrowedCoins(ctx, payment) | ||||
|  | ||||
| @ -155,7 +155,6 @@ func (suite *KeeperTestSuite) TestRepay() { | ||||
| 						sdk.MustNewDecFromStr("0.05"),  // Reserve Factor
 | ||||
| 						sdk.MustNewDecFromStr("0.05")), // Keeper Reward Percent
 | ||||
| 				}, | ||||
| 				0, // LTV counter
 | ||||
| 			), types.DefaultAccumulationTimes, types.DefaultDeposits, types.DefaultBorrows, | ||||
| 				types.DefaultTotalSupplied, types.DefaultTotalBorrowed, types.DefaultTotalReserves, | ||||
| 			) | ||||
|  | ||||
| @ -285,7 +285,6 @@ func (suite *KeeperTestSuite) TestSendTimeLockedCoinsToAccount() { | ||||
| 					types.NewMoneyMarket("usdx", types.NewBorrowLimit(false, sdk.NewDec(1000000000000000), loanToValue), "usdx:usd", sdk.NewInt(1000000), sdk.NewInt(USDX_CF*1000), types.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()), | ||||
| 					types.NewMoneyMarket("ukava", types.NewBorrowLimit(false, sdk.NewDec(1000000000000000), loanToValue), "kava:usd", sdk.NewInt(1000000), sdk.NewInt(KAVA_CF*1000), types.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()), | ||||
| 				}, | ||||
| 				0, // LTV counter
 | ||||
| 			), types.DefaultAccumulationTimes, types.DefaultDeposits, types.DefaultBorrows, | ||||
| 				types.DefaultTotalSupplied, types.DefaultTotalBorrowed, types.DefaultTotalReserves, | ||||
| 			) | ||||
|  | ||||
| @ -9,18 +9,16 @@ import ( | ||||
| 
 | ||||
| // Withdraw returns some or all of a deposit back to original depositor
 | ||||
| func (k Keeper) Withdraw(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Coins) error { | ||||
| 	// Get current stored LTV based on stored borrows/deposits
 | ||||
| 	prevLtv, err := k.GetStoreLTV(ctx, depositor) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	deposit, found := k.GetDeposit(ctx, depositor) | ||||
| 	if !found { | ||||
| 		return sdkerrors.Wrapf(types.ErrDepositNotFound, "no deposit found for %s", depositor) | ||||
| 	} | ||||
| 	// Call incentive hook
 | ||||
| 	// Call incentive hooks
 | ||||
| 	k.BeforeDepositModified(ctx, deposit) | ||||
| 	existingBorrow, hasExistingBorrow := k.GetBorrow(ctx, depositor) | ||||
| 	if hasExistingBorrow { | ||||
| 		k.BeforeBorrowModified(ctx, existingBorrow) | ||||
| 	} | ||||
| 
 | ||||
| 	k.SyncBorrowInterest(ctx, depositor) | ||||
| 	k.SyncSupplyInterest(ctx, depositor) | ||||
| @ -61,12 +59,11 @@ func (k Keeper) Withdraw(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Co | ||||
| 	} | ||||
| 
 | ||||
| 	deposit.Amount = deposit.Amount.Sub(amount) | ||||
| 	newLtv, err := k.CalculateLtv(ctx, deposit, borrow) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	if deposit.Amount.Empty() { | ||||
| 		k.DeleteDeposit(ctx, deposit) | ||||
| 	} else { | ||||
| 		k.SetDeposit(ctx, deposit) | ||||
| 	} | ||||
| 	k.UpdateDepositAndLtvIndex(ctx, deposit, newLtv, prevLtv) | ||||
| 
 | ||||
| 	// Update total supplied amount
 | ||||
| 	k.DecrementSuppliedCoins(ctx, amount) | ||||
| 
 | ||||
|  | ||||
| @ -129,7 +129,6 @@ func (suite *KeeperTestSuite) TestWithdraw() { | ||||
| 					types.NewMoneyMarket("ukava", types.NewBorrowLimit(false, sdk.NewDec(1000000000000000), loanToValue), "kava:usd", sdk.NewInt(1000000), sdk.NewInt(KAVA_CF*1000), types.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()), | ||||
| 					types.NewMoneyMarket("bnb", types.NewBorrowLimit(false, sdk.NewDec(1000000000000000), loanToValue), "bnb:usd", sdk.NewInt(100000000), sdk.NewInt(BNB_CF*1000), types.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()), | ||||
| 				}, | ||||
| 				0, // LTV counter
 | ||||
| 			), types.DefaultAccumulationTimes, types.DefaultDeposits, types.DefaultBorrows, | ||||
| 				types.DefaultTotalSupplied, types.DefaultTotalBorrowed, types.DefaultTotalReserves, | ||||
| 			) | ||||
| @ -283,7 +282,6 @@ func (suite *KeeperTestSuite) TestLtvWithdraw() { | ||||
| 						reserveFactor,                  // Reserve Factor
 | ||||
| 						sdk.MustNewDecFromStr("0.05")), // Keeper Reward Percent
 | ||||
| 				}, | ||||
| 				0, // LTV counter
 | ||||
| 			), types.DefaultAccumulationTimes, types.DefaultDeposits, types.DefaultBorrows, | ||||
| 				types.DefaultTotalSupplied, types.DefaultTotalBorrowed, types.DefaultTotalReserves, | ||||
| 			) | ||||
|  | ||||
| @ -61,7 +61,6 @@ func (suite *GenesisTestSuite) TestGenesisValidation() { | ||||
| 					types.MoneyMarkets{ | ||||
| 						types.NewMoneyMarket("usdx", types.NewBorrowLimit(true, sdk.MustNewDecFromStr("100000000000"), sdk.MustNewDecFromStr("1")), "usdx:usd", sdk.NewInt(USDX_CF), sdk.NewInt(USDX_CF*1000), types.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()), | ||||
| 					}, | ||||
| 					10, | ||||
| 				), | ||||
| 				gats: types.GenesisAccumulationTimes{ | ||||
| 					types.NewGenesisAccumulationTime("usdx", time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), sdk.OneDec(), sdk.OneDec()), | ||||
|  | ||||
| @ -1,9 +1,5 @@ | ||||
| package types | ||||
| 
 | ||||
| import ( | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	// ModuleName name that will be used throughout the module
 | ||||
| 	ModuleName = "hard" | ||||
| @ -38,7 +34,6 @@ var ( | ||||
| 	BorrowInterestFactorPrefix    = []byte{0x08} // denom -> sdk.Dec
 | ||||
| 	SupplyInterestFactorPrefix    = []byte{0x09} // denom -> sdk.Dec
 | ||||
| 	DelegatorInterestFactorPrefix = []byte{0x10} // denom -> sdk.Dec
 | ||||
| 	LtvIndexPrefix                = []byte{0x11} | ||||
| 	sep                           = []byte(":") | ||||
| ) | ||||
| 
 | ||||
| @ -47,11 +42,6 @@ func DepositTypeIteratorKey(denom string) []byte { | ||||
| 	return createKey([]byte(denom)) | ||||
| } | ||||
| 
 | ||||
| // GetBorrowByLtvKey is used by the LTV index
 | ||||
| func GetBorrowByLtvKey(ltv sdk.Dec, borrower sdk.AccAddress) []byte { | ||||
| 	return append(ltv.Bytes(), borrower...) | ||||
| } | ||||
| 
 | ||||
| func createKey(bytes ...[]byte) (r []byte) { | ||||
| 	for _, b := range bytes { | ||||
| 		r = append(r, b...) | ||||
|  | ||||
| @ -11,23 +11,20 @@ import ( | ||||
| 
 | ||||
| // Parameter keys and default values
 | ||||
| var ( | ||||
| 	KeyMoneyMarkets           = []byte("MoneyMarkets") | ||||
| 	KeyCheckLtvIndexCount     = []byte("CheckLtvIndexCount") | ||||
| 	DefaultMoneyMarkets       = MoneyMarkets{} | ||||
| 	DefaultCheckLtvIndexCount = 10 | ||||
| 	GovDenom                  = cdptypes.DefaultGovDenom | ||||
| 	DefaultAccumulationTimes  = GenesisAccumulationTimes{} | ||||
| 	DefaultTotalSupplied      = sdk.Coins{} | ||||
| 	DefaultTotalBorrowed      = sdk.Coins{} | ||||
| 	DefaultTotalReserves      = sdk.Coins{} | ||||
| 	DefaultDeposits           = Deposits{} | ||||
| 	DefaultBorrows            = Borrows{} | ||||
| 	KeyMoneyMarkets          = []byte("MoneyMarkets") | ||||
| 	DefaultMoneyMarkets      = MoneyMarkets{} | ||||
| 	GovDenom                 = cdptypes.DefaultGovDenom | ||||
| 	DefaultAccumulationTimes = GenesisAccumulationTimes{} | ||||
| 	DefaultTotalSupplied     = sdk.Coins{} | ||||
| 	DefaultTotalBorrowed     = sdk.Coins{} | ||||
| 	DefaultTotalReserves     = sdk.Coins{} | ||||
| 	DefaultDeposits          = Deposits{} | ||||
| 	DefaultBorrows           = Borrows{} | ||||
| ) | ||||
| 
 | ||||
| // Params governance parameters for hard module
 | ||||
| type Params struct { | ||||
| 	MoneyMarkets       MoneyMarkets `json:"money_markets" yaml:"money_markets"` | ||||
| 	CheckLtvIndexCount int          `json:"check_ltv_index_count" yaml:"check_ltv_index_count"` | ||||
| 	MoneyMarkets MoneyMarkets `json:"money_markets" yaml:"money_markets"` | ||||
| } | ||||
| 
 | ||||
| // BorrowLimit enforces restrictions on a money market
 | ||||
| @ -232,24 +229,22 @@ func (irm InterestRateModel) Equal(irmCompareTo InterestRateModel) bool { | ||||
| type InterestRateModels []InterestRateModel | ||||
| 
 | ||||
| // NewParams returns a new params object
 | ||||
| func NewParams(moneyMarkets MoneyMarkets, checkLtvIndexCount int) Params { | ||||
| func NewParams(moneyMarkets MoneyMarkets) Params { | ||||
| 	return Params{ | ||||
| 		MoneyMarkets:       moneyMarkets, | ||||
| 		CheckLtvIndexCount: checkLtvIndexCount, | ||||
| 		MoneyMarkets: moneyMarkets, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // DefaultParams returns default params for hard module
 | ||||
| func DefaultParams() Params { | ||||
| 	return NewParams(DefaultMoneyMarkets, DefaultCheckLtvIndexCount) | ||||
| 	return NewParams(DefaultMoneyMarkets) | ||||
| } | ||||
| 
 | ||||
| // String implements fmt.Stringer
 | ||||
| func (p Params) String() string { | ||||
| 	return fmt.Sprintf(`Params: | ||||
| 	Money Markets %v | ||||
| 	Check LTV Index Count: %v`, | ||||
| 		p.MoneyMarkets, p.CheckLtvIndexCount) | ||||
| 	Money Markets %v`, | ||||
| 		p.MoneyMarkets) | ||||
| } | ||||
| 
 | ||||
| // ParamKeyTable Key declaration for parameters
 | ||||
| @ -261,18 +256,12 @@ func ParamKeyTable() params.KeyTable { | ||||
| func (p *Params) ParamSetPairs() params.ParamSetPairs { | ||||
| 	return params.ParamSetPairs{ | ||||
| 		params.NewParamSetPair(KeyMoneyMarkets, &p.MoneyMarkets, validateMoneyMarketParams), | ||||
| 		params.NewParamSetPair(KeyCheckLtvIndexCount, &p.CheckLtvIndexCount, validateCheckLtvIndexCount), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Validate checks that the parameters have valid values.
 | ||||
| func (p Params) Validate() error { | ||||
| 
 | ||||
| 	if err := validateMoneyMarketParams(p.MoneyMarkets); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return validateCheckLtvIndexCount(p.CheckLtvIndexCount) | ||||
| 	return validateMoneyMarketParams(p.MoneyMarkets) | ||||
| } | ||||
| 
 | ||||
| func validateMoneyMarketParams(i interface{}) error { | ||||
| @ -283,16 +272,3 @@ func validateMoneyMarketParams(i interface{}) error { | ||||
| 
 | ||||
| 	return mm.Validate() | ||||
| } | ||||
| 
 | ||||
| func validateCheckLtvIndexCount(i interface{}) error { | ||||
| 	ltvCheckCount, ok := i.(int) | ||||
| 	if !ok { | ||||
| 		return fmt.Errorf("invalid parameter type: %T", i) | ||||
| 	} | ||||
| 
 | ||||
| 	if ltvCheckCount < 0 { | ||||
| 		return fmt.Errorf("CheckLtvIndexCount param must be positive, got: %d", ltvCheckCount) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @ -15,8 +15,7 @@ type ParamTestSuite struct { | ||||
| 
 | ||||
| func (suite *ParamTestSuite) TestParamValidation() { | ||||
| 	type args struct { | ||||
| 		mms        types.MoneyMarkets | ||||
| 		ltvCounter int | ||||
| 		mms types.MoneyMarkets | ||||
| 	} | ||||
| 	testCases := []struct { | ||||
| 		name        string | ||||
| @ -27,8 +26,7 @@ func (suite *ParamTestSuite) TestParamValidation() { | ||||
| 		{ | ||||
| 			name: "default", | ||||
| 			args: args{ | ||||
| 				mms:        types.DefaultMoneyMarkets, | ||||
| 				ltvCounter: types.DefaultCheckLtvIndexCount, | ||||
| 				mms: types.DefaultMoneyMarkets, | ||||
| 			}, | ||||
| 			expectPass:  true, | ||||
| 			expectedErr: "", | ||||
| @ -36,7 +34,7 @@ func (suite *ParamTestSuite) TestParamValidation() { | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(tc.name, func() { | ||||
| 			params := types.NewParams(tc.args.mms, tc.args.ltvCounter) | ||||
| 			params := types.NewParams(tc.args.mms) | ||||
| 			err := params.Validate() | ||||
| 			if tc.expectPass { | ||||
| 				suite.NoError(err) | ||||
|  | ||||
| @ -164,7 +164,6 @@ func NewHardGenStateMulti() app.GenesisState { | ||||
| 			hard.NewMoneyMarket("btcb", hard.NewBorrowLimit(false, borrowLimit, loanToValue), "btc:usd", sdk.NewInt(1000000), sdk.NewInt(BTCB_CF*1000), hard.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()), | ||||
| 			hard.NewMoneyMarket("xrp", hard.NewBorrowLimit(false, borrowLimit, loanToValue), "xrp:usd", sdk.NewInt(1000000), sdk.NewInt(BTCB_CF*1000), hard.NewInterestRateModel(sdk.MustNewDecFromStr("0.05"), sdk.MustNewDecFromStr("2"), sdk.MustNewDecFromStr("0.8"), sdk.MustNewDecFromStr("10")), sdk.MustNewDecFromStr("0.05"), sdk.ZeroDec()), | ||||
| 		}, | ||||
| 		0, // LTV counter
 | ||||
| 	), hard.DefaultAccumulationTimes, hard.DefaultDeposits, hard.DefaultBorrows, | ||||
| 		hard.DefaultTotalSupplied, hard.DefaultTotalBorrowed, hard.DefaultTotalReserves, | ||||
| 	) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Denali Marsh
						Denali Marsh