Skip to content

Commit

Permalink
Add getFactoGaugesCrvRewards to retrieve crv rewards from sidechain f…
Browse files Browse the repository at this point in the history
…acto gauges
  • Loading branch information
philippe-git committed Mar 18, 2022
1 parent 3780b08 commit 2a33eb6
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 34 deletions.
1 change: 1 addition & 0 deletions constants/abis/sidechain-root-gauge.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_crv_token","type":"address"},{"name":"_gauge_controller","type":"address"},{"name":"_minter","type":"address"}],"outputs":[]},{"stateMutability":"payable","type":"fallback"},{"stateMutability":"nonpayable","type":"function","name":"transmit_emissions","inputs":[],"outputs":[]},{"stateMutability":"view","type":"function","name":"integrate_fraction","inputs":[{"name":"_user","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"user_checkpoint","inputs":[{"name":"_user","type":"address"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"set_killed","inputs":[{"name":"_is_killed","type":"bool"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"update_bridger","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"initialize","inputs":[{"name":"_bridger","type":"address"},{"name":"_chain_id","type":"uint256"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"chain_id","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"bridger","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"factory","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"inflation_params","inputs":[],"outputs":[{"name":"","type":"tuple","components":[{"name":"rate","type":"uint256"},{"name":"finish_time","type":"uint256"}]}]},{"stateMutability":"view","type":"function","name":"last_period","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"total_emissions","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"is_killed","inputs":[],"outputs":[{"name":"","type":"bool"}]}]
38 changes: 36 additions & 2 deletions pages/api/getFactoGauges/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import Web3 from 'web3';
import groupBy from 'lodash.groupby';
import { fn } from 'utils/api';
import gaugeRegistry from 'constants/abis/gauge-registry.json';
import sideChainGauge from 'constants/abis/sidechain-gauge.json';
import sideChainRootGauge from 'constants/abis/sidechain-root-gauge.json';

import multicallAbi from 'constants/abis/multicall.json';
import gaugeControllerAbi from 'constants/abis/gauge_controller.json';
Expand Down Expand Up @@ -83,8 +85,34 @@ export default fn(async ({ blockchainId }) => {
}
}

const weekSeconds = 86400 * 7;
const nowTs = +Date.now() / 1000;
const startOfWeekTs = Math.trunc(nowTs / weekSeconds) * weekSeconds;
const endOfWeekTs = startOfWeekTs + weekSeconds;

/**
* Root gauges with emissions meant for their side gauge, but not passed on to it yet
* (will be passed to side gauge as soon as someone interacts with it). We thus
* use those pending emissions as the basis to calculate apys for this side gauge.
*/
const pendingEmissionsRaw = await multiCall(gaugeList.map((gaugeAddress) => ({
address: gaugeAddress,
abi: sideChainRootGauge,
methodName: 'total_emissions',
metaData: { gaugeAddress },
networkSettings: { web3, multicall2Address: configs.ethereum.multicall2Address },
})));
const pendingEmissions = arrayToHashmap(pendingEmissionsRaw.map(({ data, metaData }) => {
const inflationRate = data / (endOfWeekTs - nowTs);

return [
metaData.gaugeAddress,
inflationRate,
];
}));

calls = []
const gaugeContract = new web3Side.eth.Contract(sideChainGauge, gaugeList[0]);
const gaugeContract = new web3Side.eth.Contract(sideChainGauge, gaugeList[0]);

const gaugeControllerAddress = '0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB'
const gaugeController = new web3.eth.Contract(gaugeControllerAbi, gaugeControllerAddress);
Expand All @@ -94,6 +122,7 @@ export default fn(async ({ blockchainId }) => {
calls.push([gaugeList[i], gaugeContract.methods.name().encodeABI()])
calls.push([gaugeList[i], gaugeContract.methods.symbol().encodeABI()])
calls.push([gaugeList[i], gaugeContract.methods.working_supply().encodeABI()])
calls.push([gaugeList[i], gaugeContract.methods.inflation_rate(startOfWeekTs).encodeABI()])
}
aggGaugecalls = await multicall.methods.aggregate(calls).call();
aggGaugecalls = aggGaugecalls[1]
Expand All @@ -108,10 +137,14 @@ export default fn(async ({ blockchainId }) => {
let symbol = await web3.eth.abi.decodeParameter('string', aggGaugecalls[i])
i += 1
let working_supply = await web3.eth.abi.decodeParameter('uint256', aggGaugecalls[i])
i += 1
let inflation_rate = await web3.eth.abi.decodeParameter('uint256', aggGaugecalls[i])

let hasCrv = false
let gauge_relative_weight;
try {
await gaugeController.methods.gauge_types(gaugeList[gaugeN]).call()
gauge_relative_weight = await gaugeController.methods.gauge_relative_weight(gaugeList[gaugeN]).call()
hasCrv = true
} catch (e) { }

Expand All @@ -134,7 +167,8 @@ export default fn(async ({ blockchainId }) => {
type: 'stable', //we will have a problem detecting this which is used by cur.vote or the voting app to calculate the $ value in the gauge
gauge_data: {
working_supply,
inflation_rate: 0
gauge_relative_weight,
inflation_rate: Number(inflation_rate) || pendingEmissions[gaugeList[gaugeN]],
},
swap_data: {
virtual_price
Expand Down
8 changes: 8 additions & 0 deletions pages/api/getFactoGaugesCrvRewards/[blockchainId].js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { fn } from 'utils/api';
import getFactoGaugesCrvRewardsApiFn from './index';

export default fn(async ({ blockchainId }) => (
getFactoGaugesCrvRewardsApiFn.straightCall({ blockchainId })
), {
maxAge: 60,
});
66 changes: 66 additions & 0 deletions pages/api/getFactoGaugesCrvRewards/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* Returns unboosted CRV APRs for sidechain facto gauges.
*/

import { fn } from 'utils/api';
import getAssetsPrices from 'utils/data/assets-prices';

import getFactoGauges from 'pages/api/getFactoGauges';
import getPools from 'pages/api/getPools';
import configs from 'constants/configs';

export default fn(async ({ blockchainId }) => {
if (typeof blockchainId === 'undefined') blockchainId = 'ethereum'; // Default value

const config = configs[blockchainId];

const { gauges } = await getFactoGauges.straightCall({ blockchainId });
const { poolData: mainPoolData } = await getPools.straightCall({ blockchainId, registryId: 'factory' });
const { poolData: cryptoPoolData } = (
config.getFactoryCryptoRegistryAddress ?
await getPools.straightCall({ blockchainId, registryId: 'factory-crypto' }) :
{ poolData: [] }
);
const poolData = [...mainPoolData, ...cryptoPoolData];

const sideChainGauges = gauges.filter(({
side_chain: isSideChain,
name,
is_killed: isKilled,
}) => (
isSideChain &&
// name.startsWith(`${blockchainId}-`) &&
!isKilled
));

if (sideChainGauges.length === 0) {
throw new Error(`No side gauges data for blockchainId "${blockchainId}"`);
}

const { 'curve-dao-token': crvPrice } = await getAssetsPrices(['curve-dao-token']);

const sideChainGaugesApys = sideChainGauges.map(({
swap,
name,
gauge_data: {
gauge_relative_weight: weight,
inflation_rate: rate,
},
}) => {
const lcAddress = swap.toLowerCase();
const pool = poolData.find(({ address }) => address.toLowerCase() === lcAddress);
if (!pool) throw new Error(`Can't find pool data for swap address "${swap}"`);

const apy = (rate / 1e18) * (weight / 1e18) * (86400 * 365) / pool.usdTotal * 0.4 * crvPrice * 100;

return {
address: lcAddress,
name,
apy,
};
});

return { sideChainGaugesApys };
}, {
maxAge: 60,
});
69 changes: 37 additions & 32 deletions pages/api/getGauges.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,24 +286,24 @@ export default fn(async () => {
type: 'stable',
},
"polygon-a3CRV": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0x445FE580eF8d70FF569aB36e80c647af338db351',
swap_token: '0xE7a24EF0C5e95Ffb0f6684b813A78F2a3AD7D171',
name: 'polygon-a3CRV',
gauge: '0xC48f4653dd6a9509De44c92beb0604BEA3AEe714',
type: 'stable',
side_chain: true
},
"fantom-2pool": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0x27e611fd27b276acbd5ffd632e5eaebec9761e40',
swap_token: '0x27e611fd27b276acbd5ffd632e5eaebec9761e40',
name: 'fantom-2pool',
gauge: '0xb9C05B8EE41FDCbd9956114B3aF15834FDEDCb54',
type: 'stable',
side_chain: true
},
"fantom-geist": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0x0fa949783947Bf6c1b171DB13AEACBB488845B3f',
swap_token: '0x0fa949783947Bf6c1b171DB13AEACBB488845B3f',
name: 'fantom-geist',
gauge: '0xfE1A3dD8b169fB5BF0D5dbFe813d956F39fF6310',
type: 'stable',
Expand All @@ -318,32 +318,33 @@ export default fn(async () => {
is_killed: true
},
"polygon-ren": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0xC2d95EEF97Ec6C17551d45e77B590dc1F9117C67',
swap_token: '0xf8a57c1d3b9629b77b6726a042ca48990A84Fb49',
name: 'polygon-ren',
gauge: '0x488E6ef919C2bB9de535C634a80afb0114DA8F62',
type: 'bitcoin',
side_chain: true
},
"fantom-ren": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0x3eF6A01A0f81D6046290f3e2A8c5b843e738E604',
swap_token: '0x3eF6A01A0f81D6046290f3e2A8c5b843e738E604',
name: 'fantom-ren',
gauge: '0xfDb129ea4b6f557b07BcDCedE54F665b7b6Bc281',
type: 'bitcoin',
side_chain: true
},
"polygon-atricrypto": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0x92577943c7aC4accb35288aB2CC84D75feC330aF',
swap_token: '0xbece5d20A8a104c54183CC316C8286E3F00ffC71',
name: 'polygon-atricrypto',
gauge: '0x060e386eCfBacf42Aa72171Af9EFe17b3993fC4F',
type: 'crypto',
side_chain: true
side_chain: true,
is_killed: true
},
"xdai-3pool": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0x7f90122BF0700F9E7e1F688fe926940E8839F353',
swap_token: '0x1337BedC9D22ecbe766dF105c9623922A27963EC',
name: 'xdai-3pool',
gauge: '0x6C09F6727113543Fd061a721da512B7eFCDD0267',
type: 'stable',
Expand Down Expand Up @@ -443,32 +444,32 @@ export default fn(async () => {
factory: true,
},
"arbitrum-tricrypto": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0x960ea3e3C7FB317332d990873d354E18d7645590',
swap_token: '0x8e0B8c8BB9db49a46697F3a5Bb8A308e744821D2',
name: 'arbitrum-tricrypto',
gauge: '0x9044E12fB1732f88ed0c93cfa5E9bB9bD2990cE5',
type: 'crypto',
side_chain: true
},
"arbitrum-2pool": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0x7f90122bf0700f9e7e1f688fe926940e8839f353',
swap_token: '0x7f90122bf0700f9e7e1f688fe926940e8839f353',
name: 'arbitrum-2pool',
gauge: '0xFf17560d746F85674FE7629cE986E949602EF948',
type: 'stable',
side_chain: true
},
"arbitrum-ren": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0x3E01dD8a5E1fb3481F0F589056b428Fc308AF0Fb',
swap_token: '0x3E01dD8a5E1fb3481F0F589056b428Fc308AF0Fb',
name: 'arbitrum-ren',
gauge: '0x9F86c5142369B1Ffd4223E5A2F2005FC66807894',
type: 'bitcoin',
side_chain: true
},
"fantom-tricrypto": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0x3a1659Ddcf2339Be3aeA159cA010979FB49155FF',
swap_token: '0x3a1659Ddcf2339Be3aeA159cA010979FB49155FF',
name: 'fantom-tricrypto',
gauge: '0x260e4fBb13DD91e187AE992c3435D0cf97172316',
type: 'crypto',
Expand Down Expand Up @@ -508,32 +509,32 @@ export default fn(async () => {
factory: true,
},
"avalanche-a3CRV": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0x7f90122BF0700F9E7e1F688fe926940E8839F353',
swap_token: '0x1337BedC9D22ecbe766dF105c9623922A27963EC',
name: 'avalanche-a3CRV',
gauge: '0xB504b6EB06760019801a91B451d3f7BD9f027fC9',
type: 'stable',
side_chain: true
},
"avalanche-ren": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0x16a7DA911A4DD1d83F3fF066fE28F3C792C50d90',
swap_token: '0xC2b1DF84112619D190193E48148000e3990Bf627',
name: 'avalanche-ren',
gauge: '0x75D05190f35567e79012c2F0a02330D3Ed8a1F74',
type: 'bitcoin',
side_chain: true
},
"avalanche-atricrypto": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0xB755B949C126C04e0348DD881a5cF55d424742B2',
swap_token: '0x1daB6560494B04473A0BE3E7D83CF3Fdf3a51828',
name: 'avalanche-atricrypto',
gauge: '0xa05E565cA0a103FcD999c7A7b8de7Bd15D5f6505',
type: 'crypto',
side_chain: true
},
"harmony-3pool": {
swap: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap_token: '0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c',
swap: '0xC5cfaDA84E902aD92DD40194f0883ad49639b023',
swap_token: '0xC5cfaDA84E902aD92DD40194f0883ad49639b023',
name: 'harmony-3pool',
gauge: '0xf2Cde8c47C20aCbffC598217Ad5FE6DB9E00b163',
type: 'stable',
Expand Down Expand Up @@ -795,6 +796,7 @@ export default fn(async () => {
calls.push([gaugeControllerAddress, gaugeController.methods.get_gauge_weight(gauges[key].gauge).encodeABI()]);
// calls.push([gaugeControllerAddress, gaugeController.methods.gauge_types(gauges[key].gauge).encodeABI()]);
calls.push([gaugeControllerAddress, gaugeController.methods.gauge_relative_weight(gauges[key].gauge).encodeABI()]);
calls.push([gauges[key].gauge, exampleGauge.methods.inflation_rate().encodeABI()]);
}
});

Expand Down Expand Up @@ -846,11 +848,14 @@ export default fn(async () => {
// let gauge_types = web3.eth.abi.decodeParameter('int128', aggcalls[i])
// i += 1
let gauge_relative_weight = web3.eth.abi.decodeParameter('uint256', aggcalls[i])
i += 1
let inflation_rate = web3.eth.abi.decodeParameter('uint256', aggcalls[i])

let gaugeData = {
'get_gauge_weight': get_gauge_weight,
// 'gauge_types': gauge_types,
'gauge_relative_weight': gauge_relative_weight
'gauge_relative_weight': gauge_relative_weight,
inflation_rate,
}
allGaugeDetails.push(gaugeData)
}
Expand Down
2 changes: 2 additions & 0 deletions utils/Calls.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const getContractInstance = memoize((address, abi, library) => (
* If `metaData` is passed alongside any call, returns an array of objects of shape { data, metaData } instead.
*/
const multiCall = async (callsConfig, isDebugging = false) => {
if (callsConfig.length === 0) return [];

const defaultCallConfig = {
// Pass either a contract object (if that contract object is already instantiated and it's easier)
contract: undefined, // e.g. currentContract
Expand Down

0 comments on commit 2a33eb6

Please sign in to comment.