Skip to content

Commit

Permalink
Merge pull request #80 from Gearbox-protocol/ReserveOracles
Browse files Browse the repository at this point in the history
Reserve oracles
  • Loading branch information
harsh-98 authored Feb 17, 2024
2 parents 76b92df + 2edccb3 commit 1e7b0bf
Show file tree
Hide file tree
Showing 57 changed files with 861 additions and 541 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,8 @@ modifying, or distributing this software product.

### Important information for contributors
As a contributor to the Gearbox Protocol GitHub repository, your pull requests indicate acceptance of our Gearbox Contribution Agreement. This agreement outlines that you assign the Intellectual Property Rights of your contributions to the Gearbox Foundation. This helps safeguard the Gearbox protocol and ensure the accumulation of its intellectual property. Contributions become part of the repository and may be used for various purposes, including commercial. As recognition for your expertise and work, you receive the opportunity to participate in the protocol's development and the potential to see your work integrated within it. The full Gearbox Contribution Agreement is accessible within the [repository](/ContributionAgreement) for comprehensive understanding. [Let's innovate together!]


# TODO
# (p *PriceFeed) Clone() *PriceFeed {
# PFVersion: p.PFVersion,
54 changes: 54 additions & 0 deletions db_scripts/local_testing/anvil_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
set -e

PARENT_DIR=$(dirname $0)
REMOTE_DB=$1
SUPERUSER=$2

FORK_BLOCK=`jq .forkBlock.number < <(curl https://anvil.gearbox.foundation/api/forks/432945bc-3620-11ee-be56-0242ac120002 )`

# if [ "$PROXY_IP" = '' ]; then
# ssh -t debian@$MAINNET_IP "bash /home/debian/db_copy.sh"
# scp debian@$MAINNET_IP:/tmp/db.sql /tmp/db.sql
# else
# ssh -t root@$PROXY_IP 'ssh -t debian@'$MAINNET_IP' "bash /home/debian/db_copy.sh"'
# ssh -t root@$PROXY_IP 'scp debian@'$MAINNET_IP':/tmp/db.sql /tmp/db.sql'
# scp root@$PROXY_IP:/tmp/db.sql /tmp/db.sql
# fi

# if [ "$SUPERUSER" = "postgres" ]; then
# sudo su postgres
# fi


export SAMPLE_DB="postgres://$SUPERUSER@localhost:5432/sample?sslmode=disable"

set +e
psql -U $SUPERUSER -d postgres -c 'drop database sample'
psql -U $SUPERUSER -d postgres -c 'create database sample'
pg_dump "$REMOTE_DB" | psql -U $SUPERUSER -d sample
set -e

# psql -U $SUPERUSER -d sample < db_scripts/local_testing/missing_table_from_download_db.sql
psql -U $SUPERUSER -d sample < $PARENT_DIR/../../migrations/000016_rankings.up.sql
migrate -path $PARENT_DIR/../../migrations/ -database "$SAMPLE_DB" up


psql -U $SUPERUSER -d sample < <(cat $PARENT_DIR/reset_to_blocknum.sql | sed "s/18246321/$FORK_BLOCK/" )
set +e
psql -U $SUPERUSER -d postgres -c 'drop database tmp_sample'
set -e
createdb -O $SUPERUSER -T sample tmp_sample

# create user sample with encrypted password '123Sample';
# GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO sample;
# ALTER DATABASE sample OWNER TO sample;
# update schema_migrations set version=27, dirty='f';
#
# SELECT format(
# 'ALTER TABLE public.%I OWNER TO sample',
# table_name
# )
# FROM information_schema.tables
# WHERE table_schema = 'public';

# SELECT * FROM information_schema.tables WHERE table_schema = 'public';
59 changes: 6 additions & 53 deletions db_scripts/local_testing/local_test.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,54 +1,7 @@
set -e

PARENT_DIR=$(dirname $0)
REMOTE_DB=$1
SUPERUSER=$2

FORK_BLOCK=`jq .forkBlock.number < <(curl https://anvil.gearbox.foundation/api/forks/432945bc-3620-11ee-be56-0242ac120002 )`

# if [ "$PROXY_IP" = '' ]; then
# ssh -t debian@$MAINNET_IP "bash /home/debian/db_copy.sh"
# scp debian@$MAINNET_IP:/tmp/db.sql /tmp/db.sql
# else
# ssh -t root@$PROXY_IP 'ssh -t debian@'$MAINNET_IP' "bash /home/debian/db_copy.sh"'
# ssh -t root@$PROXY_IP 'scp debian@'$MAINNET_IP':/tmp/db.sql /tmp/db.sql'
# scp root@$PROXY_IP:/tmp/db.sql /tmp/db.sql
# fi

# if [ "$SUPERUSER" = "postgres" ]; then
# sudo su postgres
# fi


export SAMPLE_DB="postgres://$SUPERUSER@localhost:5432/sample?sslmode=disable"

set +e
SUPERUSER="$1"
psql -U $SUPERUSER -d postgres -c 'drop database sample'
psql -U $SUPERUSER -d postgres -c 'create database sample'
pg_dump "$REMOTE_DB" | psql -U $SUPERUSER -d sample
set -e

# psql -U $SUPERUSER -d sample < db_scripts/local_testing/missing_table_from_download_db.sql
psql -U $SUPERUSER -d sample < $PARENT_DIR/../../migrations/000016_rankings.up.sql
migrate -path $PARENT_DIR/../../migrations/ -database "$SAMPLE_DB" up


psql -U $SUPERUSER -d sample < <(cat $PARENT_DIR/reset_to_blocknum.sql | sed "s/18246321/$FORK_BLOCK/" )
set +e
psql -U $SUPERUSER -d postgres -c 'drop database tmp_sample'
set -e
createdb -O $SUPERUSER -T sample tmp_sample

# create user sample with encrypted password '123Sample';
# GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO sample;
# ALTER DATABASE sample OWNER TO sample;
# update schema_migrations set version=27, dirty='f';
#
# SELECT format(
# 'ALTER TABLE public.%I OWNER TO sample',
# table_name
# )
# FROM information_schema.tables
# WHERE table_schema = 'public';

# SELECT * FROM information_schema.tables WHERE table_schema = 'public';
psql -U $SUPERUSER -d postgres -c "create database sample with owner $SUPERUSER"
pg_dump "$DCDB" | psql -U $SUPERUSER -d sample
psql -U $SUPERUSER -d sample < migrations/000016_rankings.up.sql
FORK_BLOCK=`jq .forkBlock.number < <(curl https://anvil.gearbox.foundation/api/forks/$2 )`
psql -U $SUPERUSER -d sample < <(cat db_scripts/local_testing/reset_to_blocknum.sql | sed "s/18246321/$FORK_BLOCK/" )
2 changes: 1 addition & 1 deletion debts/calc_details.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ type storeForCalc struct {
func (s storeForCalc) GetToken(token string) *schemas.Token {
return s.inner.repo.GetToken(token)
}
func (s storeForCalc) GetPrices(token string, version core.VersionType, blockNums ...int64) *big.Int {
func (s storeForCalc) GetPrices(token string, version schemas.PFVersion, blockNums ...int64) *big.Int {
return s.inner.GetTokenLastPrice(token, version)
}

Expand Down
76 changes: 34 additions & 42 deletions debts/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func (eng *DebtEngine) CalculateDebt() {
caTotalValueInUSD += utils.GetFloat64Decimal(
eng.GetAmountInUSD(
cmToPoolDetails[session.CreditManager].Token,
sessionSnapshot.TotalValueBI.Convert(), session.Version,
sessionSnapshot.TotalValueBI.Convert(), schemas.VersionToPFVersion(session.Version, false),
), 8)

for token, tokenBalance := range *sessionSnapshot.Balances {
Expand Down Expand Up @@ -192,9 +192,12 @@ func (eng *DebtEngine) createTvlSnapshots(blockNum int64, caTotalValueInUSD floa
//
underlyingToken := state.(*schemas.PoolState).UnderlyingToken
//
version := core.NewVersion(1)
if eng.tokenLastPriceV2[underlyingToken] != nil {
version = core.NewVersion(2)
version := schemas.V1PF
if eng.tokenLastPrice[schemas.V2PF] != nil {
version = schemas.V2PF
}
if eng.tokenLastPrice[schemas.V3PF_MAIN] != nil {
version = schemas.V3PF_MAIN
}
//
totalAvailableLiquidityInUSD += utils.GetFloat64Decimal(
Expand Down Expand Up @@ -281,12 +284,8 @@ func (eng *DebtEngine) GetCumulativeIndexAndDecimalForCMs(blockNum int64, ts uin
return cmToCumIndex
}

func (eng *DebtEngine) getTokenPriceFeed(token string, version core.VersionType) *schemas.PriceFeed {
if version.IsGBv1() {
return eng.tokenLastPrice[token]
} else { // v2 and above
return eng.tokenLastPriceV2[token]
}
func (eng *DebtEngine) getTokenPriceFeed(token string, pfVersion schemas.PFVersion) *schemas.PriceFeed {
return eng.tokenLastPrice[pfVersion][token]
}

func (eng *DebtEngine) SessionDebtHandler(blockNum int64, session *schemas.CreditSession, cumIndexAndUToken *ds.CumIndexAndUToken) {
Expand All @@ -301,12 +300,12 @@ func (eng *DebtEngine) SessionDebtHandler(blockNum int64, session *schemas.Credi
yearnFeeds := eng.repo.GetYearnFeedAddrs()
for tokenAddr, details := range *sessionSnapshot.Balances {
if details.IsEnabled && details.HasBalanceMoreThanOne() {
lastPriceEvent := eng.getTokenPriceFeed(tokenAddr, session.Version)
lastPriceEvent := eng.getTokenPriceFeed(tokenAddr, schemas.VersionToPFVersion(session.Version, false)) // don't use reserve
//
if tokenAddr != eng.repo.GetWETHAddr() && lastPriceEvent.BlockNumber != blockNum {
feed := lastPriceEvent.Feed
if utils.Contains(yearnFeeds, feed) {
eng.requestPriceFeed(blockNum, feed, tokenAddr, lastPriceEvent.IsPriceInUSD)
eng.requestPriceFeed(blockNum, feed, tokenAddr, lastPriceEvent.MergedPFVersion)
}
}
}
Expand Down Expand Up @@ -380,7 +379,7 @@ func (eng *DebtEngine) CalculateSessionDebt(blockNum int64, session *schemas.Cre
for tokenAddr, details := range *sessionSnapshot.Balances {
if details.IsEnabled {
profile.Tokens[tokenAddr] = ds.TokenDetails{
Price: eng.GetTokenLastPrice(tokenAddr, session.Version),
Price: eng.GetTokenLastPrice(tokenAddr, schemas.VersionToPFVersion(session.Version, false)), // don't use reserve
Decimals: eng.repo.GetToken(tokenAddr).Decimals,
TokenLiqThreshold: eng.allowedTokensThreshold[session.CreditManager][tokenAddr],
}
Expand Down Expand Up @@ -428,14 +427,15 @@ func (eng *DebtEngine) CalculateSessionDebt(blockNum int64, session *schemas.Cre
}

// helper methods
func (eng *DebtEngine) GetAmountInUSD(tokenAddr string, amount *big.Int, version core.VersionType) *big.Int {
usdcAddr := eng.repo.GetUSDCAddr()
tokenPrice := eng.GetTokenLastPrice(tokenAddr, version)
func (eng *DebtEngine) GetAmountInUSD(tokenAddr string, amount *big.Int, pfVersion schemas.PFVersion) *big.Int {
tokenPrice := eng.GetTokenLastPrice(tokenAddr, pfVersion)
tokenDecimals := eng.repo.GetToken(tokenAddr).Decimals
if version.Eq(2) {
if pfVersion.Decimals() == 8 {
return utils.GetInt64(new(big.Int).Mul(tokenPrice, amount), tokenDecimals)
}
usdcPrice := eng.GetTokenLastPrice(usdcAddr, version)
// for v1
usdcAddr := eng.repo.GetUSDCAddr()
usdcPrice := eng.GetTokenLastPrice(usdcAddr, pfVersion)
usdcDecimals := eng.repo.GetToken(usdcAddr).Decimals

value := new(big.Int).Mul(amount, tokenPrice)
Expand All @@ -444,22 +444,18 @@ func (eng *DebtEngine) GetAmountInUSD(tokenAddr string, amount *big.Int, version
return new(big.Int).Mul(value, big.NewInt(100))
}

func (eng *DebtEngine) GetTokenLastPrice(addr string, version core.VersionType, dontFail ...bool) *big.Int {
if version.Eq(1) {
if eng.tokenLastPrice[addr] != nil {
return eng.tokenLastPrice[addr].PriceBI.Convert()
} else if eng.repo.GetWETHAddr() == addr {
return core.WETHPrice
}
} else if version.Eq(2) || version.Eq(300) {
if eng.tokenLastPriceV2[addr] != nil {
return eng.tokenLastPriceV2[addr].PriceBI.Convert()
}
func (eng *DebtEngine) GetTokenLastPrice(addr string, pfVersion schemas.PFVersion, dontFail ...bool) *big.Int {
if pfVersion.ToVersion().Eq(1) && eng.repo.GetWETHAddr() == addr {
return core.WETHPrice
}
if eng.tokenLastPrice[pfVersion][addr] != nil {
return eng.tokenLastPrice[pfVersion][addr].PriceBI.Convert()
}
//
if len(dontFail) > 0 && dontFail[0] {
return nil
}
log.Fatal(fmt.Sprintf("Price not found for %s version: %d", addr, version))
log.Fatal(fmt.Sprintf("Price not found for %s pfversion: %d", addr, pfVersion))
return nil
}

Expand All @@ -483,7 +479,7 @@ func (eng *DebtEngine) SessionDataFromDC(version core.VersionType, blockNum int6
return data
}

func (eng *DebtEngine) requestPriceFeed(blockNum int64, feed, token string, isPriceInUSD bool) {
func (eng *DebtEngine) requestPriceFeed(blockNum int64, feed, token string, pfVersion schemas.MergedPFVersion) {
// PFFIX
yearnPFContract, err := yearnPriceFeed.NewYearnPriceFeed(common.HexToAddress(feed), eng.client)
log.CheckFatal(err)
Expand All @@ -494,17 +490,13 @@ func (eng *DebtEngine) requestPriceFeed(blockNum int64, feed, token string, isPr
if err != nil {
log.Fatal(err)
}
var decimals int8 = 18 // for eth
if isPriceInUSD {
decimals = 8 // for usd
}
eng.AddTokenLastPrice(&schemas.PriceFeed{
BlockNumber: blockNum,
Token: token,
Feed: feed,
RoundId: roundData.RoundId.Int64(),
PriceBI: (*core.BigInt)(roundData.Answer),
Price: utils.GetFloat64Decimal(roundData.Answer, decimals),
IsPriceInUSD: isPriceInUSD,
BlockNumber: blockNum,
Token: token,
Feed: feed,
RoundId: roundData.RoundId.Int64(),
PriceBI: (*core.BigInt)(roundData.Answer),
Price: utils.GetFloat64Decimal(roundData.Answer, pfVersion.Decimals()),
MergedPFVersion: pfVersion,
})
}
16 changes: 7 additions & 9 deletions debts/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ import (
)

type DebtEngine struct {
repo ds.RepositoryI
db *gorm.DB
client core.ClientI
config *config.Config
lastCSS map[string]*schemas.CreditSessionSnapshot
tokenLastPrice map[string]*schemas.PriceFeed
tokenLastPriceV2 map[string]*schemas.PriceFeed
repo ds.RepositoryI
db *gorm.DB
client core.ClientI
config *config.Config
lastCSS map[string]*schemas.CreditSessionSnapshot
tokenLastPrice map[schemas.PFVersion]map[string]*schemas.PriceFeed
//// credit_manager -> token -> liquidity threshold
allowedTokensThreshold map[string]map[string]*core.BigInt
poolLastInterestData map[string]*schemas.PoolInterestData
Expand Down Expand Up @@ -48,8 +47,7 @@ func GetDebtEngine(db *gorm.DB, client core.ClientI, config *config.Config, repo
client: client,
config: config,
lastCSS: make(map[string]*schemas.CreditSessionSnapshot),
tokenLastPrice: make(map[string]*schemas.PriceFeed),
tokenLastPriceV2: make(map[string]*schemas.PriceFeed),
tokenLastPrice: make(map[schemas.PFVersion]map[string]*schemas.PriceFeed),
allowedTokensThreshold: make(map[string]map[string]*core.BigInt),
poolLastInterestData: make(map[string]*schemas.PoolInterestData),
lastDebts: make(map[string]*schemas.Debt),
Expand Down
12 changes: 6 additions & 6 deletions debts/pnl.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ func (eng *DebtEngine) calAmountToPoolAndProfit(debt *schemas.Debt, session *sch
debt.RepayAmountBI = (*core.BigInt)(repayAmount)
}

remainingFundsInUSD := eng.GetAmountInUSD(cumIndexAndUToken.Token, remainingFunds, session.Version)
remainingFundsInUSD := eng.GetAmountInUSD(cumIndexAndUToken.Token, remainingFunds, schemas.VersionToPFVersion(session.Version, false))
debt.ProfitInUnderlying = utils.GetFloat64Decimal(remainingFunds, cumIndexAndUToken.Decimals) - debt.CollateralInUnderlying
// debt.CollateralInUnderlying = sessionSnapshot.CollateralInUnderlying
// fields in USD
debt.CollateralInUSD = sessionSnapshot.CollateralInUSD
debt.ProfitInUSD = utils.GetFloat64Decimal(remainingFundsInUSD, 8) - sessionSnapshot.CollateralInUSD
debt.TotalValueInUSD = utils.GetFloat64Decimal(
eng.GetAmountInUSD(cumIndexAndUToken.Token, debt.CalTotalValueBI.Convert(), session.Version), 8)
eng.GetAmountInUSD(cumIndexAndUToken.Token, debt.CalTotalValueBI.Convert(), schemas.VersionToPFVersion(session.Version, false)), 8)
}

func (eng *DebtEngine) remainingFundsv3(session *schemas.CreditSession, debt *schemas.Debt, cumIndexAndUToken *ds.CumIndexAndUToken,
Expand All @@ -81,7 +81,7 @@ func (eng *DebtEngine) remainingFundsv3(session *schemas.CreditSession, debt *sc
if session.Status == schemas.Closed && session.ClosedAt == debt.BlockNumber+1 {
prices := core.JsonFloatMap{}
for token, transferAmt := range *session.CloseTransfers {
tokenPrice := eng.GetTokenLastPrice(token, session.Version)
tokenPrice := eng.GetTokenLastPrice(token, schemas.VersionToPFVersion(session.Version, false))
price := utils.GetFloat64Decimal(tokenPrice, 8)
prices[token] = price
if transferAmt < 0 {
Expand All @@ -95,7 +95,7 @@ func (eng *DebtEngine) remainingFundsv3(session *schemas.CreditSession, debt *sc
// remainingFunds calculation
// set price for underlying token
prices[cumIndexAndUToken.Token] = utils.GetFloat64Decimal(
eng.GetTokenLastPrice(cumIndexAndUToken.Token, session.Version), 8)
eng.GetTokenLastPrice(cumIndexAndUToken.Token, schemas.VersionToPFVersion(session.Version, false)), 8)
remainingFunds = session.CloseTransfers.ValueInUnderlying(cumIndexAndUToken.Token, cumIndexAndUToken.Decimals, prices)
} else if secStatus := session.StatusAt(debt.BlockNumber + 1); schemas.IsStatusLiquidated(secStatus) {
//
Expand Down Expand Up @@ -129,7 +129,7 @@ func (eng *DebtEngine) remainingFundsv2(session *schemas.CreditSession, debt *sc
if session.Status == schemas.Closed && session.ClosedAt == debt.BlockNumber+1 {
prices := core.JsonFloatMap{}
for token, transferAmt := range *session.CloseTransfers {
tokenPrice := eng.GetTokenLastPrice(token, session.Version)
tokenPrice := eng.GetTokenLastPrice(token, schemas.VersionToPFVersion(session.Version, false))
price := utils.GetFloat64Decimal(tokenPrice, 8)
prices[token] = price
if transferAmt < 0 {
Expand All @@ -143,7 +143,7 @@ func (eng *DebtEngine) remainingFundsv2(session *schemas.CreditSession, debt *sc
// remainingFunds calculation
// set price for underlying token
prices[cumIndexAndUToken.Token] = utils.GetFloat64Decimal(
eng.GetTokenLastPrice(cumIndexAndUToken.Token, session.Version), 8)
eng.GetTokenLastPrice(cumIndexAndUToken.Token, schemas.VersionToPFVersion(session.Version, false)), 8)
remainingFunds = session.CloseTransfers.ValueInUnderlying(cumIndexAndUToken.Token, cumIndexAndUToken.Decimals, prices)
} else if session.ClosedAt == debt.BlockNumber+1 && schemas.IsStatusLiquidated(session.Status) {
remainingFunds = session.RemainingFunds.Convert()
Expand Down
5 changes: 3 additions & 2 deletions debts/tf_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,19 @@ func (calc FarmingCalculator) addFarmingVal(debt *schemas.Debt, session *schemas
if calc.testing || session.Status != schemas.Active {
return
}
pfVersion := schemas.VersionToPFVersion(session.Version, false)
var farmingVal float64 = 0
for token, balance := range *css.Balances {
if balance.IsEnabled && balance.HasBalanceMoreThanOne() && !calc.tradingTokensMap[token] {
var priceDecimals int8 = 8
if session.Version.Eq(1) {
priceDecimals = 18
}
farmingVal += balance.F * utils.GetFloat64Decimal(priceStore.GetPrices(token, session.Version), priceDecimals)
farmingVal += balance.F * utils.GetFloat64Decimal(priceStore.GetPrices(token, pfVersion), priceDecimals)
}
}
if session.Version.Eq(1) {
farmingVal = farmingVal / utils.GetFloat64Decimal(priceStore.GetPrices(calc.usdc, session.Version), 18) // convert to usd
farmingVal = farmingVal / utils.GetFloat64Decimal(priceStore.GetPrices(calc.usdc, pfVersion), 18) // convert to usd
// by dividing by usdc price in eth
}
// farming val is zero for closed accounts
Expand Down
Loading

0 comments on commit 1e7b0bf

Please sign in to comment.