Skip to content

Commit

Permalink
Use beefy swapper for all token prices to native
Browse files Browse the repository at this point in the history
  • Loading branch information
prevostc committed Jun 29, 2024
1 parent cc91a83 commit efc958d
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 87 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,6 @@ yarn test:lint # run prettier linter
- clmStrategy.range()
- clmStrategy.output() // optional
- clmStrategy.balanceOfPool()
- clmStrategy.lpToken1ToNativePrice()
- clmStrategy.lpToken0ToNativePrice()
- clmStrategy: Initialized(uint8)
- clmStrategy: Paused(address)
- clmStrategy: Unpaused(address)
Expand Down
31 changes: 0 additions & 31 deletions config/optimism-tmp.json

This file was deleted.

4 changes: 2 additions & 2 deletions config/optimism.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"clmStrategyFactoryStartBlock": 121125469,
"rewardPoolFactoryAddress": "0x4399457CB360fC37242d2BE326579Caf3981c769",
"rewardPoolFactoryStartBlock": 121125461,
"beefyClassicVaultFactoryAddress": "0xf14e1bd3315CfADE440Ba29B3cF62CBc811F9DEd",
"beefyClassicVaultFactoryStartBlock": 121125456,
"beefyClassicVaultFactoryAddress": "0xA6D3769faC465FC0415e7E9F16dcdC96B83C240B",
"beefyClassicVaultFactoryStartBlock": 121101589,
"beefyClassicBoostFactoryAddress": "0xf0a7626eccbee00af144bb1f77cd187af85bbf41",
"beefyClassicBoostFactoryStartBlock": 121125456,
"clockTickBlocks": 250,
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"prepare:linea": "./bin/prepare.sh linea",
"prepare:manta": "./bin/prepare.sh manta",
"prepare:moonbeam": "./bin/prepare.sh moonbeam",
"prepare:optimism-tmp": "./bin/prepare.sh optimism-tmp",
"prepare:optimism": "./bin/prepare.sh optimism",
"prepare:polygon": "./bin/prepare.sh polygon",
"prepare:zksync": "./bin/prepare.sh zksync"
Expand Down
118 changes: 68 additions & 50 deletions src/clm/utils/clm-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
PYTH_PRICE_FEED_ADDRESS,
PYTH_NATIVE_PRICE_ID,
PRICE_ORACLE_TYPE,
WNATIVE_DECIMALS,
} from "../../config"
import { Multicall3Params, MulticallResult, multicall } from "../../common/utils/multicall"
import { getToken, isNullToken } from "../../common/entity/token"
Expand All @@ -23,19 +24,21 @@ export function fetchCLMData(clm: CLM): CLMData {
const strategyAddress = clm.strategy
const rewardPoolAddress = clm.rewardPoolToken

const token1 = getToken(clm.underlyingToken0)
const token0 = getToken(clm.underlyingToken0)
const token1 = getToken(clm.underlyingToken1)
const rewardPoolToken = getToken(clm.rewardPoolToken)
const hasRewardPool = !isNullToken(rewardPoolToken)

const calls = [
new Multicall3Params(managerAddress, "totalSupply()", "uint256"),
new Multicall3Params(managerAddress, "balances()", "(uint256,uint256)"),
new Multicall3Params(strategyAddress, "balancesOfPool()", "(uint256,uint256,uint256,uint256,uint256,uint256)"),
new Multicall3Params(strategyAddress, "price()", "uint256"),
new Multicall3Params(strategyAddress, "range()", "(uint256,uint256)"),
new Multicall3Params(strategyAddress, "lpToken0ToNativePrice()", "uint256"),
new Multicall3Params(strategyAddress, "lpToken1ToNativePrice()", "uint256"),
new Multicall3Params(rewardPoolAddress, "totalSupply()", "uint256"),
]

// wnative price to usd
if (PRICE_ORACLE_TYPE == "chainlink") {
calls.push(
new Multicall3Params(
Expand All @@ -55,51 +58,62 @@ export function fetchCLMData(clm: CLM): CLMData {
throw new Error("Unsupported price oracle type")
}

const hasRewardPool = !isNullToken(rewardPoolToken)
const rewardTokens = clm.rewardTokens
let rewardCallStartIndex = calls.length
if (hasRewardPool) {
calls.push(new Multicall3Params(rewardPoolAddress, "totalSupply()", "uint256"))
// warm up beefy swapper oracle
const tokensToRefresh = new Array<Address>()
tokensToRefresh.push(WNATIVE_TOKEN_ADDRESS)
tokensToRefresh.push(Address.fromBytes(clm.underlyingToken0))
tokensToRefresh.push(Address.fromBytes(clm.underlyingToken1))
for (let i = 0; i < clm.outputTokens.length; i++) {
tokensToRefresh.push(Address.fromBytes(clm.outputTokens[i]))
}
for (let i = 0; i < clm.rewardTokens.length; i++) {
tokensToRefresh.push(Address.fromBytes(clm.rewardTokens[i]))
}
for (let i = 0; i < tokensToRefresh.length; i++) {
const tokenAddress = tokensToRefresh[i]
calls.push(
new Multicall3Params(BEEFY_ORACLE_ADDRESS, "getFreshPrice(address)", "(uint256,bool)", [
ethereum.Value.fromAddress(WNATIVE_TOKEN_ADDRESS),
ethereum.Value.fromAddress(tokenAddress),
]),
)

rewardCallStartIndex = calls.length // ignore the first two calls, those just warm up the prices
for (let i = 0; i < rewardTokens.length; i++) {
const rewardTokenAddress = Address.fromBytes(rewardTokens[i])
const rewardToken = getToken(rewardTokenAddress)
calls.push(
new Multicall3Params(BEEFY_ORACLE_ADDRESS, "getFreshPrice(address)", "(uint256,bool)", [
ethereum.Value.fromAddress(rewardTokenAddress),
]),
)

const amountIn = changeValueEncoding(ONE_BI, ZERO_BI, rewardToken.decimals).div(BEEFY_SWAPPER_VALUE_SCALER)
calls.push(
new Multicall3Params(BEEFY_SWAPPER_ADDRESS, "getAmountOut(address,address,uint256)", "uint256", [
ethereum.Value.fromAddress(rewardTokenAddress),
ethereum.Value.fromAddress(WNATIVE_TOKEN_ADDRESS),
ethereum.Value.fromUnsignedBigInt(amountIn),
]),
)
}
}
const rewardCallsEndIndex = calls.length

const outputCallsStartIndex = calls.length
const outputTokens = clm.outputTokens
for (let i = 0; i < outputTokens.length; i++) {
const outputTokenAddress = Address.fromBytes(outputTokens[i])
// underlying token 0/1 prices
const amount0In = changeValueEncoding(ONE_BI, ZERO_BI, token0.decimals).div(BEEFY_SWAPPER_VALUE_SCALER)
calls.push(
new Multicall3Params(BEEFY_SWAPPER_ADDRESS, "getAmountOut(address,address,uint256)", "uint256", [
ethereum.Value.fromAddress(Address.fromBytes(clm.underlyingToken0)),
ethereum.Value.fromAddress(WNATIVE_TOKEN_ADDRESS),
ethereum.Value.fromUnsignedBigInt(amount0In),
]),
)
const amount1In = changeValueEncoding(ONE_BI, ZERO_BI, token1.decimals).div(BEEFY_SWAPPER_VALUE_SCALER)
calls.push(
new Multicall3Params(BEEFY_SWAPPER_ADDRESS, "getAmountOut(address,address,uint256)", "uint256", [
ethereum.Value.fromAddress(Address.fromBytes(clm.underlyingToken1)),
ethereum.Value.fromAddress(WNATIVE_TOKEN_ADDRESS),
ethereum.Value.fromUnsignedBigInt(amount1In),
]),
)

const rewardTokens = clm.rewardTokens
for (let i = 0; i < rewardTokens.length; i++) {
const rewardTokenAddress = Address.fromBytes(rewardTokens[i])
const rewardToken = getToken(rewardTokenAddress)
const amountIn = changeValueEncoding(ONE_BI, ZERO_BI, rewardToken.decimals).div(BEEFY_SWAPPER_VALUE_SCALER)
calls.push(
new Multicall3Params(BEEFY_ORACLE_ADDRESS, "getFreshPrice(address)", "(uint256,bool)", [
ethereum.Value.fromAddress(outputTokenAddress),
new Multicall3Params(BEEFY_SWAPPER_ADDRESS, "getAmountOut(address,address,uint256)", "uint256", [
ethereum.Value.fromAddress(rewardTokenAddress),
ethereum.Value.fromAddress(WNATIVE_TOKEN_ADDRESS),
ethereum.Value.fromUnsignedBigInt(amountIn),
]),
)
}

const amountIn = changeValueEncoding(ONE_BI, ZERO_BI, token1.decimals).div(BEEFY_SWAPPER_VALUE_SCALER)
const outputTokens = clm.outputTokens
for (let i = 0; i < outputTokens.length; i++) {
const outputTokenAddress = Address.fromBytes(outputTokens[i])
const amountIn = changeValueEncoding(ONE_BI, ZERO_BI, WNATIVE_DECIMALS).div(BEEFY_SWAPPER_VALUE_SCALER)
calls.push(
new Multicall3Params(BEEFY_SWAPPER_ADDRESS, "getAmountOut(address,address,uint256)", "uint256", [
ethereum.Value.fromAddress(outputTokenAddress),
Expand All @@ -108,29 +122,33 @@ export function fetchCLMData(clm: CLM): CLMData {
]),
)
}
const outputCallsEndIndex = calls.length

// map multicall indices to variables
const results = multicall(calls)
const totalSupplyRes = results[0]
const balanceRes = results[1]
const balanceOfPoolRes = results[2]
const priceRes = results[3]
const rangeRes = results[4]
const token0ToNativePriceRes = results[5]
const token1ToNativePriceRes = results[6]
const priceFeedRes = results[7]
const rewardPoolTotalSupplyRes = hasRewardPool ? results[8] : null
const rewardPoolTotalSupplyRes = results[5]
const priceFeedRes = results[6]
let idxAfterRefresh = 6 + tokensToRefresh.length
const token0ToNativePriceRes = results[idxAfterRefresh + 1]
const token1ToNativePriceRes = results[idxAfterRefresh + 2]
const rewardTokenOutputAmountsRes = new Array<MulticallResult>()
if (hasRewardPool) {
for (let i = rewardCallStartIndex; i < rewardCallsEndIndex; i += 2) {
rewardTokenOutputAmountsRes.push(results[i + 1])
}
let start = idxAfterRefresh + 3
let end = start + rewardTokens.length
for (let i = start; i < end; i++) {
rewardTokenOutputAmountsRes.push(results[i])
}
start = end
end = start + outputTokens.length
const outputTokenOutputAmountsRes = new Array<MulticallResult>()
for (let i = outputCallsStartIndex; i < outputCallsEndIndex; i += 2) {
outputTokenOutputAmountsRes.push(results[i + 1])
for (let i = start; i < end; i++) {
outputTokenOutputAmountsRes.push(results[i])
}

// extract the data
let managerTotalSupply = ZERO_BI
if (!totalSupplyRes.reverted) {
managerTotalSupply = totalSupplyRes.value.toBigInt()
Expand Down Expand Up @@ -190,13 +208,13 @@ export function fetchCLMData(clm: CLM): CLMData {
// due to a misconfigured quote path in the contract
let token0ToNativePrice = ZERO_BI
if (!token0ToNativePriceRes.reverted) {
token0ToNativePrice = token0ToNativePriceRes.value.toBigInt()
token0ToNativePrice = token0ToNativePriceRes.value.toBigInt().times(BEEFY_SWAPPER_VALUE_SCALER)
} else {
log.error("Failed to fetch token0ToNativePrice for CLM {}", [clm.id.toHexString()])
}
let token1ToNativePrice = ZERO_BI
if (!token1ToNativePriceRes.reverted) {
token1ToNativePrice = token1ToNativePriceRes.value.toBigInt()
token1ToNativePrice = token1ToNativePriceRes.value.toBigInt().times(BEEFY_SWAPPER_VALUE_SCALER)
} else {
log.error("Failed to fetch token0ToNativePrice for CLM {}", [clm.id.toHexString()])
}
Expand Down
2 changes: 1 addition & 1 deletion src/config.template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ export const BEEFY_SWAPPER_ADDRESS = Address.fromString("{{beefySwapperAddress}}
export const BEEFY_ORACLE_ADDRESS = Address.fromString("{{beefyOracleAddress}}")
// amount we divide 1 of _fromToken to get 1 of _toToken before asking for the price
// this is to avoid liquidity issues with tokens that have very high price (e.g. BTC)
export const BEEFY_SWAPPER_VALUE_SCALER = BigInt.fromU32(20)
export const BEEFY_SWAPPER_VALUE_SCALER = BigInt.fromU32(1000)

0 comments on commit efc958d

Please sign in to comment.