From 0f31b39f7bc5dba33499abca196dda5be47159b1 Mon Sep 17 00:00:00 2001 From: ethzoomer Date: Mon, 13 May 2024 18:14:13 -0500 Subject: [PATCH] Velo/Aero fixes --- dexs/aerodrome-slipstream/index.ts | 78 ++++++++++++++++++++ dexs/aerodrome/index.ts | 110 ++++++++++++++++++++++------- dexs/velodrome-slipstream/index.ts | 56 ++++++++++----- fees/aerodrome/bribes.ts | 33 ++++----- fees/aerodrome/index.ts | 24 +++++-- 5 files changed, 232 insertions(+), 69 deletions(-) create mode 100644 dexs/aerodrome-slipstream/index.ts diff --git a/dexs/aerodrome-slipstream/index.ts b/dexs/aerodrome-slipstream/index.ts new file mode 100644 index 0000000000..3e69a75809 --- /dev/null +++ b/dexs/aerodrome-slipstream/index.ts @@ -0,0 +1,78 @@ +import { FetchOptions, FetchResult, SimpleAdapter } from "../../adapters/types" +import { CHAIN } from "../../helpers/chains" + +const gurar = '0xe521fc2C55AF632cdcC3D69E7EFEd93d56c89015'; +const abis: any = { + "forSwaps": "function forSwaps(uint256 _limit, uint256 _offset) view returns ((address lp, int24 type, address token0, address token1, address factory, uint256 pool_fee)[])" +} + +interface IForSwap { + lp: string; + token0: string; + token1: string; + pool_fee: string; +} + +interface ILog { + address: string; + data: string; + transactionHash: string; + topics: string[]; +} +const event_swap = 'event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick)' + +const fetch = async (timestamp: number, _: any, { api, getLogs, createBalances, }: FetchOptions): Promise => { + const dailyVolume = createBalances() + const dailyFees = createBalances() + const chunkSize = 400; + let currentOffset = 965; // Slipstream launched after ~970 v2 pools were already created + const allForSwaps: IForSwap[] = []; + let unfinished = true; + + while (unfinished) { + const forSwaps: IForSwap[] = (await api.call({ + target: gurar, + params: [chunkSize, currentOffset], + abi: abis.forSwaps, + chain: CHAIN.BASE, + })).filter(t => Number(t.type) > 0).map((e: any) => { + return { + lp: e.lp, + token0: e.token0, + token1: e.token1, + pool_fee: e.pool_fee, + } + }) + + unfinished = forSwaps.length !== 0; + currentOffset += chunkSize; + allForSwaps.push(...forSwaps); + } + + const targets = allForSwaps.map((forSwap: IForSwap) => forSwap.lp) + + const logs: ILog[][] = await getLogs({ + targets, + eventAbi: event_swap, + flatten: false, + }) + + logs.forEach((logs: ILog[], idx: number) => { + const { token1, pool_fee } = allForSwaps[idx] + logs.forEach((log: any) => { + dailyVolume.add(token1, BigInt(Math.abs(Number(log.amount1)))) + dailyFees.add(token1, BigInt( Math.round((((Math.abs(Number(log.amount1))) * Number(pool_fee)) / 1000000)))) // 1% fee represented as pool_fee=10000 + }) + }) + + return { dailyVolume, timestamp, dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees } +} +const adapters: SimpleAdapter = { + adapter: { + [CHAIN.BASE]: { + fetch: fetch as any, + start: 1714743000, + } + } +} +export default adapters; diff --git a/dexs/aerodrome/index.ts b/dexs/aerodrome/index.ts index 6d271e322b..f3274d1c79 100644 --- a/dexs/aerodrome/index.ts +++ b/dexs/aerodrome/index.ts @@ -1,8 +1,12 @@ -import { FetchOptions, FetchResultVolume, SimpleAdapter } from "../../adapters/types" +import { FetchOptions, FetchResult, SimpleAdapter } from "../../adapters/types" import { CHAIN } from "../../helpers/chains" -const gurar = '0x2073D8035bB2b0F2e85aAF5a8732C6f397F9ff9b'; +const sugar = '0xe521fc2C55AF632cdcC3D69E7EFEd93d56c89015'; +const sugarOld = '0x2073D8035bB2b0F2e85aAF5a8732C6f397F9ff9b'; const abis: any = { + "forSwaps": "function forSwaps(uint256 _limit, uint256 _offset) view returns ((address lp, int24 type, address token0, address token1, address factory, uint256 pool_fee)[])" +} +const abisOld: any = { "forSwaps": "function forSwaps() view returns ((address lp, bool stable, address token0, address token1, address factory)[])" } @@ -10,6 +14,7 @@ interface IForSwap { lp: string; token0: string; token1: string; + pool_fee: string; } interface ILog { @@ -20,37 +25,90 @@ interface ILog { } const event_swap = 'event Swap(address indexed sender,address indexed to,uint256 amount0In,uint256 amount1In,uint256 amount0Out,uint256 amount1Out)' -const fetch = async (timestamp: number, _: any, { api, getLogs, createBalances, }: FetchOptions): Promise => { +const fetch = async (timestamp: number, _: any, { api, getLogs, createBalances, }: FetchOptions): Promise => { const dailyVolume = createBalances() - const forSwaps: IForSwap[] = (await api.call({ - target: gurar, - abi: abis.forSwaps, - chain: CHAIN.BASE, - })).map((e: any) => { - return { - lp: e.lp, - token0: e.token0, - token1: e.token1, + const dailyFees = createBalances() + const chunkSize = 400; + let currentOffset = 0; + const allForSwaps: IForSwap[] = []; + let unfinished = true; + + if (timestamp > 1714743000) { + + while (unfinished) { + const forSwaps: IForSwap[] = (await api.call({ + target: sugar, + params: [chunkSize, currentOffset], + abi: abis.forSwaps, + chain: CHAIN.BASE, + })).filter(t => Number(t.type) < 1).map((e: any) => { // Regular v2 pool are types 0 and -1 + return { + lp: e.lp, + token0: e.token0, + token1: e.token1, + pool_fee: e.pool_fee, + } + }); + + unfinished = forSwaps.length !== 0; + currentOffset += chunkSize; + allForSwaps.push(...forSwaps); } - }) - const targets = forSwaps.map((forSwap: IForSwap) => forSwap.lp) + const targets = allForSwaps.map((forSwap: IForSwap) => forSwap.lp) + + const logs: ILog[][] = await getLogs({ + targets, + eventAbi: event_swap, + flatten: false, + }) + + logs.forEach((logs: ILog[], idx: number) => { + const { token0, token1, pool_fee } = allForSwaps[idx] + logs.forEach((log: any) => { + dailyVolume.add(token0, BigInt(Math.abs(Number(log.amount0In)))) + dailyVolume.add(token1, BigInt(Math.abs(Number(log.amount1In)))) + dailyFees.add(token0, BigInt( Math.round((((Math.abs(Number(log.amount0In))) * Number(pool_fee)) / 10000)))) // 1% fee represented as pool_fee=100 + dailyFees.add(token1, BigInt( Math.round((((Math.abs(Number(log.amount1In))) * Number(pool_fee)) / 10000)))) + }) + }) + + return { dailyVolume, timestamp, dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees } + } + else { + const forSwapsOld: IForSwap[] = (await api.call({ + target: sugarOld, + abi: abisOld.forSwaps, + chain: CHAIN.BASE, + })).map((e: any) => { + return { + lp: e.lp, + token0: e.token0, + token1: e.token1, + pool_fee: e.stable ? 5 : 30, // v2 0.05% stable swap fees, 0.3% volatile fees + } + }) - const logs: ILog[][] = await getLogs({ - targets, - eventAbi: event_swap, - flatten: false, - }) + const targets = forSwapsOld.map((forSwap: IForSwap) => forSwap.lp) - logs.forEach((logs: ILog[], idx: number) => { - const { token0, token1 } = forSwaps[idx] - logs.forEach((log: any) => { - dailyVolume.add(token0, log.amount0Out) - dailyVolume.add(token1, log.amount1Out) + const logs: ILog[][] = await getLogs({ + targets, + eventAbi: event_swap, + flatten: false, }) - }) - return { dailyVolume, timestamp } + logs.forEach((logs: ILog[], idx: number) => { + const { token0, token1, pool_fee } = forSwapsOld[idx] + logs.forEach((log: any) => { + dailyVolume.add(token0, log.amount0Out) + dailyVolume.add(token1, log.amount1Out) + dailyFees.add(token0, BigInt( Math.round((((Math.abs(Number(log.amount0Out))) * Number(pool_fee)) / 10000)))) + dailyFees.add(token1, BigInt( Math.round((((Math.abs(Number(log.amount1Out))) * Number(pool_fee)) / 10000)))) + }) + }) + + return { dailyVolume, timestamp, dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees } + } } const adapters: SimpleAdapter = { adapter: { diff --git a/dexs/velodrome-slipstream/index.ts b/dexs/velodrome-slipstream/index.ts index 54f92bfb1d..5bef8012b9 100644 --- a/dexs/velodrome-slipstream/index.ts +++ b/dexs/velodrome-slipstream/index.ts @@ -1,7 +1,8 @@ import { FetchOptions, FetchResult, FetchResultVolume, SimpleAdapter } from "../../adapters/types" import { CHAIN } from "../../helpers/chains" -const gurar = '0xc734656F0112CA18cdcaD424ddd8949F3D4c1DdD'; +const sugarOld = '0x3e532BC1998584fe18e357B5187897ad0110ED3A'; // old Sugar version doesn't properly support pagination +const sugar = '0xdE2aE25FB984dd60C77dcF6489Be9ee6438eC195'; const abis: any = { "forSwaps": "function forSwaps(uint256 _limit, uint256 _offset) view returns ((address lp, int24 type, address token0, address token1, address factory, uint256 pool_fee)[])" } @@ -10,7 +11,7 @@ interface IForSwap { lp: string; token0: string; token1: string; - pool_fee: string + pool_fee: string; } interface ILog { @@ -24,21 +25,40 @@ const event_swap = 'event Swap(address indexed sender, address indexed recipient const fetch = async (timestamp: number, _: any, { api, getLogs, createBalances, }: FetchOptions): Promise => { const dailyVolume = createBalances() const dailyFees = createBalances() - const forSwaps: IForSwap[] = (await api.call({ - target: gurar, - params: [3000, 640], // Slipstream launched after ~650 v2 pools were already created - abi: abis.forSwaps, - chain: CHAIN.OPTIMISM, - })).filter(t => Number(t.type) > 0).map((e: any) => { - return { - lp: e.lp, - token0: e.token0, - token1: e.token1, - pool_fee: e.pool_fee, - } - }) + let chunkSize = 400; + let currentOffset = 630; // Slipstream launched after ~650 v2 pools were already created + const allForSwaps: IForSwap[] = []; + let unfinished = true; + let sugarContract = sugar; + + // before the new Sugar is deployed, we must use the old Sugar contract, and make one large Sugar call + if (timestamp < 1715160600) { + chunkSize = 1800; + currentOffset = 0; + sugarContract = sugarOld; + } - const targets = forSwaps.map((forSwap: IForSwap) => forSwap.lp) + while (unfinished) { + const forSwaps: IForSwap[] = (await api.call({ + target: sugarContract, + params: [chunkSize, currentOffset], // Slipstream launched after ~650 v2 pools were already created + abi: abis.forSwaps, + chain: CHAIN.OPTIMISM, + })).filter(t => Number(t.type) > 0).map((e: any) => { + return { + lp: e.lp, + token0: e.token0, + token1: e.token1, + pool_fee: e.pool_fee, + } + }) + + unfinished = forSwaps.length !== 0; + currentOffset += chunkSize; + allForSwaps.push(...forSwaps); + } + + const targets = allForSwaps.map((forSwap: IForSwap) => forSwap.lp) const logs: ILog[][] = await getLogs({ targets, @@ -47,7 +67,7 @@ const fetch = async (timestamp: number, _: any, { api, getLogs, createBalances, }) logs.forEach((logs: ILog[], idx: number) => { - const { token1, pool_fee } = forSwaps[idx] + const { token1, pool_fee } = allForSwaps[idx] logs.forEach((log: any) => { dailyVolume.add(token1, BigInt(Math.abs(Number(log.amount1)))) dailyFees.add(token1, BigInt( Math.round((((Math.abs(Number(log.amount1))) * Number(pool_fee)) / 1000000)))) // 1% fee represented as pool_fee=10000 @@ -60,7 +80,7 @@ const adapters: SimpleAdapter = { adapter: { [CHAIN.OPTIMISM]: { fetch: fetch as any, - start: 1709686921, + start: 1709724600, } } } diff --git a/fees/aerodrome/bribes.ts b/fees/aerodrome/bribes.ts index 811bb616c4..da243e0481 100644 --- a/fees/aerodrome/bribes.ts +++ b/fees/aerodrome/bribes.ts @@ -1,30 +1,27 @@ -import ADDRESSES from '../../helpers/coreAssets.json' +import * as sdk from "@defillama/sdk"; import { FetchOptions } from '../../adapters/types'; const event_notify_reward = 'event NotifyReward(address indexed from,address indexed reward,uint256 indexed epoch,uint256 amount)'; +const event_geuge_created = 'event GaugeCreated(address indexed poolFactory,address indexed votingRewardsFactory,address indexed gaugeFactory,address pool,address bribeVotingReward,address feeVotingReward,address gauge,address creator)' -const gurar = '0x2073D8035bB2b0F2e85aAF5a8732C6f397F9ff9b'; - -const abis: any = { - "all": "function all(uint256 _limit, uint256 _offset, address _account) view returns ((address lp, string symbol, uint8 decimals, bool stable, uint256 total_supply, address token0, uint256 reserve0, uint256 claimable0, address token1, uint256 reserve1, uint256 claimable1, address gauge, uint256 gauge_total_supply, bool gauge_alive, address fee, address bribe, address factory, uint256 emissions, address emissions_token, uint256 account_balance, uint256 account_earned, uint256 account_staked, uint256 pool_fee, uint256 token0_fees, uint256 token1_fees)[])" -} - -export const fees_bribes = async ({ getLogs, api, createBalances }: FetchOptions)=> { +export const fees_bribes = async ({ getLogs, createBalances, getToBlock }: FetchOptions): Promise => { + const voter = '0x16613524e02ad97eDfeF371bC883F2F5d6C480A5'; const dailyFees = createBalances() - const bribeVotingReward: string[] = (await api.call({ - target: gurar, - params: [1000, 0, ADDRESSES.null], - abi: abis.all, - })).map((e: any) => { - return e.bribe; - }).filter((e: string) => e !== ADDRESSES.null); - const bribe_contracct = [...new Set(bribeVotingReward)]; + const logs_geuge_created = (await getLogs({ + target: voter, + fromBlock: 3200601, + toBlock: await getToBlock(), + eventAbi: event_geuge_created, + cacheInCloud: true, + })) + const bribes_contract: string[] = logs_geuge_created.map((e: any) => e.bribeVotingReward.toLowerCase()); + const logs = await getLogs({ - targets: bribe_contracct, + targets: bribes_contract, eventAbi: event_notify_reward, }) logs.map((e: any) => { dailyFees.add(e.reward, e.amount) }) return dailyFees; -} +} \ No newline at end of file diff --git a/fees/aerodrome/index.ts b/fees/aerodrome/index.ts index 718fc84993..065b5c7f73 100644 --- a/fees/aerodrome/index.ts +++ b/fees/aerodrome/index.ts @@ -4,10 +4,11 @@ import * as sdk from "@defillama/sdk"; import { fees_bribes } from "./bribes"; import { getDexFees } from "../../helpers/dexVolumeLogs"; -const gurar = '0x2073D8035bB2b0F2e85aAF5a8732C6f397F9ff9b'; +const sugar = '0xe521fc2C55AF632cdcC3D69E7EFEd93d56c89015'; const abis: any = { - "forSwaps": "function forSwaps() view returns ((address lp, bool stable, address token0, address token1, address factory)[])" + "forSwaps": "function forSwaps(uint256 _limit, uint256 _offset) view returns ((address lp, int24 type, address token0, address token1, address factory, uint256 pool_fee)[])" } + // defualt abi for multiCall is error some pools const multiCall = async (callN: any) => { return (await sdk.api.abi.multiCall({ @@ -21,14 +22,23 @@ const multiCall = async (callN: any) => { } const fetch = async (timestamp: number, _: ChainBlocks, fetchOptions: FetchOptions): Promise => { - const forSwaps = await sdk.api2.abi.call({ target: gurar, abi: abis.forSwaps, chain: CHAIN.BASE, }) - const pools = forSwaps.map((e: any) => e.lp) + const chunkSize = 500; + let currentOffset = 0; + let unfinished = true; + const allPools: any[] = []; + + while (unfinished) { + const allPoolsChunk = await sdk.api2.abi.call({ target: sugar, abi: abis.forSwaps, params: [chunkSize, currentOffset], chain: CHAIN.BASE, block: "latest", }) + unfinished = allPoolsChunk.length !== 0; + currentOffset += chunkSize; + allPools.push(...allPoolsChunk); + } + + const pools = allPools.map((e: any) => e.lp) fetchOptions.api.multiCall = multiCall const res: any = await getDexFees({ chain: CHAIN.BASE, fromTimestamp: fetchOptions.fromTimestamp, toTimestamp: fetchOptions.toTimestamp, pools, timestamp, fetchOptions }) res.dailyBribesRevenue = await fees_bribes(fetchOptions); - - return res - + return res; } const adapters: SimpleAdapter = { adapter: {