mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-11-10 10:05:18 +00:00
Hard Audit: fix duplicate supply/borrow index factors (#794)
* types: set/get interest factor * delete 0 balance index factors from deposit * types: set/get borrow interest factor * delete 0 balance index factors from borrow * delete index factor directly
This commit is contained in:
parent
3d6e730368
commit
0343edf0d0
@ -60,26 +60,15 @@ func (k Keeper) Borrow(ctx sdk.Context, borrower sdk.AccAddress, coins sdk.Coins
|
||||
}
|
||||
}
|
||||
|
||||
// The first time a user borrows a denom we add it the user's borrow interest factor index
|
||||
var borrowInterestFactors types.BorrowInterestFactors
|
||||
interestFactors := types.BorrowInterestFactors{}
|
||||
currBorrow, foundBorrow := k.GetBorrow(ctx, borrower)
|
||||
// On user's first borrow, build borrow index list containing denoms and current global borrow index value
|
||||
if foundBorrow {
|
||||
// If the coin denom to be borrowed is not in the user's existing borrow, we add it borrow index
|
||||
for _, coin := range coins {
|
||||
if !sdk.NewCoins(coin).DenomsSubsetOf(currBorrow.Amount) {
|
||||
borrowInterestFactorValue, _ := k.GetBorrowInterestFactor(ctx, coin.Denom)
|
||||
borrowInterestFactor := types.NewBorrowInterestFactor(coin.Denom, borrowInterestFactorValue)
|
||||
borrowInterestFactors = append(borrowInterestFactors, borrowInterestFactor)
|
||||
}
|
||||
}
|
||||
// Concatenate new borrow interest factors to existing borrow interest factors
|
||||
borrowInterestFactors = append(borrowInterestFactors, currBorrow.Index...)
|
||||
} else {
|
||||
for _, coin := range coins {
|
||||
borrowInterestFactorValue, _ := k.GetBorrowInterestFactor(ctx, coin.Denom)
|
||||
borrowInterestFactor := types.NewBorrowInterestFactor(coin.Denom, borrowInterestFactorValue)
|
||||
borrowInterestFactors = append(borrowInterestFactors, borrowInterestFactor)
|
||||
interestFactors = currBorrow.Index
|
||||
}
|
||||
for _, coin := range coins {
|
||||
interestFactorValue, foundValue := k.GetBorrowInterestFactor(ctx, coin.Denom)
|
||||
if foundValue {
|
||||
interestFactors = interestFactors.SetInterestFactor(coin.Denom, interestFactorValue)
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,7 +80,7 @@ func (k Keeper) Borrow(ctx sdk.Context, borrower sdk.AccAddress, coins sdk.Coins
|
||||
amount = coins
|
||||
}
|
||||
// Construct the user's new/updated borrow with amount and interest factors
|
||||
borrow := types.NewBorrow(borrower, amount, borrowInterestFactors)
|
||||
borrow := types.NewBorrow(borrower, amount, interestFactors)
|
||||
|
||||
// Calculate the new Loan-to-Value ratio of Deposit-to-Borrow
|
||||
deposit, foundDeposit := k.GetDeposit(ctx, borrower)
|
||||
|
@ -63,26 +63,15 @@ func (k Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Coi
|
||||
return err
|
||||
}
|
||||
|
||||
// The first time a user deposits a denom we add it the user's supply interest factor index
|
||||
var supplyInterestFactors types.SupplyInterestFactors
|
||||
interestFactors := types.SupplyInterestFactors{}
|
||||
currDeposit, foundDeposit := k.GetDeposit(ctx, depositor)
|
||||
// On user's first deposit, build deposit index list containing denoms and current global deposit index value
|
||||
if foundDeposit {
|
||||
// If the coin denom to be deposited is not in the user's existing deposit, we add it deposit index
|
||||
for _, coin := range coins {
|
||||
if !sdk.NewCoins(coin).DenomsSubsetOf(currDeposit.Amount) {
|
||||
supplyInterestFactorValue, _ := k.GetSupplyInterestFactor(ctx, coin.Denom)
|
||||
supplyInterestFactor := types.NewSupplyInterestFactor(coin.Denom, supplyInterestFactorValue)
|
||||
supplyInterestFactors = append(supplyInterestFactors, supplyInterestFactor)
|
||||
}
|
||||
}
|
||||
// Concatenate new deposit interest factors to existing deposit interest factors
|
||||
supplyInterestFactors = append(supplyInterestFactors, currDeposit.Index...)
|
||||
} else {
|
||||
for _, coin := range coins {
|
||||
supplyInterestFactorValue, _ := k.GetSupplyInterestFactor(ctx, coin.Denom)
|
||||
supplyInterestFactor := types.NewSupplyInterestFactor(coin.Denom, supplyInterestFactorValue)
|
||||
supplyInterestFactors = append(supplyInterestFactors, supplyInterestFactor)
|
||||
interestFactors = currDeposit.Index
|
||||
}
|
||||
for _, coin := range coins {
|
||||
interestFactorValue, foundValue := k.GetSupplyInterestFactor(ctx, coin.Denom)
|
||||
if foundValue {
|
||||
interestFactors = interestFactors.SetInterestFactor(coin.Denom, interestFactorValue)
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,7 +83,7 @@ func (k Keeper) Deposit(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Coi
|
||||
amount = coins
|
||||
}
|
||||
// Update the depositer's amount and supply interest factors in the store
|
||||
deposit := types.NewDeposit(depositor, amount, supplyInterestFactors)
|
||||
deposit := types.NewDeposit(depositor, amount, interestFactors)
|
||||
|
||||
// Calculate the new Loan-to-Value ratio of Deposit-to-Borrow
|
||||
borrow, _ := k.GetBorrow(ctx, depositor)
|
||||
|
@ -43,6 +43,17 @@ func (k Keeper) Repay(ctx sdk.Context, sender sdk.AccAddress, coins sdk.Coins) e
|
||||
return err
|
||||
}
|
||||
|
||||
// If any coin denoms have been completely repaid reset the denom's borrow index factor
|
||||
for _, coin := range payment {
|
||||
if coin.Amount.Equal(borrow.Amount.AmountOf(coin.Denom)) {
|
||||
borrowIndex, removed := borrow.Index.RemoveInterestFactor(coin.Denom)
|
||||
if !removed {
|
||||
return sdkerrors.Wrapf(types.ErrInvalidIndexFactorDenom, "%s", coin.Denom)
|
||||
}
|
||||
borrow.Index = borrowIndex
|
||||
}
|
||||
}
|
||||
|
||||
// Update user's borrow in store
|
||||
borrow.Amount = borrow.Amount.Sub(payment)
|
||||
|
||||
|
@ -49,6 +49,17 @@ func (k Keeper) Withdraw(ctx sdk.Context, depositor sdk.AccAddress, coins sdk.Co
|
||||
return err
|
||||
}
|
||||
|
||||
// If any coin denoms have been completely withdrawn reset the denom's supply index factor
|
||||
for _, coin := range deposit.Amount {
|
||||
if !sdk.NewCoins(coin).DenomsSubsetOf(proposedDeposit.Amount) {
|
||||
depositIndex, removed := deposit.Index.RemoveInterestFactor(coin.Denom)
|
||||
if !removed {
|
||||
return sdkerrors.Wrapf(types.ErrInvalidIndexFactorDenom, "%s", coin.Denom)
|
||||
}
|
||||
deposit.Index = depositIndex
|
||||
}
|
||||
}
|
||||
|
||||
deposit.Amount = deposit.Amount.Sub(amount)
|
||||
newLtv, err := k.CalculateLtv(ctx, deposit, borrow)
|
||||
if err != nil {
|
||||
|
@ -100,6 +100,38 @@ func (bif BorrowInterestFactor) String() string {
|
||||
// BorrowInterestFactors is a slice of BorrowInterestFactor, because Amino won't marshal maps
|
||||
type BorrowInterestFactors []BorrowInterestFactor
|
||||
|
||||
// GetInterestFactor returns a denom's interest factor value
|
||||
func (bifs BorrowInterestFactors) GetInterestFactor(denom string) (sdk.Dec, bool) {
|
||||
for _, bif := range bifs {
|
||||
if bif.Denom == denom {
|
||||
return bif.Value, true
|
||||
}
|
||||
}
|
||||
return sdk.ZeroDec(), false
|
||||
}
|
||||
|
||||
// SetInterestFactor sets a denom's interest factor value
|
||||
func (bifs BorrowInterestFactors) SetInterestFactor(denom string, factor sdk.Dec) BorrowInterestFactors {
|
||||
for i, bif := range bifs {
|
||||
if bif.Denom == denom {
|
||||
bif.Value = factor
|
||||
bifs[i] = bif
|
||||
return bifs
|
||||
}
|
||||
}
|
||||
return append(bifs, NewBorrowInterestFactor(denom, factor))
|
||||
}
|
||||
|
||||
// RemoveInterestFactor removes a denom's interest factor value
|
||||
func (bifs BorrowInterestFactors) RemoveInterestFactor(denom string) (BorrowInterestFactors, bool) {
|
||||
for i, bif := range bifs {
|
||||
if bif.Denom == denom {
|
||||
return append(bifs[:i], bifs[i+1:]...), true
|
||||
}
|
||||
}
|
||||
return bifs, false
|
||||
}
|
||||
|
||||
// Validate validates BorrowInterestFactors
|
||||
func (bifs BorrowInterestFactors) Validate() error {
|
||||
for _, bif := range bifs {
|
||||
|
@ -100,6 +100,38 @@ func (sif SupplyInterestFactor) String() string {
|
||||
// SupplyInterestFactors is a slice of SupplyInterestFactor, because Amino won't marshal maps
|
||||
type SupplyInterestFactors []SupplyInterestFactor
|
||||
|
||||
// GetInterestFactor returns a denom's interest factor value
|
||||
func (sifs SupplyInterestFactors) GetInterestFactor(denom string) (sdk.Dec, bool) {
|
||||
for _, sif := range sifs {
|
||||
if sif.Denom == denom {
|
||||
return sif.Value, true
|
||||
}
|
||||
}
|
||||
return sdk.ZeroDec(), false
|
||||
}
|
||||
|
||||
// SetInterestFactor sets a denom's interest factor value
|
||||
func (sifs SupplyInterestFactors) SetInterestFactor(denom string, factor sdk.Dec) SupplyInterestFactors {
|
||||
for i, sif := range sifs {
|
||||
if sif.Denom == denom {
|
||||
sif.Value = factor
|
||||
sifs[i] = sif
|
||||
return sifs
|
||||
}
|
||||
}
|
||||
return append(sifs, NewSupplyInterestFactor(denom, factor))
|
||||
}
|
||||
|
||||
// RemoveInterestFactor removes a denom's interest factor value
|
||||
func (sifs SupplyInterestFactors) RemoveInterestFactor(denom string) (SupplyInterestFactors, bool) {
|
||||
for i, sif := range sifs {
|
||||
if sif.Denom == denom {
|
||||
return append(sifs[:i], sifs[i+1:]...), true
|
||||
}
|
||||
}
|
||||
return sifs, false
|
||||
}
|
||||
|
||||
// Validate validates SupplyInterestFactors
|
||||
func (sifs SupplyInterestFactors) Validate() error {
|
||||
for _, sif := range sifs {
|
||||
|
@ -61,4 +61,6 @@ var (
|
||||
ErrInvalidWithdrawDenom = sdkerrors.Register(ModuleName, 26, "no coins of this type deposited")
|
||||
// ErrInvalidRepaymentDenom error for when user attempts to repay a non-borrowed coin type
|
||||
ErrInvalidRepaymentDenom = sdkerrors.Register(ModuleName, 27, "no coins of this type borrowed")
|
||||
// ErrInvalidIndexFactorDenom error for when index factor denom cannot be found
|
||||
ErrInvalidIndexFactorDenom = sdkerrors.Register(ModuleName, 28, "no index factor found for denom")
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user