mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-27 00:35:18 +00:00
Hard: LTV index refactor (#758)
* add set/delete/update ltv methods * refactor borrow logic * basic updates to keeper logic for compile * Add deposit index set/delete/update keeper methods * refactor deposit logic * refactor repay logic * update withdraw logic * introduce DeleteDepositBorrowAndLtvIndex * remove unused bool from AttemptKeeperLiquidation * remove comments (transitioned to asana cards) * catch multiple error types in liquidation loop
This commit is contained in:
parent
38306e5465
commit
bc110ce609
@ -124,7 +124,7 @@ func handleMsgRepay(ctx sdk.Context, k keeper.Keeper, msg types.MsgRepay) (*sdk.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgLiquidate(ctx sdk.Context, k keeper.Keeper, msg types.MsgLiquidate) (*sdk.Result, error) {
|
func handleMsgLiquidate(ctx sdk.Context, k keeper.Keeper, msg types.MsgLiquidate) (*sdk.Result, error) {
|
||||||
_, err := k.AttemptKeeperLiquidation(ctx, msg.Keeper, msg.Borrower)
|
err := k.AttemptKeeperLiquidation(ctx, msg.Keeper, msg.Borrower)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ func (k Keeper) Borrow(ctx sdk.Context, borrower sdk.AccAddress, coins sdk.Coins
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get current stored LTV based on stored borrows/deposits
|
// Get current stored LTV based on stored borrows/deposits
|
||||||
prevLtv, shouldRemoveIndex, err := k.GetStoreLTV(ctx, borrower)
|
prevLtv, err := k.GetStoreLTV(ctx, borrower)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -85,11 +85,20 @@ func (k Keeper) Borrow(ctx sdk.Context, borrower sdk.AccAddress, coins sdk.Coins
|
|||||||
amount = coins
|
amount = coins
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the borrower's amount and borrow interest factors in the store
|
// Construct the user's new/updated borrow with amount and interest factors
|
||||||
borrow := types.NewBorrow(borrower, amount, borrowInterestFactors)
|
borrow := types.NewBorrow(borrower, amount, borrowInterestFactors)
|
||||||
k.SetBorrow(ctx, borrow)
|
|
||||||
|
|
||||||
k.UpdateItemInLtvIndex(ctx, prevLtv, shouldRemoveIndex, borrower)
|
// Calculate the new Loan-to-Value ratio of Deposit-to-Borrow
|
||||||
|
deposit, foundDeposit := k.GetDeposit(ctx, borrower)
|
||||||
|
if !foundDeposit {
|
||||||
|
return types.ErrDepositNotFound
|
||||||
|
}
|
||||||
|
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
|
// 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.
|
// it has already been included in the total borrowed coins by the BeginBlocker.
|
||||||
|
@ -24,7 +24,7 @@ func (k Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Coi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get current stored LTV based on stored borrows/deposits
|
// Get current stored LTV based on stored borrows/deposits
|
||||||
prevLtv, shouldRemoveIndex, err := k.GetStoreLTV(ctx, depositor)
|
prevLtv, err := k.GetStoreLTV(ctx, depositor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -87,12 +87,17 @@ func (k Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Coi
|
|||||||
} else {
|
} else {
|
||||||
amount = coins
|
amount = coins
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the depositer's amount and supply interest factors in the store
|
// Update the depositer's amount and supply interest factors in the store
|
||||||
deposit := types.NewDeposit(depositor, amount, supplyInterestFactors)
|
deposit := types.NewDeposit(depositor, amount, supplyInterestFactors)
|
||||||
k.SetDeposit(ctx, deposit)
|
|
||||||
|
|
||||||
k.UpdateItemInLtvIndex(ctx, prevLtv, shouldRemoveIndex, depositor)
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
k.UpdateDepositAndLtvIndex(ctx, deposit, newLtv, prevLtv)
|
||||||
|
|
||||||
// Update total supplied amount by newly supplied coins. Don't add user's pending interest as
|
// Update total supplied amount by newly supplied coins. Don't add user's pending interest as
|
||||||
// it has already been included in the total supplied coins by the BeginBlocker.
|
// it has already been included in the total supplied coins by the BeginBlocker.
|
||||||
|
@ -22,9 +22,9 @@ func (k Keeper) AttemptIndexLiquidations(ctx sdk.Context) error {
|
|||||||
borrowers := k.GetLtvIndexSlice(ctx, params.CheckLtvIndexCount)
|
borrowers := k.GetLtvIndexSlice(ctx, params.CheckLtvIndexCount)
|
||||||
|
|
||||||
for _, borrower := range borrowers {
|
for _, borrower := range borrowers {
|
||||||
_, err := k.AttemptKeeperLiquidation(ctx, sdk.AccAddress(types.LiquidatorAccount), borrower)
|
err := k.AttemptKeeperLiquidation(ctx, sdk.AccAddress(types.LiquidatorAccount), borrower)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, types.ErrBorrowNotLiquidatable) {
|
if !errors.Is(err, types.ErrBorrowNotLiquidatable) && !errors.Is(err, types.ErrBorrowNotFound) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,34 +33,30 @@ func (k Keeper) AttemptIndexLiquidations(ctx sdk.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AttemptKeeperLiquidation enables a keeper to liquidate an individual borrower's position
|
// AttemptKeeperLiquidation enables a keeper to liquidate an individual borrower's position
|
||||||
func (k Keeper) AttemptKeeperLiquidation(ctx sdk.Context, keeper sdk.AccAddress, borrower sdk.AccAddress) (bool, error) {
|
func (k Keeper) AttemptKeeperLiquidation(ctx sdk.Context, keeper sdk.AccAddress, borrower sdk.AccAddress) error {
|
||||||
prevLtv, shouldInsertIndex, err := k.GetStoreLTV(ctx, borrower)
|
prevLtv, err := k.GetStoreLTV(ctx, borrower)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
k.SyncBorrowInterest(ctx, borrower)
|
k.SyncBorrowInterest(ctx, borrower)
|
||||||
|
|
||||||
k.UpdateItemInLtvIndex(ctx, prevLtv, shouldInsertIndex, borrower)
|
|
||||||
|
|
||||||
// Fetch deposits and parse coin denoms
|
|
||||||
deposit, found := k.GetDeposit(ctx, borrower)
|
deposit, found := k.GetDeposit(ctx, borrower)
|
||||||
if !found {
|
if !found {
|
||||||
return false, sdkerrors.Wrapf(types.ErrDepositsNotFound, "no deposits found for %s", borrower)
|
return types.ErrDepositNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch borrow balances and parse coin denoms
|
|
||||||
borrow, found := k.GetBorrow(ctx, borrower)
|
borrow, found := k.GetBorrow(ctx, borrower)
|
||||||
if !found {
|
if !found {
|
||||||
return false, types.ErrBorrowNotFound
|
return types.ErrBorrowNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
isWithinRange, err := k.IsWithinValidLtvRange(ctx, deposit, borrow)
|
isWithinRange, err := k.IsWithinValidLtvRange(ctx, deposit, borrow)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return err
|
||||||
}
|
}
|
||||||
if isWithinRange {
|
if isWithinRange {
|
||||||
return false, sdkerrors.Wrapf(types.ErrBorrowNotLiquidatable, "position is within valid LTV range")
|
return sdkerrors.Wrapf(types.ErrBorrowNotLiquidatable, "position is within valid LTV range")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sending coins to auction module with keeper address getting % of the profits
|
// Sending coins to auction module with keeper address getting % of the profits
|
||||||
@ -68,19 +64,11 @@ func (k Keeper) AttemptKeeperLiquidation(ctx sdk.Context, keeper sdk.AccAddress,
|
|||||||
depositDenoms := getDenoms(deposit.Amount)
|
depositDenoms := getDenoms(deposit.Amount)
|
||||||
err = k.SeizeDeposits(ctx, keeper, deposit, borrow, depositDenoms, borrowDenoms)
|
err = k.SeizeDeposits(ctx, keeper, deposit, borrow, depositDenoms, borrowDenoms)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
currLtv, _, err := k.GetStoreLTV(ctx, borrower)
|
k.DeleteDepositBorrowAndLtvIndex(ctx, deposit, borrow, prevLtv)
|
||||||
if err != nil {
|
return nil
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
k.RemoveFromLtvIndex(ctx, currLtv, borrower)
|
|
||||||
|
|
||||||
k.DeleteBorrow(ctx, borrow)
|
|
||||||
k.DeleteDeposit(ctx, deposit)
|
|
||||||
|
|
||||||
return true, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SeizeDeposits seizes a list of deposits and sends them to auction
|
// SeizeDeposits seizes a list of deposits and sends them to auction
|
||||||
@ -276,36 +264,40 @@ func (k Keeper) IsWithinValidLtvRange(ctx sdk.Context, deposit types.Deposit, bo
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateItemInLtvIndex updates the key a borrower's address is stored under in the LTV index
|
// UpdateBorrowAndLtvIndex updates a borrow and its LTV index value in the store
|
||||||
func (k Keeper) UpdateItemInLtvIndex(ctx sdk.Context, prevLtv sdk.Dec,
|
func (k Keeper) UpdateBorrowAndLtvIndex(ctx sdk.Context, borrow types.Borrow, newLtv, oldLtv sdk.Dec) {
|
||||||
shouldRemoveIndex bool, borrower sdk.AccAddress) error {
|
k.RemoveFromLtvIndex(ctx, oldLtv, borrow.Borrower)
|
||||||
currLtv, shouldInsertIndex, err := k.GetStoreLTV(ctx, borrower)
|
k.SetBorrow(ctx, borrow)
|
||||||
if err != nil {
|
k.InsertIntoLtvIndex(ctx, newLtv, borrow.Borrower)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if shouldRemoveIndex {
|
// UpdateDepositAndLtvIndex updates a deposit and its LTV index value in the store
|
||||||
k.RemoveFromLtvIndex(ctx, prevLtv, borrower)
|
func (k Keeper) UpdateDepositAndLtvIndex(ctx sdk.Context, deposit types.Deposit, newLtv, oldLtv sdk.Dec) {
|
||||||
|
k.RemoveFromLtvIndex(ctx, oldLtv, deposit.Depositor)
|
||||||
|
k.SetDeposit(ctx, deposit)
|
||||||
|
k.InsertIntoLtvIndex(ctx, newLtv, deposit.Depositor)
|
||||||
}
|
}
|
||||||
if shouldInsertIndex {
|
|
||||||
k.InsertIntoLtvIndex(ctx, currLtv, borrower)
|
// DeleteDepositBorrowAndLtvIndex deletes deposit, borrow, and ltv index
|
||||||
}
|
func (k Keeper) DeleteDepositBorrowAndLtvIndex(ctx sdk.Context, deposit types.Deposit, borrow types.Borrow, oldLtv sdk.Dec) {
|
||||||
return nil
|
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
|
// GetStoreLTV calculates the user's current LTV based on their deposits/borrows in the store
|
||||||
// and does not include any outsanding interest.
|
// and does not include any outsanding interest.
|
||||||
func (k Keeper) GetStoreLTV(ctx sdk.Context, addr sdk.AccAddress) (sdk.Dec, bool, error) {
|
func (k Keeper) GetStoreLTV(ctx sdk.Context, addr sdk.AccAddress) (sdk.Dec, error) {
|
||||||
// Fetch deposits and parse coin denoms
|
// Fetch deposits and parse coin denoms
|
||||||
deposit, found := k.GetDeposit(ctx, addr)
|
deposit, found := k.GetDeposit(ctx, addr)
|
||||||
if !found {
|
if !found {
|
||||||
return sdk.ZeroDec(), false, nil
|
return sdk.ZeroDec(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch borrow balances and parse coin denoms
|
// Fetch borrow balances and parse coin denoms
|
||||||
borrow, found := k.GetBorrow(ctx, addr)
|
borrow, found := k.GetBorrow(ctx, addr)
|
||||||
if !found {
|
if !found {
|
||||||
return sdk.ZeroDec(), false, nil
|
return sdk.ZeroDec(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return k.CalculateLtv(ctx, deposit, borrow)
|
return k.CalculateLtv(ctx, deposit, borrow)
|
||||||
@ -313,11 +305,11 @@ func (k Keeper) GetStoreLTV(ctx sdk.Context, addr sdk.AccAddress) (sdk.Dec, bool
|
|||||||
|
|
||||||
// CalculateLtv calculates the potential LTV given a user's deposits and borrows.
|
// CalculateLtv calculates the potential LTV given a user's deposits and borrows.
|
||||||
// The boolean returned indicates if the LTV should be added to the store's LTV index.
|
// The boolean returned indicates if the LTV should be added to the store's LTV index.
|
||||||
func (k Keeper) CalculateLtv(ctx sdk.Context, deposit types.Deposit, borrow types.Borrow) (sdk.Dec, bool, error) {
|
func (k Keeper) CalculateLtv(ctx sdk.Context, deposit types.Deposit, borrow types.Borrow) (sdk.Dec, error) {
|
||||||
// Load required liquidation data for every deposit/borrow denom
|
// Load required liquidation data for every deposit/borrow denom
|
||||||
liqMap, err := k.LoadLiquidationData(ctx, deposit, borrow)
|
liqMap, err := k.LoadLiquidationData(ctx, deposit, borrow)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sdk.ZeroDec(), false, nil
|
return sdk.ZeroDec(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build valuation map to hold deposit coin USD valuations
|
// Build valuation map to hold deposit coin USD valuations
|
||||||
@ -339,11 +331,11 @@ func (k Keeper) CalculateLtv(ctx sdk.Context, deposit types.Deposit, borrow type
|
|||||||
// User doesn't have any deposits, catch divide by 0 error
|
// User doesn't have any deposits, catch divide by 0 error
|
||||||
sumDeposits := depositCoinValues.Sum()
|
sumDeposits := depositCoinValues.Sum()
|
||||||
if sumDeposits.Equal(sdk.ZeroDec()) {
|
if sumDeposits.Equal(sdk.ZeroDec()) {
|
||||||
return sdk.ZeroDec(), false, nil
|
return sdk.ZeroDec(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loan-to-Value ratio
|
// Loan-to-Value ratio
|
||||||
return borrowCoinValues.Sum().Quo(sumDeposits), true, nil
|
return borrowCoinValues.Sum().Quo(sumDeposits), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadLiquidationData returns liquidation data, deposit, borrow
|
// LoadLiquidationData returns liquidation data, deposit, borrow
|
||||||
|
@ -1358,9 +1358,8 @@ func (suite *KeeperTestSuite) TestKeeperLiquidation() {
|
|||||||
suite.Require().True(foundDepositBefore)
|
suite.Require().True(foundDepositBefore)
|
||||||
|
|
||||||
// Attempt to liquidate
|
// Attempt to liquidate
|
||||||
liquidated, err := suite.keeper.AttemptKeeperLiquidation(liqCtx, tc.args.keeper, tc.args.borrower)
|
err = suite.keeper.AttemptKeeperLiquidation(liqCtx, tc.args.keeper, tc.args.borrower)
|
||||||
if tc.errArgs.expectPass {
|
if tc.errArgs.expectPass {
|
||||||
suite.Require().True(liquidated)
|
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
// Check borrow does not exist after liquidation
|
// Check borrow does not exist after liquidation
|
||||||
@ -1383,7 +1382,6 @@ func (suite *KeeperTestSuite) TestKeeperLiquidation() {
|
|||||||
suite.Require().True(len(auctions) > 0)
|
suite.Require().True(len(auctions) > 0)
|
||||||
suite.Require().Equal(tc.args.expectedAuctions, auctions)
|
suite.Require().Equal(tc.args.expectedAuctions, auctions)
|
||||||
} else {
|
} else {
|
||||||
suite.Require().False(liquidated)
|
|
||||||
suite.Require().Error(err)
|
suite.Require().Error(err)
|
||||||
suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains))
|
suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains))
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
// Repay borrowed funds
|
// Repay borrowed funds
|
||||||
func (k Keeper) Repay(ctx sdk.Context, sender sdk.AccAddress, coins sdk.Coins) error {
|
func (k Keeper) Repay(ctx sdk.Context, sender sdk.AccAddress, coins sdk.Coins) error {
|
||||||
// Get current stored LTV based on stored borrows/deposits
|
// Get current stored LTV based on stored borrows/deposits
|
||||||
prevLtv, shouldRemoveIndex, err := k.GetStoreLTV(ctx, sender)
|
prevLtv, err := k.GetStoreLTV(ctx, sender)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -43,9 +43,18 @@ func (k Keeper) Repay(ctx sdk.Context, sender sdk.AccAddress, coins sdk.Coins) e
|
|||||||
|
|
||||||
// Update user's borrow in store
|
// Update user's borrow in store
|
||||||
borrow.Amount = borrow.Amount.Sub(payment)
|
borrow.Amount = borrow.Amount.Sub(payment)
|
||||||
k.SetBorrow(ctx, borrow)
|
|
||||||
|
|
||||||
k.UpdateItemInLtvIndex(ctx, prevLtv, shouldRemoveIndex, sender)
|
// Calculate the new Loan-to-Value ratio of Deposit-to-Borrow
|
||||||
|
deposit, foundDeposit := k.GetDeposit(ctx, sender)
|
||||||
|
if !foundDeposit {
|
||||||
|
return types.ErrDepositNotFound
|
||||||
|
}
|
||||||
|
newLtv, err := k.CalculateLtv(ctx, deposit, borrow)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
k.UpdateBorrowAndLtvIndex(ctx, borrow, newLtv, prevLtv)
|
||||||
|
|
||||||
// Update total borrowed amount
|
// Update total borrowed amount
|
||||||
k.DecrementBorrowedCoins(ctx, payment)
|
k.DecrementBorrowedCoins(ctx, payment)
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
// Withdraw returns some or all of a deposit back to original depositor
|
// 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 {
|
func (k Keeper) Withdraw(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Coins) error {
|
||||||
// Get current stored LTV based on stored borrows/deposits
|
// Get current stored LTV based on stored borrows/deposits
|
||||||
prevLtv, shouldRemoveIndex, err := k.GetStoreLTV(ctx, depositor)
|
prevLtv, err := k.GetStoreLTV(ctx, depositor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -27,18 +27,17 @@ func (k Keeper) Withdraw(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Co
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
proposedDeposit := types.NewDeposit(deposit.Depositor, deposit.Amount.Sub(amount), types.SupplyInterestFactors{})
|
|
||||||
|
|
||||||
borrow, found := k.GetBorrow(ctx, depositor)
|
borrow, found := k.GetBorrow(ctx, depositor)
|
||||||
if !found {
|
if !found {
|
||||||
borrow = types.Borrow{}
|
borrow = types.Borrow{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proposedDeposit := types.NewDeposit(deposit.Depositor, deposit.Amount.Sub(amount), types.SupplyInterestFactors{})
|
||||||
valid, err := k.IsWithinValidLtvRange(ctx, proposedDeposit, borrow)
|
valid, err := k.IsWithinValidLtvRange(ctx, proposedDeposit, borrow)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !valid {
|
if !valid {
|
||||||
return sdkerrors.Wrapf(types.ErrInvalidWithdrawAmount, "proposed withdraw outside loan-to-value range")
|
return sdkerrors.Wrapf(types.ErrInvalidWithdrawAmount, "proposed withdraw outside loan-to-value range")
|
||||||
}
|
}
|
||||||
@ -60,9 +59,12 @@ func (k Keeper) Withdraw(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
deposit.Amount = deposit.Amount.Sub(amount)
|
deposit.Amount = deposit.Amount.Sub(amount)
|
||||||
k.SetDeposit(ctx, deposit)
|
|
||||||
|
|
||||||
k.UpdateItemInLtvIndex(ctx, prevLtv, shouldRemoveIndex, depositor)
|
newLtv, err := k.CalculateLtv(ctx, deposit, borrow)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
k.UpdateDepositAndLtvIndex(ctx, deposit, newLtv, prevLtv)
|
||||||
|
|
||||||
// Update total supplied amount
|
// Update total supplied amount
|
||||||
k.DecrementBorrowedCoins(ctx, amount)
|
k.DecrementBorrowedCoins(ctx, amount)
|
||||||
|
Loading…
Reference in New Issue
Block a user