Skip to content

Commit

Permalink
Pre-replant pool price update on sunrise
Browse files Browse the repository at this point in the history
  • Loading branch information
soilking committed Apr 12, 2024
1 parent c999b95 commit 19d5acf
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 111 deletions.
76 changes: 10 additions & 66 deletions projects/subgraph-bean/src/Bean3CRVHandler_V1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,13 @@ import {
TokenExchangeUnderlying
} from "../generated/Bean3CRV/Bean3CRV";
import { loadBean, updateBeanSupplyPegPercent, updateBeanValues } from "./utils/Bean";
import {
BEAN_3CRV_V1,
BEAN_ERC20_V1,
BEAN_LUSD_V1,
CALCULATIONS_CURVE,
CRV3_POOL_V1,
LUSD_3POOL
} from "../../subgraph-core/utils/Constants";
import { BEAN_ERC20_V1 } from "../../subgraph-core/utils/Constants";
import { toDecimal, ZERO_BD, ZERO_BI } from "../../subgraph-core/utils/Decimals";
import { loadOrCreatePool, setPoolReserves, updatePoolPrice, updatePoolValues } from "./utils/Pool";
import { CalculationsCurve } from "../generated/Bean3CRV-V1/CalculationsCurve";
import { Bean3CRV } from "../generated/Bean3CRV-V1/Bean3CRV";
import { ERC20 } from "../generated/Bean3CRV-V1/ERC20";
import { checkBeanCross } from "./utils/Cross";
import { curveDeltaB } from "./utils/Price";
import { curveDeltaB, curvePriceAndLp } from "./utils/Price";

export function handleTokenExchange(event: TokenExchange): void {
// Do not index post-exploit data
Expand Down Expand Up @@ -113,35 +105,11 @@ function handleLiquidityChange(
): void {
let pool = loadOrCreatePool(poolAddress, blockNumber);

// Get Curve Price Details
let curveCalc = CalculationsCurve.bind(CALCULATIONS_CURVE);
let metapoolPrice = toDecimal(curveCalc.getCurvePriceUsdc(CRV3_POOL_V1));

let lpContract = Bean3CRV.bind(Address.fromString(poolAddress));
let beanCrvPrice = ZERO_BD;
let lusd3crvPrice = ZERO_BD;

let lpValue = ZERO_BD;
if (poolAddress == BEAN_3CRV_V1.toHexString()) {
beanCrvPrice = toDecimal(lpContract.get_dy(ZERO_BI, BigInt.fromI32(1), BigInt.fromI32(1000000)), 18);

let crv3PoolContract = ERC20.bind(CRV3_POOL_V1);
let crvHolding = toDecimal(crv3PoolContract.balanceOf(Address.fromString(poolAddress)), 18);
lpValue = crvHolding.times(metapoolPrice);
} else if (poolAddress == BEAN_LUSD_V1.toHexString()) {
// price in LUSD
let priceInLusd = toDecimal(lpContract.get_dy(ZERO_BI, BigInt.fromI32(1), BigInt.fromI32(1000000)), 18);
log.info("LiquidityChange: Bean LUSD price: {}", [priceInLusd.toString()]);

let lusdContract = Bean3CRV.bind(LUSD_3POOL);
lusd3crvPrice = toDecimal(lusdContract.get_dy(ZERO_BI, BigInt.fromI32(1), BigInt.fromString("1000000000000000000")), 18);
beanCrvPrice = priceInLusd.times(lusd3crvPrice);

let lusdHolding = toDecimal(lusdContract.balanceOf(Address.fromString(poolAddress)), 18);
lpValue = lusdHolding.times(lusd3crvPrice).times(metapoolPrice);
}

let newPrice = metapoolPrice.times(beanCrvPrice);
let priceAndLp = curvePriceAndLp(Address.fromString(poolAddress));
let newPrice = priceAndLp[0];
let lpValue = priceAndLp[1];

let bean = loadBean(BEAN_ERC20_V1.toHexString());
let oldBeanPrice = bean.price;
Expand Down Expand Up @@ -169,7 +137,7 @@ function handleLiquidityChange(
setPoolReserves(poolAddress, reserveBalances.value, blockNumber);
}

let deltaB = curveDeltaB(lpContract, reserveBalances.value[0]);
let deltaB = curveDeltaB(Address.fromString(poolAddress), reserveBalances.value[0]);

updateBeanSupplyPegPercent(blockNumber);

Expand All @@ -190,35 +158,11 @@ function handleSwap(
): void {
let pool = loadOrCreatePool(poolAddress, blockNumber);

// Get Curve Price Details
let curveCalc = CalculationsCurve.bind(CALCULATIONS_CURVE);
let metapoolPrice = toDecimal(curveCalc.getCurvePriceUsdc(CRV3_POOL_V1));

let lpContract = Bean3CRV.bind(Address.fromString(poolAddress));
let beanCrvPrice = ZERO_BD;
let lusd3crvPrice = ZERO_BD;

let lpValue = ZERO_BD;
if (poolAddress == BEAN_3CRV_V1.toHexString()) {
beanCrvPrice = toDecimal(lpContract.get_dy(ZERO_BI, BigInt.fromI32(1), BigInt.fromI32(1000000)), 18);

let crv3PoolContract = ERC20.bind(CRV3_POOL_V1);
let crvHolding = toDecimal(crv3PoolContract.balanceOf(Address.fromString(poolAddress)), 18);
lpValue = crvHolding.times(metapoolPrice);
} else if (poolAddress == BEAN_LUSD_V1.toHexString()) {
// price in LUSD
let priceInLusd = toDecimal(lpContract.get_dy(ZERO_BI, BigInt.fromI32(1), BigInt.fromI32(1000000)), 18);
log.info("LiquidityChange: Bean LUSD price: {}", [priceInLusd.toString()]);

let lusdContract = Bean3CRV.bind(LUSD_3POOL);
lusd3crvPrice = toDecimal(lusdContract.get_dy(ZERO_BI, BigInt.fromI32(1), BigInt.fromString("1000000000000000000")), 18);
beanCrvPrice = priceInLusd.times(lusd3crvPrice);

let lusdHolding = toDecimal(lusdContract.balanceOf(Address.fromString(poolAddress)), 18);
lpValue = lusdHolding.times(lusd3crvPrice).times(metapoolPrice);
}

let newPrice = metapoolPrice.times(beanCrvPrice);
let priceAndLp = curvePriceAndLp(Address.fromString(poolAddress));
let newPrice = priceAndLp[0];
let lpValue = priceAndLp[1];

let bean = loadBean(BEAN_ERC20_V1.toHexString());
let oldBeanPrice = bean.price;
Expand All @@ -242,7 +186,7 @@ function handleSwap(
setPoolReserves(poolAddress, reserveBalances.value, blockNumber);
}

let deltaB = curveDeltaB(lpContract, reserveBalances.value[0]);
let deltaB = curveDeltaB(Address.fromString(poolAddress), reserveBalances.value[0]);

updateBeanSupplyPegPercent(blockNumber);

Expand Down
40 changes: 38 additions & 2 deletions projects/subgraph-bean/src/BeanstalkHandler.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { BigInt } from "@graphprotocol/graph-ts";
import { Address, BigInt } from "@graphprotocol/graph-ts";
import { Sunrise } from "../generated/Beanstalk/Beanstalk";
import { getBeanTokenAddress, loadBean, updateBeanSeason, updateBeanValues } from "./utils/Bean";
import { loadOrCreatePool, updatePoolPrice, updatePoolSeason, updatePoolValues } from "./utils/Pool";
import { BeanstalkPrice } from "../generated/Beanstalk/BeanstalkPrice";
import { BEANSTALK_PRICE, BEAN_3CRV, BEAN_ERC20, BEAN_WETH_CP2_WELL, CURVE_PRICE } from "../../subgraph-core/utils/Constants";
import { BEANSTALK_PRICE, BEAN_3CRV, BEAN_ERC20, BEAN_WETH_CP2_WELL, BEAN_WETH_V1, CURVE_PRICE } from "../../subgraph-core/utils/Constants";
import { ZERO_BD, ZERO_BI, toDecimal } from "../../subgraph-core/utils/Decimals";
import { CurvePrice } from "../generated/Beanstalk/CurvePrice";
import { checkBeanCross } from "./utils/Cross";
import { curveDeltaB, curvePriceAndLp, uniswapV2DeltaB, uniswapV2Price, updatePreReplantPriceETH } from "./utils/Price";

export function handleSunrise(event: Sunrise): void {
// Update the season for hourly and daily liquidity metrics
Expand Down Expand Up @@ -88,5 +89,40 @@ export function handleSunrise(event: Sunrise): void {
checkBeanCross(BEAN_ERC20.toHexString(), event.block.timestamp, event.block.number, oldBeanPrice, toDecimal(curve.value.price));
}
}
} else {
// Pre-Replant
for (let i = 0; i < bean.pools.length; i++) {
const pool = loadOrCreatePool(bean.pools[i], event.block.number);
let price = ZERO_BD;
let liquidity = ZERO_BD;
let deltaB = ZERO_BI;
if (bean.pools[i] == BEAN_WETH_V1.toHexString()) {
const wethToken = updatePreReplantPriceETH();
const reserves = [toDecimal(pool.reserves[0], 18), toDecimal(pool.reserves[1])];
price = uniswapV2Price(reserves[1], reserves[0], wethToken.lastPriceUSD);
liquidity = reserves[0].times(wethToken.lastPriceUSD);
deltaB = uniswapV2DeltaB(reserves[1], reserves[0], wethToken.lastPriceUSD);
} else {
const priceAndLp = curvePriceAndLp(Address.fromString(bean.pools[i]));
price = priceAndLp[0];
liquidity = priceAndLp[1];
deltaB = curveDeltaB(Address.fromString(bean.pools[i]), pool.reserves[0]);
}

// Update price, liquidity, and deltaB in the pool
updatePoolValues(
BEAN_3CRV.toHexString(),
event.block.timestamp,
event.block.number,
ZERO_BI,
ZERO_BD,
liquidity.minus(pool.liquidityUSD),
deltaB
);
updatePoolPrice(BEAN_3CRV.toHexString(), event.block.timestamp, event.block.number, price);
}
// TODO: Total price
// updateBeanValues(BEAN_ERC20.toHexString(), event.block.timestamp, price, ZERO_BI, ZERO_BI, ZERO_BD, ZERO_BD);
// checkBeanCross(BEAN_ERC20.toHexString(), event.block.timestamp, event.block.number, oldBeanPrice, toDecimal(curve.value.price));
}
}
34 changes: 7 additions & 27 deletions projects/subgraph-bean/src/UniswapV2Handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { loadOrCreatePool, setPoolReserves, updatePoolPrice, updatePoolReserves,
import { loadOrCreateToken } from "./utils/Token";
import { checkBeanCross } from "./utils/Cross";
import { Token } from "../generated/schema";
import { uniswapV2DeltaB } from "./utils/Price";
import { uniswapV2DeltaB, uniswapV2Price, uniswapV2Reserves, updatePreReplantPriceETH } from "./utils/Price";

// export function handleMint(event: Mint): void {
// updatePoolReserves(event.address.toHexString(), event.params.amount0, event.params.amount1, event.block.number);
Expand Down Expand Up @@ -71,19 +71,14 @@ export function handleSync(event: Sync): void {
let bean = loadBean(BEAN_ERC20_V1.toHexString());
let oldBeanPrice = bean.price;

let pair = UniswapV2Pair.bind(event.address);

let reserves = pair.try_getReserves();
if (reserves.reverted) {
return;
}
let reserves = uniswapV2Reserves(event.address);

// Token 0 is WETH and Token 1 is BEAN

let weth = updatePriceETH();
let weth = updatePreReplantPriceETH();

let wethBalance = toDecimal(reserves.value.value0, 18);
let beanBalance = toDecimal(reserves.value.value1);
let wethBalance = toDecimal(reserves[0], 18);
let beanBalance = toDecimal(reserves[1]);

let pool = loadOrCreatePool(event.address.toHexString(), event.block.number);
let startLiquidityUSD = pool.liquidityUSD;
Expand All @@ -93,30 +88,15 @@ export function handleSync(event: Sync): void {

updatePoolValues(event.address.toHexString(), event.block.timestamp, event.block.number, ZERO_BI, ZERO_BD, deltaLiquidityUSD, deltaBeans);

let currentBeanPrice = wethBalance.times(weth.lastPriceUSD).div(beanBalance);
let currentBeanPrice = uniswapV2Price(beanBalance, wethBalance, weth.lastPriceUSD);

updatePoolPrice(event.address.toHexString(), event.block.timestamp, event.block.number, currentBeanPrice);

checkBeanCross(BEAN_ERC20_V1.toHexString(), event.block.timestamp, event.block.number, oldBeanPrice, currentBeanPrice);

setPoolReserves(event.address.toHexString(), [reserves.value.value0, reserves.value.value1], event.block.number);
setPoolReserves(event.address.toHexString(), reserves, event.block.number);

updateBeanSupplyPegPercent(event.block.number);

updateBeanValues(BEAN_ERC20_V1.toHexString(), event.block.timestamp, currentBeanPrice, ZERO_BI, ZERO_BI, ZERO_BD, deltaLiquidityUSD);
}

function updatePriceETH(): Token {
let token = loadOrCreateToken(WETH.toHexString());
let pair = UniswapV2Pair.bind(WETH_USDC_PAIR);

let reserves = pair.try_getReserves();
if (reserves.reverted) {
return token;
}

// Token 0 is USDC and Token 1 is WETH
token.lastPriceUSD = toDecimal(reserves.value.value0).div(toDecimal(reserves.value.value1, 18));
token.save();
return token;
}
7 changes: 3 additions & 4 deletions projects/subgraph-bean/src/utils/Pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,11 @@ export function updatePoolSeason(poolAddress: string, timestamp: BigInt, blockNu
let poolDaily = loadOrCreatePoolDailySnapshot(poolAddress, timestamp, blockNumber);

pool.lastSeason = season;
pool.save();

poolHourly.season = season;
poolHourly.save();

poolDaily.season = season;

pool.save();
poolHourly.save();
poolDaily.save();
}

Expand Down
Loading

0 comments on commit 19d5acf

Please sign in to comment.