mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 00:05:18 +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...)
|
||||
|
@ -12,9 +12,7 @@ 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{}
|
||||
@ -27,7 +25,6 @@ var (
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// 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,
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ type ParamTestSuite struct {
|
||||
func (suite *ParamTestSuite) TestParamValidation() {
|
||||
type args struct {
|
||||
mms types.MoneyMarkets
|
||||
ltvCounter int
|
||||
}
|
||||
testCases := []struct {
|
||||
name string
|
||||
@ -28,7 +27,6 @@ func (suite *ParamTestSuite) TestParamValidation() {
|
||||
name: "default",
|
||||
args: args{
|
||||
mms: types.DefaultMoneyMarkets,
|
||||
ltvCounter: types.DefaultCheckLtvIndexCount,
|
||||
},
|
||||
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