From bbb3e582efbcd7c7bf117554669a759e6b58ed9f Mon Sep 17 00:00:00 2001 From: 0xpeluche <0xpeluche@protonmail.com> Date: Thu, 25 Jul 2024 17:19:22 +0200 Subject: [PATCH 1/3] wip --- fees/silo-finance/index.ts | 177 +++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 fees/silo-finance/index.ts diff --git a/fees/silo-finance/index.ts b/fees/silo-finance/index.ts new file mode 100644 index 0000000000..56e77f4b52 --- /dev/null +++ b/fees/silo-finance/index.ts @@ -0,0 +1,177 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +type IFactory = { + address: string; + block: number; +}; + +type ISilo = { + lens: string; + factory: IFactory | IFactory[]; +}; + +type IAddress = { + [s: string | Chain]: ISilo[]; +}; + +// const silo: IAddress = { +// [CHAIN.ETHEREUM]: ["0x0e466FC22386997daC23D1f89A43ecb2CB1e76E9","0x32a4Bcd8DEa5E18a12a50584682f8E4B77fFF2DF"], +// [CHAIN.ARBITRUM]: ["0xBDb843c7a7e48Dc543424474d7Aa63b61B5D9536"], +// [CHAIN.OPTIMISM]: ["0xd3De080436b9d38DC315944c16d89C050C414Fed"], +// [CHAIN.BASE]: ["0x196D312fd81412B6443620Ca81B41103b4E123FD"], +// }; + +const silo: IAddress = { + [CHAIN.ETHEREUM]: [ + { + lens: "0x0e466FC22386997daC23D1f89A43ecb2CB1e76E9", + factory: [ + { + address: "0x4D919CEcfD4793c0D47866C8d0a02a0950737589", + block: 15307294, + }, + { + address: "0x6d4A256695586F61b77B09bc3D28333A91114d5a", + block: 17391885, + }, + ], + }, + { + lens: "0x32a4Bcd8DEa5E18a12a50584682f8E4B77fFF2DF", + factory: { + address: "0x2c0fA05281730EFd3ef71172d8992500B36b56eA", + block: 17782576, + }, + }, + ], + // [CHAIN.ARBITRUM]: [ + // { + // lens: "0xBDb843c7a7e48Dc543424474d7Aa63b61B5D9536", + // factory: { + // address: "0x4166487056A922D784b073d4d928a516B074b719", + // block: 51894508, + // }, + // }, + // ], + // [CHAIN.OPTIMISM]: [ + // { + // lens: "0xd3De080436b9d38DC315944c16d89C050C414Fed", + // factory: { + // address: "0x6B14c4450a29Dd9562c20259eBFF67a577b540b9", + // block: 120480601, + // }, + // }, + // ], + // [CHAIN.BASE]: [ + // { + // lens: "0x196D312fd81412B6443620Ca81B41103b4E123FD", + // factory: { + // address: "0x408822E4E8682413666809b0655161093cd36f2b", + // block: 16262586, + // }, + // }, + // ], +}; + +const fallbackBlacklist: string[] = [ + "0x6543ee07cf5dd7ad17aeecf22ba75860ef3bbaaa", +]; + +async function getSilos(silos: ISilo[], { getLogs }: FetchOptions) { + const logs: any = []; + for (const { factory } of silos) { + if (Array.isArray(factory)) { + for (const { address, block } of factory) { + const logChunk = await getLogs({ + target: address, + fromBlock: block, + topic: "NewSiloCreated(address,address,uint128)", + }); + logs.push([...logs, ...logChunk]); + } + } else { + const { address, block } = factory; + console.log(`Address: ${address}, Block: ${block}`); + } + } + + console.log(logs); + + // for (let factory of config[chain].factories) { + // const { SILO_FACTORY, START_BLOCK } = factory; + // let logChunk = await getLogs({ + // api, + // target: SILO_FACTORY, + // fromBlock: START_BLOCK, + // topic: "NewSiloCreated(address,address,uint128)", + // }); + // logs = [...logs, ...logChunk]; + // } + + // return logs + // .map((log) => `0x${log.topics[1].substring(26)}`) + // .filter( + // (address) => fallbackBlacklist.indexOf(address.toLowerCase()) === -1 + // ); +} + +const fetch = async ( + options: FetchOptions, + silos: ISilo[] +): Promise => { + const dailyFees = options.createBalances(); + const test = await getSilos(silos, options); + + // console.log(silo); + + return { dailyFees }; +}; + +const adapter: Adapter = { + adapter: { + [CHAIN.ETHEREUM]: { + fetch: (options: FetchOptions) => fetch(options, silo[CHAIN.ETHEREUM]), + start: 1668812400, + }, + }, + version: 2, +}; + +export default adapter; + +// const config = { +// ethereum: { +// factories: [ +// { +// START_BLOCK: 15307294, +// SILO_FACTORY: '0x4D919CEcfD4793c0D47866C8d0a02a0950737589', // Silo Ethereum (Original) +// }, +// { +// START_BLOCK: 17391885, +// SILO_FACTORY: '0x6d4A256695586F61b77B09bc3D28333A91114d5a' // Silo Ethereum (Convex Factory) +// }, +// { +// START_BLOCK: 17782576, +// SILO_FACTORY: '0x2c0fA05281730EFd3ef71172d8992500B36b56eA' // Silo Ethereum (LLAMA Edition) +// } +// ] +// }, +// arbitrum: { +// factories: [ +// { +// START_BLOCK: 51894508, +// SILO_FACTORY: '0x4166487056A922D784b073d4d928a516B074b719', // Silo Arbitrum (Original) +// } +// ] +// }, +// optimism: { +// factories: [ +// { +// START_BLOCK: 120480601, +// SILO_FACTORY: '0x6B14c4450a29Dd9562c20259eBFF67a577b540b9', // Silo Optimism (Original) +// } +// ] +// }, +// } From fa2be1669badf172f91f12d1027db08d98431934 Mon Sep 17 00:00:00 2001 From: 0xpeluche <0xpeluche@protonmail.com> Date: Thu, 25 Jul 2024 18:57:52 +0200 Subject: [PATCH 2/3] feat: Adapter Silo-finance totalFees --- fees/silo-finance/index.ts | 255 +++++++++++++++++++++---------------- 1 file changed, 146 insertions(+), 109 deletions(-) diff --git a/fees/silo-finance/index.ts b/fees/silo-finance/index.ts index 56e77f4b52..44422120c3 100644 --- a/fees/silo-finance/index.ts +++ b/fees/silo-finance/index.ts @@ -10,19 +10,13 @@ type IFactory = { type ISilo = { lens: string; factory: IFactory | IFactory[]; + silos?: { silo: string; assets: string[] }[]; }; type IAddress = { [s: string | Chain]: ISilo[]; }; -// const silo: IAddress = { -// [CHAIN.ETHEREUM]: ["0x0e466FC22386997daC23D1f89A43ecb2CB1e76E9","0x32a4Bcd8DEa5E18a12a50584682f8E4B77fFF2DF"], -// [CHAIN.ARBITRUM]: ["0xBDb843c7a7e48Dc543424474d7Aa63b61B5D9536"], -// [CHAIN.OPTIMISM]: ["0xd3De080436b9d38DC315944c16d89C050C414Fed"], -// [CHAIN.BASE]: ["0x196D312fd81412B6443620Ca81B41103b4E123FD"], -// }; - const silo: IAddress = { [CHAIN.ETHEREUM]: [ { @@ -46,132 +40,175 @@ const silo: IAddress = { }, }, ], - // [CHAIN.ARBITRUM]: [ - // { - // lens: "0xBDb843c7a7e48Dc543424474d7Aa63b61B5D9536", - // factory: { - // address: "0x4166487056A922D784b073d4d928a516B074b719", - // block: 51894508, - // }, - // }, - // ], - // [CHAIN.OPTIMISM]: [ - // { - // lens: "0xd3De080436b9d38DC315944c16d89C050C414Fed", - // factory: { - // address: "0x6B14c4450a29Dd9562c20259eBFF67a577b540b9", - // block: 120480601, - // }, - // }, - // ], - // [CHAIN.BASE]: [ - // { - // lens: "0x196D312fd81412B6443620Ca81B41103b4E123FD", - // factory: { - // address: "0x408822E4E8682413666809b0655161093cd36f2b", - // block: 16262586, - // }, - // }, - // ], + [CHAIN.ARBITRUM]: [ + { + lens: "0xBDb843c7a7e48Dc543424474d7Aa63b61B5D9536", + factory: { + address: "0x4166487056A922D784b073d4d928a516B074b719", + block: 51894508, + }, + }, + ], + [CHAIN.OPTIMISM]: [ + { + lens: "0xd3De080436b9d38DC315944c16d89C050C414Fed", + factory: { + address: "0x6B14c4450a29Dd9562c20259eBFF67a577b540b9", + block: 120480601, + }, + }, + ], + [CHAIN.BASE]: [ + { + lens: "0x196D312fd81412B6443620Ca81B41103b4E123FD", + factory: { + address: "0x408822E4E8682413666809b0655161093cd36f2b", + block: 16262586, + }, + }, + ], }; -const fallbackBlacklist: string[] = [ - "0x6543ee07cf5dd7ad17aeecf22ba75860ef3bbaaa", -]; - -async function getSilos(silos: ISilo[], { getLogs }: FetchOptions) { +async function getSilos( + silos: ISilo[], + { getLogs }: FetchOptions +): Promise { const logs: any = []; + + const fetchLogsFromFactory = async (address: string, block: number) => { + const logChunk = await getLogs({ + target: address, + fromBlock: block, + eventAbi: + "event NewSiloCreated(address indexed silo, address indexed asset, uint128 version)", + }); + + logs.push(logChunk.map((result) => result[0])); + }; + for (const { factory } of silos) { if (Array.isArray(factory)) { for (const { address, block } of factory) { - const logChunk = await getLogs({ - target: address, - fromBlock: block, - topic: "NewSiloCreated(address,address,uint128)", - }); - logs.push([...logs, ...logChunk]); + await fetchLogsFromFactory(address, block); } } else { const { address, block } = factory; - console.log(`Address: ${address}, Block: ${block}`); + await fetchLogsFromFactory(address, block); } } - console.log(logs); - - // for (let factory of config[chain].factories) { - // const { SILO_FACTORY, START_BLOCK } = factory; - // let logChunk = await getLogs({ - // api, - // target: SILO_FACTORY, - // fromBlock: START_BLOCK, - // topic: "NewSiloCreated(address,address,uint128)", - // }); - // logs = [...logs, ...logChunk]; - // } - - // return logs - // .map((log) => `0x${log.topics[1].substring(26)}`) - // .filter( - // (address) => fallbackBlacklist.indexOf(address.toLowerCase()) === -1 - // ); + return silos.map((silo, index) => ({ + ...silo, + silos: logs[index]?.map((siloAddress: string) => ({ + silo: siloAddress, + assets: [], + })), + })); } -const fetch = async ( - options: FetchOptions, - silos: ISilo[] -): Promise => { - const dailyFees = options.createBalances(); - const test = await getSilos(silos, options); +async function getSilosAssets( + silos: ISilo[], + { api }: FetchOptions +): Promise { + const siloAddresses = silos.flatMap((silo) => + (silo.silos || []).map((s) => ({ target: s.silo })) + ); + + const assetsInSilosRes = await api.multiCall({ + calls: siloAddresses, + abi: "function getAssets() view returns (address[] assets)", + }); + + const assetsMap: { [key: string]: string[] } = {}; + siloAddresses.forEach((call, index) => { + assetsMap[call.target] = assetsInSilosRes[index]; + }); + + return silos.map((silo) => ({ + ...silo, + silos: (silo.silos || []).map((s) => ({ + silo: s.silo, + assets: assetsMap[s.silo] || [], + })), + })); +} - // console.log(silo); +async function getSilosFeesStorage( + rawSilos: ISilo[], + { api }: FetchOptions +): Promise<{ asset: string; fee: bigint }[]> { + const calls = rawSilos.flatMap((silo) => + (silo.silos || []).flatMap(({ silo: siloAddress, assets }) => + assets.map((asset) => ({ + target: silo.lens, + params: [siloAddress, asset], + })) + ) + ); + + const assetsInSilosRes = await api.multiCall({ + calls: calls, + abi: "function protocolFees(address _silo, address _asset) view returns (uint256)", + }); + + const feesMap: { [key: string]: { [key: string]: bigint } } = {}; + calls.forEach((call, index) => { + const [siloAddress, asset] = call.params; + if (!feesMap[siloAddress]) { + feesMap[siloAddress] = {}; + } + feesMap[siloAddress][asset] = assetsInSilosRes[index]; + }); + + const results: { asset: string; fee: bigint }[] = []; + rawSilos.forEach((silo) => { + (silo.silos || []).forEach((s) => { + s.assets.forEach((asset) => { + const fee = feesMap[s.silo]?.[asset] || 0n; + results.push({ asset, fee }); + }); + }); + }); + + return results; +} - return { dailyFees }; -}; +async function fetch( + options: FetchOptions, + rawSilos: ISilo[] +): Promise { + const totalFees = options.createBalances(); + const rawSiloWithAddresses = await getSilos(rawSilos, options); + const siloWithAssets = await getSilosAssets(rawSiloWithAddresses, options); + const feesInSilos = await getSilosFeesStorage(siloWithAssets, options); + + feesInSilos.forEach(({ asset, fee }) => { + totalFees.add(asset, fee); + }); + + return { totalFees }; +} const adapter: Adapter = { adapter: { [CHAIN.ETHEREUM]: { fetch: (options: FetchOptions) => fetch(options, silo[CHAIN.ETHEREUM]), - start: 1668812400, + start: 1660150409, + }, + [CHAIN.ARBITRUM]: { + fetch: (options: FetchOptions) => fetch(options, silo[CHAIN.ARBITRUM]), + start: 1683046409, + }, + [CHAIN.OPTIMISM]: { + fetch: (options: FetchOptions) => fetch(options, silo[CHAIN.OPTIMISM]), + start: 1716656009, + }, + [CHAIN.BASE]: { + fetch: (options: FetchOptions) => fetch(options, silo[CHAIN.BASE]), + start: 1719420809, }, }, version: 2, }; export default adapter; - -// const config = { -// ethereum: { -// factories: [ -// { -// START_BLOCK: 15307294, -// SILO_FACTORY: '0x4D919CEcfD4793c0D47866C8d0a02a0950737589', // Silo Ethereum (Original) -// }, -// { -// START_BLOCK: 17391885, -// SILO_FACTORY: '0x6d4A256695586F61b77B09bc3D28333A91114d5a' // Silo Ethereum (Convex Factory) -// }, -// { -// START_BLOCK: 17782576, -// SILO_FACTORY: '0x2c0fA05281730EFd3ef71172d8992500B36b56eA' // Silo Ethereum (LLAMA Edition) -// } -// ] -// }, -// arbitrum: { -// factories: [ -// { -// START_BLOCK: 51894508, -// SILO_FACTORY: '0x4166487056A922D784b073d4d928a516B074b719', // Silo Arbitrum (Original) -// } -// ] -// }, -// optimism: { -// factories: [ -// { -// START_BLOCK: 120480601, -// SILO_FACTORY: '0x6B14c4450a29Dd9562c20259eBFF67a577b540b9', // Silo Optimism (Original) -// } -// ] -// }, -// } From 02e21368dca3ab6e593f9992af58198edf6eb2c1 Mon Sep 17 00:00:00 2001 From: 0xpeluche <0xpeluche@protonmail.com> Date: Fri, 26 Jul 2024 13:49:20 +0200 Subject: [PATCH 3/3] add daily fees --- fees/silo-finance/index.ts | 66 +++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/fees/silo-finance/index.ts b/fees/silo-finance/index.ts index 44422120c3..6e8aed81ed 100644 --- a/fees/silo-finance/index.ts +++ b/fees/silo-finance/index.ts @@ -2,6 +2,11 @@ import { Chain } from "@defillama/sdk/build/general"; import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; +type FeeResult = { + asset: string; + fee: bigint; +}; + type IFactory = { address: string; block: number; @@ -135,8 +140,11 @@ async function getSilosAssets( async function getSilosFeesStorage( rawSilos: ISilo[], - { api }: FetchOptions -): Promise<{ asset: string; fee: bigint }[]> { + { fromApi, toApi }: FetchOptions +): Promise<{ totalFeesResults: FeeResult[]; dailyFeesResults: FeeResult[] }> { + const totalFeesResults: FeeResult[] = []; + const dailyFeesResults: FeeResult[] = []; + const calls = rawSilos.flatMap((silo) => (silo.silos || []).flatMap(({ silo: siloAddress, assets }) => assets.map((asset) => ({ @@ -146,31 +154,30 @@ async function getSilosFeesStorage( ) ); - const assetsInSilosRes = await api.multiCall({ - calls: calls, - abi: "function protocolFees(address _silo, address _asset) view returns (uint256)", - }); + const [prevFeesInSilosRes, currFeesInSilosRes] = await Promise.all([ + fromApi.multiCall({ + calls: calls, + abi: "function protocolFees(address _silo, address _asset) view returns (uint256)", + permitFailure: true, + }), + toApi.multiCall({ + calls: calls, + abi: "function protocolFees(address _silo, address _asset) view returns (uint256)", + permitFailure: true, + }), + ]); - const feesMap: { [key: string]: { [key: string]: bigint } } = {}; calls.forEach((call, index) => { - const [siloAddress, asset] = call.params; - if (!feesMap[siloAddress]) { - feesMap[siloAddress] = {}; - } - feesMap[siloAddress][asset] = assetsInSilosRes[index]; - }); + const [_siloAddress, asset] = call.params; + const prevFee = prevFeesInSilosRes[index]; + const currFee = currFeesInSilosRes[index]; - const results: { asset: string; fee: bigint }[] = []; - rawSilos.forEach((silo) => { - (silo.silos || []).forEach((s) => { - s.assets.forEach((asset) => { - const fee = feesMap[s.silo]?.[asset] || 0n; - results.push({ asset, fee }); - }); - }); + if (!prevFee || !currFee) return; + totalFeesResults.push({ asset, fee: currFee }); + dailyFeesResults.push({ asset, fee: BigInt(currFee - prevFee) }); }); - return results; + return { totalFeesResults, dailyFeesResults }; } async function fetch( @@ -178,15 +185,24 @@ async function fetch( rawSilos: ISilo[] ): Promise { const totalFees = options.createBalances(); + const dailyFees = options.createBalances(); + const rawSiloWithAddresses = await getSilos(rawSilos, options); const siloWithAssets = await getSilosAssets(rawSiloWithAddresses, options); - const feesInSilos = await getSilosFeesStorage(siloWithAssets, options); + const { totalFeesResults, dailyFeesResults } = await getSilosFeesStorage( + siloWithAssets, + options + ); - feesInSilos.forEach(({ asset, fee }) => { + totalFeesResults.forEach(({ asset, fee }) => { totalFees.add(asset, fee); }); - return { totalFees }; + dailyFeesResults.forEach(({ asset, fee }) => { + dailyFees.add(asset, fee); + }); + + return { totalFees, dailyFees }; } const adapter: Adapter = {