From 920ddd2e79d38097e1fb2d350c09301222e86304 Mon Sep 17 00:00:00 2001 From: harsh-98 Date: Wed, 25 Oct 2023 21:57:45 +0700 Subject: [PATCH] refactor: calculations --- calc/account_fields.go | 39 ++++++++++++++++++++++++++++--------- calc/account_fields_test.go | 12 ++++++------ calc/account_fields_v3.go | 17 ++++++++-------- calc/close_amount.go | 24 +++++++++++------------ calc/close_amount_test.go | 7 +++++-- utils/bigint.go | 4 ++++ 6 files changed, 65 insertions(+), 38 deletions(-) diff --git a/calc/account_fields.go b/calc/account_fields.go index 496461161..ac9ab13ff 100644 --- a/calc/account_fields.go +++ b/calc/account_fields.go @@ -14,6 +14,25 @@ type TokenDetailsForCalcI interface { GetLiqThreshold(ts uint64, cm, token string) *big.Int } +type DebtDetails struct { + total *big.Int + interest *big.Int + borrowedAmount *big.Int +} + +func (d DebtDetails) Total() *big.Int { + return d.total +} +func (d DebtDetails) Interest() *big.Int { + return d.interest +} +func (d DebtDetails) BorrowedAmount() *big.Int { + return d.borrowedAmount +} +func (d DebtDetails) BorrowedAmountWithInterest() *big.Int { + return new(big.Int).Add(d.borrowedAmount, d.interest) +} + type AccountForCalcI interface { GetCM() string GetBalances() core.DBBalanceFormat @@ -30,7 +49,7 @@ type Calculator struct { func (c Calculator) CalcAccountFields(ts uint64, blockNum int64, poolDetails PoolForCalcI, account AccountForCalcI, feeInterest uint16, -) (calHF, calBorrowWithInterestAndFees, calTotalValue, calThresholdValue, calBorrowWithInterest *big.Int) { +) (calHF, calTotalValue, calThresholdValue *big.Int, debtDetails *DebtDetails) { version := account.GetVersion() if version.Eq(300) { return c.CalcAccountFieldsv3(ts, blockNum, poolDetails, account, feeInterest) @@ -53,9 +72,14 @@ func (c Calculator) CalcAccountFields(ts uint64, blockNum int64, } } - calBorrowWithInterest = new(big.Int).Quo( + calBorrowWithInterest := new(big.Int).Quo( new(big.Int).Mul(poolDetails.GetCumIndexNow(), account.GetBorrowedAmount()), account.GetCumulativeIndex()) + debtDetails = &DebtDetails{ + borrowedAmount: account.GetBorrowedAmount(), + total: calBorrowWithInterest, + interest: new(big.Int).Sub(calBorrowWithInterest, account.GetBorrowedAmount()), + } // calTotalValue = c.convertFromUSD(calTotalValueInUSD, underlyingToken, version, blockNum) calThresholdValue = utils.GetInt64( @@ -69,18 +93,15 @@ func (c Calculator) CalcAccountFields(ts uint64, blockNum int64, if version.Eq(1) { calHF = new(big.Int).Quo( utils.GetInt64(calThresholdValue, -4), - calBorrowWithInterest, + debtDetails.Total(), ) - // set calBorrowWithInterestAndFees - calBorrowWithInterestAndFees = calBorrowWithInterest } else if version.Eq(2) { //https://github.com/Gearbox-protocol/core-v2/blob/da38b329f0c59e4a3dcedc993192bbc849d981f5/contracts/credit/CreditFacade.sol#L1206 - interest := new(big.Int).Sub(calBorrowWithInterest, account.GetBorrowedAmount()) - fees := utils.PercentMul(interest, big.NewInt(int64(feeInterest))) - calBorrowWithInterestAndFees = new(big.Int).Add(calBorrowWithInterest, fees) + fees := utils.PercentMul(debtDetails.Interest(), big.NewInt(int64(feeInterest))) + debtDetails.total = new(big.Int).Add(debtDetails.total, fees) calHF = new(big.Int).Quo( utils.GetInt64(calThresholdValue, -4), - calBorrowWithInterestAndFees, + debtDetails.Total(), ) } return diff --git a/calc/account_fields_test.go b/calc/account_fields_test.go index 9d2e1ad7a..028a5281e 100644 --- a/calc/account_fields_test.go +++ b/calc/account_fields_test.go @@ -100,7 +100,7 @@ func TestCalcFields(t *testing.T) { utils.ReadJsonAndSetInterface("../inputs/calc_account_fields.json", &input) // // - calHF, calDebt, calTotalValue, calThresholdValue, _ := Calculator{Store: input.store}.CalcAccountFields( + calHF, calTotalValue, calThresholdValue, calDebtDetails := Calculator{Store: input.store}.CalcAccountFields( 0, 0, input.PoolDetails, @@ -110,8 +110,8 @@ func TestCalcFields(t *testing.T) { if calHF.Cmp(utils.StringToInt("13225")) != 0 { t.Fatalf("calculated HF(%d) is wrong", calHF) } - if calDebt.Cmp(utils.StringToInt("8319356395")) != 0 { - t.Fatalf("calculated borrowedamount + interest(%d) is wrong", calDebt) + if calDebtDetails.Total().Cmp(utils.StringToInt("8319356395")) != 0 { + t.Fatalf("calculated borrowedamount + interest(%d) is wrong", calDebtDetails.Total()) } if calTotalValue.Cmp(utils.StringToInt("12944049438")) != 0 { t.Fatalf("calculated totalvalue(%d) is wrong", calTotalValue) @@ -129,7 +129,7 @@ func TestCalcFieldsWithFeeInterest(t *testing.T) { utils.ReadJsonAndSetInterface("../inputs/calc_account_fields_v2.json", &input) // // - calHF, calDebt, calTotalValue, calThresholdValue, _ := Calculator{Store: input.store}.CalcAccountFields( + calHF, calTotalValue, calThresholdValue, calDebtDetails := Calculator{Store: input.store}.CalcAccountFields( 0, 0, // @@ -141,8 +141,8 @@ func TestCalcFieldsWithFeeInterest(t *testing.T) { if calHF.Cmp(utils.StringToInt("2725195")) != 0 { t.Fatalf("calculated HF(%d) is wrong", calHF) } - if calDebt.Cmp(utils.StringToInt("5000008908519365762")) != 0 { - t.Fatalf("calculated borrowedamount + interest(%d) is wrong", calDebt) + if calDebtDetails.Total().Cmp(utils.StringToInt("5000008908519365762")) != 0 { + t.Fatalf("calculated borrowedamount + interest(%d) is wrong", calDebtDetails.Total()) } if calTotalValue.Cmp(utils.StringToInt("1651636475399519415042")) != 0 { t.Fatalf("calculated totalvalue(%d) is wrong", calTotalValue) diff --git a/calc/account_fields_v3.go b/calc/account_fields_v3.go index fe75481d5..f8151b7f3 100644 --- a/calc/account_fields_v3.go +++ b/calc/account_fields_v3.go @@ -29,9 +29,9 @@ func GetbaseInterest(poolCumIndexNow *big.Int, session AccountForCalcI) *big.Int // - whenever there is updateQuota, cumulative quota intereest and fees are stored in creditManager and cumulativeQuotaIndex for account is updated. // cumulative quota interest and quotafees increase on every updateQuota and decrase on decrease debt. -func (c Calculator) CalcAccountFieldsv3(ts uint64, blockNum int64, poolDetails PoolForCalcI, session AccountForCalcI, feeInterest uint16) (calHF, calBorrowWithInterestAndFees, calTotalValue, calThresholdValue, calBorrowWithInterest *big.Int) { +func (c Calculator) CalcAccountFieldsv3(ts uint64, blockNum int64, poolDetails PoolForCalcI, session AccountForCalcI, feeInterest uint16) (calHF, calTotalValue, calThresholdValue *big.Int, debtDetails *DebtDetails) { version := core.NewVersion(300) - accruedFees, accruedInterest, borrowedAmount := c.getDebt(ts, poolDetails, session, feeInterest) + debtDetails = c.getDebtDetails(ts, poolDetails, session, feeInterest) underlying := poolDetails.GetUnderlying() // quotaedTokens := poolQuotaDetails.GetPoolQuotaDetails(underlying) @@ -69,11 +69,8 @@ func (c Calculator) CalcAccountFieldsv3(ts uint64, blockNum int64, poolDetails P // calTotalValue = c.convertFromUSD(totalValueInUSD, underlying, version, blockNum) calThresholdValue = c.convertFromUSD(tvwValueInUSD, underlying, version, blockNum) - // calBorrowWithInterestAndFees := totalDebt - calBorrowWithInterest = new(big.Int).Add(borrowedAmount, accruedInterest) - calBorrowWithInterestAndFees = new(big.Int).Add(calBorrowWithInterest, accruedFees) - calHF = new(big.Int).Quo(utils.GetInt64(calThresholdValue, -4), calBorrowWithInterestAndFees) + calHF = new(big.Int).Quo(utils.GetInt64(calThresholdValue, -4), debtDetails.Total()) return } @@ -85,7 +82,7 @@ func minBigInt(a, b *big.Int) *big.Int { } } -func (c Calculator) getDebt(ts uint64, poolDetails PoolForCalcI, session AccountForCalcI, feeInterest uint16) (*big.Int, *big.Int, *big.Int) { +func (c Calculator) getDebtDetails(ts uint64, poolDetails PoolForCalcI, session AccountForCalcI, feeInterest uint16) *DebtDetails { borrowedAmount := session.GetBorrowedAmount() baseInterestSinceUpdate := GetbaseInterest(poolDetails.GetCumIndexNow(), session) @@ -105,7 +102,11 @@ func (c Calculator) getDebt(ts uint64, poolDetails PoolForCalcI, session Account accruedInterest := new(big.Int).Add(cumQuotaInterest, totalNewInterest) - return accruedFees, accruedInterest, borrowedAmount + return &DebtDetails{ + total: utils.BigIntAdd3(accruedFees, accruedInterest, borrowedAmount), + interest: accruedInterest, + borrowedAmount: borrowedAmount, + } } func calcExtraQuotaInterest(ts uint64, poolQuotas map[string]*schemas_v3.QuotaDetails, session AccountForCalcI) *big.Int { diff --git a/calc/close_amount.go b/calc/close_amount.go index 65c90d435..25c20db97 100644 --- a/calc/close_amount.go +++ b/calc/close_amount.go @@ -8,16 +8,16 @@ import ( "github.com/Gearbox-protocol/sdk-go/utils" ) -func CalCloseAmount(params *schemas.Parameters, version core.VersionType, totalValue *big.Int, closureStatus int, borrowedAmountWithInterest, borrowedAmount *big.Int) (amountToPool, remainingFunds, profit, loss *big.Int) { +func CalCloseAmount(params *schemas.Parameters, version core.VersionType, totalValue *big.Int, closureStatus int, debtDetails *DebtDetails) (amountToPool, remainingFunds, profit, loss *big.Int) { if version.Eq(1) { - return calCloseAmountV1(params, totalValue, schemas.IsStatusLiquidated(closureStatus), borrowedAmountWithInterest, borrowedAmount) - } else if version.Eq(2) { - amountToPool, remainingFunds, profit, loss = calCloseAmountV2(params, totalValue, closureStatus, borrowedAmountWithInterest, borrowedAmount) + return calCloseAmountV1(params, totalValue, schemas.IsStatusLiquidated(closureStatus), debtDetails) + } else if version.Eq(2) || version.Eq(300) { + amountToPool, remainingFunds, profit, loss = calCloseAmountV2(params, totalValue, closureStatus, debtDetails) } return } -func calCloseAmountV1(params *schemas.Parameters, totalValue *big.Int, isLiquidated bool, borrowedAmountWithInterest, borrowedAmount *big.Int) (amountToPool, remainingFunds, profit, loss *big.Int) { +func calCloseAmountV1(params *schemas.Parameters, totalValue *big.Int, isLiquidated bool, debtDetails *DebtDetails) (amountToPool, remainingFunds, profit, loss *big.Int) { loss = big.NewInt(0) profit = big.NewInt(0) remainingFunds = new(big.Int) @@ -27,6 +27,7 @@ func calCloseAmountV1(params *schemas.Parameters, totalValue *big.Int, isLiquida } else { totalFunds = totalValue } + borrowedAmountWithInterest := debtDetails.BorrowedAmountWithInterest() // borrow amt is greater than total funds if totalFunds.Cmp(borrowedAmountWithInterest) < 0 { amountToPool = new(big.Int).Sub(totalFunds, big.NewInt(1)) @@ -36,7 +37,7 @@ func calCloseAmountV1(params *schemas.Parameters, totalValue *big.Int, isLiquida amountToPool = utils.PercentMulByUInt16(totalFunds, params.FeeLiquidation) amountToPool = new(big.Int).Add(borrowedAmountWithInterest, amountToPool) } else { - interestAmt := new(big.Int).Sub(borrowedAmountWithInterest, borrowedAmount) + interestAmt := debtDetails.Interest() fee := utils.PercentMulByUInt16(interestAmt, params.FeeInterest) amountToPool = new(big.Int).Add(borrowedAmountWithInterest, fee) } @@ -53,16 +54,12 @@ func calCloseAmountV1(params *schemas.Parameters, totalValue *big.Int, isLiquida } // https://github.com/Gearbox-protocol/core-v2/blob/da38b329f0c59e4a3dcedc993192bbc849d981f5/contracts/credit/CreditManager.sol#L1238 -func calCloseAmountV2(params *schemas.Parameters, totalValue *big.Int, closureStatus int, borrowedAmountWithInterest, borrowedAmount *big.Int) (amountToPool, remainingFunds, profit, loss *big.Int) { +func calCloseAmountV2(params *schemas.Parameters, totalValue *big.Int, closureStatus int, debtDetails *DebtDetails) (amountToPool, remainingFunds, profit, loss *big.Int) { loss = big.NewInt(0) profit = big.NewInt(0) remainingFunds = new(big.Int) - amountToPool = utils.PercentMulByUInt16( - new(big.Int).Sub(borrowedAmountWithInterest, borrowedAmount), - params.FeeInterest, - ) - amountToPool = new(big.Int).Add(amountToPool, borrowedAmountWithInterest) + amountToPool = debtDetails.Total() if schemas.IsStatusLiquidated(closureStatus) { var totalFunds *big.Int @@ -89,13 +86,14 @@ func calCloseAmountV2(params *schemas.Parameters, totalValue *big.Int, closureSt amountToPool = totalFunds } + borrowedAmountWithInterest := debtDetails.BorrowedAmountWithInterest() if totalFunds.Cmp(borrowedAmountWithInterest) >= 0 { profit = new(big.Int).Sub(amountToPool, borrowedAmountWithInterest) } else { loss = new(big.Int).Sub(borrowedAmountWithInterest, amountToPool) } } else { - profit = new(big.Int).Sub(amountToPool, borrowedAmountWithInterest) + profit = new(big.Int).Sub(amountToPool, debtDetails.BorrowedAmountWithInterest()) // reminaingFunds is totalValue - debt remainingFunds = new(big.Int).Sub(totalValue, amountToPool) } diff --git a/calc/close_amount_test.go b/calc/close_amount_test.go index 60727b213..4f92406d4 100644 --- a/calc/close_amount_test.go +++ b/calc/close_amount_test.go @@ -18,8 +18,11 @@ func TestCalcCloseAmount(t *testing.T) { core.NewVersion(2), utils.StringToInt("2003445408514560318103"), schemas.Liquidated, - utils.StringToInt("2000036753743938235"), - utils.StringToInt("1999999990917566710"), + &DebtDetails{ + total: utils.StringToInt("2000037121372201950"), + interest: utils.StringToInt("36762826371525"), + borrowedAmount: utils.StringToInt("1999999990917566710"), + }, ) expectedAmounToPool := utils.StringToInt("42068945291663408312") expectedRemainingFunds := utils.StringToInt("1861204192797168893884") diff --git a/utils/bigint.go b/utils/bigint.go index 7940719d5..0e17a62c1 100644 --- a/utils/bigint.go +++ b/utils/bigint.go @@ -172,3 +172,7 @@ func DiffMoreThanFraction(oldValue, newValue *big.Int, diff *big.Float) bool { func BytesToUInt16(data []byte) uint16 { return uint16(new(big.Int).SetBytes(data).Int64()) } + +func BigIntAdd3(a, b, c *big.Int) *big.Int { + return new(big.Int).Add(a, new(big.Int).Add(b, c)) +}