From 5294c2210f8b6a918ba92bba87a502ea1cfa6ffa Mon Sep 17 00:00:00 2001 From: webmass Date: Fri, 22 Nov 2024 17:21:24 +0400 Subject: [PATCH] Inverse: add sDOLA & sINV --- .../inverse-finance-firm/ERC4626.json | 461 ++++++++++++++++++ src/adaptors/inverse-finance-firm/index.js | 127 +++++ 2 files changed, 588 insertions(+) create mode 100644 src/adaptors/inverse-finance-firm/ERC4626.json diff --git a/src/adaptors/inverse-finance-firm/ERC4626.json b/src/adaptors/inverse-finance-firm/ERC4626.json new file mode 100644 index 0000000000..90dcd58ec3 --- /dev/null +++ b/src/adaptors/inverse-finance-firm/ERC4626.json @@ -0,0 +1,461 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [{ "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "name": "_spender", "type": "address" }, + { "name": "_value", "type": "uint256" } + ], + "name": "approve", + "outputs": [{ "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [{ "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" }, + { "name": "_value", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [{ "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [{ "name": "", "type": "uint8" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "name": "_owner", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "name": "balance", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [{ "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "name": "_to", "type": "address" }, + { "name": "_value", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "name": "_owner", "type": "address" }, + { "name": "_spender", "type": "address" } + ], + "name": "allowance", + "outputs": [{ "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { "payable": true, "stateMutability": "payable", "type": "fallback" }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "name": "owner", "type": "address" }, + { "indexed": true, "name": "spender", "type": "address" }, + { "indexed": false, "name": "value", "type": "uint256" } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "name": "from", "type": "address" }, + { "indexed": true, "name": "to", "type": "address" }, + { "indexed": false, "name": "value", "type": "uint256" } + ], + "name": "Transfer", + "type": "event" + }, + { + "name": "asset", + "type": "function", + "stateMutability": "view", + "inputs": [], + "outputs": [ + { + "name": "assetTokenAddress", + "type": "address" + } + ] + }, + { + "name": "totalAssets", + "type": "function", + "stateMutability": "view", + "inputs": [], + "outputs": [ + { + "name": "totalManagedAssets", + "type": "uint256" + } + ] + }, + { + "name": "convertToShares", + "type": "function", + "stateMutability": "view", + "inputs": [ + { + "name": "assets", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "shares", + "type": "uint256" + } + ] + }, + { + "name": "convertToAssets", + "type": "function", + "stateMutability": "view", + "inputs": [ + { + "name": "shares", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "assets", + "type": "uint256" + } + ] + }, + { + "name": "maxDeposit", + "type": "function", + "stateMutability": "view", + "inputs": [ + { + "name": "receiver", + "type": "address" + } + ], + "outputs": [ + { + "name": "maxAssets", + "type": "uint256" + } + ] + }, + { + "name": "previewDeposit", + "type": "function", + "stateMutability": "view", + "inputs": [ + { + "name": "assets", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "shares", + "type": "uint256" + } + ] + }, + { + "name": "deposit", + "type": "function", + "stateMutability": "nonpayable", + "inputs": [ + { + "name": "assets", + "type": "uint256" + }, + { + "name": "receiver", + "type": "address" + } + ], + "outputs": [ + { + "name": "shares", + "type": "uint256" + } + ] + }, + { + "name": "maxMint", + "type": "function", + "stateMutability": "view", + "inputs": [ + { + "name": "receiver", + "type": "address" + } + ], + "outputs": [ + { + "name": "maxShares", + "type": "uint256" + } + ] + }, + { + "name": "previewMint", + "type": "function", + "stateMutability": "view", + "inputs": [ + { + "name": "shares", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "assets", + "type": "uint256" + } + ] + }, + { + "name": "mint", + "type": "function", + "stateMutability": "nonpayable", + "inputs": [ + { + "name": "shares", + "type": "uint256" + }, + { + "name": "receiver", + "type": "address" + } + ], + "outputs": [ + { + "name": "assets", + "type": "uint256" + } + ] + }, + { + "name": "maxWithdraw", + "type": "function", + "stateMutability": "view", + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "outputs": [ + { + "name": "maxAssets", + "type": "uint256" + } + ] + }, + { + "name": "previewWithdraw", + "type": "function", + "stateMutability": "view", + "inputs": [ + { + "name": "assets", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "shares", + "type": "uint256" + } + ] + }, + { + "name": "withdraw", + "type": "function", + "stateMutability": "nonpayable", + "inputs": [ + { + "name": "assets", + "type": "uint256" + }, + { + "name": "receiver", + "type": "address" + }, + { + "name": "owner", + "type": "address" + } + ], + "outputs": [ + { + "name": "shares", + "type": "uint256" + } + ] + }, + { + "name": "maxRedeem", + "type": "function", + "stateMutability": "view", + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "outputs": [ + { + "name": "maxShares", + "type": "uint256" + } + ] + }, + { + "name": "previewRedeem", + "type": "function", + "stateMutability": "view", + "inputs": [ + { + "name": "shares", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "assets", + "type": "uint256" + } + ] + }, + { + "name": "redeem", + "type": "function", + "stateMutability": "nonpayable", + "inputs": [ + { + "name": "shares", + "type": "uint256" + }, + { + "name": "receiver", + "type": "address" + }, + { + "name": "owner", + "type": "address" + } + ], + "outputs": [ + { + "name": "assets", + "type": "uint256" + } + ] + }, + { + "name": "Deposit", + "type": "event", + "inputs": [ + { + "name": "_caller", + "indexed": true, + "type": "address" + }, + { + "name": "owner", + "indexed": true, + "type": "address" + }, + { + "name": "assets", + "indexed": false, + "type": "uint256" + }, + { + "name": "shares", + "indexed": false, + "type": "uint256" + } + ] + }, + { + "name": "Withdraw", + "type": "event", + "inputs": [ + { + "name": "_caller", + "indexed": true, + "type": "address" + }, + { + "name": "receiver", + "indexed": true, + "type": "address" + }, + { + "name": "owner", + "indexed": true, + "type": "address" + }, + { + "name": "assets", + "indexed": false, + "type": "uint256" + }, + { + "name": "shares", + "indexed": false, + "type": "uint256" + } + ] + } + ] + \ No newline at end of file diff --git a/src/adaptors/inverse-finance-firm/index.js b/src/adaptors/inverse-finance-firm/index.js index 97b2d35ad3..e48e802bd7 100644 --- a/src/adaptors/inverse-finance-firm/index.js +++ b/src/adaptors/inverse-finance-firm/index.js @@ -5,6 +5,7 @@ const BigNumber = require('bignumber.js'); const utils = require('../utils'); const abi = require('./abi'); const path = require('path'); +const ERC4626abi = require('./ERC4626.json'); require('dotenv').config({ path: path.resolve(__dirname, '../../../config.env'), @@ -13,11 +14,26 @@ require('dotenv').config({ const firmStart = 16159015; const DBR = '0xAD038Eb671c44b853887A7E32528FaB35dC5D710'; const DOLA = '0x865377367054516e17014CcdED1e7d814EDC9ce4'; +const INV = '0x41D5D79431A913C4aE7d69a668ecdfE5fF9DFB68'; +const SINV_ADDRESS = '0x08d23468A467d2bb86FaE0e32F247A26C7E2e994'; +const SDOLA_ADDRESS = '0xb45ad160634c528Cc3D2926d9807104FA3157305'; +const TOKENS_VIEWER = '0x826bBeB1DBd9aA36CD44538CC45Dcf9E93BDA574'; +const ONE_DAY_MS = 86400000; +const WEEKS_PER_YEAR = 365 / 7; const provider = new ethers.providers.JsonRpcProvider( process.env.ALCHEMY_CONNECTION_ETHEREUM ); +const getWeekIndexUtc = (ts) => { + const d = ts ? new Date(ts) : new Date(); + const weekFloat = Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), 0, 0, 0) / (ONE_DAY_MS * 7); + return Math.floor(weekFloat); +} + +const aprToApy = (apr, compoundingsPerYear) => + !compoundingsPerYear ? apr : (Math.pow(1 + (apr / 100) / compoundingsPerYear, compoundingsPerYear) - 1) * 100; + const l1TokenPrices = async (l1TokenAddrs) => { const l1TokenQuery = l1TokenAddrs.map((addr) => `ethereum:${addr}`).join(); const data = await utils.getData( @@ -62,6 +78,7 @@ const getFirmEscrowsWithMarket = async (markets, provider) => { return escrowsWithMarkets; }; + const main = async () => { const balances = {}; @@ -127,6 +144,8 @@ const main = async () => { }) ).output; + const weekIndex = getWeekIndexUtc(); + const allLiquidity = ( await sdk.api.abi.multiCall({ chain: 'ethereum', @@ -182,6 +201,114 @@ const main = async () => { }; }); + // sDOLA + const sdolaData = ( + await Promise.all([ + sdk.api.abi.multiCall( + { + chain: 'ethereum', + calls: [ + { + target: SDOLA_ADDRESS, + params: [], + }, + ], + abi: 'uint:totalAssets', + } + ), + sdk.api.abi.multiCall( + { + chain: 'ethereum', + calls: [ + { + target: SDOLA_ADDRESS, + params: [weekIndex-1], + }, + ], + abi: 'uint:weeklyRevenue', + } + ), + ]) + ).output; + + const sDolaTotalAssets = Number(sdolaData[0].output) / 1e18; + const sDolaPastWeekRevenue = Number(sdolaData[1].output) / 1e18; + const sDOLAapr = sDolaTotalAssets > 0 ? (sDolaPastWeekRevenue * WEEKS_PER_YEAR) / sDolaTotalAssets * 100 : 0; + + // add sDOLA + pools.push({ + pool: `sDOLA`, + chain: 'Ethereum', + project: 'inverse-finance-firm', + mintedCoin: 'sDOLA', + symbol: 'sDOLA', + tvlUsd: sDolaTotalAssets * prices[DOLA].price, + apyBase: aprToApy(sDOLAapr, WEEKS_PER_YEAR), + underlyingTokens: [DOLA], + poolMeta: 'Yield-Bearing stable', + url: 'https://inverse.finance/sDOLA', + }); + + // sINV + const sinvData = ( + await Promise.all([ + sdk.api.abi.multiCall( + { + chain: 'ethereum', + calls: [ + { + target: SINV_ADDRESS, + params: [], + }, + ], + abi: 'uint:totalAssets', + } + ), + sdk.api.abi.multiCall( + { + chain: 'ethereum', + calls: [ + { + target: SINV_ADDRESS, + params: [], + }, + ], + abi: 'uint:pastPeriodRevenue', + } + ), + sdk.api.abi.multiCall( + { + chain: 'ethereum', + calls: [ + { + target: TOKENS_VIEWER, + params: [], + }, + ], + abi: 'uint:getDbrApr', + } + ), + ]) + ).output; + + const sInvTotalAssets = Number(sinvData[0].output) / 1e18; + const sinvPastWeekRevenue = Number(sinvData[1].output) / 1e18; + const sINVapr = sDolaTotalAssets > 0 ? (sinvPastWeekRevenue * WEEKS_PER_YEAR) / sInvTotalAssets * 100 : 0; + const dbrApr = Number(sinvData[2].output) / 1e18; + + // add sINV + pools.push({ + pool: `sINV`, + chain: 'Ethereum', + project: 'inverse-finance-firm', + mintedCoin: 'sINV', + symbol: 'sINV', + tvlUsd: sInvTotalAssets * prices[INV].price, + apyBase: aprToApy(sINVapr, WEEKS_PER_YEAR), + underlyingTokens: [INV], + url: 'https://inverse.finance/sINV', + }); + return utils.removeDuplicates(pools.filter((p) => utils.keepFinite(p))); };