Skip to content

Commit

Permalink
IPOR liquidity mining power up from contracts (#1559)
Browse files Browse the repository at this point in the history
* IPOR liquidity mining power up from contracts

* IPOR set new url

* Set individual urls for each IPOR pool
  • Loading branch information
kris-ipor authored Oct 17, 2024
1 parent 50850c4 commit e686d01
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 59 deletions.
29 changes: 29 additions & 0 deletions src/adaptors/ipor-derivatives/abiV2.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,34 @@ module.exports = {
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "address",
name: "lpToken",
type: "address"
}
],
name: "getPoolPowerUpModifiers",
outputs: [
{
"name": "pwTokenModifier",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "logBase",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "vectorOfCurve",
"type": "uint256",
"internalType": "uint256"
}
],
stateMutability: "view",
type: "function"
},
]
}
116 changes: 57 additions & 59 deletions src/adaptors/ipor-derivatives/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,12 @@ const LP_STATS_ETHEREUM_URL =
'https://api.ipor.io/monitor/liquiditypool-statistics-1';
const LP_STATS_ARBITRUM_URL =
'https://api.ipor.io/monitor/liquiditypool-statistics-42161';
const ARB_AIRDROP_URL = 'https://api.ipor.io/monitor/arb-airdrop';
const WSTETH_AIRDROP_URL = 'https://api.ipor.io/monitor/arb-lido-airdrop';
const COIN_PRICES_URL = 'https://coins.llama.fi/prices/current';

const LM_ADDRESS_ETHEREUM = '0xCC3Fc4C9Ba7f8b8aA433Bc586D390A70560FF366';
const LM_ADDRESS_ARBITRUM = '0xdE645aB0560E5A413820234d9DDED5f4a55Ff6dd';
const IPOR_TOKEN_ETHEREUM = '0x1e4746dc744503b53b4a082cb3607b169a289090';
const IPOR_TOKEN_ARBITRUM = '0x34229b3f16fbcdfa8d8d9d17c0852f9496f4c7bb';
const ARB_TOKEN_ARBITRUM = '0x912ce59144191c1204e64559fe8253a0e49e6548';
const WSTETH_TOKEN_ARBITRUM = '0x5979d7b546e38e414f7e9822514be443a4800529';

const BLOCKS_PER_YEAR = (365 * 24 * 3600) / 12;

Expand All @@ -24,12 +20,6 @@ const apy = async () => {
.assets;
const assetsArbitrum = (await superagent.get(LP_STATS_ARBITRUM_URL)).body
.assets;
const arbAidrdop = (await superagent.get(ARB_AIRDROP_URL)).body;
const arbAirdropLastEpochFinished =
Date.parse(arbAidrdop.epochEnd) < Date.now(); //epochEnd will be date in past when last airdrop epoch will be finished
const wstEthAirdrop = (await superagent.get(WSTETH_AIRDROP_URL)).body;
const wstEthAirdropLastEpochFinished =
Date.parse(wstEthAirdrop.epochEnd) < Date.now(); //epochEnd will be date in past when last airdrop epoch will be finished
const coinKeys = assetsEthereum.map(
(assetData) => 'ethereum:' + assetData.assetAddress
);
Expand All @@ -39,17 +29,12 @@ const apy = async () => {

coinKeys.push('ethereum:' + IPOR_TOKEN_ETHEREUM);
coinKeys.push(...coinKeysArbitrum);
coinKeys.push('arbitrum:' + ARB_TOKEN_ARBITRUM);
coinKeys.push('arbitrum:' + WSTETH_TOKEN_ARBITRUM);
const coinPrices = (
await superagent.get(
`${COIN_PRICES_URL}/${coinKeys.join(',').toLowerCase()}`
)
).body.coins;
const iporTokenUsdPrice = coinPrices['ethereum:' + IPOR_TOKEN_ETHEREUM].price;
const arbTokenUsdPrice = coinPrices['arbitrum:' + ARB_TOKEN_ARBITRUM].price;
const wstethTokenUsdPrice =
coinPrices['arbitrum:' + WSTETH_TOKEN_ARBITRUM].price;

const lpTokenEthereumAddresses = assetsEthereum.map(
(assetData) => assetData.ipTokenAssetAddress
Expand Down Expand Up @@ -80,6 +65,26 @@ const apy = async () => {
])
)
);
const poolPowerUpModifiersEthereum = new Map(
(
await sdk.api.abi.multiCall({
chain: 'ethereum',
abi: liquidityMiningV2Abi.find(
({ name }) => name === 'getPoolPowerUpModifiers'
),
calls: lpTokenEthereumAddresses.map(lpTokenEthereumAddress => {
return {
target: LM_ADDRESS_ETHEREUM,
params: [lpTokenEthereumAddress]
};
}
),
})
).output.map((response) => [
response.input.params[0].toLowerCase(),
response.output,
])
);

const globalStatsArbitrum = new Map(
(
Expand All @@ -102,6 +107,26 @@ const apy = async () => {
])
)
);
const poolPowerUpModifiersArbitrum = new Map(
(
await sdk.api.abi.multiCall({
chain: 'arbitrum',
abi: liquidityMiningV2Abi.find(
({ name }) => name === 'getPoolPowerUpModifiers'
),
calls: lpTokenArbitrumAddresses.map(lpTokenEthereumAddress => {
return {
target: LM_ADDRESS_ARBITRUM,
params: [lpTokenEthereumAddress]
};
}
),
})
).output.map((response) => [
response.input.params[0].toLowerCase(),
response.output,
])
);

const pools = [];

Expand All @@ -124,18 +149,23 @@ const apy = async () => {
const liquidityMiningGlobalStats = globalStatsEthereum.get(
asset.ipTokenAssetAddress.toLowerCase()
);
const vectorOfCurve = poolPowerUpModifiersEthereum.get(
asset.ipTokenAssetAddress.toLowerCase()
).vectorOfCurve / 1e18
const apyReward =
(((liquidityMiningGlobalStats.rewardsPerBlock /
1e8 /
(liquidityMiningGlobalStats.aggregatedPowerUp / 1e18)) *
0.2 * //base powerup
(0.2 + vectorOfCurve) * //base powerup
BLOCKS_PER_YEAR *
iporTokenUsdPrice) /
lpTokenPrice /
coinPrice /
2) * //50% early withdraw fee
100; //percentage

const url = `https://app.ipor.io/zap/ethereum/${asset.asset.toLowerCase()}`;

pools.push({
pool: asset.ipTokenAssetAddress + '-ethereum',
chain: 'Ethereum',
Expand All @@ -146,17 +176,12 @@ const apy = async () => {
apyReward: Number(apyReward),
underlyingTokens: [asset.assetAddress],
rewardTokens: [IPOR_TOKEN_ETHEREUM],
url: url,
});
}

for (const asset of assetsArbitrum) {
const rewardsToken = [IPOR_TOKEN_ARBITRUM];
if (asset.asset === 'wstETH' && !wstEthAirdropLastEpochFinished) {
rewardsToken.push(WSTETH_TOKEN_ARBITRUM);
}
if (!arbAirdropLastEpochFinished) {
rewardsToken.push(ARB_TOKEN_ARBITRUM);
}
const lpApr = asset.periods.find(
({ period }) => period === 'MONTH'
).ipTokenReturnValue;
Expand All @@ -175,51 +200,24 @@ const apy = async () => {
const liquidityMiningGlobalStats = globalStatsArbitrum.get(
asset.ipTokenAssetAddress.toLowerCase()
);
const vectorOfCurve = poolPowerUpModifiersArbitrum.get(
asset.ipTokenAssetAddress.toLowerCase()
).vectorOfCurve / 1e18;
const apyReward =
(((liquidityMiningGlobalStats.rewardsPerBlock /
1e8 /
(liquidityMiningGlobalStats.aggregatedPowerUp / 1e18)) *
0.2 * //base powerup
(0.2 + vectorOfCurve) * //base powerup
BLOCKS_PER_YEAR *
iporTokenUsdPrice) /
lpTokenPrice /
coinPrice /
2) * //50% early withdraw fee
100; //percentage

let apyWstEthAirdrop = 0;
if (asset.asset === 'wstETH' && !wstEthAirdropLastEpochFinished) {
const rewardsWstEthIporRatio = wstEthAirdrop.pools.find(
(assetData) => assetData.asset === asset.asset
).rewardsArbIporRatio;
apyWstEthAirdrop =
(((liquidityMiningGlobalStats.rewardsPerBlock /
1e8 /
(liquidityMiningGlobalStats.aggregatedPowerUp / 1e18)) *
0.2 * //base powerup
BLOCKS_PER_YEAR *
wstethTokenUsdPrice *
rewardsWstEthIporRatio) /
lpTokenPrice /
coinPrice) *
100; //percentage
}

const rewardsArbIporRatio = arbAidrdop.pools.find(
(assetData) => assetData.asset === asset.asset
).rewardsArbIporRatio;
const apyAirdrop = !arbAirdropLastEpochFinished
? (((liquidityMiningGlobalStats.rewardsPerBlock /
1e8 /
(liquidityMiningGlobalStats.aggregatedPowerUp / 1e18)) *
0.2 * //base powerup
BLOCKS_PER_YEAR *
arbTokenUsdPrice *
rewardsArbIporRatio) /
lpTokenPrice /
coinPrice) *
100 //percentage
: 0;
const url = asset.asset === 'USDM'
? `https://app.ipor.io/deposit/arbitrum/${asset.asset.toLowerCase()}`
: `https://app.ipor.io/zap/arbitrum/${asset.asset.toLowerCase()}`;

pools.push({
pool: asset.ipTokenAssetAddress + '-arbitrum',
Expand All @@ -228,9 +226,10 @@ const apy = async () => {
symbol: asset.asset,
tvlUsd: lpBalance * coinPrice,
apyBase: Number(lpApr),
apyReward: Number(apyReward + apyWstEthAirdrop + apyAirdrop),
apyReward: Number(apyReward),
underlyingTokens: [asset.assetAddress],
rewardTokens: rewardsToken,
url: url,
});
}

Expand All @@ -239,6 +238,5 @@ const apy = async () => {

module.exports = {
timetravel: false,
apy: apy,
url: 'https://app.ipor.io/pools',
apy: apy
};

0 comments on commit e686d01

Please sign in to comment.