Skip to content

Commit

Permalink
Merge pull request #56 from harvestfi/base-curve-pool
Browse files Browse the repository at this point in the history
fix: base curve vaults apy 0 fix
  • Loading branch information
CryptJS13 authored Jun 26, 2024
2 parents a3db417 + 55ea386 commit 129033c
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 32 deletions.
4 changes: 4 additions & 0 deletions data/mainnet/tokens.js
Original file line number Diff line number Diff line change
Expand Up @@ -4198,6 +4198,7 @@ module.exports = {
addresses.BASE.V2.curve_USDC_USDbC_axlUSDC_crvUSD.Gauge,
profitSharingCut10Percent,
CHAIN_IDS.BASE,
addresses.BASE.V2.curve_USDC_USDbC_axlUSDC_crvUSD.NewStrategy,
],
},
],
Expand Down Expand Up @@ -4233,6 +4234,7 @@ module.exports = {
addresses.BASE.V2.curve_CBETH_ETH.Gauge,
profitSharingCut10Percent,
CHAIN_IDS.BASE,
addresses.BASE.V2.curve_CBETH_ETH.NewStrategy,
],
},
],
Expand Down Expand Up @@ -4267,6 +4269,7 @@ module.exports = {
addresses.BASE.V2.curve_CRV_crvUSD.Gauge,
profitSharingCut10Percent,
CHAIN_IDS.BASE,
addresses.BASE.V2.curve_CRV_crvUSD.NewStrategy,
],
},
],
Expand Down Expand Up @@ -4301,6 +4304,7 @@ module.exports = {
addresses.BASE.V2.curve_ETH_tBTC_crvUSD.Gauge,
profitSharingCut10Percent,
CHAIN_IDS.BASE,
addresses.BASE.V2.curve_ETH_tBTC_crvUSD.NewStrategy,
],
},
],
Expand Down
2 changes: 2 additions & 0 deletions src/lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ const STAKEWISE_API_URLS = {
const DEXSCREENER_API_URL = 'https://api.dexscreener.com/latest/dex/tokens'

const CURVE_FINANCE_API_URL = 'https://api.curve.fi/api'
const CURVE_FINANCE_BASE_API_URL = 'https://prices.curve.fi/v1/chains/base'

const QUICKSWAP_GAMMA_ENDPOINT = 'https://wire2.gamma.xyz/'
const MERKL_ENDPOINT = 'https://api.angle.money/v2/merkl'
Expand Down Expand Up @@ -304,6 +305,7 @@ module.exports = {
BASE_RPC_URL,
DEXSCREENER_API_URL,
CURVE_FINANCE_API_URL,
CURVE_FINANCE_BASE_API_URL,
WOMBAT_ARB_SUBGRAPH_URL,
WOMBAT_ARB_ONE_BLOCK_URL,
CURRENCY_API_URL,
Expand Down
3 changes: 3 additions & 0 deletions src/lib/web3/contracts/crv-child-gauge/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const getRewardData = (addr, instance) =>
countFunctionCall(instance.methods.reward_data(addr).call())
const getRewardToken = (index, instance) =>
countFunctionCall(instance.methods.reward_tokens(index).call())
const getInflationRate = (arg, instance) =>
countFunctionCall(instance.methods.inflation_rate(arg).call())

module.exports = {
getWorkingSupply,
Expand All @@ -17,4 +19,5 @@ module.exports = {
balanceOf,
getRewardData,
getRewardToken,
getInflationRate,
}
83 changes: 57 additions & 26 deletions src/vaults/apys/implementations/curve-gauge.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ const { getTokenPrice } = require('../../../prices')
const { crvGauge, crvChildGauge } = require('../../../lib/web3/contracts')
const { CHAIN_IDS } = require('../../../lib/constants')

const getApy = async (tokenSymbol, gaugeAddress, factor, chainId) => {
const getApy = async (tokenSymbol, gaugeAddress, factor, chainId, strategy = null) => {
const web3 = getWeb3(chainId)
const MAX_REWARD_TOKENS = 8
const ZeroAddress = '0x0000000000000000000000000000000000000000'
const CRV_BASE = '0x8Ee73c484A26e0A5df2Ee2a4960B789967dd0415'
let {
contract: { abi: gaugeAbi },
methods: gaugeMethods,
Expand All @@ -22,41 +23,71 @@ const getApy = async (tokenSymbol, gaugeAddress, factor, chainId) => {
gaugeMethods = childMethods
}

const lpTokenPrice = new BigNumber(await getTokenPrice(tokenSymbol, chainId))
const gaugeInstance = new web3.eth.Contract(gaugeAbi, gaugeAddress)

let rewardTokens = []
for (let i = 0; i < MAX_REWARD_TOKENS; i++) {
rewardTokens[i] = await gaugeMethods.getRewardToken(i, gaugeInstance)
}
const totalSupply = new BigNumber(await gaugeMethods.getTotalSupply(gaugeInstance)).dividedBy(
new BigNumber(1e18),
)
const lpTokenPrice = new BigNumber(await getTokenPrice(tokenSymbol, chainId))

let totalRewardPerWeekUsd = new BigNumber(0)
for (let i = 0; i < rewardTokens.length; i++) {
const rewardToken = rewardTokens[i]
if (rewardToken !== ZeroAddress) {
const rewardTokenMeta = await gaugeMethods.getRewardData(rewardToken, gaugeInstance)
if (Date.now() / 1000 > parseInt(rewardTokenMeta.period_finish)) {
continue
}
const inflationRate = new BigNumber(rewardTokenMeta.rate).dividedBy(new BigNumber(1e18))
const tokenPerWeek = inflationRate.times(7).times(86400)
const shareForOneLpt = new BigNumber(1).dividedBy(totalSupply).plus(1)
const rewardPerWeek = shareForOneLpt.times(tokenPerWeek)
let result = 0

if (chainId == CHAIN_IDS.BASE) {
const arg = Math.floor(Date.now() / (1000 * 86400 * 7))
const inflationRate = new BigNumber(await gaugeMethods.getInflationRate(arg, gaugeInstance))
const workingBalance = new BigNumber(
await gaugeMethods.getWorkingBalance(strategy, gaugeInstance),
)
const workingSupply = new BigNumber(await gaugeMethods.getWorkingSupply(gaugeInstance))

const rewardTokenInUsd = await getTokenPrice(rewardToken, chainId)
const rewardPerWeekUsd = rewardPerWeek.times(rewardTokenInUsd)
totalRewardPerWeekUsd = totalRewardPerWeekUsd.plus(rewardPerWeekUsd)
const rewardPerYear = inflationRate
.dividedBy(new BigNumber(1e18))
.times(365)
.times(86400)
.times(workingBalance)
.dividedBy(workingSupply)
const rewardTokenInUsd = await getTokenPrice(CRV_BASE, chainId)
const lpBalance = new BigNumber(
await gaugeMethods.balanceOf(strategy, gaugeInstance),
).dividedBy(new BigNumber(1e18))

const apy = rewardPerYear
.times(rewardTokenInUsd)
.dividedBy(lpTokenPrice)
.dividedBy(lpBalance)
.multipliedBy(100)
result = apy.times(factor).toFixed(2, 1)
} else {
let rewardTokens = []
for (let i = 0; i < MAX_REWARD_TOKENS; i++) {
rewardTokens[i] = await gaugeMethods.getRewardToken(i, gaugeInstance)
}

for (let i = 0; i < rewardTokens.length; i++) {
const rewardToken = rewardTokens[i]
if (rewardToken !== ZeroAddress) {
const rewardTokenMeta = await gaugeMethods.getRewardData(rewardToken, gaugeInstance)
if (Date.now() / 1000 > parseInt(rewardTokenMeta.period_finish)) {
continue
}
const inflationRate = new BigNumber(rewardTokenMeta.rate).dividedBy(new BigNumber(1e18))
const tokenPerWeek = inflationRate.times(7).times(86400)
const shareForOneLpt = new BigNumber(1).dividedBy(totalSupply).plus(1)
const rewardPerWeek = shareForOneLpt.times(tokenPerWeek)

const rewardTokenInUsd = await getTokenPrice(rewardToken, chainId)
const rewardPerWeekUsd = rewardPerWeek.times(rewardTokenInUsd)
totalRewardPerWeekUsd = totalRewardPerWeekUsd.plus(rewardPerWeekUsd)
}
}
const apy = totalRewardPerWeekUsd
.times(52)
.dividedBy(lpTokenPrice)
.dividedBy(totalSupply)
.multipliedBy(100)
result = apy.times(factor).toFixed(2, 1)
}
const apy = totalRewardPerWeekUsd
.times(52)
.dividedBy(lpTokenPrice)
.dividedBy(totalSupply)
.multipliedBy(100)
const result = apy.times(factor).toFixed(2, 1)

return result
}
Expand Down
13 changes: 7 additions & 6 deletions src/vaults/trading-apys/implementations/curve-base.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
const axios = require('axios')
const { get } = require('lodash')
const { CURVE_FINANCE_API_URL } = require('../../../lib/constants')
const { CURVE_FINANCE_BASE_API_URL } = require('../../../lib/constants')

const getTradingApy = async poolAddress => {
let response, poolDetails, poolDetail, apy

try {
response = await axios.get(`${CURVE_FINANCE_API_URL}/getFactoryAPYs-base`)
poolDetails = get(response, 'data.data.poolDetails', 0)
response = await axios.get(`${CURVE_FINANCE_BASE_API_URL}`)
poolDetails = get(response, 'data.data', 0)
} catch (err) {
console.error('DexScreener API error: ', err)
console.error('Curve API error: ', err)
response = null
poolDetails = null
}

if (poolDetails != null) {
poolDetail = poolDetails.find(obj => obj.poolAddress.toLowerCase() == poolAddress.toLowerCase())
poolDetail = poolDetails.find(obj => obj.address.toLowerCase() == poolAddress.toLowerCase())
} else {
poolDetail = null
}

if (poolDetail != null) {
apy = parseFloat(poolDetail.apy)
apy = parseFloat(poolDetail.base_daily_apr) * 100
apy = apy.toFixed(2, 1)
} else {
apy = 0
Expand Down

0 comments on commit 129033c

Please sign in to comment.