From ec494726c750e684d7cfd2e5c31af3bb382d0cd5 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Mon, 19 Jun 2023 17:50:29 -0400 Subject: [PATCH 01/52] feat: price feed mappings including native btc price --- deployment/deployment.json | 30 + schema-lending.graphql | 1 + .../_reference_/src/prices/common/utils.ts | 3 + .../_reference_/src/prices/config/goerli.ts | 122 + subgraphs/ebtc/.gitignore | 2 + subgraphs/ebtc/NOTES.md | 22 + subgraphs/ebtc/README.md | 28 + subgraphs/ebtc/abis/PriceFeed.json | 260 +++ subgraphs/ebtc/abis/Prices/AaveOracle.json | 159 ++ .../ebtc/abis/Prices/Calculations/Curve.json | 143 ++ .../abis/Prices/Calculations/SushiSwap.json | 137 ++ subgraphs/ebtc/abis/Prices/ChainLink.json | 530 +++++ subgraphs/ebtc/abis/Prices/Curve/Pool.json | 916 ++++++++ .../ebtc/abis/Prices/Curve/Registry.json | 337 +++ subgraphs/ebtc/abis/Prices/ERC20.json | 828 +++++++ .../ebtc/abis/Prices/Uniswap/Factory.json | 125 + subgraphs/ebtc/abis/Prices/Uniswap/Pair.json | 461 ++++ .../ebtc/abis/Prices/Uniswap/Router.json | 398 ++++ subgraphs/ebtc/abis/Prices/YearnLens.json | 174 ++ subgraphs/ebtc/package.json | 6 + .../ebtc-goerli/configurations.json | 61 + .../ebtc/config/templates/ebtc.template.yaml | 57 + subgraphs/ebtc/schema.graphql | 2012 +++++++++++++++++ subgraphs/ebtc/src/constants.mustache | 42 + subgraphs/ebtc/src/entities/token.ts | 64 + subgraphs/ebtc/src/mapping/PriceFeed.ts | 12 + subgraphs/ebtc/src/prices/README.md | 240 ++ .../prices/calculations/CalculationsCurve.ts | 47 + .../calculations/CalculationsSushiswap.ts | 47 + subgraphs/ebtc/src/prices/common/constants.ts | 38 + subgraphs/ebtc/src/prices/common/types.ts | 103 + subgraphs/ebtc/src/prices/common/utils.ts | 99 + subgraphs/ebtc/src/prices/config/arbitrum.ts | 138 ++ subgraphs/ebtc/src/prices/config/aurora.ts | 125 + subgraphs/ebtc/src/prices/config/avalanche.ts | 132 ++ subgraphs/ebtc/src/prices/config/bsc.ts | 123 + subgraphs/ebtc/src/prices/config/celo.ts | 124 + subgraphs/ebtc/src/prices/config/cronos.ts | 123 + subgraphs/ebtc/src/prices/config/fantom.ts | 137 ++ subgraphs/ebtc/src/prices/config/fuse.ts | 124 + subgraphs/ebtc/src/prices/config/gnosis.ts | 126 ++ subgraphs/ebtc/src/prices/config/goerli.ts | 122 + subgraphs/ebtc/src/prices/config/harmony.ts | 128 ++ subgraphs/ebtc/src/prices/config/mainnet.ts | 176 ++ subgraphs/ebtc/src/prices/config/moonbeam.ts | 125 + subgraphs/ebtc/src/prices/config/optimism.ts | 137 ++ subgraphs/ebtc/src/prices/config/polygon.ts | 131 ++ subgraphs/ebtc/src/prices/config/template.ts | 115 + subgraphs/ebtc/src/prices/index.ts | 140 ++ .../ebtc/src/prices/oracles/AaveOracle.ts | 44 + .../ebtc/src/prices/oracles/ChainLinkFeed.ts | 53 + .../src/prices/oracles/YearnLensOracle.ts | 44 + .../ebtc/src/prices/routers/CurveRouter.ts | 327 +++ .../src/prices/routers/UniswapForksRouter.ts | 222 ++ subgraphs/ebtc/src/sdk/README.md | 20 + subgraphs/ebtc/src/sdk/account.ts | 80 + subgraphs/ebtc/src/sdk/constants.ts | 281 +++ subgraphs/ebtc/src/sdk/manager.ts | 1238 ++++++++++ subgraphs/ebtc/src/sdk/position.ts | 327 +++ subgraphs/ebtc/src/sdk/snapshots.ts | 645 ++++++ subgraphs/ebtc/src/sdk/token.ts | 274 +++ subgraphs/ebtc/src/sdk/util/arrays.ts | 95 + subgraphs/ebtc/src/sdk/util/constants.ts | 228 ++ subgraphs/ebtc/src/sdk/util/events.ts | 70 + subgraphs/ebtc/src/sdk/util/numbers.ts | 61 + subgraphs/ebtc/src/sdk/util/rewards.ts | 292 +++ subgraphs/ebtc/tsconfig.json | 4 + 67 files changed, 14035 insertions(+) create mode 100644 subgraphs/_reference_/src/prices/config/goerli.ts create mode 100644 subgraphs/ebtc/.gitignore create mode 100644 subgraphs/ebtc/NOTES.md create mode 100644 subgraphs/ebtc/README.md create mode 100644 subgraphs/ebtc/abis/PriceFeed.json create mode 100644 subgraphs/ebtc/abis/Prices/AaveOracle.json create mode 100644 subgraphs/ebtc/abis/Prices/Calculations/Curve.json create mode 100644 subgraphs/ebtc/abis/Prices/Calculations/SushiSwap.json create mode 100644 subgraphs/ebtc/abis/Prices/ChainLink.json create mode 100644 subgraphs/ebtc/abis/Prices/Curve/Pool.json create mode 100644 subgraphs/ebtc/abis/Prices/Curve/Registry.json create mode 100644 subgraphs/ebtc/abis/Prices/ERC20.json create mode 100644 subgraphs/ebtc/abis/Prices/Uniswap/Factory.json create mode 100644 subgraphs/ebtc/abis/Prices/Uniswap/Pair.json create mode 100644 subgraphs/ebtc/abis/Prices/Uniswap/Router.json create mode 100644 subgraphs/ebtc/abis/Prices/YearnLens.json create mode 100644 subgraphs/ebtc/package.json create mode 100644 subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json create mode 100644 subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml create mode 100644 subgraphs/ebtc/schema.graphql create mode 100644 subgraphs/ebtc/src/constants.mustache create mode 100644 subgraphs/ebtc/src/entities/token.ts create mode 100644 subgraphs/ebtc/src/mapping/PriceFeed.ts create mode 100644 subgraphs/ebtc/src/prices/README.md create mode 100644 subgraphs/ebtc/src/prices/calculations/CalculationsCurve.ts create mode 100644 subgraphs/ebtc/src/prices/calculations/CalculationsSushiswap.ts create mode 100644 subgraphs/ebtc/src/prices/common/constants.ts create mode 100644 subgraphs/ebtc/src/prices/common/types.ts create mode 100644 subgraphs/ebtc/src/prices/common/utils.ts create mode 100644 subgraphs/ebtc/src/prices/config/arbitrum.ts create mode 100644 subgraphs/ebtc/src/prices/config/aurora.ts create mode 100644 subgraphs/ebtc/src/prices/config/avalanche.ts create mode 100644 subgraphs/ebtc/src/prices/config/bsc.ts create mode 100644 subgraphs/ebtc/src/prices/config/celo.ts create mode 100644 subgraphs/ebtc/src/prices/config/cronos.ts create mode 100644 subgraphs/ebtc/src/prices/config/fantom.ts create mode 100644 subgraphs/ebtc/src/prices/config/fuse.ts create mode 100644 subgraphs/ebtc/src/prices/config/gnosis.ts create mode 100644 subgraphs/ebtc/src/prices/config/goerli.ts create mode 100644 subgraphs/ebtc/src/prices/config/harmony.ts create mode 100644 subgraphs/ebtc/src/prices/config/mainnet.ts create mode 100644 subgraphs/ebtc/src/prices/config/moonbeam.ts create mode 100644 subgraphs/ebtc/src/prices/config/optimism.ts create mode 100644 subgraphs/ebtc/src/prices/config/polygon.ts create mode 100644 subgraphs/ebtc/src/prices/config/template.ts create mode 100644 subgraphs/ebtc/src/prices/index.ts create mode 100644 subgraphs/ebtc/src/prices/oracles/AaveOracle.ts create mode 100644 subgraphs/ebtc/src/prices/oracles/ChainLinkFeed.ts create mode 100644 subgraphs/ebtc/src/prices/oracles/YearnLensOracle.ts create mode 100644 subgraphs/ebtc/src/prices/routers/CurveRouter.ts create mode 100644 subgraphs/ebtc/src/prices/routers/UniswapForksRouter.ts create mode 100644 subgraphs/ebtc/src/sdk/README.md create mode 100644 subgraphs/ebtc/src/sdk/account.ts create mode 100644 subgraphs/ebtc/src/sdk/constants.ts create mode 100644 subgraphs/ebtc/src/sdk/manager.ts create mode 100644 subgraphs/ebtc/src/sdk/position.ts create mode 100644 subgraphs/ebtc/src/sdk/snapshots.ts create mode 100644 subgraphs/ebtc/src/sdk/token.ts create mode 100644 subgraphs/ebtc/src/sdk/util/arrays.ts create mode 100644 subgraphs/ebtc/src/sdk/util/constants.ts create mode 100644 subgraphs/ebtc/src/sdk/util/events.ts create mode 100644 subgraphs/ebtc/src/sdk/util/numbers.ts create mode 100644 subgraphs/ebtc/src/sdk/util/rewards.ts create mode 100644 subgraphs/ebtc/tsconfig.json diff --git a/deployment/deployment.json b/deployment/deployment.json index 106cca9fed..615b6cd7ad 100644 --- a/deployment/deployment.json +++ b/deployment/deployment.json @@ -8856,5 +8856,35 @@ } } } + }, + "ebtc": { + "schema": "lending", + "base": "ebtc", + "protocol": "ebtc", + "project": "ebtc", + "deployments": { + "ebtc-goerli": { + "network": "goerli", + "status": "dev", + "versions": { + "schema": "3.0.1", + "subgraph": "0.0.1", + "methodology": "0.0.1" + }, + "files": { + "template": "ebtc.template.yaml" + }, + "options": { + "prepare:yaml": true, + "prepare:constants": true + }, + "services": { + "decentralized-network": { + "slug": "ebtc-goerli", + "query-id": "QmdZphstRBDgd6teT5dhQDZ84H6bsqwTy8tEj579JFhqwU" + } + } + } + } } } diff --git a/schema-lending.graphql b/schema-lending.graphql index bae9d99ad0..f4376f1c47 100644 --- a/schema-lending.graphql +++ b/schema-lending.graphql @@ -24,6 +24,7 @@ enum Network { OSMOSIS MATIC # aka Polygon GNOSIS + GOERLI } enum ProtocolType { diff --git a/subgraphs/_reference_/src/prices/common/utils.ts b/subgraphs/_reference_/src/prices/common/utils.ts index 078d446bab..b8ff594c24 100644 --- a/subgraphs/_reference_/src/prices/common/utils.ts +++ b/subgraphs/_reference_/src/prices/common/utils.ts @@ -5,6 +5,7 @@ import * as XDAI from "../config/gnosis"; import * as CRONOS from "../config/cronos"; import * as AURORA from "../config/aurora"; import * as FANTOM from "../config/fantom"; +import * as GOERLI from "../config/goerli"; import * as POLYGON from "../config/polygon"; import * as MAINNET from "../config/mainnet"; import * as HARMONY from "../config/harmony"; @@ -90,6 +91,8 @@ export function getConfig(): Configurations { return new CELO.config(); } else if (network == FUSE.NETWORK_STRING) { return new FUSE.config(); + } else if (network == GOERLI.NETWORK_STRING) { + return new GOERLI.config(); } return new TEMPLATE.config(); diff --git a/subgraphs/_reference_/src/prices/config/goerli.ts b/subgraphs/_reference_/src/prices/config/goerli.ts new file mode 100644 index 0000000000..ff353b4923 --- /dev/null +++ b/subgraphs/_reference_/src/prices/config/goerli.ts @@ -0,0 +1,122 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "goerli"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = []; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0x7a250d5630b4cf539739df2c5dacb4c659f2488d", 2822883), // Uniswap +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" +); +export const WETH_ADDRESS = Address.fromString( + "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6" +); +export const USDC_ADDRESS = Address.fromString( + "0xD87Ba7A50B2E7E660f678A895E4B72E7CB4CCd9C" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/.gitignore b/subgraphs/ebtc/.gitignore new file mode 100644 index 0000000000..06597745fb --- /dev/null +++ b/subgraphs/ebtc/.gitignore @@ -0,0 +1,2 @@ +# gets generated from constants.mustache +src/constants.ts diff --git a/subgraphs/ebtc/NOTES.md b/subgraphs/ebtc/NOTES.md new file mode 100644 index 0000000000..d8a8cd9980 --- /dev/null +++ b/subgraphs/ebtc/NOTES.md @@ -0,0 +1,22 @@ +### Goerli + +- https://docs.chain.link/data-feeds/price-feeds/addresses#Goerli%20Testnet +- collEthCLFeed: `0xb4c4a493AB6356497713A78FFA6c60FB53517c63` +- ethBtcCLFeed: `0x779877A7B0D9E8603169DdbD7836e478b4624789` + +### Test GQL Queries + +`PriceFeed`: + +``` +{ + tokens(first: 5) { + id + name + symbol + decimals + lastPriceUSD + lastPriceBlockNumber + } +} +``` diff --git a/subgraphs/ebtc/README.md b/subgraphs/ebtc/README.md new file mode 100644 index 0000000000..f4ce7243a4 --- /dev/null +++ b/subgraphs/ebtc/README.md @@ -0,0 +1,28 @@ +# Template Subgraph + +## Calculation Methodology v1.0.0 + +### TODO + +Explain how the main metrics are calculated for this subgraph. + +See [Compound](../compound-forks/protocols/compound-v2/README.md) or [Uniswap](../uniswap-forks/protocols/uniswap-v2/README.md) for inspiration. + +## Notes + +Any issues, discrepancies, unique logic to report. + +## Links + +Links to the relevant sources to learn about this protocol. + +- Protocol: https://uniswap.org/ +- Analytics: https://v2.info.uniswap.org/ +- Docs: https://docs.uniswap.org/protocol/V2/introduction +- Smart contracts: https://github.com/Uniswap/v2-core +- Deployed addresses: https://docs.uniswap.org/protocol/V2/reference/smart-contracts/factory +- Official subgraph: https://github.com/Uniswap/v2-subgraph + +## Contract Relationship Map (Optional) + +A map of relationships between contracts and interactions diff --git a/subgraphs/ebtc/abis/PriceFeed.json b/subgraphs/ebtc/abis/PriceFeed.json new file mode 100644 index 0000000000..2219169a88 --- /dev/null +++ b/subgraphs/ebtc/abis/PriceFeed.json @@ -0,0 +1,260 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_lastGoodPrice", + "type": "uint256" + } + ], + "name": "LastGoodPriceUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum PriceFeed.Status", + "name": "newStatus", + "type": "uint8" + } + ], + "name": "PriceFeedStatusChanged", + "type": "event" + }, + { + "inputs": [], + "name": "DECIMAL_PRECISION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETHUSD_TELLOR_REQ_ID", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PRICE_DEVIATION_FROM_PREVIOUS_ROUND", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PRICE_DIFFERENCE_BETWEEN_ORACLES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TARGET_DIGITS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TELLOR_DIGITS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TIMEOUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fetchPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastGoodPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "priceAggregator", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_priceAggregatorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_tellorCallerAddress", + "type": "address" + } + ], + "name": "setAddresses", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "enum PriceFeed.Status", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tellorCaller", + "outputs": [ + { + "internalType": "contract ITellorCaller", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/subgraphs/ebtc/abis/Prices/AaveOracle.json b/subgraphs/ebtc/abis/Prices/AaveOracle.json new file mode 100644 index 0000000000..3149642bb9 --- /dev/null +++ b/subgraphs/ebtc/abis/Prices/AaveOracle.json @@ -0,0 +1,159 @@ +[ + { + "inputs": [ + { + "internalType": "contract IPoolAddressesProvider", + "name": "provider", + "type": "address" + }, + { "internalType": "address[]", "name": "assets", "type": "address[]" }, + { "internalType": "address[]", "name": "sources", "type": "address[]" }, + { + "internalType": "address", + "name": "fallbackOracle", + "type": "address" + }, + { "internalType": "address", "name": "baseCurrency", "type": "address" }, + { + "internalType": "uint256", + "name": "baseCurrencyUnit", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "source", + "type": "address" + } + ], + "name": "AssetSourceUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "baseCurrency", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "baseCurrencyUnit", + "type": "uint256" + } + ], + "name": "BaseCurrencySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "fallbackOracle", + "type": "address" + } + ], + "name": "FallbackOracleUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "ADDRESSES_PROVIDER", + "outputs": [ + { + "internalType": "contract IPoolAddressesProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BASE_CURRENCY", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BASE_CURRENCY_UNIT", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "asset", "type": "address" } + ], + "name": "getAssetPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address[]", "name": "assets", "type": "address[]" } + ], + "name": "getAssetsPrices", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFallbackOracle", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "asset", "type": "address" } + ], + "name": "getSourceOfAsset", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address[]", "name": "assets", "type": "address[]" }, + { "internalType": "address[]", "name": "sources", "type": "address[]" } + ], + "name": "setAssetSources", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "fallbackOracle", "type": "address" } + ], + "name": "setFallbackOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/subgraphs/ebtc/abis/Prices/Calculations/Curve.json b/subgraphs/ebtc/abis/Prices/Calculations/Curve.json new file mode 100644 index 0000000000..b1f6da3de4 --- /dev/null +++ b/subgraphs/ebtc/abis/Prices/Calculations/Curve.json @@ -0,0 +1,143 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_curveAddressProviderAddress", + "type": "address" + }, + { "internalType": "address", "name": "_oracleAddress", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "curveAddressProviderAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "curveMetapoolFactoryAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "curveRegistryAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "curveLpTokenAddress", + "type": "address" + } + ], + "name": "getBasePrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "curveLpTokenAddress", + "type": "address" + } + ], + "name": "getCurvePriceUsdc", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" } + ], + "name": "getPool", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "assetAddress", "type": "address" } + ], + "name": "getPriceUsdc", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "poolAddress", "type": "address" } + ], + "name": "getUnderlyingCoinFromPool", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "curveLpTokenAddress", + "type": "address" + } + ], + "name": "getVirtualPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" } + ], + "name": "isBasicToken", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" } + ], + "name": "isCurveLpToken", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracleAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ownerAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "slot", "type": "bytes32" }, + { "internalType": "bytes32", "name": "value", "type": "bytes32" } + ], + "name": "updateSlot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/subgraphs/ebtc/abis/Prices/Calculations/SushiSwap.json b/subgraphs/ebtc/abis/Prices/Calculations/SushiSwap.json new file mode 100644 index 0000000000..8b9718ae78 --- /dev/null +++ b/subgraphs/ebtc/abis/Prices/Calculations/SushiSwap.json @@ -0,0 +1,137 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_primaryRouterAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_primaryFactoryAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_secondaryRouterAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_secondaryFactoryAddress", + "type": "address" + }, + { "internalType": "address", "name": "_usdcAddress", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" } + ], + "name": "getLpTokenPriceUsdc", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" } + ], + "name": "getLpTokenTotalLiquidityUsdc", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token0Address", "type": "address" }, + { "internalType": "address", "name": "token1Address", "type": "address" } + ], + "name": "getPriceFromRouter", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" } + ], + "name": "getPriceFromRouterUsdc", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" } + ], + "name": "getPriceUsdc", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" } + ], + "name": "getRouterForLpToken", + "outputs": [ + { "internalType": "contract PriceRouter", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" } + ], + "name": "isLpToken", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "primaryFactoryAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "primaryRouterAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "secondaryFactoryAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "secondaryRouterAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "usdcAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wethAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/subgraphs/ebtc/abis/Prices/ChainLink.json b/subgraphs/ebtc/abis/Prices/ChainLink.json new file mode 100644 index 0000000000..55882931c3 --- /dev/null +++ b/subgraphs/ebtc/abis/Prices/ChainLink.json @@ -0,0 +1,530 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "accessController", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "AccessControllerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "denomination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "latestAggregator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "previousAggregator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "nextPhaseId", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "FeedConfirmed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "denomination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "proposedAggregator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "currentAggregator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "FeedProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" }, + { "internalType": "address", "name": "aggregator", "type": "address" } + ], + "name": "confirmFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" } + ], + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" } + ], + "name": "description", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAccessController", + "outputs": [ + { + "internalType": "contract AccessControllerInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" }, + { "internalType": "uint256", "name": "roundId", "type": "uint256" } + ], + "name": "getAnswer", + "outputs": [ + { "internalType": "int256", "name": "answer", "type": "int256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" } + ], + "name": "getCurrentPhaseId", + "outputs": [ + { "internalType": "uint16", "name": "currentPhaseId", "type": "uint16" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" } + ], + "name": "getFeed", + "outputs": [ + { + "internalType": "contract AggregatorV2V3Interface", + "name": "aggregator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" }, + { "internalType": "uint80", "name": "roundId", "type": "uint80" } + ], + "name": "getNextRoundId", + "outputs": [ + { "internalType": "uint80", "name": "nextRoundId", "type": "uint80" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" }, + { "internalType": "uint16", "name": "phaseId", "type": "uint16" } + ], + "name": "getPhase", + "outputs": [ + { + "components": [ + { "internalType": "uint16", "name": "phaseId", "type": "uint16" }, + { + "internalType": "uint80", + "name": "startingAggregatorRoundId", + "type": "uint80" + }, + { + "internalType": "uint80", + "name": "endingAggregatorRoundId", + "type": "uint80" + } + ], + "internalType": "struct FeedRegistryInterface.Phase", + "name": "phase", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" }, + { "internalType": "uint16", "name": "phaseId", "type": "uint16" } + ], + "name": "getPhaseFeed", + "outputs": [ + { + "internalType": "contract AggregatorV2V3Interface", + "name": "aggregator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" }, + { "internalType": "uint16", "name": "phaseId", "type": "uint16" } + ], + "name": "getPhaseRange", + "outputs": [ + { "internalType": "uint80", "name": "startingRoundId", "type": "uint80" }, + { "internalType": "uint80", "name": "endingRoundId", "type": "uint80" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" }, + { "internalType": "uint80", "name": "roundId", "type": "uint80" } + ], + "name": "getPreviousRoundId", + "outputs": [ + { "internalType": "uint80", "name": "previousRoundId", "type": "uint80" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" } + ], + "name": "getProposedFeed", + "outputs": [ + { + "internalType": "contract AggregatorV2V3Interface", + "name": "proposedAggregator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" }, + { "internalType": "uint80", "name": "_roundId", "type": "uint80" } + ], + "name": "getRoundData", + "outputs": [ + { "internalType": "uint80", "name": "roundId", "type": "uint80" }, + { "internalType": "int256", "name": "answer", "type": "int256" }, + { "internalType": "uint256", "name": "startedAt", "type": "uint256" }, + { "internalType": "uint256", "name": "updatedAt", "type": "uint256" }, + { "internalType": "uint80", "name": "answeredInRound", "type": "uint80" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" }, + { "internalType": "uint80", "name": "roundId", "type": "uint80" } + ], + "name": "getRoundFeed", + "outputs": [ + { + "internalType": "contract AggregatorV2V3Interface", + "name": "aggregator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" }, + { "internalType": "uint256", "name": "roundId", "type": "uint256" } + ], + "name": "getTimestamp", + "outputs": [ + { "internalType": "uint256", "name": "timestamp", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "aggregator", "type": "address" } + ], + "name": "isFeedEnabled", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" } + ], + "name": "latestAnswer", + "outputs": [ + { "internalType": "int256", "name": "answer", "type": "int256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" } + ], + "name": "latestRound", + "outputs": [ + { "internalType": "uint256", "name": "roundId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" } + ], + "name": "latestRoundData", + "outputs": [ + { "internalType": "uint80", "name": "roundId", "type": "uint80" }, + { "internalType": "int256", "name": "answer", "type": "int256" }, + { "internalType": "uint256", "name": "startedAt", "type": "uint256" }, + { "internalType": "uint256", "name": "updatedAt", "type": "uint256" }, + { "internalType": "uint80", "name": "answeredInRound", "type": "uint80" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" } + ], + "name": "latestTimestamp", + "outputs": [ + { "internalType": "uint256", "name": "timestamp", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" }, + { "internalType": "address", "name": "aggregator", "type": "address" } + ], + "name": "proposeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" }, + { "internalType": "uint80", "name": "roundId", "type": "uint80" } + ], + "name": "proposedGetRoundData", + "outputs": [ + { "internalType": "uint80", "name": "id", "type": "uint80" }, + { "internalType": "int256", "name": "answer", "type": "int256" }, + { "internalType": "uint256", "name": "startedAt", "type": "uint256" }, + { "internalType": "uint256", "name": "updatedAt", "type": "uint256" }, + { "internalType": "uint80", "name": "answeredInRound", "type": "uint80" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" } + ], + "name": "proposedLatestRoundData", + "outputs": [ + { "internalType": "uint80", "name": "id", "type": "uint80" }, + { "internalType": "int256", "name": "answer", "type": "int256" }, + { "internalType": "uint256", "name": "startedAt", "type": "uint256" }, + { "internalType": "uint256", "name": "updatedAt", "type": "uint256" }, + { "internalType": "uint80", "name": "answeredInRound", "type": "uint80" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract AccessControllerInterface", + "name": "_accessController", + "type": "address" + } + ], + "name": "setAccessController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "to", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "base", "type": "address" }, + { "internalType": "address", "name": "quote", "type": "address" } + ], + "name": "version", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/subgraphs/ebtc/abis/Prices/Curve/Pool.json b/subgraphs/ebtc/abis/Prices/Curve/Pool.json new file mode 100644 index 0000000000..d4843cae7d --- /dev/null +++ b/subgraphs/ebtc/abis/Prices/Curve/Pool.json @@ -0,0 +1,916 @@ +[ + { + "name": "TokenExchange", + "inputs": [ + { "type": "address", "name": "buyer", "indexed": true }, + { "type": "int128", "name": "sold_id", "indexed": false }, + { "type": "uint256", "name": "tokens_sold", "indexed": false }, + { "type": "int128", "name": "bought_id", "indexed": false }, + { "type": "uint256", "name": "tokens_bought", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "TokenExchange", + "inputs": [ + { "name": "buyer", "type": "address", "indexed": true }, + { "name": "sold_id", "type": "uint256", "indexed": false }, + { "name": "tokens_sold", "type": "uint256", "indexed": false }, + { "name": "bought_id", "type": "uint256", "indexed": false }, + { "name": "tokens_bought", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "TokenExchangeUnderlying", + "inputs": [ + { "name": "buyer", "type": "address", "indexed": true }, + { "name": "sold_id", "type": "int128", "indexed": false }, + { "name": "tokens_sold", "type": "uint256", "indexed": false }, + { "name": "bought_id", "type": "int128", "indexed": false }, + { "name": "tokens_bought", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, + { "name": "fee", "type": "uint256", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[3]", "indexed": false }, + { "name": "fee", "type": "uint256", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, + { "name": "fees", "type": "uint256[2]", "indexed": false }, + { "name": "invariant", "type": "uint256", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddLiquidity", + "inputs": [ + { "type": "address", "name": "provider", "indexed": true }, + { "type": "uint256[3]", "name": "token_amounts", "indexed": false }, + { "type": "uint256[3]", "name": "fees", "indexed": false }, + { "type": "uint256", "name": "invariant", "indexed": false }, + { "type": "uint256", "name": "token_supply", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddLiquidity", + "inputs": [ + { "type": "address", "name": "provider", "indexed": true }, + { "type": "uint256[4]", "name": "token_amounts", "indexed": false }, + { "type": "uint256[4]", "name": "fees", "indexed": false }, + { "type": "uint256", "name": "invariant", "indexed": false }, + { "type": "uint256", "name": "token_supply", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[3]", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[2]", "indexed": false }, + { "name": "fees", "type": "uint256[2]", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidity", + "inputs": [ + { "type": "address", "name": "provider", "indexed": true }, + { "type": "uint256[3]", "name": "token_amounts", "indexed": false }, + { "type": "uint256[3]", "name": "fees", "indexed": false }, + { "type": "uint256", "name": "token_supply", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidity", + "inputs": [ + { "type": "address", "name": "provider", "indexed": true }, + { "type": "uint256[4]", "name": "token_amounts", "indexed": false }, + { "type": "uint256[4]", "name": "fees", "indexed": false }, + { "type": "uint256", "name": "token_supply", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidityOne", + "inputs": [ + { "type": "address", "name": "provider", "indexed": true }, + { "type": "uint256", "name": "token_amount", "indexed": false }, + { "type": "uint256", "name": "coin_amount", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidityOne", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amount", "type": "uint256", "indexed": false }, + { "name": "coin_amount", "type": "uint256", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidityImbalance", + "inputs": [ + { "type": "address", "name": "provider", "indexed": true }, + { "type": "uint256[2]", "name": "token_amounts", "indexed": false }, + { "type": "uint256[2]", "name": "fees", "indexed": false }, + { "type": "uint256", "name": "invariant", "indexed": false }, + { "type": "uint256", "name": "token_supply", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidityImbalance", + "inputs": [ + { "type": "address", "name": "provider", "indexed": true }, + { "type": "uint256[3]", "name": "token_amounts", "indexed": false }, + { "type": "uint256[3]", "name": "fees", "indexed": false }, + { "type": "uint256", "name": "invariant", "indexed": false }, + { "type": "uint256", "name": "token_supply", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidityImbalance", + "inputs": [ + { "type": "address", "name": "provider", "indexed": true }, + { "type": "uint256[4]", "name": "token_amounts", "indexed": false }, + { "type": "uint256[4]", "name": "fees", "indexed": false }, + { "type": "uint256", "name": "invariant", "indexed": false }, + { "type": "uint256", "name": "token_supply", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewFee", + "inputs": [ + { "type": "uint256", "name": "fee", "indexed": false }, + { "type": "uint256", "name": "admin_fee", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewFee", + "inputs": [ + { "type": "uint256", "name": "fee", "indexed": false }, + { "type": "uint256", "name": "admin_fee", "indexed": false }, + { "type": "uint256", "name": "offpeg_fee_multiplier", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + + { + "name": "CommitNewAdmin", + "inputs": [ + { "name": "deadline", "type": "uint256", "indexed": true }, + { "name": "admin", "type": "address", "indexed": true } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewAdmin", + "inputs": [{ "name": "admin", "type": "address", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "name": "CommitNewParameters", + "inputs": [ + { "name": "deadline", "type": "uint256", "indexed": true }, + { "name": "admin_fee", "type": "uint256", "indexed": false }, + { "name": "mid_fee", "type": "uint256", "indexed": false }, + { "name": "out_fee", "type": "uint256", "indexed": false }, + { "name": "fee_gamma", "type": "uint256", "indexed": false }, + { "name": "allowed_extra_profit", "type": "uint256", "indexed": false }, + { "name": "adjustment_step", "type": "uint256", "indexed": false }, + { "name": "ma_half_time", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewParameters", + "inputs": [ + { "name": "admin_fee", "type": "uint256", "indexed": false }, + { "name": "mid_fee", "type": "uint256", "indexed": false }, + { "name": "out_fee", "type": "uint256", "indexed": false }, + { "name": "fee_gamma", "type": "uint256", "indexed": false }, + { "name": "allowed_extra_profit", "type": "uint256", "indexed": false }, + { "name": "adjustment_step", "type": "uint256", "indexed": false }, + { "name": "ma_half_time", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RampAgamma", + "inputs": [ + { "name": "initial_A", "type": "uint256", "indexed": false }, + { "name": "future_A", "type": "uint256", "indexed": false }, + { "name": "initial_gamma", "type": "uint256", "indexed": false }, + { "name": "future_gamma", "type": "uint256", "indexed": false }, + { "name": "initial_time", "type": "uint256", "indexed": false }, + { "name": "future_time", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StopRampA", + "inputs": [ + { "name": "current_A", "type": "uint256", "indexed": false }, + { "name": "current_gamma", "type": "uint256", "indexed": false }, + { "name": "time", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "ClaimAdminFee", + "inputs": [ + { "name": "admin", "type": "address", "indexed": true }, + { "name": "tokens", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [ + { "name": "owner", "type": "address" }, + { "name": "admin_fee_receiver", "type": "address" }, + { "name": "A", "type": "uint256" }, + { "name": "gamma", "type": "uint256" }, + { "name": "mid_fee", "type": "uint256" }, + { "name": "out_fee", "type": "uint256" }, + { "name": "allowed_extra_profit", "type": "uint256" }, + { "name": "fee_gamma", "type": "uint256" }, + { "name": "adjustment_step", "type": "uint256" }, + { "name": "admin_fee", "type": "uint256" }, + { "name": "ma_half_time", "type": "uint256" }, + { "name": "initial_price", "type": "uint256" } + ], + "outputs": [] + }, + { "stateMutability": "payable", "type": "fallback" }, + { + "stateMutability": "view", + "type": "function", + "name": "token", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 516 + }, + { + "stateMutability": "view", + "type": "function", + "name": "coins", + "inputs": [{ "name": "i", "type": "uint256" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 648 + }, + { + "stateMutability": "view", + "type": "function", + "name": "A", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 685 + }, + { + "stateMutability": "view", + "type": "function", + "name": "gamma", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 11789 + }, + { + "stateMutability": "view", + "type": "function", + "name": "fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 17633 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_virtual_price", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 364797 + }, + { + "stateMutability": "payable", + "type": "function", + "name": "exchange", + "inputs": [ + { "name": "i", "type": "uint256" }, + { "name": "j", "type": "uint256" }, + { "name": "dx", "type": "uint256" }, + { "name": "min_dy", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 16775598 + }, + { + "stateMutability": "payable", + "type": "function", + "name": "exchange", + "inputs": [ + { "name": "i", "type": "uint256" }, + { "name": "j", "type": "uint256" }, + { "name": "dx", "type": "uint256" }, + { "name": "min_dy", "type": "uint256" }, + { "name": "use_eth", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 16775598 + }, + { + "stateMutability": "payable", + "type": "function", + "name": "exchange_underlying", + "inputs": [ + { "name": "i", "type": "uint256" }, + { "name": "j", "type": "uint256" }, + { "name": "dx", "type": "uint256" }, + { "name": "min_dy", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 16775396 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_dy", + "inputs": [ + { "name": "i", "type": "uint256" }, + { "name": "j", "type": "uint256" }, + { "name": "dx", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4577515 + }, + { + "stateMutability": "payable", + "type": "function", + "name": "add_liquidity", + "inputs": [ + { "name": "amounts", "type": "uint256[2]" }, + { "name": "min_mint_amount", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 17694821 + }, + { + "stateMutability": "payable", + "type": "function", + "name": "add_liquidity", + "inputs": [ + { "name": "amounts", "type": "uint256[2]" }, + { "name": "min_mint_amount", "type": "uint256" }, + { "name": "use_eth", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 17694821 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity", + "inputs": [ + { "name": "_amount", "type": "uint256" }, + { "name": "min_amounts", "type": "uint256[2]" } + ], + "outputs": [], + "gas": 263729 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity", + "inputs": [ + { "name": "_amount", "type": "uint256" }, + { "name": "min_amounts", "type": "uint256[2]" }, + { "name": "use_eth", "type": "bool" } + ], + "outputs": [], + "gas": 263729 + }, + { + "stateMutability": "view", + "type": "function", + "name": "calc_token_amount", + "inputs": [{ "name": "amounts", "type": "uint256[2]" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 5200947 + }, + { + "stateMutability": "view", + "type": "function", + "name": "calc_withdraw_one_coin", + "inputs": [ + { "name": "token_amount", "type": "uint256" }, + { "name": "i", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 12584 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_one_coin", + "inputs": [ + { "name": "token_amount", "type": "uint256" }, + { "name": "i", "type": "uint256" }, + { "name": "min_amount", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 16702178 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_one_coin", + "inputs": [ + { "name": "token_amount", "type": "uint256" }, + { "name": "i", "type": "uint256" }, + { "name": "min_amount", "type": "uint256" }, + { "name": "use_eth", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 16702178 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "claim_admin_fees", + "inputs": [], + "outputs": [], + "gas": 3250985 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "ramp_A_gamma", + "inputs": [ + { "name": "future_A", "type": "uint256" }, + { "name": "future_gamma", "type": "uint256" }, + { "name": "future_time", "type": "uint256" } + ], + "outputs": [], + "gas": 161698 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "stop_ramp_A_gamma", + "inputs": [], + "outputs": [], + "gas": 156743 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "commit_new_parameters", + "inputs": [ + { "name": "_new_mid_fee", "type": "uint256" }, + { "name": "_new_out_fee", "type": "uint256" }, + { "name": "_new_admin_fee", "type": "uint256" }, + { "name": "_new_fee_gamma", "type": "uint256" }, + { "name": "_new_allowed_extra_profit", "type": "uint256" }, + { "name": "_new_adjustment_step", "type": "uint256" }, + { "name": "_new_ma_half_time", "type": "uint256" } + ], + "outputs": [], + "gas": 305084 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "apply_new_parameters", + "inputs": [], + "outputs": [], + "gas": 3543175 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "revert_new_parameters", + "inputs": [], + "outputs": [], + "gas": 23142 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "commit_transfer_ownership", + "inputs": [{ "name": "_owner", "type": "address" }], + "outputs": [], + "gas": 78827 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "apply_transfer_ownership", + "inputs": [], + "outputs": [], + "gas": 67042 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "revert_transfer_ownership", + "inputs": [], + "outputs": [], + "gas": 23232 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "kill_me", + "inputs": [], + "outputs": [], + "gas": 40455 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "unkill_me", + "inputs": [], + "outputs": [], + "gas": 23292 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_admin_fee_receiver", + "inputs": [{ "name": "_admin_fee_receiver", "type": "address" }], + "outputs": [], + "gas": 38482 + }, + { + "stateMutability": "view", + "type": "function", + "name": "lp_price", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 217046 + }, + { + "stateMutability": "view", + "type": "function", + "name": "price_scale", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3426 + }, + { + "stateMutability": "view", + "type": "function", + "name": "price_oracle", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3456 + }, + { + "stateMutability": "view", + "type": "function", + "name": "price_oracle", + "inputs": [{ "name": "", "type": "uint256" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3456 + }, + { + "stateMutability": "view", + "type": "function", + "name": "last_prices", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3486 + }, + { + "stateMutability": "view", + "type": "function", + "name": "last_prices_timestamp", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3516 + }, + { + "stateMutability": "view", + "type": "function", + "name": "initial_A_gamma", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3546 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_A_gamma", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3576 + }, + { + "stateMutability": "view", + "type": "function", + "name": "initial_A_gamma_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3606 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_A_gamma_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3636 + }, + { + "stateMutability": "view", + "type": "function", + "name": "allowed_extra_profit", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3666 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_allowed_extra_profit", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3696 + }, + { + "stateMutability": "view", + "type": "function", + "name": "fee_gamma", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3726 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_fee_gamma", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3756 + }, + { + "stateMutability": "view", + "type": "function", + "name": "adjustment_step", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3786 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_adjustment_step", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3816 + }, + { + "stateMutability": "view", + "type": "function", + "name": "ma_half_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3846 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_ma_half_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3876 + }, + { + "stateMutability": "view", + "type": "function", + "name": "mid_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3906 + }, + { + "stateMutability": "view", + "type": "function", + "name": "out_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3936 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3966 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_mid_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3996 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_out_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4026 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_admin_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4056 + }, + { + "stateMutability": "view", + "type": "function", + "name": "balances", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4131 + }, + { + "stateMutability": "view", + "type": "function", + "name": "D", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4116 + }, + { + "stateMutability": "view", + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 4146 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_owner", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 4176 + }, + { + "stateMutability": "view", + "type": "function", + "name": "xcp_profit", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4206 + }, + { + "stateMutability": "view", + "type": "function", + "name": "xcp_profit_a", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4236 + }, + { + "stateMutability": "view", + "type": "function", + "name": "virtual_price", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4266 + }, + { + "stateMutability": "view", + "type": "function", + "name": "is_killed", + "inputs": [], + "outputs": [{ "name": "", "type": "bool" }], + "gas": 4296 + }, + { + "stateMutability": "view", + "type": "function", + "name": "kill_deadline", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4326 + }, + { + "stateMutability": "view", + "type": "function", + "name": "transfer_ownership_deadline", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4356 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_actions_deadline", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4386 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_fee_receiver", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 4416 + }, + { + "name": "lp_token", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2291 + } +] diff --git a/subgraphs/ebtc/abis/Prices/Curve/Registry.json b/subgraphs/ebtc/abis/Prices/Curve/Registry.json new file mode 100644 index 0000000000..9747624cc9 --- /dev/null +++ b/subgraphs/ebtc/abis/Prices/Curve/Registry.json @@ -0,0 +1,337 @@ +[ + { + "name": "PoolAdded", + "inputs": [ + { "type": "address", "name": "pool", "indexed": true }, + { "type": "bytes", "name": "rate_method_id", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "PoolRemoved", + "inputs": [{ "type": "address", "name": "pool", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "outputs": [], + "inputs": [ + { "type": "address", "name": "_address_provider" }, + { "type": "address", "name": "_gauge_controller" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "name": "find_pool_for_coins", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [ + { "type": "address", "name": "_from" }, + { "type": "address", "name": "_to" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "name": "find_pool_for_coins", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [ + { "type": "address", "name": "_from" }, + { "type": "address", "name": "_to" }, + { "type": "uint256", "name": "i" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "name": "get_n_coins", + "outputs": [{ "type": "uint256[2]", "name": "" }], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 1704 + }, + { + "name": "get_coins", + "outputs": [{ "type": "address[8]", "name": "" }], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 12285 + }, + { + "name": "get_underlying_coins", + "outputs": [{ "type": "address[8]", "name": "" }], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 12347 + }, + { + "name": "get_decimals", + "outputs": [{ "type": "uint256[8]", "name": "" }], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 8199 + }, + { + "name": "get_underlying_decimals", + "outputs": [{ "type": "uint256[8]", "name": "" }], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 8261 + }, + { + "name": "get_rates", + "outputs": [{ "type": "uint256[8]", "name": "" }], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 34780 + }, + { + "name": "get_gauges", + "outputs": [ + { "type": "address[10]", "name": "" }, + { "type": "int128[10]", "name": "" } + ], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 20310 + }, + { + "name": "get_balances", + "outputs": [{ "type": "uint256[8]", "name": "" }], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 16818 + }, + { + "name": "get_underlying_balances", + "outputs": [{ "type": "uint256[8]", "name": "" }], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 158953 + }, + { + "name": "get_virtual_price_from_lp_token", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "address", "name": "_token" }], + "stateMutability": "view", + "type": "function", + "gas": 2080 + }, + { + "name": "get_A", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 1198 + }, + { + "name": "get_parameters", + "outputs": [ + { "type": "uint256", "name": "A" }, + { "type": "uint256", "name": "future_A" }, + { "type": "uint256", "name": "fee" }, + { "type": "uint256", "name": "admin_fee" }, + { "type": "uint256", "name": "future_fee" }, + { "type": "uint256", "name": "future_admin_fee" }, + { "type": "address", "name": "future_owner" }, + { "type": "uint256", "name": "initial_A" }, + { "type": "uint256", "name": "initial_A_time" }, + { "type": "uint256", "name": "future_A_time" } + ], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 6458 + }, + { + "name": "get_fees", + "outputs": [{ "type": "uint256[2]", "name": "" }], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 1603 + }, + { + "name": "get_admin_balances", + "outputs": [{ "type": "uint256[8]", "name": "" }], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "view", + "type": "function", + "gas": 36719 + }, + { + "name": "get_coin_indices", + "outputs": [ + { "type": "int128", "name": "" }, + { "type": "int128", "name": "" }, + { "type": "bool", "name": "" } + ], + "inputs": [ + { "type": "address", "name": "_pool" }, + { "type": "address", "name": "_from" }, + { "type": "address", "name": "_to" } + ], + "stateMutability": "view", + "type": "function", + "gas": 27456 + }, + { + "name": "estimate_gas_used", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [ + { "type": "address", "name": "_pool" }, + { "type": "address", "name": "_from" }, + { "type": "address", "name": "_to" } + ], + "stateMutability": "view", + "type": "function", + "gas": 32329 + }, + { + "name": "add_pool", + "outputs": [], + "inputs": [ + { "type": "address", "name": "_pool" }, + { "type": "uint256", "name": "_n_coins" }, + { "type": "address", "name": "_lp_token" }, + { "type": "bytes32", "name": "_rate_method_id" }, + { "type": "uint256", "name": "_decimals" }, + { "type": "uint256", "name": "_underlying_decimals" }, + { "type": "bool", "name": "_has_initial_A" }, + { "type": "bool", "name": "_is_v1" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 10196577 + }, + { + "name": "add_pool_without_underlying", + "outputs": [], + "inputs": [ + { "type": "address", "name": "_pool" }, + { "type": "uint256", "name": "_n_coins" }, + { "type": "address", "name": "_lp_token" }, + { "type": "bytes32", "name": "_rate_method_id" }, + { "type": "uint256", "name": "_decimals" }, + { "type": "uint256", "name": "_use_rates" }, + { "type": "bool", "name": "_has_initial_A" }, + { "type": "bool", "name": "_is_v1" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 5590664 + }, + { + "name": "add_metapool", + "outputs": [], + "inputs": [ + { "type": "address", "name": "_pool" }, + { "type": "uint256", "name": "_n_coins" }, + { "type": "address", "name": "_lp_token" }, + { "type": "uint256", "name": "_decimals" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 10226976 + }, + { + "name": "remove_pool", + "outputs": [], + "inputs": [{ "type": "address", "name": "_pool" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 779646579509 + }, + { + "name": "set_coin_gas_estimates", + "outputs": [], + "inputs": [ + { "type": "address[10]", "name": "_addr" }, + { "type": "uint256[10]", "name": "_amount" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 357165 + }, + { + "name": "set_gas_estimate_contract", + "outputs": [], + "inputs": [ + { "type": "address", "name": "_pool" }, + { "type": "address", "name": "_estimator" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37747 + }, + { + "name": "set_liquidity_gauges", + "outputs": [], + "inputs": [ + { "type": "address", "name": "_pool" }, + { "type": "address[10]", "name": "_liquidity_gauges" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 365793 + }, + { + "name": "address_provider", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2111 + }, + { + "name": "gauge_controller", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2141 + }, + { + "name": "pool_list", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [{ "type": "uint256", "name": "arg0" }], + "stateMutability": "view", + "type": "function", + "gas": 2280 + }, + { + "name": "pool_count", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2201 + }, + { + "name": "get_pool_from_lp_token", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [{ "type": "address", "name": "arg0" }], + "stateMutability": "view", + "type": "function", + "gas": 2446 + }, + { + "name": "get_lp_token", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [{ "type": "address", "name": "arg0" }], + "stateMutability": "view", + "type": "function", + "gas": 2476 + } +] diff --git a/subgraphs/ebtc/abis/Prices/ERC20.json b/subgraphs/ebtc/abis/Prices/ERC20.json new file mode 100644 index 0000000000..5c47f76a53 --- /dev/null +++ b/subgraphs/ebtc/abis/Prices/ERC20.json @@ -0,0 +1,828 @@ +[ + { + "name": "Transfer", + "inputs": [ + { "type": "address", "name": "sender", "indexed": true }, + { "type": "address", "name": "receiver", "indexed": true }, + { "type": "uint256", "name": "value", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "Approval", + "inputs": [ + { "type": "address", "name": "owner", "indexed": true }, + { "type": "address", "name": "spender", "indexed": true }, + { "type": "uint256", "name": "value", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyAdded", + "inputs": [ + { "type": "address", "name": "strategy", "indexed": true }, + { "type": "uint256", "name": "debtRatio", "indexed": false }, + { "type": "uint256", "name": "rateLimit", "indexed": false }, + { "type": "uint256", "name": "performanceFee", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyReported", + "inputs": [ + { "type": "address", "name": "strategy", "indexed": true }, + { "type": "uint256", "name": "gain", "indexed": false }, + { "type": "uint256", "name": "loss", "indexed": false }, + { "type": "uint256", "name": "totalGain", "indexed": false }, + { "type": "uint256", "name": "totalLoss", "indexed": false }, + { "type": "uint256", "name": "totalDebt", "indexed": false }, + { "type": "uint256", "name": "debtAdded", "indexed": false }, + { "type": "uint256", "name": "debtRatio", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateGovernance", + "inputs": [{ "type": "address", "name": "governance", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateManagement", + "inputs": [{ "type": "address", "name": "management", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateGuestList", + "inputs": [{ "type": "address", "name": "guestList", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateRewards", + "inputs": [{ "type": "address", "name": "rewards", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateDepositLimit", + "inputs": [{ "type": "uint256", "name": "depositLimit", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdatePerformanceFee", + "inputs": [ + { "type": "uint256", "name": "performanceFee", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateManagementFee", + "inputs": [ + { "type": "uint256", "name": "managementFee", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateGuardian", + "inputs": [{ "type": "address", "name": "guardian", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "EmergencyShutdown", + "inputs": [{ "type": "bool", "name": "active", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateWithdrawalQueue", + "inputs": [{ "type": "address[20]", "name": "queue", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyUpdateDebtRatio", + "inputs": [ + { "type": "address", "name": "strategy", "indexed": true }, + { "type": "uint256", "name": "debtRatio", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyUpdateRateLimit", + "inputs": [ + { "type": "address", "name": "strategy", "indexed": true }, + { "type": "uint256", "name": "rateLimit", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyUpdatePerformanceFee", + "inputs": [ + { "type": "address", "name": "strategy", "indexed": true }, + { "type": "uint256", "name": "performanceFee", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyMigrated", + "inputs": [ + { "type": "address", "name": "oldVersion", "indexed": true }, + { "type": "address", "name": "newVersion", "indexed": true } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyRevoked", + "inputs": [{ "type": "address", "name": "strategy", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyRemovedFromQueue", + "inputs": [{ "type": "address", "name": "strategy", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyAddedToQueue", + "inputs": [{ "type": "address", "name": "strategy", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "name": "initialize", + "outputs": [], + "inputs": [ + { "type": "address", "name": "token" }, + { "type": "address", "name": "governance" }, + { "type": "address", "name": "rewards" }, + { "type": "string", "name": "nameOverride" }, + { "type": "string", "name": "symbolOverride" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "initialize", + "outputs": [], + "inputs": [ + { "type": "address", "name": "token" }, + { "type": "address", "name": "governance" }, + { "type": "address", "name": "rewards" }, + { "type": "string", "name": "nameOverride" }, + { "type": "string", "name": "symbolOverride" }, + { "type": "address", "name": "guardian" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "apiVersion", + "outputs": [{ "type": "string", "name": "" }], + "inputs": [], + "stateMutability": "pure", + "type": "function", + "gas": 4519 + }, + { + "name": "setName", + "outputs": [], + "inputs": [{ "type": "string", "name": "name" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 107017 + }, + { + "name": "setSymbol", + "outputs": [], + "inputs": [{ "type": "string", "name": "symbol" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 71867 + }, + { + "name": "setGovernance", + "outputs": [], + "inputs": [{ "type": "address", "name": "governance" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 36338 + }, + { + "name": "acceptGovernance", + "outputs": [], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37610 + }, + { + "name": "setManagement", + "outputs": [], + "inputs": [{ "type": "address", "name": "management" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37748 + }, + { + "name": "setGuestList", + "outputs": [], + "inputs": [{ "type": "address", "name": "guestList" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37778 + }, + { + "name": "setRewards", + "outputs": [], + "inputs": [{ "type": "address", "name": "rewards" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37808 + }, + { + "name": "setDepositLimit", + "outputs": [], + "inputs": [{ "type": "uint256", "name": "limit" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37738 + }, + { + "name": "setPerformanceFee", + "outputs": [], + "inputs": [{ "type": "uint256", "name": "fee" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37872 + }, + { + "name": "setManagementFee", + "outputs": [], + "inputs": [{ "type": "uint256", "name": "fee" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37902 + }, + { + "name": "setGuardian", + "outputs": [], + "inputs": [{ "type": "address", "name": "guardian" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 39146 + }, + { + "name": "setEmergencyShutdown", + "outputs": [], + "inputs": [{ "type": "bool", "name": "active" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 39217 + }, + { + "name": "setWithdrawalQueue", + "outputs": [], + "inputs": [{ "type": "address[20]", "name": "queue" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 763893 + }, + { + "name": "transfer", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "address", "name": "receiver" }, + { "type": "uint256", "name": "amount" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 76733 + }, + { + "name": "transferFrom", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "address", "name": "sender" }, + { "type": "address", "name": "receiver" }, + { "type": "uint256", "name": "amount" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 116496 + }, + { + "name": "approve", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "address", "name": "spender" }, + { "type": "uint256", "name": "amount" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 38244 + }, + { + "name": "increaseAllowance", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "address", "name": "spender" }, + { "type": "uint256", "name": "amount" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 40285 + }, + { + "name": "decreaseAllowance", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "address", "name": "spender" }, + { "type": "uint256", "name": "amount" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 40309 + }, + { + "name": "permit", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "address", "name": "owner" }, + { "type": "address", "name": "spender" }, + { "type": "uint256", "name": "amount" }, + { "type": "uint256", "name": "expiry" }, + { "type": "bytes", "name": "signature" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 81237 + }, + { + "name": "totalAssets", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 4123 + }, + { + "name": "deposit", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "deposit", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "uint256", "name": "_amount" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "deposit", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [ + { "type": "uint256", "name": "_amount" }, + { "type": "address", "name": "recipient" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "maxAvailableShares", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 364171 + }, + { + "name": "withdraw", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "withdraw", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "uint256", "name": "maxShares" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "withdraw", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [ + { "type": "uint256", "name": "maxShares" }, + { "type": "address", "name": "recipient" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "withdraw", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [ + { "type": "uint256", "name": "maxShares" }, + { "type": "address", "name": "recipient" }, + { "type": "uint256", "name": "maxLoss" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "pricePerShare", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 12412 + }, + { + "name": "addStrategy", + "outputs": [], + "inputs": [ + { "type": "address", "name": "strategy" }, + { "type": "uint256", "name": "debtRatio" }, + { "type": "uint256", "name": "rateLimit" }, + { "type": "uint256", "name": "performanceFee" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 1450351 + }, + { + "name": "updateStrategyDebtRatio", + "outputs": [], + "inputs": [ + { "type": "address", "name": "strategy" }, + { "type": "uint256", "name": "debtRatio" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 115316 + }, + { + "name": "updateStrategyRateLimit", + "outputs": [], + "inputs": [ + { "type": "address", "name": "strategy" }, + { "type": "uint256", "name": "rateLimit" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 41467 + }, + { + "name": "updateStrategyPerformanceFee", + "outputs": [], + "inputs": [ + { "type": "address", "name": "strategy" }, + { "type": "uint256", "name": "performanceFee" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 41344 + }, + { + "name": "migrateStrategy", + "outputs": [], + "inputs": [ + { "type": "address", "name": "oldVersion" }, + { "type": "address", "name": "newVersion" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 1105801 + }, + { + "name": "revokeStrategy", + "outputs": [], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "revokeStrategy", + "outputs": [], + "inputs": [{ "type": "address", "name": "strategy" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "addStrategyToQueue", + "outputs": [], + "inputs": [{ "type": "address", "name": "strategy" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 1196920 + }, + { + "name": "removeStrategyFromQueue", + "outputs": [], + "inputs": [{ "type": "address", "name": "strategy" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 23091666 + }, + { + "name": "debtOutstanding", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "name": "debtOutstanding", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "address", "name": "strategy" }], + "stateMutability": "view", + "type": "function" + }, + { + "name": "creditAvailable", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "name": "creditAvailable", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "address", "name": "strategy" }], + "stateMutability": "view", + "type": "function" + }, + { + "name": "availableDepositLimit", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 9808 + }, + { + "name": "expectedReturn", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "name": "expectedReturn", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "address", "name": "strategy" }], + "stateMutability": "view", + "type": "function" + }, + { + "name": "report", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [ + { "type": "uint256", "name": "gain" }, + { "type": "uint256", "name": "loss" }, + { "type": "uint256", "name": "_debtPayment" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 937520 + }, + { + "name": "sweep", + "outputs": [], + "inputs": [{ "type": "address", "name": "token" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "sweep", + "outputs": [], + "inputs": [ + { "type": "address", "name": "token" }, + { "type": "uint256", "name": "amount" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "name", + "outputs": [{ "type": "string", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 9053 + }, + { + "name": "symbol", + "outputs": [{ "type": "string", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 8106 + }, + { + "name": "decimals", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2711 + }, + { + "name": "balanceOf", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "address", "name": "arg0" }], + "stateMutability": "view", + "type": "function", + "gas": 2956 + }, + { + "name": "allowance", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [ + { "type": "address", "name": "arg0" }, + { "type": "address", "name": "arg1" } + ], + "stateMutability": "view", + "type": "function", + "gas": 3201 + }, + { + "name": "totalSupply", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2801 + }, + { + "name": "token", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2831 + }, + { + "name": "governance", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2861 + }, + { + "name": "management", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2891 + }, + { + "name": "guardian", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2921 + }, + { + "name": "guestList", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2951 + }, + { + "name": "strategies", + "outputs": [ + { "type": "uint256", "name": "performanceFee" }, + { "type": "uint256", "name": "activation" }, + { "type": "uint256", "name": "debtRatio" }, + { "type": "uint256", "name": "rateLimit" }, + { "type": "uint256", "name": "lastReport" }, + { "type": "uint256", "name": "totalDebt" }, + { "type": "uint256", "name": "totalGain" }, + { "type": "uint256", "name": "totalLoss" } + ], + "inputs": [{ "type": "address", "name": "arg0" }], + "stateMutability": "view", + "type": "function", + "gas": 10322 + }, + { + "name": "withdrawalQueue", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [{ "type": "uint256", "name": "arg0" }], + "stateMutability": "view", + "type": "function", + "gas": 3120 + }, + { + "name": "emergencyShutdown", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3041 + }, + { + "name": "depositLimit", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3071 + }, + { + "name": "debtRatio", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3101 + }, + { + "name": "totalDebt", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3131 + }, + { + "name": "lastReport", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3161 + }, + { + "name": "activation", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3191 + }, + { + "name": "rewards", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3221 + }, + { + "name": "managementFee", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3251 + }, + { + "name": "performanceFee", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3281 + }, + { + "name": "nonces", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "address", "name": "arg0" }], + "stateMutability": "view", + "type": "function", + "gas": 3526 + }, + { + "name": "DOMAIN_SEPARATOR", + "outputs": [{ "type": "bytes32", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3341 + } +] diff --git a/subgraphs/ebtc/abis/Prices/Uniswap/Factory.json b/subgraphs/ebtc/abis/Prices/Uniswap/Factory.json new file mode 100644 index 0000000000..1b14599d5d --- /dev/null +++ b/subgraphs/ebtc/abis/Prices/Uniswap/Factory.json @@ -0,0 +1,125 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "_feeToSetter", "type": "address" } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "pair", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "constant": true, + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "allPairs", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "allPairsLength", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "tokenA", "type": "address" }, + { "internalType": "address", "name": "tokenB", "type": "address" } + ], + "name": "createPair", + "outputs": [ + { "internalType": "address", "name": "pair", "type": "address" } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "feeTo", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "feeToSetter", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" } + ], + "name": "getPair", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "_feeTo", "type": "address" } + ], + "name": "setFeeTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "_feeToSetter", "type": "address" } + ], + "name": "setFeeToSetter", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/subgraphs/ebtc/abis/Prices/Uniswap/Pair.json b/subgraphs/ebtc/abis/Prices/Uniswap/Pair.json new file mode 100644 index 0000000000..e5efebf418 --- /dev/null +++ b/subgraphs/ebtc/abis/Prices/Uniswap/Pair.json @@ -0,0 +1,461 @@ +[ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Burn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0In", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1In", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0Out", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1Out", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Swap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint112", + "name": "reserve0", + "type": "uint112" + }, + { + "indexed": false, + "internalType": "uint112", + "name": "reserve1", + "type": "uint112" + } + ], + "name": "Sync", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MINIMUM_LIQUIDITY", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "PERMIT_TYPEHASH", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" } + ], + "name": "allowance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "approve", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "address", "name": "to", "type": "address" }], + "name": "burn", + "outputs": [ + { "internalType": "uint256", "name": "amount0", "type": "uint256" }, + { "internalType": "uint256", "name": "amount1", "type": "uint256" } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "factory", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getReserves", + "outputs": [ + { "internalType": "uint112", "name": "_reserve0", "type": "uint112" }, + { "internalType": "uint112", "name": "_reserve1", "type": "uint112" }, + { + "internalType": "uint32", + "name": "_blockTimestampLast", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "_token0", "type": "address" }, + { "internalType": "address", "name": "_token1", "type": "address" } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "kLast", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "address", "name": "to", "type": "address" }], + "name": "mint", + "outputs": [ + { "internalType": "uint256", "name": "liquidity", "type": "uint256" } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "nonces", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "permit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "price0CumulativeLast", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "price1CumulativeLast", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "address", "name": "to", "type": "address" }], + "name": "skim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "uint256", "name": "amount0Out", "type": "uint256" }, + { "internalType": "uint256", "name": "amount1Out", "type": "uint256" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "swap", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "sync", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "token0", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "token1", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/subgraphs/ebtc/abis/Prices/Uniswap/Router.json b/subgraphs/ebtc/abis/Prices/Uniswap/Router.json new file mode 100644 index 0000000000..efc7f31728 --- /dev/null +++ b/subgraphs/ebtc/abis/Prices/Uniswap/Router.json @@ -0,0 +1,398 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "_factory", "type": "address" }, + { "internalType": "address", "name": "_WETH", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "WETH", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenA", "type": "address" }, + { "internalType": "address", "name": "tokenB", "type": "address" }, + { + "internalType": "uint256", + "name": "amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBDesired", + "type": "uint256" + }, + { "internalType": "uint256", "name": "amountAMin", "type": "uint256" }, + { "internalType": "uint256", "name": "amountBMin", "type": "uint256" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "addLiquidity", + "outputs": [ + { "internalType": "uint256", "name": "amountA", "type": "uint256" }, + { "internalType": "uint256", "name": "amountB", "type": "uint256" }, + { "internalType": "uint256", "name": "liquidity", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { + "internalType": "uint256", + "name": "amountTokenDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { "internalType": "uint256", "name": "amountETHMin", "type": "uint256" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "addLiquidityETH", + "outputs": [ + { "internalType": "uint256", "name": "amountToken", "type": "uint256" }, + { "internalType": "uint256", "name": "amountETH", "type": "uint256" }, + { "internalType": "uint256", "name": "liquidity", "type": "uint256" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountOut", "type": "uint256" }, + { "internalType": "uint256", "name": "reserveIn", "type": "uint256" }, + { "internalType": "uint256", "name": "reserveOut", "type": "uint256" } + ], + "name": "getAmountIn", + "outputs": [ + { "internalType": "uint256", "name": "amountIn", "type": "uint256" } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "reserveIn", "type": "uint256" }, + { "internalType": "uint256", "name": "reserveOut", "type": "uint256" } + ], + "name": "getAmountOut", + "outputs": [ + { "internalType": "uint256", "name": "amountOut", "type": "uint256" } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountOut", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" } + ], + "name": "getAmountsIn", + "outputs": [ + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" } + ], + "name": "getAmountsOut", + "outputs": [ + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountA", "type": "uint256" }, + { "internalType": "uint256", "name": "reserveA", "type": "uint256" }, + { "internalType": "uint256", "name": "reserveB", "type": "uint256" } + ], + "name": "quote", + "outputs": [ + { "internalType": "uint256", "name": "amountB", "type": "uint256" } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenA", "type": "address" }, + { "internalType": "address", "name": "tokenB", "type": "address" }, + { "internalType": "uint256", "name": "liquidity", "type": "uint256" }, + { "internalType": "uint256", "name": "amountAMin", "type": "uint256" }, + { "internalType": "uint256", "name": "amountBMin", "type": "uint256" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "removeLiquidity", + "outputs": [ + { "internalType": "uint256", "name": "amountA", "type": "uint256" }, + { "internalType": "uint256", "name": "amountB", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "liquidity", "type": "uint256" }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { "internalType": "uint256", "name": "amountETHMin", "type": "uint256" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "removeLiquidityETH", + "outputs": [ + { "internalType": "uint256", "name": "amountToken", "type": "uint256" }, + { "internalType": "uint256", "name": "amountETH", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "liquidity", "type": "uint256" }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { "internalType": "uint256", "name": "amountETHMin", "type": "uint256" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "removeLiquidityETHSupportingFeeOnTransferTokens", + "outputs": [ + { "internalType": "uint256", "name": "amountETH", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "liquidity", "type": "uint256" }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { "internalType": "uint256", "name": "amountETHMin", "type": "uint256" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "bool", "name": "approveMax", "type": "bool" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "removeLiquidityETHWithPermit", + "outputs": [ + { "internalType": "uint256", "name": "amountToken", "type": "uint256" }, + { "internalType": "uint256", "name": "amountETH", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "liquidity", "type": "uint256" }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { "internalType": "uint256", "name": "amountETHMin", "type": "uint256" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "bool", "name": "approveMax", "type": "bool" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "removeLiquidityETHWithPermitSupportingFeeOnTransferTokens", + "outputs": [ + { "internalType": "uint256", "name": "amountETH", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenA", "type": "address" }, + { "internalType": "address", "name": "tokenB", "type": "address" }, + { "internalType": "uint256", "name": "liquidity", "type": "uint256" }, + { "internalType": "uint256", "name": "amountAMin", "type": "uint256" }, + { "internalType": "uint256", "name": "amountBMin", "type": "uint256" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "bool", "name": "approveMax", "type": "bool" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "removeLiquidityWithPermit", + "outputs": [ + { "internalType": "uint256", "name": "amountA", "type": "uint256" }, + { "internalType": "uint256", "name": "amountB", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountOut", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "swapETHForExactTokens", + "outputs": [ + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "swapExactETHForTokens", + "outputs": [ + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "swapExactETHForTokensSupportingFeeOnTransferTokens", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "swapExactTokensForETH", + "outputs": [ + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "swapExactTokensForETHSupportingFeeOnTransferTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "swapExactTokensForTokensSupportingFeeOnTransferTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountOut", "type": "uint256" }, + { "internalType": "uint256", "name": "amountInMax", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "swapTokensForExactETH", + "outputs": [ + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountOut", "type": "uint256" }, + { "internalType": "uint256", "name": "amountInMax", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "swapTokensForExactTokens", + "outputs": [ + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { "stateMutability": "payable", "type": "receive" } +] diff --git a/subgraphs/ebtc/abis/Prices/YearnLens.json b/subgraphs/ebtc/abis/Prices/YearnLens.json new file mode 100644 index 0000000000..60a45cc87c --- /dev/null +++ b/subgraphs/ebtc/abis/Prices/YearnLens.json @@ -0,0 +1,174 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_managementListAddress", + "type": "address" + }, + { "internalType": "address", "name": "_usdcAddress", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "tokenAliasAddress", + "type": "address" + } + ], + "name": "TokenAliasAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "TokenAliasRemoved", + "type": "event" + }, + { "stateMutability": "nonpayable", "type": "fallback" }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" }, + { + "internalType": "address", + "name": "tokenAliasAddress", + "type": "address" + } + ], + "name": "addTokenAlias", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenAliasAddress", + "type": "address" + } + ], + "internalType": "struct Oracle.TokenAlias[]", + "name": "_tokenAliases", + "type": "tuple[]" + } + ], + "name": "addTokenAliases", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "calculations", + "outputs": [ + { "internalType": "address[]", "name": "", "type": "address[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "getNormalizedValueUsdc", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "uint256", "name": "priceUsdc", "type": "uint256" } + ], + "name": "getNormalizedValueUsdc", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" } + ], + "name": "getPriceUsdcRecommended", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managementList", + "outputs": [ + { + "internalType": "contract ManagementList", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" } + ], + "name": "removeTokenAlias", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "calculationAddresses", + "type": "address[]" + } + ], + "name": "setCalculations", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "tokenAliases", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "usdcAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/subgraphs/ebtc/package.json b/subgraphs/ebtc/package.json new file mode 100644 index 0000000000..c4042de424 --- /dev/null +++ b/subgraphs/ebtc/package.json @@ -0,0 +1,6 @@ +{ + "license": "MIT", + "scripts": { + "prepare:constants": "mustache protocols/${npm_config_protocol}/config/deployments/${npm_config_id}/configurations.json src/constants.mustache > src/constants.ts" + } +} diff --git a/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json b/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json new file mode 100644 index 0000000000..5acf044fd6 --- /dev/null +++ b/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json @@ -0,0 +1,61 @@ +{ + "network": "goerli", + "stethToken": { + "address": "0x6B842CEA279aB886119F66fdCf6F864B5305008f" + }, + "eBTCDeployer": { + "address": "0x76B8F26b28da3C933a01F6a46fD63aCC01190cd6", + "verification": "https://goerli.etherscan.io/address/0x76B8F26b28da3C933a01F6a46fD63aCC01190cd6#code" + }, + "collateral": { + "address": "0x6B842CEA279aB886119F66fdCf6F864B5305008f", + "verification": "https://goerli.etherscan.io/address/0x6B842CEA279aB886119F66fdCf6F864B5305008f#code" + }, + "authority": { + "address": "0xc9A417f2Ab00A4E454428E55DD4CC29C0a087619", + "verification": "https://goerli.etherscan.io/address/0xc9A417f2Ab00A4E454428E55DD4CC29C0a087619#code" + }, + "liquidationLibrary": { + "address": "0x0d6d61aC6f4caa5fE6aBBBd3Ca862668FC26a5C2", + "verification": "https://goerli.etherscan.io/address/0x0d6d61aC6f4caa5fE6aBBBd3Ca862668FC26a5C2#code" + }, + "cdpManager": { + "address": "0x7Cbde961F8aDB94c8A7660Abe1f3e647dbB8513f", + "verification": "https://goerli.etherscan.io/address/0x7Cbde961F8aDB94c8A7660Abe1f3e647dbB8513f#code" + }, + "borrowerOperations": { + "address": "0x11d823a74104A4E9D2E49672BAa6Ab9B5d321D06", + "verification": "https://goerli.etherscan.io/address/0x11d823a74104A4E9D2E49672BAa6Ab9B5d321D06#code" + }, + "eBTCToken": { + "address": "0x5F9Da4b8B81AB38649Aa5d2043eD58C313Bf4139", + "verification": "https://goerli.etherscan.io/address/0x5F9Da4b8B81AB38649Aa5d2043eD58C313Bf4139#code" + }, + "priceFeed": { + "address": "0x3BC7F4D73bC4568cD69579c0A5c709E2FF082422", + "verification": "https://goerli.etherscan.io/address/0x3BC7F4D73bC4568cD69579c0A5c709E2FF082422#code", + "startBlock": 9129660 + }, + "activePool": { + "address": "0xB230cDa730CF515795Ad047fD8320D3e4480C8b8", + "verification": "https://goerli.etherscan.io/address/0xB230cDa730CF515795Ad047fD8320D3e4480C8b8#code", + "startBlock": 9129672, + "createdAt": 1686026808 + }, + "collSurplusPool": { + "address": "0xDB58AfEb24C44EAe3F0f211f71D1a88F92F0c5d9", + "verification": "https://goerli.etherscan.io/address/0xDB58AfEb24C44EAe3F0f211f71D1a88F92F0c5d9#code" + }, + "sortedCdps": { + "address": "0xdf00C96Efec9784022553d550898003E8e65D622", + "verification": "https://goerli.etherscan.io/address/0xdf00C96Efec9784022553d550898003E8e65D622#code" + }, + "hintHelpers": { + "address": "0xCf9d6402840008F24B428d4496c8Dc8433527C99", + "verification": "https://goerli.etherscan.io/address/0xCf9d6402840008F24B428d4496c8Dc8433527C99#code" + }, + "feeRecipient": { + "address": "0x2D81Ad01FA2f94f009853241FdCa0A2715EC39d4", + "verification": "https://goerli.etherscan.io/address/0x2D81Ad01FA2f94f009853241FdCa0A2715EC39d4#code" + } +} diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml new file mode 100644 index 0000000000..34484b0a61 --- /dev/null +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -0,0 +1,57 @@ +specVersion: 0.0.4 +repository: https://github.com/messari/subgraphs +schema: + file: ./schema.graphql +dataSources: + - name: PriceFeed + kind: ethereum/contract + network: {{ network }} + source: + abi: PriceFeed + address: "{{ priceFeed.address }}" + startBlock: {{ priceFeed.startBlock }} + mapping: + file: ./src/mapping/PriceFeed.ts + language: wasm/assemblyscript + kind: ethereum/events + apiVersion: 0.0.7 + entities: + - Token + abis: + - name: PriceFeed + file: ./abis/PriceFeed.json + ########################################### + ############## Price Oracle ############### + ########################################### + # ERC20 + - name: _ERC20 + file: ./abis/Prices/ERC20.json + # Curve Contracts + - name: CurvePool + file: ./abis/Prices/Curve/Pool.json + - name: CurveRegistry + file: ./abis/Prices/Curve/Registry.json + - name: CalculationsCurve + file: ./abis/Prices/Calculations/Curve.json + # YearnLens Contracts + - name: YearnLensContract + file: ./abis/Prices/YearnLens.json + # Aave Oracle Contract + - name: AaveOracleContract + file: ./abis/Prices/AaveOracle.json + # SushiSwap Contracts + - name: CalculationsSushiSwap + file: ./abis/Prices/Calculations/SushiSwap.json + # ChainLink Contracts + - name: ChainLinkContract + file: ./abis/Prices/ChainLink.json + # Uniswap Contracts + - name: UniswapRouter + file: ./abis/Prices/Uniswap/Router.json + - name: UniswapFactory + file: ./abis/Prices/Uniswap/Factory.json + - name: UniswapPair + file: ./abis/Prices/Uniswap/Pair.json + eventHandlers: + - event: LastGoodPriceUpdated(uint256) + handler: handleLastGoodPriceUpdated diff --git a/subgraphs/ebtc/schema.graphql b/subgraphs/ebtc/schema.graphql new file mode 100644 index 0000000000..f4376f1c47 --- /dev/null +++ b/subgraphs/ebtc/schema.graphql @@ -0,0 +1,2012 @@ +# Subgraph Schema: Lending Protocol +# Version: 3.0.1 +# See https://github.com/messari/subgraphs/blob/master/docs/SCHEMA.md for details + +enum Network { + ARBITRUM_ONE + ARWEAVE_MAINNET + AURORA + AVALANCHE + BOBA + BSC # aka BNB Chain + CELO + COSMOS + CRONOS + MAINNET # Ethereum Mainnet + FANTOM + FUSE + HARMONY + JUNO + MOONBEAM + MOONRIVER + NEAR_MAINNET + OPTIMISM + OSMOSIS + MATIC # aka Polygon + GNOSIS + GOERLI +} + +enum ProtocolType { + EXCHANGE + LENDING + YIELD + BRIDGE + GENERIC + # Will add more +} + +type Token @entity @regularPolling { + " Smart contract address of the token " + id: Bytes! + + " Name of the token, mirrored from the smart contract " + name: String! + + " Symbol of the token, mirrored from the smart contract " + symbol: String! + + " The number of decimal places this token uses, default to 18 " + decimals: Int! + + " Optional field to track the price of a token, mostly for caching purposes " + lastPriceUSD: BigDecimal + + " Optional field to track the block number of the last token price " + lastPriceBlockNumber: BigInt + + " The type of token the protocol creates for positions " + type: TokenType +} + +enum RewardTokenType { + " For reward tokens awarded to LPs/lenders " + DEPOSIT + + " For reward tokens awarded to borrowers of variable debt " + VARIABLE_BORROW + + " For reward tokens awarded to borrowers of stable debt " + STABLE_BORROW + + " For reward tokens awarded to stakers " + STAKE +} + +type RewardToken @entity(immutable: true) @regularPolling { + " { Reward token type }-{ Smart contract address of the reward token } " + id: ID! + + " Reference to the actual token " + token: Token! + + " The type of the reward token " + type: RewardTokenType! +} + +enum LendingType { + " Collateralized Debt Position (CDP) protocols have singular isolated positions created by users. We aggregate them to give a single view of a market " + CDP + + " Pooled protocols pool all users assets into a single market " + POOLED +} + +enum PermissionType { + " Only users that have been whitelisted can interact. e.g. Only approved institutions can borrow " + WHITELIST_ONLY + + " To interact a user must be KYC'd " + PERMISSIONED + + " Protocols that do not KYC. Can be used by any account " + PERMISSIONLESS + + " Only the protocol admin address can make do the defined actions " + ADMIN +} + +enum RiskType { + " Global risk means each users position in a market is combined for one score to determine if they can be liquidated " + GLOBAL + + " Isolated risk means each users position in a market or CDP is isolated for risk of liquidation " + ISOLATED +} + +enum CollateralizationType { + " Over collateralized protocols require users to put up more collateral than the amount borrowed. " + OVER_COLLATERALIZED + + " Protocols that allow users to borrow more than their collateral locked. " + UNDER_COLLATERALIZED + + " Protocols that allow users to borrow without any collateral. Generally this protocol is KYC'd and only whitelist users can do this " + UNCOLLATERALIZED +} + +# This is used for representative token descriptions +# e.g. collateral or debt tokens in a protocol +enum TokenType { + " Rebasing tokens continuously adjust balances / supply as interest is accrued (e.g. Aave debt balances adjust at each block with interest) " + REBASING + + " Non-rebasing token balances / supply do not change as interest is accrued (e.g. Compound's cToken's do not adjust balance, the exchange rate changes with interest) " + NON_REBASING +} + +enum InterestRateType { + " Stable interest rate (e.g. Aave) " + STABLE + + " Variable interest rate (e.g. Compound) " + VARIABLE + + " Fixed interest rate (e.g. Notional) " + FIXED +} + +enum InterestRateSide { + " Interest rate accrued by lenders " + LENDER + + " Interest rate paid by borrowers " + BORROWER +} + +enum Tranche { + " Senior denotes debt with a higher priority. The first debt to be paid back to lenders. " + SENIOR + + " Junior tranche denotes lower priority debt. This is secondary priority to be paid back to lenders. " + JUNIOR +} + +enum PositionSide { + " Position opened as a lender (used as collateral) " + COLLATERAL + + " Position opened as a borrower " + BORROWER +} + +# Most markets only have a single interest rate given a specific type. +# However, fixed term lending protocols can have multiple rates with +# different duration/maturity per market. You can append a counter +# to the IDs to differentiate. +type InterestRate @entity @regularPolling { + " { Interest rate side }-{ Interest rate type }-{ Market ID }-{ Optional: Tranche }-{ Optional: # days/hours since epoch time } " + id: ID! + + " Interest rate in percentage APY. E.g. 5.21% should be stored as 5.21 " + rate: BigDecimal! + + " Duration of the loan in days. Only applies to fixed term lending (e.g. Notional) " + duration: Int + + " Maturity of the loan in block height. Only applies to fixed term lending (e.g. Notional) " + maturityBlock: BigInt + + " The party the interest is paid to / received from " + side: InterestRateSide! + + " The type of interest rate (e.g. stable, fixed, variable, etc) " + type: InterestRateType! + + " The level of debt priority at this interest rate " + tranche: Tranche +} + +enum FeeType { + " Fees from liquidations " + LIQUIDATION_FEE + + " Fees given to an admin " + ADMIN_FEE + + " Fees that are taken by the protocol " + PROTOCOL_FEE + + " Fee to mint an asset. Found mostly in CDPs " + MINT_FEE + + " Fee taken on withdrawal. e.g. found in Euler " + WITHDRAW_FEE + + " Any fee not represented here. Please make a github issue for this to be added: https://github.com/messari/subgraphs/issues/new " + OTHER +} + +type Fee @entity @regularPolling { + " { Fee type } " + id: ID! + + " Fee in percentage. E.g. 5.21% should be stored as 5.21 " + rate: BigDecimal + + " A flat fee in the native token. This may be a base fee in addition to the rate, or the only fee. " + flatFee: BigDecimal + + " The type of fee (e.g. liquidation, admin, etc.) " + type: FeeType! +} + +# This entity offers a more nuanced view of revenue types +# Use this to provide the sources of revenue and amounts of each +type RevenueDetail @entity @regularPolling { + " { Market/Protocol ID }{ Optional: Snapshot ID } " + id: Bytes! + + " The source of revenue (in alphabetical order) " + sources: [Fee!]! + + " The amount of revenue in USD (same order as sources) " + amountsUSD: [BigDecimal!]! +} + +enum OracleSource { + UNISWAP + BALANCER + CHAINLINK + YEARN + SUSHISWAP + CURVE + ## Can add more +} + +# Most lending protocols get token prices through onchain oracles. +# As oracles are a source of truth it is important to understand the details. +# This entity will help track oracle-related data in a market +type Oracle @entity @regularPolling { + " { Market Address }{ Token Address } " + id: Bytes! + + oracleAddress: Bytes! + + " The market that this oracle is used for pricing " + market: Market! + + " The block this oracle was adopted for a market " + blockCreated: BigInt! + + " The timestamp this oracle was adopted for a market " + timestampCreated: BigInt! + + " Is the Oracle currently used as the source of truth for a market" + isActive: Boolean! + + " True if the oracle returns prices in USD (e.g. generally the other case is the network's native token) " + isUSD: Boolean! + + " The hash where the oracle was no longer used " + hashEnded: Bytes + + " The Protocol that is providing the oracle (nullable if non-standard source)" + oracleSource: OracleSource +} + +############################# +##### Protocol Metadata ##### +############################# + +interface Protocol { + " Smart contract address of the protocol's main contract (Factory, Registry, etc) " + id: Bytes! + + " Base name of the protocol, excluding transformations. e.g. Aave " + protocol: String! + + " Name of the protocol, including version. e.g. Aave v2 " + name: String! + + " Slug of protocol, including version. e.g. aave-v2 " + slug: String! + + " Version of the subgraph schema, in SemVer format (e.g. 1.0.0) " + schemaVersion: String! + + " Version of the subgraph implementation, in SemVer format (e.g. 1.0.0) " + subgraphVersion: String! + + " Version of the methodology used to compute metrics, loosely based on SemVer format (e.g. 1.0.0) " + methodologyVersion: String! + + " The blockchain network this subgraph is indexing on " + network: Network! + + " The type of protocol (e.g. DEX, Lending, Yield, etc) " + type: ProtocolType! + + " The specific lending protocol type " + lendingType: LendingType + + " The specific permissions required to lend in this protocol " + lenderPermissionType: PermissionType + + " The specific permissions required to borrow from this protocol " + borrowerPermissionType: PermissionType + + " The specific permissions required to create a pool (market) in this protocol " + poolCreatorPermissionType: PermissionType + + " Risk type of the lending protocol " + riskType: RiskType + + " The way a positions can be collateralized " + collateralizationType: CollateralizationType + + ##### Quantitative Data ##### + + " Current TVL (Total Value Locked) of the entire protocol " + totalValueLockedUSD: BigDecimal! + + " Current PCV (Protocol Controlled Value). Only relevant for protocols with PCV. " + protocolControlledValueUSD: BigDecimal + + " Number of cumulative unique users. e.g. accounts that spent gas to interact with this protocol " + cumulativeUniqueUsers: Int! + + " Revenue claimed by suppliers to the protocol. LPs on DEXs (e.g. 0.25% of the swap fee in Sushiswap). Depositors on Lending Protocols. NFT sellers on OpenSea. " + cumulativeSupplySideRevenueUSD: BigDecimal! + + " Gross revenue for the protocol (revenue claimed by protocol). Examples: AMM protocol fee (Sushi’s 0.05%). OpenSea 10% sell fee. " + cumulativeProtocolSideRevenueUSD: BigDecimal! + + " All revenue generated by the protocol. e.g. 0.30% of swap fee in Sushiswap, all yield generated by Yearn. " + cumulativeTotalRevenueUSD: BigDecimal! + + " Total number of pools " + totalPoolCount: Int! + + ##### Snapshots ##### + + " Daily usage metrics for this protocol " + dailyUsageMetrics: [UsageMetricsDailySnapshot!]! + @derivedFrom(field: "protocol") + + " Hourly usage metrics for this protocol " + hourlyUsageMetrics: [UsageMetricsHourlySnapshot!]! + @derivedFrom(field: "protocol") + + " Daily financial metrics for this protocol " + financialMetrics: [FinancialsDailySnapshot!]! @derivedFrom(field: "protocol") +} + +type LendingProtocol implements Protocol @entity @regularPolling { + " Smart contract address of the protocol's main contract (Factory, Registry, etc) " + id: Bytes! + + " Base name of the protocol, excluding transformations. e.g. Aave " + protocol: String! + + " Name of the protocol, including version. e.g. Aave v2 " + name: String! + + " Slug of protocol, including version. e.g. aave-v2 " + slug: String! + + " Version of the subgraph schema, in SemVer format (e.g. 1.0.0) " + schemaVersion: String! + + " Version of the subgraph implementation, in SemVer format (e.g. 1.0.0) " + subgraphVersion: String! + + " Version of the methodology used to compute metrics, loosely based on SemVer format (e.g. 1.0.0) " + methodologyVersion: String! + + " The blockchain network this subgraph is indexing on " + network: Network! + + " The type of protocol (e.g. DEX, Lending, Yield, etc) " + type: ProtocolType! + + " The specific lending protocol type " + lendingType: LendingType + + " The specific permissions required to lend in this protocol " + lenderPermissionType: PermissionType + + " The specific permissions required to borrow from this protocol " + borrowerPermissionType: PermissionType + + " The specific permissions required to create a pool (market) in this protocol " + poolCreatorPermissionType: PermissionType + + " Risk type of the lending protocol " + riskType: RiskType + + " The way a positions can be collateralized " + collateralizationType: CollateralizationType + + " Tokens that can be minted. Only applies to CDP (usually stable coins) " + mintedTokens: [Token!] + + " Additional tokens that are given as reward for position in a protocol, usually in liquidity mining programs. " + rewardTokens: [RewardToken!] + + ##### Quantitative Data ##### + + " Number of cumulative unique users. e.g. accounts that spent gas to interact with this protocol " + cumulativeUniqueUsers: Int! + + " Number of cumulative depositors " + cumulativeUniqueDepositors: Int! + + " Number of cumulative borrowers " + cumulativeUniqueBorrowers: Int! + + " Number of cumulative liquidators (accounts that performed liquidation) " + cumulativeUniqueLiquidators: Int! + + " Number of cumulative liquidatees (accounts that got liquidated) " + cumulativeUniqueLiquidatees: Int! + + " Current TVL (Total Value Locked) of the entire protocol " + totalValueLockedUSD: BigDecimal! + + " Current PCV (Protocol Controlled Value). Only relevant for protocols with PCV. " + protocolControlledValueUSD: BigDecimal + + " Revenue claimed by suppliers to the protocol. LPs on DEXs (e.g. 0.25% of the swap fee in Sushiswap). Depositors on Lending Protocols. NFT sellers on OpenSea. " + cumulativeSupplySideRevenueUSD: BigDecimal! + + " Gross revenue for the protocol (revenue claimed by protocol). Examples: AMM protocol fee (Sushi’s 0.05%). OpenSea 10% sell fee. " + cumulativeProtocolSideRevenueUSD: BigDecimal! + + " All revenue generated by the protocol. e.g. 0.30% of swap fee in Sushiswap, all yield generated by Yearn. " + cumulativeTotalRevenueUSD: BigDecimal! + + " All fees in the protocol. Fee should be in percentage format. e.g. 0.30% liquidation fee " + fees: [Fee!] + + " Details of revenue sources and amounts " + revenueDetail: RevenueDetail + + " Current balance of all deposited assets, in USD. Note this metric should be the same as TVL. " + totalDepositBalanceUSD: BigDecimal! + + " Sum of all historical deposits in USD (only considers deposits and not withdrawals) " + cumulativeDepositUSD: BigDecimal! + + " Current balance of all borrowed/minted assets (not historical cumulative), in USD. " + totalBorrowBalanceUSD: BigDecimal! + + " Sum of all historical borrows/mints in USD (i.e. total loan origination). " + cumulativeBorrowUSD: BigDecimal! + + " Sum of all historical liquidations in USD " + cumulativeLiquidateUSD: BigDecimal! + + " Total supply of minted tokens in native amounts, with same ordering as mintedTokens. Only applies to CDP " + mintedTokenSupplies: [BigInt!] + + " Total number of pools " + totalPoolCount: Int! + + " Total number of open positions " + openPositionCount: Int! + + " Total number of positions (open and closed) " + cumulativePositionCount: Int! + + " Total number of transactions " + transactionCount: Int! + + " Total number of deposits " + depositCount: Int! + + " Total number of withdrawals " + withdrawCount: Int! + + " Total number of borrows " + borrowCount: Int! + + " Total number of repayments " + repayCount: Int! + + " Total number of liquidations " + liquidationCount: Int! + + " Total number of transfers " + transferCount: Int! + + " Total number of flashloans " + flashloanCount: Int! + + ##### Token Balances ##### + + " Per-block reward token emission as of the current block normalized to a day, in token's native amount. This should be ideally calculated as the theoretical rate instead of the realized amount. " + rewardTokenEmissionsAmount: [BigInt!] + + " Per-block reward token emission as of the current block normalized to a day, in USD value. This should be ideally calculated as the theoretical rate instead of the realized amount. " + rewardTokenEmissionsUSD: [BigDecimal!] + + ##### Snapshots ##### + + " Daily usage metrics for this protocol " + dailyUsageMetrics: [UsageMetricsDailySnapshot!]! + @derivedFrom(field: "protocol") + + " Hourly usage metrics for this protocol " + hourlyUsageMetrics: [UsageMetricsHourlySnapshot!]! + @derivedFrom(field: "protocol") + + " Daily financial metrics for this protocol " + financialMetrics: [FinancialsDailySnapshot!]! @derivedFrom(field: "protocol") + + ##### Markets ##### + + " All markets that belong to this protocol " + markets: [Market!]! @derivedFrom(field: "protocol") +} + +# helper entity to iterate through all markets +type _MarketList @entity { + " Same ID as LendingProtocol " + id: Bytes! + + " IDs of all markets in the LendingProtocol " + markets: [Bytes!]! +} + +############################### +##### Protocol Timeseries ##### +############################### + +type UsageMetricsDailySnapshot @entity @dailySnapshot { + " ID is # of days since Unix epoch time " + id: Bytes! + + " Number of days since Unix epoch time " + days: Int! + + " Protocol this snapshot is associated with " + protocol: LendingProtocol! + + " Number of unique daily active users. e.g. accounts that spent gas to interact with this protocol " + dailyActiveUsers: Int! + + " Number of cumulative unique users. e.g. accounts that spent gas to interact with this protocol " + cumulativeUniqueUsers: Int! + + " Number of unique daily depositors " + dailyActiveDepositors: Int! + + " Number of cumulative depositors " + cumulativeUniqueDepositors: Int! + + " Number of unique daily borrowers " + dailyActiveBorrowers: Int! + + " Number of cumulative borrowers " + cumulativeUniqueBorrowers: Int! + + " Number of unique daily liquidators (accounts that performed liquidation) " + dailyActiveLiquidators: Int! + + " Number of cumulative liquidators (accounts that performed liquidation) " + cumulativeUniqueLiquidators: Int! + + " Number of unique daily liquidatees (accounts that got liquidated) " + dailyActiveLiquidatees: Int! + + " Number of cumulative liquidatees (accounts that got liquidated) " + cumulativeUniqueLiquidatees: Int! + + " Total number of transactions occurred in a day. Transactions include all entities that implement the Event interface. " + dailyTransactionCount: Int! + + " Total number of deposits in a day " + dailyDepositCount: Int! + + " Total number of withdrawals in a day " + dailyWithdrawCount: Int! + + " Total number of borrows/mints in a day " + dailyBorrowCount: Int! + + " Total number of repayments/burns in a day " + dailyRepayCount: Int! + + " Total number of liquidations in a day " + dailyLiquidateCount: Int! + + " Total number of transfers in a day " + dailyTransferCount: Int! + + " Total number of flashloans in a day " + dailyFlashloanCount: Int! + + " Total number of positions (open and closed) " + cumulativePositionCount: Int! + + " Total number of open positions " + openPositionCount: Int! + + " Total number of positions touched in a day. This includes opening, closing, and modifying positions. " + dailyActivePositions: Int! + + " Total number of pools " + totalPoolCount: Int! + + " Block number of this snapshot " + blockNumber: BigInt! + + " Timestamp of this snapshot " + timestamp: BigInt! +} + +type UsageMetricsHourlySnapshot @entity @hourlySnapshot { + " { # of hours since Unix epoch time } " + id: Bytes! + + " Number of hours since Unix epoch time " + hours: Int! + + " Protocol this snapshot is associated with " + protocol: LendingProtocol! + + " Number of unique hourly active users " + hourlyActiveUsers: Int! + + " Number of cumulative unique users. e.g. accounts that spent gas to interact with this protocol " + cumulativeUniqueUsers: Int! + + " Total number of transactions occurred in an hour. Transactions include all entities that implement the Event interface. " + hourlyTransactionCount: Int! + + " Total number of deposits in an hour " + hourlyDepositCount: Int! + + " Total number of withdrawals in an hour " + hourlyWithdrawCount: Int! + + " Total number of borrows/mints in an hour " + hourlyBorrowCount: Int! + + " Total number of repayments/burns in an hour " + hourlyRepayCount: Int! + + " Total number of liquidations in an hour " + hourlyLiquidateCount: Int! + + " Block number of this snapshot " + blockNumber: BigInt! + + " Timestamp of this snapshot " + timestamp: BigInt! +} + +type FinancialsDailySnapshot @entity @dailySnapshot { + " ID is # of days since Unix epoch time " + id: Bytes! + + " Number of days since Unix epoch time " + days: Int! + + " Protocol this snapshot is associated with " + protocol: LendingProtocol! + + " Block number of this snapshot " + blockNumber: BigInt! + + " Timestamp of this snapshot " + timestamp: BigInt! + + " Current TVL (Total Value Locked) of the entire protocol " + totalValueLockedUSD: BigDecimal! + + " Current PCV (Protocol Controlled Value). Only relevant for protocols with PCV. " + protocolControlledValueUSD: BigDecimal + + " Total supply of minted tokens in native amounts, with same ordering as mintedTokens. Only applies to CDP " + mintedTokenSupplies: [BigInt!] + + ##### Revenue ##### + + " Revenue claimed by suppliers to the protocol. LPs on DEXs (e.g. 0.25% of the swap fee in Sushiswap). Depositors on Lending Protocols. NFT sellers on OpenSea. " + dailySupplySideRevenueUSD: BigDecimal! + + " Revenue claimed by suppliers to the protocol. LPs on DEXs (e.g. 0.25% of the swap fee in Sushiswap). Depositors on Lending Protocols. NFT sellers on OpenSea. " + cumulativeSupplySideRevenueUSD: BigDecimal! + + " Gross revenue for the protocol (revenue claimed by protocol). Examples: AMM protocol fee (Sushi’s 0.05%). OpenSea 10% sell fee. " + dailyProtocolSideRevenueUSD: BigDecimal! + + " Gross revenue for the protocol (revenue claimed by protocol). Examples: AMM protocol fee (Sushi’s 0.05%). OpenSea 10% sell fee. " + cumulativeProtocolSideRevenueUSD: BigDecimal! + + " All revenue generated by the protocol. e.g. 0.30% of swap fee in Sushiswap, all yield generated by Yearn. " + dailyTotalRevenueUSD: BigDecimal! + + " All revenue generated by the protocol. e.g. 0.30% of swap fee in Sushiswap, all yield generated by Yearn. " + cumulativeTotalRevenueUSD: BigDecimal! + + " Details of revenue sources and amounts " + revenueDetail: RevenueDetail + + ##### Lending Activities ##### + + " Current balance of all deposited assets, in USD. Note this metric should be the same as TVL. " + totalDepositBalanceUSD: BigDecimal! + + " Total assets deposited on a given day, in USD " + dailyDepositUSD: BigDecimal! + + " Sum of all historical deposits in USD (only considers deposits and not withdrawals) " + cumulativeDepositUSD: BigDecimal! + + " Current balance of all borrowed/minted assets, in USD. " + totalBorrowBalanceUSD: BigDecimal! + + " Total assets borrowed/minted on a given day, in USD. " + dailyBorrowUSD: BigDecimal! + + " Sum of all historical borrows/mints in USD (i.e. total loan origination). " + cumulativeBorrowUSD: BigDecimal! + + " Total assets liquidated on a given day, in USD. " + dailyLiquidateUSD: BigDecimal! + + " Sum of all historical liquidations in USD " + cumulativeLiquidateUSD: BigDecimal! + + " Total assets withdrawn on a given day, in USD. " + dailyWithdrawUSD: BigDecimal! + + " Total assets repaid on a given day, in USD. " + dailyRepayUSD: BigDecimal! + + " Total assets transferred on a given day, in USD. " + dailyTransferUSD: BigDecimal! + + " Total flashloans executed on a given day, in USD. " + dailyFlashloanUSD: BigDecimal! +} + +############################### +##### Pool-Level Metadata ##### +############################### + +""" +A market is defined by the input token. +At a minimum that means being able to deposit/withdraw that token. +e.g. there may be related markets as they only act as collateral for other markets. +""" +type Market @entity @regularPolling { + " Smart contract address of the market " + id: Bytes! + + " The protocol this pool belongs to " + protocol: LendingProtocol! + + " Name of market " + name: String + + " Is this market active or is it frozen " + isActive: Boolean! + + " Can you borrow from this market " + canBorrowFrom: Boolean! + + " Can you use the output token as collateral " + canUseAsCollateral: Boolean! + + " Maximum loan-to-value ratio as a percentage value (e.g. 75% for DAI in Aave) " + maximumLTV: BigDecimal! + + " Liquidation threshold as a percentage value (e.g. 80% for DAI in Aave). When it is reached, the position is defined as undercollateralised and could be liquidated " + liquidationThreshold: BigDecimal! + + " Liquidation penalty (or the liquidation bonus for liquidators) as a percentage value. It is the penalty/bonus price on the collateral when liquidators purchase it as part of the liquidation of a loan that has passed the liquidation threshold " + liquidationPenalty: BigDecimal! + + " Can the user choose to isolate assets in this market. e.g. only this market's collateral can be used for a borrow in Aave V3 " + canIsolate: Boolean! + + " Creation timestamp " + createdTimestamp: BigInt! + + " Creation block number " + createdBlockNumber: BigInt! + + " Details about the price oracle used to get this token's price " + oracle: Oracle + + " A unique identifier that can relate multiple markets. e.g. a common address that is the same for each related market. This is useful for markets with multiple input tokens " + relation: Bytes + + ##### Incentives ##### + + " Additional tokens that are given as reward for position in a protocol, usually in liquidity mining programs. e.g. SUSHI in the Onsen program, MATIC for Aave Polygon " + rewardTokens: [RewardToken!] + + " Per-block reward token emission as of the current block normalized to a day, in token's native amount. This should be ideally calculated as the theoretical rate instead of the realized amount. " + rewardTokenEmissionsAmount: [BigInt!] + + " Per-block reward token emission as of the current block normalized to a day, in USD value. This should be ideally calculated as the theoretical rate instead of the realized amount. " + rewardTokenEmissionsUSD: [BigDecimal!] + + " Total supply of output tokens that are staked. Used to calculate reward APY. " + stakedOutputTokenAmount: BigInt + + ##### Quantitative Data ##### + + " Token that need to be deposited in this market to take a position in protocol (should be alphabetized) " + inputToken: Token! + + " Amount of input token in the market (same order as inputTokens) " + inputTokenBalance: BigInt! + + " Prices in USD of the input token (same order as inputTokens) " + inputTokenPriceUSD: BigDecimal! + + " Tokens that are minted to track ownership of position in protocol (e.g. aToken, cToken). Leave as null if doesn't exist (should be alphabetized) " + outputToken: Token + + " Total supply of output token (same order as outputTokens) " + outputTokenSupply: BigInt + + " Prices in USD of the output token (same order as outputTokens) " + outputTokenPriceUSD: BigDecimal + + " Amount of input token per full share of output token. Only applies when the output token exists (note this is a ratio and not a percentage value, i.e. 1.05 instead of 105%) " + exchangeRate: BigDecimal + + " All interest rates for this input token. Should be in APR format " + rates: [InterestRate!] + + " Total amount of reserves (in USD) " + reserves: BigDecimal + + " The amount of revenue that is converted to reserves at the current time. 20% reserve factor should be in format 0.20 " + reserveFactor: BigDecimal + + " The token that can be borrowed (e.g. inputToken in POOLED and generally a stable in CDPs) " + borrowedToken: Token + + " Amount of input tokens borrowed in this market using variable interest rates (in native terms) " + variableBorrowedTokenBalance: BigInt + + " Amount of input tokens borrowed in this market using stable interest rates (in native terms) " + stableBorrowedTokenBalance: BigInt + + " Allowed limit to how much of the underlying asset can be supplied to this market. " + supplyCap: BigInt + + " Allowed limit for how much of the underlying asset can be borrowed from this market. " + borrowCap: BigInt + + " Current TVL (Total Value Locked) of this market " + totalValueLockedUSD: BigDecimal! + + " All revenue generated by the market, accrued to the supply side. " + cumulativeSupplySideRevenueUSD: BigDecimal! + + " All revenue generated by the market, accrued to the protocol. " + cumulativeProtocolSideRevenueUSD: BigDecimal! + + " All revenue generated by the market. " + cumulativeTotalRevenueUSD: BigDecimal! + + " Details of revenue sources and amounts " + revenueDetail: RevenueDetail + + " Current balance of all deposited assets (not historical cumulative), in USD " + totalDepositBalanceUSD: BigDecimal! + + " Sum of all historical deposits in USD (only considers deposits and not withdrawals) " + cumulativeDepositUSD: BigDecimal! + + " Current balance of all borrowed/minted assets (not historical cumulative), in USD " + totalBorrowBalanceUSD: BigDecimal! + + " Sum of all historical borrows/mints in USD (i.e. total loan origination) " + cumulativeBorrowUSD: BigDecimal! + + " Sum of all historical liquidations in USD " + cumulativeLiquidateUSD: BigDecimal! + + " Sum of all historical transfers in USD " + cumulativeTransferUSD: BigDecimal! + + " Sum of all historical flashloans in USD " + cumulativeFlashloanUSD: BigDecimal! + + " Total number of transactions " + transactionCount: Int! + + " Total number of deposits " + depositCount: Int! + + " Total number of withdrawals " + withdrawCount: Int! + + " Total number of borrows " + borrowCount: Int! + + " Total number of repayments " + repayCount: Int! + + " Total number of liquidations " + liquidationCount: Int! + + " Total number of transfers " + transferCount: Int! + + " Total number of flashloans " + flashloanCount: Int! + + ##### Usage Data ##### + + " Number of cumulative unique users. e.g. accounts that spent gas to interact with this market " + cumulativeUniqueUsers: Int! + + " Number of cumulative depositors " + cumulativeUniqueDepositors: Int! + + " Number of cumulative borrowers " + cumulativeUniqueBorrowers: Int! + + " Number of cumulative liquidators (accounts that performed liquidation) " + cumulativeUniqueLiquidators: Int! + + " Number of cumulative liquidatees (accounts that got liquidated) " + cumulativeUniqueLiquidatees: Int! + + " Number of cumulative accounts that transferred positions (generally in the form of outputToken transfer) " + cumulativeUniqueTransferrers: Int! + + " Number of cumulative accounts that performed flashloans " + cumulativeUniqueFlashloaners: Int! + + ##### Account/Position Data ##### + + " All positions in this market " + positions: [Position!]! @derivedFrom(field: "market") + + " Number of positions in this market " + positionCount: Int! + + " Number of open positions in this market " + openPositionCount: Int! + + " Number of closed positions in this market " + closedPositionCount: Int! + + " Number of lending positions in this market. Note: this is cumulative and strictly increasing " + lendingPositionCount: Int! + + " Number of borrowing positions in this market. Note: this is cumulative and strictly increasing " + borrowingPositionCount: Int! + + ##### Snapshots ##### + + " Market daily snapshots " + dailySnapshots: [MarketDailySnapshot!]! @derivedFrom(field: "market") + + " Market hourly snapshots " + hourlySnapshots: [MarketHourlySnapshot!]! @derivedFrom(field: "market") + + ##### Events ##### + + " All deposits made to this market " + deposits: [Deposit!]! @derivedFrom(field: "market") + + " All withdrawals made from this market " + withdraws: [Withdraw!]! @derivedFrom(field: "market") + + " All borrows from this market " + borrows: [Borrow!]! @derivedFrom(field: "market") + + " All repayments to this market " + repays: [Repay!]! @derivedFrom(field: "market") + + " All liquidations made to this market " + liquidates: [Liquidate!]! @derivedFrom(field: "market") + + " All transfers made in this market " + transfers: [Transfer!]! @derivedFrom(field: "market") + + " All flashloans made in this market" + flashloans: [Flashloan!]! @derivedFrom(field: "market") +} + +################################# +##### Pool-Level Timeseries ##### +################################# + +type MarketDailySnapshot @entity @dailySnapshot { + " { Smart contract address of the market }{ # of days since Unix epoch time } " + id: Bytes! + + " Number of days since Unix epoch time " + days: Int! + + " The protocol this snapshot belongs to " + protocol: LendingProtocol! + + " The pool this snapshot belongs to " + market: Market! + + " Block number of this snapshot " + blockNumber: BigInt! + + " Timestamp of this snapshot " + timestamp: BigInt! + + " A unique identifier that can relate multiple markets together. e.g. a common address that they all share. This is useful for markets with multiple input tokens " + relation: Bytes + + ##### Incentives ##### + + " Additional tokens that are given as reward for position in a protocol, usually in liquidity mining programs. e.g. SUSHI in the Onsen program, MATIC for Aave Polygon " + rewardTokens: [RewardToken!] + + " Per-block reward token emission as of the current block normalized to a day, in token's native amount. This should be ideally calculated as the theoretical rate instead of the realized amount. " + rewardTokenEmissionsAmount: [BigInt!] + + " Per-block reward token emission as of the current block normalized to a day, in USD value. This should be ideally calculated as the theoretical rate instead of the realized amount. " + rewardTokenEmissionsUSD: [BigDecimal!] + + " Total supply of output tokens that are staked. Used to calculate reward APY. " + stakedOutputTokenAmount: BigInt + + ##### Quantitative Data ##### + + " Amount of input token in the market (same order as inputTokens) " + inputTokenBalance: BigInt! + + " Prices in USD of the input token (same order as inputTokens) " + inputTokenPriceUSD: BigDecimal! + + " Total supply of output token (same order as outputTokens) " + outputTokenSupply: BigInt + + " Prices in USD of the output token (same order as outputTokens) " + outputTokenPriceUSD: BigDecimal + + " Amount of input token per full share of output token. Only applies when the output token exists (note this is a ratio and not a percentage value, i.e. 1.05 instead of 105%) " + exchangeRate: BigDecimal + + " All interest rates for this input token. Should be in APR format " + rates: [InterestRate!] + + " Total amount of reserves (in USD) " + reserves: BigDecimal + + " The amount of revenue that is converted to reserves at the current time. 20% reserve factor should be in format 0.20 " + reserveFactor: BigDecimal + + " Amount of input tokens borrowed in this market using variable interest rates (in native terms) " + variableBorrowedTokenBalance: BigInt + + " Amount of input tokens borrowed in this market using stable interest rates (in native terms) " + stableBorrowedTokenBalance: BigInt + + " Allowed limit to how much of the underlying asset can be supplied to this market. " + supplyCap: BigInt + + " Allowed limit for how much of the underlying asset can be borrowed from this market. " + borrowCap: BigInt + + " Current TVL (Total Value Locked) of this market " + totalValueLockedUSD: BigDecimal! + + " All revenue generated by the market, accrued to the supply side. " + cumulativeSupplySideRevenueUSD: BigDecimal! + + " Daily revenue generated by the market, accrued to the supply side. " + dailySupplySideRevenueUSD: BigDecimal! + + " All revenue generated by the market, accrued to the protocol. " + cumulativeProtocolSideRevenueUSD: BigDecimal! + + " Daily revenue generated by the market, accrued to the protocol. " + dailyProtocolSideRevenueUSD: BigDecimal! + + " All revenue generated by the market. " + cumulativeTotalRevenueUSD: BigDecimal! + + " Daily revenue generated by the market. " + dailyTotalRevenueUSD: BigDecimal! + + " Details of revenue sources and amounts " + revenueDetail: RevenueDetail + + " Current balance of all deposited assets (not historical cumulative), in USD. Same as pool TVL. " + totalDepositBalanceUSD: BigDecimal! + + " Sum of all deposits made on a given day, in USD " + dailyDepositUSD: BigDecimal! + + " Sum of all the deposits on a given day, in native units " + dailyNativeDeposit: BigInt! + + " Sum of all historical deposits in USD (only considers deposits and not withdrawals) " + cumulativeDepositUSD: BigDecimal! + + " Current balance of all borrowed/minted assets (not historical cumulative), in USD. " + totalBorrowBalanceUSD: BigDecimal! + + " Sum of all borrows/mints made on a given day, in USD " + dailyBorrowUSD: BigDecimal! + + " Sum of all the borrows on a given day, in native units " + dailyNativeBorrow: BigInt! + + " Sum of all historical borrows/mints in USD (i.e. total loan origination) " + cumulativeBorrowUSD: BigDecimal! + + " Total assets liquidated on a given day, in USD. " + dailyLiquidateUSD: BigDecimal! + + " Total assets liquidated on a given day, in native units. " + dailyNativeLiquidate: BigInt! + + " Sum of all historical liquidations in USD " + cumulativeLiquidateUSD: BigDecimal! + + " Total assets withdrawn on a given day, in USD. " + dailyWithdrawUSD: BigDecimal! + + " Total assets withdrawn on a given day, in native units. " + dailyNativeWithdraw: BigInt! + + " Total assets repaid on a given day, in USD. " + dailyRepayUSD: BigDecimal! + + " Total assets repaid on a given day, in native units. " + dailyNativeRepay: BigInt! + + " Total assets transferred on a given day, in USD. " + dailyTransferUSD: BigDecimal! + + " Total assets transferred on a given day, in native units. " + dailyNativeTransfer: BigInt! + + " Sum of all historical transfers in USD " + cumulativeTransferUSD: BigDecimal! + + " Total assets flashloaned on a given day, in USD. " + dailyFlashloanUSD: BigDecimal! + + " Total assets flashloaned on a given day, in native units. " + dailyNativeFlashloan: BigInt! + + " Sum of all historical flashloans in USD " + cumulativeFlashloanUSD: BigDecimal! + + ##### Usage Data ##### + + " Number of unique daily active users. e.g. accounts that spent gas to interact with this market " + dailyActiveUsers: Int! + + " Number of unique daily depositors " + dailyActiveDepositors: Int! + + " Number of unique daily borrowers " + dailyActiveBorrowers: Int! + + " Number of unique daily liquidators (accounts that performed liquidation) " + dailyActiveLiquidators: Int! + + " Number of unique daily liquidatees (accounts that got liquidated) " + dailyActiveLiquidatees: Int! + + " Number of unique daily transferrers (the sender in a Transfer) " + dailyActiveTransferrers: Int! + + " Number of unique daily accounts that executed a flash loan" + dailyActiveFlashloaners: Int! + + " Total number of deposits in a day " + dailyDepositCount: Int! + + " Total number of withdrawals in a day " + dailyWithdrawCount: Int! + + " Total number of borrows/mints in a day " + dailyBorrowCount: Int! + + " Total number of repayments/burns in a day " + dailyRepayCount: Int! + + " Total number of liquidations in a day " + dailyLiquidateCount: Int! + + " Total number of transfers in a day " + dailyTransferCount: Int! + + " Total number of flashloans in a day " + dailyFlashloanCount: Int! + + ##### Account/Position Data ##### + + " Number of positions in this market " + positionCount: Int! + + " Number of open positions in this market " + openPositionCount: Int! + + " Number of closed positions in this market " + closedPositionCount: Int! + + " Number of lending positions in this market. Note: this is cumulative and strictly increasing " + lendingPositionCount: Int! + + " Total number of lending positions touched in a day. This includes opening, closing, and modifying positions. " + dailyActiveLendingPositionCount: Int! + + " Number of borrowing positions in this market. Note: this is cumulative and strictly increasing " + borrowingPositionCount: Int! + + " Total number of borrow positions touched in a day. This includes opening, closing, and modifying positions. " + dailyActiveBorrowingPositionCount: Int! +} + +type MarketHourlySnapshot @entity @hourlySnapshot { + " { Smart contract address of the market }{ # of hours since Unix epoch time } " + id: Bytes! + + " Number of hours since Unix epoch time " + hours: Int! + + " The protocol this snapshot belongs to " + protocol: LendingProtocol! + + " The pool this snapshot belongs to " + market: Market! + + " Block number of this snapshot " + blockNumber: BigInt! + + " Timestamp of this snapshot " + timestamp: BigInt! + + " A unique identifier that can relate multiple markets together. e.g. a common address that they all share. This is useful for markets with multiple input tokens " + relation: Bytes + + ##### Incentives ##### + + " Additional tokens that are given as reward for position in a protocol, usually in liquidity mining programs. e.g. SUSHI in the Onsen program, MATIC for Aave Polygon " + rewardTokens: [RewardToken!] + + " Per-block reward token emission as of the current block normalized to a day, in token's native amount. This should be ideally calculated as the theoretical rate instead of the realized amount. " + rewardTokenEmissionsAmount: [BigInt!] + + " Per-block reward token emission as of the current block normalized to a day, in USD value. This should be ideally calculated as the theoretical rate instead of the realized amount. " + rewardTokenEmissionsUSD: [BigDecimal!] + + " Total supply of output tokens that are staked. Used to calculate reward APY. " + stakedOutputTokenAmount: BigInt + + ##### Quantitative Data ##### + + " Amount of input token in the market (same order as inputTokens) " + inputTokenBalance: BigInt! + + " Prices in USD of the input token (same order as inputTokens) " + inputTokenPriceUSD: BigDecimal! + + " Total supply of output token (same order as outputTokens) " + outputTokenSupply: BigInt + + " Prices in USD of the output token (same order as outputTokens) " + outputTokenPriceUSD: BigDecimal + + " Amount of input token per full share of output token. Only applies when the output token exists (note this is a ratio and not a percentage value, i.e. 1.05 instead of 105%) " + exchangeRate: BigDecimal + + " All interest rates for this input token. Should be in APR format " + rates: [InterestRate!] + + " Total amount of reserves (in USD) " + reserves: BigDecimal + + " Amount of input tokens borrowed in this market using variable interest rates (in native terms) " + variableBorrowedTokenBalance: BigInt + + " Amount of input tokens borrowed in this market using stable interest rates (in native terms) " + stableBorrowedTokenBalance: BigInt + + " Current TVL (Total Value Locked) of this market " + totalValueLockedUSD: BigDecimal! + + " All revenue generated by the market, accrued to the supply side. " + cumulativeSupplySideRevenueUSD: BigDecimal! + + " Hourly revenue generated by the market, accrued to the supply side. " + hourlySupplySideRevenueUSD: BigDecimal! + + " All revenue generated by the market, accrued to the protocol. " + cumulativeProtocolSideRevenueUSD: BigDecimal! + + " Hourly revenue generated by the market, accrued to the protocol. " + hourlyProtocolSideRevenueUSD: BigDecimal! + + " All revenue generated by the market. " + cumulativeTotalRevenueUSD: BigDecimal! + + " Hourly revenue generated by the market. " + hourlyTotalRevenueUSD: BigDecimal! + + " Current balance of all deposited assets (not historical cumulative), in USD. Same as pool TVL. " + totalDepositBalanceUSD: BigDecimal! + + " Sum of all deposits made in a given hour, in USD " + hourlyDepositUSD: BigDecimal! + + " Sum of all historical deposits in USD (only considers deposits and not withdrawals) " + cumulativeDepositUSD: BigDecimal! + + " Current balance of all borrowed/minted assets (not historical cumulative), in USD. " + totalBorrowBalanceUSD: BigDecimal! + + " Sum of all borrows/mints made in a given hour, in USD " + hourlyBorrowUSD: BigDecimal! + + " Sum of all historical borrows/mints in USD (i.e. total loan origination) " + cumulativeBorrowUSD: BigDecimal! + + " Total assets liquidated in a given hour, in USD. " + hourlyLiquidateUSD: BigDecimal! + + " Sum of all historical liquidations in USD " + cumulativeLiquidateUSD: BigDecimal! + + " Total assets withdrawn on a given hour, in USD. " + hourlyWithdrawUSD: BigDecimal! + + " Total assets repaid on a given hour, in USD. " + hourlyRepayUSD: BigDecimal! + + " Total assets transferred on a given hour, in USD. " + hourlyTransferUSD: BigDecimal! + + " Total assets flashloaned on a given hour, in USD. " + hourlyFlashloanUSD: BigDecimal! +} + +############################## +##### Account-Level Data ##### +############################## + +type Account @entity @regularPolling { + " { Account address } " + id: Bytes! + + " Number of positions this account has " + positionCount: Int! + + " All positions that belong to this account " + positions: [Position!]! @derivedFrom(field: "account") + + " Number of open positions this account has " + openPositionCount: Int! + + " Number of closed positions this account has " + closedPositionCount: Int! + + " Number of deposits this account made " + depositCount: Int! + + " All deposit events of this account " + deposits: [Deposit!]! @derivedFrom(field: "account") + + " Number of withdrawals this account made " + withdrawCount: Int! + + " All withdraw events of this account " + withdraws: [Withdraw!]! @derivedFrom(field: "account") + + " Number of borrows this account made " + borrowCount: Int! + + " All borrow events of this account " + borrows: [Borrow!]! @derivedFrom(field: "account") + + " Number of repays this account made " + repayCount: Int! + + " All repay events of this account " + repays: [Repay!]! @derivedFrom(field: "account") + + " Number of times this account liquidated a position " + liquidateCount: Int! + + " All liquidation events where this account was the liquidator " + liquidates: [Liquidate!]! @derivedFrom(field: "liquidator") + + " Number of times this account has been liquidated " + liquidationCount: Int! + + " All liquidation events where this account got liquidated " + liquidations: [Liquidate!]! @derivedFrom(field: "liquidatee") + + " Number of times this account has transferred " + transferredCount: Int! + + " All transfer events where this account was the sender " + transfers: [Transfer!]! @derivedFrom(field: "sender") + + " Number of times this account has received a transfer " + receivedCount: Int! + + " All transfer events where this account was the receiver " + receives: [Transfer!]! @derivedFrom(field: "receiver") + + " Number of times this account has executed a flashloan " + flashloanCount: Int! + + " All flashloan events where this account executed it " + flashloans: [Flashloan!]! @derivedFrom(field: "account") + + " The amount of rewards claimed by this account in USD (use the USD value at the time of claiming) " + rewardsClaimedUSD: BigDecimal +} + +# A position is defined as who has control over the collateral or debt +type Position @entity @regularPolling { + " { Account address }-{ Market address }-{ Position Side }-{ Optional: Interest Rate Type}-{ Counter } " + id: ID! + + " Account that owns this position " + account: Account! + + " The market in which this position was opened " + market: Market! + + " The asset in which this position was opened with " + asset: Token! + + " The hash of the transaction that opened this position " + hashOpened: Bytes! + + " The hash of the transaction that closed this position " + hashClosed: Bytes + + " Block number of when the position was opened " + blockNumberOpened: BigInt! + + " Timestamp when the position was opened " + timestampOpened: BigInt! + + " Block number of when the position was closed (0 if still open) " + blockNumberClosed: BigInt + + " Timestamp when the position was closed (0 if still open) " + timestampClosed: BigInt + + " Side of the position (either lender or borrower) " + side: PositionSide! + + " Type of interest rate used for this position (stable or variable). Generally for borrow side positions." + type: InterestRateType + + " Whether this position has been enabled as a collateral (only applies to LENDER positions). For protocols (e.g. MakerDAO) that doesn't require enabling explicitly, this will always be true. " + isCollateral: Boolean + + " Whether this position is being isolated from risk from other positions (only applies to LENDER positions). For protocols (e.g. Aave V3) this reduces risk exposure from other user positions. " + isIsolated: Boolean + + " Token balance in this position, in native amounts " + balance: BigInt! + + " Number of deposits related to this position " + depositCount: Int! + + " All deposit events of this position " + deposits: [Deposit!]! @derivedFrom(field: "position") + + " Number of withdrawals related to this position " + withdrawCount: Int! + + " All withdraw events of this position " + withdraws: [Withdraw!]! @derivedFrom(field: "position") + + " Number of borrows related to this position " + borrowCount: Int! + + " All borrow events of this position " + borrows: [Borrow!]! @derivedFrom(field: "position") + + " Number of repays related to this position " + repayCount: Int! + + " All repay events of this position " + repays: [Repay!]! @derivedFrom(field: "position") + + " Number of liquidations related to this position (incremented when this position is liquidated) " + liquidationCount: Int! + + " Liquidation event related to this position (if exists) " + liquidations: [Liquidate!]! @derivedFrom(field: "positions") + + " Number of times this position has transferred " + transferredCount: Int! + + " Number of times this position has received a transfer " + receivedCount: Int! + + " All transfer events related to this position " + transfers: [Transfer!]! @derivedFrom(field: "positions") + + " Position daily snapshots for open positions " + snapshots: [PositionSnapshot!]! @derivedFrom(field: "position") +} + +# Unlike other snapshots that are taken at a fixed time interval. Position +# snapshots should be taken after every event, including the opening and +# closing events. This will prevent an ever growing number of snapshots +# for positions that are not moving. As we are only recording the balance +# in token amounts instead of in USD, this will work well. +# Note that we only take snapshot for open positions. +type PositionSnapshot @entity(immutable: true) @regularPolling { + " { Position ID }-{ Transaction hash }-{ Log index } " + id: ID! + + " Transaction hash of the transaction that triggered this snapshot " + hash: Bytes! + + " Event log index. For transactions that don't emit event, create arbitrary index starting from 0 " + logIndex: Int! + + " Nonce of the transaction that triggered this snapshot " + nonce: BigInt! + + " Account that owns this position " + account: Account! + + " Position of this snapshot " + position: Position! + + " Token balance in this position, in native amounts " + balance: BigInt! + + " Token balance in this position, in USD " + balanceUSD: BigDecimal! + + " Block number of this snapshot " + blockNumber: BigInt! + + " Timestamp of this snapshot " + timestamp: BigInt! +} + +# Helper entity for calculating daily/hourly active users +type _ActiveAccount @entity(immutable: true) { + " { daily/hourly }-{ Address of the account }-{ Optional: Transaction Type }-{ Optional: Market Address }-{ Optional: Days/hours since Unix epoch } " + id: ID! +} + +# Helper entity for getting positions +type _PositionCounter @entity { + " { Account address }-{ Market address }-{ Position Side } " + id: ID! + + " Next count " + nextCount: Int! + + " The last timestamp this position was updated " + lastTimestamp: BigInt! +} + +############################ +##### Event-Level Data ##### +############################ + +""" +An event is any user action that occurs in a protocol. Generally, they are Ethereum events +emitted by a function in the smart contracts, stored in transaction receipts as event logs. +However, some user actions of interest are function calls that don't emit events. For example, +the deposit and withdraw functions in Yearn do not emit any events. In our subgraphs, we still +store them as events, although they are not technically Ethereum events emitted by smart +contracts. +""" +interface Event { + " { Transaction hash }{ Log index } " + id: Bytes! + + " Transaction hash of the transaction that emitted this event " + hash: Bytes! + + " Nonce of the transaction that emitted this event " + nonce: BigInt! + + " Event log index. For transactions that don't emit event, create arbitrary index starting from 0 " + logIndex: Int! + + " Price of gas in this transaction " + gasPrice: BigInt + + " Gas used in this transaction. (Optional because not every chain will support this) " + gasUsed: BigInt + + " Gas limit of this transaction. e.g. the amount of gas the sender will pay " + gasLimit: BigInt + + " Block number of this event " + blockNumber: BigInt! + + " Timestamp of this event " + timestamp: BigInt! + + " The market tokens are deposited to " + market: Market! + + " Token deposited " + asset: Token! + + " Amount of token deposited in native units " + amount: BigInt! + + " Amount of token deposited in USD " + amountUSD: BigDecimal! +} + +type Deposit implements Event @entity(immutable: true) @transaction { + " { Transaction hash }{ Log index } " + id: Bytes! + + " Transaction hash of the transaction that emitted this event " + hash: Bytes! + + " Nonce of the transaction that emitted this event " + nonce: BigInt! + + " Event log index. For transactions that don't emit event, create arbitrary index starting from 0 " + logIndex: Int! + + " Price of gas in this transaction " + gasPrice: BigInt + + " Gas used in this transaction. (Optional because not every chain will support this) " + gasUsed: BigInt + + " Gas limit of this transaction. e.g. the amount of gas the sender will pay " + gasLimit: BigInt + + " Block number of this event " + blockNumber: BigInt! + + " Timestamp of this event " + timestamp: BigInt! + + "Account where deposit was executed (e.g. a deposit on behalf of account)" + account: Account! + + " Account that executed the deposit (e.g. a deposit on behalf of account) " + accountActor: Account + + " The market tokens are deposited to " + market: Market! + + " The user position changed by this event " + position: Position! + + " Token deposited " + asset: Token! + + " Amount of token deposited in native units " + amount: BigInt! + + " Amount of token deposited in USD " + amountUSD: BigDecimal! +} + +type Withdraw implements Event @entity(immutable: true) @transaction { + " { Transaction hash }{ Log index } " + id: Bytes! + + " Transaction hash of the transaction that emitted this event " + hash: Bytes! + + " Nonce of the transaction that emitted this event " + nonce: BigInt! + + " Event log index. For transactions that don't emit event, create arbitrary index starting from 0 " + logIndex: Int! + + " Price of gas in this transaction " + gasPrice: BigInt + + " Gas used in this transaction. (Optional because not every chain will support this) " + gasUsed: BigInt + + " Gas limit of this transaction. e.g. the amount of gas the sender will pay " + gasLimit: BigInt + + " Block number of this event " + blockNumber: BigInt! + + " Timestamp of this event " + timestamp: BigInt! + + " Account that controls the position (e.g. the aToken owner initiating the withdraw in Aave) " + account: Account! + + " Account that receives the underlying withdrawn amount " + accountActor: Account + + " The market tokens are withdrew from " + market: Market! + + " The user position changed by this event " + position: Position! + + " Token withdrawn " + asset: Token! + + # Certain protocols (e.g. MakerDAO) uses a negative amount for withdraws. You + # should convert them to positive for consistency. + # e.g. Event log 27 in https://etherscan.io/tx/0xe957cf6252c7712c218c842c1ade672bf5ce529f8512f7a5ce7ebc8afa4ec690#eventlog + + " Amount of token withdrawn in native units " + amount: BigInt! + + " Amount of token withdrawn in USD " + amountUSD: BigDecimal! +} + +# For CDPs, use this for mint events +type Borrow implements Event @entity(immutable: true) @transaction { + " { Transaction hash }{ Log index } " + id: Bytes! + + " Transaction hash of the transaction that emitted this event " + hash: Bytes! + + " Nonce of the transaction that emitted this event " + nonce: BigInt! + + " Event log index. For transactions that don't emit event, create arbitrary index starting from 0 " + logIndex: Int! + + " Price of gas in this transaction " + gasPrice: BigInt + + " Gas used in this transaction. (Optional because not every chain will support this) " + gasUsed: BigInt + + " Gas limit of this transaction. e.g. the amount of gas the sender will pay " + gasLimit: BigInt + + " Block number of this event " + blockNumber: BigInt! + + " Timestamp of this event " + timestamp: BigInt! + + " Account that controls incurs debt in this transaction " + account: Account! + + " Account that receives the funds from the new debt " + accountActor: Account + + " The market tokens are borrowed/minted from " + market: Market! + + " The user position changed by this event " + position: Position! + + " Token borrowed " + asset: Token! + + " Amount of token borrowed in native units " + amount: BigInt! + + " Amount of token borrowed in USD " + amountUSD: BigDecimal! +} + +# For CDPs, use this for burn events +type Repay implements Event @entity(immutable: true) @transaction { + " { Transaction hash }{ Log index } " + id: Bytes! + + " Transaction hash of the transaction that emitted this event " + hash: Bytes! + + " Nonce of the transaction that emitted this event " + nonce: BigInt! + + " Event log index. For transactions that don't emit event, create arbitrary index starting from 0 " + logIndex: Int! + + " Price of gas in this transaction " + gasPrice: BigInt + + " Gas used in this transaction. (Optional because not every chain will support this) " + gasUsed: BigInt + + " Gas limit of this transaction. e.g. the amount of gas the sender will pay " + gasLimit: BigInt + + " Block number of this event " + blockNumber: BigInt! + + " Timestamp of this event " + timestamp: BigInt! + + " Account that reduces their debt on this transaction " + account: Account! + + " Account that is providing the funds to repay the debt " + accountActor: Account + + " The market tokens are repaid/burned to " + market: Market! + + " The user position changed by this event " + position: Position! + + " Token repaid/burned " + asset: Token! + + " Amount of token repaid/burned in native units " + amount: BigInt! + + " Amount of token repaid/burned in USD " + amountUSD: BigDecimal! +} + +type Liquidate implements Event @entity(immutable: true) @transaction { + " { Transaction hash }{ Log index } " + id: Bytes! + + " Transaction hash of the transaction that emitted this event " + hash: Bytes! + + " Nonce of the transaction that emitted this event " + nonce: BigInt! + + " Event log index. For transactions that don't emit event, create arbitrary index starting from 0 " + logIndex: Int! + + " Price of gas in this transaction " + gasPrice: BigInt + + " Gas used in this transaction. (Optional because not every chain will support this) " + gasUsed: BigInt + + " Gas limit of this transaction. e.g. the amount of gas the sender will pay " + gasLimit: BigInt + + " Block number of this event " + blockNumber: BigInt! + + " Timestamp of this event " + timestamp: BigInt! + + " Account that carried out the liquidation " + liquidator: Account! + + " Account that got liquidated " + liquidatee: Account! + + " The market of the collateral being used " + market: Market! + + " The user position changed by this event " + positions: [Position!]! + + " Asset repaid (borrowed) " + asset: Token! + + " Amount of collateral liquidated in native units " + amount: BigInt! + + " Amount of collateral liquidated in USD " + amountUSD: BigDecimal! + + " Amount of profit from liquidation in USD " + profitUSD: BigDecimal! +} + +# This entity is solely for transfers outside of normal protocol interaction +# e.g. transferring aTokens (collateral) directly, not a deposit. +# Transfers associated with other transactions in this schema should live there and not here. +# Note that only one transfer event should be created per transfer. +type Transfer implements Event @entity(immutable: true) @transaction { + " { Transaction hash }{ Log index } " + id: Bytes! + + " Transaction hash of the transaction that emitted this event " + hash: Bytes! + + " Nonce of the transaction that emitted this event " + nonce: BigInt! + + " Event log index. For transactions that don't emit event, create arbitrary index starting from 0 " + logIndex: Int! + + " Price of gas in this transaction " + gasPrice: BigInt + + " Gas used in this transaction. (Optional because not every chain will support this) " + gasUsed: BigInt + + " Gas limit of this transaction. e.g. the amount of gas the sender will pay " + gasLimit: BigInt + + " Block number of this event " + blockNumber: BigInt! + + " Timestamp of this event " + timestamp: BigInt! + + " The account that sent the tokens " + sender: Account! + + " The Account that received the tokens " + receiver: Account! + + " The user positions changed by this event " + positions: [Position!]! + + " The market associated with the token transfer " + market: Market! + + " The asset that was actually transferred. This could also include a debt token. " + asset: Token! + + " Amount of token transferred in native units " + amount: BigInt! + + " Amount of token transferred in USD " + amountUSD: BigDecimal! +} + +type Flashloan implements Event @entity(immutable: true) @transaction { + " { Transaction hash }{ Log index } " + id: Bytes! + + " Transaction hash of the transaction that emitted this event " + hash: Bytes! + + " Nonce of the transaction that emitted this event " + nonce: BigInt! + + " Event log index. For transactions that don't emit event, create arbitrary index starting from 0 " + logIndex: Int! + + " Price of gas in this transaction " + gasPrice: BigInt + + " Gas used in this transaction. (Optional because not every chain will support this) " + gasUsed: BigInt + + " Gas limit of this transaction. e.g. the amount of gas the sender will pay " + gasLimit: BigInt + + " Block number of this event " + blockNumber: BigInt! + + " Timestamp of this event " + timestamp: BigInt! + + " Account that receives the funds from the flashloan " + account: Account! + + " Account that initiates the flashloan " + accountActor: Account + + " The market in which this flashloan is executed " + market: Market! + + " Asset borrowed " + asset: Token! + + " Amount of asset borrowed in native units " + amount: BigInt! + + " Amount of asset borrowed in USD " + amountUSD: BigDecimal! + + " Amount of asset taken by protocol as a fee in native units " + feeAmount: BigInt + + " Amount of asset taken by protocol as a fee in USD " + feeAmountUSD: BigDecimal +} diff --git a/subgraphs/ebtc/src/constants.mustache b/subgraphs/ebtc/src/constants.mustache new file mode 100644 index 0000000000..fd17f611f6 --- /dev/null +++ b/subgraphs/ebtc/src/constants.mustache @@ -0,0 +1,42 @@ +import { BigDecimal, BigInt, Bytes } from "@graphprotocol/graph-ts"; +import { BIGDECIMAL_ONE, BIGDECIMAL_HUNDRED } from "./sdk/constants"; + +///////////////////////////// +///// Protocol Specific ///// +///////////////////////////// + +export const PROTOCOL_NAME = "eBTC"; +export const PROTOCOL_SLUG = "ebtc"; + +export const BTC_ADDRESS = Bytes.fromHexString( + "0xC04B0d3107736C32e19F1c62b2aF67BE61d63a05" + // TODO: since chainlink does not have a registry on goerli, we get the wbtc + // price from uniswap instead. however, for mainnet we have to get the + // native btc price from the chainlink registry! + //"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" +); +export const ETH_ADDRESS = Bytes.fromHexString( + "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" +); +export const EBTC_ADDRESS = Bytes.fromHexString( + "{{ eBTCToken.address }}" +); +export const STETH_ADDRESS = Bytes.fromHexString( + "{{ stethToken.address }}" +); +export const CDP_MANAGER = Bytes.fromHexString( + "{{ cdpManager.address }}" +); +export const ACTIVE_POOL = Bytes.fromHexString( + "{{ activePool.address }}" +); + +export const ACTIVE_POOL_CREATED_BLOCK = BigInt.fromI32({{ activePool.startBlock }}); +export const ACTIVE_POOL_CREATED_TIMESTAMP = BigInt.fromI32({{ activePool.createdAt }}); + +export const MINIMUM_COLLATERAL_RATIO = BigDecimal.fromString("1.1"); +export const MAXIMUM_LTV = BIGDECIMAL_ONE.div(MINIMUM_COLLATERAL_RATIO).times( + BIGDECIMAL_HUNDRED +); +export const LIQUIDATION_FEE_PERCENT = BigDecimal.fromString("0.5"); +export const LIQUIDATION_FEE = LIQUIDATION_FEE_PERCENT.div(BIGDECIMAL_HUNDRED); diff --git a/subgraphs/ebtc/src/entities/token.ts b/subgraphs/ebtc/src/entities/token.ts new file mode 100644 index 0000000000..3312a52289 --- /dev/null +++ b/subgraphs/ebtc/src/entities/token.ts @@ -0,0 +1,64 @@ +import { Address, BigDecimal, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Token } from "../../generated/schema"; +import { BTC_ADDRESS, EBTC_ADDRESS, STETH_ADDRESS } from "../constants"; +import { BIGDECIMAL_ONE } from "../sdk/constants"; +import { bigIntToBigDecimal } from "../sdk/util/numbers"; +import { getUsdPrice } from "../prices"; + +export function getBtcToken(): Token { + const token = new Token(BTC_ADDRESS); + token.name = "Bitcoin"; + token.symbol = "BTC"; + token.decimals = 8; + token.save(); + return token; +} + +export function getCollToken(): Token { + const token = new Token(STETH_ADDRESS); + token.name = "Staked Ether"; + token.symbol = "stETH"; + token.decimals = 18; + token.save(); + return token; +} + +export function getEbtcToken(): Token { + const token = new Token(EBTC_ADDRESS); + token.name = "EBTC Stablecoin"; + token.symbol = "EBTC"; + token.decimals = 18; + token.save(); + return token; +} + +export function setCurrentBtcPrice(block: ethereum.Block): void { + const btc = getBtcToken(); + btc.lastPriceUSD = getUsdPrice( + Address.fromBytes(BTC_ADDRESS), + BIGDECIMAL_ONE + ); + btc.lastPriceBlockNumber = block.number; + btc.save(); +} + +export function getCurrentBtcPrice(): BigDecimal { + const btcToken = Token.load(BTC_ADDRESS); + return btcToken!.lastPriceUSD!; +} + +export function setCurrentCollPrice( + block: ethereum.Block, + stethBtcRatio: BigInt +): void { + const coll = getCollToken(); + const btcPrice = getCurrentBtcPrice(); + coll.lastPriceUSD = btcPrice.times(bigIntToBigDecimal(stethBtcRatio)); + coll.lastPriceBlockNumber = block.number; + coll.save(); +} + +export function getCurrentCollPrice(): BigDecimal { + const stethToken = Token.load(STETH_ADDRESS); + return stethToken!.lastPriceUSD!; +} diff --git a/subgraphs/ebtc/src/mapping/PriceFeed.ts b/subgraphs/ebtc/src/mapping/PriceFeed.ts new file mode 100644 index 0000000000..a0631aee37 --- /dev/null +++ b/subgraphs/ebtc/src/mapping/PriceFeed.ts @@ -0,0 +1,12 @@ +import { LastGoodPriceUpdated } from "../../generated/PriceFeed/PriceFeed"; +import { setCurrentBtcPrice, setCurrentCollPrice } from "../entities/token"; + +/** + * Emitted whenever latest stETH/BTC price is fetched from oracle + * + * @param event LastGoodPriceUpdated event + */ +export function handleLastGoodPriceUpdated(event: LastGoodPriceUpdated): void { + setCurrentBtcPrice(event.block); + setCurrentCollPrice(event.block, event.params._lastGoodPrice); +} diff --git a/subgraphs/ebtc/src/prices/README.md b/subgraphs/ebtc/src/prices/README.md new file mode 100644 index 0000000000..51fc9fb576 --- /dev/null +++ b/subgraphs/ebtc/src/prices/README.md @@ -0,0 +1,240 @@ +# Price Oracle + +## Configuration + +In `subgraph.yaml`, add the following code snippet inside the `abis` section of the `datasources` which is going to fetch prices of token using the `Price Oracle`. +**NOTE**: Include the following code snippet in each of the datasources, that is dependent on the `Price Oracle` and update imports in each file inside oracle folder. + +``` +########################################### +############## Price Oracle ############### +########################################### +# ERC20 +- name: _ERC20 + file: ./abis/Prices/ERC20.json +# Curve Contracts +- name: CurvePool + file: ./abis/Prices/Curve/Pool.json +- name: CurveRegistry + file: ./abis/Prices/Curve/Registry.json +- name: CalculationsCurve + file: ./abis/Prices/Calculations/Curve.json +# YearnLens Contracts +- name: YearnLensContract + file: ./abis/Prices/YearnLens.json +# Aave Oracle Contract +- name: AaveOracleContract + file: ./abis/Prices/AaveOracle.json +# SushiSwap Contracts +- name: CalculationsSushiSwap + file: ./abis/Prices/Calculations/SushiSwap.json +# ChainLink Contracts +- name: ChainLinkContract + file: ./abis/Prices/ChainLink.json +# Uniswap Contracts +- name: UniswapRouter + file: ./abis/Prices/Uniswap/Router.json +- name: UniswapFactory + file: ./abis/Prices/Uniswap/Factory.json +- name: UniswapPair + file: ./abis/Prices/Uniswap/Pair.json +``` + +## Usage + +Following are some ways through which you can get the prices of tokens: + +``` +import { BigDecimal } from "@graphprotocol/graph-ts"; +import { getUsdPricePerToken, getUsdPrice } from "../Oracle"; + +// Method 1 +// Using function getUsdPricePerToken(tokenAddr: Address): CustomPriceType + +let tokenPrice: BigDecimal; +let fetchPrice = getUsdPricePerToken(tokenAddr); + +// fetchPrice.reverted: Bool +// fetchPrice.usdPrice: BigDecimal +// fetchPrice.decimals: number + +tokenPrice = fetchPrice.usdPrice * amount + +// Method 2 +// Using function getUsdPrice(tokenAddr: Address, amount: BigDecimal): BigDecimal + +let tokenPrice = getUsdPrice(tokenAddr, amount); +``` + +## Optimizations + +- Reorder the methods present in `index.ts`, depending on which method works best for you. + +## Folder Structure + +``` +Prices +├── calculations +│ ├── CalculationsCurve.ts +│ └── CalculationsSushiSwap.ts +├── common +│ ├── types.ts +│ ├── constants.ts +│ └── utils.ts +├── config +│ ├── arbitrum.ts +│ ├── aurora.ts +│ ├── avalanche.ts +│ ├── bsc.ts +│ ├── fantom.ts +│ ├── gnosis.ts +│ ├── harmony.ts +│ ├── mainnet.ts +│ ├── moonbeam.ts +│ ├── optimism.ts +│ └── polygon.ts +├── oracles +│ ├── AaveOracle.ts +│ ├── ChainLinkFeed.ts +│ └── YearnLensOracle.ts +├── routers +│ ├── CurveRouter.ts +│ └── UniswapForksRouter.ts +│── README.md +└── index.ts +``` + +## Development Status + +🔨 = In progress. +🛠 = Feature complete. Additional testing required. +`MultiCall` = If the method uses more than two `JSON RPC Call`. + +### Arbitrum + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| YearnLens | `0x043518ab266485dc085a1db095b8d9c2fc78e9b9` | `2396321` | ❎ | +| AaveOracle | `0xb56c2F0B653B2e0b10C9b928C8580Ac5Df02C7C7` | `7740843` | ❎ | +| Curve | `0x3268c3bda100ef0ff3c2d044f23eab62c80d78d2` | `11707234` | ❎ | +| SushiSwap | `0x5ea7e501c9a23f4a76dc7d33a11d995b13a1dd25` | `2396120` | ❎ | +| CurveRouters | | | | +| | `0x445FE580eF8d70FF569aB36e80c647af338db351` | `1362056` | ✅ | +| | `0x0E9fBb167DF83EdE3240D6a5fa5d40c6C6851e15` | `4530115` | ✅ | +| UniswapForks | | | | +| | `0x1b02da8cb0d097eb8d57a175b88c7d8b47997506` | `73` | ✅ | + +### Aurora + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| CurveRouters | | | | +| | `0x5B5CFE992AdAC0C9D48E05854B2d91C73a003858` | `62440525` | ✅ | +| UniswapForks | | | | +| | `0x2CB45Edb4517d5947aFdE3BEAbF95A582506858B` | | ✅ | + +### Avalanche + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| AaveOracle | `0xEBd36016B3eD09D4693Ed4251c67Bd858c3c7C9C` | `11970477` | ❎ | +| CurveRouters | | | | +| | `0x8474DdbE98F5aA3179B3B3F5942D724aFcdec9f6` | `5254206` | ✅ | +| | `0x90f421832199e93d01b64DaF378b183809EB0988` | `9384663` | ✅ | +| UniswapForks | | | | +| | `0x60aE616a2155Ee3d9A68541Ba4544862310933d4` | `2486393` | ✅ | +| | `0xE54Ca86531e17Ef3616d22Ca28b0D458b6C89106` | `56879` | ✅ | +| | `0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506` | `506236` | ✅ | + +### BSC + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| UniswapForks | | | | +| | `0x10ED43C718714eb63d5aA57B78B54704E256024E` | `6810080` | ✅ | +| | `0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F` | `586899` | ✅ | + +### Fantom + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| YearnLens | `0x57aa88a0810dfe3f9b71a9b179dd8bf5f956c46a` | `17091856` | ❎ | +| Curve | `0x0b53e9df372e72d8fdcdbedfbb56059957a37128` | `27067399` | ❎ | +| SushiSwap | `0x44536de2220987d098d1d29d3aafc7f7348e9ee4` | `3809480` | ❎ | +| CurveRouters | | | | +| | `0x0f854EA9F38ceA4B1c2FC79047E9D0134419D5d6` | `5655918` | ✅ | +| | `0x4fb93D7d320E8A263F22f62C2059dFC2A8bCbC4c` | `27552509` | ✅ | +| UniswapForks | | | | +| | `0xbe4fc72f8293f9d3512d58b969c98c3f676cb957` | `3796241` | ✅ | +| | `0x16327E3FbDaCA3bcF7E38F5Af2599D2DDc33aE52` | `4250168` | ✅ | +| | `0x1b02da8cb0d097eb8d57a175b88c7d8b47997506` | `2457904` | ✅ | + +### Gnosis + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| CurveRouters | | | | +| | `0x55E91365697EB8032F98290601847296eC847210` | `20754886` | ✅ | +| | `0x8A4694401bE8F8FCCbC542a3219aF1591f87CE17` | `23334728` | ✅ | +| UniswapForks | | | | +| | `0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506` | `14735910` | ✅ | + +### Harmony + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| AaveOracle | `0x3c90887ede8d65ccb2777a5d577beab2548280ad` | `23930344` | ❎ | +| CurveRouters | | | | +| | `0x0a53FaDa2d943057C47A301D25a4D9b3B8e01e8E` | `18003250` | ✅ | +| UniswapForks | | | | +| | `0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506` | `11256069` | ✅ | + +### Mainnet + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| YearnLens | `0x83d95e0d5f402511db06817aff3f9ea88224b030` | `12242339` | ❎ | +| ChainLink | `0x47Fb2585D2C56Fe188D0E6ec628a38b74fCeeeDf` | `12864088` | ❎ | +| Curve | `0x25BF7b72815476Dd515044F9650Bf79bAd0Df655` | `12370088` | ❎ | +| SushiSwap | `0x8263e161A855B644f582d9C164C66aABEe53f927` | `12692284` | ❎ | +| CurveRouters | | | | +| | `0x7D86446dDb609eD0F5f8684AcF30380a356b2B4c` | `11154794` | ✅ | +| | `0x8F942C20D02bEfc377D41445793068908E2250D0` | `13986752` | ✅ | +| UniswapForks | | | | +| | `0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F` | `10794261` | ✅ | +| | `0x7a250d5630b4cf539739df2c5dacb4c659f2488d` | `10207858` | ✅ | + +### Moonbeam + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| CurveRouters | | | | +| | `0xC2b1DF84112619D190193E48148000e3990Bf627` | `1452049` | ✅ | +| UniswapForks | | | | +| | `0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506` | `503734` | ✅ | + +### Optimism + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| YearnLens | `0xb082d9f4734c535d9d80536f7e87a6f4f471bf65` | `18109291` | ❎ | +| AaveOracle | `0xD81eb3728a631871a7eBBaD631b5f424909f0c77` | `4365625` | ❎ | +| Curve | `0x0ffe8434eae67c9838b12c3cd11ac4005daa7227` | `18368996` | ❎ | +| SushiSwap | `0x5fd3815dcb668200a662114fbc9af13ac0a55b4d` | `18216910` | ❎ | +| CurveRouters | | | | +| | `0xC5cfaDA84E902aD92DD40194f0883ad49639b023` | `2373837` | ✅ | +| | `0x7DA64233Fefb352f8F501B357c018158ED8aA455` | `3729171` | ✅ | +| UniswapForks | | | | +| | `0x9c12939390052919aF3155f41Bf4160Fd3666A6f` | `19702709` | ✅ | + +### Polygon + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| AaveOracle | `0xb023e699F5a33916Ea823A16485e259257cA8Bd1` | `25825996` | ❎ | +| CurveRouters | | | | +| | `0x094d12e5b541784701FD8d65F11fc0598FBC6332` | `13991825` | ✅ | +| | `0x47bB542B9dE58b970bA50c9dae444DDB4c16751a` | `23556360` | ✅ | +| UniswapForks | | | | +| | `0xa5e0829caced8ffdd4de3c43696c57f7d7a678ff` | `4931900` | ✅ | +| | `0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506` | `11333235` | ✅ | diff --git a/subgraphs/ebtc/src/prices/calculations/CalculationsCurve.ts b/subgraphs/ebtc/src/prices/calculations/CalculationsCurve.ts new file mode 100644 index 0000000000..b659618a04 --- /dev/null +++ b/subgraphs/ebtc/src/prices/calculations/CalculationsCurve.ts @@ -0,0 +1,47 @@ +import * as utils from "../common/utils"; +import * as constants from "../common/constants"; +import { CustomPriceType, OracleContract } from "../common/types"; +import { Address, BigDecimal, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { CalculationsCurve as CalculationsCurveContract } from "../../../generated/PriceFeed/CalculationsCurve"; + +export function getCalculationsCurveContract( + contract: OracleContract, + block: ethereum.Block | null = null +): CalculationsCurveContract | null { + if ( + (block && contract.startBlock.gt(block.number)) || + utils.isNullAddress(contract.address) + ) + return null; + + return CalculationsCurveContract.bind(contract.address); +} + +export function getTokenPriceUSDC( + tokenAddr: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const config = utils.getConfig(); + + if (!config || config.curveCalculationsBlacklist().includes(tokenAddr)) + return new CustomPriceType(); + + const calculationCurveContract = getCalculationsCurveContract( + config.curveCalculations(), + block + ); + if (!calculationCurveContract) return new CustomPriceType(); + + const tokenPrice: BigDecimal = utils + .readValue( + calculationCurveContract.try_getCurvePriceUsdc(tokenAddr), + constants.BIGINT_ZERO + ) + .toBigDecimal(); + + return CustomPriceType.initialize( + tokenPrice, + constants.DEFAULT_USDC_DECIMALS, + constants.OracleType.CURVE_CALCULATIONS + ); +} diff --git a/subgraphs/ebtc/src/prices/calculations/CalculationsSushiswap.ts b/subgraphs/ebtc/src/prices/calculations/CalculationsSushiswap.ts new file mode 100644 index 0000000000..9826c68c3a --- /dev/null +++ b/subgraphs/ebtc/src/prices/calculations/CalculationsSushiswap.ts @@ -0,0 +1,47 @@ +import * as utils from "../common/utils"; +import * as constants from "../common/constants"; +import { CustomPriceType, OracleContract } from "../common/types"; +import { Address, BigDecimal, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { CalculationsSushiSwap as CalculationsSushiContract } from "../../../generated/PriceFeed/CalculationsSushiSwap"; + +export function getSushiSwapContract( + contract: OracleContract, + block: ethereum.Block | null = null +): CalculationsSushiContract | null { + if ( + (block && contract.startBlock.gt(block.number)) || + utils.isNullAddress(contract.address) + ) + return null; + + return CalculationsSushiContract.bind(contract.address); +} + +export function getTokenPriceUSDC( + tokenAddr: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const config = utils.getConfig(); + + if (!config || config.sushiCalculationsBlacklist().includes(tokenAddr)) + return new CustomPriceType(); + + const calculationSushiContract = getSushiSwapContract( + config.sushiCalculations(), + block + ); + if (!calculationSushiContract) return new CustomPriceType(); + + const tokenPrice: BigDecimal = utils + .readValue( + calculationSushiContract.try_getPriceUsdc(tokenAddr), + constants.BIGINT_ZERO + ) + .toBigDecimal(); + + return CustomPriceType.initialize( + tokenPrice, + constants.DEFAULT_USDC_DECIMALS, + constants.OracleType.SUSHI_CALCULATIONS + ); +} diff --git a/subgraphs/ebtc/src/prices/common/constants.ts b/subgraphs/ebtc/src/prices/common/constants.ts new file mode 100644 index 0000000000..32100b7a08 --- /dev/null +++ b/subgraphs/ebtc/src/prices/common/constants.ts @@ -0,0 +1,38 @@ +import { Address, BigDecimal, BigInt } from "@graphprotocol/graph-ts"; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////// COMMON //////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export namespace NULL { + export const TYPE_STRING = "0x0000000000000000000000000000000000000000"; + export const TYPE_ADDRESS = Address.fromString(TYPE_STRING); +} + +export namespace OracleType { + export const AAVE_ORACLE = "AaveOracle"; + export const CURVE_ROUTER = "CurveRouter"; + export const CHAINLINK_FEED = "ChainlinkFeed"; + export const YEARN_LENS_ORACLE = "YearnLensOracle"; + export const CURVE_CALCULATIONS = "CurveCalculations"; + export const UNISWAP_FORKS_ROUTER = "UniswapForksRouter"; + export const SUSHI_CALCULATIONS = "SushiswapCalculations"; +} + +export const CHAIN_LINK_USD_ADDRESS = Address.fromString( + "0x0000000000000000000000000000000000000348" +); + +export const PRICE_LIB_VERSION = "1.2.0"; + +export const BIGINT_ZERO = BigInt.fromI32(0); +export const BIGINT_ONE = BigInt.fromI32(1); +export const BIGINT_TEN = BigInt.fromI32(10); +export const BIGINT_TEN_THOUSAND = BigInt.fromI32(10000); + +export const BIGDECIMAL_ZERO = new BigDecimal(BIGINT_ZERO); +export const BIGDECIMAL_USD_PRICE = BigDecimal.fromString("1000000"); + +export const AAVE_ORACLE_DECIMALS = 8; +export const DEFAULT_USDC_DECIMALS = 6; +export const DEFAULT_DECIMALS = BigInt.fromI32(18); diff --git a/subgraphs/ebtc/src/prices/common/types.ts b/subgraphs/ebtc/src/prices/common/types.ts new file mode 100644 index 0000000000..7227bf05c5 --- /dev/null +++ b/subgraphs/ebtc/src/prices/common/types.ts @@ -0,0 +1,103 @@ +import * as constants from "./constants"; +import { Address, BigDecimal, BigInt } from "@graphprotocol/graph-ts"; + +export class Wrapped { + inner: T; + + constructor(inner: T) { + this.inner = inner; + } +} + +export class OracleContract { + private _contractAddress: string; + private _contractStartBlock: i32; + + constructor( + contractAddress: string = constants.NULL.TYPE_STRING, + startBlock: i32 = -1 + ) { + this._contractAddress = contractAddress; + this._contractStartBlock = startBlock; + } + + get address(): Address { + return Address.fromString(this._contractAddress); + } + + get startBlock(): BigInt { + return BigInt.fromI32(this._contractStartBlock); + } +} + +export class CustomPriceType { + // `null` indicates a reverted call. + private _usdPrice: Wrapped; + private _decimals: Wrapped; + private _oracleType: string; + + constructor() { + this._usdPrice = new Wrapped(constants.BIGDECIMAL_ZERO); + this._decimals = new Wrapped(constants.BIGINT_ZERO.toI32() as u8); + this._oracleType = ""; + } + + static initialize( + _usdPrice: BigDecimal, + _decimals: i32 = 0, + _oracleType: string = "" + ): CustomPriceType { + const result = new CustomPriceType(); + result._usdPrice = new Wrapped(_usdPrice); + result._decimals = new Wrapped(_decimals as u8); + result._oracleType = _oracleType; + + return result; + } + + get reverted(): bool { + return this._usdPrice.inner == constants.BIGDECIMAL_ZERO; + } + + get usdPrice(): BigDecimal { + return changetype>(this._usdPrice).inner.div( + constants.BIGINT_TEN.pow(this.decimals as u8).toBigDecimal() + ); + } + + get decimals(): i32 { + return changetype>(this._decimals).inner; + } + + get oracleType(): string { + return this._oracleType; + } +} + +export interface Configurations { + network(): string; + + yearnLens(): OracleContract; + chainLink(): OracleContract; + yearnLensBlacklist(): Address[]; + + aaveOracle(): OracleContract; + aaveOracleBlacklist(): Address[]; + + curveCalculations(): OracleContract; + curveCalculationsBlacklist(): Address[]; + + sushiCalculations(): OracleContract; + sushiCalculationsBlacklist(): Address[]; + + uniswapForks(): OracleContract[]; + curveRegistry(): OracleContract[]; + + hardcodedStables(): Address[]; + + ethAddress(): Address; + wethAddress(): Address; + usdcAddress(): Address; + + usdcTokenDecimals(): BigInt; +} diff --git a/subgraphs/ebtc/src/prices/common/utils.ts b/subgraphs/ebtc/src/prices/common/utils.ts new file mode 100644 index 0000000000..450300e896 --- /dev/null +++ b/subgraphs/ebtc/src/prices/common/utils.ts @@ -0,0 +1,99 @@ +import * as BSC from "../config/bsc"; +import * as CELO from "../config/celo"; +import * as FUSE from "../config/fuse"; +import * as XDAI from "../config/gnosis"; +import * as CRONOS from "../config/cronos"; +import * as AURORA from "../config/aurora"; +import * as FANTOM from "../config/fantom"; +import * as GOERLI from "../config/goerli"; +import * as POLYGON from "../config/polygon"; +import * as MAINNET from "../config/mainnet"; +import * as HARMONY from "../config/harmony"; +import * as MOONBEAM from "../config/moonbeam"; +import * as OPTIMISM from "../config/optimism"; +import * as AVALANCHE from "../config/avalanche"; +import * as ARBITRUM_ONE from "../config/arbitrum"; + +import { Configurations } from "./types"; +import * as constants from "./constants"; +import * as TEMPLATE from "../config/template"; +import { _ERC20 } from "../../../generated/PriceFeed/_ERC20"; +import { Address, BigInt, dataSource, ethereum } from "@graphprotocol/graph-ts"; + +export function isNullAddress(tokenAddr: Address): boolean { + return tokenAddr.equals(constants.NULL.TYPE_ADDRESS); +} + +export function readValue( + callResult: ethereum.CallResult, + defaultValue: T +): T { + return callResult.reverted ? defaultValue : callResult.value; +} + +export function getTokenName(tokenAddr: Address): string { + const tokenContract = _ERC20.bind(tokenAddr); + const name = readValue(tokenContract.try_name(), ""); + + return name; +} + +export function getTokenDecimals(tokenAddr: Address): BigInt { + const tokenContract = _ERC20.bind(tokenAddr); + + const decimals = readValue( + tokenContract.try_decimals(), + constants.DEFAULT_DECIMALS + ); + + return decimals; +} + +export function getTokenSupply(tokenAddr: Address): BigInt { + const tokenContract = _ERC20.bind(tokenAddr); + + const totalSupply = readValue( + tokenContract.try_totalSupply(), + constants.BIGINT_ONE + ); + + return totalSupply; +} + +export function getConfig(): Configurations { + const network = dataSource.network(); + + if (network == XDAI.NETWORK_STRING) { + return new XDAI.config(); + } else if (network == AURORA.NETWORK_STRING) { + return new AURORA.config(); + } else if (network == BSC.NETWORK_STRING) { + return new BSC.config(); + } else if (network == FANTOM.NETWORK_STRING) { + return new FANTOM.config(); + } else if (network == POLYGON.NETWORK_STRING) { + return new POLYGON.config(); + } else if (network == MAINNET.NETWORK_STRING) { + return new MAINNET.config(); + } else if (network == HARMONY.NETWORK_STRING) { + return new HARMONY.config(); + } else if (network == MOONBEAM.NETWORK_STRING) { + return new MOONBEAM.config(); + } else if (network == OPTIMISM.NETWORK_STRING) { + return new OPTIMISM.config(); + } else if (network == AVALANCHE.NETWORK_STRING) { + return new AVALANCHE.config(); + } else if (network == ARBITRUM_ONE.NETWORK_STRING) { + return new ARBITRUM_ONE.config(); + } else if (network == CRONOS.NETWORK_STRING) { + return new CRONOS.config(); + } else if (network == CELO.NETWORK_STRING) { + return new CELO.config(); + } else if (network == FUSE.NETWORK_STRING) { + return new FUSE.config(); + } else if (network == GOERLI.NETWORK_STRING) { + return new GOERLI.config(); + } + + return new TEMPLATE.config(); +} diff --git a/subgraphs/ebtc/src/prices/config/arbitrum.ts b/subgraphs/ebtc/src/prices/config/arbitrum.ts new file mode 100644 index 0000000000..b95c07b52c --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/arbitrum.ts @@ -0,0 +1,138 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "arbitrum-one"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract( + "0x043518ab266485dc085a1db095b8d9c2fc78e9b9", + 2396321 +); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract( + "0xb56c2f0b653b2e0b10c9b928c8580ac5df02c7c7", + 7740843 +); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract( + "0x5ea7e501c9a23f4a76dc7d33a11d995b13a1dd25", + 2396120 +); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract( + "0x3268c3bda100ef0ff3c2d044f23eab62c80d78d2", + 11707234 +); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = [ + new OracleContract("0x445fe580ef8d70ff569ab36e80c647af338db351", 1362056), + new OracleContract("0x0e9fbb167df83ede3240d6a5fa5d40c6c6851e15", 4530115), +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0x1b02da8cb0d097eb8d57a175b88c7d8b47997506", 73), // SushiSwap +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" +); +export const WETH_ADDRESS = Address.fromString( + "0x82af49447d8a07e3bd95bd0d56f35241523fbab1" +); +export const USDC_ADDRESS = Address.fromString( + "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/aurora.ts b/subgraphs/ebtc/src/prices/config/aurora.ts new file mode 100644 index 0000000000..8cd2f4a42e --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/aurora.ts @@ -0,0 +1,125 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "aurora"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = [ + new OracleContract("0x5b5cfe992adac0c9d48e05854b2d91c73a003858", 62440526), +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0x2cb45edb4517d5947afde3beabf95a582506858b", 49607893), // TriSolaris +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0x8bec47865ade3b172a928df8f990bc7f2a3b9f79" // Aurora +); +export const WETH_ADDRESS = Address.fromString( + "0xc9bdeed33cd01541e1eed10f90519d2c06fe3feb" // WETH +); +export const USDC_ADDRESS = Address.fromString( + "0xb12bfca5a55806aaf64e99521918a4bf0fc40802" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/avalanche.ts b/subgraphs/ebtc/src/prices/config/avalanche.ts new file mode 100644 index 0000000000..70e23839d8 --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/avalanche.ts @@ -0,0 +1,132 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "avalanche"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); + +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract( + "0xebd36016b3ed09d4693ed4251c67bd858c3c7c9c", + 11970477 +); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = [ + new OracleContract("0x8474ddbe98f5aa3179b3b3f5942d724afcdec9f6", 5254206), + new OracleContract("0x90f421832199e93d01b64daf378b183809eb0988", 9384663), +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0x60ae616a2155ee3d9a68541ba4544862310933d4", 2486393), // TraderJOE + new OracleContract("0xe54ca86531e17ef3616d22ca28b0d458b6c89106", 56879), // Pangolin + new OracleContract("0x1b02da8cb0d097eb8d57a175b88c7d8b47997506", 506236), // Sushiswap +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0x49d5c2bdffac6ce2bfdb6640f4f80f226bc10bab" +); +export const WETH_ADDRESS = Address.fromString( + "0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7" +); +export const USDC_ADDRESS = Address.fromString( + "0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/bsc.ts b/subgraphs/ebtc/src/prices/config/bsc.ts new file mode 100644 index 0000000000..d79139fca2 --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/bsc.ts @@ -0,0 +1,123 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import * as constants from "../common/constants"; +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "bsc"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = []; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0x10ed43c718714eb63d5aa57b78b54704e256024e", 6810080), // PancakeSwap v2 + new OracleContract("0x05ff2b0db69458a0750badebc4f9e13add608c7f", 586899), // PancakeSwap v1 +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(18); + +export const ETH_ADDRESS = constants.NULL.TYPE_ADDRESS; +export const WETH_ADDRESS = Address.fromString( + "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c" +); +export const USDC_ADDRESS = Address.fromString( + "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/celo.ts b/subgraphs/ebtc/src/prices/config/celo.ts new file mode 100644 index 0000000000..45ad9469f4 --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/celo.ts @@ -0,0 +1,124 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "celo"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = []; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0xe3d8bd6aed4f159bc8000a9cd47cffdb95f96121", 5272598), // Ubeswap + new OracleContract("0x1b02da8cb0d097eb8d57a175b88c7d8b47997506", 7254057), // Sushiswap +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0x122013fd7df1c6f636a5bb8f03108e876548b455" +); +export const WETH_ADDRESS = Address.fromString( + "0x471ece3750da237f93b8e339c536989b8978a438" // Celo native asset (CELO) +); +export const USDC_ADDRESS = Address.fromString( + "0x37f750b7cc259a2f741af45294f6a16572cf5cad" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/cronos.ts b/subgraphs/ebtc/src/prices/config/cronos.ts new file mode 100644 index 0000000000..d47070c52b --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/cronos.ts @@ -0,0 +1,123 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "cronos"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = []; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0x145863eb42cf62847a6ca784e6416c1682b1b2ae", 5247), // VVS Finance +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0xe44fd7fcb2b1581822d0c862b68222998a0c299a" +); +export const WETH_ADDRESS = Address.fromString( + "0x5c7f8a570d578ed84e63fdfa7b1ee72deae1ae23" // Wrapped CRO (WCRO) +); +export const USDC_ADDRESS = Address.fromString( + "0xc21223249ca28397b4b6541dffaecc539bff0c59" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/fantom.ts b/subgraphs/ebtc/src/prices/config/fantom.ts new file mode 100644 index 0000000000..afec8235f5 --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/fantom.ts @@ -0,0 +1,137 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "fantom"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract( + "0x57aa88a0810dfe3f9b71a9b179dd8bf5f956c46a", + 17091856 +); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract( + "0x44536de2220987d098d1d29d3aafc7f7348e9ee4", + 3809480 +); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract( + "0x0b53e9df372e72d8fdcdbedfbb56059957a37128", + 27067399 +); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = [ + new OracleContract("0x0f854ea9f38cea4b1c2fc79047e9d0134419d5d6", 5655918), + new OracleContract("0x4fb93d7d320e8a263f22f62c2059dfc2a8bcbc4c", 27552509), +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0xbe4fc72f8293f9d3512d58b969c98c3f676cb957", 3796241), // Uniswap v2 + new OracleContract("0x16327e3fbdaca3bcf7e38f5af2599d2ddc33ae52", 4250168), // Spiritswap + new OracleContract("0x1b02da8cb0d097eb8d57a175b88c7d8b47997506", 2457904), // Sushiswap +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0x658b0c7613e890ee50b8c4bc6a3f41ef411208ad" +); +export const WETH_ADDRESS = Address.fromString( + "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83" +); +export const USDC_ADDRESS = Address.fromString( + "0x04068da6c83afcfa0e13ba15a6696662335d5b75" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/fuse.ts b/subgraphs/ebtc/src/prices/config/fuse.ts new file mode 100644 index 0000000000..c8b308b2b7 --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/fuse.ts @@ -0,0 +1,124 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "fuse"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = []; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0xe3f85aad0c8dd7337427b9df5d0fb741d65eeeb5", 15645719), // Voltage Finance + new OracleContract("0x1b02da8cb0d097eb8d57a175b88c7d8b47997506", 12936314), // Sushiswap +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0xa722c13135930332eb3d749b2f0906559d2c5b99" +); +export const WETH_ADDRESS = Address.fromString( + "0x0be9e53fd7edac9f859882afdda116645287c629" // Wrapped Fuse (WFUSE) +); +export const USDC_ADDRESS = Address.fromString( + "0x620fd5fa44be6af63715ef4e65ddfa0387ad13f5" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/gnosis.ts b/subgraphs/ebtc/src/prices/config/gnosis.ts new file mode 100644 index 0000000000..cacea20084 --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/gnosis.ts @@ -0,0 +1,126 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING: string = "xdai"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = [ + new OracleContract("0x55e91365697eb8032f98290601847296ec847210", 20754886), + new OracleContract("0x8a4694401be8f8fccbc542a3219af1591f87ce17", 23334728), +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0x1b02da8cb0d097eb8d57a175b88c7d8b47997506", 14735910), // SushiSwap +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1" +); +export const WETH_ADDRESS = Address.fromString( + "0xe91d153e0b41518a2ce8dd3d7944fa863463a97d" +); +export const USDC_ADDRESS = Address.fromString( + "0xddafbb505ad214d7b80b1f830fccc89b60fb7a83" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/goerli.ts b/subgraphs/ebtc/src/prices/config/goerli.ts new file mode 100644 index 0000000000..ff353b4923 --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/goerli.ts @@ -0,0 +1,122 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "goerli"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = []; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0x7a250d5630b4cf539739df2c5dacb4c659f2488d", 2822883), // Uniswap +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" +); +export const WETH_ADDRESS = Address.fromString( + "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6" +); +export const USDC_ADDRESS = Address.fromString( + "0xD87Ba7A50B2E7E660f678A895E4B72E7CB4CCd9C" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/harmony.ts b/subgraphs/ebtc/src/prices/config/harmony.ts new file mode 100644 index 0000000000..eeea74d9be --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/harmony.ts @@ -0,0 +1,128 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "harmony"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract( + "0xb56c2f0b653b2e0b10c9b928c8580ac5df02c7c7", + 23930344 +); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = [ + new OracleContract("0x0a53fada2d943057c47a301d25a4d9b3b8e01e8e", 18003250), +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0x1b02da8cb0d097eb8d57a175b88c7d8b47997506", 11256069), // SushiSwap +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0x6983d1e6def3690c4d616b13597a09e6193ea013" +); +export const WETH_ADDRESS = Address.fromString( + "0xcf664087a5bb0237a0bad6742852ec6c8d69a27a" +); +export const USDC_ADDRESS = Address.fromString( + "0x985458e523db3d53125813ed68c274899e9dfab4" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/mainnet.ts b/subgraphs/ebtc/src/prices/config/mainnet.ts new file mode 100644 index 0000000000..343d150823 --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/mainnet.ts @@ -0,0 +1,176 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "mainnet"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract( + "0x83d95e0d5f402511db06817aff3f9ea88224b030", + 12242339 +); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract( + "0x47fb2585d2c56fe188d0e6ec628a38b74fceeedf", + 12864088 +); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract( + "0x8263e161a855b644f582d9c164c66aabee53f927", + 12692284 +); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract( + "0x25bf7b72815476dd515044f9650bf79bad0df655", + 12370088 +); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = [ + new OracleContract("0x7d86446ddb609ed0f5f8684acf30380a356b2b4c", 11154794), + new OracleContract("0x8f942c20d02befc377d41445793068908e2250d0", 13986752), +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f", 10794261), // SushiSwap + new OracleContract("0x7a250d5630b4cf539739df2c5dacb4c659f2488d", 10207858), // Uniswap +]; +2822883; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = [ + Address.fromString("0x5f98805a4e8be255a32880fdec7f6728c6568ba0"), // LUSD + Address.fromString("0x8daebade922df735c38c80c7ebd708af50815faa"), // tBTC + Address.fromString("0x0316eb71485b0ab14103307bf65a021042c6d380"), // Huobi BTC + Address.fromString("0xca3d75ac011bf5ad07a98d02f18225f9bd9a6bdf"), // crvTriCrypto +]; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = [ + Address.fromString("0xca3d75ac011bf5ad07a98d02f18225f9bd9a6bdf"), // crvTriCrypto + Address.fromString("0xc4ad29ba4b3c580e6d59105fff484999997675ff"), // crv3Crypto +]; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = [ + Address.fromString("0xd632f22692fac7611d2aa1c0d552930d43caed3b"), // Curve.fi Factory USD Metapool: Frax + Address.fromString("0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3"), // Magic Internet Money + Address.fromString("0x5a6a4d54456819380173272a5e8e9b9904bdf41b"), // Curve.fi Factory USD Metapool: Magic Internet Money 3Pool + Address.fromString("0xbc6da0fe9ad5f3b0d58160288917aa56653660e9"), // Alchemix USD + Address.fromString("0x43b4fdfd4ff969587185cdb6f0bd875c5fc83f8c"), // Curve.fi Factory USD Metapool: Alchemix USD + Address.fromString("0x57ab1ec28d129707052df4df418d58a2d46d5f51"), // Synth SUSD + Address.fromString("0xc25a3a3b969415c80451098fa907ec722572917f"), // Curve.fi DAI/USDC/USDT/sUSD + Address.fromString("0x0000000000085d4780b73119b644ae5ecd22b376"), // TrueUSD + Address.fromString("0xecd5e75afb02efa118af914515d6521aabd189f1"), // Curve.fi Factory USD Metapool: TrueUSD + Address.fromString("0xfd2a8fa60abd58efe3eee34dd494cd491dc14900"), // Curve.fi aDAI/aUSDC/aUSDT + Address.fromString("0x8ee017541375f6bcd802ba119bddc94dad6911a1"), // Curve.fi Factory USD Metapool: PUSd + Address.fromString("0x5b3b5df2bf2b6543f78e053bd91c4bdd820929f1"), // Curve.fi Factory USD Metapool: USDM + Address.fromString("0x04b727c7e246ca70d496ecf52e6b6280f3c8077d"), // Curve.fi Factory USD Metapool: apeUSDFRAXBP + Address.fromString("0x3175df0976dfa876431c2e9ee6bc45b65d3473cc"), // Curve.fi FRAX/USDC + Address.fromString("0xbcb91e689114b9cc865ad7871845c95241df4105"), // Curve.fi Factory USD Metapool: PWRD Metapool + Address.fromString("0x26ea744e5b887e5205727f55dfbe8685e3b21951"), // iearn USDC + Address.fromString("0xc2cb1040220768554cf699b0d863a3cd4324ce32"), // iearn DAI + Address.fromString("0x04bc0ab673d88ae9dbc9da2380cb6b79c4bca9ae"), // iearn BUSD + Address.fromString("0xe6354ed5bc4b393a5aad09f21c46e101e692d447"), // iearn USDT + Address.fromString("0x3b3ac5386837dc563660fb6a0937dfaa5924333b"), // Curve.fi yDAI/yUSDC/yUSDT/yBUSD + Address.fromString("0xc2f5fea5197a3d92736500fd7733fcc7a3bbdf3f"), // Curve.fi Factory USD Metapool: fUSD-3pool + Address.fromString("0x0c10bf8fcb7bf5412187a595ab97a3609160b5c6"), // Decentralized USD + Address.fromString("0x028171bca77440897b824ca71d1c56cac55b68a3"), // Aave interest bearing DAI + Address.fromString("0x3ed3b47dd13ec9a98b44e6204a523e766b225811"), // Aave interest bearing USDT + Address.fromString("0xbcca60bb61934080951369a648fb03df4f96263c"), // Aave interest bearing USDC + Address.fromString("0x6c5024cd4f8a59110119c56f8933403a539555eb"), // Aave interest bearing SUSD + Address.fromString("0xd71ecff9342a5ced620049e616c5035f1db98620"), // Synth sEUR +]; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" +); +export const WETH_ADDRESS = Address.fromString( + "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" +); +export const USDC_ADDRESS = Address.fromString( + "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/moonbeam.ts b/subgraphs/ebtc/src/prices/config/moonbeam.ts new file mode 100644 index 0000000000..85bf1c1ed7 --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/moonbeam.ts @@ -0,0 +1,125 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "moonbeam"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = [ + new OracleContract("0xc2b1df84112619d190193e48148000e3990bf627", 1452049), +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0x445fe580ef8d70ff569ab36e80c647af338db351", 503734), // SushiSwap +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0xfa9343c3897324496a05fc75abed6bac29f8a40f" +); +export const WETH_ADDRESS = Address.fromString( + "0xacc15dc74880c9944775448304b263d191c6077f" +); +export const USDC_ADDRESS = Address.fromString( + "0x818ec0a7fe18ff94269904fced6ae3dae6d6dc0b" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/optimism.ts b/subgraphs/ebtc/src/prices/config/optimism.ts new file mode 100644 index 0000000000..5fa69e7e31 --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/optimism.ts @@ -0,0 +1,137 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "optimism"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract( + "0xb082d9f4734c535d9d80536f7e87a6f4f471bf65", + 18109291 +); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract( + "0xd81eb3728a631871a7ebbad631b5f424909f0c77", + 4365625 +); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract( + "0x5fd3815dcb668200a662114fbc9af13ac0a55b4d", + 18216910 +); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract( + "0x0ffe8434eae67c9838b12c3cd11ac4005daa7227", + 18368996 +); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = [ + new OracleContract("0xc5cfada84e902ad92dd40194f0883ad49639b023", 2373837), + new OracleContract("0x445fe580ef8d70ff569ab36e80c647af338db351", 3729171), +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0x9c12939390052919af3155f41bf4160fd3666a6f", 19702709), // Velodrame +]; +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0x4200000000000000000000000000000000000042" +); +export const WETH_ADDRESS = Address.fromString( + "0x4200000000000000000000000000000000000006" +); +export const USDC_ADDRESS = Address.fromString( + "0x7f5c764cbc14f9669b88837ca1490cca17c31607" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/polygon.ts b/subgraphs/ebtc/src/prices/config/polygon.ts new file mode 100644 index 0000000000..dbbc217c42 --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/polygon.ts @@ -0,0 +1,131 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { BigInt, Address } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "matic"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); + +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract( + "0xb023e699f5a33916ea823a16485e259257ca8bd1", + 25825996 +); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); + +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = [ + new OracleContract("0x094d12e5b541784701fd8d65f11fc0598fbc6332", 13991825), + new OracleContract("0x47bb542b9de58b970ba50c9dae444ddb4c16751a", 23556360), +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ + new OracleContract("0xa5e0829caced8ffdd4de3c43696c57f7d7a678ff", 4931900), // QuickSwap + new OracleContract("0x1b02da8cb0d097eb8d57a175b88c7d8b47997506", 11333235), // SushiSwap +]; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = Address.fromString( + "0x7ceb23fd6bc0add59e62ac25578270cff1b9f619" +); +export const WETH_ADDRESS = Address.fromString( + "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270" +); +export const USDC_ADDRESS = Address.fromString( + "0x2791bca1f2de4661ed88a30c99a7a9449aa84174" +); + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/config/template.ts b/subgraphs/ebtc/src/prices/config/template.ts new file mode 100644 index 0000000000..622780c561 --- /dev/null +++ b/subgraphs/ebtc/src/prices/config/template.ts @@ -0,0 +1,115 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import * as constants from "../common/constants"; +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; + +export const NETWORK_STRING = "default"; + +/////////////////////////////////////////////////////////////////////////// +///////////////////// CALCULATIONS/ORACLE CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_CONTRACT_ADDRESS = new OracleContract(); +export const CHAIN_LINK_CONTRACT_ADDRESS = new OracleContract(); +export const AAVE_ORACLE_CONTRACT_ADDRESS = new OracleContract(); +export const SUSHISWAP_CALCULATIONS_ADDRESS = new OracleContract(); + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////// CURVE CONTRACT ////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const CURVE_CALCULATIONS_ADDRESS = new OracleContract(); +export const CURVE_REGISTRY_ADDRESSES: OracleContract[] = []; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// UNISWAP FORKS CONTRACT //////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = []; + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////// BLACKLISTED TOKENS //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const YEARN_LENS_BLACKLIST: Address[] = []; +export const AAVE_ORACLE_BLACKLIST: Address[] = []; +export const CURVE_CALCULATIONS_BLACKSLIST: Address[] = []; +export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +//////////////////////////// HARDCODED STABLES //////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const HARDCODED_STABLES: Address[] = []; + +/////////////////////////////////////////////////////////////////////////// +///////////////////////////////// HELPERS ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + +export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); + +export const ETH_ADDRESS = constants.NULL.TYPE_ADDRESS; +export const WETH_ADDRESS = constants.NULL.TYPE_ADDRESS; +export const USDC_ADDRESS = constants.NULL.TYPE_ADDRESS; + +export class config implements Configurations { + network(): string { + return NETWORK_STRING; + } + + yearnLens(): OracleContract { + return YEARN_LENS_CONTRACT_ADDRESS; + } + chainLink(): OracleContract { + return CHAIN_LINK_CONTRACT_ADDRESS; + } + yearnLensBlacklist(): Address[] { + return YEARN_LENS_BLACKLIST; + } + + aaveOracle(): OracleContract { + return AAVE_ORACLE_CONTRACT_ADDRESS; + } + aaveOracleBlacklist(): Address[] { + return AAVE_ORACLE_BLACKLIST; + } + + curveCalculations(): OracleContract { + return CURVE_CALCULATIONS_ADDRESS; + } + curveCalculationsBlacklist(): Address[] { + return CURVE_CALCULATIONS_BLACKSLIST; + } + + sushiCalculations(): OracleContract { + return SUSHISWAP_CALCULATIONS_ADDRESS; + } + sushiCalculationsBlacklist(): Address[] { + return SUSHI_CALCULATIONS_BLACKSLIST; + } + + uniswapForks(): OracleContract[] { + return UNISWAP_FORKS_ROUTER_ADDRESSES; + } + curveRegistry(): OracleContract[] { + return CURVE_REGISTRY_ADDRESSES; + } + + hardcodedStables(): Address[] { + return HARDCODED_STABLES; + } + + ethAddress(): Address { + return ETH_ADDRESS; + } + wethAddress(): Address { + return WETH_ADDRESS; + } + usdcAddress(): Address { + return USDC_ADDRESS; + } + + usdcTokenDecimals(): BigInt { + return USDC_TOKEN_DECIMALS; + } +} diff --git a/subgraphs/ebtc/src/prices/index.ts b/subgraphs/ebtc/src/prices/index.ts new file mode 100644 index 0000000000..3a2c0ce408 --- /dev/null +++ b/subgraphs/ebtc/src/prices/index.ts @@ -0,0 +1,140 @@ +import { + log, + Address, + ethereum, + BigDecimal, + dataSource, +} from "@graphprotocol/graph-ts"; +import { CustomPriceType } from "./common/types"; + +import * as utils from "./common/utils"; +import * as constants from "./common/constants"; +import * as AaveOracle from "./oracles/AaveOracle"; +import * as CurveRouter from "./routers/CurveRouter"; +import * as ChainLinkFeed from "./oracles/ChainLinkFeed"; +import * as YearnLensOracle from "./oracles/YearnLensOracle"; +import * as UniswapForksRouter from "./routers/UniswapForksRouter"; +import * as CurveCalculations from "./calculations/CalculationsCurve"; +import * as SushiCalculations from "./calculations/CalculationsSushiswap"; + +export function getUsdPricePerToken( + tokenAddr: Address, + block: ethereum.Block | null = null +): CustomPriceType { + if (tokenAddr.equals(constants.NULL.TYPE_ADDRESS)) { + return new CustomPriceType(); + } + + const config = utils.getConfig(); + if (config.network() == "default") { + log.warning("Failed to fetch price: network {} not implemented", [ + dataSource.network(), + ]); + + return new CustomPriceType(); + } + + if (config.hardcodedStables().includes(tokenAddr)) { + return CustomPriceType.initialize( + constants.BIGDECIMAL_USD_PRICE, + constants.DEFAULT_USDC_DECIMALS + ); + } + + // 1. Yearn Lens Oracle + const yearnLensPrice = YearnLensOracle.getTokenPriceUSDC(tokenAddr, block); + if (!yearnLensPrice.reverted) { + log.info("[YearnLensOracle] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + yearnLensPrice.usdPrice.toString(), + ]); + return yearnLensPrice; + } + + // 2. ChainLink Feed Registry + const chainLinkPrice = ChainLinkFeed.getTokenPriceUSDC(tokenAddr, block); + if (!chainLinkPrice.reverted) { + log.info("[ChainLinkFeed] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + chainLinkPrice.usdPrice.toString(), + ]); + return chainLinkPrice; + } + + // 3. CalculationsCurve + const calculationsCurvePrice = CurveCalculations.getTokenPriceUSDC( + tokenAddr, + block + ); + if (!calculationsCurvePrice.reverted) { + log.info("[CalculationsCurve] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + calculationsCurvePrice.usdPrice.toString(), + ]); + return calculationsCurvePrice; + } + + // 4. CalculationsSushiSwap + const calculationsSushiSwapPrice = SushiCalculations.getTokenPriceUSDC( + tokenAddr, + block + ); + if (!calculationsSushiSwapPrice.reverted) { + log.info("[CalculationsSushiSwap] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + calculationsSushiSwapPrice.usdPrice.toString(), + ]); + return calculationsSushiSwapPrice; + } + + // 6. Aave Oracle + const aaveOraclePrice = AaveOracle.getTokenPriceUSDC(tokenAddr, block); + if (!aaveOraclePrice.reverted) { + log.info("[AaveOracle] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + aaveOraclePrice.usdPrice.toString(), + ]); + return aaveOraclePrice; + } + + // 7. Curve Router + const curvePrice = CurveRouter.getCurvePriceUsdc(tokenAddr, block); + if (!curvePrice.reverted) { + log.info("[CurveRouter] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + curvePrice.usdPrice.toString(), + ]); + return curvePrice; + } + + // 8. Uniswap Router + const uniswapPrice = UniswapForksRouter.getTokenPriceUSDC(tokenAddr, block); + if (!uniswapPrice.reverted) { + log.info("[UniswapRouter] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + uniswapPrice.usdPrice.toString(), + ]); + return uniswapPrice; + } + + log.warning("[Oracle] Failed to Fetch Price, Name: {} Address: {}", [ + utils.getTokenName(tokenAddr), + tokenAddr.toHexString(), + ]); + + return new CustomPriceType(); +} + +export function getUsdPrice( + tokenAddr: Address, + amount: BigDecimal, + block: ethereum.Block | null = null +): BigDecimal { + const tokenPrice = getUsdPricePerToken(tokenAddr, block); + + if (!tokenPrice.reverted) { + return tokenPrice.usdPrice.times(amount); + } + + return constants.BIGDECIMAL_ZERO; +} diff --git a/subgraphs/ebtc/src/prices/oracles/AaveOracle.ts b/subgraphs/ebtc/src/prices/oracles/AaveOracle.ts new file mode 100644 index 0000000000..ede131c3ef --- /dev/null +++ b/subgraphs/ebtc/src/prices/oracles/AaveOracle.ts @@ -0,0 +1,44 @@ +import * as utils from "../common/utils"; +import * as constants from "../common/constants"; +import { CustomPriceType, OracleContract } from "../common/types"; +import { Address, BigDecimal, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { AaveOracleContract } from "../../../generated/PriceFeed/AaveOracleContract"; + +export function getAaveOracleContract( + contract: OracleContract, + block: ethereum.Block | null = null +): AaveOracleContract | null { + if ( + (block && contract.startBlock.gt(block.number)) || + utils.isNullAddress(contract.address) + ) + return null; + + return AaveOracleContract.bind(contract.address); +} + +export function getTokenPriceUSDC( + tokenAddr: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const config = utils.getConfig(); + + if (!config || config.aaveOracleBlacklist().includes(tokenAddr)) + return new CustomPriceType(); + + const aaveOracleContract = getAaveOracleContract(config.aaveOracle(), block); + if (!aaveOracleContract) return new CustomPriceType(); + + const tokenPrice: BigDecimal = utils + .readValue( + aaveOracleContract.try_getAssetPrice(tokenAddr), + constants.BIGINT_ZERO + ) + .toBigDecimal(); + + return CustomPriceType.initialize( + tokenPrice, + constants.AAVE_ORACLE_DECIMALS, + constants.OracleType.AAVE_ORACLE + ); +} diff --git a/subgraphs/ebtc/src/prices/oracles/ChainLinkFeed.ts b/subgraphs/ebtc/src/prices/oracles/ChainLinkFeed.ts new file mode 100644 index 0000000000..dbba12f5d6 --- /dev/null +++ b/subgraphs/ebtc/src/prices/oracles/ChainLinkFeed.ts @@ -0,0 +1,53 @@ +import * as utils from "../common/utils"; +import * as constants from "../common/constants"; +import { Address, ethereum } from "@graphprotocol/graph-ts"; +import { CustomPriceType, OracleContract } from "../common/types"; +import { ChainLinkContract } from "../../../generated/PriceFeed/ChainLinkContract"; + +export function getChainLinkContract( + contract: OracleContract, + block: ethereum.Block | null = null +): ChainLinkContract | null { + if ( + (block && contract.startBlock.gt(block.number)) || + utils.isNullAddress(contract.address) + ) + return null; + + return ChainLinkContract.bind(contract.address); +} + +export function getTokenPriceUSDC( + tokenAddr: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const config = utils.getConfig(); + if (!config) return new CustomPriceType(); + + const chainLinkContract = getChainLinkContract(config.chainLink(), block); + if (!chainLinkContract) return new CustomPriceType(); + + const result = chainLinkContract.try_latestRoundData( + tokenAddr, + constants.CHAIN_LINK_USD_ADDRESS + ); + + if (!result.reverted) { + const decimals = chainLinkContract.try_decimals( + tokenAddr, + constants.CHAIN_LINK_USD_ADDRESS + ); + + if (decimals.reverted) { + return new CustomPriceType(); + } + + return CustomPriceType.initialize( + result.value.value1.toBigDecimal(), + decimals.value, + constants.OracleType.CHAINLINK_FEED + ); + } + + return new CustomPriceType(); +} diff --git a/subgraphs/ebtc/src/prices/oracles/YearnLensOracle.ts b/subgraphs/ebtc/src/prices/oracles/YearnLensOracle.ts new file mode 100644 index 0000000000..b0c2a6bb5c --- /dev/null +++ b/subgraphs/ebtc/src/prices/oracles/YearnLensOracle.ts @@ -0,0 +1,44 @@ +import * as utils from "../common/utils"; +import * as constants from "../common/constants"; +import { CustomPriceType, OracleContract } from "../common/types"; +import { Address, BigDecimal, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { YearnLensContract } from "../../../generated/PriceFeed/YearnLensContract"; + +export function getYearnLensContract( + contract: OracleContract, + block: ethereum.Block | null = null +): YearnLensContract | null { + if ( + (block && contract.startBlock.gt(block.number)) || + utils.isNullAddress(contract.address) + ) + return null; + + return YearnLensContract.bind(contract.address); +} + +export function getTokenPriceUSDC( + tokenAddr: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const config = utils.getConfig(); + + if (!config || config.yearnLensBlacklist().includes(tokenAddr)) + return new CustomPriceType(); + + const yearnLensContract = getYearnLensContract(config.yearnLens(), block); + if (!yearnLensContract) return new CustomPriceType(); + + const tokenPrice: BigDecimal = utils + .readValue( + yearnLensContract.try_getPriceUsdcRecommended(tokenAddr), + constants.BIGINT_ZERO + ) + .toBigDecimal(); + + return CustomPriceType.initialize( + tokenPrice, + constants.DEFAULT_USDC_DECIMALS, + constants.OracleType.YEARN_LENS_ORACLE + ); +} diff --git a/subgraphs/ebtc/src/prices/routers/CurveRouter.ts b/subgraphs/ebtc/src/prices/routers/CurveRouter.ts new file mode 100644 index 0000000000..f25e55d86e --- /dev/null +++ b/subgraphs/ebtc/src/prices/routers/CurveRouter.ts @@ -0,0 +1,327 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { getUsdPricePerToken } from ".."; +import * as utils from "../common/utils"; +import * as constants from "../common/constants"; +import { CustomPriceType } from "../common/types"; +import { BigInt, Address, BigDecimal, ethereum } from "@graphprotocol/graph-ts"; +import { CurvePool as CurvePoolContract } from "../../../generated/PriceFeed/CurvePool"; +import { CurveRegistry as CurveRegistryContract } from "../../../generated/PriceFeed/CurveRegistry"; + +export function isCurveLpToken( + lpAddress: Address, + block: ethereum.Block +): bool { + const poolAddress = getPoolFromLpToken(lpAddress, block); + if (poolAddress.notEqual(constants.NULL.TYPE_ADDRESS)) return true; + + return false; +} + +export function getPoolFromLpToken( + lpAddress: Address, + block: ethereum.Block | null = null +): Address { + const config = utils.getConfig(); + const curveRegistryAdresses = config.curveRegistry(); + + for (let idx = 0; idx < curveRegistryAdresses.length; idx++) { + const curveRegistry = curveRegistryAdresses[idx]; + if (block && curveRegistry.startBlock.gt(block.number)) continue; + + const curveRegistryContract = CurveRegistryContract.bind( + curveRegistry.address + ); + + const poolAddress = utils.readValue
( + curveRegistryContract.try_get_pool_from_lp_token(lpAddress), + constants.NULL.TYPE_ADDRESS + ); + + if (poolAddress.notEqual(constants.NULL.TYPE_ADDRESS)) return poolAddress; + } + + return constants.NULL.TYPE_ADDRESS; +} + +export function isLpCryptoPool( + lpAddress: Address, + block: ethereum.Block | null = null +): bool { + const poolAddress = getPoolFromLpToken(lpAddress, block); + + if (poolAddress != constants.NULL.TYPE_ADDRESS) { + return isPoolCryptoPool(poolAddress); + } + + return false; +} + +export function isPoolCryptoPool(poolAddress: Address): bool { + const poolContract = CurvePoolContract.bind(poolAddress); + + const priceOracleCall = poolContract.try_price_oracle(); + if (!priceOracleCall.reverted) return true; + + const priceOracle1Call = poolContract.try_price_oracle1( + constants.BIGINT_ZERO + ); + if (!priceOracle1Call.reverted) return true; + + return false; +} + +export function getCurvePriceUsdc( + lpAddress: Address, + block: ethereum.Block | null = null +): CustomPriceType { + if (isLpCryptoPool(lpAddress, block)) + return cryptoPoolLpPriceUsdc(lpAddress, block); + + const basePrice = getBasePrice(lpAddress, block); + const virtualPrice = getVirtualPrice(lpAddress, block).toBigDecimal(); + + const config = utils.getConfig(); + const usdcTokenDecimals = config.usdcTokenDecimals(); + + const decimalsAdjustment = + constants.DEFAULT_DECIMALS.minus(usdcTokenDecimals); + const priceUsdc = virtualPrice + .times(basePrice.usdPrice) + .times( + constants.BIGINT_TEN.pow(decimalsAdjustment.toI32() as u8).toBigDecimal() + ); + + return CustomPriceType.initialize( + priceUsdc, + decimalsAdjustment.plus(constants.DEFAULT_DECIMALS).toI32() as u8, + constants.OracleType.CURVE_ROUTER + ); +} + +export function getBasePrice( + lpAddress: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const poolAddress = getPoolFromLpToken(lpAddress, block); + + if (poolAddress.equals(constants.NULL.TYPE_ADDRESS)) + return new CustomPriceType(); + + const underlyingCoinAddress = getUnderlyingCoinFromPool(poolAddress, block); + const basePrice = getPriceUsdcRecommended(underlyingCoinAddress, block); + + return basePrice; +} + +export function getUnderlyingCoinFromPool( + poolAddress: Address, + block: ethereum.Block | null = null +): Address { + const config = utils.getConfig(); + const curveRegistryAdresses = config.curveRegistry(); + + for (let idx = 0; idx < curveRegistryAdresses.length; idx++) { + const curveRegistry = curveRegistryAdresses[idx]; + if (block && curveRegistry.startBlock.gt(block.number)) continue; + + const curveRegistryContract = CurveRegistryContract.bind( + curveRegistry.address + ); + + const coins = utils.readValue( + curveRegistryContract.try_get_underlying_coins(poolAddress), + [] + ); + + if (coins.length != 0) return getPreferredCoinFromCoins(coins); + } + + return constants.NULL.TYPE_ADDRESS; +} + +export function getPreferredCoinFromCoins(coins: Address[]): Address { + let preferredCoinAddress = constants.NULL.TYPE_ADDRESS; + for (let coinIdx = 0; coinIdx < 8; coinIdx++) { + const coinAddress = coins[coinIdx]; + + if (coinAddress.notEqual(constants.NULL.TYPE_ADDRESS)) { + preferredCoinAddress = coinAddress; + } + // Found preferred coin and we're at the end of the token array + if ( + (preferredCoinAddress.notEqual(constants.NULL.TYPE_ADDRESS) && + coinAddress.equals(constants.NULL.TYPE_ADDRESS)) || + coinIdx == 7 + ) { + break; + } + } + + return preferredCoinAddress; +} + +export function getVirtualPrice( + curveLpTokenAddress: Address, + block: ethereum.Block | null = null +): BigInt { + const config = utils.getConfig(); + const curveRegistryAdresses = config.curveRegistry(); + + for (let idx = 0; idx < curveRegistryAdresses.length; idx++) { + const curveRegistry = curveRegistryAdresses[idx]; + if (block && curveRegistry.startBlock.gt(block.number)) continue; + + const curveRegistryContract = CurveRegistryContract.bind( + curveRegistry.address + ); + + const virtualPriceCall = + curveRegistryContract.try_get_virtual_price_from_lp_token( + curveLpTokenAddress + ); + + if (!virtualPriceCall.reverted) return virtualPriceCall.value; + } + + return constants.BIGINT_ZERO; +} + +export function getPriceUsdcRecommended( + tokenAddress: Address, + block: ethereum.Block | null = null +): CustomPriceType { + return getUsdPricePerToken(tokenAddress, block); +} + +export function cryptoPoolLpPriceUsdc( + lpAddress: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const totalSupply = utils.getTokenSupply(lpAddress); + + const totalValueUsdc = cryptoPoolLpTotalValueUsdc(lpAddress, block); + const priceUsdc = totalValueUsdc + .times( + constants.BIGINT_TEN.pow( + constants.DEFAULT_DECIMALS.toI32() as u8 + ).toBigDecimal() + ) + .div(totalSupply.toBigDecimal()); + + return CustomPriceType.initialize( + priceUsdc, + 0, + constants.OracleType.CURVE_ROUTER + ); +} + +export function cryptoPoolLpTotalValueUsdc( + lpAddress: Address, + block: ethereum.Block | null = null +): BigDecimal { + const poolAddress = getPoolFromLpToken(lpAddress, block); + + const underlyingTokensAddresses = + cryptoPoolUnderlyingTokensAddressesByPoolAddress(poolAddress); + + let totalValue = constants.BIGDECIMAL_ZERO; + + for ( + let tokenIdx = 0; + tokenIdx < underlyingTokensAddresses.length; + tokenIdx++ + ) { + const tokenValueUsdc = cryptoPoolTokenAmountUsdc( + poolAddress, + underlyingTokensAddresses[tokenIdx], + BigInt.fromI32(tokenIdx), + block + ); + totalValue = totalValue.plus(tokenValueUsdc); + } + + return totalValue; +} + +export function cryptoPoolTokenAmountUsdc( + poolAddress: Address, + tokenAddress: Address, + tokenIdx: BigInt, + block: ethereum.Block | null = null +): BigDecimal { + const poolContract = CurvePoolContract.bind(poolAddress); + + const tokenBalance = utils + .readValue( + poolContract.try_balances(tokenIdx), + constants.BIGINT_ZERO + ) + .toBigDecimal(); + + const tokenDecimals = utils.getTokenDecimals(tokenAddress); + const tokenPrice = getPriceUsdcRecommended(tokenAddress, block); + const tokenValueUsdc = tokenBalance + .times(tokenPrice.usdPrice) + .div(constants.BIGINT_TEN.pow(tokenDecimals.toI32() as u8).toBigDecimal()); + + return tokenValueUsdc; +} + +export function cryptoPoolUnderlyingTokensAddressesByPoolAddress( + poolAddress: Address +): Address[] { + const poolContract = CurvePoolContract.bind(poolAddress); + + let idx = 0; + const coins: Address[] = []; + while (idx >= 0) { + const coin = utils.readValue
( + poolContract.try_coins(BigInt.fromI32(idx)), + constants.NULL.TYPE_ADDRESS + ); + + if (coin.equals(constants.NULL.TYPE_ADDRESS)) { + return coins; + } + + coins.push(coin); + idx += 1; + } + + return coins; +} + +export function getPriceUsdc( + tokenAddress: Address, + block: ethereum.Block +): CustomPriceType { + if (isCurveLpToken(tokenAddress, block)) + return getCurvePriceUsdc(tokenAddress, block); + + const poolContract = CurvePoolContract.bind(tokenAddress); + const virtualPrice = utils + .readValue( + poolContract.try_get_virtual_price(), + constants.BIGINT_ZERO + ) + .toBigDecimal(); + + const coins: Address[] = []; + for (let i = 0; i < 8; i++) { + const coin = utils.readValue
( + poolContract.try_coins(BigInt.fromI32(i)), + constants.NULL.TYPE_ADDRESS + ); + + coins.push(coin); + } + + const preferredCoin = getPreferredCoinFromCoins(coins); + const price = getPriceUsdcRecommended(preferredCoin, block); + + return CustomPriceType.initialize( + price.usdPrice.times(virtualPrice), + constants.DEFAULT_DECIMALS.toI32() as u8, + constants.OracleType.CURVE_ROUTER + ); +} diff --git a/subgraphs/ebtc/src/prices/routers/UniswapForksRouter.ts b/subgraphs/ebtc/src/prices/routers/UniswapForksRouter.ts new file mode 100644 index 0000000000..a39cb74cbb --- /dev/null +++ b/subgraphs/ebtc/src/prices/routers/UniswapForksRouter.ts @@ -0,0 +1,222 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import * as utils from "../common/utils"; +import * as constants from "../common/constants"; +import { CustomPriceType } from "../common/types"; +import { Address, BigInt, ethereum, log } from "@graphprotocol/graph-ts"; +import { UniswapPair as UniswapPairContract } from "../../../generated/PriceFeed/UniswapPair"; +import { UniswapRouter as UniswapRouterContract } from "../../../generated/PriceFeed/UniswapRouter"; + +export function isLpToken(tokenAddress: Address, ethAddress: Address): bool { + if (tokenAddress.equals(ethAddress)) return false; + + const lpToken = UniswapRouterContract.bind(tokenAddress); + const isFactoryAvailable = utils.readValue( + lpToken.try_factory(), + constants.NULL.TYPE_ADDRESS + ); + + if (isFactoryAvailable.equals(constants.NULL.TYPE_ADDRESS)) return false; + + return true; +} + +export function getTokenPriceUSDC( + tokenAddress: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const config = utils.getConfig(); + if (!config) return new CustomPriceType(); + + const ethAddress = config.ethAddress(); + const usdcAddress = config.usdcAddress(); + + if (isLpToken(tokenAddress, ethAddress)) { + return getLpTokenPriceUsdc(tokenAddress, block); + } + return getPriceFromRouterUSDC(tokenAddress, usdcAddress, block); +} + +export function getPriceFromRouterUSDC( + tokenAddress: Address, + usdcAddress: Address, + block: ethereum.Block | null = null +): CustomPriceType { + return getPriceFromRouter(tokenAddress, usdcAddress, block); +} + +export function getPriceFromRouter( + token0Address: Address, + token1Address: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const config = utils.getConfig(); + + const ethAddress = config.ethAddress(); + const wethAddress = config.wethAddress(); + + // Construct swap path + const path: Address[] = []; + let numberOfJumps: BigInt; + + // Convert ETH address to WETH + if (token0Address == ethAddress) token0Address = wethAddress; + if (token1Address == ethAddress) token1Address = wethAddress; + + const inputTokenIsWeth: bool = + token0Address.equals(wethAddress) || token1Address.equals(wethAddress); + + if (inputTokenIsWeth) { + // Path = [token0, weth] or [weth, token1] + numberOfJumps = BigInt.fromI32(1); + + path.push(token0Address); + path.push(token1Address); + } else { + // Path = [token0, weth, token1] + numberOfJumps = BigInt.fromI32(2); + + path.push(token0Address); + path.push(wethAddress); + path.push(token1Address); + } + + const token0Decimals = utils.getTokenDecimals(token0Address); + const amountIn = constants.BIGINT_TEN.pow(token0Decimals.toI32() as u8); + + const routerAddresses = config.uniswapForks(); + + let amountOut = constants.BIGINT_ZERO; + for (let idx = 0; idx < routerAddresses.length; idx++) { + const routerAddress = routerAddresses[idx]; + if (block && routerAddress.startBlock.gt(block.number)) continue; + + const uniswapForkRouter = UniswapRouterContract.bind(routerAddress.address); + const amountOutArray = uniswapForkRouter.try_getAmountsOut(amountIn, path); + + if (!amountOutArray.reverted) { + amountOut = amountOutArray.value[amountOutArray.value.length - 1]; + break; + } + } + + const feeBips = BigInt.fromI32(30); + + const amountOutBigDecimal = amountOut + .times(constants.BIGINT_TEN_THOUSAND) + .div(constants.BIGINT_TEN_THOUSAND.minus(feeBips.times(numberOfJumps))) + .toBigDecimal(); + + return CustomPriceType.initialize( + amountOutBigDecimal, + config.usdcTokenDecimals().toI32() as u8, + constants.OracleType.UNISWAP_FORKS_ROUTER + ); +} + +export function getLpTokenPriceUsdc( + tokenAddress: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const uniSwapPair = UniswapPairContract.bind(tokenAddress); + + const totalLiquidity: CustomPriceType = getLpTokenTotalLiquidityUsdc( + tokenAddress, + block + ); + const totalSupply = utils.readValue( + uniSwapPair.try_totalSupply(), + constants.BIGINT_ZERO + ); + if (totalSupply == constants.BIGINT_ZERO || totalLiquidity.reverted) { + return new CustomPriceType(); + } + + let pairDecimals: number; + const pairDecimalsCall = uniSwapPair.try_decimals(); + + if (pairDecimalsCall.reverted) { + log.warning( + "[UniswapForksRouter] Failed to fetch pair decimals, tokenAddress: {}", + [tokenAddress.toHexString()] + ); + + return new CustomPriceType(); + } else { + pairDecimals = pairDecimalsCall.value; + } + + const pricePerLpTokenUsdc = totalLiquidity.usdPrice + .times(constants.BIGINT_TEN.pow(pairDecimals as u8).toBigDecimal()) + .div(totalSupply.toBigDecimal()); + + return CustomPriceType.initialize( + pricePerLpTokenUsdc, + constants.DEFAULT_USDC_DECIMALS, + constants.OracleType.UNISWAP_FORKS_ROUTER + ); +} + +export function getLpTokenTotalLiquidityUsdc( + tokenAddress: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const uniSwapPair = UniswapPairContract.bind(tokenAddress); + + const token0Address = utils.readValue
( + uniSwapPair.try_token0(), + constants.NULL.TYPE_ADDRESS + ); + const token1Address = utils.readValue
( + uniSwapPair.try_token1(), + constants.NULL.TYPE_ADDRESS + ); + + if ( + token0Address.equals(constants.NULL.TYPE_ADDRESS) || + token1Address.equals(constants.NULL.TYPE_ADDRESS) + ) { + return new CustomPriceType(); + } + + const token0Decimals = utils.getTokenDecimals(token0Address); + const token1Decimals = utils.getTokenDecimals(token1Address); + + const reservesCall = uniSwapPair.try_getReserves(); + + if (reservesCall.reverted) return new CustomPriceType(); + + const token0Price = getTokenPriceUSDC(token0Address, block); + const token1Price = getTokenPriceUSDC(token1Address, block); + + if (token0Price.reverted || token1Price.reverted) { + return new CustomPriceType(); + } + + const reserves = reservesCall.value; + const reserve0 = reserves.value0; + const reserve1 = reserves.value1; + + if ( + reserve0.notEqual(constants.BIGINT_ZERO) || + reserve1.notEqual(constants.BIGINT_ZERO) + ) { + const liquidity0 = reserve0 + .div(constants.BIGINT_TEN.pow(token0Decimals.toI32() as u8)) + .toBigDecimal() + .times(token0Price.usdPrice); + + const liquidity1 = reserve1 + .div(constants.BIGINT_TEN.pow(token1Decimals.toI32() as u8)) + .toBigDecimal() + .times(token1Price.usdPrice); + + const totalLiquidity = liquidity0.plus(liquidity1); + + return CustomPriceType.initialize( + totalLiquidity, + constants.DEFAULT_USDC_DECIMALS, + constants.OracleType.UNISWAP_FORKS_ROUTER + ); + } + return new CustomPriceType(); +} diff --git a/subgraphs/ebtc/src/sdk/README.md b/subgraphs/ebtc/src/sdk/README.md new file mode 100644 index 0000000000..9b6ac3c616 --- /dev/null +++ b/subgraphs/ebtc/src/sdk/README.md @@ -0,0 +1,20 @@ +# Lending SDK `1.0.2` + +The lending SDK follows the `3.0.1` lending schema. You can learn about each `manager` class in the class headers, but there are a few things to note. + +As a general rule of thumb you want to do a few things before you create an `event` entity. Whether that is in the `Deposit` handler or a unique handler before that. + +- You want to update market/protocol data. + - This includes price, input token balance, and borrow balance, etc. + - The function to do that is `DataManager.updateMarketAndProtocolData()` +- It is also standard to update revenue or rewards here as well (of course it may be different depending on the protocol) + - The revenue update functions are: + - `DataManager.addProtocolRevenue()` and it takes an optional `Fee` that the revenue is associated with + - `DataManager.addSupplyRevenue()` with the optional `Fee` + - For rewards you can use `DataManager.updateRewards()` + +> Note: The `_reference_` subgraph will not build and deploy. It is a place to see standards that you can copy into your subgraph. + +### Questions / Fixes + +If you find anything incorrect or have questions please feel free to make a [PR](https://github.com/messari/subgraphs/blob/master/docs/CONTRIBUTING.md) to fix it or raise an [issue](https://github.com/messari/subgraphs/issues/new). diff --git a/subgraphs/ebtc/src/sdk/account.ts b/subgraphs/ebtc/src/sdk/account.ts new file mode 100644 index 0000000000..7d8590b289 --- /dev/null +++ b/subgraphs/ebtc/src/sdk/account.ts @@ -0,0 +1,80 @@ +import { Bytes } from "@graphprotocol/graph-ts"; +import { Account } from "../../../../generated/schema"; +import { INT_ONE, INT_ZERO } from "./constants"; + +/** + * This file contains the AccountClass, which does + * the operations on the Account entity. This includes: + * - Creating a new Account + * - Updating an existing Account + * - Making a position + * - Making position snapshots + * + * Schema Version: 3.0.1 + * SDK Version: 1.0.2 + * Author(s): + * - @dmelotik + */ + +export class AccountManager { + private isNew: boolean; // true if the account was created + private account: Account; + + constructor(account: Bytes) { + let _account = Account.load(account); + if (!_account) { + _account = new Account(account); + _account.positionCount = INT_ZERO; + _account.openPositionCount = INT_ZERO; + _account.closedPositionCount = INT_ZERO; + _account.depositCount = INT_ZERO; + _account.withdrawCount = INT_ZERO; + _account.borrowCount = INT_ZERO; + _account.repayCount = INT_ZERO; + _account.liquidateCount = INT_ZERO; + _account.liquidationCount = INT_ZERO; + _account.transferredCount = INT_ZERO; + _account.receivedCount = INT_ZERO; + _account.flashloanCount = INT_ZERO; + _account.save(); + this.isNew = true; + } else { + this.isNew = false; + } + this.account = _account; + } + + getAccount(): Account { + return this.account; + } + + // returns true if the account was created in this instance + isNewUser(): boolean { + if (this.isNew) { + return true; + } + + // true if there have been no transactions submitted by the user + // ie, liquidations and receives don't count (did not spend gas) + return ( + this.account.depositCount == INT_ZERO && + this.account.withdrawCount == INT_ZERO && + this.account.borrowCount == INT_ZERO && + this.account.repayCount == INT_ZERO && + this.account.liquidateCount == INT_ZERO && + this.account.transferredCount == INT_ZERO && + this.account.flashloanCount == INT_ZERO + ); + } + + countFlashloan(): void { + this.account.flashloanCount += INT_ONE; + this.account.save(); + } + + // Ensure this is called on the liquidators account + countLiquidate(): void { + this.account.liquidateCount += INT_ONE; + this.account.save(); + } +} diff --git a/subgraphs/ebtc/src/sdk/constants.ts b/subgraphs/ebtc/src/sdk/constants.ts new file mode 100644 index 0000000000..aa14803b2f --- /dev/null +++ b/subgraphs/ebtc/src/sdk/constants.ts @@ -0,0 +1,281 @@ +import { BigDecimal, BigInt, Bytes } from "@graphprotocol/graph-ts"; +import { _ActiveAccount } from "../../generated/schema"; + +//////////////////////// +///// Schema Enums ///// +//////////////////////// + +// The network names corresponding to the Network enum in the schema. +// They also correspond to the ones in `dataSource.network()` after converting to lower case. +// See below for a complete list: +// https://thegraph.com/docs/en/hosted-service/what-is-hosted-service/#supported-networks-on-the-hosted-service +export namespace Network { + export const ARBITRUM_ONE = "ARBITRUM_ONE"; + export const ARWEAVE_MAINNET = "ARWEAVE_MAINNET"; + export const AURORA = "AURORA"; + export const AVALANCHE = "AVALANCHE"; + export const BOBA = "BOBA"; + export const BSC = "BSC"; // aka BNB Chain + export const CELO = "CELO"; + export const COSMOS = "COSMOS"; + export const CRONOS = "CRONOS"; + export const MAINNET = "MAINNET"; // Ethereum mainnet + export const FANTOM = "FANTOM"; + export const FUSE = "FUSE"; + export const HARMONY = "HARMONY"; + export const JUNO = "JUNO"; + export const MOONBEAM = "MOONBEAM"; + export const MOONRIVER = "MOONRIVER"; + export const NEAR_MAINNET = "NEAR_MAINNET"; + export const OPTIMISM = "OPTIMISM"; + export const OSMOSIS = "OSMOSIS"; + export const MATIC = "MATIC"; // aka Polygon + export const XDAI = "XDAI"; // aka Gnosis Chain +} + +export namespace ProtocolType { + export const EXCHANGE = "EXCHANGE"; + export const LENDING = "LENDING"; + export const YIELD = "YIELD"; + export const BRIDGE = "BRIDGE"; + export const GENERIC = "GENERIC"; +} + +export namespace LendingType { + export const CDP = "CDP"; + export const POOLED = "POOLED"; +} + +export namespace PermissionType { + export const WHITELIST_ONLY = "WHITELIST_ONLY"; + export const PERMISSIONED = "PERMISSIONED"; + export const PERMISSIONLESS = "PERMISSIONLESS"; + export const ADMIN = "ADMIN"; +} + +export namespace RiskType { + export const GLOBAL = "GLOBAL"; + export const ISOLATED = "ISOLATED"; +} + +export namespace CollateralizationType { + export const OVER_COLLATERALIZED = "OVER_COLLATERALIZED"; + export const UNDER_COLLATERALIZED = "UNDER_COLLATERALIZED"; + export const UNCOLLATERALIZED = "UNCOLLATERALIZED"; +} + +export namespace TokenType { + export const REBASING = "REBASING"; + export const NON_REBASING = "NON_REBASING"; +} + +export namespace InterestRateType { + export const STABLE = "STABLE"; + export const VARIABLE = "VARIABLE"; + export const FIXED = "FIXED"; +} + +export namespace InterestRateSide { + export const LENDER = "LENDER"; + export const BORROWER = "BORROWER"; +} + +export namespace FeeType { + export const LIQUIDATION_FEE = "LIQUIDATION_FEE"; + export const ADMIN_FEE = "ADMIN_FEE"; + export const PROTOCOL_FEE = "PROTOCOL_FEE"; + export const MINT_FEE = "MINT_FEE"; + export const WITHDRAW_FEE = "WITHDRAW_FEE"; + export const OTHER = "OTHER"; +} + +export namespace PositionSide { + export const COLLATERAL = "COLLATERAL"; + export const BORROWER = "BORROWER"; +} + +export namespace OracleSource { + export const UNISWAP = "UNISWAP"; + export const BALANCER = "BALANCER"; + export const CHAINLINK = "CHAINLINK"; + export const YEARN = "YEARN"; + export const SUSHISWAP = "SUSHISWAP"; + export const CURVE = "CURVE"; +} + +export namespace TransactionType { + export const DEPOSIT = "DEPOSIT"; + export const WITHDRAW = "WITHDRAW"; + export const BORROW = "BORROW"; + export const REPAY = "REPAY"; + export const LIQUIDATE = "LIQUIDATE"; + export const TRANSFER = "TRANSFER"; + export const FLASHLOAN = "FLASHLOAN"; + + export const LIQUIDATOR = "LIQUIDATOR"; + export const LIQUIDATEE = "LIQUIDATEE"; +} + +export namespace AccountActivity { + export const DAILY = "DAILY"; + export const HOURLY = "HOURLY"; +} + +export namespace RewardTokenType { + export const DEPOSIT = "DEPOSIT"; + export const VARIABLE_BORROW = "VARIABLE_BORROW"; + export const STABLE_BORROW = "STABLE_BORROW"; + export const STAKE = "STAKE"; +} + +export enum Transaction { + DEPOSIT = 0, + WITHDRAW = 1, + BORROW = 2, + REPAY = 3, + LIQUIDATE = 4, + TRANSFER = 5, + FLASHLOAN = 6, +} + +//////////////////////// +///// Type Helpers ///// +//////////////////////// + +export const INT_NEGATIVE_ONE = -1 as i32; +export const INT_ZERO = 0 as i32; +export const INT_ONE = 1 as i32; +export const INT_TWO = 2 as i32; +export const INT_FOUR = 4 as i32; +export const INT_SIX = 6 as i32; +export const INT_NINE = 9 as i32; +export const INT_SIXTEEN = 16 as i32; +export const INT_EIGHTTEEN = 18 as i32; + +export const BIGINT_NEGATIVE_ONE = BigInt.fromI32(-1); +export const BIGINT_ZERO = BigInt.fromI32(0); +export const BIGINT_ONE = BigInt.fromI32(1); +export const BIGINT_HUNDRED = BigInt.fromI32(100); +export const BIGINT_THREE_HUNDRED = BigInt.fromI32(300); +export const BIGINT_TEN_TO_EIGHTEENTH = BigInt.fromString("10").pow(18); + +export const BIGDECIMAL_ZERO = new BigDecimal(BIGINT_ZERO); +export const BIGDECIMAL_ONE = new BigDecimal(BIGINT_ONE); +export const BIGDECIMAL_HUNDRED = new BigDecimal(BigInt.fromI32(100)); + +///////////////////// +///// Date/Time ///// +///////////////////// + +export const DAYS_PER_YEAR = 365; +export const SECONDS_PER_YEAR = 60 * 60 * 24 * DAYS_PER_YEAR; +export const SECONDS_PER_DAY = 60 * 60 * 24; // 86400 +export const SECONDS_PER_HOUR = 60 * 60; // 3600 + +export const ETHEREUM_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 13; // 13 = seconds per block +export const AVALANCHE_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 2; // 2 = seconds per block. This is NOT ideal since avalanche has variable block time. +export const FANTOM_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 1; // 1 = seconds per block. This is NOT ideal since fantom has variable block time. +export const BSC_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 3; // 3 = seconds per block +export const MATIC_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 2; // 2 = seconds per block +export const ARBITRUM_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 1; // 1 = seconds per block. + +///////////////////////////// +///// Math ///// +///////////////////////////// + +export const mantissaFactor = 18; +export const cTokenDecimals = 8; +export const mantissaFactorBD = exponentToBigDecimal(mantissaFactor); +export const cTokenDecimalsBD = exponentToBigDecimal(cTokenDecimals); + +// n => 10^n +export function exponentToBigDecimal(decimals: i32): BigDecimal { + let result = BIGINT_ONE; + const ten = BigInt.fromI32(10); + for (let i = 0; i < decimals; i++) { + result = result.times(ten); + } + return result.toBigDecimal(); +} + +// BigInt to BigDecimal +export function bigIntToBigDecimal(x: BigInt, decimals: i32): BigDecimal { + return x.toBigDecimal().div(exponentToBigDecimal(decimals)); +} + +//change number of decimals for BigDecimal +export function BDChangeDecimals( + x: BigDecimal, + from: i32, + to: i32 +): BigDecimal { + if (to > from) { + // increase number of decimals + const diffMagnitude = exponentToBigDecimal(to - from); + return x.times(diffMagnitude); + } else if (to < from) { + // decrease number of decimals + const diffMagnitude = exponentToBigDecimal(from - to); + return x.div(diffMagnitude); + } else { + return x; + } +} + +// insert value into arr at index +export function insert( + arr: Array, + index: i32, + value: Type +): Array { + const result: Type[] = []; + for (let i = 0; i < index; i++) { + result.push(arr[i]); + } + result.push(value); + for (let i = index; i < arr.length; i++) { + result.push(arr[i]); + } + return result; +} + +// returns the increment to update the usage activity by +// 1 for a new account in the specified period, otherwise 0 +export function activityCounter( + account: Bytes, + transactionType: string, + useTransactionType: boolean, + intervalID: i32, // 0 = no intervalID + marketID: Bytes | null = null +): i32 { + let activityID = account + .toHexString() + .concat("-") + .concat(intervalID.toString()); + if (marketID) { + activityID = activityID.concat("-").concat(marketID.toHexString()); + } + if (useTransactionType) { + activityID = activityID.concat("-").concat(transactionType); + } + let activeAccount = _ActiveAccount.load(activityID); + if (!activeAccount) { + // if account / market only + transactionType is LIQUIDATEE + // then do not count that account as it did not spend gas to use the protocol + if (!useTransactionType && transactionType == TransactionType.LIQUIDATEE) { + return INT_ZERO; + } + + activeAccount = new _ActiveAccount(activityID); + activeAccount.save(); + return INT_ONE; + } + + return INT_ZERO; +} + +///////////////////////////// +///// Addresses ///// +///////////////////////////// + +export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; diff --git a/subgraphs/ebtc/src/sdk/manager.ts b/subgraphs/ebtc/src/sdk/manager.ts new file mode 100644 index 0000000000..e1107c47f9 --- /dev/null +++ b/subgraphs/ebtc/src/sdk/manager.ts @@ -0,0 +1,1238 @@ +import { + Address, + Bytes, + BigInt, + ethereum, + BigDecimal, + log, +} from "@graphprotocol/graph-ts"; +import { + Borrow, + Deposit, + Fee, + Flashloan, + InterestRate, + LendingProtocol, + Liquidate, + Market, + Oracle, + Repay, + RevenueDetail, + RewardToken, + Token, + Transfer, + Withdraw, + _MarketList, +} from "../../generated/schema"; +import { Versions } from "../versions"; +import { AccountManager } from "./account"; +import { + activityCounter, + BIGDECIMAL_ZERO, + BIGINT_ZERO, + exponentToBigDecimal, + FeeType, + INT_ONE, + INT_ZERO, + PositionSide, + ProtocolType, + Transaction, + TransactionType, +} from "./constants"; +import { SnapshotManager } from "./snapshots"; +import { TokenManager } from "./token"; +import { insert } from "./constants"; +import { PositionManager } from "./position"; + +/** + * This file contains the DataManager, which is used to + * make all of the storage changes that occur in a protocol. + * + * You can think of this as an abstraction so the developer doesn't + * need to think about all of the detailed storage changes that occur. + * + * Schema Version: 3.0.1 + * SDK Version: 1.0.2 + * Author(s): + * - @dmelotik + */ + +export class ProtocolData { + constructor( + public readonly protocolID: Bytes, + public readonly protocol: string, + public readonly name: string, + public readonly slug: string, + public readonly network: string, + public readonly lendingType: string, + public readonly lenderPermissionType: string | null, + public readonly borrowerPermissionType: string | null, + public readonly poolCreatorPermissionType: string | null, + public readonly collateralizationType: string | null, + public readonly riskType: string | null + ) {} +} + +export class RewardData { + constructor( + public readonly rewardToken: RewardToken, + public readonly rewardTokenEmissionsAmount: BigInt, + public readonly rewardTokenEmissionsUSD: BigDecimal + ) {} +} + +export class DataManager { + private event!: ethereum.Event; + private protocol!: LendingProtocol; + private market!: Market; + private inputToken!: TokenManager; + private oracle!: Oracle; + private snapshots!: SnapshotManager; + + constructor( + marketID: Bytes, + inputToken: Bytes, + event: ethereum.Event, + protocolData: ProtocolData + ) { + this.protocol = this.getOrCreateLendingProtocol(protocolData); + this.inputToken = new TokenManager(inputToken, event); + let _market = Market.load(marketID); + + // create new market + if (!_market) { + _market = new Market(marketID); + _market.protocol = this.protocol.id; + _market.isActive = true; + _market.canBorrowFrom = false; // default + _market.canUseAsCollateral = false; // default + _market.maximumLTV = BIGDECIMAL_ZERO; // default + _market.liquidationThreshold = BIGDECIMAL_ZERO; // default + _market.liquidationPenalty = BIGDECIMAL_ZERO; // default + _market.canIsolate = false; // default + _market.inputToken = this.inputToken.getToken().id; + _market.inputTokenBalance = BIGINT_ZERO; + _market.inputTokenPriceUSD = BIGDECIMAL_ZERO; + _market.totalValueLockedUSD = BIGDECIMAL_ZERO; + _market.cumulativeSupplySideRevenueUSD = BIGDECIMAL_ZERO; + _market.cumulativeProtocolSideRevenueUSD = BIGDECIMAL_ZERO; + _market.cumulativeTotalRevenueUSD = BIGDECIMAL_ZERO; + _market.totalDepositBalanceUSD = BIGDECIMAL_ZERO; + _market.cumulativeDepositUSD = BIGDECIMAL_ZERO; + _market.totalBorrowBalanceUSD = BIGDECIMAL_ZERO; + _market.cumulativeBorrowUSD = BIGDECIMAL_ZERO; + _market.cumulativeLiquidateUSD = BIGDECIMAL_ZERO; + _market.cumulativeTransferUSD = BIGDECIMAL_ZERO; + _market.cumulativeFlashloanUSD = BIGDECIMAL_ZERO; + _market.transactionCount = INT_ZERO; + _market.depositCount = INT_ZERO; + _market.withdrawCount = INT_ZERO; + _market.borrowCount = INT_ZERO; + _market.repayCount = INT_ZERO; + _market.liquidationCount = INT_ZERO; + _market.transferCount = INT_ZERO; + _market.flashloanCount = INT_ZERO; + + _market.cumulativeUniqueUsers = INT_ZERO; + _market.cumulativeUniqueDepositors = INT_ZERO; + _market.cumulativeUniqueBorrowers = INT_ZERO; + _market.cumulativeUniqueLiquidators = INT_ZERO; + _market.cumulativeUniqueLiquidatees = INT_ZERO; + _market.cumulativeUniqueTransferrers = INT_ZERO; + _market.cumulativeUniqueFlashloaners = INT_ZERO; + + _market.createdTimestamp = event.block.timestamp; + _market.createdBlockNumber = event.block.number; + + _market.positionCount = INT_ZERO; + _market.openPositionCount = INT_ZERO; + _market.closedPositionCount = INT_ZERO; + _market.lendingPositionCount = INT_ZERO; + _market.borrowingPositionCount = INT_ZERO; + _market.save(); + + // add to market list + this.getOrAddMarketToList(marketID); + this.protocol.totalPoolCount += INT_ONE; + this.protocol.save(); + } + this.market = _market; + this.event = event; + + // load snapshots + this.snapshots = new SnapshotManager(event, this.protocol, this.market); + + // load oracle + if (this.market.oracle) { + this.oracle = Oracle.load(this.market.oracle!)!; + } + } + + ///////////////// + //// Getters //// + ///////////////// + + getOrCreateLendingProtocol(data: ProtocolData): LendingProtocol { + let protocol = LendingProtocol.load(data.protocolID); + if (!protocol) { + protocol = new LendingProtocol(data.protocolID); + protocol.protocol = data.protocol; + protocol.name = data.name; + protocol.slug = data.slug; + protocol.network = data.network; + protocol.type = ProtocolType.LENDING; + protocol.lendingType = data.lendingType; + protocol.lenderPermissionType = data.lenderPermissionType; + protocol.borrowerPermissionType = data.borrowerPermissionType; + protocol.poolCreatorPermissionType = data.poolCreatorPermissionType; + protocol.riskType = data.riskType; + protocol.collateralizationType = data.collateralizationType; + + protocol.cumulativeUniqueUsers = INT_ZERO; + protocol.cumulativeUniqueDepositors = INT_ZERO; + protocol.cumulativeUniqueBorrowers = INT_ZERO; + protocol.cumulativeUniqueLiquidators = INT_ZERO; + protocol.cumulativeUniqueLiquidatees = INT_ZERO; + protocol.totalValueLockedUSD = BIGDECIMAL_ZERO; + protocol.cumulativeSupplySideRevenueUSD = BIGDECIMAL_ZERO; + protocol.cumulativeProtocolSideRevenueUSD = BIGDECIMAL_ZERO; + protocol.cumulativeTotalRevenueUSD = BIGDECIMAL_ZERO; + protocol.totalDepositBalanceUSD = BIGDECIMAL_ZERO; + protocol.cumulativeDepositUSD = BIGDECIMAL_ZERO; + protocol.totalBorrowBalanceUSD = BIGDECIMAL_ZERO; + protocol.cumulativeBorrowUSD = BIGDECIMAL_ZERO; + protocol.cumulativeLiquidateUSD = BIGDECIMAL_ZERO; + protocol.totalPoolCount = INT_ZERO; + protocol.openPositionCount = INT_ZERO; + protocol.cumulativePositionCount = INT_ZERO; + protocol.transactionCount = INT_ZERO; + protocol.depositCount = INT_ZERO; + protocol.withdrawCount = INT_ZERO; + protocol.borrowCount = INT_ZERO; + protocol.repayCount = INT_ZERO; + protocol.liquidationCount = INT_ZERO; + protocol.transferCount = INT_ZERO; + protocol.flashloanCount = INT_ZERO; + } + + protocol.schemaVersion = Versions.getSchemaVersion(); + protocol.subgraphVersion = Versions.getSubgraphVersion(); + protocol.methodologyVersion = Versions.getMethodologyVersion(); + protocol.save(); + + return protocol; + } + + getMarket(): Market { + return this.market; + } + + getProtocol(): LendingProtocol { + return this.protocol; + } + + getInputToken(): Token { + return this.inputToken.getToken(); + } + + getOrCreateOracle( + oracleAddress: Address, + isUSD: boolean, + source?: string + ): Oracle { + const oracleID = this.market.id.concat(this.market.inputToken); + let oracle = Oracle.load(oracleID); + if (!oracle) { + oracle = new Oracle(oracleID); + oracle.market = this.market.id; + oracle.blockCreated = this.event.block.number; + oracle.timestampCreated = this.event.block.timestamp; + oracle.isActive = true; + } + oracle.oracleAddress = oracleAddress; + oracle.isUSD = isUSD; + if (source) { + oracle.oracleSource = source; + } + oracle.save(); + this.oracle = oracle; + + return oracle; + } + + getOracleAddress(): Address { + return Address.fromBytes(this.oracle.oracleAddress); + } + + getOrUpdateRate( + rateSide: string, + rateType: string, + interestRate: BigDecimal + ): InterestRate { + const interestRateID = rateSide + .concat("-") + .concat(rateType) + .concat("-") + .concat(this.market.id.toHexString()); + let rate = InterestRate.load(interestRateID); + if (!rate) { + rate = new InterestRate(interestRateID); + rate.side = rateSide; + rate.type = rateType; + } + rate.rate = interestRate; + rate.save(); + + let marketRates = this.market.rates; + if (!marketRates) { + marketRates = []; + } + + if (marketRates.indexOf(interestRateID) == -1) { + marketRates.push(interestRateID); + } + this.market.rates = marketRates; + this.market.save(); + + return rate; + } + + getOrUpdateFee( + feeType: string, + flatFee: BigDecimal | null = null, + rate: BigDecimal | null = null + ): Fee { + let fee = Fee.load(feeType); + if (!fee) { + fee = new Fee(feeType); + fee.type = feeType; + } + + fee.rate = rate; + fee.flatFee = flatFee; + fee.save(); + + let protocolFees = this.protocol.fees; + if (!protocolFees) { + protocolFees = []; + } + + if (protocolFees.indexOf(feeType) == -1) { + protocolFees.push(feeType); + } + this.protocol.fees = protocolFees; + this.protocol.save(); + + return fee; + } + + getAddress(): Address { + return Address.fromBytes(this.market.id); + } + + getOrCreateRevenueDetail(id: Bytes, isMarket: boolean): RevenueDetail { + let details = RevenueDetail.load(id); + if (!details) { + details = new RevenueDetail(id); + details.sources = []; + details.amountsUSD = []; + details.save(); + + if (isMarket) { + this.market.revenueDetail = details.id; + this.market.save(); + } else { + this.protocol.revenueDetail = details.id; + this.protocol.save(); + } + } + + return details; + } + + ////////////////// + //// Creators //// + ////////////////// + + createDeposit( + asset: Bytes, + account: Bytes, + amount: BigInt, + amountUSD: BigDecimal, + newBalance: BigInt, + interestType: string | null = null + ): Deposit { + const depositor = new AccountManager(account); + if (depositor.isNewUser()) { + this.protocol.cumulativeUniqueUsers += INT_ONE; + this.protocol.save(); + } + const position = new PositionManager( + depositor.getAccount(), + this.market, + PositionSide.COLLATERAL, + interestType + ); + position.addPosition( + this.event, + asset, + this.protocol, + newBalance, + TransactionType.DEPOSIT, + this.market.inputTokenPriceUSD + ); + + const deposit = new Deposit( + this.event.transaction.hash + .concatI32(this.event.logIndex.toI32()) + .concatI32(Transaction.DEPOSIT) + ); + deposit.hash = this.event.transaction.hash; + deposit.nonce = this.event.transaction.nonce; + deposit.logIndex = this.event.logIndex.toI32(); + deposit.gasPrice = this.event.transaction.gasPrice; + deposit.gasUsed = this.event.receipt ? this.event.receipt!.gasUsed : null; + deposit.gasLimit = this.event.transaction.gasLimit; + deposit.blockNumber = this.event.block.number; + deposit.timestamp = this.event.block.timestamp; + deposit.account = account; + deposit.market = this.market.id; + deposit.position = position.getPositionID()!; + deposit.asset = asset; + deposit.amount = amount; + deposit.amountUSD = amountUSD; + deposit.save(); + + this.updateTransactionData(TransactionType.DEPOSIT, amount, amountUSD); + this.updateUsageData(TransactionType.DEPOSIT, account); + + return deposit; + } + + createWithdraw( + asset: Bytes, + account: Bytes, + amount: BigInt, + amountUSD: BigDecimal, + newBalance: BigInt, + interestType: string | null = null + ): Withdraw | null { + const withdrawer = new AccountManager(account); + if (withdrawer.isNewUser()) { + this.protocol.cumulativeUniqueUsers += INT_ONE; + this.protocol.save(); + } + const position = new PositionManager( + withdrawer.getAccount(), + this.market, + PositionSide.COLLATERAL, + interestType + ); + position.subtractPosition( + this.event, + this.protocol, + newBalance, + TransactionType.WITHDRAW, + this.market.inputTokenPriceUSD + ); + const positionID = position.getPositionID(); + if (!positionID) { + log.error( + "[createWithdraw] positionID is null for market: {} account: {}", + [this.market.id.toHexString(), account.toHexString()] + ); + return null; + } + + const withdraw = new Withdraw( + this.event.transaction.hash + .concatI32(this.event.logIndex.toI32()) + .concatI32(Transaction.WITHDRAW) + ); + withdraw.hash = this.event.transaction.hash; + withdraw.nonce = this.event.transaction.nonce; + withdraw.logIndex = this.event.logIndex.toI32(); + withdraw.gasPrice = this.event.transaction.gasPrice; + withdraw.gasUsed = this.event.receipt ? this.event.receipt!.gasUsed : null; + withdraw.gasLimit = this.event.transaction.gasLimit; + withdraw.blockNumber = this.event.block.number; + withdraw.timestamp = this.event.block.timestamp; + withdraw.account = account; + withdraw.market = this.market.id; + withdraw.position = positionID!; + withdraw.asset = asset; + withdraw.amount = amount; + withdraw.amountUSD = amountUSD; + withdraw.save(); + + this.updateTransactionData(TransactionType.WITHDRAW, amount, amountUSD); + this.updateUsageData(TransactionType.WITHDRAW, account); + + return withdraw; + } + + createBorrow( + asset: Bytes, + account: Bytes, + amount: BigInt, + amountUSD: BigDecimal, + newBalance: BigInt, + tokenPriceUSD: BigDecimal, // used for different borrow token in CDP + interestType: string | null = null + ): Borrow { + const borrower = new AccountManager(account); + if (borrower.isNewUser()) { + this.protocol.cumulativeUniqueUsers += INT_ONE; + this.protocol.save(); + } + const position = new PositionManager( + borrower.getAccount(), + this.market, + PositionSide.BORROWER, + interestType + ); + position.addPosition( + this.event, + asset, + this.protocol, + newBalance, + TransactionType.BORROW, + tokenPriceUSD + ); + + const borrow = new Borrow( + this.event.transaction.hash + .concatI32(this.event.logIndex.toI32()) + .concatI32(Transaction.BORROW) + ); + borrow.hash = this.event.transaction.hash; + borrow.nonce = this.event.transaction.nonce; + borrow.logIndex = this.event.logIndex.toI32(); + borrow.gasPrice = this.event.transaction.gasPrice; + borrow.gasUsed = this.event.receipt ? this.event.receipt!.gasUsed : null; + borrow.gasLimit = this.event.transaction.gasLimit; + borrow.blockNumber = this.event.block.number; + borrow.timestamp = this.event.block.timestamp; + borrow.account = account; + borrow.market = this.market.id; + borrow.position = position.getPositionID()!; + borrow.asset = asset; + borrow.amount = amount; + borrow.amountUSD = amountUSD; + borrow.save(); + + this.updateTransactionData(TransactionType.BORROW, amount, amountUSD); + this.updateUsageData(TransactionType.BORROW, account); + + return borrow; + } + + createRepay( + asset: Bytes, + account: Bytes, + amount: BigInt, + amountUSD: BigDecimal, + newBalance: BigInt, + tokenPriceUSD: BigDecimal, // used for different borrow token in CDP + interestType: string | null = null + ): Repay | null { + const repayer = new AccountManager(account); + if (repayer.isNewUser()) { + this.protocol.cumulativeUniqueUsers += INT_ONE; + this.protocol.save(); + } + const position = new PositionManager( + repayer.getAccount(), + this.market, + PositionSide.BORROWER, + interestType + ); + position.subtractPosition( + this.event, + this.protocol, + newBalance, + TransactionType.REPAY, + tokenPriceUSD + ); + const positionID = position.getPositionID(); + if (!positionID) { + log.error("[createRepay] positionID is null for market: {} account: {}", [ + this.market.id.toHexString(), + account.toHexString(), + ]); + return null; + } + + const repay = new Repay( + this.event.transaction.hash + .concatI32(this.event.logIndex.toI32()) + .concatI32(Transaction.REPAY) + ); + repay.hash = this.event.transaction.hash; + repay.nonce = this.event.transaction.nonce; + repay.logIndex = this.event.logIndex.toI32(); + repay.gasPrice = this.event.transaction.gasPrice; + repay.gasUsed = this.event.receipt ? this.event.receipt!.gasUsed : null; + repay.gasLimit = this.event.transaction.gasLimit; + repay.blockNumber = this.event.block.number; + repay.timestamp = this.event.block.timestamp; + repay.account = account; + repay.market = this.market.id; + repay.position = positionID!; + repay.asset = asset; + repay.amount = amount; + repay.amountUSD = amountUSD; + repay.save(); + + this.updateTransactionData(TransactionType.REPAY, amount, amountUSD); + this.updateUsageData(TransactionType.REPAY, account); + + return repay; + } + + createLiquidate( + asset: Bytes, + liquidator: Address, + liquidatee: Address, + amount: BigInt, + amountUSD: BigDecimal, + profitUSD: BigDecimal, + newBalance: BigInt, // repaid token balance for liquidatee + interestType: string | null = null + ): Liquidate | null { + const liquidatorAccount = new AccountManager(liquidator); + if (liquidatorAccount.isNewUser()) { + this.protocol.cumulativeUniqueUsers += INT_ONE; + this.protocol.save(); + } + liquidatorAccount.countLiquidate(); + // Note: Be careful, some protocols might give the liquidated collateral to the liquidator + // in collateral in the market. But that is not always the case so we don't do it here. + + const liquidateeAccount = new AccountManager(liquidatee); + const liquidateePosition = new PositionManager( + liquidateeAccount.getAccount(), + this.market, + PositionSide.COLLATERAL, + interestType + ); + liquidateePosition.subtractPosition( + this.event, + this.protocol, + newBalance, + TransactionType.LIQUIDATE, + this.market.inputTokenPriceUSD + ); + // Note: + // - liquidatees are not considered users since they are not spending gas for the transaction + // - It is possible in some protocols for the liquidator to incur a position if they are transferred collateral tokens + + const positionID = liquidateePosition.getPositionID(); + if (!positionID) { + log.error( + "[createLiquidate] positionID is null for market: {} account: {}", + [this.market.id.toHexString(), liquidatee.toHexString()] + ); + return null; + } + + const liquidate = new Liquidate( + this.event.transaction.hash + .concatI32(this.event.logIndex.toI32()) + .concatI32(Transaction.LIQUIDATE) + ); + liquidate.hash = this.event.transaction.hash; + liquidate.nonce = this.event.transaction.nonce; + liquidate.logIndex = this.event.logIndex.toI32(); + liquidate.gasPrice = this.event.transaction.gasPrice; + liquidate.gasUsed = this.event.receipt ? this.event.receipt!.gasUsed : null; + liquidate.gasLimit = this.event.transaction.gasLimit; + liquidate.blockNumber = this.event.block.number; + liquidate.timestamp = this.event.block.timestamp; + liquidate.liquidator = liquidator; + liquidate.liquidatee = liquidatee; + liquidate.market = this.market.id; + liquidate.positions = [positionID!]; + liquidate.asset = asset; + liquidate.amount = amount; + liquidate.amountUSD = amountUSD; + liquidate.profitUSD = profitUSD; + liquidate.save(); + + this.updateTransactionData(TransactionType.LIQUIDATE, amount, amountUSD); + this.updateUsageData(TransactionType.LIQUIDATEE, liquidatee); + this.updateUsageData(TransactionType.LIQUIDATOR, liquidator); + + return liquidate; + } + + createTransfer( + asset: Bytes, + sender: Address, + receiver: Address, + amount: BigInt, + amountUSD: BigDecimal, + senderNewBalance: BigInt, + receiverNewBalance: BigInt, + interestType: string | null = null + ): Transfer | null { + const transferrer = new AccountManager(sender); + if (transferrer.isNewUser()) { + this.protocol.cumulativeUniqueUsers += INT_ONE; + this.protocol.save(); + } + const transferrerPosition = new PositionManager( + transferrer.getAccount(), + this.market, + PositionSide.COLLATERAL, + interestType + ); + transferrerPosition.subtractPosition( + this.event, + this.protocol, + senderNewBalance, + TransactionType.TRANSFER, + this.market.inputTokenPriceUSD + ); + const positionID = transferrerPosition.getPositionID(); + if (!positionID) { + log.error( + "[createTransfer] positionID is null for market: {} account: {}", + [this.market.id.toHexString(), receiver.toHexString()] + ); + return null; + } + + const recieverAccount = new AccountManager(receiver); + // receivers are not considered users since they are not spending gas for the transaction + const receiverPosition = new PositionManager( + recieverAccount.getAccount(), + this.market, + PositionSide.COLLATERAL, + interestType + ); + receiverPosition.addPosition( + this.event, + asset, + this.protocol, + receiverNewBalance, + TransactionType.TRANSFER, + this.market.inputTokenPriceUSD + ); + + const transfer = new Transfer( + this.event.transaction.hash + .concatI32(this.event.logIndex.toI32()) + .concatI32(Transaction.TRANSFER) + ); + transfer.hash = this.event.transaction.hash; + transfer.nonce = this.event.transaction.nonce; + transfer.logIndex = this.event.logIndex.toI32(); + transfer.gasPrice = this.event.transaction.gasPrice; + transfer.gasUsed = this.event.receipt ? this.event.receipt!.gasUsed : null; + transfer.gasLimit = this.event.transaction.gasLimit; + transfer.blockNumber = this.event.block.number; + transfer.timestamp = this.event.block.timestamp; + transfer.sender = sender; + transfer.receiver = receiver; + transfer.market = this.market.id; + transfer.positions = [receiverPosition.getPositionID()!, positionID!]; + transfer.asset = asset; + transfer.amount = amount; + transfer.amountUSD = amountUSD; + transfer.save(); + + this.updateTransactionData(TransactionType.TRANSFER, amount, amountUSD); + this.updateUsageData(TransactionType.TRANSFER, sender); + + return transfer; + } + + createFlashloan( + asset: Address, + account: Address, + amount: BigInt, + amountUSD: BigDecimal + ): Flashloan { + const flashloaner = new AccountManager(account); + if (flashloaner.isNewUser()) { + this.protocol.cumulativeUniqueUsers += INT_ONE; + this.protocol.save(); + } + flashloaner.countFlashloan(); + + const flashloan = new Flashloan( + this.event.transaction.hash + .concatI32(this.event.logIndex.toI32()) + .concatI32(Transaction.FLASHLOAN) + ); + flashloan.hash = this.event.transaction.hash; + flashloan.nonce = this.event.transaction.nonce; + flashloan.logIndex = this.event.logIndex.toI32(); + flashloan.gasPrice = this.event.transaction.gasPrice; + flashloan.gasUsed = this.event.receipt ? this.event.receipt!.gasUsed : null; + flashloan.gasLimit = this.event.transaction.gasLimit; + flashloan.blockNumber = this.event.block.number; + flashloan.timestamp = this.event.block.timestamp; + flashloan.account = account; + flashloan.market = this.market.id; + flashloan.asset = asset; + flashloan.amount = amount; + flashloan.amountUSD = amountUSD; + flashloan.save(); + + this.updateTransactionData(TransactionType.FLASHLOAN, amount, amountUSD); + this.updateUsageData(TransactionType.FLASHLOAN, account); + + return flashloan; + } + + ////////////////// + //// Updaters //// + ////////////////// + + updateRewards(rewardData: RewardData): void { + if (!this.market.rewardTokens) { + this.market.rewardTokens = [rewardData.rewardToken.id]; + this.market.rewardTokenEmissionsAmount = [ + rewardData.rewardTokenEmissionsAmount, + ]; + this.market.rewardTokenEmissionsUSD = [ + rewardData.rewardTokenEmissionsUSD, + ]; + return; // initial add is manual + } + + // update market reward tokens with rewardData so that it is in alphabetical order + let rewardTokens = this.market.rewardTokens!; + let rewardTokenEmissionsAmount = this.market.rewardTokenEmissionsAmount!; + let rewardTokenEmissionsUSD = this.market.rewardTokenEmissionsUSD!; + + for (let i = 0; i < rewardTokens.length; i++) { + const index = rewardData.rewardToken.id.localeCompare(rewardTokens[i]); + if (index < 0) { + // insert rewardData at index i + rewardTokens = insert(rewardTokens, i, rewardData.rewardToken.id); + rewardTokenEmissionsAmount = insert( + rewardTokenEmissionsAmount, + i, + rewardData.rewardTokenEmissionsAmount + ); + rewardTokenEmissionsUSD = insert( + rewardTokenEmissionsUSD, + i, + rewardData.rewardTokenEmissionsUSD + ); + break; + } else if (index == 0) { + // update the rewardData at index i + rewardTokens[i] = rewardData.rewardToken.id; + rewardTokenEmissionsAmount[i] = rewardData.rewardTokenEmissionsAmount; + rewardTokenEmissionsUSD[i] = rewardData.rewardTokenEmissionsUSD; + break; + } else { + if (i == rewardTokens.length - 1) { + // insert rewardData at end of array + rewardTokens.push(rewardData.rewardToken.id); + rewardTokenEmissionsAmount.push( + rewardData.rewardTokenEmissionsAmount + ); + rewardTokenEmissionsUSD.push(rewardData.rewardTokenEmissionsUSD); + break; + } + } + } + + this.market.rewardTokens = rewardTokens; + this.market.rewardTokenEmissionsAmount = rewardTokenEmissionsAmount; + this.market.rewardTokenEmissionsUSD = rewardTokenEmissionsUSD; + this.market.save(); + } + + // used to update tvl, borrow balance, reserves, etc. in market and protocol + updateMarketAndProtocolData( + inputTokenPriceUSD: BigDecimal, + newInputTokenBalance: BigInt, + newVariableBorrowBalance: BigInt | null = null, + newStableBorrowBalance: BigInt | null = null, + newReserveBalance: BigInt | null = null, + exchangeRate: BigDecimal | null = null + ): void { + const mantissaFactorBD = exponentToBigDecimal( + this.inputToken.getDecimals() + ); + this.inputToken.updatePrice(inputTokenPriceUSD); + this.market.inputTokenPriceUSD = inputTokenPriceUSD; + this.market.inputTokenBalance = newInputTokenBalance; + if (newVariableBorrowBalance) { + this.market.variableBorrowedTokenBalance = newVariableBorrowBalance; + } + if (newStableBorrowBalance) { + this.market.stableBorrowedTokenBalance = newStableBorrowBalance; + } + if (newReserveBalance) { + this.market.reserves = newReserveBalance + .toBigDecimal() + .div(mantissaFactorBD) + .times(inputTokenPriceUSD); + } + if (exchangeRate) { + this.market.exchangeRate = exchangeRate; + } + const vBorrowAmount = this.market.variableBorrowedTokenBalance + ? this.market + .variableBorrowedTokenBalance!.toBigDecimal() + .div(mantissaFactorBD) + : BIGDECIMAL_ZERO; + const sBorrowAmount = this.market.stableBorrowedTokenBalance + ? this.market + .stableBorrowedTokenBalance!.toBigDecimal() + .div(mantissaFactorBD) + : BIGDECIMAL_ZERO; + const totalBorrowed = vBorrowAmount.plus(sBorrowAmount); + this.market.totalValueLockedUSD = newInputTokenBalance + .toBigDecimal() + .div(mantissaFactorBD) + .times(inputTokenPriceUSD); + this.market.totalDepositBalanceUSD = this.market.totalValueLockedUSD; + this.market.totalBorrowBalanceUSD = totalBorrowed.times(inputTokenPriceUSD); + this.market.save(); + + let totalValueLockedUSD = BIGDECIMAL_ZERO; + let totalBorrowBalanceUSD = BIGDECIMAL_ZERO; + const marketList = this.getOrAddMarketToList(); + for (let i = 0; i < marketList.length; i++) { + const _market = Market.load(marketList[i]); + if (!_market) { + log.error("[updateMarketAndProtocolData] Market not found: {}", [ + marketList[i].toHexString(), + ]); + continue; + } + totalValueLockedUSD = totalValueLockedUSD.plus( + _market.totalValueLockedUSD + ); + totalBorrowBalanceUSD = totalBorrowBalanceUSD.plus( + _market.totalBorrowBalanceUSD + ); + } + this.protocol.totalValueLockedUSD = totalValueLockedUSD; + this.protocol.totalDepositBalanceUSD = totalValueLockedUSD; + this.protocol.totalBorrowBalanceUSD = totalBorrowBalanceUSD; + this.protocol.save(); + } + + // + // + // Update the protocol revenue + addProtocolRevenue( + protocolRevenueDelta: BigDecimal, + fee: Fee | null = null + ): void { + this.updateRevenue(protocolRevenueDelta, BIGDECIMAL_ZERO); + + if (!fee) { + fee = this.getOrUpdateFee(FeeType.OTHER); + } + + const marketRevDetails = this.getOrCreateRevenueDetail( + this.market.id, + true + ); + const protocolRevenueDetail = this.getOrCreateRevenueDetail( + this.protocol.id, + false + ); + + this.insertInOrder(marketRevDetails, protocolRevenueDelta, fee.id); + this.insertInOrder(protocolRevenueDetail, protocolRevenueDelta, fee.id); + } + + // + // + // Update the protocol revenue + addSupplyRevenue( + supplyRevenueDelta: BigDecimal, + fee: Fee | null = null + ): void { + this.updateRevenue(BIGDECIMAL_ZERO, supplyRevenueDelta); + + if (!fee) { + fee = this.getOrUpdateFee(FeeType.OTHER); + } + + const marketRevDetails = this.getOrCreateRevenueDetail( + this.market.id, + true + ); + const protocolRevenueDetail = this.getOrCreateRevenueDetail( + this.protocol.id, + false + ); + + this.insertInOrder(marketRevDetails, supplyRevenueDelta, fee.id); + this.insertInOrder(protocolRevenueDetail, supplyRevenueDelta, fee.id); + } + + private updateRevenue( + protocolRevenueDelta: BigDecimal, + supplyRevenueDelta: BigDecimal + ): void { + const totalRevenueDelta = protocolRevenueDelta.plus(supplyRevenueDelta); + + // update market + this.market.cumulativeTotalRevenueUSD = + this.market.cumulativeTotalRevenueUSD.plus(totalRevenueDelta); + this.market.cumulativeProtocolSideRevenueUSD = + this.market.cumulativeProtocolSideRevenueUSD.plus(protocolRevenueDelta); + this.market.cumulativeSupplySideRevenueUSD = + this.market.cumulativeSupplySideRevenueUSD.plus(supplyRevenueDelta); + this.market.save(); + + // update protocol + this.protocol.cumulativeTotalRevenueUSD = + this.protocol.cumulativeTotalRevenueUSD.plus(totalRevenueDelta); + this.protocol.cumulativeProtocolSideRevenueUSD = + this.protocol.cumulativeProtocolSideRevenueUSD.plus(protocolRevenueDelta); + this.protocol.cumulativeSupplySideRevenueUSD = + this.protocol.cumulativeSupplySideRevenueUSD.plus(supplyRevenueDelta); + this.protocol.save(); + + // update revenue in snapshots + this.snapshots.updateRevenue(protocolRevenueDelta, supplyRevenueDelta); + } + + // + // + // this only updates the usage data for the entities changed in this class + // (ie, market and protocol) + private updateUsageData(transactionType: string, account: Bytes): void { + this.market.cumulativeUniqueUsers += activityCounter( + account, + transactionType, + false, + 0, + this.market.id + ); + if (transactionType == TransactionType.DEPOSIT) { + this.market.cumulativeUniqueDepositors += activityCounter( + account, + transactionType, + true, + 0, + this.market.id + ); + this.protocol.cumulativeUniqueDepositors += activityCounter( + account, + transactionType, + true, + 0 + ); + } + if (transactionType == TransactionType.BORROW) { + this.market.cumulativeUniqueBorrowers += activityCounter( + account, + transactionType, + true, + 0, + this.market.id + ); + this.protocol.cumulativeUniqueBorrowers += activityCounter( + account, + transactionType, + true, + 0 + ); + } + if (transactionType == TransactionType.LIQUIDATOR) { + this.market.cumulativeUniqueLiquidators += activityCounter( + account, + transactionType, + true, + 0, + this.market.id + ); + this.protocol.cumulativeUniqueLiquidators += activityCounter( + account, + transactionType, + true, + 0 + ); + } + if (transactionType == TransactionType.LIQUIDATEE) { + this.market.cumulativeUniqueLiquidatees += activityCounter( + account, + transactionType, + true, + 0, + this.market.id + ); + this.protocol.cumulativeUniqueLiquidatees += activityCounter( + account, + transactionType, + true, + 0 + ); + } + if (transactionType == TransactionType.TRANSFER) + this.market.cumulativeUniqueTransferrers += activityCounter( + account, + transactionType, + true, + 0, + this.market.id + ); + if (transactionType == TransactionType.FLASHLOAN) + this.market.cumulativeUniqueFlashloaners += activityCounter( + account, + transactionType, + true, + 0, + this.market.id + ); + + this.protocol.save(); + this.market.save(); + + // update the snapshots in their respective class + this.snapshots.updateUsageData(transactionType, account); + } + + // + // + // this only updates the usage data for the entities changed in this class + // (ie, market and protocol) + private updateTransactionData( + transactionType: string, + amount: BigInt, + amountUSD: BigDecimal + ): void { + if (transactionType == TransactionType.DEPOSIT) { + this.protocol.depositCount += INT_ONE; + this.protocol.cumulativeDepositUSD = + this.protocol.cumulativeDepositUSD.plus(amountUSD); + this.market.cumulativeDepositUSD = + this.market.cumulativeDepositUSD.plus(amountUSD); + this.market.depositCount += INT_ONE; + } else if (transactionType == TransactionType.WITHDRAW) { + this.protocol.withdrawCount += INT_ONE; + this.market.withdrawCount += INT_ONE; + } else if (transactionType == TransactionType.BORROW) { + this.protocol.borrowCount += INT_ONE; + this.protocol.cumulativeBorrowUSD = + this.protocol.cumulativeBorrowUSD.plus(amountUSD); + this.market.cumulativeBorrowUSD = + this.market.cumulativeBorrowUSD.plus(amountUSD); + this.market.borrowCount += INT_ONE; + } else if (transactionType == TransactionType.REPAY) { + this.protocol.repayCount += INT_ONE; + this.market.repayCount += INT_ONE; + } else if (transactionType == TransactionType.LIQUIDATE) { + this.protocol.liquidationCount += INT_ONE; + this.protocol.cumulativeLiquidateUSD = + this.protocol.cumulativeLiquidateUSD.plus(amountUSD); + this.market.cumulativeLiquidateUSD = + this.market.cumulativeLiquidateUSD.plus(amountUSD); + this.market.liquidationCount += INT_ONE; + } else if (transactionType == TransactionType.TRANSFER) { + this.protocol.transferCount += INT_ONE; + this.market.cumulativeTransferUSD = + this.market.cumulativeTransferUSD.plus(amountUSD); + this.market.transferCount += INT_ONE; + } else if (transactionType == TransactionType.FLASHLOAN) { + this.protocol.flashloanCount += INT_ONE; + this.market.cumulativeFlashloanUSD = + this.market.cumulativeFlashloanUSD.plus(amountUSD); + this.market.flashloanCount += INT_ONE; + } else { + log.error("[updateTransactionData] Invalid transaction type: {}", [ + transactionType, + ]); + return; + } + this.protocol.transactionCount += INT_ONE; + this.market.transactionCount += INT_ONE; + + this.protocol.save(); + this.market.save(); + + // update the snapshots in their respective class + this.snapshots.updateTransactionData(transactionType, amount, amountUSD); + } + + // + // + // Insert revenue in RevenueDetail in order (alphabetized) + private insertInOrder( + details: RevenueDetail, + amountUSD: BigDecimal, + associatedSource: string + ): void { + if (details.sources.length == 0) { + details.sources = [associatedSource]; + details.amountsUSD = [amountUSD]; + details.save(); + return; // initial add is manually done + } + + let sources = details.sources; + let amountsUSD = details.amountsUSD; + + // insert in alphabetical order + for (let i = 0; i < sources.length; i++) { + const index = associatedSource.localeCompare(sources[i]); + if (index < 0) { + // insert associatedSource at index i + sources = insert(sources, i, associatedSource); + amountsUSD = insert( + details.amountsUSD, + i, + amountsUSD[i].plus(amountUSD) + ); + break; + } else if (index == 0) { + // update associatedSource at index i + sources[i] = associatedSource; + amountsUSD[i] = amountsUSD[i].plus(amountUSD); + break; + } else { + if (i == sources.length - 1) { + sources.push(associatedSource); + amountsUSD.push(amountUSD); + break; + } + } + } + details.sources = sources; + details.amountsUSD = amountsUSD; + details.save(); + } + + // + // + // Get list of markets in the protocol (or add new market if not in there) + private getOrAddMarketToList(marketID: Bytes | null = null): Bytes[] { + let markets = _MarketList.load(this.protocol.id); + if (!markets) { + markets = new _MarketList(this.protocol.id); + markets.markets = []; + } + + if (!marketID) { + return markets.markets; + } + + // check if market is already in list + if (markets.markets.includes(marketID)) { + return markets.markets; + } + + // add new market and return + const marketList = markets.markets; + marketList.push(marketID); + markets.markets = marketList; + markets.save(); + + return marketList; + } +} diff --git a/subgraphs/ebtc/src/sdk/position.ts b/subgraphs/ebtc/src/sdk/position.ts new file mode 100644 index 0000000000..0560a89dbe --- /dev/null +++ b/subgraphs/ebtc/src/sdk/position.ts @@ -0,0 +1,327 @@ +import { + BigDecimal, + Bytes, + BigInt, + log, + ethereum, +} from "@graphprotocol/graph-ts"; +import { + Account, + LendingProtocol, + Market, + Position, + _PositionCounter, + PositionSnapshot, +} from "../../../../generated/schema"; +import { + BIGINT_ZERO, + exponentToBigDecimal, + INT_ONE, + INT_ZERO, + SECONDS_PER_DAY, + TransactionType, +} from "./constants"; +import { SnapshotManager } from "./snapshots"; +import { TokenManager } from "./token"; + +/** + * This file contains the PositionManager class, which is used to + * make changes to a given position. + * + * Schema Version: 3.0.1 + * SDK Version: 1.0.2 + * Author(s): + * - @dmelotik + */ + +export class PositionManager { + private counterID: string; + private position: Position | null = null; + private market: Market; + private account: Account; + private side: string; + private interestType: string | null = null; + + constructor( + account: Account, + market: Market, + side: string, + interestType: string | null = null + ) { + this.counterID = account.id + .toHexString() + .concat("-") + .concat(market.id.toHexString()) + .concat("-") + .concat(side); + if (interestType) { + this.counterID = this.counterID.concat("-").concat(interestType); + } + const positionCounter = _PositionCounter.load(this.counterID); + if (positionCounter) { + const positionID = positionCounter.id + .concat("-") + .concat(positionCounter.nextCount.toString()); + this.position = Position.load(positionID); + } + + this.market = market; + this.account = account; + this.side = side; + this.interestType = interestType; + } + + getPositionID(): string | null { + if (this.position) { + return this.position!.id; + } + return null; + } + + setCollateral(isCollateral: boolean): void { + if (this.position) { + this.position.isCollateral = isCollateral; + this.position.save(); + } + } + + setIsolation(isIsolated: boolean): void { + if (this.position) { + this.position.isIsolated = isIsolated; + this.position.save(); + } + } + + addPosition( + event: ethereum.Event, + asset: Bytes, + protocol: LendingProtocol, + newBalance: BigInt, + transactionType: string, + priceUSD: BigDecimal + ): void { + let positionCounter = _PositionCounter.load(this.counterID); + if (!positionCounter) { + positionCounter = new _PositionCounter(this.counterID); + positionCounter.nextCount = 0; + positionCounter.lastTimestamp = event.block.timestamp; + positionCounter.save(); + } + const positionID = positionCounter.id + .concat("-") + .concat(positionCounter.nextCount.toString()); + + let position = Position.load(positionID); + const openPosition = position == null; + if (!openPosition) { + // update existing position + position = position!; + position.balance = newBalance; + if (transactionType == TransactionType.DEPOSIT) { + position.depositCount += INT_ONE; + } else if (transactionType == TransactionType.BORROW) { + position.borrowCount += INT_ONE; + } else if (transactionType == TransactionType.TRANSFER) { + position.receivedCount += INT_ONE; + } + // Note: liquidateCount is not incremented here + position.save(); + this.position = position; + + // + // take position snapshot + // + this.snapshotPosition(event, priceUSD); + return; + } + position = new Position(positionID); + position.account = this.account.id; + position.market = this.market.id; + position.asset = asset; + position.hashOpened = event.transaction.hash; + position.blockNumberOpened = event.block.number; + position.timestampOpened = event.block.timestamp; + position.side = this.side; + if (this.interestType) { + position.type = this.interestType; + } + position.balance = newBalance; + position.depositCount = INT_ZERO; + position.withdrawCount = INT_ZERO; + position.borrowCount = INT_ZERO; + position.repayCount = INT_ZERO; + position.liquidationCount = INT_ZERO; + position.transferredCount = INT_ZERO; + position.receivedCount = INT_ZERO; + + if (transactionType == TransactionType.DEPOSIT) { + position.depositCount += INT_ONE; + } else if (transactionType == TransactionType.BORROW) { + position.borrowCount += INT_ONE; + } else if (transactionType == TransactionType.TRANSFER) { + position.receivedCount += INT_ONE; + } + position.save(); + + // + // update account position + // + this.account.positionCount += 1; + this.account.openPositionCount += 1; + this.account.save(); + + // + // update market position + // + this.market.positionCount += 1; + this.market.openPositionCount += 1; + + if ( + transactionType == TransactionType.DEPOSIT || + transactionType == TransactionType.TRANSFER + ) { + this.market.lendingPositionCount += 1; + } else if (transactionType == TransactionType.BORROW) { + this.market.borrowingPositionCount += 1; + } + this.market.save(); + + // + // update protocol position + // + protocol.cumulativePositionCount += 1; + protocol.openPositionCount += 1; + protocol.save(); + + this.position = position; + + // + // take position snapshot + // + this.snapshotPosition(event, priceUSD); + this.dailyActivePosition(positionCounter, event, protocol); + } + + subtractPosition( + event: ethereum.Event, + protocol: LendingProtocol, + newBalance: BigInt, + transactionType: string, + priceUSD: BigDecimal + ): void { + const positionCounter = _PositionCounter.load(this.counterID); + if (!positionCounter) { + log.warning("[subtractPosition] position counter {} not found", [ + this.counterID, + ]); + return; + } + const positionID = positionCounter.id + .concat("-") + .concat(positionCounter.nextCount.toString()); + const position = Position.load(positionID); + if (!position) { + log.warning("[subtractPosition] position {} not found", [positionID]); + return; + } + + position.balance = newBalance; + + if (transactionType == TransactionType.WITHDRAW) { + position.withdrawCount += INT_ONE; + } else if (transactionType == TransactionType.REPAY) { + position.repayCount += INT_ONE; + } else if (transactionType == TransactionType.TRANSFER) { + position.transferredCount += INT_ONE; + } else if (transactionType == TransactionType.LIQUIDATE) { + position.liquidationCount += INT_ONE; + } + position.save(); + + const closePosition = position.balance == BIGINT_ZERO; + if (closePosition) { + // + // update position counter + // + positionCounter.nextCount += INT_ONE; + positionCounter.save(); + + // + // close position + // + position.hashClosed = event.transaction.hash; + position.blockNumberClosed = event.block.number; + position.timestampClosed = event.block.timestamp; + position.save(); + + // + // update account position + // + this.account.openPositionCount -= INT_ONE; + this.account.closedPositionCount += INT_ONE; + this.account.save(); + + // + // update market position + // + this.market.openPositionCount -= INT_ONE; + this.market.closedPositionCount += INT_ONE; + this.market.save(); + + // + // update protocol position + // + protocol.openPositionCount -= INT_ONE; + protocol.save(); + } + this.position = position; + + // + // update position snapshot + // + this.snapshotPosition(event, priceUSD); + this.dailyActivePosition(positionCounter, event, protocol); + } + + private snapshotPosition(event: ethereum.Event, priceUSD: BigDecimal): void { + const snapshot = new PositionSnapshot( + this.position!.id.concat("-") + .concat(event.transaction.hash.toHexString()) + .concat("-") + .concat(event.logIndex.toString()) + ); + const token = new TokenManager(this.position!.asset, event); + const mantissaFactorBD = exponentToBigDecimal(token.getDecimals()); + snapshot.hash = event.transaction.hash; + snapshot.logIndex = event.logIndex.toI32(); + snapshot.nonce = event.transaction.nonce; + snapshot.account = this.account.id; + snapshot.position = this.position!.id; + snapshot.balance = this.position!.balance; + snapshot.balanceUSD = this.position!.balance.toBigDecimal() + .div(mantissaFactorBD) + .times(priceUSD); + snapshot.blockNumber = event.block.number; + snapshot.timestamp = event.block.timestamp; + snapshot.save(); + } + + private dailyActivePosition( + counter: _PositionCounter, + event: ethereum.Event, + protocol: LendingProtocol + ): void { + const lastDay = counter.lastTimestamp.toI32() / SECONDS_PER_DAY; + const currentDay = event.block.timestamp.toI32() / SECONDS_PER_DAY; + if (lastDay == currentDay) { + return; + } + + // this is a new active position + const snapshots = new SnapshotManager(event, protocol, this.market); + snapshots.addDailyActivePosition(this.side); + + counter.lastTimestamp = event.block.timestamp; + counter.save(); + } +} diff --git a/subgraphs/ebtc/src/sdk/snapshots.ts b/subgraphs/ebtc/src/sdk/snapshots.ts new file mode 100644 index 0000000000..9252c5aea8 --- /dev/null +++ b/subgraphs/ebtc/src/sdk/snapshots.ts @@ -0,0 +1,645 @@ +import { + BigDecimal, + BigInt, + Bytes, + ethereum, + log, +} from "@graphprotocol/graph-ts"; +import { + FinancialsDailySnapshot, + InterestRate, + LendingProtocol, + Market, + MarketDailySnapshot, + MarketHourlySnapshot, + RevenueDetail, + UsageMetricsDailySnapshot, + UsageMetricsHourlySnapshot, +} from "../../../../generated/schema"; +import { + activityCounter, + BIGDECIMAL_ZERO, + BIGINT_ZERO, + INT_ONE, + INT_ZERO, + PositionSide, + SECONDS_PER_DAY, + SECONDS_PER_HOUR, + TransactionType, +} from "./constants"; + +/** + * This file contains the SnapshotManager, which is used to + * make all of the storage changes that occur in lending snapshots. + * + * You can think of this as an abstraction so the developer doesn't + * need to think about all of the detailed storage changes that occur. + * + * Schema Version: 3.0.1 + * SDK Version: 1.0.2 + * Author(s): + * - @dmelotik + */ + +export class SnapshotManager { + private marketHourlySnapshot!: MarketHourlySnapshot; + private marketDailySnapshot!: MarketDailySnapshot; + private financialSnapshot!: FinancialsDailySnapshot; + private usageHourlySnapshot!: UsageMetricsHourlySnapshot; + private usageDailySnapshot!: UsageMetricsDailySnapshot; + + private event: ethereum.Event; + private market: Market; + private protocol: LendingProtocol; + + constructor( + event: ethereum.Event, + protocol: LendingProtocol, + market: Market + ) { + this.event = event; + this.protocol = protocol; + this.market = market; + + this.createOrUpdateMarketHourlySnapshot(); + this.createOrUpdateMarketDailySnapshot(); + this.createOrUpdateFinancials(); + this.createOrUpdateUsageDailySnapshot(); + this.createOrUpdateUsageHourlySnapshot(); + } + + /////////////////// + ///// Getters ///// + /////////////////// + + private createOrUpdateMarketHourlySnapshot(): void { + const hours = this.event.block.timestamp.toI32() / SECONDS_PER_HOUR; + const id = this.market.id.concat(Bytes.fromI32(hours)); + let snapshot = MarketHourlySnapshot.load(id); + + if (!snapshot) { + snapshot = new MarketHourlySnapshot(id); + snapshot.hours = hours; + snapshot.protocol = this.protocol.id; + snapshot.market = this.market.id; + snapshot.relation = this.market.relation; + snapshot.hourlySupplySideRevenueUSD = BIGDECIMAL_ZERO; + snapshot.hourlyProtocolSideRevenueUSD = BIGDECIMAL_ZERO; + snapshot.hourlyTotalRevenueUSD = BIGDECIMAL_ZERO; + snapshot.hourlyDepositUSD = BIGDECIMAL_ZERO; + snapshot.hourlyBorrowUSD = BIGDECIMAL_ZERO; + snapshot.hourlyLiquidateUSD = BIGDECIMAL_ZERO; + snapshot.hourlyWithdrawUSD = BIGDECIMAL_ZERO; + snapshot.hourlyRepayUSD = BIGDECIMAL_ZERO; + snapshot.hourlyTransferUSD = BIGDECIMAL_ZERO; + snapshot.hourlyFlashloanUSD = BIGDECIMAL_ZERO; + } + snapshot.blockNumber = this.event.block.number; + snapshot.timestamp = this.event.block.timestamp; + snapshot.inputTokenBalance = this.market.inputTokenBalance; + snapshot.inputTokenPriceUSD = this.market.inputTokenPriceUSD; + snapshot.outputTokenSupply = this.market.outputTokenSupply; + snapshot.outputTokenPriceUSD = this.market.outputTokenPriceUSD; + snapshot.exchangeRate = this.market.exchangeRate; + snapshot.rates = this.market.rates + ? this.getSnapshotRates(this.market.rates!, hours.toString()) + : null; + snapshot.reserves = this.market.reserves; + snapshot.variableBorrowedTokenBalance = + this.market.variableBorrowedTokenBalance; + snapshot.stableBorrowedTokenBalance = + this.market.stableBorrowedTokenBalance; + snapshot.totalValueLockedUSD = this.market.totalValueLockedUSD; + snapshot.cumulativeSupplySideRevenueUSD = + this.market.cumulativeSupplySideRevenueUSD; + snapshot.cumulativeProtocolSideRevenueUSD = + this.market.cumulativeProtocolSideRevenueUSD; + snapshot.cumulativeTotalRevenueUSD = this.market.cumulativeTotalRevenueUSD; + snapshot.totalDepositBalanceUSD = this.market.totalDepositBalanceUSD; + snapshot.cumulativeDepositUSD = this.market.cumulativeDepositUSD; + snapshot.totalBorrowBalanceUSD = this.market.totalBorrowBalanceUSD; + snapshot.cumulativeBorrowUSD = this.market.cumulativeBorrowUSD; + snapshot.cumulativeLiquidateUSD = this.market.cumulativeLiquidateUSD; + snapshot.rewardTokenEmissionsAmount = + this.market.rewardTokenEmissionsAmount; + snapshot.rewardTokenEmissionsUSD = this.market.rewardTokenEmissionsUSD; + snapshot.stakedOutputTokenAmount = this.market.stakedOutputTokenAmount; + + snapshot.save(); + this.marketHourlySnapshot = snapshot; + } + + private createOrUpdateMarketDailySnapshot(): void { + const days = this.event.block.timestamp.toI32() / SECONDS_PER_DAY; + const id = this.market.id.concat(Bytes.fromI32(days)); + let snapshot = MarketDailySnapshot.load(id); + + if (!snapshot) { + snapshot = new MarketDailySnapshot(id); + snapshot.days = days; + snapshot.protocol = this.protocol.id; + snapshot.market = this.market.id; + snapshot.relation = this.market.relation; + snapshot.dailySupplySideRevenueUSD = BIGDECIMAL_ZERO; + snapshot.dailyProtocolSideRevenueUSD = BIGDECIMAL_ZERO; + snapshot.dailyTotalRevenueUSD = BIGDECIMAL_ZERO; + snapshot.dailyDepositUSD = BIGDECIMAL_ZERO; + snapshot.dailyNativeDeposit = BIGINT_ZERO; + snapshot.dailyBorrowUSD = BIGDECIMAL_ZERO; + snapshot.dailyNativeBorrow = BIGINT_ZERO; + snapshot.dailyLiquidateUSD = BIGDECIMAL_ZERO; + snapshot.dailyNativeLiquidate = BIGINT_ZERO; + snapshot.dailyWithdrawUSD = BIGDECIMAL_ZERO; + snapshot.dailyNativeWithdraw = BIGINT_ZERO; + snapshot.dailyRepayUSD = BIGDECIMAL_ZERO; + snapshot.dailyNativeRepay = BIGINT_ZERO; + snapshot.dailyTransferUSD = BIGDECIMAL_ZERO; + snapshot.dailyNativeTransfer = BIGINT_ZERO; + snapshot.dailyFlashloanUSD = BIGDECIMAL_ZERO; + snapshot.dailyNativeFlashloan = BIGINT_ZERO; + snapshot.dailyActiveUsers = INT_ZERO; + snapshot.dailyActiveDepositors = INT_ZERO; + snapshot.dailyActiveBorrowers = INT_ZERO; + snapshot.dailyActiveLiquidators = INT_ZERO; + snapshot.dailyActiveLiquidatees = INT_ZERO; + snapshot.dailyActiveTransferrers = INT_ZERO; + snapshot.dailyActiveFlashloaners = INT_ZERO; + snapshot.dailyDepositCount = INT_ZERO; + snapshot.dailyWithdrawCount = INT_ZERO; + snapshot.dailyBorrowCount = INT_ZERO; + snapshot.dailyRepayCount = INT_ZERO; + snapshot.dailyLiquidateCount = INT_ZERO; + snapshot.dailyTransferCount = INT_ZERO; + snapshot.dailyFlashloanCount = INT_ZERO; + snapshot.dailyActiveLendingPositionCount = INT_ZERO; + snapshot.dailyActiveBorrowingPositionCount = INT_ZERO; + } + snapshot.blockNumber = this.event.block.number; + snapshot.timestamp = this.event.block.timestamp; + snapshot.inputTokenBalance = this.market.inputTokenBalance; + snapshot.inputTokenPriceUSD = this.market.inputTokenPriceUSD; + snapshot.outputTokenSupply = this.market.outputTokenSupply; + snapshot.outputTokenPriceUSD = this.market.outputTokenPriceUSD; + snapshot.exchangeRate = this.market.exchangeRate; + snapshot.rates = this.market.rates + ? this.getSnapshotRates(this.market.rates!, days.toString()) + : null; + snapshot.reserves = this.market.reserves; + snapshot.variableBorrowedTokenBalance = + this.market.variableBorrowedTokenBalance; + snapshot.stableBorrowedTokenBalance = + this.market.stableBorrowedTokenBalance; + snapshot.supplyCap = this.market.supplyCap; + snapshot.borrowCap = this.market.borrowCap; + snapshot.totalValueLockedUSD = this.market.totalValueLockedUSD; + snapshot.cumulativeSupplySideRevenueUSD = + this.market.cumulativeSupplySideRevenueUSD; + snapshot.cumulativeProtocolSideRevenueUSD = + this.market.cumulativeProtocolSideRevenueUSD; + snapshot.cumulativeTotalRevenueUSD = this.market.cumulativeTotalRevenueUSD; + snapshot.revenueDetail = this.market.revenueDetail + ? this.getSnapshotRevenueDetail(this.market.revenueDetail!, days) + : null; + snapshot.totalDepositBalanceUSD = this.market.totalDepositBalanceUSD; + snapshot.cumulativeDepositUSD = this.market.cumulativeDepositUSD; + snapshot.totalBorrowBalanceUSD = this.market.totalBorrowBalanceUSD; + snapshot.cumulativeBorrowUSD = this.market.cumulativeBorrowUSD; + snapshot.cumulativeLiquidateUSD = this.market.cumulativeLiquidateUSD; + snapshot.cumulativeTransferUSD = this.market.cumulativeTransferUSD; + snapshot.cumulativeFlashloanUSD = this.market.cumulativeFlashloanUSD; + snapshot.positionCount = this.market.positionCount; + snapshot.openPositionCount = this.market.openPositionCount; + snapshot.closedPositionCount = this.market.closedPositionCount; + snapshot.lendingPositionCount = this.market.lendingPositionCount; + snapshot.borrowingPositionCount = this.market.borrowingPositionCount; + snapshot.rewardTokenEmissionsAmount = + this.market.rewardTokenEmissionsAmount; + snapshot.rewardTokenEmissionsUSD = this.market.rewardTokenEmissionsUSD; + snapshot.stakedOutputTokenAmount = this.market.stakedOutputTokenAmount; + + snapshot.save(); + this.marketDailySnapshot = snapshot; + } + + createOrUpdateFinancials(): void { + const days = this.event.block.timestamp.toI32() / SECONDS_PER_DAY; + const id = Bytes.fromI32(days); + let snapshot = FinancialsDailySnapshot.load(id); + + if (!snapshot) { + snapshot = new FinancialsDailySnapshot(id); + snapshot.days = days; + snapshot.protocol = this.protocol.id; + snapshot.dailySupplySideRevenueUSD = BIGDECIMAL_ZERO; + snapshot.dailyProtocolSideRevenueUSD = BIGDECIMAL_ZERO; + snapshot.dailyTotalRevenueUSD = BIGDECIMAL_ZERO; + snapshot.dailyDepositUSD = BIGDECIMAL_ZERO; + snapshot.dailyBorrowUSD = BIGDECIMAL_ZERO; + snapshot.dailyLiquidateUSD = BIGDECIMAL_ZERO; + snapshot.dailyWithdrawUSD = BIGDECIMAL_ZERO; + snapshot.dailyLiquidateUSD = BIGDECIMAL_ZERO; + snapshot.dailyWithdrawUSD = BIGDECIMAL_ZERO; + snapshot.dailyRepayUSD = BIGDECIMAL_ZERO; + snapshot.dailyTransferUSD = BIGDECIMAL_ZERO; + snapshot.dailyFlashloanUSD = BIGDECIMAL_ZERO; + } + snapshot.blockNumber = this.event.block.number; + snapshot.timestamp = this.event.block.timestamp; + snapshot.totalValueLockedUSD = this.protocol.totalValueLockedUSD; + snapshot.protocolControlledValueUSD = + this.protocol.protocolControlledValueUSD; + snapshot.mintedTokenSupplies = this.protocol.mintedTokenSupplies; + snapshot.cumulativeSupplySideRevenueUSD = + this.protocol.cumulativeSupplySideRevenueUSD; + snapshot.cumulativeProtocolSideRevenueUSD = + this.protocol.cumulativeProtocolSideRevenueUSD; + snapshot.cumulativeTotalRevenueUSD = + this.protocol.cumulativeTotalRevenueUSD; + snapshot.revenueDetail = this.protocol.revenueDetail + ? this.getSnapshotRevenueDetail(this.protocol.revenueDetail!, days) + : null; + snapshot.totalDepositBalanceUSD = this.protocol.totalDepositBalanceUSD; + snapshot.cumulativeDepositUSD = this.protocol.cumulativeDepositUSD; + snapshot.totalBorrowBalanceUSD = this.protocol.totalBorrowBalanceUSD; + snapshot.cumulativeBorrowUSD = this.protocol.cumulativeBorrowUSD; + snapshot.cumulativeLiquidateUSD = this.protocol.cumulativeLiquidateUSD; + + snapshot.save(); + this.financialSnapshot = snapshot; + } + + createOrUpdateUsageDailySnapshot(): void { + const days = this.event.block.timestamp.toI32() / SECONDS_PER_DAY; + const id = Bytes.fromI32(days); + let snapshot = UsageMetricsDailySnapshot.load(id); + + if (!snapshot) { + snapshot = new UsageMetricsDailySnapshot(id); + snapshot.days = days; + snapshot.protocol = this.protocol.id; + snapshot.dailyActiveUsers = INT_ZERO; + snapshot.dailyActiveDepositors = INT_ZERO; + snapshot.dailyActiveBorrowers = INT_ZERO; + snapshot.dailyActiveLiquidators = INT_ZERO; + snapshot.dailyActiveLiquidatees = INT_ZERO; + snapshot.dailyTransactionCount = INT_ZERO; + snapshot.dailyDepositCount = INT_ZERO; + snapshot.dailyWithdrawCount = INT_ZERO; + snapshot.dailyBorrowCount = INT_ZERO; + snapshot.dailyRepayCount = INT_ZERO; + snapshot.dailyLiquidateCount = INT_ZERO; + snapshot.dailyTransferCount = INT_ZERO; + snapshot.dailyFlashloanCount = INT_ZERO; + snapshot.dailyActivePositions = INT_ZERO; + } + snapshot.cumulativeUniqueUsers = this.protocol.cumulativeUniqueUsers; + snapshot.cumulativeUniqueDepositors = + this.protocol.cumulativeUniqueDepositors; + snapshot.cumulativeUniqueBorrowers = + this.protocol.cumulativeUniqueBorrowers; + snapshot.cumulativeUniqueLiquidators = + this.protocol.cumulativeUniqueLiquidators; + snapshot.cumulativeUniqueLiquidatees = + this.protocol.cumulativeUniqueLiquidatees; + snapshot.cumulativePositionCount = this.protocol.cumulativePositionCount; + snapshot.openPositionCount = this.protocol.openPositionCount; + snapshot.totalPoolCount = this.protocol.totalPoolCount; + snapshot.blockNumber = this.event.block.number; + snapshot.timestamp = this.event.block.timestamp; + + snapshot.save(); + this.usageDailySnapshot = snapshot; + } + + createOrUpdateUsageHourlySnapshot(): void { + const hours = this.event.block.timestamp.toI32() / SECONDS_PER_HOUR; + const id = Bytes.fromI32(hours); + let snapshot = UsageMetricsHourlySnapshot.load(id); + + if (!snapshot) { + snapshot = new UsageMetricsHourlySnapshot(id); + snapshot.hours = hours; + snapshot.protocol = this.protocol.id; + snapshot.hourlyActiveUsers = INT_ZERO; + snapshot.hourlyTransactionCount = INT_ZERO; + snapshot.hourlyDepositCount = INT_ZERO; + snapshot.hourlyWithdrawCount = INT_ZERO; + snapshot.hourlyBorrowCount = INT_ZERO; + snapshot.hourlyRepayCount = INT_ZERO; + snapshot.hourlyLiquidateCount = INT_ZERO; + } + snapshot.cumulativeUniqueUsers = this.protocol.cumulativeUniqueUsers; + snapshot.blockNumber = this.event.block.number; + snapshot.timestamp = this.event.block.timestamp; + + snapshot.save(); + this.usageHourlySnapshot = snapshot; + } + + //////////////////// + ///// Updaters ///// + //////////////////// + + updateUsageData(transactionType: string, account: Bytes): void { + this.usageDailySnapshot.dailyActiveUsers += activityCounter( + account, + transactionType, + false, + this.marketDailySnapshot.days + ); + this.marketDailySnapshot.dailyActiveUsers += activityCounter( + account, + transactionType, + false, + this.marketDailySnapshot.days, + this.market.id + ); + this.usageHourlySnapshot.hourlyActiveUsers += activityCounter( + account, + transactionType, + false, + this.marketHourlySnapshot.hours + ); + if (transactionType == TransactionType.DEPOSIT) { + this.usageDailySnapshot.dailyActiveDepositors += activityCounter( + account, + transactionType, + true, + this.marketDailySnapshot.days + ); + this.marketDailySnapshot.dailyActiveDepositors += activityCounter( + account, + transactionType, + true, + this.marketDailySnapshot.days, + this.market.id + ); + } + if (transactionType == TransactionType.BORROW) { + this.usageDailySnapshot.dailyActiveBorrowers += activityCounter( + account, + transactionType, + true, + this.marketDailySnapshot.days + ); + this.marketDailySnapshot.dailyActiveBorrowers += activityCounter( + account, + transactionType, + true, + this.marketDailySnapshot.days + ); + } + if (transactionType == TransactionType.LIQUIDATOR) { + this.usageDailySnapshot.dailyActiveLiquidators += activityCounter( + account, + transactionType, + true, + this.marketDailySnapshot.days + ); + this.marketDailySnapshot.dailyActiveLiquidators += activityCounter( + account, + transactionType, + true, + this.marketDailySnapshot.days, + this.market.id + ); + } + if (transactionType == TransactionType.LIQUIDATEE) { + this.usageDailySnapshot.dailyActiveLiquidatees += activityCounter( + account, + transactionType, + true, + this.marketDailySnapshot.days + ); + this.marketDailySnapshot.dailyActiveLiquidatees += activityCounter( + account, + transactionType, + true, + this.marketDailySnapshot.days, + this.market.id + ); + } + if (transactionType == TransactionType.TRANSFER) + this.marketDailySnapshot.dailyActiveTransferrers += activityCounter( + account, + transactionType, + true, + this.marketDailySnapshot.days, + this.market.id + ); + if (transactionType == TransactionType.FLASHLOAN) + this.marketDailySnapshot.dailyActiveFlashloaners += activityCounter( + account, + transactionType, + true, + this.marketDailySnapshot.days, + this.market.id + ); + + this.marketDailySnapshot.save(); + this.usageDailySnapshot.save(); + this.usageHourlySnapshot.save(); + } + + updateTransactionData( + transactionType: string, + amount: BigInt, + amountUSD: BigDecimal + ): void { + if (transactionType == TransactionType.DEPOSIT) { + this.marketDailySnapshot.dailyDepositUSD = + this.marketDailySnapshot.dailyDepositUSD.plus(amountUSD); + this.marketDailySnapshot.dailyNativeDeposit = + this.marketDailySnapshot.dailyNativeDeposit.plus(amount); + this.marketHourlySnapshot.hourlyDepositUSD = + this.marketHourlySnapshot.hourlyDepositUSD.plus(amountUSD); + this.financialSnapshot.dailyDepositUSD = + this.financialSnapshot.dailyDepositUSD.plus(amountUSD); + this.usageDailySnapshot.dailyDepositCount += INT_ONE; + this.usageHourlySnapshot.hourlyDepositCount += INT_ONE; + } else if (transactionType == TransactionType.WITHDRAW) { + this.marketDailySnapshot.dailyWithdrawUSD = + this.marketDailySnapshot.dailyWithdrawUSD.plus(amountUSD); + this.marketDailySnapshot.dailyNativeWithdraw = + this.marketDailySnapshot.dailyNativeWithdraw.plus(amount); + this.marketHourlySnapshot.hourlyWithdrawUSD = + this.marketHourlySnapshot.hourlyWithdrawUSD.plus(amountUSD); + this.financialSnapshot.dailyWithdrawUSD = + this.financialSnapshot.dailyWithdrawUSD.plus(amountUSD); + this.usageDailySnapshot.dailyWithdrawCount += INT_ONE; + this.usageHourlySnapshot.hourlyWithdrawCount += INT_ONE; + } else if (transactionType == TransactionType.BORROW) { + this.marketDailySnapshot.dailyBorrowUSD = + this.marketDailySnapshot.dailyBorrowUSD.plus(amountUSD); + this.marketDailySnapshot.dailyNativeBorrow = + this.marketDailySnapshot.dailyNativeBorrow.plus(amount); + this.marketHourlySnapshot.hourlyBorrowUSD = + this.marketHourlySnapshot.hourlyBorrowUSD.plus(amountUSD); + this.financialSnapshot.dailyBorrowUSD = + this.financialSnapshot.dailyBorrowUSD.plus(amountUSD); + this.usageDailySnapshot.dailyBorrowCount += INT_ONE; + this.usageHourlySnapshot.hourlyBorrowCount += INT_ONE; + } else if (transactionType == TransactionType.REPAY) { + this.marketDailySnapshot.dailyRepayUSD = + this.marketDailySnapshot.dailyRepayUSD.plus(amountUSD); + this.marketDailySnapshot.dailyNativeRepay = + this.marketDailySnapshot.dailyNativeRepay.plus(amount); + this.marketHourlySnapshot.hourlyRepayUSD = + this.marketHourlySnapshot.hourlyRepayUSD.plus(amountUSD); + this.financialSnapshot.dailyRepayUSD = + this.financialSnapshot.dailyRepayUSD.plus(amountUSD); + this.usageDailySnapshot.dailyRepayCount += INT_ONE; + this.usageHourlySnapshot.hourlyRepayCount += INT_ONE; + } else if (transactionType == TransactionType.LIQUIDATE) { + this.marketDailySnapshot.dailyLiquidateUSD = + this.marketDailySnapshot.dailyLiquidateUSD.plus(amountUSD); + this.marketDailySnapshot.dailyNativeLiquidate = + this.marketDailySnapshot.dailyNativeLiquidate.plus(amount); + this.marketHourlySnapshot.hourlyLiquidateUSD = + this.marketHourlySnapshot.hourlyLiquidateUSD.plus(amountUSD); + this.financialSnapshot.dailyLiquidateUSD = + this.financialSnapshot.dailyLiquidateUSD.plus(amountUSD); + this.usageDailySnapshot.dailyLiquidateCount += INT_ONE; + this.usageHourlySnapshot.hourlyLiquidateCount += INT_ONE; + } else if (transactionType == TransactionType.TRANSFER) { + this.marketDailySnapshot.dailyTransferUSD = + this.marketDailySnapshot.dailyTransferUSD.plus(amountUSD); + this.marketDailySnapshot.dailyNativeTransfer = + this.marketDailySnapshot.dailyNativeTransfer.plus(amount); + this.marketHourlySnapshot.hourlyTransferUSD = + this.marketHourlySnapshot.hourlyTransferUSD.plus(amountUSD); + this.financialSnapshot.dailyTransferUSD = + this.financialSnapshot.dailyTransferUSD.plus(amountUSD); + this.usageDailySnapshot.dailyTransferCount += INT_ONE; + } else if (transactionType == TransactionType.FLASHLOAN) { + this.marketDailySnapshot.dailyFlashloanUSD = + this.marketDailySnapshot.dailyFlashloanUSD.plus(amountUSD); + this.marketDailySnapshot.dailyNativeFlashloan = + this.marketDailySnapshot.dailyNativeFlashloan.plus(amount); + this.marketHourlySnapshot.hourlyFlashloanUSD = + this.marketHourlySnapshot.hourlyFlashloanUSD.plus(amountUSD); + this.financialSnapshot.dailyFlashloanUSD = + this.financialSnapshot.dailyFlashloanUSD.plus(amountUSD); + this.usageDailySnapshot.dailyFlashloanCount += INT_ONE; + } else { + log.error("[updateTransactionData] Invalid transaction type: {}", [ + transactionType, + ]); + return; + } + this.usageDailySnapshot.dailyTransactionCount += INT_ONE; + this.usageHourlySnapshot.hourlyTransactionCount += INT_ONE; + + this.usageDailySnapshot.save(); + this.usageHourlySnapshot.save(); + this.marketDailySnapshot.save(); + this.marketHourlySnapshot.save(); + this.financialSnapshot.save(); + } + + updateRevenue( + protocolRevenueDelta: BigDecimal, + supplyRevenueDelta: BigDecimal + ): void { + const totalRevenueDelta = protocolRevenueDelta.plus(supplyRevenueDelta); + + // update market hourly snapshot + this.marketHourlySnapshot.hourlyTotalRevenueUSD = + this.marketHourlySnapshot.hourlyTotalRevenueUSD.plus(totalRevenueDelta); + this.marketHourlySnapshot.hourlyProtocolSideRevenueUSD = + this.marketHourlySnapshot.hourlyProtocolSideRevenueUSD.plus( + protocolRevenueDelta + ); + this.marketHourlySnapshot.hourlySupplySideRevenueUSD = + this.marketHourlySnapshot.hourlySupplySideRevenueUSD.plus( + supplyRevenueDelta + ); + this.marketHourlySnapshot.save(); + + // update market daily snapshot + this.marketDailySnapshot.dailyTotalRevenueUSD = + this.marketDailySnapshot.dailyTotalRevenueUSD.plus(totalRevenueDelta); + this.marketDailySnapshot.dailyProtocolSideRevenueUSD = + this.marketDailySnapshot.dailyProtocolSideRevenueUSD.plus( + protocolRevenueDelta + ); + this.marketDailySnapshot.dailySupplySideRevenueUSD = + this.marketDailySnapshot.dailySupplySideRevenueUSD.plus( + supplyRevenueDelta + ); + this.marketDailySnapshot.save(); + + // update financials snapshot + this.financialSnapshot.dailyTotalRevenueUSD = + this.financialSnapshot.dailyTotalRevenueUSD.plus(totalRevenueDelta); + this.financialSnapshot.dailyProtocolSideRevenueUSD = + this.financialSnapshot.dailyProtocolSideRevenueUSD.plus( + protocolRevenueDelta + ); + this.financialSnapshot.dailySupplySideRevenueUSD = + this.financialSnapshot.dailySupplySideRevenueUSD.plus(supplyRevenueDelta); + this.financialSnapshot.save(); + } + + addDailyActivePosition(side: string): void { + if (side == PositionSide.BORROWER) { + this.marketDailySnapshot.dailyActiveBorrowingPositionCount += INT_ONE; + } + if (side == PositionSide.COLLATERAL) { + this.marketDailySnapshot.dailyActiveLendingPositionCount += INT_ONE; + } + this.marketDailySnapshot.save(); + } + + /////////////////// + ///// Helpers ///// + /////////////////// + + private getSnapshotRates(rates: string[], timeSuffix: string): string[] { + const snapshotRates: string[] = []; + for (let i = 0; i < rates.length; i++) { + const rate = InterestRate.load(rates[i]); + if (!rate) { + log.warning("[getSnapshotRates] rate {} not found, should not happen", [ + rates[i], + ]); + continue; + } + + // create new snapshot rate + const snapshotRateId = rates[i].concat("-").concat(timeSuffix); + const snapshotRate = new InterestRate(snapshotRateId); + snapshotRate.rate = rate.rate; + if (rate.maturityBlock) snapshotRate.maturityBlock = rate.maturityBlock; + snapshotRate.side = rate.side; + snapshotRate.type = rate.type; + if (rate.tranche) snapshotRate.tranche = rate.tranche; + snapshotRate.save(); + snapshotRates.push(snapshotRateId); + } + return snapshotRates; + } + + private getSnapshotRevenueDetail( + currID: Bytes, + timeSuffix: i32 + ): Bytes | null { + const currDetails = RevenueDetail.load(currID); + if (!currDetails) { + log.error( + "[getRevenueDetailSnapshot] Cannot find revenue details id: {}", + [currID.toHexString()] + ); + return null; + } + + const newDetails = new RevenueDetail( + currDetails.id.concat(Bytes.fromI32(timeSuffix)) + ); + newDetails.sources = currDetails.sources; + newDetails.amountsUSD = currDetails.amountsUSD; + newDetails.save(); + + return newDetails.id; + } +} diff --git a/subgraphs/ebtc/src/sdk/token.ts b/subgraphs/ebtc/src/sdk/token.ts new file mode 100644 index 0000000000..ae2df52ada --- /dev/null +++ b/subgraphs/ebtc/src/sdk/token.ts @@ -0,0 +1,274 @@ +import { ERC20 } from "../../../../generated/Configurator/ERC20"; +import { ERC20SymbolBytes } from "../../../../generated/Configurator/ERC20SymbolBytes"; +import { ERC20NameBytes } from "../../../../generated/Configurator/ERC20NameBytes"; +import { Address, BigDecimal, Bytes, ethereum } from "@graphprotocol/graph-ts"; +import { RewardToken, Token } from "../../../../generated/schema"; +import { + BIGDECIMAL_ZERO, + INT_EIGHTTEEN, + INT_NINE, + INT_SIX, + INT_SIXTEEN, +} from "./constants"; + +/** + * This file contains the TokenClass, which acts as + * a wrapper for the Token entity making it easier to + * use in mappings and get info about the token. + * + * Schema Version: 3.0.1 + * SDK Version: 1.0.2 + * Author(s): + * - @dmelotik + */ + +export class TokenManager { + private INVALID_TOKEN_DECIMALS: i32 = 0; + private UNKNOWN_TOKEN_VALUE: string = "unknown"; + + private token!: Token; + private event!: ethereum.Event; + + constructor( + tokenAddress: Bytes, + event: ethereum.Event, + tokenType: string | null = null + ) { + let _token = Token.load(tokenAddress); + if (!_token) { + _token = new Token(tokenAddress); + _token.name = this.fetchTokenName(Address.fromBytes(tokenAddress)); + _token.symbol = this.fetchTokenSymbol(Address.fromBytes(tokenAddress)); + _token.decimals = this.fetchTokenDecimals( + Address.fromBytes(tokenAddress) + ); + if (tokenType) { + _token.type = tokenType; + } + _token.save(); + } + + this.token = _token; + this.event = event; + } + + getToken(): Token { + return this.token; + } + + getDecimals(): i32 { + return this.token.decimals; + } + + updatePrice(newPriceUSD: BigDecimal): void { + this.token.lastPriceBlockNumber = this.event.block.number; + this.token.lastPriceUSD = newPriceUSD; + this.token.save(); + } + + getPriceUSD(): BigDecimal { + if (this.token.lastPriceUSD) { + return this.token.lastPriceUSD!; + } + return BIGDECIMAL_ZERO; + } + + //////////////////// + ///// Creators ///// + //////////////////// + + getOrCreateRewardToken(rewardTokenType: string): RewardToken { + const rewardTokenID = rewardTokenType + .concat("-") + .concat(this.token.id.toHexString()); + let rewardToken = RewardToken.load(rewardTokenID); + if (!rewardToken) { + rewardToken = new RewardToken(rewardTokenID); + rewardToken.token = this.token.id; + rewardToken.type = rewardTokenType; + rewardToken.save(); + } + return rewardToken; + } + + private fetchTokenSymbol(tokenAddress: Address): string { + const contract = ERC20.bind(tokenAddress); + const contractSymbolBytes = ERC20SymbolBytes.bind(tokenAddress); + + // try types string and bytes32 for symbol + let symbolValue = this.UNKNOWN_TOKEN_VALUE; + const symbolResult = contract.try_symbol(); + if (!symbolResult.reverted) { + return symbolResult.value; + } + + // non-standard ERC20 implementation + const symbolResultBytes = contractSymbolBytes.try_symbol(); + if (!symbolResultBytes.reverted) { + // for broken pairs that have no symbol function exposed + if (!this.isNullEthValue(symbolResultBytes.value.toHexString())) { + symbolValue = symbolResultBytes.value.toString(); + } else { + // try with the static definition + const staticTokenDefinition = + StaticTokenDefinition.fromAddress(tokenAddress); + if (staticTokenDefinition != null) { + symbolValue = staticTokenDefinition.symbol; + } + } + } + + return symbolValue; + } + + private fetchTokenName(tokenAddress: Address): string { + const contract = ERC20.bind(tokenAddress); + const contractNameBytes = ERC20NameBytes.bind(tokenAddress); + + // try types string and bytes32 for name + let nameValue = this.UNKNOWN_TOKEN_VALUE; + const nameResult = contract.try_name(); + if (!nameResult.reverted) { + return nameResult.value; + } + + // non-standard ERC20 implementation + const nameResultBytes = contractNameBytes.try_name(); + if (!nameResultBytes.reverted) { + // for broken exchanges that have no name function exposed + if (!this.isNullEthValue(nameResultBytes.value.toHexString())) { + nameValue = nameResultBytes.value.toString(); + } else { + // try with the static definition + const staticTokenDefinition = + StaticTokenDefinition.fromAddress(tokenAddress); + if (staticTokenDefinition != null) { + nameValue = staticTokenDefinition.name; + } + } + } + + return nameValue; + } + + private fetchTokenDecimals(tokenAddress: Address): i32 { + const contract = ERC20.bind(tokenAddress); + + // try types uint8 for decimals + const decimalResult = contract.try_decimals(); + if (!decimalResult.reverted) { + const decimalValue = decimalResult.value; + return decimalValue; + } + + // try with the static definition + const staticTokenDefinition = + StaticTokenDefinition.fromAddress(tokenAddress); + if (staticTokenDefinition != null) { + return staticTokenDefinition.decimals as i32; + } else { + return this.INVALID_TOKEN_DECIMALS as i32; + } + } + + private isNullEthValue(value: string): boolean { + return ( + value == + "0x0000000000000000000000000000000000000000000000000000000000000001" + ); + } +} + +// Initialize a Token Definition with the attributes +export class StaticTokenDefinition { + address: Address; + symbol: string; + name: string; + decimals: i32; + + // Initialize a Token Definition with its attributes + constructor(address: Address, symbol: string, name: string, decimals: i32) { + this.address = address; + this.symbol = symbol; + this.name = name; + this.decimals = decimals; + } + + // Get all tokens with a static defintion + static getStaticDefinitions(): Array { + const staticDefinitions = new Array(INT_SIX); + + // Add DGD + const tokenDGD = new StaticTokenDefinition( + Address.fromString("0xe0b7927c4af23765cb51314a0e0521a9645f0e2a"), + "DGD", + "DGD", + INT_NINE as i32 + ); + staticDefinitions.push(tokenDGD); + + // Add AAVE + const tokenAAVE = new StaticTokenDefinition( + Address.fromString("0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9"), + "AAVE", + "Aave Token", + INT_EIGHTTEEN as i32 + ); + staticDefinitions.push(tokenAAVE); + + // Add LIF + const tokenLIF = new StaticTokenDefinition( + Address.fromString("0xeb9951021698b42e4399f9cbb6267aa35f82d59d"), + "LIF", + "Lif", + INT_EIGHTTEEN as i32 + ); + staticDefinitions.push(tokenLIF); + + // Add SVD + const tokenSVD = new StaticTokenDefinition( + Address.fromString("0xbdeb4b83251fb146687fa19d1c660f99411eefe3"), + "SVD", + "savedroid", + INT_EIGHTTEEN as i32 + ); + staticDefinitions.push(tokenSVD); + + // Add TheDAO + const tokenTheDAO = new StaticTokenDefinition( + Address.fromString("0xbb9bc244d798123fde783fcc1c72d3bb8c189413"), + "TheDAO", + "TheDAO", + INT_SIXTEEN as i32 + ); + staticDefinitions.push(tokenTheDAO); + + // Add HPB + const tokenHPB = new StaticTokenDefinition( + Address.fromString("0x38c6a68304cdefb9bec48bbfaaba5c5b47818bb2"), + "HPB", + "HPBCoin", + INT_EIGHTTEEN as i32 + ); + staticDefinitions.push(tokenHPB); + + return staticDefinitions; + } + + // Helper for hardcoded tokens + static fromAddress(tokenAddress: Address): StaticTokenDefinition | null { + const staticDefinitions = this.getStaticDefinitions(); + const tokenAddressHex = tokenAddress.toHexString(); + + // Search the definition using the address + for (let i = 0; i < staticDefinitions.length; i++) { + const staticDefinition = staticDefinitions[i]; + if (staticDefinition.address.toHexString() == tokenAddressHex) { + return staticDefinition; + } + } + + // If not found, return null + return null; + } +} diff --git a/subgraphs/ebtc/src/sdk/util/arrays.ts b/subgraphs/ebtc/src/sdk/util/arrays.ts new file mode 100644 index 0000000000..566f95545d --- /dev/null +++ b/subgraphs/ebtc/src/sdk/util/arrays.ts @@ -0,0 +1,95 @@ +import { Bytes } from "@graphprotocol/graph-ts"; + +// A function which given 3 arrays of arbitrary types of the same length, +// where the first one holds the reference order, the second one holds the same elements +// as the first but in different order, and the third any arbitrary elements. It will return +// the third array after sorting it according to the order of the first one. +// For example: +// sortArrayByReference(['a', 'c', 'b'], ['a', 'b', 'c'], [1, 2, 3]) => [1, 3, 2] +export function sortArrayByReference( + reference: T[], + array: T[], + toSort: K[] +): K[] { + const sorted: K[] = new Array(); + for (let i = 0; i < reference.length; i++) { + const index = array.indexOf(reference[i]); + sorted.push(toSort[index]); + } + return sorted; +} + +// sortBytesArray will sort an array of Bytes in ascending order +// by comparing their hex string representation. +export function sortBytesArray(array: Bytes[]): Bytes[] { + const toSort = array.map((item) => item.toHexString()); + toSort.sort(); + return toSort.map((item) => Bytes.fromHexString(item)); +} + +export function updateArrayAtIndex(x: T[], item: T, index: i32): T[] { + if (x.length == 0) { + return [item]; + } + if (index == -1 || index > x.length) { + index = x.length; + } + const retval = new Array(); + let i = 0; + while (i < index) { + retval.push(x[i]); + i += 1; + } + retval.push(item); + i += 1; + while (i < x.length) { + retval.push(x[i]); + i += 1; + } + return retval; +} + +export function addToArrayAtIndex(x: T[], item: T, index: i32 = -1): T[] { + if (x.length == 0) { + return [item]; + } + if (index == -1 || index > x.length) { + index = x.length; + } + const retval = new Array(); + let i = 0; + while (i < index) { + retval.push(x[i]); + i += 1; + } + retval.push(item); + while (i < x.length) { + retval.push(x[i]); + i += 1; + } + return retval; +} + +export function addArrays(a: T[], b: T[]): T[] { + const retval = new Array(); + if (a.length == b.length) { + let i = 0; + while (i < a.length) { + retval.push(a[i].plus(b[i])); + i += 1; + } + } + return retval; +} + +export function subtractArrays(a: T[], b: T[]): T[] { + const retval = new Array(); + if (a.length == b.length) { + let i = 0; + while (i < a.length) { + retval.push(a[i].minus(b[i])); + i += 1; + } + } + return retval; +} diff --git a/subgraphs/ebtc/src/sdk/util/constants.ts b/subgraphs/ebtc/src/sdk/util/constants.ts new file mode 100644 index 0000000000..185e7bf83d --- /dev/null +++ b/subgraphs/ebtc/src/sdk/util/constants.ts @@ -0,0 +1,228 @@ +import { BigDecimal, BigInt } from "@graphprotocol/graph-ts"; + +//////////////////////// +///// Schema Enums ///// +//////////////////////// + +// The network names corresponding to the Network enum in the schema. +// They also correspond to the ones in `dataSource.network()` after converting to lower case. +// See below for a complete list: +// https://thegraph.com/docs/en/hosted-service/what-is-hosted-service/#supported-networks-on-the-hosted-service +export namespace Network { + export const ARBITRUM_ONE = "ARBITRUM_ONE"; + export const AVALANCHE = "AVALANCHE"; + export const AURORA = "AURORA"; + export const BSC = "BSC"; // aka BNB Chain + export const CELO = "CELO"; + export const MAINNET = "MAINNET"; // Ethereum mainnet + export const FANTOM = "FANTOM"; + export const FUSE = "FUSE"; + export const MOONBEAM = "MOONBEAM"; + export const MOONRIVER = "MOONRIVER"; + export const NEAR_MAINNET = "NEAR_MAINNET"; + export const OPTIMISM = "OPTIMISM"; + export const MATIC = "MATIC"; // aka Polygon + export const XDAI = "XDAI"; // aka Gnosis Chain + + // other networks + export const UBIQ = "UBIQ"; + export const SONGBIRD = "SONGBIRD"; + export const ELASTOS = "ELASTOS"; + export const KARDIACHAIN = "KARDIACHAIN"; + export const CRONOS = "CRONOS"; + export const RSK = "RSK"; + export const TELOS = "TELOS"; + export const XDC = "XDC"; + export const ZYX = "ZYX"; + export const CSC = "CSC"; + export const SYSCOIN = "SYSCOIN"; + export const GOCHAIN = "GOCHAIN"; + export const ETHEREUMCLASSIC = "ETHEREUMCLASSIC"; + export const OKEXCHAIN = "OKEXCHAIN"; + export const HOO = "HOO"; + export const METER = "METER"; + export const NOVA_NETWORK = "NOVA_NETWORK"; + export const TOMOCHAIN = "TOMOCHAIN"; + export const VELAS = "VELAS"; + export const THUNDERCORE = "THUNDERCORE"; + export const HECO = "HECO"; + export const XDAIARB = "XDAIARB"; + export const ENERGYWEB = "ENERGYWEB"; + export const HPB = "HPB"; + export const BOBA = "BOBA"; + export const KUCOIN = "KUCOIN"; + export const SHIDEN = "SHIDEN"; + export const THETA = "THETA"; + export const SX = "SX"; + export const CANDLE = "CANDLE"; + export const ASTAR = "ASTAR"; + export const CALLISTO = "CALLISTO"; + export const WANCHAIN = "WANCHAIN"; + export const METIS = "METIS"; + export const ULTRON = "ULTRON"; + export const STEP = "STEP"; + export const DOGECHAIN = "DOGECHAIN"; + export const RONIN = "RONIN"; + export const KAVA = "KAVA"; + export const IOTEX = "IOTEX"; + export const XLC = "XLC"; + export const NAHMII = "NAHMII"; + export const TOMBCHAIN = "TOMBCHAIN"; + export const CANTO = "CANTO"; + export const KLAYTN = "KLAYTN"; + export const EVMOS = "EVMOS"; + export const SMARTBCH = "SMARTBCH"; + export const BITGERT = "BITGERT"; + export const FUSION = "FUSION"; + export const OHO = "OHO"; + export const ARB_NOVA = "ARB_NOVA"; + export const OASIS = "OASIS"; + export const REI = "REI"; + export const REICHAIN = "REICHAIN"; + export const GODWOKEN = "GODWOKEN"; + export const POLIS = "POLIS"; + export const KEKCHAIN = "KEKCHAIN"; + export const VISION = "VISION"; + export const HARMONY = "HARMONY"; + export const PALM = "PALM"; + export const CURIO = "CURIO"; + + export const UNKNOWN_NETWORK = "UNKNOWN_NETWORK"; +} +export type Network = string; + +export namespace ProtocolType { + export const EXCHANGE = "EXCHANGE"; + export const LENDING = "LENDING"; + export const YIELD = "YIELD"; + export const BRIDGE = "BRIDGE"; + export const OPTION = "OPTION"; + export const PERPETUAL = "PERPETUAL"; + export const GENERIC = "GENERIC"; +} + +export namespace VaultFeeType { + export const MANAGEMENT_FEE = "MANAGEMENT_FEE"; + export const PERFORMANCE_FEE = "PERFORMANCE_FEE"; + export const DEPOSIT_FEE = "DEPOSIT_FEE"; + export const WITHDRAWAL_FEE = "WITHDRAWAL_FEE"; +} + +export namespace LiquidityPoolFeeType { + export const FIXED_TRADING_FEE = "FIXED_TRADING_FEE"; + export const TIERED_TRADING_FEE = "TIERED_TRADING_FEE"; + export const DYNAMIC_TRADING_FEE = "DYNAMIC_TRADING_FEE"; + export const FIXED_LP_FEE = "FIXED_LP_FEE"; + export const DYNAMIC_LP_FEE = "DYNAMIC_LP_FEE"; + export const FIXED_PROTOCOL_FEE = "FIXED_PROTOCOL_FEE"; + export const DYNAMIC_PROTOCOL_FEE = "DYNAMIC_PROTOCOL_FEE"; +} +export type LiquidityPoolFeeType = string; + +export namespace RewardTokenType { + export const DEPOSIT = "DEPOSIT"; + export const BORROW = "BORROW"; + export const STAKE = "STAKE"; +} +export type RewardTokenType = string; + +export namespace ActivityInterval { + export const HOURLY = "HOURLY"; + export const DAILY = "DAILY"; +} + +export namespace LendingType { + export const CDP = "CDP"; + export const POOLED = "POOLED"; +} + +export namespace RiskType { + export const GLOBAL = "GLOBAL"; + export const ISOLATED = "ISOLATED"; +} + +export namespace InterestRateType { + export const STABLE = "STABLE"; + export const VARIABLE = "VARIABLE"; + export const FIXED_TERM = "FIXED_TERM"; +} + +export namespace InterestRateSide { + export const LENDER = "LENDER"; + export const BORROWER = "BORROWER"; +} + +export namespace UsageType { + export const DEPOSIT = "DEPOSIT"; + export const WITHDRAW = "WITHDRAW"; + export const SWAP = "SWAP"; +} + +export namespace PositionSide { + export const LONG = "LONG"; + export const SHORT = "SHORT"; +} +export type PositionSide = string; + +////////////////////////////// +///// Ethereum Addresses ///// +////////////////////////////// + +export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; +export const ETH_ADDRESS = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; + +//////////////////////// +///// Type Helpers ///// +//////////////////////// + +export const DEFAULT_DECIMALS = 18; + +export const USDC_DECIMALS = 6; +export const USDC_DENOMINATOR = BigDecimal.fromString("1000000"); + +export const BIGINT_ZERO = BigInt.fromI32(0); +export const BIGINT_ONE = BigInt.fromI32(1); +export const BIGINT_TWO = BigInt.fromI32(2); +export const BIGINT_TEN = BigInt.fromI32(10); +export const BIGINT_HUNDRED = BigInt.fromI32(100); +export const BIGINT_THOUSAND = BigInt.fromI32(1000); +export const BIGINT_TEN_TO_EIGHTEENTH = BigInt.fromString("10").pow(18); +export const BIGINT_MINUS_ONE = BigInt.fromI32(-1); +export const BIGINT_MAX = BigInt.fromString( + "115792089237316195423570985008687907853269984665640564039457584007913129639935" +); + +export const INT_NEGATIVE_ONE = -1 as i32; +export const INT_ZERO = 0 as i32; +export const INT_ONE = 1 as i32; +export const INT_TWO = 2 as i32; +export const INT_FOUR = 4 as i32; + +export const BIGDECIMAL_ZERO = new BigDecimal(BIGINT_ZERO); +export const BIGDECIMAL_ONE = new BigDecimal(BIGINT_ONE); +export const BIGDECIMAL_TWO = new BigDecimal(BIGINT_TWO); +export const BIGDECIMAL_HUNDRED = new BigDecimal(BIGINT_HUNDRED); +export const BIGDECIMAL_MINUS_ONE = new BigDecimal(BIGINT_MINUS_ONE); + +export const MAX_UINT = BigInt.fromI32(2).times(BigInt.fromI32(255)); + +///////////////////// +///// Date/Time ///// +///////////////////// + +export const SECONDS_PER_DAY = 60 * 60 * 24; // 86400 +export const SECONDS_PER_HOUR = 60 * 60; // 3600 +export const SECONDS_PER_DAY_BI = BigInt.fromI32(SECONDS_PER_DAY); +export const SECONDS_PER_HOUR_BI = BigInt.fromI32(SECONDS_PER_HOUR); +export const MS_PER_DAY = new BigDecimal(BigInt.fromI32(24 * 60 * 60 * 1000)); +export const DAYS_PER_YEAR = new BigDecimal(BigInt.fromI32(365)); +export const MS_PER_YEAR = DAYS_PER_YEAR.times( + new BigDecimal(BigInt.fromI32(24 * 60 * 60 * 1000)) +); + +//////////////// +///// Misc ///// +//////////////// + +export const ETH_SYMBOL = "ETH"; +export const ETH_NAME = "Ether"; diff --git a/subgraphs/ebtc/src/sdk/util/events.ts b/subgraphs/ebtc/src/sdk/util/events.ts new file mode 100644 index 0000000000..5c6ee1e4d1 --- /dev/null +++ b/subgraphs/ebtc/src/sdk/util/events.ts @@ -0,0 +1,70 @@ +import { BigInt, Address, Bytes, ethereum } from "@graphprotocol/graph-ts"; +import { + BIGINT_ZERO, + SECONDS_PER_DAY, + SECONDS_PER_HOUR, + ZERO_ADDRESS, +} from "./constants"; + +export class CustomEventType { + block: ethereum.Block; + transaction: ethereum.Transaction; + logIndex: BigInt; + event: ethereum.Event | null; + + constructor() { + this.block = new ethereum.Block( + Bytes.empty(), + Bytes.empty(), + Bytes.empty(), + Address.fromString(ZERO_ADDRESS), + Bytes.empty(), + Bytes.empty(), + Bytes.empty(), + BIGINT_ZERO, + BIGINT_ZERO, + BIGINT_ZERO, + BIGINT_ZERO, + BIGINT_ZERO, + BIGINT_ZERO, + null, + null + ); + this.transaction = new ethereum.Transaction( + Bytes.empty(), + BIGINT_ZERO, + Address.fromString(ZERO_ADDRESS), + null, + BIGINT_ZERO, + BIGINT_ZERO, + BIGINT_ZERO, + Bytes.empty(), + BIGINT_ZERO + ); + this.logIndex = BIGINT_ZERO; + this.event = null; + } + + static initialize( + block: ethereum.Block, + transaction: ethereum.Transaction, + logIndex: BigInt, + event: ethereum.Event | null = null + ): CustomEventType { + const customEvent = new CustomEventType(); + customEvent.block = block; + customEvent.transaction = transaction; + customEvent.logIndex = logIndex; + customEvent.event = event; + + return customEvent; + } +} + +export function getUnixDays(block: ethereum.Block): i32 { + return block.timestamp.toI32() / SECONDS_PER_DAY; +} + +export function getUnixHours(block: ethereum.Block): i32 { + return block.timestamp.toI32() / SECONDS_PER_HOUR; +} diff --git a/subgraphs/ebtc/src/sdk/util/numbers.ts b/subgraphs/ebtc/src/sdk/util/numbers.ts new file mode 100644 index 0000000000..725140a922 --- /dev/null +++ b/subgraphs/ebtc/src/sdk/util/numbers.ts @@ -0,0 +1,61 @@ +import { BigDecimal, BigInt } from "@graphprotocol/graph-ts"; +import { + BIGDECIMAL_ZERO, + BIGINT_TEN, + DEFAULT_DECIMALS, + INT_TWO, +} from "./constants"; + +export function bigIntToBigDecimal( + quantity: BigInt, + decimals: i32 = DEFAULT_DECIMALS +): BigDecimal { + return quantity.divDecimal(BIGINT_TEN.pow(decimals as u8).toBigDecimal()); +} + +export function bigDecimalToBigInt(input: BigDecimal): BigInt { + const str = input.truncate(0).toString(); + return BigInt.fromString(str); +} + +// returns 10^exp +export function exponentToBigDecimal(exp: i32 = DEFAULT_DECIMALS): BigDecimal { + let bd = BigDecimal.fromString("1"); + const ten = BigDecimal.fromString("10"); + for (let i = 0; i < exp; i++) { + bd = bd.times(ten); + } + return bd; +} + +export function calculateAverage(prices: BigDecimal[]): BigDecimal { + let sum = BigDecimal.fromString("0"); + for (let i = 0; i < prices.length; i++) { + sum = sum.plus(prices[i]); + } + + return sum.div( + BigDecimal.fromString(BigInt.fromI32(prices.length).toString()) + ); +} + +export function calculateMedian(prices: BigDecimal[]): BigDecimal { + const sorted = prices.sort((a, b) => { + return a.equals(b) ? 0 : a.gt(b) ? 1 : -1; + }); + + const mid = Math.ceil(sorted.length / 2) as i32; + if (sorted.length % 2 == 0) { + return sorted[mid] + .plus(sorted[mid - 1]) + .div(BigDecimal.fromString(INT_TWO.toString())); + } + + return sorted[mid - 1]; +} + +export function safeDivide(a: BigDecimal, b: BigDecimal): BigDecimal { + if (b == BIGDECIMAL_ZERO) return BIGDECIMAL_ZERO; + + return a.div(b); +} diff --git a/subgraphs/ebtc/src/sdk/util/rewards.ts b/subgraphs/ebtc/src/sdk/util/rewards.ts new file mode 100644 index 0000000000..ec9b7c6029 --- /dev/null +++ b/subgraphs/ebtc/src/sdk/util/rewards.ts @@ -0,0 +1,292 @@ +///////////////////// +// VERSION 1.0.3 //// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// The purpose of this program is to dynamically estimate the blocks generated for the 24 HR period following the most recent update. // +// It does so by calculating the moving average block rate for an arbitrary length of time preceding the current block. // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +import { log, BigDecimal, BigInt, dataSource } from "@graphprotocol/graph-ts"; +import { _CircularBuffer } from "../../../generated/schema"; +import { + Network, + BIGDECIMAL_ZERO, + INT_FOUR, + INT_NEGATIVE_ONE, + INT_ONE, + INT_TWO, + INT_ZERO, +} from "./constants"; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// WINDOW_SIZE_SECONDS, TIMESTAMP_STORAGE_INTERVALS, and BUFFER_SIZE can be modified. These are just recommended values - 'somewhat' arbitrary. // +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// The storage interval tells you to only store blocks where the timestamps are separated by at least this amount. +// Increasing this value will mean less blocks stored and less frequently computes blocksSpeed. +export const TIMESTAMP_STORAGE_INTERVAL = 600; + +// The window size determines the range of blocks that you track from the current block minus the window size. +// Window of block time used to calculate the moving average. +// Increasing means less deviation but also less sensitivity to changing block speeds. +export const WINDOW_SIZE_SECONDS = 86400; + +// BUFFER_SIZE determined the size of the array +// Makes the buffer the maximum amount of blocks that can be stored given the block rate and storage interval +// Recommended value is (RATE_IN_SECODNDS / TIMESTAMP_STORAGE_INTERVAL) * 2 - > Round up to nearest even integer +export const BUFFER_SIZE = 288; + +// Add this entity to the schema. +// type _CircularBuffer @entity { +// " 'CIRCULAR_BUFFER' " +// id: ID! + +// " Array of sorted block numbers sorted continuously " +// blocks: [Int!]! + +// " The index in the blocks array which will be used with the newest block to calculate block speed (Usally set to about a day before newest block) " +// windowStartIndex: Int! + +// " The next index in the blocks array that will be replaced with the newest block " +// nextIndex: Int! + +// " This determines the size of the blocks array. Should be set to contain at least a days worth of blocks according to a 1 day window for measuring speed" +// bufferSize: Int! + +// " The current calculated number of blocks per day based on calculated block speed " +// blocksPerDay: BigDecimal! + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +export const CIRCULAR_BUFFER = "CIRCULAR_BUFFER"; + +// Describes whether the interval for which rewards are emitted is done by block or timestamp +export namespace RewardIntervalType { + export const BLOCK = "BLOCK"; + export const TIMESTAMP = "TIMESTAMP"; +} + +// Forecast period. This gives you the time period that you want to estimate count of blocks per interval, based on moving average block speed. +// 86400 = 1 Day +export const RATE_IN_SECONDS = 86400; +export const RATE_IN_SECONDS_BD = BigDecimal.fromString( + RATE_IN_SECONDS.toString() +); + +// Estimated seconds per block of the protocol +export const STARTING_BLOCKS_PER_DAY = RATE_IN_SECONDS_BD.div( + getStartingBlockRate() +); + +export const WINDOW_SIZE_SECONDS_BD = BigDecimal.fromString( + WINDOW_SIZE_SECONDS.toString() +); + +// Call this function in event handlers frequently enough so that it calls on blocks frequently enough +/** + * @param {BigInt} currentTimestamp - Timestamp for current event + * @param {BigInt} currentBlockNumber - Block nunmber of current event + * @param {BigInt} rewardRate - Rate of reward emissions per reward interval + * @param {BigInt} rewardType - Describes whether rewards are given per block or timestamp + * @returns {BigDecimal} - Returns estimated blocks for specified rate + */ +export function getRewardsPerDay( + currentTimestamp: BigInt, + currentBlockNumber: BigInt, + rewardRate: BigDecimal, + rewardType: string +): BigDecimal { + const circularBuffer = getOrCreateCircularBuffer(); + + // Create entity for the current block + const currentTimestampI32 = currentTimestamp.toI32(); + const currentBlockNumberI32 = currentBlockNumber.toI32(); + + const blocks = circularBuffer.blocks; + + // Interval between index and the index of the start of the window block + const windowWidth = abs( + circularBuffer.windowStartIndex - circularBuffer.nextIndex + ); + if (windowWidth == INT_ZERO) { + if (circularBuffer.nextIndex >= circularBuffer.bufferSize) { + blocks[INT_ZERO] = currentTimestampI32; + blocks[INT_ONE] = currentBlockNumberI32; + circularBuffer.nextIndex = INT_TWO; + } else { + blocks[circularBuffer.nextIndex] = currentTimestampI32; + blocks[circularBuffer.nextIndex + INT_ONE] = currentBlockNumberI32; + circularBuffer.nextIndex += INT_TWO; + } + + circularBuffer.save(); + + // return because there is only 1 reference point. + if (rewardType == RewardIntervalType.TIMESTAMP) { + return rewardRate.times(RATE_IN_SECONDS_BD); + } else { + return circularBuffer.blocksPerDay.times(rewardRate); + } + } + + // Add current timestamp and block numnber to array if new block is at least X blocks later than previously stored. + // Used to save memory and efficiency on array resizing. + let recentSavedTimestamp: i32; + if (circularBuffer.nextIndex == INT_ZERO) { + recentSavedTimestamp = blocks[circularBuffer.bufferSize - INT_TWO]; + } else { + recentSavedTimestamp = blocks[circularBuffer.nextIndex - INT_TWO]; + } + + if ( + currentTimestampI32 - recentSavedTimestamp <= + TIMESTAMP_STORAGE_INTERVAL + ) { + if (rewardType == RewardIntervalType.TIMESTAMP) { + return rewardRate.times(RATE_IN_SECONDS_BD); + } else { + return circularBuffer.blocksPerDay.times(rewardRate); + } + } + + blocks[circularBuffer.nextIndex] = currentTimestampI32; + blocks[circularBuffer.nextIndex + INT_ONE] = currentBlockNumberI32; + if (circularBuffer.nextIndex >= BUFFER_SIZE - INT_TWO) { + circularBuffer.nextIndex = INT_ZERO; + } else { + circularBuffer.nextIndex += INT_TWO; + } + // The timestamp at the start of the window (default 24 hours in seconds). + const startTimestamp = currentTimestampI32 - WINDOW_SIZE_SECONDS; + + // Make sure to still have 2 blocks to calculate rate (This shouldn't happen past the beginning). + while (true) { + if (circularBuffer.nextIndex > circularBuffer.windowStartIndex) { + if ( + circularBuffer.nextIndex - circularBuffer.windowStartIndex <= + INT_FOUR + ) { + break; + } + } else { + if ( + BUFFER_SIZE - + circularBuffer.windowStartIndex + + circularBuffer.nextIndex <= + INT_FOUR + ) { + break; + } + } + const windowIndexBlockTimestamp = blocks[circularBuffer.windowStartIndex]; + + // Shift the start of the window if the current timestamp moves out of desired rate window + if (windowIndexBlockTimestamp < startTimestamp) { + circularBuffer.windowStartIndex = + circularBuffer.windowStartIndex + INT_TWO; + if (circularBuffer.windowStartIndex >= circularBuffer.bufferSize) { + circularBuffer.windowStartIndex = INT_ZERO; + } + } else { + break; + } + } + + // Wideness of the window in seconds. + const windowSecondsCount = BigDecimal.fromString( + (currentTimestampI32 - blocks[circularBuffer.windowStartIndex]).toString() + ); + + // Wideness of the window in blocks. + const windowBlocksCount = BigDecimal.fromString( + ( + currentBlockNumberI32 - blocks[circularBuffer.windowStartIndex + INT_ONE] + ).toString() + ); + + // Estimate block speed for the window in seconds. + const unnormalizedBlockSpeed = + WINDOW_SIZE_SECONDS_BD.div(windowSecondsCount).times(windowBlocksCount); + + // block speed converted to specified rate. + const normalizedBlockSpeed = RATE_IN_SECONDS_BD.div( + WINDOW_SIZE_SECONDS_BD + ).times(unnormalizedBlockSpeed); + + // Update BlockTracker with new values. + circularBuffer.blocksPerDay = normalizedBlockSpeed; + circularBuffer.blocks = blocks; + + circularBuffer.save(); + + if (rewardType == RewardIntervalType.TIMESTAMP) { + return rewardRate.times(RATE_IN_SECONDS_BD); + } else { + return rewardRate.times(circularBuffer.blocksPerDay); + } +} + +function getOrCreateCircularBuffer(): _CircularBuffer { + let circularBuffer = _CircularBuffer.load(CIRCULAR_BUFFER); + + if (!circularBuffer) { + circularBuffer = new _CircularBuffer(CIRCULAR_BUFFER); + + const blocks = new Array(BUFFER_SIZE); + for (let i = INT_ZERO; i < BUFFER_SIZE; i += INT_TWO) { + blocks[i] = INT_NEGATIVE_ONE; + blocks[i + INT_ONE] = INT_NEGATIVE_ONE; + } + + circularBuffer.blocks = blocks; + circularBuffer.windowStartIndex = INT_ZERO; + circularBuffer.nextIndex = INT_ZERO; + circularBuffer.bufferSize = BUFFER_SIZE; + circularBuffer.blocksPerDay = STARTING_BLOCKS_PER_DAY; + + circularBuffer.save(); + } + + return circularBuffer; +} + +function getStartingBlockRate(): BigDecimal { + // Block rates pulled from google searches - rough estimates + + const network = dataSource.network().toUpperCase().replace("-", "_"); + if (network == Network.MAINNET) { + return BigDecimal.fromString("13.39"); + } else if (network == Network.ARBITRUM_ONE) { + return BigDecimal.fromString("15"); + } else if (network == Network.AURORA) { + return BigDecimal.fromString("1.03"); + } else if (network == Network.BSC) { + return BigDecimal.fromString("5"); + } else if (network == Network.CELO) { + return BigDecimal.fromString("5"); + } else if (network == Network.FANTOM) { + return BigDecimal.fromString("1"); + } else if (network == Network.FUSE) { + return BigDecimal.fromString("1"); + } else if (network == Network.OPTIMISM) { + return BigDecimal.fromString("12.5"); + } else if (network == Network.MATIC) { + return BigDecimal.fromString("2"); + } else if (network == Network.XDAI) { + return BigDecimal.fromString("5"); + } else if (network == Network.MOONBEAM) { + return BigDecimal.fromString("13.39"); + } else if (network == Network.MOONRIVER) { + return BigDecimal.fromString("13.39"); + } else if (network == Network.AVALANCHE) { + return BigDecimal.fromString("13.39"); + } else if (network == Network.CRONOS) { + return BigDecimal.fromString("5.5"); + } + + // else if (network == SubgraphNetwork.AVALANCHE) return BigDecimal.fromString("2.5") + // else if (dataSource.network() == "harmony") return BigDecimal.fromString("13.39") + else { + log.warning("getStartingBlockRate(): Network not found", []); + return BIGDECIMAL_ZERO; + } +} diff --git a/subgraphs/ebtc/tsconfig.json b/subgraphs/ebtc/tsconfig.json new file mode 100644 index 0000000000..5c5d17c928 --- /dev/null +++ b/subgraphs/ebtc/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@graphprotocol/graph-ts/types/tsconfig.base.json", + "include": ["src"] +} From df1daa4afaaf9f5ad73d885746b4b8757f8fd28e Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 20 Jun 2023 16:12:42 -0400 Subject: [PATCH 02/52] feat: add support for hosted subgraph --- deployment/deployment.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deployment/deployment.json b/deployment/deployment.json index 615b6cd7ad..efa80ac773 100644 --- a/deployment/deployment.json +++ b/deployment/deployment.json @@ -8882,6 +8882,10 @@ "decentralized-network": { "slug": "ebtc-goerli", "query-id": "QmdZphstRBDgd6teT5dhQDZ84H6bsqwTy8tEj579JFhqwU" + }, + "hosted-service": { + "slug": "ebtc-goerli", + "query-id": "ebtc-goerli" } } } From e0ac3da169bf9396cb52081c01c8d6b5231fb0a8 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 20 Jun 2023 16:17:30 -0400 Subject: [PATCH 03/52] chore: record cli commands in notes --- subgraphs/ebtc/NOTES.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/subgraphs/ebtc/NOTES.md b/subgraphs/ebtc/NOTES.md index d8a8cd9980..7ae0540e99 100644 --- a/subgraphs/ebtc/NOTES.md +++ b/subgraphs/ebtc/NOTES.md @@ -4,6 +4,20 @@ - collEthCLFeed: `0xb4c4a493AB6356497713A78FFA6c60FB53517c63` - ethBtcCLFeed: `0x779877A7B0D9E8603169DdbD7836e478b4624789` +### CLI Commands + +``` +graph auth --product subgraph-studio *** +messari b -l -s subgraph-studio ebtc -r ebtc-goerli -v 0.0.0 -d +``` + +``` +graph auth --product hosted-service *** +messari b -l -s hosted-service ebtc -r badger-finance -d +``` + +**NOTE: Omit the `-d` for a dry run without deployment** + ### Test GQL Queries `PriceFeed`: From 56c9755732ae3c0385a679d773739d1da2f31350 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 20 Jun 2023 16:23:49 -0400 Subject: [PATCH 04/52] chore: add urls --- subgraphs/ebtc/NOTES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/subgraphs/ebtc/NOTES.md b/subgraphs/ebtc/NOTES.md index 7ae0540e99..9e989257f1 100644 --- a/subgraphs/ebtc/NOTES.md +++ b/subgraphs/ebtc/NOTES.md @@ -1,8 +1,14 @@ +### URLs + +- `hosted-service`: https://thegraph.com/hosted-service/subgraph/badger-finance/ebtc-goerli +- `decentralized-network`: https://testnet.thegraph.com/explorer/subgraphs/HgyK4pup4x75snqPrvTbbzeRsqPExHXmf2zRJPiXFjiU + ### Goerli - https://docs.chain.link/data-feeds/price-feeds/addresses#Goerli%20Testnet - collEthCLFeed: `0xb4c4a493AB6356497713A78FFA6c60FB53517c63` - ethBtcCLFeed: `0x779877A7B0D9E8603169DdbD7836e478b4624789` +- testMsig (account holder for decentralised subgraph studio): `0xfA87ce273f8C254F345Bc7de42F30e2d2FEe6779` ### CLI Commands From c089ce074a547dffad35f529ad0020a1ab709eb6 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 20 Jun 2023 19:14:05 -0400 Subject: [PATCH 05/52] chore: yaml is always being built, no bool needed --- deployment/deployment.json | 1 - 1 file changed, 1 deletion(-) diff --git a/deployment/deployment.json b/deployment/deployment.json index efa80ac773..cce05bc876 100644 --- a/deployment/deployment.json +++ b/deployment/deployment.json @@ -8875,7 +8875,6 @@ "template": "ebtc.template.yaml" }, "options": { - "prepare:yaml": true, "prepare:constants": true }, "services": { From 7fff7c3e02de3ebfdf5f98fb22e12511e3dc7579 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 21 Jun 2023 15:42:05 -0400 Subject: [PATCH 06/52] chore: add goerli bpt pools --- subgraphs/ebtc/NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subgraphs/ebtc/NOTES.md b/subgraphs/ebtc/NOTES.md index 9e989257f1..e422636c8e 100644 --- a/subgraphs/ebtc/NOTES.md +++ b/subgraphs/ebtc/NOTES.md @@ -9,6 +9,8 @@ - collEthCLFeed: `0xb4c4a493AB6356497713A78FFA6c60FB53517c63` - ethBtcCLFeed: `0x779877A7B0D9E8603169DdbD7836e478b4624789` - testMsig (account holder for decentralised subgraph studio): `0xfA87ce273f8C254F345Bc7de42F30e2d2FEe6779` +- ebtc/wbtc bpt pool: `0x070d3BDf2cd2e7067AFADC40857E8b657a057417` +- ebtc/collateral bpt pool: `0xB1d4d8eFe062C83F1e7C816E9fbd74D752927250` ### CLI Commands From 9b80d8a05b08888e34c4a9f9f4dfa09a8aa2a219 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 21 Jun 2023 16:23:40 -0400 Subject: [PATCH 07/52] chore: consolidate sdk constants --- subgraphs/ebtc/src/entities/token.ts | 2 +- subgraphs/ebtc/src/sdk/account.ts | 2 +- subgraphs/ebtc/src/sdk/constants.ts | 281 ------------------- subgraphs/ebtc/src/sdk/manager.ts | 4 +- subgraphs/ebtc/src/sdk/position.ts | 2 +- subgraphs/ebtc/src/sdk/snapshots.ts | 2 +- subgraphs/ebtc/src/sdk/token.ts | 2 +- subgraphs/ebtc/src/sdk/util/constants.ts | 326 +++++++++++++---------- 8 files changed, 199 insertions(+), 422 deletions(-) delete mode 100644 subgraphs/ebtc/src/sdk/constants.ts diff --git a/subgraphs/ebtc/src/entities/token.ts b/subgraphs/ebtc/src/entities/token.ts index 3312a52289..7f9b96a29c 100644 --- a/subgraphs/ebtc/src/entities/token.ts +++ b/subgraphs/ebtc/src/entities/token.ts @@ -1,7 +1,7 @@ import { Address, BigDecimal, BigInt, ethereum } from "@graphprotocol/graph-ts"; import { Token } from "../../generated/schema"; import { BTC_ADDRESS, EBTC_ADDRESS, STETH_ADDRESS } from "../constants"; -import { BIGDECIMAL_ONE } from "../sdk/constants"; +import { BIGDECIMAL_ONE } from "../sdk/util/constants"; import { bigIntToBigDecimal } from "../sdk/util/numbers"; import { getUsdPrice } from "../prices"; diff --git a/subgraphs/ebtc/src/sdk/account.ts b/subgraphs/ebtc/src/sdk/account.ts index 7d8590b289..02cc90bfad 100644 --- a/subgraphs/ebtc/src/sdk/account.ts +++ b/subgraphs/ebtc/src/sdk/account.ts @@ -1,6 +1,6 @@ import { Bytes } from "@graphprotocol/graph-ts"; import { Account } from "../../../../generated/schema"; -import { INT_ONE, INT_ZERO } from "./constants"; +import { INT_ONE, INT_ZERO } from "./util/constants"; /** * This file contains the AccountClass, which does diff --git a/subgraphs/ebtc/src/sdk/constants.ts b/subgraphs/ebtc/src/sdk/constants.ts deleted file mode 100644 index aa14803b2f..0000000000 --- a/subgraphs/ebtc/src/sdk/constants.ts +++ /dev/null @@ -1,281 +0,0 @@ -import { BigDecimal, BigInt, Bytes } from "@graphprotocol/graph-ts"; -import { _ActiveAccount } from "../../generated/schema"; - -//////////////////////// -///// Schema Enums ///// -//////////////////////// - -// The network names corresponding to the Network enum in the schema. -// They also correspond to the ones in `dataSource.network()` after converting to lower case. -// See below for a complete list: -// https://thegraph.com/docs/en/hosted-service/what-is-hosted-service/#supported-networks-on-the-hosted-service -export namespace Network { - export const ARBITRUM_ONE = "ARBITRUM_ONE"; - export const ARWEAVE_MAINNET = "ARWEAVE_MAINNET"; - export const AURORA = "AURORA"; - export const AVALANCHE = "AVALANCHE"; - export const BOBA = "BOBA"; - export const BSC = "BSC"; // aka BNB Chain - export const CELO = "CELO"; - export const COSMOS = "COSMOS"; - export const CRONOS = "CRONOS"; - export const MAINNET = "MAINNET"; // Ethereum mainnet - export const FANTOM = "FANTOM"; - export const FUSE = "FUSE"; - export const HARMONY = "HARMONY"; - export const JUNO = "JUNO"; - export const MOONBEAM = "MOONBEAM"; - export const MOONRIVER = "MOONRIVER"; - export const NEAR_MAINNET = "NEAR_MAINNET"; - export const OPTIMISM = "OPTIMISM"; - export const OSMOSIS = "OSMOSIS"; - export const MATIC = "MATIC"; // aka Polygon - export const XDAI = "XDAI"; // aka Gnosis Chain -} - -export namespace ProtocolType { - export const EXCHANGE = "EXCHANGE"; - export const LENDING = "LENDING"; - export const YIELD = "YIELD"; - export const BRIDGE = "BRIDGE"; - export const GENERIC = "GENERIC"; -} - -export namespace LendingType { - export const CDP = "CDP"; - export const POOLED = "POOLED"; -} - -export namespace PermissionType { - export const WHITELIST_ONLY = "WHITELIST_ONLY"; - export const PERMISSIONED = "PERMISSIONED"; - export const PERMISSIONLESS = "PERMISSIONLESS"; - export const ADMIN = "ADMIN"; -} - -export namespace RiskType { - export const GLOBAL = "GLOBAL"; - export const ISOLATED = "ISOLATED"; -} - -export namespace CollateralizationType { - export const OVER_COLLATERALIZED = "OVER_COLLATERALIZED"; - export const UNDER_COLLATERALIZED = "UNDER_COLLATERALIZED"; - export const UNCOLLATERALIZED = "UNCOLLATERALIZED"; -} - -export namespace TokenType { - export const REBASING = "REBASING"; - export const NON_REBASING = "NON_REBASING"; -} - -export namespace InterestRateType { - export const STABLE = "STABLE"; - export const VARIABLE = "VARIABLE"; - export const FIXED = "FIXED"; -} - -export namespace InterestRateSide { - export const LENDER = "LENDER"; - export const BORROWER = "BORROWER"; -} - -export namespace FeeType { - export const LIQUIDATION_FEE = "LIQUIDATION_FEE"; - export const ADMIN_FEE = "ADMIN_FEE"; - export const PROTOCOL_FEE = "PROTOCOL_FEE"; - export const MINT_FEE = "MINT_FEE"; - export const WITHDRAW_FEE = "WITHDRAW_FEE"; - export const OTHER = "OTHER"; -} - -export namespace PositionSide { - export const COLLATERAL = "COLLATERAL"; - export const BORROWER = "BORROWER"; -} - -export namespace OracleSource { - export const UNISWAP = "UNISWAP"; - export const BALANCER = "BALANCER"; - export const CHAINLINK = "CHAINLINK"; - export const YEARN = "YEARN"; - export const SUSHISWAP = "SUSHISWAP"; - export const CURVE = "CURVE"; -} - -export namespace TransactionType { - export const DEPOSIT = "DEPOSIT"; - export const WITHDRAW = "WITHDRAW"; - export const BORROW = "BORROW"; - export const REPAY = "REPAY"; - export const LIQUIDATE = "LIQUIDATE"; - export const TRANSFER = "TRANSFER"; - export const FLASHLOAN = "FLASHLOAN"; - - export const LIQUIDATOR = "LIQUIDATOR"; - export const LIQUIDATEE = "LIQUIDATEE"; -} - -export namespace AccountActivity { - export const DAILY = "DAILY"; - export const HOURLY = "HOURLY"; -} - -export namespace RewardTokenType { - export const DEPOSIT = "DEPOSIT"; - export const VARIABLE_BORROW = "VARIABLE_BORROW"; - export const STABLE_BORROW = "STABLE_BORROW"; - export const STAKE = "STAKE"; -} - -export enum Transaction { - DEPOSIT = 0, - WITHDRAW = 1, - BORROW = 2, - REPAY = 3, - LIQUIDATE = 4, - TRANSFER = 5, - FLASHLOAN = 6, -} - -//////////////////////// -///// Type Helpers ///// -//////////////////////// - -export const INT_NEGATIVE_ONE = -1 as i32; -export const INT_ZERO = 0 as i32; -export const INT_ONE = 1 as i32; -export const INT_TWO = 2 as i32; -export const INT_FOUR = 4 as i32; -export const INT_SIX = 6 as i32; -export const INT_NINE = 9 as i32; -export const INT_SIXTEEN = 16 as i32; -export const INT_EIGHTTEEN = 18 as i32; - -export const BIGINT_NEGATIVE_ONE = BigInt.fromI32(-1); -export const BIGINT_ZERO = BigInt.fromI32(0); -export const BIGINT_ONE = BigInt.fromI32(1); -export const BIGINT_HUNDRED = BigInt.fromI32(100); -export const BIGINT_THREE_HUNDRED = BigInt.fromI32(300); -export const BIGINT_TEN_TO_EIGHTEENTH = BigInt.fromString("10").pow(18); - -export const BIGDECIMAL_ZERO = new BigDecimal(BIGINT_ZERO); -export const BIGDECIMAL_ONE = new BigDecimal(BIGINT_ONE); -export const BIGDECIMAL_HUNDRED = new BigDecimal(BigInt.fromI32(100)); - -///////////////////// -///// Date/Time ///// -///////////////////// - -export const DAYS_PER_YEAR = 365; -export const SECONDS_PER_YEAR = 60 * 60 * 24 * DAYS_PER_YEAR; -export const SECONDS_PER_DAY = 60 * 60 * 24; // 86400 -export const SECONDS_PER_HOUR = 60 * 60; // 3600 - -export const ETHEREUM_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 13; // 13 = seconds per block -export const AVALANCHE_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 2; // 2 = seconds per block. This is NOT ideal since avalanche has variable block time. -export const FANTOM_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 1; // 1 = seconds per block. This is NOT ideal since fantom has variable block time. -export const BSC_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 3; // 3 = seconds per block -export const MATIC_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 2; // 2 = seconds per block -export const ARBITRUM_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 1; // 1 = seconds per block. - -///////////////////////////// -///// Math ///// -///////////////////////////// - -export const mantissaFactor = 18; -export const cTokenDecimals = 8; -export const mantissaFactorBD = exponentToBigDecimal(mantissaFactor); -export const cTokenDecimalsBD = exponentToBigDecimal(cTokenDecimals); - -// n => 10^n -export function exponentToBigDecimal(decimals: i32): BigDecimal { - let result = BIGINT_ONE; - const ten = BigInt.fromI32(10); - for (let i = 0; i < decimals; i++) { - result = result.times(ten); - } - return result.toBigDecimal(); -} - -// BigInt to BigDecimal -export function bigIntToBigDecimal(x: BigInt, decimals: i32): BigDecimal { - return x.toBigDecimal().div(exponentToBigDecimal(decimals)); -} - -//change number of decimals for BigDecimal -export function BDChangeDecimals( - x: BigDecimal, - from: i32, - to: i32 -): BigDecimal { - if (to > from) { - // increase number of decimals - const diffMagnitude = exponentToBigDecimal(to - from); - return x.times(diffMagnitude); - } else if (to < from) { - // decrease number of decimals - const diffMagnitude = exponentToBigDecimal(from - to); - return x.div(diffMagnitude); - } else { - return x; - } -} - -// insert value into arr at index -export function insert( - arr: Array, - index: i32, - value: Type -): Array { - const result: Type[] = []; - for (let i = 0; i < index; i++) { - result.push(arr[i]); - } - result.push(value); - for (let i = index; i < arr.length; i++) { - result.push(arr[i]); - } - return result; -} - -// returns the increment to update the usage activity by -// 1 for a new account in the specified period, otherwise 0 -export function activityCounter( - account: Bytes, - transactionType: string, - useTransactionType: boolean, - intervalID: i32, // 0 = no intervalID - marketID: Bytes | null = null -): i32 { - let activityID = account - .toHexString() - .concat("-") - .concat(intervalID.toString()); - if (marketID) { - activityID = activityID.concat("-").concat(marketID.toHexString()); - } - if (useTransactionType) { - activityID = activityID.concat("-").concat(transactionType); - } - let activeAccount = _ActiveAccount.load(activityID); - if (!activeAccount) { - // if account / market only + transactionType is LIQUIDATEE - // then do not count that account as it did not spend gas to use the protocol - if (!useTransactionType && transactionType == TransactionType.LIQUIDATEE) { - return INT_ZERO; - } - - activeAccount = new _ActiveAccount(activityID); - activeAccount.save(); - return INT_ONE; - } - - return INT_ZERO; -} - -///////////////////////////// -///// Addresses ///// -///////////////////////////// - -export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; diff --git a/subgraphs/ebtc/src/sdk/manager.ts b/subgraphs/ebtc/src/sdk/manager.ts index e1107c47f9..a24ce2281a 100644 --- a/subgraphs/ebtc/src/sdk/manager.ts +++ b/subgraphs/ebtc/src/sdk/manager.ts @@ -38,10 +38,10 @@ import { ProtocolType, Transaction, TransactionType, -} from "./constants"; +} from "./util/constants"; import { SnapshotManager } from "./snapshots"; import { TokenManager } from "./token"; -import { insert } from "./constants"; +import { insert } from "./util/constants"; import { PositionManager } from "./position"; /** diff --git a/subgraphs/ebtc/src/sdk/position.ts b/subgraphs/ebtc/src/sdk/position.ts index 0560a89dbe..ded2603c4a 100644 --- a/subgraphs/ebtc/src/sdk/position.ts +++ b/subgraphs/ebtc/src/sdk/position.ts @@ -20,7 +20,7 @@ import { INT_ZERO, SECONDS_PER_DAY, TransactionType, -} from "./constants"; +} from "./util/constants"; import { SnapshotManager } from "./snapshots"; import { TokenManager } from "./token"; diff --git a/subgraphs/ebtc/src/sdk/snapshots.ts b/subgraphs/ebtc/src/sdk/snapshots.ts index 9252c5aea8..cc315c14db 100644 --- a/subgraphs/ebtc/src/sdk/snapshots.ts +++ b/subgraphs/ebtc/src/sdk/snapshots.ts @@ -26,7 +26,7 @@ import { SECONDS_PER_DAY, SECONDS_PER_HOUR, TransactionType, -} from "./constants"; +} from "./util/constants"; /** * This file contains the SnapshotManager, which is used to diff --git a/subgraphs/ebtc/src/sdk/token.ts b/subgraphs/ebtc/src/sdk/token.ts index ae2df52ada..a50677e89a 100644 --- a/subgraphs/ebtc/src/sdk/token.ts +++ b/subgraphs/ebtc/src/sdk/token.ts @@ -9,7 +9,7 @@ import { INT_NINE, INT_SIX, INT_SIXTEEN, -} from "./constants"; +} from "./util/constants"; /** * This file contains the TokenClass, which acts as diff --git a/subgraphs/ebtc/src/sdk/util/constants.ts b/subgraphs/ebtc/src/sdk/util/constants.ts index 185e7bf83d..2f85e4dfe5 100644 --- a/subgraphs/ebtc/src/sdk/util/constants.ts +++ b/subgraphs/ebtc/src/sdk/util/constants.ts @@ -1,4 +1,5 @@ -import { BigDecimal, BigInt } from "@graphprotocol/graph-ts"; +import { BigDecimal, BigInt, Bytes } from "@graphprotocol/graph-ts"; +import { _ActiveAccount } from "../../../generated/schema"; //////////////////////// ///// Schema Enums ///// @@ -10,141 +11,68 @@ import { BigDecimal, BigInt } from "@graphprotocol/graph-ts"; // https://thegraph.com/docs/en/hosted-service/what-is-hosted-service/#supported-networks-on-the-hosted-service export namespace Network { export const ARBITRUM_ONE = "ARBITRUM_ONE"; - export const AVALANCHE = "AVALANCHE"; + export const ARWEAVE_MAINNET = "ARWEAVE_MAINNET"; export const AURORA = "AURORA"; + export const AVALANCHE = "AVALANCHE"; + export const BOBA = "BOBA"; export const BSC = "BSC"; // aka BNB Chain export const CELO = "CELO"; + export const COSMOS = "COSMOS"; + export const CRONOS = "CRONOS"; export const MAINNET = "MAINNET"; // Ethereum mainnet export const FANTOM = "FANTOM"; export const FUSE = "FUSE"; + export const HARMONY = "HARMONY"; + export const JUNO = "JUNO"; export const MOONBEAM = "MOONBEAM"; export const MOONRIVER = "MOONRIVER"; export const NEAR_MAINNET = "NEAR_MAINNET"; export const OPTIMISM = "OPTIMISM"; + export const OSMOSIS = "OSMOSIS"; export const MATIC = "MATIC"; // aka Polygon export const XDAI = "XDAI"; // aka Gnosis Chain - - // other networks - export const UBIQ = "UBIQ"; - export const SONGBIRD = "SONGBIRD"; - export const ELASTOS = "ELASTOS"; - export const KARDIACHAIN = "KARDIACHAIN"; - export const CRONOS = "CRONOS"; - export const RSK = "RSK"; - export const TELOS = "TELOS"; - export const XDC = "XDC"; - export const ZYX = "ZYX"; - export const CSC = "CSC"; - export const SYSCOIN = "SYSCOIN"; - export const GOCHAIN = "GOCHAIN"; - export const ETHEREUMCLASSIC = "ETHEREUMCLASSIC"; - export const OKEXCHAIN = "OKEXCHAIN"; - export const HOO = "HOO"; - export const METER = "METER"; - export const NOVA_NETWORK = "NOVA_NETWORK"; - export const TOMOCHAIN = "TOMOCHAIN"; - export const VELAS = "VELAS"; - export const THUNDERCORE = "THUNDERCORE"; - export const HECO = "HECO"; - export const XDAIARB = "XDAIARB"; - export const ENERGYWEB = "ENERGYWEB"; - export const HPB = "HPB"; - export const BOBA = "BOBA"; - export const KUCOIN = "KUCOIN"; - export const SHIDEN = "SHIDEN"; - export const THETA = "THETA"; - export const SX = "SX"; - export const CANDLE = "CANDLE"; - export const ASTAR = "ASTAR"; - export const CALLISTO = "CALLISTO"; - export const WANCHAIN = "WANCHAIN"; - export const METIS = "METIS"; - export const ULTRON = "ULTRON"; - export const STEP = "STEP"; - export const DOGECHAIN = "DOGECHAIN"; - export const RONIN = "RONIN"; - export const KAVA = "KAVA"; - export const IOTEX = "IOTEX"; - export const XLC = "XLC"; - export const NAHMII = "NAHMII"; - export const TOMBCHAIN = "TOMBCHAIN"; - export const CANTO = "CANTO"; - export const KLAYTN = "KLAYTN"; - export const EVMOS = "EVMOS"; - export const SMARTBCH = "SMARTBCH"; - export const BITGERT = "BITGERT"; - export const FUSION = "FUSION"; - export const OHO = "OHO"; - export const ARB_NOVA = "ARB_NOVA"; - export const OASIS = "OASIS"; - export const REI = "REI"; - export const REICHAIN = "REICHAIN"; - export const GODWOKEN = "GODWOKEN"; - export const POLIS = "POLIS"; - export const KEKCHAIN = "KEKCHAIN"; - export const VISION = "VISION"; - export const HARMONY = "HARMONY"; - export const PALM = "PALM"; - export const CURIO = "CURIO"; - - export const UNKNOWN_NETWORK = "UNKNOWN_NETWORK"; } -export type Network = string; export namespace ProtocolType { export const EXCHANGE = "EXCHANGE"; export const LENDING = "LENDING"; export const YIELD = "YIELD"; export const BRIDGE = "BRIDGE"; - export const OPTION = "OPTION"; - export const PERPETUAL = "PERPETUAL"; export const GENERIC = "GENERIC"; } -export namespace VaultFeeType { - export const MANAGEMENT_FEE = "MANAGEMENT_FEE"; - export const PERFORMANCE_FEE = "PERFORMANCE_FEE"; - export const DEPOSIT_FEE = "DEPOSIT_FEE"; - export const WITHDRAWAL_FEE = "WITHDRAWAL_FEE"; -} - -export namespace LiquidityPoolFeeType { - export const FIXED_TRADING_FEE = "FIXED_TRADING_FEE"; - export const TIERED_TRADING_FEE = "TIERED_TRADING_FEE"; - export const DYNAMIC_TRADING_FEE = "DYNAMIC_TRADING_FEE"; - export const FIXED_LP_FEE = "FIXED_LP_FEE"; - export const DYNAMIC_LP_FEE = "DYNAMIC_LP_FEE"; - export const FIXED_PROTOCOL_FEE = "FIXED_PROTOCOL_FEE"; - export const DYNAMIC_PROTOCOL_FEE = "DYNAMIC_PROTOCOL_FEE"; -} -export type LiquidityPoolFeeType = string; - -export namespace RewardTokenType { - export const DEPOSIT = "DEPOSIT"; - export const BORROW = "BORROW"; - export const STAKE = "STAKE"; -} -export type RewardTokenType = string; - -export namespace ActivityInterval { - export const HOURLY = "HOURLY"; - export const DAILY = "DAILY"; -} - export namespace LendingType { export const CDP = "CDP"; export const POOLED = "POOLED"; } +export namespace PermissionType { + export const WHITELIST_ONLY = "WHITELIST_ONLY"; + export const PERMISSIONED = "PERMISSIONED"; + export const PERMISSIONLESS = "PERMISSIONLESS"; + export const ADMIN = "ADMIN"; +} + export namespace RiskType { export const GLOBAL = "GLOBAL"; export const ISOLATED = "ISOLATED"; } +export namespace CollateralizationType { + export const OVER_COLLATERALIZED = "OVER_COLLATERALIZED"; + export const UNDER_COLLATERALIZED = "UNDER_COLLATERALIZED"; + export const UNCOLLATERALIZED = "UNCOLLATERALIZED"; +} + +export namespace TokenType { + export const REBASING = "REBASING"; + export const NON_REBASING = "NON_REBASING"; +} + export namespace InterestRateType { export const STABLE = "STABLE"; export const VARIABLE = "VARIABLE"; - export const FIXED_TERM = "FIXED_TERM"; + export const FIXED = "FIXED"; } export namespace InterestRateSide { @@ -152,39 +80,85 @@ export namespace InterestRateSide { export const BORROWER = "BORROWER"; } -export namespace UsageType { +export namespace FeeType { + export const LIQUIDATION_FEE = "LIQUIDATION_FEE"; + export const ADMIN_FEE = "ADMIN_FEE"; + export const PROTOCOL_FEE = "PROTOCOL_FEE"; + export const MINT_FEE = "MINT_FEE"; + export const WITHDRAW_FEE = "WITHDRAW_FEE"; + export const OTHER = "OTHER"; +} + +export namespace PositionSide { + export const COLLATERAL = "COLLATERAL"; + export const BORROWER = "BORROWER"; +} + +export namespace OracleSource { + export const UNISWAP = "UNISWAP"; + export const BALANCER = "BALANCER"; + export const CHAINLINK = "CHAINLINK"; + export const YEARN = "YEARN"; + export const SUSHISWAP = "SUSHISWAP"; + export const CURVE = "CURVE"; +} + +export namespace TransactionType { export const DEPOSIT = "DEPOSIT"; export const WITHDRAW = "WITHDRAW"; - export const SWAP = "SWAP"; + export const BORROW = "BORROW"; + export const REPAY = "REPAY"; + export const LIQUIDATE = "LIQUIDATE"; + export const TRANSFER = "TRANSFER"; + export const FLASHLOAN = "FLASHLOAN"; + + export const LIQUIDATOR = "LIQUIDATOR"; + export const LIQUIDATEE = "LIQUIDATEE"; } -export namespace PositionSide { - export const LONG = "LONG"; - export const SHORT = "SHORT"; +export namespace AccountActivity { + export const DAILY = "DAILY"; + export const HOURLY = "HOURLY"; } -export type PositionSide = string; -////////////////////////////// -///// Ethereum Addresses ///// -////////////////////////////// +export namespace RewardTokenType { + export const DEPOSIT = "DEPOSIT"; + export const VARIABLE_BORROW = "VARIABLE_BORROW"; + export const STABLE_BORROW = "STABLE_BORROW"; + export const STAKE = "STAKE"; +} -export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; -export const ETH_ADDRESS = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; +export enum Transaction { + DEPOSIT = 0, + WITHDRAW = 1, + BORROW = 2, + REPAY = 3, + LIQUIDATE = 4, + TRANSFER = 5, + FLASHLOAN = 6, +} //////////////////////// ///// Type Helpers ///// //////////////////////// -export const DEFAULT_DECIMALS = 18; - -export const USDC_DECIMALS = 6; -export const USDC_DENOMINATOR = BigDecimal.fromString("1000000"); +export const INT_NEGATIVE_ONE = -1 as i32; +export const INT_ZERO = 0 as i32; +export const INT_ONE = 1 as i32; +export const INT_TWO = 2 as i32; +export const INT_FOUR = 4 as i32; +export const INT_SIX = 6 as i32; +export const INT_NINE = 9 as i32; +export const INT_SIXTEEN = 16 as i32; +export const INT_EIGHTTEEN = 18 as i32; +export const BIGINT_NEGATIVE_ONE = BigInt.fromI32(-1); export const BIGINT_ZERO = BigInt.fromI32(0); export const BIGINT_ONE = BigInt.fromI32(1); export const BIGINT_TWO = BigInt.fromI32(2); export const BIGINT_TEN = BigInt.fromI32(10); export const BIGINT_HUNDRED = BigInt.fromI32(100); +export const BIGINT_THREE_HUNDRED = BigInt.fromI32(300); export const BIGINT_THOUSAND = BigInt.fromI32(1000); export const BIGINT_TEN_TO_EIGHTEENTH = BigInt.fromString("10").pow(18); export const BIGINT_MINUS_ONE = BigInt.fromI32(-1); @@ -192,12 +166,6 @@ export const BIGINT_MAX = BigInt.fromString( "115792089237316195423570985008687907853269984665640564039457584007913129639935" ); -export const INT_NEGATIVE_ONE = -1 as i32; -export const INT_ZERO = 0 as i32; -export const INT_ONE = 1 as i32; -export const INT_TWO = 2 as i32; -export const INT_FOUR = 4 as i32; - export const BIGDECIMAL_ZERO = new BigDecimal(BIGINT_ZERO); export const BIGDECIMAL_ONE = new BigDecimal(BIGINT_ONE); export const BIGDECIMAL_TWO = new BigDecimal(BIGINT_TWO); @@ -210,19 +178,109 @@ export const MAX_UINT = BigInt.fromI32(2).times(BigInt.fromI32(255)); ///// Date/Time ///// ///////////////////// +export const DAYS_PER_YEAR = 365; +export const SECONDS_PER_YEAR = 60 * 60 * 24 * DAYS_PER_YEAR; export const SECONDS_PER_DAY = 60 * 60 * 24; // 86400 export const SECONDS_PER_HOUR = 60 * 60; // 3600 -export const SECONDS_PER_DAY_BI = BigInt.fromI32(SECONDS_PER_DAY); -export const SECONDS_PER_HOUR_BI = BigInt.fromI32(SECONDS_PER_HOUR); -export const MS_PER_DAY = new BigDecimal(BigInt.fromI32(24 * 60 * 60 * 1000)); -export const DAYS_PER_YEAR = new BigDecimal(BigInt.fromI32(365)); -export const MS_PER_YEAR = DAYS_PER_YEAR.times( - new BigDecimal(BigInt.fromI32(24 * 60 * 60 * 1000)) -); -//////////////// -///// Misc ///// -//////////////// +export const ETHEREUM_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 13; // 13 = seconds per block +export const AVALANCHE_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 2; // 2 = seconds per block. This is NOT ideal since avalanche has variable block time. +export const FANTOM_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 1; // 1 = seconds per block. This is NOT ideal since fantom has variable block time. +export const BSC_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 3; // 3 = seconds per block +export const MATIC_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 2; // 2 = seconds per block +export const ARBITRUM_BLOCKS_PER_YEAR = SECONDS_PER_YEAR / 1; // 1 = seconds per block. + +///////////////////////////// +///// Math ///// +///////////////////////////// + +export const mantissaFactor = 18; +export const cTokenDecimals = 8; +export const mantissaFactorBD = exponentToBigDecimal(mantissaFactor); +export const cTokenDecimalsBD = exponentToBigDecimal(cTokenDecimals); + +// n => 10^n +export function exponentToBigDecimal(decimals: i32): BigDecimal { + let result = BIGINT_ONE; + const ten = BigInt.fromI32(10); + for (let i = 0; i < decimals; i++) { + result = result.times(ten); + } + return result.toBigDecimal(); +} + +// BigInt to BigDecimal +export function bigIntToBigDecimal(x: BigInt, decimals: i32): BigDecimal { + return x.toBigDecimal().div(exponentToBigDecimal(decimals)); +} -export const ETH_SYMBOL = "ETH"; -export const ETH_NAME = "Ether"; +//change number of decimals for BigDecimal +export function BDChangeDecimals( + x: BigDecimal, + from: i32, + to: i32 +): BigDecimal { + if (to > from) { + // increase number of decimals + const diffMagnitude = exponentToBigDecimal(to - from); + return x.times(diffMagnitude); + } else if (to < from) { + // decrease number of decimals + const diffMagnitude = exponentToBigDecimal(from - to); + return x.div(diffMagnitude); + } else { + return x; + } +} + +// insert value into arr at index +export function insert( + arr: Array, + index: i32, + value: Type +): Array { + const result: Type[] = []; + for (let i = 0; i < index; i++) { + result.push(arr[i]); + } + result.push(value); + for (let i = index; i < arr.length; i++) { + result.push(arr[i]); + } + return result; +} + +// returns the increment to update the usage activity by +// 1 for a new account in the specified period, otherwise 0 +export function activityCounter( + account: Bytes, + transactionType: string, + useTransactionType: boolean, + intervalID: i32, // 0 = no intervalID + marketID: Bytes | null = null +): i32 { + let activityID = account + .toHexString() + .concat("-") + .concat(intervalID.toString()); + if (marketID) { + activityID = activityID.concat("-").concat(marketID.toHexString()); + } + if (useTransactionType) { + activityID = activityID.concat("-").concat(transactionType); + } + let activeAccount = _ActiveAccount.load(activityID); + if (!activeAccount) { + // if account / market only + transactionType is LIQUIDATEE + // then do not count that account as it did not spend gas to use the protocol + if (!useTransactionType && transactionType == TransactionType.LIQUIDATEE) { + return INT_ZERO; + } + + activeAccount = new _ActiveAccount(activityID); + activeAccount.save(); + return INT_ONE; + } + + return INT_ZERO; +} From df408af626bac838ca0891d9d3398f3fae938100 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 23 Jun 2023 13:45:27 -0400 Subject: [PATCH 08/52] fix: `constants.ts` got moved --- subgraphs/ebtc/src/constants.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subgraphs/ebtc/src/constants.mustache b/subgraphs/ebtc/src/constants.mustache index fd17f611f6..0b631f777a 100644 --- a/subgraphs/ebtc/src/constants.mustache +++ b/subgraphs/ebtc/src/constants.mustache @@ -1,5 +1,5 @@ import { BigDecimal, BigInt, Bytes } from "@graphprotocol/graph-ts"; -import { BIGDECIMAL_ONE, BIGDECIMAL_HUNDRED } from "./sdk/constants"; +import { BIGDECIMAL_ONE, BIGDECIMAL_HUNDRED } from "./sdk/util/constants"; ///////////////////////////// ///// Protocol Specific ///// From 18cdd1531aaea30d28981a4e0a2d53b1087ca843 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 23 Jun 2023 13:45:53 -0400 Subject: [PATCH 09/52] fix: add missing type helper --- subgraphs/ebtc/src/sdk/util/constants.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subgraphs/ebtc/src/sdk/util/constants.ts b/subgraphs/ebtc/src/sdk/util/constants.ts index 2f85e4dfe5..cdb5a59131 100644 --- a/subgraphs/ebtc/src/sdk/util/constants.ts +++ b/subgraphs/ebtc/src/sdk/util/constants.ts @@ -142,6 +142,8 @@ export enum Transaction { ///// Type Helpers ///// //////////////////////// +export const DEFAULT_DECIMALS = 18; + export const INT_NEGATIVE_ONE = -1 as i32; export const INT_ZERO = 0 as i32; export const INT_ONE = 1 as i32; From 2d4f0423a3580ba48b4a625c819021838568f254 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 28 Jun 2023 15:02:02 +0200 Subject: [PATCH 10/52] feat: add `ActivePool` data source --- subgraphs/ebtc/abis/ActivePool.json | 806 ++++++++++++++++++ subgraphs/ebtc/abis/{Prices => }/ERC20.json | 0 subgraphs/ebtc/abis/ERC20NameBytes.json | 17 + subgraphs/ebtc/abis/ERC20SymbolBytes.json | 17 + .../ebtc-goerli/configurations.json | 5 +- .../ebtc/config/templates/ebtc.template.yaml | 31 +- subgraphs/ebtc/src/constants.mustache | 43 +- subgraphs/ebtc/src/mapping/ActivePool.ts | 27 + subgraphs/ebtc/src/sdk/util/constants.ts | 3 +- 9 files changed, 941 insertions(+), 8 deletions(-) create mode 100644 subgraphs/ebtc/abis/ActivePool.json rename subgraphs/ebtc/abis/{Prices => }/ERC20.json (100%) create mode 100644 subgraphs/ebtc/abis/ERC20NameBytes.json create mode 100644 subgraphs/ebtc/abis/ERC20SymbolBytes.json create mode 100644 subgraphs/ebtc/src/mapping/ActivePool.ts diff --git a/subgraphs/ebtc/abis/ActivePool.json b/subgraphs/ebtc/abis/ActivePool.json new file mode 100644 index 0000000000..77d940c489 --- /dev/null +++ b/subgraphs/ebtc/abis/ActivePool.json @@ -0,0 +1,806 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_borrowerOperationsAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_cdpManagerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_collTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_collSurplusAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_feeRecipientAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_newActivePoolAddress", + "type": "address" + } + ], + "name": "ActivePoolAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_coll", + "type": "uint256" + } + ], + "name": "ActivePoolCollBalanceUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_EBTCDebt", + "type": "uint256" + } + ], + "name": "ActivePoolEBTCDebtUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_coll", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "ActivePoolFeeRecipientClaimableCollDecreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_coll", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "ActivePoolFeeRecipientClaimableCollIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract Authority", + "name": "newAuthority", + "type": "address" + } + ], + "name": "AuthorityUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_newBorrowerOperationsAddress", + "type": "address" + } + ], + "name": "BorrowerOperationsAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_newCdpManagerAddress", + "type": "address" + } + ], + "name": "CdpManagerAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_collSurplusAddress", + "type": "address" + } + ], + "name": "CollSurplusPoolAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_collTokenAddress", + "type": "address" + } + ], + "name": "CollateralAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "CollateralSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_newBalance", + "type": "uint256" + } + ], + "name": "EBTCBalanceUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_newBalance", + "type": "uint256" + } + ], + "name": "ETHBalanceUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_feeRecipientAddress", + "type": "address" + } + ], + "name": "FeeRecipientAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_setter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_oldFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newFee", + "type": "uint256" + } + ], + "name": "FlashFeeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "FlashLoanSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_setter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_oldMaxFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newMaxFee", + "type": "uint256" + } + ], + "name": "MaxFlashFeeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "SweepTokenSuccess", + "type": "event" + }, + { + "inputs": [], + "name": "FLASH_SUCCESS_VALUE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_BPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_shares", + "type": "uint256" + } + ], + "name": "allocateFeeRecipientColl", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "authority", + "outputs": [ + { + "internalType": "contract Authority", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "authorityInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowerOperationsAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cdpManagerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_shares", + "type": "uint256" + } + ], + "name": "claimFeeRecipientColl", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "collSurplusPoolAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "collateral", + "outputs": [ + { + "internalType": "contract ICollateralToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "decreaseEBTCDebt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feeBps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeRecipientAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "flashFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC3156FlashBorrower", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "flashLoan", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getEBTCDebt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFeeRecipientClaimableColl", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStEthColl", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "increaseEBTCDebt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "locked", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxFeeBps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "maxFlashLoan", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "receiveColl", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_shares", + "type": "uint256" + } + ], + "name": "sendStEthColl", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_shares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_liquidatorRewardShares", + "type": "uint256" + } + ], + "name": "sendStEthCollAndLiquidatorReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAuthority", + "type": "address" + } + ], + "name": "setAuthority", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newFee", + "type": "uint256" + } + ], + "name": "setFeeBps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeRecipientAddress", + "type": "address" + } + ], + "name": "setFeeRecipientAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newMaxFlashFee", + "type": "uint256" + } + ], + "name": "setMaxFeeBps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/subgraphs/ebtc/abis/Prices/ERC20.json b/subgraphs/ebtc/abis/ERC20.json similarity index 100% rename from subgraphs/ebtc/abis/Prices/ERC20.json rename to subgraphs/ebtc/abis/ERC20.json diff --git a/subgraphs/ebtc/abis/ERC20NameBytes.json b/subgraphs/ebtc/abis/ERC20NameBytes.json new file mode 100644 index 0000000000..2d3c877a8c --- /dev/null +++ b/subgraphs/ebtc/abis/ERC20NameBytes.json @@ -0,0 +1,17 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/subgraphs/ebtc/abis/ERC20SymbolBytes.json b/subgraphs/ebtc/abis/ERC20SymbolBytes.json new file mode 100644 index 0000000000..a76d616366 --- /dev/null +++ b/subgraphs/ebtc/abis/ERC20SymbolBytes.json @@ -0,0 +1,17 @@ +[ + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json b/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json index 5acf044fd6..b22520b71c 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json +++ b/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json @@ -1,5 +1,8 @@ { - "network": "goerli", + "network": { + "slug": "goerli", + "object": "Network.GOERLI" + }, "stethToken": { "address": "0x6B842CEA279aB886119F66fdCf6F864B5305008f" }, diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index 34484b0a61..ec00b3e1c0 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -3,9 +3,36 @@ repository: https://github.com/messari/subgraphs schema: file: ./schema.graphql dataSources: + - name: ActivePool + kind: ethereum/contract + network: "{{ network.slug }}" + source: + abi: ActivePool + address: "{{ activePool.address }}" + startBlock: {{ activePool.startBlock }} + mapping: + file: ./src/mapping/ActivePool.ts + language: wasm/assemblyscript + kind: ethereum/events + apiVersion: 0.0.7 + entities: [] + abis: + - name: ActivePool + file: ./abis/ActivePool.json + - name: ERC20 + file: ./abis/ERC20.json + - name: ERC20NameBytes + file: ./abis/ERC20NameBytes.json + - name: ERC20SymbolBytes + file: ./abis/ERC20SymbolBytes.json + eventHandlers: + - event: ActivePoolCollBalanceUpdated(uint256) + handler: handleActivePoolCollBalanceUpdated + - event: ActivePoolEBTCDebtUpdated(uint256) + handler: handleActivePoolEBTCDebtUpdated - name: PriceFeed kind: ethereum/contract - network: {{ network }} + network: "{{ network.slug }}" source: abi: PriceFeed address: "{{ priceFeed.address }}" @@ -25,7 +52,7 @@ dataSources: ########################################### # ERC20 - name: _ERC20 - file: ./abis/Prices/ERC20.json + file: ./abis/ERC20.json # Curve Contracts - name: CurvePool file: ./abis/Prices/Curve/Pool.json diff --git a/subgraphs/ebtc/src/constants.mustache b/subgraphs/ebtc/src/constants.mustache index 0b631f777a..697fbb7505 100644 --- a/subgraphs/ebtc/src/constants.mustache +++ b/subgraphs/ebtc/src/constants.mustache @@ -1,13 +1,19 @@ import { BigDecimal, BigInt, Bytes } from "@graphprotocol/graph-ts"; -import { BIGDECIMAL_ONE, BIGDECIMAL_HUNDRED } from "./sdk/util/constants"; +import { + BIGDECIMAL_ONE, + BIGDECIMAL_HUNDRED, + CollateralizationType, + LendingType, + Network, + PermissionType, + RiskType, +} from "./sdk/util/constants"; +import { ProtocolData } from "./sdk/manager"; ///////////////////////////// ///// Protocol Specific ///// ///////////////////////////// -export const PROTOCOL_NAME = "eBTC"; -export const PROTOCOL_SLUG = "ebtc"; - export const BTC_ADDRESS = Bytes.fromHexString( "0xC04B0d3107736C32e19F1c62b2aF67BE61d63a05" // TODO: since chainlink does not have a registry on goerli, we get the wbtc @@ -40,3 +46,32 @@ export const MAXIMUM_LTV = BIGDECIMAL_ONE.div(MINIMUM_COLLATERAL_RATIO).times( ); export const LIQUIDATION_FEE_PERCENT = BigDecimal.fromString("0.5"); export const LIQUIDATION_FEE = LIQUIDATION_FEE_PERCENT.div(BIGDECIMAL_HUNDRED); + +/////// + +export const PROTOCOL = "Liquity"; +export const PROTOCOL_NAME = "eBTC Protocol"; +export const PROTOCOL_SLUG = "ebtc"; +export const PROTOCOL_NETWORK = {{ network.object }}; +export const LENDING_TYPE = LendingType.CDP; +export const LENDER_PERMISSION_TYPE = PermissionType.PERMISSIONLESS; +export const BORROWER_PERMISSION_TYPE = PermissionType.PERMISSIONLESS; +export const POOL_CREATOR_PERMISSION_TYPE = PermissionType.ADMIN; // N/A really; one pool only +export const COLATERALIZATION_TYPE = CollateralizationType.OVER_COLLATERALIZED; +export const RISK_TYPE = RiskType.ISOLATED; + +export function getProtocolData(): ProtocolData { + return new ProtocolData( + ACTIVE_POOL, + PROTOCOL, + PROTOCOL_NAME, + PROTOCOL_SLUG, + PROTOCOL_NETWORK, + LENDING_TYPE, + LENDER_PERMISSION_TYPE, + BORROWER_PERMISSION_TYPE, + POOL_CREATOR_PERMISSION_TYPE, + COLATERALIZATION_TYPE, + RISK_TYPE + ); +} diff --git a/subgraphs/ebtc/src/mapping/ActivePool.ts b/subgraphs/ebtc/src/mapping/ActivePool.ts new file mode 100644 index 0000000000..ba3fcb8bc3 --- /dev/null +++ b/subgraphs/ebtc/src/mapping/ActivePool.ts @@ -0,0 +1,27 @@ +import { + ActivePoolCollBalanceUpdated, + ActivePoolEBTCDebtUpdated, +} from "../../generated/ActivePool/ActivePool"; +// import { setMarketCollBalance, setMarketEBTCDebt } from "../entities/market"; + +// /** +// * Total stETH collateral was updated +// * +// * @param event ActivePoolCollBalanceUpdated event +// */ +// export function handleActivePoolCollBalanceUpdated( +// event: ActivePoolCollBalanceUpdated +// ): void { +// setMarketCollBalance(event, event.params._coll); +// } + +// /** +// * EBTC debt was updated +// * +// * @param event ActivePoolEBTCDebtUpdated event +// */ +// export function handleActivePoolEBTCDebtUpdated( +// event: ActivePoolEBTCDebtUpdated +// ): void { +// setMarketEBTCDebt(event, event.params._EBTCDebt); +// } diff --git a/subgraphs/ebtc/src/sdk/util/constants.ts b/subgraphs/ebtc/src/sdk/util/constants.ts index cdb5a59131..8b4f6b95fa 100644 --- a/subgraphs/ebtc/src/sdk/util/constants.ts +++ b/subgraphs/ebtc/src/sdk/util/constants.ts @@ -30,7 +30,8 @@ export namespace Network { export const OPTIMISM = "OPTIMISM"; export const OSMOSIS = "OSMOSIS"; export const MATIC = "MATIC"; // aka Polygon - export const XDAI = "XDAI"; // aka Gnosis Chain + export const GNOSIS = "GNOSIS"; // aka XDAI + export const GOERLI = "GOERLI"; } export namespace ProtocolType { From 264c2152ff526e5fd46df7427d4a52b3ce50720f Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 28 Jun 2023 15:02:20 +0200 Subject: [PATCH 11/52] fix: adjust relative import dir --- subgraphs/ebtc/src/sdk/account.ts | 2 +- subgraphs/ebtc/src/sdk/position.ts | 2 +- subgraphs/ebtc/src/sdk/snapshots.ts | 2 +- subgraphs/ebtc/src/sdk/token.ts | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/subgraphs/ebtc/src/sdk/account.ts b/subgraphs/ebtc/src/sdk/account.ts index 02cc90bfad..2016881f1f 100644 --- a/subgraphs/ebtc/src/sdk/account.ts +++ b/subgraphs/ebtc/src/sdk/account.ts @@ -1,5 +1,5 @@ import { Bytes } from "@graphprotocol/graph-ts"; -import { Account } from "../../../../generated/schema"; +import { Account } from "../../generated/schema"; import { INT_ONE, INT_ZERO } from "./util/constants"; /** diff --git a/subgraphs/ebtc/src/sdk/position.ts b/subgraphs/ebtc/src/sdk/position.ts index ded2603c4a..8e777c89ad 100644 --- a/subgraphs/ebtc/src/sdk/position.ts +++ b/subgraphs/ebtc/src/sdk/position.ts @@ -12,7 +12,7 @@ import { Position, _PositionCounter, PositionSnapshot, -} from "../../../../generated/schema"; +} from "../../generated/schema"; import { BIGINT_ZERO, exponentToBigDecimal, diff --git a/subgraphs/ebtc/src/sdk/snapshots.ts b/subgraphs/ebtc/src/sdk/snapshots.ts index cc315c14db..30e571d258 100644 --- a/subgraphs/ebtc/src/sdk/snapshots.ts +++ b/subgraphs/ebtc/src/sdk/snapshots.ts @@ -15,7 +15,7 @@ import { RevenueDetail, UsageMetricsDailySnapshot, UsageMetricsHourlySnapshot, -} from "../../../../generated/schema"; +} from "../../generated/schema"; import { activityCounter, BIGDECIMAL_ZERO, diff --git a/subgraphs/ebtc/src/sdk/token.ts b/subgraphs/ebtc/src/sdk/token.ts index a50677e89a..46a06212dd 100644 --- a/subgraphs/ebtc/src/sdk/token.ts +++ b/subgraphs/ebtc/src/sdk/token.ts @@ -1,8 +1,8 @@ -import { ERC20 } from "../../../../generated/Configurator/ERC20"; -import { ERC20SymbolBytes } from "../../../../generated/Configurator/ERC20SymbolBytes"; -import { ERC20NameBytes } from "../../../../generated/Configurator/ERC20NameBytes"; +import { ERC20 } from "../../generated/ActivePool/ERC20"; +import { ERC20SymbolBytes } from "../../generated/ActivePool/ERC20SymbolBytes"; +import { ERC20NameBytes } from "../../generated/ActivePool/ERC20NameBytes"; import { Address, BigDecimal, Bytes, ethereum } from "@graphprotocol/graph-ts"; -import { RewardToken, Token } from "../../../../generated/schema"; +import { RewardToken, Token } from "../../generated/schema"; import { BIGDECIMAL_ZERO, INT_EIGHTTEEN, From a3746b356f4704f10567d09fd952dd250ab09b63 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Thu, 29 Jun 2023 14:30:19 +0200 Subject: [PATCH 12/52] fix: only comment actual lines in the functions --- subgraphs/ebtc/src/mapping/ActivePool.ts | 42 ++++++++++++------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/subgraphs/ebtc/src/mapping/ActivePool.ts b/subgraphs/ebtc/src/mapping/ActivePool.ts index ba3fcb8bc3..9c82445483 100644 --- a/subgraphs/ebtc/src/mapping/ActivePool.ts +++ b/subgraphs/ebtc/src/mapping/ActivePool.ts @@ -2,26 +2,26 @@ import { ActivePoolCollBalanceUpdated, ActivePoolEBTCDebtUpdated, } from "../../generated/ActivePool/ActivePool"; -// import { setMarketCollBalance, setMarketEBTCDebt } from "../entities/market"; +// import { setMarketCollBalance, setMarketEBTCDebt } from "../entities/market"; -// /** -// * Total stETH collateral was updated -// * -// * @param event ActivePoolCollBalanceUpdated event -// */ -// export function handleActivePoolCollBalanceUpdated( -// event: ActivePoolCollBalanceUpdated -// ): void { -// setMarketCollBalance(event, event.params._coll); -// } +/** + * Total stETH collateral was updated + * + * @param event ActivePoolCollBalanceUpdated event + */ +export function handleActivePoolCollBalanceUpdated( + event: ActivePoolCollBalanceUpdated +): void { + // setMarketCollBalance(event, event.params._coll); +} -// /** -// * EBTC debt was updated -// * -// * @param event ActivePoolEBTCDebtUpdated event -// */ -// export function handleActivePoolEBTCDebtUpdated( -// event: ActivePoolEBTCDebtUpdated -// ): void { -// setMarketEBTCDebt(event, event.params._EBTCDebt); -// } +/** + * EBTC debt was updated + * + * @param event ActivePoolEBTCDebtUpdated event + */ +export function handleActivePoolEBTCDebtUpdated( + event: ActivePoolEBTCDebtUpdated +): void { + // setMarketEBTCDebt(event, event.params._EBTCDebt); +} From ea331db62d1754868482db2569ecdb54ed063b30 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Thu, 29 Jun 2023 14:40:00 +0200 Subject: [PATCH 13/52] fix: `decimalValue` needs to be `i32` --- subgraphs/ebtc/abis/CdpManager.json | 1596 +++++++++++++++++ .../ebtc-goerli/configurations.json | 3 +- .../ebtc/config/templates/ebtc.template.yaml | 21 + subgraphs/ebtc/src/mapping/CdpManager.ts | 56 + 4 files changed, 1675 insertions(+), 1 deletion(-) create mode 100644 subgraphs/ebtc/abis/CdpManager.json create mode 100644 subgraphs/ebtc/src/mapping/CdpManager.ts diff --git a/subgraphs/ebtc/abis/CdpManager.json b/subgraphs/ebtc/abis/CdpManager.json new file mode 100644 index 0000000000..4f71f50baa --- /dev/null +++ b/subgraphs/ebtc/abis/CdpManager.json @@ -0,0 +1,1596 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_liquidationLibraryAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_authorityAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_borrowerOperationsAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_collSurplusPoolAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_ebtcTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_sortedCdpsAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_activePoolAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_priceFeedAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_collTokenAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_activePoolAddress", + "type": "address" + } + ], + "name": "ActivePoolAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract Authority", + "name": "newAuthority", + "type": "address" + } + ], + "name": "AuthorityUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_baseRate", + "type": "uint256" + } + ], + "name": "BaseRateUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_beta", + "type": "uint256" + } + ], + "name": "BetaSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_newBorrowerOperationsAddress", + "type": "address" + } + ], + "name": "BorrowerOperationsAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "_cdpId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_oldPerUnitCdp", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newPerUnitCdp", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_collReduced", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "collLeft", + "type": "uint256" + } + ], + "name": "CdpFeeSplitApplied", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "_cdpId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newIndex", + "type": "uint256" + } + ], + "name": "CdpIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "_cdpId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "_borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_debt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_coll", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum ICdpManagerData.CdpManagerOperation", + "name": "_operation", + "type": "uint8" + } + ], + "name": "CdpLiquidated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "_cdpId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "_borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_debt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_coll", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum ICdpManagerData.CdpManagerOperation", + "name": "operation", + "type": "uint8" + } + ], + "name": "CdpPartiallyLiquidated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "_cdpId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_L_EBTCDebt", + "type": "uint256" + } + ], + "name": "CdpSnapshotsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "_cdpId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "_borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_oldDebt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_oldColl", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_debt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_coll", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_stake", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum ICdpManagerData.CdpManagerOperation", + "name": "_operation", + "type": "uint8" + } + ], + "name": "CdpUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_collSurplusPoolAddress", + "type": "address" + } + ], + "name": "CollSurplusPoolAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_collTokenAddress", + "type": "address" + } + ], + "name": "CollateralAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_oldPerUnit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newPerUnit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_feeTaken", + "type": "uint256" + } + ], + "name": "CollateralFeePerUnitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_oldIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_updTimestamp", + "type": "uint256" + } + ], + "name": "CollateralGlobalIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_oldInterval", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newInterval", + "type": "uint256" + } + ], + "name": "CollateralIndexUpdateIntervalUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_newEBTCTokenAddress", + "type": "address" + } + ], + "name": "EBTCTokenAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_feeRecipientAddress", + "type": "address" + } + ], + "name": "FeeRecipientAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_L_EBTCDebt", + "type": "uint256" + } + ], + "name": "LTermsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_lastFeeOpTime", + "type": "uint256" + } + ], + "name": "LastFeeOpTimeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_liquidatedDebt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_liquidatedColl", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_liqReward", + "type": "uint256" + } + ], + "name": "Liquidation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_liquidationLibraryAddress", + "type": "address" + } + ], + "name": "LiquidationLibraryAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_minuteDecayFactor", + "type": "uint256" + } + ], + "name": "MinuteDecayFactorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_newPriceFeedAddress", + "type": "address" + } + ], + "name": "PriceFeedAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_attemptedEBTCAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_actualEBTCAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_ETHSent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_ETHFee", + "type": "uint256" + } + ], + "name": "Redemption", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_redemptionFeeFloor", + "type": "uint256" + } + ], + "name": "RedemptionFeeFloorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_sortedCdpsAddress", + "type": "address" + } + ], + "name": "SortedCdpsAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_stakingRewardSplit", + "type": "uint256" + } + ], + "name": "StakingRewardSplitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_totalStakesSnapshot", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_totalCollateralSnapshot", + "type": "uint256" + } + ], + "name": "SystemSnapshotsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_newTotalStakes", + "type": "uint256" + } + ], + "name": "TotalStakesUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "BOOTSTRAP_PERIOD", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BORROWING_FEE_FLOOR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CCR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "CdpIds", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "name": "Cdps", + "outputs": [ + { "internalType": "uint256", "name": "debt", "type": "uint256" }, + { "internalType": "uint256", "name": "coll", "type": "uint256" }, + { "internalType": "uint256", "name": "stake", "type": "uint256" }, + { + "internalType": "uint256", + "name": "liquidatorRewardShares", + "type": "uint256" + }, + { + "internalType": "enum ICdpManagerData.Status", + "name": "status", + "type": "uint8" + }, + { "internalType": "uint128", "name": "arrayIndex", "type": "uint128" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DECIMAL_PRECISION", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INDEX_UPD_INTERVAL", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LICR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIQUIDATOR_REWARD", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "L_EBTCDebt", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_MINUTE_DECAY_FACTOR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REWARD_SPLIT", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MCR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_MINUTE_DECAY_FACTOR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_NET_COLL", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_REDEMPTION_FEE_FLOOR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PERCENT_DIVISOR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SECONDS_IN_ONE_MINUTE", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_REWARD_SPLIT", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_100pct", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_105pct", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_5pct", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "activePool", + "outputs": [ + { "internalType": "contract IActivePool", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "addCdpIdToArray", + "outputs": [ + { "internalType": "uint256", "name": "index", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "applyPendingRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "authority", + "outputs": [ + { "internalType": "contract Authority", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "authorityInitialized", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRate", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32[]", "name": "_cdpArray", "type": "bytes32[]" } + ], + "name": "batchLiquidateCdps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "beta", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowerOperationsAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_newIndex", "type": "uint256" }, + { "internalType": "uint256", "name": "_prevIndex", "type": "uint256" } + ], + "name": "calcFeeUponStakingReward", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_entireSystemColl", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_entireSystemDebt", + "type": "uint256" + }, + { "internalType": "uint256", "name": "_price", "type": "uint256" } + ], + "name": "checkPotentialRecoveryMode", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_price", "type": "uint256" } + ], + "name": "checkRecoveryMode", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claimStakingSplitFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "closeCdp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "collateral", + "outputs": [ + { + "internalType": "contract ICollateralToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decayBaseRateFromBorrowing", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { "internalType": "uint256", "name": "_collDecrease", "type": "uint256" } + ], + "name": "decreaseCdpColl", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { "internalType": "uint256", "name": "_debtDecrease", "type": "uint256" } + ], + "name": "decreaseCdpDebt", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "ebtcToken", + "outputs": [ + { "internalType": "contract IEBTCToken", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { + "internalType": "uint256", + "name": "_stFeePerUnitg", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_stFeePerUnitgError", + "type": "uint256" + }, + { "internalType": "uint256", "name": "_totalStakes", "type": "uint256" } + ], + "name": "getAccumulatedFeeSplitApplied", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_EBTCDebt", "type": "uint256" } + ], + "name": "getBorrowingFee", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_EBTCDebt", "type": "uint256" } + ], + "name": "getBorrowingFeeWithDecay", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBorrowingRate", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBorrowingRateWithDecay", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "getCdpColl", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "getCdpDebt", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCdpIdsCount", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "getCdpLiquidatorRewardShares", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "getCdpStake", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "getCdpStatus", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { "internalType": "uint256", "name": "_price", "type": "uint256" } + ], + "name": "getCurrentICR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDeploymentStartTime", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "getEntireDebtAndColl", + "outputs": [ + { "internalType": "uint256", "name": "debt", "type": "uint256" }, + { "internalType": "uint256", "name": "coll", "type": "uint256" }, + { + "internalType": "uint256", + "name": "pendingEBTCDebtReward", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getEntireSystemColl", + "outputs": [ + { + "internalType": "uint256", + "name": "entireSystemColl", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getEntireSystemDebt", + "outputs": [ + { + "internalType": "uint256", + "name": "entireSystemDebt", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_index", "type": "uint256" } + ], + "name": "getIdFromCdpIdsArray", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "getNominalICR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "getPendingEBTCDebtReward", + "outputs": [ + { + "internalType": "uint256", + "name": "pendingEBTCDebtReward", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_ETHDrawn", "type": "uint256" } + ], + "name": "getRedemptionFeeWithDecay", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRedemptionRate", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRedemptionRateWithDecay", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_price", "type": "uint256" } + ], + "name": "getTCR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_feeTaken", "type": "uint256" } + ], + "name": "getTotalStakeForFeeTaken", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "hasPendingRewards", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { "internalType": "uint256", "name": "_collIncrease", "type": "uint256" } + ], + "name": "increaseCdpColl", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { "internalType": "uint256", "name": "_debtIncrease", "type": "uint256" } + ], + "name": "increaseCdpDebt", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastEBTCDebtError_Redistribution", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastETHError_Redistribution", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastFeeOperationTime", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "liquidate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "_n", "type": "uint256" }], + "name": "liquidateCdps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "liquidationLibrary", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "locked", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minuteDecayFactor", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { + "internalType": "uint256", + "name": "_partialAmount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_upperPartialHint", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_lowerPartialHint", + "type": "bytes32" + } + ], + "name": "partiallyLiquidate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "priceFeed", + "outputs": [ + { "internalType": "contract IPriceFeed", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_EBTCamount", "type": "uint256" }, + { + "internalType": "bytes32", + "name": "_firstRedemptionHint", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_upperPartialRedemptionHint", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_lowerPartialRedemptionHint", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_partialRedemptionHintNICR", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxIterations", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxFeePercentage", + "type": "uint256" + } + ], + "name": "redeemCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "redemptionFeeFloor", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "removeStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "name": "rewardSnapshots", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAuthority", "type": "address" } + ], + "name": "setAuthority", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_beta", "type": "uint256" } + ], + "name": "setBeta", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { + "internalType": "uint256", + "name": "_liquidatorRewardShares", + "type": "uint256" + } + ], + "name": "setCdpLiquidatorRewardShares", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { "internalType": "uint256", "name": "_num", "type": "uint256" } + ], + "name": "setCdpStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minuteDecayFactor", + "type": "uint256" + } + ], + "name": "setMinuteDecayFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_redemptionFeeFloor", + "type": "uint256" + } + ], + "name": "setRedemptionFeeFloor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_stakingRewardSplit", + "type": "uint256" + } + ], + "name": "setStakingRewardSplit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sortedCdps", + "outputs": [ + { "internalType": "contract ISortedCdps", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stFPPSg", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "name": "stFeePerUnitcdp", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stFeePerUnitg", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stFeePerUnitgError", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stakingRewardSplit", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "syncUpdateIndexInterval", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalCollateralSnapshot", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalStakes", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalStakesSnapshot", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "updateCdpRewardSnapshots", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "updateStakeAndTotalStakes", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json b/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json index b22520b71c..28b4f241a6 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json +++ b/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json @@ -24,7 +24,8 @@ }, "cdpManager": { "address": "0x7Cbde961F8aDB94c8A7660Abe1f3e647dbB8513f", - "verification": "https://goerli.etherscan.io/address/0x7Cbde961F8aDB94c8A7660Abe1f3e647dbB8513f#code" + "verification": "https://goerli.etherscan.io/address/0x7Cbde961F8aDB94c8A7660Abe1f3e647dbB8513f#code", + "startBlock": 9129595 }, "borrowerOperations": { "address": "0x11d823a74104A4E9D2E49672BAa6Ab9B5d321D06", diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index ec00b3e1c0..f574e3fc01 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -3,6 +3,27 @@ repository: https://github.com/messari/subgraphs schema: file: ./schema.graphql dataSources: + - name: CdpManager + kind: ethereum/contract + network: "{{ network.slug }}" + source: + abi: CdpManager + address: "{{ cdpManager.address }}" + startBlock: {{ cdpManager.startBlock }} + mapping: + file: ./src/mapping/CdpManager.ts + language: wasm/assemblyscript + kind: ethereum/events + apiVersion: 0.0.7 + entities: [] + abis: + - name: CdpManager + file: ./abis/CdpManager.json + - name: ERC20 + file: ./abis/ERC20.json + eventHandlers: + - event: ActivePoolAddressChanged(address) + handler: handleSystemDeployed - name: ActivePool kind: ethereum/contract network: "{{ network.slug }}" diff --git a/subgraphs/ebtc/src/mapping/CdpManager.ts b/subgraphs/ebtc/src/mapping/CdpManager.ts new file mode 100644 index 0000000000..196efda0c3 --- /dev/null +++ b/subgraphs/ebtc/src/mapping/CdpManager.ts @@ -0,0 +1,56 @@ +import { Address, log } from "@graphprotocol/graph-ts"; +import { ActivePoolAddressChanged } from "../../generated/CdpManager/CdpManager"; +import { ActivePool } from "../../generated/ActivePool/ActivePool"; +import { OracleSource } from "../sdk/util/constants"; +import { DataManager } from "../sdk/manager"; +import { + ACTIVE_POOL, + PRICE_FEED, + STETH_ADDRESS, + getProtocolData, +} from "../constants"; + +//////////////////////////////////////// +//// Initialise Protocol and Oracle //// +//////////////////////////////////////// +export function handleSystemDeployed(event: ActivePoolAddressChanged): void { + const activePool = ActivePool.bind(event.params._activePoolAddress); + if (activePool._address != ACTIVE_POOL) { + log.error( + "deployed ActivePool address {} does not match expected address", + [event.params._activePoolAddress.toHexString()] + ); + return; + } + + const manager = new DataManager( + activePool._address, // marketID: Bytes + STETH_ADDRESS, // inputToken: Bytes + event, // event: ethereum.Event + getProtocolData() // protocolData: ProtocolData + ); + + const market = manager.getMarket(); + + // TODO: update market with ebtc specifics + // market.name = outputToken.getToken().name; + // market.outputToken = outputToken.getToken().id; + // market.outputTokenSupply = BIGINT_ZERO; + // market.outputTokenPriceUSD = BIGDECIMAL_ZERO; + // market.exchangeRate = BIGDECIMAL_ZERO; // exchange rate = (inputTokenBalance / outputTokenSupply) OR (totalAssets() / totalSupply()) + // market.isActive = false; // controlled with setAsActive + // market.canBorrowFrom = false; // controlled with setAsActive + // market.canUseAsCollateral = false; // collateral is posted during loans separate from any deposits + // market.borrowedToken = tryInputToken.value; + // market.stableBorrowedTokenBalance = BIGINT_ZERO; + // market._poolManager = event.params.instance_; + // market.save(); + + const lendingProtocol = manager.getOrCreateLendingProtocol(getProtocolData()); + + const oracle = manager.getOrCreateOracle( + Address.fromBytes(PRICE_FEED), // oracleAddress: Address + false, // isUSD: boolean + OracleSource.CHAINLINK // source?: string + ); +} From a97040c90664b2516bc7a87fc33eb1ba417233c0 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Thu, 29 Jun 2023 14:40:37 +0200 Subject: [PATCH 14/52] fix: `decimalValue` needs to be of type `i32` --- subgraphs/ebtc/src/sdk/token.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subgraphs/ebtc/src/sdk/token.ts b/subgraphs/ebtc/src/sdk/token.ts index 46a06212dd..9e0fbc0c38 100644 --- a/subgraphs/ebtc/src/sdk/token.ts +++ b/subgraphs/ebtc/src/sdk/token.ts @@ -158,7 +158,7 @@ export class TokenManager { const decimalResult = contract.try_decimals(); if (!decimalResult.reverted) { const decimalValue = decimalResult.value; - return decimalValue; + return decimalValue.toI32(); } // try with the static definition From e435522f6923af8b67a95ba828b600ff51b306f7 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Thu, 29 Jun 2023 14:40:54 +0200 Subject: [PATCH 15/52] fix: add `PRICE_FEED` constant --- subgraphs/ebtc/src/constants.mustache | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subgraphs/ebtc/src/constants.mustache b/subgraphs/ebtc/src/constants.mustache index 697fbb7505..627a1c525e 100644 --- a/subgraphs/ebtc/src/constants.mustache +++ b/subgraphs/ebtc/src/constants.mustache @@ -36,6 +36,9 @@ export const CDP_MANAGER = Bytes.fromHexString( export const ACTIVE_POOL = Bytes.fromHexString( "{{ activePool.address }}" ); +export const PRICE_FEED = Bytes.fromHexString( + "{{ priceFeed.address }}" +); export const ACTIVE_POOL_CREATED_BLOCK = BigInt.fromI32({{ activePool.startBlock }}); export const ACTIVE_POOL_CREATED_TIMESTAMP = BigInt.fromI32({{ activePool.createdAt }}); From 3a6b4b51a22a0d571c8e5abc7bd6e1b97a988ef0 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 30 Jun 2023 14:08:21 +0200 Subject: [PATCH 16/52] perf: grab blocks and timestamps from actual event --- .../ebtc/config/deployments/ebtc-goerli/configurations.json | 3 +-- subgraphs/ebtc/src/constants.mustache | 5 +---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json b/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json index 28b4f241a6..ec1c6a9b1c 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json +++ b/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json @@ -43,8 +43,7 @@ "activePool": { "address": "0xB230cDa730CF515795Ad047fD8320D3e4480C8b8", "verification": "https://goerli.etherscan.io/address/0xB230cDa730CF515795Ad047fD8320D3e4480C8b8#code", - "startBlock": 9129672, - "createdAt": 1686026808 + "startBlock": 9129672 }, "collSurplusPool": { "address": "0xDB58AfEb24C44EAe3F0f211f71D1a88F92F0c5d9", diff --git a/subgraphs/ebtc/src/constants.mustache b/subgraphs/ebtc/src/constants.mustache index 627a1c525e..19e85138cf 100644 --- a/subgraphs/ebtc/src/constants.mustache +++ b/subgraphs/ebtc/src/constants.mustache @@ -1,4 +1,4 @@ -import { BigDecimal, BigInt, Bytes } from "@graphprotocol/graph-ts"; +import { BigDecimal, Bytes } from "@graphprotocol/graph-ts"; import { BIGDECIMAL_ONE, BIGDECIMAL_HUNDRED, @@ -40,9 +40,6 @@ export const PRICE_FEED = Bytes.fromHexString( "{{ priceFeed.address }}" ); -export const ACTIVE_POOL_CREATED_BLOCK = BigInt.fromI32({{ activePool.startBlock }}); -export const ACTIVE_POOL_CREATED_TIMESTAMP = BigInt.fromI32({{ activePool.createdAt }}); - export const MINIMUM_COLLATERAL_RATIO = BigDecimal.fromString("1.1"); export const MAXIMUM_LTV = BIGDECIMAL_ONE.div(MINIMUM_COLLATERAL_RATIO).times( BIGDECIMAL_HUNDRED From 24b3b0b984a0de1fd08f5973251b11cbb016e123 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 30 Jun 2023 14:08:44 +0200 Subject: [PATCH 17/52] feat: update market with ebtc specifics --- subgraphs/ebtc/src/mapping/CdpManager.ts | 50 +++++++++++++----------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/subgraphs/ebtc/src/mapping/CdpManager.ts b/subgraphs/ebtc/src/mapping/CdpManager.ts index 196efda0c3..9d704f9ef1 100644 --- a/subgraphs/ebtc/src/mapping/CdpManager.ts +++ b/subgraphs/ebtc/src/mapping/CdpManager.ts @@ -1,24 +1,32 @@ import { Address, log } from "@graphprotocol/graph-ts"; -import { ActivePoolAddressChanged } from "../../generated/CdpManager/CdpManager"; -import { ActivePool } from "../../generated/ActivePool/ActivePool"; -import { OracleSource } from "../sdk/util/constants"; +import { + ActivePool, + CdpManagerAddressChanged, +} from "../../generated/ActivePool/ActivePool"; +import { OracleSource, BIGDECIMAL_ZERO } from "../sdk/util/constants"; import { DataManager } from "../sdk/manager"; import { ACTIVE_POOL, + EBTC_ADDRESS, + LIQUIDATION_FEE_PERCENT, + MAXIMUM_LTV, PRICE_FEED, STETH_ADDRESS, getProtocolData, } from "../constants"; -//////////////////////////////////////// -//// Initialise Protocol and Oracle //// -//////////////////////////////////////// -export function handleSystemDeployed(event: ActivePoolAddressChanged): void { - const activePool = ActivePool.bind(event.params._activePoolAddress); +/** + * On deployment of the pool, initialise and populate the market, + * lendingProtocol and oracle entities. + * @param event An event emitted by the constructor of the ActivePool proving + * it was deployed successfully. + */ +export function handleSystemDeployed(event: CdpManagerAddressChanged): void { + const activePool = ActivePool.bind(event.address); if (activePool._address != ACTIVE_POOL) { log.error( "deployed ActivePool address {} does not match expected address", - [event.params._activePoolAddress.toHexString()] + [event.address.toHexString()] ); return; } @@ -32,21 +40,17 @@ export function handleSystemDeployed(event: ActivePoolAddressChanged): void { const market = manager.getMarket(); - // TODO: update market with ebtc specifics - // market.name = outputToken.getToken().name; - // market.outputToken = outputToken.getToken().id; - // market.outputTokenSupply = BIGINT_ZERO; - // market.outputTokenPriceUSD = BIGDECIMAL_ZERO; - // market.exchangeRate = BIGDECIMAL_ZERO; // exchange rate = (inputTokenBalance / outputTokenSupply) OR (totalAssets() / totalSupply()) - // market.isActive = false; // controlled with setAsActive - // market.canBorrowFrom = false; // controlled with setAsActive - // market.canUseAsCollateral = false; // collateral is posted during loans separate from any deposits - // market.borrowedToken = tryInputToken.value; - // market.stableBorrowedTokenBalance = BIGINT_ZERO; - // market._poolManager = event.params.instance_; - // market.save(); + // update market with ebtc specifics + market.canBorrowFrom = true; + market.maximumLTV = MAXIMUM_LTV; + market.liquidationThreshold = MAXIMUM_LTV; + market.liquidationPenalty = LIQUIDATION_FEE_PERCENT; + market.borrowedToken = EBTC_ADDRESS; + market.save(); - const lendingProtocol = manager.getOrCreateLendingProtocol(getProtocolData()); + const lendingProtocol = manager.getOrCreateLendingProtocol( + getProtocolData() // data: ProtocolData + ); const oracle = manager.getOrCreateOracle( Address.fromBytes(PRICE_FEED), // oracleAddress: Address From 015d1dd97c8fe0a526ed11158efec5464c6bcce9 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 30 Jun 2023 16:36:44 +0200 Subject: [PATCH 18/52] refactor: add helper for instantiating data manager --- subgraphs/ebtc/src/constants.mustache | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/subgraphs/ebtc/src/constants.mustache b/subgraphs/ebtc/src/constants.mustache index 19e85138cf..61d7189b83 100644 --- a/subgraphs/ebtc/src/constants.mustache +++ b/subgraphs/ebtc/src/constants.mustache @@ -1,4 +1,4 @@ -import { BigDecimal, Bytes } from "@graphprotocol/graph-ts"; +import { BigDecimal, Bytes, ethereum } from "@graphprotocol/graph-ts"; import { BIGDECIMAL_ONE, BIGDECIMAL_HUNDRED, @@ -8,7 +8,7 @@ import { PermissionType, RiskType, } from "./sdk/util/constants"; -import { ProtocolData } from "./sdk/manager"; +import { DataManager, ProtocolData } from "./sdk/manager"; ///////////////////////////// ///// Protocol Specific ///// @@ -75,3 +75,12 @@ export function getProtocolData(): ProtocolData { RISK_TYPE ); } + +export function getDataManager(event: ethereum.Event): DataManager { + return new DataManager( + ACTIVE_POOL, // marketID: Bytes + STETH_ADDRESS, // inputToken: Bytes + event, // event: ethereum.Event + getProtocolData() // protocolData: ProtocolData + ); +} From adf0f81e45dfd26aa0a6c8dd5bc352d5275ed836 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 30 Jun 2023 16:38:47 +0200 Subject: [PATCH 19/52] chore: rename `_ERC20` to `ERC20` --- .../protocols/ebtc/config/templates/ebtc.template.yaml | 2 +- subgraphs/ebtc/src/prices/common/utils.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index f574e3fc01..044208ade0 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -72,7 +72,7 @@ dataSources: ############## Price Oracle ############### ########################################### # ERC20 - - name: _ERC20 + - name: ERC20 file: ./abis/ERC20.json # Curve Contracts - name: CurvePool diff --git a/subgraphs/ebtc/src/prices/common/utils.ts b/subgraphs/ebtc/src/prices/common/utils.ts index 450300e896..788325e9e3 100644 --- a/subgraphs/ebtc/src/prices/common/utils.ts +++ b/subgraphs/ebtc/src/prices/common/utils.ts @@ -17,7 +17,7 @@ import * as ARBITRUM_ONE from "../config/arbitrum"; import { Configurations } from "./types"; import * as constants from "./constants"; import * as TEMPLATE from "../config/template"; -import { _ERC20 } from "../../../generated/PriceFeed/_ERC20"; +import { ERC20 } from "../../../generated/PriceFeed/ERC20"; import { Address, BigInt, dataSource, ethereum } from "@graphprotocol/graph-ts"; export function isNullAddress(tokenAddr: Address): boolean { @@ -32,14 +32,14 @@ export function readValue( } export function getTokenName(tokenAddr: Address): string { - const tokenContract = _ERC20.bind(tokenAddr); + const tokenContract = ERC20.bind(tokenAddr); const name = readValue(tokenContract.try_name(), ""); return name; } export function getTokenDecimals(tokenAddr: Address): BigInt { - const tokenContract = _ERC20.bind(tokenAddr); + const tokenContract = ERC20.bind(tokenAddr); const decimals = readValue( tokenContract.try_decimals(), @@ -50,7 +50,7 @@ export function getTokenDecimals(tokenAddr: Address): BigInt { } export function getTokenSupply(tokenAddr: Address): BigInt { - const tokenContract = _ERC20.bind(tokenAddr); + const tokenContract = ERC20.bind(tokenAddr); const totalSupply = readValue( tokenContract.try_totalSupply(), From 4d1414773ecea9885cc3d45ac90026ebfcf1ba5a Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 30 Jun 2023 17:13:56 +0200 Subject: [PATCH 20/52] refactor: use data and token managers instead of custom functions --- subgraphs/ebtc/src/entities/token.ts | 64 ------------------------ subgraphs/ebtc/src/mapping/ActivePool.ts | 27 +++++++--- subgraphs/ebtc/src/mapping/PriceFeed.ts | 33 ++++++++++-- 3 files changed, 48 insertions(+), 76 deletions(-) delete mode 100644 subgraphs/ebtc/src/entities/token.ts diff --git a/subgraphs/ebtc/src/entities/token.ts b/subgraphs/ebtc/src/entities/token.ts deleted file mode 100644 index 7f9b96a29c..0000000000 --- a/subgraphs/ebtc/src/entities/token.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Address, BigDecimal, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Token } from "../../generated/schema"; -import { BTC_ADDRESS, EBTC_ADDRESS, STETH_ADDRESS } from "../constants"; -import { BIGDECIMAL_ONE } from "../sdk/util/constants"; -import { bigIntToBigDecimal } from "../sdk/util/numbers"; -import { getUsdPrice } from "../prices"; - -export function getBtcToken(): Token { - const token = new Token(BTC_ADDRESS); - token.name = "Bitcoin"; - token.symbol = "BTC"; - token.decimals = 8; - token.save(); - return token; -} - -export function getCollToken(): Token { - const token = new Token(STETH_ADDRESS); - token.name = "Staked Ether"; - token.symbol = "stETH"; - token.decimals = 18; - token.save(); - return token; -} - -export function getEbtcToken(): Token { - const token = new Token(EBTC_ADDRESS); - token.name = "EBTC Stablecoin"; - token.symbol = "EBTC"; - token.decimals = 18; - token.save(); - return token; -} - -export function setCurrentBtcPrice(block: ethereum.Block): void { - const btc = getBtcToken(); - btc.lastPriceUSD = getUsdPrice( - Address.fromBytes(BTC_ADDRESS), - BIGDECIMAL_ONE - ); - btc.lastPriceBlockNumber = block.number; - btc.save(); -} - -export function getCurrentBtcPrice(): BigDecimal { - const btcToken = Token.load(BTC_ADDRESS); - return btcToken!.lastPriceUSD!; -} - -export function setCurrentCollPrice( - block: ethereum.Block, - stethBtcRatio: BigInt -): void { - const coll = getCollToken(); - const btcPrice = getCurrentBtcPrice(); - coll.lastPriceUSD = btcPrice.times(bigIntToBigDecimal(stethBtcRatio)); - coll.lastPriceBlockNumber = block.number; - coll.save(); -} - -export function getCurrentCollPrice(): BigDecimal { - const stethToken = Token.load(STETH_ADDRESS); - return stethToken!.lastPriceUSD!; -} diff --git a/subgraphs/ebtc/src/mapping/ActivePool.ts b/subgraphs/ebtc/src/mapping/ActivePool.ts index 9c82445483..2bec98076f 100644 --- a/subgraphs/ebtc/src/mapping/ActivePool.ts +++ b/subgraphs/ebtc/src/mapping/ActivePool.ts @@ -2,26 +2,37 @@ import { ActivePoolCollBalanceUpdated, ActivePoolEBTCDebtUpdated, } from "../../generated/ActivePool/ActivePool"; -// import { setMarketCollBalance, setMarketEBTCDebt } from "../entities/market"; +import { getDataManager, STETH_ADDRESS } from "../constants"; +import { TokenManager } from "../sdk/token"; /** * Total stETH collateral was updated - * - * @param event ActivePoolCollBalanceUpdated event + * @param event The ActivePoolCollBalanceUpdated event. */ export function handleActivePoolCollBalanceUpdated( event: ActivePoolCollBalanceUpdated ): void { - // setMarketCollBalance(event, event.params._coll); + const manager = getDataManager(event); + const stEthToken = new TokenManager(STETH_ADDRESS, event); + manager.updateMarketAndProtocolData( + stEthToken.getPriceUSD(), // inputTokenPriceUSD: BigDecimal, + event.params._coll // newInputTokenBalance: BigInt, + ); } /** - * EBTC debt was updated - * - * @param event ActivePoolEBTCDebtUpdated event + * Total eBTC debt was updated + * @param event The ActivePoolEBTCDebtUpdated event. */ export function handleActivePoolEBTCDebtUpdated( event: ActivePoolEBTCDebtUpdated ): void { - // setMarketEBTCDebt(event, event.params._EBTCDebt); + const manager = getDataManager(event); + const market = manager.getMarket(); + const stEthToken = new TokenManager(STETH_ADDRESS, event); + manager.updateMarketAndProtocolData( + stEthToken.getPriceUSD(), // inputTokenPriceUSD: BigDecimal, + market.inputTokenBalance, // newInputTokenBalance: BigInt, + event.params._EBTCDebt // newVariableBorrowBalance: BigInt | null = null, + ); } diff --git a/subgraphs/ebtc/src/mapping/PriceFeed.ts b/subgraphs/ebtc/src/mapping/PriceFeed.ts index a0631aee37..464ecdee0f 100644 --- a/subgraphs/ebtc/src/mapping/PriceFeed.ts +++ b/subgraphs/ebtc/src/mapping/PriceFeed.ts @@ -1,12 +1,37 @@ +import { Address } from "@graphprotocol/graph-ts"; import { LastGoodPriceUpdated } from "../../generated/PriceFeed/PriceFeed"; -import { setCurrentBtcPrice, setCurrentCollPrice } from "../entities/token"; +import { BTC_ADDRESS, STETH_ADDRESS } from "../constants"; +import { TokenManager } from "../sdk/token"; +import { getUsdPricePerToken } from "../prices"; +import { bigIntToBigDecimal } from "../sdk/util/numbers"; /** * Emitted whenever latest stETH/BTC price is fetched from oracle - * * @param event LastGoodPriceUpdated event */ export function handleLastGoodPriceUpdated(event: LastGoodPriceUpdated): void { - setCurrentBtcPrice(event.block); - setCurrentCollPrice(event.block, event.params._lastGoodPrice); + const BtcToken = new TokenManager( + BTC_ADDRESS, // tokenAddress: Bytes, + event, // event: ethereum.Event, + null // tokenType: string | null = null + ); + const btcPrice = getUsdPricePerToken( + Address.fromBytes(BTC_ADDRESS), // tokenAddr: Address, + event.block // block: ethereum.Block | null = null + ); + BtcToken.updatePrice( + btcPrice.usdPrice // newPriceUSD: BigDecimal + ); + + const stEthToken = new TokenManager( + STETH_ADDRESS, // tokenAddress: Bytes, + event, // event: ethereum.Event, + null // tokenType: string | null = null + ); + const stEthPrice = btcPrice.usdPrice.times( + bigIntToBigDecimal(event.params._lastGoodPrice) + ); + stEthToken.updatePrice( + stEthPrice // newPriceUSD: BigDecimal + ); } From 2be58643ec71c33e209cc2ba2946adeaf1e48d42 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 30 Jun 2023 17:16:13 +0200 Subject: [PATCH 21/52] chore: remove unused imports --- subgraphs/ebtc/src/mapping/CdpManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subgraphs/ebtc/src/mapping/CdpManager.ts b/subgraphs/ebtc/src/mapping/CdpManager.ts index 9d704f9ef1..67784f4d3b 100644 --- a/subgraphs/ebtc/src/mapping/CdpManager.ts +++ b/subgraphs/ebtc/src/mapping/CdpManager.ts @@ -3,7 +3,7 @@ import { ActivePool, CdpManagerAddressChanged, } from "../../generated/ActivePool/ActivePool"; -import { OracleSource, BIGDECIMAL_ZERO } from "../sdk/util/constants"; +import { OracleSource } from "../sdk/util/constants"; import { DataManager } from "../sdk/manager"; import { ACTIVE_POOL, From 45db46e348b935d5454e818a3cb321c294dcd1b5 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 30 Jun 2023 17:27:02 +0200 Subject: [PATCH 22/52] refactor: move all erc20 interfaces to `PriceFeed` --- .../ebtc/config/templates/ebtc.template.yaml | 12 ++++-------- subgraphs/ebtc/src/sdk/token.ts | 6 +++--- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index 044208ade0..4f1fd7d48d 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -19,8 +19,6 @@ dataSources: abis: - name: CdpManager file: ./abis/CdpManager.json - - name: ERC20 - file: ./abis/ERC20.json eventHandlers: - event: ActivePoolAddressChanged(address) handler: handleSystemDeployed @@ -40,12 +38,6 @@ dataSources: abis: - name: ActivePool file: ./abis/ActivePool.json - - name: ERC20 - file: ./abis/ERC20.json - - name: ERC20NameBytes - file: ./abis/ERC20NameBytes.json - - name: ERC20SymbolBytes - file: ./abis/ERC20SymbolBytes.json eventHandlers: - event: ActivePoolCollBalanceUpdated(uint256) handler: handleActivePoolCollBalanceUpdated @@ -74,6 +66,10 @@ dataSources: # ERC20 - name: ERC20 file: ./abis/ERC20.json + - name: ERC20NameBytes + file: ./abis/ERC20NameBytes.json + - name: ERC20SymbolBytes + file: ./abis/ERC20SymbolBytes.json # Curve Contracts - name: CurvePool file: ./abis/Prices/Curve/Pool.json diff --git a/subgraphs/ebtc/src/sdk/token.ts b/subgraphs/ebtc/src/sdk/token.ts index 9e0fbc0c38..26e86c042d 100644 --- a/subgraphs/ebtc/src/sdk/token.ts +++ b/subgraphs/ebtc/src/sdk/token.ts @@ -1,6 +1,6 @@ -import { ERC20 } from "../../generated/ActivePool/ERC20"; -import { ERC20SymbolBytes } from "../../generated/ActivePool/ERC20SymbolBytes"; -import { ERC20NameBytes } from "../../generated/ActivePool/ERC20NameBytes"; +import { ERC20 } from "../../generated/PriceFeed/ERC20"; +import { ERC20SymbolBytes } from "../../generated/PriceFeed/ERC20SymbolBytes"; +import { ERC20NameBytes } from "../../generated/PriceFeed/ERC20NameBytes"; import { Address, BigDecimal, Bytes, ethereum } from "@graphprotocol/graph-ts"; import { RewardToken, Token } from "../../generated/schema"; import { From 4d38a32b0f3af63bc733194759a0f6d2bf60ba3a Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 30 Jun 2023 17:32:46 +0200 Subject: [PATCH 23/52] fix: correct name for protocol --- subgraphs/ebtc/src/constants.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subgraphs/ebtc/src/constants.mustache b/subgraphs/ebtc/src/constants.mustache index 61d7189b83..bcde33c020 100644 --- a/subgraphs/ebtc/src/constants.mustache +++ b/subgraphs/ebtc/src/constants.mustache @@ -49,7 +49,7 @@ export const LIQUIDATION_FEE = LIQUIDATION_FEE_PERCENT.div(BIGDECIMAL_HUNDRED); /////// -export const PROTOCOL = "Liquity"; +export const PROTOCOL = "BadgerDAO"; export const PROTOCOL_NAME = "eBTC Protocol"; export const PROTOCOL_SLUG = "ebtc"; export const PROTOCOL_NETWORK = {{ network.object }}; From 5ef84ccd4301000cfa26a16a8ca86fc43623cc78 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 5 Jul 2023 16:04:36 +0200 Subject: [PATCH 24/52] chore: clean up comments --- subgraphs/ebtc/src/mapping/ActivePool.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/subgraphs/ebtc/src/mapping/ActivePool.ts b/subgraphs/ebtc/src/mapping/ActivePool.ts index 2bec98076f..14adcb7fba 100644 --- a/subgraphs/ebtc/src/mapping/ActivePool.ts +++ b/subgraphs/ebtc/src/mapping/ActivePool.ts @@ -15,8 +15,8 @@ export function handleActivePoolCollBalanceUpdated( const manager = getDataManager(event); const stEthToken = new TokenManager(STETH_ADDRESS, event); manager.updateMarketAndProtocolData( - stEthToken.getPriceUSD(), // inputTokenPriceUSD: BigDecimal, - event.params._coll // newInputTokenBalance: BigInt, + stEthToken.getPriceUSD(), // inputTokenPriceUSD: BigDecimal + event.params._coll // newInputTokenBalance: BigInt ); } @@ -31,8 +31,8 @@ export function handleActivePoolEBTCDebtUpdated( const market = manager.getMarket(); const stEthToken = new TokenManager(STETH_ADDRESS, event); manager.updateMarketAndProtocolData( - stEthToken.getPriceUSD(), // inputTokenPriceUSD: BigDecimal, - market.inputTokenBalance, // newInputTokenBalance: BigInt, - event.params._EBTCDebt // newVariableBorrowBalance: BigInt | null = null, + stEthToken.getPriceUSD(), // inputTokenPriceUSD: BigDecimal + market.inputTokenBalance, // newInputTokenBalance: BigInt + event.params._EBTCDebt // newVariableBorrowBalance: BigInt | null = null ); } From c2b3977801cb30fcf55e07fe04d2e374a1410ed9 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 5 Jul 2023 16:26:42 +0200 Subject: [PATCH 25/52] chore: bump schema and sdk --- subgraphs/ebtc/schema.graphql | 24 +++++++++- subgraphs/ebtc/src/sdk/account.ts | 4 +- subgraphs/ebtc/src/sdk/manager.ts | 73 ++++++++++++++++++++++-------- subgraphs/ebtc/src/sdk/position.ts | 36 +++++++++++---- 4 files changed, 107 insertions(+), 30 deletions(-) diff --git a/subgraphs/ebtc/schema.graphql b/subgraphs/ebtc/schema.graphql index f4376f1c47..36254949db 100644 --- a/subgraphs/ebtc/schema.graphql +++ b/subgraphs/ebtc/schema.graphql @@ -1,5 +1,5 @@ # Subgraph Schema: Lending Protocol -# Version: 3.0.1 +# Version: 3.1.0 # See https://github.com/messari/subgraphs/blob/master/docs/SCHEMA.md for details enum Network { @@ -871,9 +871,18 @@ type Market @entity @regularPolling { " Amount of input tokens borrowed in this market using stable interest rates (in native terms) " stableBorrowedTokenBalance: BigInt + " Last updated timestamp of supply/borrow index. " + indexLastUpdatedTimestamp: BigInt + + " Index used by the protocol to calculate interest generated on the supply token (ie, liquidityIndex in Aave)" + supplyIndex: BigInt + " Allowed limit to how much of the underlying asset can be supplied to this market. " supplyCap: BigInt + " Index used by the protocol to calculate the interest paid on the borrowed token (ie, variableBorrowIndex in Aave))" + borrowIndex: BigInt + " Allowed limit for how much of the underlying asset can be borrowed from this market. " borrowCap: BigInt @@ -1493,6 +1502,9 @@ type Position @entity @regularPolling { " Token balance in this position, in native amounts " balance: BigInt! + " The token balance of this position without interest generated (Used to calculate interest generated on a position) " + principal: BigInt + " Number of deposits related to this position " depositCount: Int! @@ -1542,7 +1554,7 @@ type Position @entity @regularPolling { # for positions that are not moving. As we are only recording the balance # in token amounts instead of in USD, this will work well. # Note that we only take snapshot for open positions. -type PositionSnapshot @entity(immutable: true) @regularPolling { +type PositionSnapshot @entity(immutable: true) @hourlySnapshot { " { Position ID }-{ Transaction hash }-{ Log index } " id: ID! @@ -1572,6 +1584,14 @@ type PositionSnapshot @entity(immutable: true) @regularPolling { " Timestamp of this snapshot " timestamp: BigInt! + + ##### Interest Tracking Fields ##### + + " The principal value without interest accrued. Used to calculate interest per position. " + principal: BigInt + + " Base borrow OR supply index (based on the position side). Used to calculate interest across snapshots. " + index: BigInt } # Helper entity for calculating daily/hourly active users diff --git a/subgraphs/ebtc/src/sdk/account.ts b/subgraphs/ebtc/src/sdk/account.ts index 2016881f1f..9d2db80236 100644 --- a/subgraphs/ebtc/src/sdk/account.ts +++ b/subgraphs/ebtc/src/sdk/account.ts @@ -10,8 +10,8 @@ import { INT_ONE, INT_ZERO } from "./util/constants"; * - Making a position * - Making position snapshots * - * Schema Version: 3.0.1 - * SDK Version: 1.0.2 + * Schema Version: 3.1.0 + * SDK Version: 1.0.4 * Author(s): * - @dmelotik */ diff --git a/subgraphs/ebtc/src/sdk/manager.ts b/subgraphs/ebtc/src/sdk/manager.ts index a24ce2281a..697c90db90 100644 --- a/subgraphs/ebtc/src/sdk/manager.ts +++ b/subgraphs/ebtc/src/sdk/manager.ts @@ -32,6 +32,7 @@ import { BIGINT_ZERO, exponentToBigDecimal, FeeType, + insert, INT_ONE, INT_ZERO, PositionSide, @@ -41,7 +42,6 @@ import { } from "./util/constants"; import { SnapshotManager } from "./snapshots"; import { TokenManager } from "./token"; -import { insert } from "./util/constants"; import { PositionManager } from "./position"; /** @@ -51,8 +51,8 @@ import { PositionManager } from "./position"; * You can think of this as an abstraction so the developer doesn't * need to think about all of the detailed storage changes that occur. * - * Schema Version: 3.0.1 - * SDK Version: 1.0.2 + * Schema Version: 3.1.0 + * SDK Version: 1.0.4 * Author(s): * - @dmelotik */ @@ -88,6 +88,7 @@ export class DataManager { private inputToken!: TokenManager; private oracle!: Oracle; private snapshots!: SnapshotManager; + private newMarket: boolean = false; constructor( marketID: Bytes, @@ -151,6 +152,8 @@ export class DataManager { _market.borrowingPositionCount = INT_ZERO; _market.save(); + this.newMarket = true; + // add to market list this.getOrAddMarketToList(marketID); this.protocol.totalPoolCount += INT_ONE; @@ -227,6 +230,20 @@ export class DataManager { return this.market; } + isNewMarket(): boolean { + return this.newMarket; + } + + saveMarket(): void { + this.market.save(); + } + + // only update when updating the supply/borrow index + updateIndexLastMarketTimestamp(): void { + this.market.indexLastUpdatedTimestamp = this.event.block.timestamp; + this.saveMarket(); + } + getProtocol(): LendingProtocol { return this.protocol; } @@ -292,7 +309,7 @@ export class DataManager { marketRates.push(interestRateID); } this.market.rates = marketRates; - this.market.save(); + this.saveMarket(); return rate; } @@ -340,7 +357,7 @@ export class DataManager { if (isMarket) { this.market.revenueDetail = details.id; - this.market.save(); + this.saveMarket(); } else { this.protocol.revenueDetail = details.id; this.protocol.save(); @@ -360,7 +377,8 @@ export class DataManager { amount: BigInt, amountUSD: BigDecimal, newBalance: BigInt, - interestType: string | null = null + interestType: string | null = null, + principal: BigInt | null = null ): Deposit { const depositor = new AccountManager(account); if (depositor.isNewUser()) { @@ -379,7 +397,8 @@ export class DataManager { this.protocol, newBalance, TransactionType.DEPOSIT, - this.market.inputTokenPriceUSD + this.market.inputTokenPriceUSD, + principal ); const deposit = new Deposit( @@ -415,7 +434,8 @@ export class DataManager { amount: BigInt, amountUSD: BigDecimal, newBalance: BigInt, - interestType: string | null = null + interestType: string | null = null, + principal: BigInt | null = null ): Withdraw | null { const withdrawer = new AccountManager(account); if (withdrawer.isNewUser()) { @@ -433,7 +453,8 @@ export class DataManager { this.protocol, newBalance, TransactionType.WITHDRAW, - this.market.inputTokenPriceUSD + this.market.inputTokenPriceUSD, + principal ); const positionID = position.getPositionID(); if (!positionID) { @@ -478,7 +499,8 @@ export class DataManager { amountUSD: BigDecimal, newBalance: BigInt, tokenPriceUSD: BigDecimal, // used for different borrow token in CDP - interestType: string | null = null + interestType: string | null = null, + principal: BigInt | null = null ): Borrow { const borrower = new AccountManager(account); if (borrower.isNewUser()) { @@ -497,7 +519,8 @@ export class DataManager { this.protocol, newBalance, TransactionType.BORROW, - tokenPriceUSD + tokenPriceUSD, + principal ); const borrow = new Borrow( @@ -534,7 +557,8 @@ export class DataManager { amountUSD: BigDecimal, newBalance: BigInt, tokenPriceUSD: BigDecimal, // used for different borrow token in CDP - interestType: string | null = null + interestType: string | null = null, + principal: BigInt | null = null ): Repay | null { const repayer = new AccountManager(account); if (repayer.isNewUser()) { @@ -552,7 +576,8 @@ export class DataManager { this.protocol, newBalance, TransactionType.REPAY, - tokenPriceUSD + tokenPriceUSD, + principal ); const positionID = position.getPositionID(); if (!positionID) { @@ -846,7 +871,7 @@ export class DataManager { this.market.rewardTokens = rewardTokens; this.market.rewardTokenEmissionsAmount = rewardTokenEmissionsAmount; this.market.rewardTokenEmissionsUSD = rewardTokenEmissionsUSD; - this.market.save(); + this.saveMarket(); } // used to update tvl, borrow balance, reserves, etc. in market and protocol @@ -896,7 +921,7 @@ export class DataManager { .times(inputTokenPriceUSD); this.market.totalDepositBalanceUSD = this.market.totalValueLockedUSD; this.market.totalBorrowBalanceUSD = totalBorrowed.times(inputTokenPriceUSD); - this.market.save(); + this.saveMarket(); let totalValueLockedUSD = BIGDECIMAL_ZERO; let totalBorrowBalanceUSD = BIGDECIMAL_ZERO; @@ -922,6 +947,18 @@ export class DataManager { this.protocol.save(); } + updateSupplyIndex(supplyIndex: BigInt): void { + this.market.supplyIndex = supplyIndex; + this.market.indexLastUpdatedTimestamp = this.event.block.timestamp; + this.saveMarket(); + } + + updateBorrowIndex(borrowIndex: BigInt): void { + this.market.borrowIndex = borrowIndex; + this.market.indexLastUpdatedTimestamp = this.event.block.timestamp; + this.saveMarket(); + } + // // // Update the protocol revenue @@ -987,7 +1024,7 @@ export class DataManager { this.market.cumulativeProtocolSideRevenueUSD.plus(protocolRevenueDelta); this.market.cumulativeSupplySideRevenueUSD = this.market.cumulativeSupplySideRevenueUSD.plus(supplyRevenueDelta); - this.market.save(); + this.saveMarket(); // update protocol this.protocol.cumulativeTotalRevenueUSD = @@ -1092,7 +1129,7 @@ export class DataManager { ); this.protocol.save(); - this.market.save(); + this.saveMarket(); // update the snapshots in their respective class this.snapshots.updateUsageData(transactionType, account); @@ -1154,7 +1191,7 @@ export class DataManager { this.market.transactionCount += INT_ONE; this.protocol.save(); - this.market.save(); + this.saveMarket(); // update the snapshots in their respective class this.snapshots.updateTransactionData(transactionType, amount, amountUSD); diff --git a/subgraphs/ebtc/src/sdk/position.ts b/subgraphs/ebtc/src/sdk/position.ts index 8e777c89ad..72f565d0dd 100644 --- a/subgraphs/ebtc/src/sdk/position.ts +++ b/subgraphs/ebtc/src/sdk/position.ts @@ -18,6 +18,7 @@ import { exponentToBigDecimal, INT_ONE, INT_ZERO, + PositionSide, SECONDS_PER_DAY, TransactionType, } from "./util/constants"; @@ -28,8 +29,8 @@ import { TokenManager } from "./token"; * This file contains the PositionManager class, which is used to * make changes to a given position. * - * Schema Version: 3.0.1 - * SDK Version: 1.0.2 + * Schema Version: 3.1.0 + * SDK Version: 1.0.4 * Author(s): * - @dmelotik */ @@ -80,15 +81,15 @@ export class PositionManager { setCollateral(isCollateral: boolean): void { if (this.position) { - this.position.isCollateral = isCollateral; - this.position.save(); + this.position!.isCollateral = isCollateral; + this.position!.save(); } } setIsolation(isIsolated: boolean): void { if (this.position) { - this.position.isIsolated = isIsolated; - this.position.save(); + this.position!.isIsolated = isIsolated; + this.position!.save(); } } @@ -98,7 +99,8 @@ export class PositionManager { protocol: LendingProtocol, newBalance: BigInt, transactionType: string, - priceUSD: BigDecimal + priceUSD: BigDecimal, + principal: BigInt | null = null ): void { let positionCounter = _PositionCounter.load(this.counterID); if (!positionCounter) { @@ -117,6 +119,7 @@ export class PositionManager { // update existing position position = position!; position.balance = newBalance; + if (principal) position.principal = principal; if (transactionType == TransactionType.DEPOSIT) { position.depositCount += INT_ONE; } else if (transactionType == TransactionType.BORROW) { @@ -146,6 +149,7 @@ export class PositionManager { position.type = this.interestType; } position.balance = newBalance; + if (principal) position.principal = principal; position.depositCount = INT_ZERO; position.withdrawCount = INT_ZERO; position.borrowCount = INT_ZERO; @@ -207,7 +211,8 @@ export class PositionManager { protocol: LendingProtocol, newBalance: BigInt, transactionType: string, - priceUSD: BigDecimal + priceUSD: BigDecimal, + principal: BigInt | null = null ): void { const positionCounter = _PositionCounter.load(this.counterID); if (!positionCounter) { @@ -226,6 +231,7 @@ export class PositionManager { } position.balance = newBalance; + if (principal) position.principal = principal; if (transactionType == TransactionType.WITHDRAW) { position.withdrawCount += INT_ONE; @@ -303,6 +309,20 @@ export class PositionManager { .times(priceUSD); snapshot.blockNumber = event.block.number; snapshot.timestamp = event.block.timestamp; + + if (this.position!.principal) snapshot.principal = this.position!.principal; + if ( + this.market.borrowIndex && + this.position!.side == PositionSide.BORROWER + ) { + snapshot.index = this.market.borrowIndex; + } else if ( + this.market.supplyIndex && + this.position!.side == PositionSide.COLLATERAL + ) { + snapshot.index = this.market.supplyIndex; + } + snapshot.save(); } From e2f84c7aec5d16c0a80cdb15c5f70bb5e989285f Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 5 Jul 2023 16:28:18 +0200 Subject: [PATCH 26/52] feat: handle `CdpUpdated` --- .../ebtc/config/templates/ebtc.template.yaml | 2 + subgraphs/ebtc/src/mapping/CdpManager.ts | 59 +++++++++++++++---- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index 4f1fd7d48d..448204a18a 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -22,6 +22,8 @@ dataSources: eventHandlers: - event: ActivePoolAddressChanged(address) handler: handleSystemDeployed + - event: CdpUpdated(indexed bytes32,indexed address,uint256,uint256,uint256,uint256,uint256,uint8) + handler: handleCdpUpdated - name: ActivePool kind: ethereum/contract network: "{{ network.slug }}" diff --git a/subgraphs/ebtc/src/mapping/CdpManager.ts b/subgraphs/ebtc/src/mapping/CdpManager.ts index 67784f4d3b..1077a21174 100644 --- a/subgraphs/ebtc/src/mapping/CdpManager.ts +++ b/subgraphs/ebtc/src/mapping/CdpManager.ts @@ -3,16 +3,24 @@ import { ActivePool, CdpManagerAddressChanged, } from "../../generated/ActivePool/ActivePool"; -import { OracleSource } from "../sdk/util/constants"; -import { DataManager } from "../sdk/manager"; +import { CdpUpdated } from "../../generated/CdpManager/CdpManager"; +import { AccountManager } from "../sdk/account"; +import { PositionManager } from "../sdk/position"; +import { TokenManager } from "../sdk/token"; +import { + OracleSource, + PositionSide, + TransactionType, +} from "../sdk/util/constants"; import { ACTIVE_POOL, EBTC_ADDRESS, LIQUIDATION_FEE_PERCENT, MAXIMUM_LTV, PRICE_FEED, - STETH_ADDRESS, getProtocolData, + getDataManager, + STETH_ADDRESS, } from "../constants"; /** @@ -24,6 +32,7 @@ import { export function handleSystemDeployed(event: CdpManagerAddressChanged): void { const activePool = ActivePool.bind(event.address); if (activePool._address != ACTIVE_POOL) { + // quick check to make sure our configurations.json is correct log.error( "deployed ActivePool address {} does not match expected address", [event.address.toHexString()] @@ -31,16 +40,10 @@ export function handleSystemDeployed(event: CdpManagerAddressChanged): void { return; } - const manager = new DataManager( - activePool._address, // marketID: Bytes - STETH_ADDRESS, // inputToken: Bytes - event, // event: ethereum.Event - getProtocolData() // protocolData: ProtocolData - ); - - const market = manager.getMarket(); + const dataManager = getDataManager(event); // update market with ebtc specifics + const market = dataManager.getMarket(); market.canBorrowFrom = true; market.maximumLTV = MAXIMUM_LTV; market.liquidationThreshold = MAXIMUM_LTV; @@ -48,13 +51,43 @@ export function handleSystemDeployed(event: CdpManagerAddressChanged): void { market.borrowedToken = EBTC_ADDRESS; market.save(); - const lendingProtocol = manager.getOrCreateLendingProtocol( + const lendingProtocol = dataManager.getOrCreateLendingProtocol( getProtocolData() // data: ProtocolData ); - const oracle = manager.getOrCreateOracle( + const oracle = dataManager.getOrCreateOracle( Address.fromBytes(PRICE_FEED), // oracleAddress: Address false, // isUSD: boolean OracleSource.CHAINLINK // source?: string ); } + +/** + * Make necessary adjustments to the system when a CDP changes. + * @param event The event emitted by the CdpManager when a CDP changes. + */ +export function handleCdpUpdated(event: CdpUpdated): void { + const dataManager = getDataManager(event); + const accountManager = new AccountManager(event.params._borrower); + const positionManager = new PositionManager( + accountManager.getAccount(), // account: Account + dataManager.getMarket(), // market: Market + PositionSide.COLLATERAL //side + ); + const stEthTokenManager = new TokenManager(STETH_ADDRESS, event); + + // TODO: there is also a subtractPosition method + positionManager.addPosition( + event, // event: ethereum.Event + STETH_ADDRESS, // asset: Bytes + dataManager.getOrCreateLendingProtocol(getProtocolData()), // protocol: LendingProtocol + event.params._coll, // newBalance: BigInt + // TODO: obivously the transaction type needs to be determined properly + TransactionType.BORROW, // transactionType: string + stEthTokenManager.getPriceUSD() // priceUSD: BigDecimal + ); + if (positionManager.getPositionID()) { + positionManager.setCollateral(true); + positionManager.setIsolation(true); + } +} From 9fe2cac6031280cd9a0bb4197da9eb4283580bbe Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 5 Jul 2023 19:03:05 +0200 Subject: [PATCH 27/52] docs: add query that returns most important fields --- subgraphs/ebtc/QUERY.gql | 72 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 subgraphs/ebtc/QUERY.gql diff --git a/subgraphs/ebtc/QUERY.gql b/subgraphs/ebtc/QUERY.gql new file mode 100644 index 0000000000..993a2d4702 --- /dev/null +++ b/subgraphs/ebtc/QUERY.gql @@ -0,0 +1,72 @@ +{ + protocols { + borrowerPermissionType + collateralizationType + cumulativeProtocolSideRevenueUSD + cumulativeSupplySideRevenueUSD + cumulativeTotalRevenueUSD + cumulativeUniqueUsers + id + lenderPermissionType + lendingType + methodologyVersion + name + network + poolCreatorPermissionType + protocol + protocolControlledValueUSD + riskType + schemaVersion + slug + subgraphVersion + totalPoolCount + totalValueLockedUSD + type + } + tokens { + decimals + id + lastPriceBlockNumber + lastPriceUSD + name + symbol + type + } + accounts { + borrowCount + closedPositionCount + depositCount + flashloanCount + id + liquidateCount + liquidationCount + openPositionCount + positionCount + receivedCount + repayCount + rewardsClaimedUSD + transferredCount + withdrawCount + } + positions { + balance + blockNumberClosed + blockNumberOpened + borrowCount + depositCount + hashClosed + hashOpened + id + isCollateral + isIsolated + liquidationCount + receivedCount + repayCount + side + timestampClosed + timestampOpened + transferredCount + type + withdrawCount + } +} From 3aeb3408630a2380fc3f8a785590a88a3a5a3e8c Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 5 Jul 2023 22:51:41 +0200 Subject: [PATCH 28/52] fix: erc20 interface for prices is different from erc20 --- subgraphs/ebtc/abis/ERC20.json | 926 +++--------------- subgraphs/ebtc/abis/Prices/ERC20.json | 828 ++++++++++++++++ .../ebtc/config/templates/ebtc.template.yaml | 2 + subgraphs/ebtc/src/sdk/token.ts | 6 +- 4 files changed, 993 insertions(+), 769 deletions(-) create mode 100644 subgraphs/ebtc/abis/Prices/ERC20.json diff --git a/subgraphs/ebtc/abis/ERC20.json b/subgraphs/ebtc/abis/ERC20.json index 5c47f76a53..405d6b3648 100644 --- a/subgraphs/ebtc/abis/ERC20.json +++ b/subgraphs/ebtc/abis/ERC20.json @@ -1,828 +1,222 @@ [ { - "name": "Transfer", - "inputs": [ - { "type": "address", "name": "sender", "indexed": true }, - { "type": "address", "name": "receiver", "indexed": true }, - { "type": "uint256", "name": "value", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "Approval", - "inputs": [ - { "type": "address", "name": "owner", "indexed": true }, - { "type": "address", "name": "spender", "indexed": true }, - { "type": "uint256", "name": "value", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "StrategyAdded", - "inputs": [ - { "type": "address", "name": "strategy", "indexed": true }, - { "type": "uint256", "name": "debtRatio", "indexed": false }, - { "type": "uint256", "name": "rateLimit", "indexed": false }, - { "type": "uint256", "name": "performanceFee", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "StrategyReported", - "inputs": [ - { "type": "address", "name": "strategy", "indexed": true }, - { "type": "uint256", "name": "gain", "indexed": false }, - { "type": "uint256", "name": "loss", "indexed": false }, - { "type": "uint256", "name": "totalGain", "indexed": false }, - { "type": "uint256", "name": "totalLoss", "indexed": false }, - { "type": "uint256", "name": "totalDebt", "indexed": false }, - { "type": "uint256", "name": "debtAdded", "indexed": false }, - { "type": "uint256", "name": "debtRatio", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdateGovernance", - "inputs": [{ "type": "address", "name": "governance", "indexed": false }], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdateManagement", - "inputs": [{ "type": "address", "name": "management", "indexed": false }], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdateGuestList", - "inputs": [{ "type": "address", "name": "guestList", "indexed": false }], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdateRewards", - "inputs": [{ "type": "address", "name": "rewards", "indexed": false }], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdateDepositLimit", - "inputs": [{ "type": "uint256", "name": "depositLimit", "indexed": false }], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdatePerformanceFee", - "inputs": [ - { "type": "uint256", "name": "performanceFee", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdateManagementFee", - "inputs": [ - { "type": "uint256", "name": "managementFee", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdateGuardian", - "inputs": [{ "type": "address", "name": "guardian", "indexed": false }], - "anonymous": false, - "type": "event" - }, - { - "name": "EmergencyShutdown", - "inputs": [{ "type": "bool", "name": "active", "indexed": false }], - "anonymous": false, - "type": "event" - }, - { - "name": "UpdateWithdrawalQueue", - "inputs": [{ "type": "address[20]", "name": "queue", "indexed": false }], - "anonymous": false, - "type": "event" - }, - { - "name": "StrategyUpdateDebtRatio", - "inputs": [ - { "type": "address", "name": "strategy", "indexed": true }, - { "type": "uint256", "name": "debtRatio", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "StrategyUpdateRateLimit", - "inputs": [ - { "type": "address", "name": "strategy", "indexed": true }, - { "type": "uint256", "name": "rateLimit", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "StrategyUpdatePerformanceFee", - "inputs": [ - { "type": "address", "name": "strategy", "indexed": true }, - { "type": "uint256", "name": "performanceFee", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "StrategyMigrated", - "inputs": [ - { "type": "address", "name": "oldVersion", "indexed": true }, - { "type": "address", "name": "newVersion", "indexed": true } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "StrategyRevoked", - "inputs": [{ "type": "address", "name": "strategy", "indexed": true }], - "anonymous": false, - "type": "event" - }, - { - "name": "StrategyRemovedFromQueue", - "inputs": [{ "type": "address", "name": "strategy", "indexed": true }], - "anonymous": false, - "type": "event" - }, - { - "name": "StrategyAddedToQueue", - "inputs": [{ "type": "address", "name": "strategy", "indexed": true }], - "anonymous": false, - "type": "event" - }, - { - "name": "initialize", - "outputs": [], - "inputs": [ - { "type": "address", "name": "token" }, - { "type": "address", "name": "governance" }, - { "type": "address", "name": "rewards" }, - { "type": "string", "name": "nameOverride" }, - { "type": "string", "name": "symbolOverride" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "initialize", - "outputs": [], - "inputs": [ - { "type": "address", "name": "token" }, - { "type": "address", "name": "governance" }, - { "type": "address", "name": "rewards" }, - { "type": "string", "name": "nameOverride" }, - { "type": "string", "name": "symbolOverride" }, - { "type": "address", "name": "guardian" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "apiVersion", - "outputs": [{ "type": "string", "name": "" }], - "inputs": [], - "stateMutability": "pure", - "type": "function", - "gas": 4519 - }, - { - "name": "setName", - "outputs": [], - "inputs": [{ "type": "string", "name": "name" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 107017 - }, - { - "name": "setSymbol", - "outputs": [], - "inputs": [{ "type": "string", "name": "symbol" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 71867 - }, - { - "name": "setGovernance", - "outputs": [], - "inputs": [{ "type": "address", "name": "governance" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 36338 - }, - { - "name": "acceptGovernance", - "outputs": [], + "constant": true, "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "gas": 37610 - }, - { - "name": "setManagement", - "outputs": [], - "inputs": [{ "type": "address", "name": "management" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 37748 - }, - { - "name": "setGuestList", - "outputs": [], - "inputs": [{ "type": "address", "name": "guestList" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 37778 - }, - { - "name": "setRewards", - "outputs": [], - "inputs": [{ "type": "address", "name": "rewards" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 37808 - }, - { - "name": "setDepositLimit", - "outputs": [], - "inputs": [{ "type": "uint256", "name": "limit" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 37738 - }, - { - "name": "setPerformanceFee", - "outputs": [], - "inputs": [{ "type": "uint256", "name": "fee" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 37872 - }, - { - "name": "setManagementFee", - "outputs": [], - "inputs": [{ "type": "uint256", "name": "fee" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 37902 - }, - { - "name": "setGuardian", - "outputs": [], - "inputs": [{ "type": "address", "name": "guardian" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 39146 - }, - { - "name": "setEmergencyShutdown", - "outputs": [], - "inputs": [{ "type": "bool", "name": "active" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 39217 - }, - { - "name": "setWithdrawalQueue", - "outputs": [], - "inputs": [{ "type": "address[20]", "name": "queue" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 763893 - }, - { - "name": "transfer", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [ - { "type": "address", "name": "receiver" }, - { "type": "uint256", "name": "amount" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 76733 - }, - { - "name": "transferFrom", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [ - { "type": "address", "name": "sender" }, - { "type": "address", "name": "receiver" }, - { "type": "uint256", "name": "amount" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 116496 - }, - { - "name": "approve", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [ - { "type": "address", "name": "spender" }, - { "type": "uint256", "name": "amount" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 38244 - }, - { - "name": "increaseAllowance", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [ - { "type": "address", "name": "spender" }, - { "type": "uint256", "name": "amount" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 40285 - }, - { - "name": "decreaseAllowance", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [ - { "type": "address", "name": "spender" }, - { "type": "uint256", "name": "amount" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 40309 - }, - { - "name": "permit", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [ - { "type": "address", "name": "owner" }, - { "type": "address", "name": "spender" }, - { "type": "uint256", "name": "amount" }, - { "type": "uint256", "name": "expiry" }, - { "type": "bytes", "name": "signature" } + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 81237 - }, - { - "name": "totalAssets", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], + "payable": false, "stateMutability": "view", - "type": "function", - "gas": 4123 - }, - { - "name": "deposit", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "deposit", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "uint256", "name": "_amount" }], - "stateMutability": "nonpayable", "type": "function" }, { - "name": "deposit", - "outputs": [{ "type": "uint256", "name": "" }], + "constant": false, "inputs": [ - { "type": "uint256", "name": "_amount" }, - { "type": "address", "name": "recipient" } + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "name": "maxAvailableShares", - "outputs": [{ "type": "uint256", "name": "" }], + "constant": true, "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, "stateMutability": "view", - "type": "function", - "gas": 364171 - }, - { - "name": "withdraw", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "withdraw", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "uint256", "name": "maxShares" }], - "stateMutability": "nonpayable", "type": "function" }, { - "name": "withdraw", - "outputs": [{ "type": "uint256", "name": "" }], + "constant": false, "inputs": [ - { "type": "uint256", "name": "maxShares" }, - { "type": "address", "name": "recipient" } + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "withdraw", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256", "name": "maxShares" }, - { "type": "address", "name": "recipient" }, - { "type": "uint256", "name": "maxLoss" } + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } ], + "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "name": "pricePerShare", - "outputs": [{ "type": "uint256", "name": "" }], + "constant": true, "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 12412 - }, - { - "name": "addStrategy", - "outputs": [], - "inputs": [ - { "type": "address", "name": "strategy" }, - { "type": "uint256", "name": "debtRatio" }, - { "type": "uint256", "name": "rateLimit" }, - { "type": "uint256", "name": "performanceFee" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 1450351 - }, - { - "name": "updateStrategyDebtRatio", - "outputs": [], - "inputs": [ - { "type": "address", "name": "strategy" }, - { "type": "uint256", "name": "debtRatio" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 115316 - }, - { - "name": "updateStrategyRateLimit", - "outputs": [], - "inputs": [ - { "type": "address", "name": "strategy" }, - { "type": "uint256", "name": "rateLimit" } + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 41467 + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "name": "updateStrategyPerformanceFee", - "outputs": [], + "constant": true, "inputs": [ - { "type": "address", "name": "strategy" }, - { "type": "uint256", "name": "performanceFee" } + { + "name": "_owner", + "type": "address" + } ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 41344 - }, - { - "name": "migrateStrategy", - "outputs": [], - "inputs": [ - { "type": "address", "name": "oldVersion" }, - { "type": "address", "name": "newVersion" } + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 1105801 - }, - { - "name": "revokeStrategy", - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "revokeStrategy", - "outputs": [], - "inputs": [{ "type": "address", "name": "strategy" }], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "addStrategyToQueue", - "outputs": [], - "inputs": [{ "type": "address", "name": "strategy" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 1196920 - }, - { - "name": "removeStrategyFromQueue", - "outputs": [], - "inputs": [{ "type": "address", "name": "strategy" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 23091666 - }, - { - "name": "debtOutstanding", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "name": "debtOutstanding", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "address", "name": "strategy" }], - "stateMutability": "view", - "type": "function" - }, - { - "name": "creditAvailable", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], + "payable": false, "stateMutability": "view", "type": "function" }, { - "name": "creditAvailable", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "address", "name": "strategy" }], - "stateMutability": "view", - "type": "function" - }, - { - "name": "availableDepositLimit", - "outputs": [{ "type": "uint256", "name": "" }], + "constant": true, "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 9808 - }, - { - "name": "expectedReturn", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "name": "expectedReturn", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "address", "name": "strategy" }], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, "stateMutability": "view", "type": "function" }, { - "name": "report", - "outputs": [{ "type": "uint256", "name": "" }], + "constant": false, "inputs": [ - { "type": "uint256", "name": "gain" }, - { "type": "uint256", "name": "loss" }, - { "type": "uint256", "name": "_debtPayment" } + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 937520 - }, - { - "name": "sweep", - "outputs": [], - "inputs": [{ "type": "address", "name": "token" }], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "sweep", - "outputs": [], - "inputs": [ - { "type": "address", "name": "token" }, - { "type": "uint256", "name": "amount" } + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } ], + "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "name": "name", - "outputs": [{ "type": "string", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 9053 - }, - { - "name": "symbol", - "outputs": [{ "type": "string", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 8106 - }, - { - "name": "decimals", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2711 - }, - { - "name": "balanceOf", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "address", "name": "arg0" }], - "stateMutability": "view", - "type": "function", - "gas": 2956 - }, - { - "name": "allowance", - "outputs": [{ "type": "uint256", "name": "" }], + "constant": true, "inputs": [ - { "type": "address", "name": "arg0" }, - { "type": "address", "name": "arg1" } + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } ], - "stateMutability": "view", - "type": "function", - "gas": 3201 - }, - { - "name": "totalSupply", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2801 - }, - { - "name": "token", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2831 - }, - { - "name": "governance", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2861 - }, - { - "name": "management", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2891 - }, - { - "name": "guardian", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2921 - }, - { - "name": "guestList", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2951 - }, - { - "name": "strategies", + "name": "allowance", "outputs": [ - { "type": "uint256", "name": "performanceFee" }, - { "type": "uint256", "name": "activation" }, - { "type": "uint256", "name": "debtRatio" }, - { "type": "uint256", "name": "rateLimit" }, - { "type": "uint256", "name": "lastReport" }, - { "type": "uint256", "name": "totalDebt" }, - { "type": "uint256", "name": "totalGain" }, - { "type": "uint256", "name": "totalLoss" } + { + "name": "", + "type": "uint256" + } ], - "inputs": [{ "type": "address", "name": "arg0" }], - "stateMutability": "view", - "type": "function", - "gas": 10322 - }, - { - "name": "withdrawalQueue", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [{ "type": "uint256", "name": "arg0" }], - "stateMutability": "view", - "type": "function", - "gas": 3120 - }, - { - "name": "emergencyShutdown", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 3041 - }, - { - "name": "depositLimit", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 3071 - }, - { - "name": "debtRatio", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 3101 - }, - { - "name": "totalDebt", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 3131 - }, - { - "name": "lastReport", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 3161 - }, - { - "name": "activation", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], + "payable": false, "stateMutability": "view", - "type": "function", - "gas": 3191 - }, - { - "name": "rewards", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 3221 - }, - { - "name": "managementFee", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 3251 + "type": "function" }, { - "name": "performanceFee", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 3281 + "payable": true, + "stateMutability": "payable", + "type": "fallback" }, { - "name": "nonces", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "address", "name": "arg0" }], - "stateMutability": "view", - "type": "function", - "gas": 3526 + "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" }, { - "name": "DOMAIN_SEPARATOR", - "outputs": [{ "type": "bytes32", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 3341 + "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" } ] diff --git a/subgraphs/ebtc/abis/Prices/ERC20.json b/subgraphs/ebtc/abis/Prices/ERC20.json new file mode 100644 index 0000000000..5c47f76a53 --- /dev/null +++ b/subgraphs/ebtc/abis/Prices/ERC20.json @@ -0,0 +1,828 @@ +[ + { + "name": "Transfer", + "inputs": [ + { "type": "address", "name": "sender", "indexed": true }, + { "type": "address", "name": "receiver", "indexed": true }, + { "type": "uint256", "name": "value", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "Approval", + "inputs": [ + { "type": "address", "name": "owner", "indexed": true }, + { "type": "address", "name": "spender", "indexed": true }, + { "type": "uint256", "name": "value", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyAdded", + "inputs": [ + { "type": "address", "name": "strategy", "indexed": true }, + { "type": "uint256", "name": "debtRatio", "indexed": false }, + { "type": "uint256", "name": "rateLimit", "indexed": false }, + { "type": "uint256", "name": "performanceFee", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyReported", + "inputs": [ + { "type": "address", "name": "strategy", "indexed": true }, + { "type": "uint256", "name": "gain", "indexed": false }, + { "type": "uint256", "name": "loss", "indexed": false }, + { "type": "uint256", "name": "totalGain", "indexed": false }, + { "type": "uint256", "name": "totalLoss", "indexed": false }, + { "type": "uint256", "name": "totalDebt", "indexed": false }, + { "type": "uint256", "name": "debtAdded", "indexed": false }, + { "type": "uint256", "name": "debtRatio", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateGovernance", + "inputs": [{ "type": "address", "name": "governance", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateManagement", + "inputs": [{ "type": "address", "name": "management", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateGuestList", + "inputs": [{ "type": "address", "name": "guestList", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateRewards", + "inputs": [{ "type": "address", "name": "rewards", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateDepositLimit", + "inputs": [{ "type": "uint256", "name": "depositLimit", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdatePerformanceFee", + "inputs": [ + { "type": "uint256", "name": "performanceFee", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateManagementFee", + "inputs": [ + { "type": "uint256", "name": "managementFee", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateGuardian", + "inputs": [{ "type": "address", "name": "guardian", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "EmergencyShutdown", + "inputs": [{ "type": "bool", "name": "active", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "UpdateWithdrawalQueue", + "inputs": [{ "type": "address[20]", "name": "queue", "indexed": false }], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyUpdateDebtRatio", + "inputs": [ + { "type": "address", "name": "strategy", "indexed": true }, + { "type": "uint256", "name": "debtRatio", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyUpdateRateLimit", + "inputs": [ + { "type": "address", "name": "strategy", "indexed": true }, + { "type": "uint256", "name": "rateLimit", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyUpdatePerformanceFee", + "inputs": [ + { "type": "address", "name": "strategy", "indexed": true }, + { "type": "uint256", "name": "performanceFee", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyMigrated", + "inputs": [ + { "type": "address", "name": "oldVersion", "indexed": true }, + { "type": "address", "name": "newVersion", "indexed": true } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyRevoked", + "inputs": [{ "type": "address", "name": "strategy", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyRemovedFromQueue", + "inputs": [{ "type": "address", "name": "strategy", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "name": "StrategyAddedToQueue", + "inputs": [{ "type": "address", "name": "strategy", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "name": "initialize", + "outputs": [], + "inputs": [ + { "type": "address", "name": "token" }, + { "type": "address", "name": "governance" }, + { "type": "address", "name": "rewards" }, + { "type": "string", "name": "nameOverride" }, + { "type": "string", "name": "symbolOverride" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "initialize", + "outputs": [], + "inputs": [ + { "type": "address", "name": "token" }, + { "type": "address", "name": "governance" }, + { "type": "address", "name": "rewards" }, + { "type": "string", "name": "nameOverride" }, + { "type": "string", "name": "symbolOverride" }, + { "type": "address", "name": "guardian" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "apiVersion", + "outputs": [{ "type": "string", "name": "" }], + "inputs": [], + "stateMutability": "pure", + "type": "function", + "gas": 4519 + }, + { + "name": "setName", + "outputs": [], + "inputs": [{ "type": "string", "name": "name" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 107017 + }, + { + "name": "setSymbol", + "outputs": [], + "inputs": [{ "type": "string", "name": "symbol" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 71867 + }, + { + "name": "setGovernance", + "outputs": [], + "inputs": [{ "type": "address", "name": "governance" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 36338 + }, + { + "name": "acceptGovernance", + "outputs": [], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37610 + }, + { + "name": "setManagement", + "outputs": [], + "inputs": [{ "type": "address", "name": "management" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37748 + }, + { + "name": "setGuestList", + "outputs": [], + "inputs": [{ "type": "address", "name": "guestList" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37778 + }, + { + "name": "setRewards", + "outputs": [], + "inputs": [{ "type": "address", "name": "rewards" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37808 + }, + { + "name": "setDepositLimit", + "outputs": [], + "inputs": [{ "type": "uint256", "name": "limit" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37738 + }, + { + "name": "setPerformanceFee", + "outputs": [], + "inputs": [{ "type": "uint256", "name": "fee" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37872 + }, + { + "name": "setManagementFee", + "outputs": [], + "inputs": [{ "type": "uint256", "name": "fee" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 37902 + }, + { + "name": "setGuardian", + "outputs": [], + "inputs": [{ "type": "address", "name": "guardian" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 39146 + }, + { + "name": "setEmergencyShutdown", + "outputs": [], + "inputs": [{ "type": "bool", "name": "active" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 39217 + }, + { + "name": "setWithdrawalQueue", + "outputs": [], + "inputs": [{ "type": "address[20]", "name": "queue" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 763893 + }, + { + "name": "transfer", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "address", "name": "receiver" }, + { "type": "uint256", "name": "amount" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 76733 + }, + { + "name": "transferFrom", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "address", "name": "sender" }, + { "type": "address", "name": "receiver" }, + { "type": "uint256", "name": "amount" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 116496 + }, + { + "name": "approve", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "address", "name": "spender" }, + { "type": "uint256", "name": "amount" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 38244 + }, + { + "name": "increaseAllowance", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "address", "name": "spender" }, + { "type": "uint256", "name": "amount" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 40285 + }, + { + "name": "decreaseAllowance", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "address", "name": "spender" }, + { "type": "uint256", "name": "amount" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 40309 + }, + { + "name": "permit", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [ + { "type": "address", "name": "owner" }, + { "type": "address", "name": "spender" }, + { "type": "uint256", "name": "amount" }, + { "type": "uint256", "name": "expiry" }, + { "type": "bytes", "name": "signature" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 81237 + }, + { + "name": "totalAssets", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 4123 + }, + { + "name": "deposit", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "deposit", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "uint256", "name": "_amount" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "deposit", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [ + { "type": "uint256", "name": "_amount" }, + { "type": "address", "name": "recipient" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "maxAvailableShares", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 364171 + }, + { + "name": "withdraw", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "withdraw", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "uint256", "name": "maxShares" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "withdraw", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [ + { "type": "uint256", "name": "maxShares" }, + { "type": "address", "name": "recipient" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "withdraw", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [ + { "type": "uint256", "name": "maxShares" }, + { "type": "address", "name": "recipient" }, + { "type": "uint256", "name": "maxLoss" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "pricePerShare", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 12412 + }, + { + "name": "addStrategy", + "outputs": [], + "inputs": [ + { "type": "address", "name": "strategy" }, + { "type": "uint256", "name": "debtRatio" }, + { "type": "uint256", "name": "rateLimit" }, + { "type": "uint256", "name": "performanceFee" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 1450351 + }, + { + "name": "updateStrategyDebtRatio", + "outputs": [], + "inputs": [ + { "type": "address", "name": "strategy" }, + { "type": "uint256", "name": "debtRatio" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 115316 + }, + { + "name": "updateStrategyRateLimit", + "outputs": [], + "inputs": [ + { "type": "address", "name": "strategy" }, + { "type": "uint256", "name": "rateLimit" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 41467 + }, + { + "name": "updateStrategyPerformanceFee", + "outputs": [], + "inputs": [ + { "type": "address", "name": "strategy" }, + { "type": "uint256", "name": "performanceFee" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 41344 + }, + { + "name": "migrateStrategy", + "outputs": [], + "inputs": [ + { "type": "address", "name": "oldVersion" }, + { "type": "address", "name": "newVersion" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 1105801 + }, + { + "name": "revokeStrategy", + "outputs": [], + "inputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "revokeStrategy", + "outputs": [], + "inputs": [{ "type": "address", "name": "strategy" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "addStrategyToQueue", + "outputs": [], + "inputs": [{ "type": "address", "name": "strategy" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 1196920 + }, + { + "name": "removeStrategyFromQueue", + "outputs": [], + "inputs": [{ "type": "address", "name": "strategy" }], + "stateMutability": "nonpayable", + "type": "function", + "gas": 23091666 + }, + { + "name": "debtOutstanding", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "name": "debtOutstanding", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "address", "name": "strategy" }], + "stateMutability": "view", + "type": "function" + }, + { + "name": "creditAvailable", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "name": "creditAvailable", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "address", "name": "strategy" }], + "stateMutability": "view", + "type": "function" + }, + { + "name": "availableDepositLimit", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 9808 + }, + { + "name": "expectedReturn", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "name": "expectedReturn", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "address", "name": "strategy" }], + "stateMutability": "view", + "type": "function" + }, + { + "name": "report", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [ + { "type": "uint256", "name": "gain" }, + { "type": "uint256", "name": "loss" }, + { "type": "uint256", "name": "_debtPayment" } + ], + "stateMutability": "nonpayable", + "type": "function", + "gas": 937520 + }, + { + "name": "sweep", + "outputs": [], + "inputs": [{ "type": "address", "name": "token" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "sweep", + "outputs": [], + "inputs": [ + { "type": "address", "name": "token" }, + { "type": "uint256", "name": "amount" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "name": "name", + "outputs": [{ "type": "string", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 9053 + }, + { + "name": "symbol", + "outputs": [{ "type": "string", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 8106 + }, + { + "name": "decimals", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2711 + }, + { + "name": "balanceOf", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "address", "name": "arg0" }], + "stateMutability": "view", + "type": "function", + "gas": 2956 + }, + { + "name": "allowance", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [ + { "type": "address", "name": "arg0" }, + { "type": "address", "name": "arg1" } + ], + "stateMutability": "view", + "type": "function", + "gas": 3201 + }, + { + "name": "totalSupply", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2801 + }, + { + "name": "token", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2831 + }, + { + "name": "governance", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2861 + }, + { + "name": "management", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2891 + }, + { + "name": "guardian", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2921 + }, + { + "name": "guestList", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 2951 + }, + { + "name": "strategies", + "outputs": [ + { "type": "uint256", "name": "performanceFee" }, + { "type": "uint256", "name": "activation" }, + { "type": "uint256", "name": "debtRatio" }, + { "type": "uint256", "name": "rateLimit" }, + { "type": "uint256", "name": "lastReport" }, + { "type": "uint256", "name": "totalDebt" }, + { "type": "uint256", "name": "totalGain" }, + { "type": "uint256", "name": "totalLoss" } + ], + "inputs": [{ "type": "address", "name": "arg0" }], + "stateMutability": "view", + "type": "function", + "gas": 10322 + }, + { + "name": "withdrawalQueue", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [{ "type": "uint256", "name": "arg0" }], + "stateMutability": "view", + "type": "function", + "gas": 3120 + }, + { + "name": "emergencyShutdown", + "outputs": [{ "type": "bool", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3041 + }, + { + "name": "depositLimit", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3071 + }, + { + "name": "debtRatio", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3101 + }, + { + "name": "totalDebt", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3131 + }, + { + "name": "lastReport", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3161 + }, + { + "name": "activation", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3191 + }, + { + "name": "rewards", + "outputs": [{ "type": "address", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3221 + }, + { + "name": "managementFee", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3251 + }, + { + "name": "performanceFee", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3281 + }, + { + "name": "nonces", + "outputs": [{ "type": "uint256", "name": "" }], + "inputs": [{ "type": "address", "name": "arg0" }], + "stateMutability": "view", + "type": "function", + "gas": 3526 + }, + { + "name": "DOMAIN_SEPARATOR", + "outputs": [{ "type": "bytes32", "name": "" }], + "inputs": [], + "stateMutability": "view", + "type": "function", + "gas": 3341 + } +] diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index 448204a18a..ee55bf4db9 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -66,6 +66,8 @@ dataSources: ############## Price Oracle ############### ########################################### # ERC20 + - name: _ERC20 + file: ./abis/Prices/ERC20.json - name: ERC20 file: ./abis/ERC20.json - name: ERC20NameBytes diff --git a/subgraphs/ebtc/src/sdk/token.ts b/subgraphs/ebtc/src/sdk/token.ts index 26e86c042d..e5237c9d7b 100644 --- a/subgraphs/ebtc/src/sdk/token.ts +++ b/subgraphs/ebtc/src/sdk/token.ts @@ -16,8 +16,8 @@ import { * a wrapper for the Token entity making it easier to * use in mappings and get info about the token. * - * Schema Version: 3.0.1 - * SDK Version: 1.0.2 + * Schema Version: 3.1.0 + * SDK Version: 1.0.4 * Author(s): * - @dmelotik */ @@ -158,7 +158,7 @@ export class TokenManager { const decimalResult = contract.try_decimals(); if (!decimalResult.reverted) { const decimalValue = decimalResult.value; - return decimalValue.toI32(); + return decimalValue; } // try with the static definition From 0bd8ffc9eb6cfa2ca1c14138a9d4880001aaa764 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 5 Jul 2023 23:23:16 +0200 Subject: [PATCH 29/52] fix: more erc20 related changes --- subgraphs/ebtc/src/prices/common/utils.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subgraphs/ebtc/src/prices/common/utils.ts b/subgraphs/ebtc/src/prices/common/utils.ts index 788325e9e3..450300e896 100644 --- a/subgraphs/ebtc/src/prices/common/utils.ts +++ b/subgraphs/ebtc/src/prices/common/utils.ts @@ -17,7 +17,7 @@ import * as ARBITRUM_ONE from "../config/arbitrum"; import { Configurations } from "./types"; import * as constants from "./constants"; import * as TEMPLATE from "../config/template"; -import { ERC20 } from "../../../generated/PriceFeed/ERC20"; +import { _ERC20 } from "../../../generated/PriceFeed/_ERC20"; import { Address, BigInt, dataSource, ethereum } from "@graphprotocol/graph-ts"; export function isNullAddress(tokenAddr: Address): boolean { @@ -32,14 +32,14 @@ export function readValue( } export function getTokenName(tokenAddr: Address): string { - const tokenContract = ERC20.bind(tokenAddr); + const tokenContract = _ERC20.bind(tokenAddr); const name = readValue(tokenContract.try_name(), ""); return name; } export function getTokenDecimals(tokenAddr: Address): BigInt { - const tokenContract = ERC20.bind(tokenAddr); + const tokenContract = _ERC20.bind(tokenAddr); const decimals = readValue( tokenContract.try_decimals(), @@ -50,7 +50,7 @@ export function getTokenDecimals(tokenAddr: Address): BigInt { } export function getTokenSupply(tokenAddr: Address): BigInt { - const tokenContract = ERC20.bind(tokenAddr); + const tokenContract = _ERC20.bind(tokenAddr); const totalSupply = readValue( tokenContract.try_totalSupply(), From b91c5d8ce3f80e3b5696eca6ba0d6f6b75f8179b Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 7 Jul 2023 16:50:28 +0200 Subject: [PATCH 30/52] chore: update prices sdk to newer version --- subgraphs/ebtc/src/prices/README.md | 75 +++++++-- subgraphs/ebtc/src/prices/common/constants.ts | 7 +- subgraphs/ebtc/src/prices/common/types.ts | 48 +++++- subgraphs/ebtc/src/prices/common/utils.ts | 80 ++++++++- subgraphs/ebtc/src/prices/config/arbitrum.ts | 14 +- subgraphs/ebtc/src/prices/config/aurora.ts | 14 +- subgraphs/ebtc/src/prices/config/avalanche.ts | 14 +- subgraphs/ebtc/src/prices/config/bsc.ts | 13 +- subgraphs/ebtc/src/prices/config/celo.ts | 14 +- subgraphs/ebtc/src/prices/config/cronos.ts | 14 +- subgraphs/ebtc/src/prices/config/fantom.ts | 14 +- subgraphs/ebtc/src/prices/config/fuse.ts | 14 +- subgraphs/ebtc/src/prices/config/gnosis.ts | 14 +- subgraphs/ebtc/src/prices/config/goerli.ts | 12 +- subgraphs/ebtc/src/prices/config/harmony.ts | 14 +- subgraphs/ebtc/src/prices/config/mainnet.ts | 98 ++++++++++- subgraphs/ebtc/src/prices/config/moonbeam.ts | 14 +- subgraphs/ebtc/src/prices/config/optimism.ts | 14 +- subgraphs/ebtc/src/prices/config/polygon.ts | 14 +- subgraphs/ebtc/src/prices/config/template.ts | 33 +++- subgraphs/ebtc/src/prices/index.ts | 153 ++++++++++-------- .../ebtc/src/prices/routers/CurveRouter.ts | 43 ++++- .../src/prices/routers/UniswapForksRouter.ts | 89 +++++++++- 23 files changed, 679 insertions(+), 140 deletions(-) diff --git a/subgraphs/ebtc/src/prices/README.md b/subgraphs/ebtc/src/prices/README.md index 51fc9fb576..a21d78286a 100644 --- a/subgraphs/ebtc/src/prices/README.md +++ b/subgraphs/ebtc/src/prices/README.md @@ -3,6 +3,7 @@ ## Configuration In `subgraph.yaml`, add the following code snippet inside the `abis` section of the `datasources` which is going to fetch prices of token using the `Price Oracle`. +
**NOTE**: Include the following code snippet in each of the datasources, that is dependent on the `Price Oracle` and update imports in each file inside oracle folder. ``` @@ -46,9 +47,21 @@ Following are some ways through which you can get the prices of tokens: ``` import { BigDecimal } from "@graphprotocol/graph-ts"; -import { getUsdPricePerToken, getUsdPrice } from "../Oracle"; +import { getUsdPrice, getUsdPricePerToken, getLiquidityBoundPrice } from "../Oracle"; // Method 1 +// Using function getUsdPrice(tokenAddr: Address, amount: BigDecimal): BigDecimal + +let tokenPrice = getUsdPrice(tokenAddr, amount); +``` + +> Note: Preferred as it internally calls `getLiquidityBoundPrice(...)` and returns token price bounded by it's pool's liquidity. +>
+> To get the price per token, you can still use `getUsdPrice(...)` as: +>

> `let tokenPrice = getUsdPrice(tokenAddr, BIGDECIMAL_ONE);` + +``` +// Method 2 // Using function getUsdPricePerToken(tokenAddr: Address): CustomPriceType let tokenPrice: BigDecimal; @@ -57,18 +70,33 @@ let fetchPrice = getUsdPricePerToken(tokenAddr); // fetchPrice.reverted: Bool // fetchPrice.usdPrice: BigDecimal // fetchPrice.decimals: number - -tokenPrice = fetchPrice.usdPrice * amount - -// Method 2 -// Using function getUsdPrice(tokenAddr: Address, amount: BigDecimal): BigDecimal - -let tokenPrice = getUsdPrice(tokenAddr, amount); +// fetchPrice.oracleType: string +// fetchPrice.liquidity: BigDecimal + +if (!fetchPrice.reverted) { + if ( + fetchPrice.oracleType == constants.OracleType.UNISWAP_FORKS_ROUTER || + fetchPrice.oracleType == constants.OracleType.CURVE_ROUTER + ) { + fetchPrice = getLiquidityBoundPrice(tokenAddr, fetchPrice, amount) + } + tokenPrice = fetchPrice.usdPrice * amount +} ``` ## Optimizations -- Reorder the methods present in `index.ts`, depending on which method works best for you. +- Configure default `number of oracles` to fetch price from and their `order of preference` in OracleType's constructor, depending on which oracles _generally_ works best for you. +- Although querying multiple oracles for the same token's price mean more contract calls, this overhead can be beared for smaller subgraphs, and for specific tokens/block ranges for larger ones in favour of spotting and ignoring outlier values by avoiding complete reliance on a single source of truth and trusting the closer majority values, especially for low/distributed liquidity tokens, or during volatile markets. +

+ The result is an average price on the k-closest reported values. +
+ where, `k = ceil(reportedPrices.length/2)` +- For any observed pricing discrepancies, you may define an override on the default oracle configuration in network's config file which works better for the mispriced token(s). +
+ An example override is defined under `ORACLE CONFIG OVERRIDES` section in `config/template.ts` +

+ Any new overrides shall be maintained in both the subgraph as well as the reference pricelib directory, so the same inconsistencies do not have to be handled separately. ## Folder Structure @@ -86,13 +114,17 @@ Prices │ ├── aurora.ts │ ├── avalanche.ts │ ├── bsc.ts +│ ├── celo.ts +│ ├── cronos.ts │ ├── fantom.ts +│ ├── fuse.ts │ ├── gnosis.ts │ ├── harmony.ts │ ├── mainnet.ts │ ├── moonbeam.ts │ ├── optimism.ts -│ └── polygon.ts +│ ├── polygon.ts +│ └── template.ts ├── oracles │ ├── AaveOracle.ts │ ├── ChainLinkFeed.ts @@ -154,6 +186,21 @@ Prices | | `0x10ED43C718714eb63d5aA57B78B54704E256024E` | `6810080` | ✅ | | | `0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F` | `586899` | ✅ | +### Celo + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| UniswapForks | | | | +| | `0xe3d8bd6aed4f159bc8000a9cd47cffdb95f96121` | `5272598` | ✅ | +| | `0x1b02da8cb0d097eb8d57a175b88c7d8b47997506` | `7254057` | ✅ | + +### Cronos + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| UniswapForks | | | | +| | `0x145863eb42cf62847a6ca784e6416c1682b1b2ae` | `5247` | ✅ | + ### Fantom | **Method** | **Address** | **StartBlock** | **MultiCall** | @@ -169,6 +216,14 @@ Prices | | `0x16327E3FbDaCA3bcF7E38F5Af2599D2DDc33aE52` | `4250168` | ✅ | | | `0x1b02da8cb0d097eb8d57a175b88c7d8b47997506` | `2457904` | ✅ | +### Fuse + +| **Method** | **Address** | **StartBlock** | **MultiCall** | +| ------------ | :------------------------------------------: | :------------: | :-----------: | +| UniswapForks | | | | +| | `0xe3f85aad0c8dd7337427b9df5d0fb741d65eeeb5` | `15645719` | ✅ | +| | `0x1b02da8cb0d097eb8d57a175b88c7d8b47997506` | `12936314` | ✅ | + ### Gnosis | **Method** | **Address** | **StartBlock** | **MultiCall** | diff --git a/subgraphs/ebtc/src/prices/common/constants.ts b/subgraphs/ebtc/src/prices/common/constants.ts index 32100b7a08..c63322f4d2 100644 --- a/subgraphs/ebtc/src/prices/common/constants.ts +++ b/subgraphs/ebtc/src/prices/common/constants.ts @@ -23,7 +23,12 @@ export const CHAIN_LINK_USD_ADDRESS = Address.fromString( "0x0000000000000000000000000000000000000348" ); -export const PRICE_LIB_VERSION = "1.2.0"; +export const PRICE_LIB_VERSION = "1.3.0"; + +export const INT_ZERO = 0 as i32; +export const INT_ONE = 1 as i32; +export const INT_TWO = 2 as i32; +export const INT_NEGATIVE_ONE = -1 as i32; export const BIGINT_ZERO = BigInt.fromI32(0); export const BIGINT_ONE = BigInt.fromI32(1); diff --git a/subgraphs/ebtc/src/prices/common/types.ts b/subgraphs/ebtc/src/prices/common/types.ts index 7227bf05c5..bf2dfe1a41 100644 --- a/subgraphs/ebtc/src/prices/common/types.ts +++ b/subgraphs/ebtc/src/prices/common/types.ts @@ -1,5 +1,5 @@ import * as constants from "./constants"; -import { Address, BigDecimal, BigInt } from "@graphprotocol/graph-ts"; +import { Address, BigDecimal, BigInt, ethereum } from "@graphprotocol/graph-ts"; export class Wrapped { inner: T; @@ -35,22 +35,26 @@ export class CustomPriceType { private _usdPrice: Wrapped; private _decimals: Wrapped; private _oracleType: string; + private _liquidity: Wrapped; constructor() { this._usdPrice = new Wrapped(constants.BIGDECIMAL_ZERO); this._decimals = new Wrapped(constants.BIGINT_ZERO.toI32() as u8); this._oracleType = ""; + this._liquidity = new Wrapped(constants.BIGDECIMAL_ZERO); } static initialize( _usdPrice: BigDecimal, _decimals: i32 = 0, - _oracleType: string = "" + _oracleType: string = "", + _liquidity: BigDecimal | null = null ): CustomPriceType { const result = new CustomPriceType(); result._usdPrice = new Wrapped(_usdPrice); result._decimals = new Wrapped(_decimals as u8); result._oracleType = _oracleType; + if (_liquidity) result._liquidity = new Wrapped(_liquidity); return result; } @@ -72,6 +76,41 @@ export class CustomPriceType { get oracleType(): string { return this._oracleType; } + + get liquidity(): BigDecimal { + return this._liquidity.inner; + } + + setLiquidity(liquidity: BigDecimal): void { + this._liquidity = new Wrapped(liquidity); + } +} + +export interface OracleConfig { + oracleCount(): number; + oracleOrder(): string[]; +} + +export class OracleType { + oracleCount: number; + oracleOrder: string[]; + + constructor() { + this.oracleCount = constants.INT_ONE; + this.oracleOrder = [ + constants.OracleType.YEARN_LENS_ORACLE, + constants.OracleType.CHAINLINK_FEED, + constants.OracleType.CURVE_CALCULATIONS, + constants.OracleType.SUSHI_CALCULATIONS, + constants.OracleType.CURVE_ROUTER, + constants.OracleType.UNISWAP_FORKS_ROUTER, + ]; + } + + setOracleConfig(override: OracleConfig): void { + this.oracleCount = override.oracleCount(); + this.oracleOrder = override.oracleOrder(); + } } export interface Configurations { @@ -100,4 +139,9 @@ export interface Configurations { usdcAddress(): Address; usdcTokenDecimals(): BigInt; + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null; } diff --git a/subgraphs/ebtc/src/prices/common/utils.ts b/subgraphs/ebtc/src/prices/common/utils.ts index 450300e896..9d7678434c 100644 --- a/subgraphs/ebtc/src/prices/common/utils.ts +++ b/subgraphs/ebtc/src/prices/common/utils.ts @@ -14,11 +14,17 @@ import * as OPTIMISM from "../config/optimism"; import * as AVALANCHE from "../config/avalanche"; import * as ARBITRUM_ONE from "../config/arbitrum"; -import { Configurations } from "./types"; +import { Configurations, CustomPriceType } from "./types"; import * as constants from "./constants"; import * as TEMPLATE from "../config/template"; import { _ERC20 } from "../../../generated/PriceFeed/_ERC20"; -import { Address, BigInt, dataSource, ethereum } from "@graphprotocol/graph-ts"; +import { + Address, + BigInt, + BigDecimal, + dataSource, + ethereum, +} from "@graphprotocol/graph-ts"; export function isNullAddress(tokenAddr: Address): boolean { return tokenAddr.equals(constants.NULL.TYPE_ADDRESS); @@ -97,3 +103,73 @@ export function getConfig(): Configurations { return new TEMPLATE.config(); } + +function sortByPrices(prices: CustomPriceType[]): CustomPriceType[] { + const pricesSorted = prices.sort(function (a, b) { + const x = a.usdPrice; + const y = b.usdPrice; + + if (x < y) return -1; + if (x > y) return 1; + return 0; + }); + + return pricesSorted; +} + +function pairwiseDiffOfPrices(prices: CustomPriceType[]): BigDecimal[] { + const diff: BigDecimal[] = []; + for (let i = 1; i < prices.length; i++) { + const x = prices[i].usdPrice; + const y = prices[i - 1].usdPrice; + + diff.push(x.minus(y)); + } + + return diff; +} + +export function kClosestPrices( + k: i32, + prices: CustomPriceType[] +): CustomPriceType[] { + // sort by USD prices + const pricesSorted = sortByPrices(prices); + + // pairwise difference in USD prices + const pairwiseDiff = pairwiseDiffOfPrices(pricesSorted); + + // k minimum difference values and their original indexes + const pairwiseDiffCopy = pairwiseDiff.map((x: BigDecimal) => x); + const pairwiseDiffSortedSlice = pairwiseDiffCopy.sort().slice(0, k); + const minDiffAtIdx: i32[] = []; + for (let i = 0; i < pairwiseDiffSortedSlice.length; i++) { + const idx = pairwiseDiff.indexOf(pairwiseDiffSortedSlice[i]); + minDiffAtIdx.push(idx as i32); + } + + // k closest USD price values + const kClosestPrices: CustomPriceType[] = []; + for (let i = 0; i < minDiffAtIdx.length; i++) { + if (!kClosestPrices.includes(pricesSorted[minDiffAtIdx[i]])) { + kClosestPrices.push(pricesSorted[minDiffAtIdx[i]]); + } + if (!kClosestPrices.includes(pricesSorted[minDiffAtIdx[i] + 1])) { + kClosestPrices.push(pricesSorted[minDiffAtIdx[i] + 1]); + } + } + + return kClosestPrices; +} + +export function averagePrice(prices: CustomPriceType[]): CustomPriceType { + let summationUSDPrice = constants.BIGDECIMAL_ZERO; + for (let i = 0; i < prices.length; i++) { + summationUSDPrice = summationUSDPrice.plus(prices[i].usdPrice); + } + + return CustomPriceType.initialize( + summationUSDPrice.div(new BigDecimal(BigInt.fromI32(prices.length as i32))), + constants.DEFAULT_USDC_DECIMALS + ); +} diff --git a/subgraphs/ebtc/src/prices/config/arbitrum.ts b/subgraphs/ebtc/src/prices/config/arbitrum.ts index b95c07b52c..145692b274 100644 --- a/subgraphs/ebtc/src/prices/config/arbitrum.ts +++ b/subgraphs/ebtc/src/prices/config/arbitrum.ts @@ -1,6 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "arbitrum-one"; @@ -135,4 +136,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/aurora.ts b/subgraphs/ebtc/src/prices/config/aurora.ts index 8cd2f4a42e..628013c4bf 100644 --- a/subgraphs/ebtc/src/prices/config/aurora.ts +++ b/subgraphs/ebtc/src/prices/config/aurora.ts @@ -1,6 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "aurora"; @@ -122,4 +123,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/avalanche.ts b/subgraphs/ebtc/src/prices/config/avalanche.ts index 70e23839d8..5d181039be 100644 --- a/subgraphs/ebtc/src/prices/config/avalanche.ts +++ b/subgraphs/ebtc/src/prices/config/avalanche.ts @@ -1,6 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "avalanche"; @@ -129,4 +130,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/bsc.ts b/subgraphs/ebtc/src/prices/config/bsc.ts index d79139fca2..ecef0f8d3e 100644 --- a/subgraphs/ebtc/src/prices/config/bsc.ts +++ b/subgraphs/ebtc/src/prices/config/bsc.ts @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ import * as constants from "../common/constants"; -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "bsc"; @@ -120,4 +120,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/celo.ts b/subgraphs/ebtc/src/prices/config/celo.ts index 45ad9469f4..2318f6b643 100644 --- a/subgraphs/ebtc/src/prices/config/celo.ts +++ b/subgraphs/ebtc/src/prices/config/celo.ts @@ -1,6 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "celo"; @@ -121,4 +122,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/cronos.ts b/subgraphs/ebtc/src/prices/config/cronos.ts index d47070c52b..f847104822 100644 --- a/subgraphs/ebtc/src/prices/config/cronos.ts +++ b/subgraphs/ebtc/src/prices/config/cronos.ts @@ -1,6 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "cronos"; @@ -120,4 +121,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/fantom.ts b/subgraphs/ebtc/src/prices/config/fantom.ts index afec8235f5..9d461b497a 100644 --- a/subgraphs/ebtc/src/prices/config/fantom.ts +++ b/subgraphs/ebtc/src/prices/config/fantom.ts @@ -1,6 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "fantom"; @@ -134,4 +135,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/fuse.ts b/subgraphs/ebtc/src/prices/config/fuse.ts index c8b308b2b7..2392dba83d 100644 --- a/subgraphs/ebtc/src/prices/config/fuse.ts +++ b/subgraphs/ebtc/src/prices/config/fuse.ts @@ -1,6 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "fuse"; @@ -121,4 +122,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/gnosis.ts b/subgraphs/ebtc/src/prices/config/gnosis.ts index cacea20084..8c4abb1db8 100644 --- a/subgraphs/ebtc/src/prices/config/gnosis.ts +++ b/subgraphs/ebtc/src/prices/config/gnosis.ts @@ -1,6 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING: string = "xdai"; @@ -123,4 +124,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/goerli.ts b/subgraphs/ebtc/src/prices/config/goerli.ts index ff353b4923..fce77fa2fc 100644 --- a/subgraphs/ebtc/src/prices/config/goerli.ts +++ b/subgraphs/ebtc/src/prices/config/goerli.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "goerli"; @@ -119,4 +120,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/harmony.ts b/subgraphs/ebtc/src/prices/config/harmony.ts index eeea74d9be..4ed750f8ca 100644 --- a/subgraphs/ebtc/src/prices/config/harmony.ts +++ b/subgraphs/ebtc/src/prices/config/harmony.ts @@ -1,6 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "harmony"; @@ -125,4 +126,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/mainnet.ts b/subgraphs/ebtc/src/prices/config/mainnet.ts index 343d150823..b8681b603d 100644 --- a/subgraphs/ebtc/src/prices/config/mainnet.ts +++ b/subgraphs/ebtc/src/prices/config/mainnet.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "mainnet"; @@ -44,7 +45,6 @@ export const UNISWAP_FORKS_ROUTER_ADDRESSES: OracleContract[] = [ new OracleContract("0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f", 10794261), // SushiSwap new OracleContract("0x7a250d5630b4cf539739df2c5dacb4c659f2488d", 10207858), // Uniswap ]; -2822883; /////////////////////////////////////////////////////////////////////////// /////////////////////////// BLACKLISTED TOKENS //////////////////////////// @@ -97,6 +97,61 @@ export const HARDCODED_STABLES: Address[] = [ Address.fromString("0xd71ecff9342a5ced620049e616c5035f1db98620"), // Synth sEUR ]; +/////////////////////////////////////////////////////////////////////////// +///////////////////////// ORACLE CONFIG OVERRIDES ///////////////////////// +/////////////////////////////////////////////////////////////////////////// + +// https://github.com/messari/subgraphs/issues/2090 +class spellOverride implements OracleConfig { + oracleCount(): number { + return constants.INT_ONE; + } + oracleOrder(): string[] { + return [ + constants.OracleType.CHAINLINK_FEED, + constants.OracleType.CURVE_CALCULATIONS, + constants.OracleType.SUSHI_CALCULATIONS, + constants.OracleType.CURVE_ROUTER, + constants.OracleType.UNISWAP_FORKS_ROUTER, + constants.OracleType.YEARN_LENS_ORACLE, + ]; + } +} + +// https://github.com/messari/subgraphs/issues/726 +class stETHOverride implements OracleConfig { + oracleCount(): number { + return constants.INT_ONE; + } + oracleOrder(): string[] { + return [ + constants.OracleType.CHAINLINK_FEED, + constants.OracleType.CURVE_CALCULATIONS, + constants.OracleType.SUSHI_CALCULATIONS, + constants.OracleType.CURVE_ROUTER, + constants.OracleType.UNISWAP_FORKS_ROUTER, + constants.OracleType.YEARN_LENS_ORACLE, + ]; + } +} + +// https://github.com/messari/subgraphs/issues/2097 +class baxaOverride implements OracleConfig { + oracleCount(): number { + return constants.INT_ONE; + } + oracleOrder(): string[] { + return [ + constants.OracleType.UNISWAP_FORKS_ROUTER, + constants.OracleType.YEARN_LENS_ORACLE, + constants.OracleType.CHAINLINK_FEED, + constants.OracleType.CURVE_CALCULATIONS, + constants.OracleType.CURVE_ROUTER, + constants.OracleType.SUSHI_CALCULATIONS, + ]; + } +} + /////////////////////////////////////////////////////////////////////////// ///////////////////////////////// HELPERS ///////////////////////////////// /////////////////////////////////////////////////////////////////////////// @@ -173,4 +228,41 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + if (tokenAddr || block) { + if ( + tokenAddr && + [ + Address.fromString("0x090185f2135308bad17527004364ebcc2d37e5f6"), // SPELL + ].includes(tokenAddr) + ) { + return new spellOverride(); + } + if ( + tokenAddr && + [ + Address.fromString("0xae7ab96520de3a18e5e111b5eaab095312d7fe84"), // stETH + ].includes(tokenAddr) && + block && + block.number.gt(BigInt.fromString("14019699")) && + block.number.lt(BigInt.fromString("14941265")) + ) { + return new stETHOverride(); + } + if ( + tokenAddr && + [ + Address.fromString("0x91b08f4a7c1251dfccf5440f8894f8daa10c8de5"), // BAXA + ].includes(tokenAddr) + ) { + return new baxaOverride(); + } + } + + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/moonbeam.ts b/subgraphs/ebtc/src/prices/config/moonbeam.ts index 85bf1c1ed7..91b3002639 100644 --- a/subgraphs/ebtc/src/prices/config/moonbeam.ts +++ b/subgraphs/ebtc/src/prices/config/moonbeam.ts @@ -1,6 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "moonbeam"; @@ -122,4 +123,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/optimism.ts b/subgraphs/ebtc/src/prices/config/optimism.ts index 5fa69e7e31..14a271641f 100644 --- a/subgraphs/ebtc/src/prices/config/optimism.ts +++ b/subgraphs/ebtc/src/prices/config/optimism.ts @@ -1,6 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +import * as constants from "../common/constants"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "optimism"; @@ -134,4 +135,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/polygon.ts b/subgraphs/ebtc/src/prices/config/polygon.ts index dbbc217c42..55d2778512 100644 --- a/subgraphs/ebtc/src/prices/config/polygon.ts +++ b/subgraphs/ebtc/src/prices/config/polygon.ts @@ -1,6 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ -import { BigInt, Address } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +import * as constants from "../common/constants"; +import { BigInt, Address, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "matic"; @@ -128,4 +129,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return null; + } } diff --git a/subgraphs/ebtc/src/prices/config/template.ts b/subgraphs/ebtc/src/prices/config/template.ts index 622780c561..b470ccbed3 100644 --- a/subgraphs/ebtc/src/prices/config/template.ts +++ b/subgraphs/ebtc/src/prices/config/template.ts @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers */ +/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ import * as constants from "../common/constants"; -import { Address, BigInt } from "@graphprotocol/graph-ts"; -import { Configurations, OracleContract } from "../common/types"; +import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Configurations, OracleConfig, OracleContract } from "../common/types"; export const NETWORK_STRING = "default"; @@ -42,6 +42,26 @@ export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; export const HARDCODED_STABLES: Address[] = []; +/////////////////////////////////////////////////////////////////////////// +///////////////////////// ORACLE CONFIG OVERRIDES ///////////////////////// +/////////////////////////////////////////////////////////////////////////// + +class someOverride implements OracleConfig { + oracleCount(): number { + return constants.INT_ONE; + } + oracleOrder(): string[] { + return [ + constants.OracleType.YEARN_LENS_ORACLE, + constants.OracleType.CHAINLINK_FEED, + constants.OracleType.CURVE_CALCULATIONS, + constants.OracleType.SUSHI_CALCULATIONS, + constants.OracleType.CURVE_ROUTER, + constants.OracleType.UNISWAP_FORKS_ROUTER, + ]; + } +} + /////////////////////////////////////////////////////////////////////////// ///////////////////////////////// HELPERS ///////////////////////////////// /////////////////////////////////////////////////////////////////////////// @@ -112,4 +132,11 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } + + getOracleOverride( + tokenAddr: Address | null, + block: ethereum.Block | null + ): OracleConfig | null { + return new someOverride(); + } } diff --git a/subgraphs/ebtc/src/prices/index.ts b/subgraphs/ebtc/src/prices/index.ts index 3a2c0ce408..7dcd1ced4f 100644 --- a/subgraphs/ebtc/src/prices/index.ts +++ b/subgraphs/ebtc/src/prices/index.ts @@ -5,7 +5,7 @@ import { BigDecimal, dataSource, } from "@graphprotocol/graph-ts"; -import { CustomPriceType } from "./common/types"; +import { CustomPriceType, OracleType } from "./common/types"; import * as utils from "./common/utils"; import * as constants from "./common/constants"; @@ -41,88 +41,93 @@ export function getUsdPricePerToken( ); } - // 1. Yearn Lens Oracle - const yearnLensPrice = YearnLensOracle.getTokenPriceUSDC(tokenAddr, block); - if (!yearnLensPrice.reverted) { - log.info("[YearnLensOracle] tokenAddress: {}, Price: {}", [ - tokenAddr.toHexString(), - yearnLensPrice.usdPrice.toString(), - ]); - return yearnLensPrice; + const oracle = new OracleType(); + const override = config.getOracleOverride(tokenAddr, block); + if (override) { + oracle.setOracleConfig(override); } - - // 2. ChainLink Feed Registry - const chainLinkPrice = ChainLinkFeed.getTokenPriceUSDC(tokenAddr, block); - if (!chainLinkPrice.reverted) { - log.info("[ChainLinkFeed] tokenAddress: {}, Price: {}", [ - tokenAddr.toHexString(), - chainLinkPrice.usdPrice.toString(), - ]); - return chainLinkPrice; + const oracleCount = oracle.oracleCount; + const oracleOrder = oracle.oracleOrder; + + const prices: CustomPriceType[] = []; + for (let i = 0; i < oracleOrder.length; i++) { + if (prices.length >= oracleCount) { + break; + } + + let oraclePrice = new CustomPriceType(); + + if (oracleOrder[i] == constants.OracleType.YEARN_LENS_ORACLE) { + oraclePrice = YearnLensOracle.getTokenPriceUSDC(tokenAddr, block); + } else if (oracleOrder[i] == constants.OracleType.CHAINLINK_FEED) { + oraclePrice = ChainLinkFeed.getTokenPriceUSDC(tokenAddr, block); + } else if (oracleOrder[i] == constants.OracleType.CURVE_CALCULATIONS) { + oraclePrice = CurveCalculations.getTokenPriceUSDC(tokenAddr, block); + } else if (oracleOrder[i] == constants.OracleType.SUSHI_CALCULATIONS) { + oraclePrice = SushiCalculations.getTokenPriceUSDC(tokenAddr, block); + } else if (oracleOrder[i] == constants.OracleType.AAVE_ORACLE) { + oraclePrice = AaveOracle.getTokenPriceUSDC(tokenAddr, block); + } else if (oracleOrder[i] == constants.OracleType.CURVE_ROUTER) { + oraclePrice = CurveRouter.getCurvePriceUsdc(tokenAddr, block); + } else if (oracleOrder[i] == constants.OracleType.UNISWAP_FORKS_ROUTER) { + oraclePrice = UniswapForksRouter.getTokenPriceUSDC(tokenAddr, block); + } + + if (!oraclePrice.reverted) { + prices.push(oraclePrice); + } } - // 3. CalculationsCurve - const calculationsCurvePrice = CurveCalculations.getTokenPriceUSDC( - tokenAddr, - block - ); - if (!calculationsCurvePrice.reverted) { - log.info("[CalculationsCurve] tokenAddress: {}, Price: {}", [ + if (prices.length == constants.INT_ZERO) { + log.warning("[Oracle] Failed to Fetch Price, tokenAddr: {}", [ tokenAddr.toHexString(), - calculationsCurvePrice.usdPrice.toString(), ]); - return calculationsCurvePrice; - } - // 4. CalculationsSushiSwap - const calculationsSushiSwapPrice = SushiCalculations.getTokenPriceUSDC( - tokenAddr, - block - ); - if (!calculationsSushiSwapPrice.reverted) { - log.info("[CalculationsSushiSwap] tokenAddress: {}, Price: {}", [ - tokenAddr.toHexString(), - calculationsSushiSwapPrice.usdPrice.toString(), - ]); - return calculationsSushiSwapPrice; + return new CustomPriceType(); + } else if (prices.length == constants.INT_ONE) { + return prices[constants.INT_ZERO]; + } else if (prices.length == constants.INT_TWO) { + return utils.averagePrice(prices); } - // 6. Aave Oracle - const aaveOraclePrice = AaveOracle.getTokenPriceUSDC(tokenAddr, block); - if (!aaveOraclePrice.reverted) { - log.info("[AaveOracle] tokenAddress: {}, Price: {}", [ - tokenAddr.toHexString(), - aaveOraclePrice.usdPrice.toString(), - ]); - return aaveOraclePrice; - } + const k = Math.ceil(prices.length / constants.INT_TWO) as i32; + const closestPrices = utils.kClosestPrices(k, prices); - // 7. Curve Router - const curvePrice = CurveRouter.getCurvePriceUsdc(tokenAddr, block); - if (!curvePrice.reverted) { - log.info("[CurveRouter] tokenAddress: {}, Price: {}", [ - tokenAddr.toHexString(), - curvePrice.usdPrice.toString(), - ]); - return curvePrice; - } + return utils.averagePrice(closestPrices); +} - // 8. Uniswap Router - const uniswapPrice = UniswapForksRouter.getTokenPriceUSDC(tokenAddr, block); - if (!uniswapPrice.reverted) { - log.info("[UniswapRouter] tokenAddress: {}, Price: {}", [ - tokenAddr.toHexString(), - uniswapPrice.usdPrice.toString(), - ]); - return uniswapPrice; +export function getLiquidityBoundPrice( + tokenAddress: Address, + tokenPrice: CustomPriceType, + amount: BigDecimal +): BigDecimal { + const reportedPriceUSD = tokenPrice.usdPrice.times(amount); + const liquidity = tokenPrice.liquidity; + + let liquidityBoundPriceUSD = reportedPriceUSD; + if (liquidity > constants.BIGDECIMAL_ZERO && reportedPriceUSD > liquidity) { + liquidityBoundPriceUSD = liquidity + .div( + constants.BIGINT_TEN.pow( + constants.DEFAULT_USDC_DECIMALS as u8 + ).toBigDecimal() + ) + .times(constants.BIGINT_TEN.pow(tokenPrice.decimals as u8).toBigDecimal()) + .div(amount); + + log.warning( + "[getLiquidityBoundPrice] reported (token price * amount): ({} * {}) bound to: {} for token: {} due to insufficient liquidity: {}", + [ + tokenPrice.usdPrice.toString(), + amount.toString(), + liquidityBoundPriceUSD.toString(), + tokenAddress.toHexString(), + liquidity.toString(), + ] + ); } - log.warning("[Oracle] Failed to Fetch Price, Name: {} Address: {}", [ - utils.getTokenName(tokenAddr), - tokenAddr.toHexString(), - ]); - - return new CustomPriceType(); + return liquidityBoundPriceUSD; } export function getUsdPrice( @@ -133,6 +138,12 @@ export function getUsdPrice( const tokenPrice = getUsdPricePerToken(tokenAddr, block); if (!tokenPrice.reverted) { + if ( + tokenPrice.oracleType == constants.OracleType.UNISWAP_FORKS_ROUTER || + tokenPrice.oracleType == constants.OracleType.CURVE_ROUTER + ) { + return getLiquidityBoundPrice(tokenAddr, tokenPrice, amount); + } return tokenPrice.usdPrice.times(amount); } diff --git a/subgraphs/ebtc/src/prices/routers/CurveRouter.ts b/subgraphs/ebtc/src/prices/routers/CurveRouter.ts index f25e55d86e..36d8349e42 100644 --- a/subgraphs/ebtc/src/prices/routers/CurveRouter.ts +++ b/subgraphs/ebtc/src/prices/routers/CurveRouter.ts @@ -91,10 +91,13 @@ export function getCurvePriceUsdc( constants.BIGINT_TEN.pow(decimalsAdjustment.toI32() as u8).toBigDecimal() ); + const liquidity = getLpTokenLiquidityUsdc(lpAddress, block); + return CustomPriceType.initialize( priceUsdc, decimalsAdjustment.plus(constants.DEFAULT_DECIMALS).toI32() as u8, - constants.OracleType.CURVE_ROUTER + constants.OracleType.CURVE_ROUTER, + liquidity.usdPrice ); } @@ -325,3 +328,41 @@ export function getPriceUsdc( constants.OracleType.CURVE_ROUTER ); } + +function getLpTokenLiquidityUsdc( + lpAddress: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const poolAddress = getPoolFromLpToken(lpAddress, block); + const poolContract = CurvePoolContract.bind(poolAddress); + + let liquidity = constants.BIGDECIMAL_ZERO; + for (let i = 0; i < 8; i++) { + const coin = utils.readValue
( + poolContract.try_coins(BigInt.fromI32(i)), + constants.NULL.TYPE_ADDRESS + ); + if (coin.equals(constants.NULL.TYPE_ADDRESS) || coin.equals(lpAddress)) + continue; + + const decimals = utils.getTokenDecimals(coin); + const balance = utils.readValue( + poolContract.try_balances(BigInt.fromI32(i as i32)), + constants.BIGINT_ZERO + ); + + const price = getPriceUsdcRecommended(coin, block); + liquidity = liquidity.plus( + balance + .div(constants.BIGINT_TEN.pow(decimals.toI32() as u8)) + .toBigDecimal() + .times(price.usdPrice) + ); + } + + return CustomPriceType.initialize( + liquidity, + constants.DEFAULT_USDC_DECIMALS, + constants.OracleType.CURVE_ROUTER + ); +} diff --git a/subgraphs/ebtc/src/prices/routers/UniswapForksRouter.ts b/subgraphs/ebtc/src/prices/routers/UniswapForksRouter.ts index a39cb74cbb..ec2031aad6 100644 --- a/subgraphs/ebtc/src/prices/routers/UniswapForksRouter.ts +++ b/subgraphs/ebtc/src/prices/routers/UniswapForksRouter.ts @@ -5,6 +5,7 @@ import { CustomPriceType } from "../common/types"; import { Address, BigInt, ethereum, log } from "@graphprotocol/graph-ts"; import { UniswapPair as UniswapPairContract } from "../../../generated/PriceFeed/UniswapPair"; import { UniswapRouter as UniswapRouterContract } from "../../../generated/PriceFeed/UniswapRouter"; +import { UniswapFactory as UniswapFactoryContract } from "../../../generated/PriceFeed/UniswapFactory"; export function isLpToken(tokenAddress: Address, ethAddress: Address): bool { if (tokenAddress.equals(ethAddress)) return false; @@ -85,15 +86,17 @@ export function getPriceFromRouter( const routerAddresses = config.uniswapForks(); + let routerAddress = constants.NULL.TYPE_ADDRESS; let amountOut = constants.BIGINT_ZERO; for (let idx = 0; idx < routerAddresses.length; idx++) { - const routerAddress = routerAddresses[idx]; - if (block && routerAddress.startBlock.gt(block.number)) continue; + const router = routerAddresses[idx]; + if (block && router.startBlock.gt(block.number)) continue; - const uniswapForkRouter = UniswapRouterContract.bind(routerAddress.address); + const uniswapForkRouter = UniswapRouterContract.bind(router.address); const amountOutArray = uniswapForkRouter.try_getAmountsOut(amountIn, path); if (!amountOutArray.reverted) { + routerAddress = router.address; amountOut = amountOutArray.value[amountOutArray.value.length - 1]; break; } @@ -106,11 +109,37 @@ export function getPriceFromRouter( .div(constants.BIGINT_TEN_THOUSAND.minus(feeBips.times(numberOfJumps))) .toBigDecimal(); - return CustomPriceType.initialize( + const priceFromRouter = CustomPriceType.initialize( amountOutBigDecimal, config.usdcTokenDecimals().toI32() as u8, constants.OracleType.UNISWAP_FORKS_ROUTER ); + + const routerContract = UniswapRouterContract.bind(routerAddress); + const factoryAddress = utils.readValue( + routerContract.try_factory(), + constants.NULL.TYPE_ADDRESS + ); + if (factoryAddress.equals(constants.NULL.TYPE_ADDRESS)) + return priceFromRouter; + + const factoryContract = UniswapFactoryContract.bind(factoryAddress); + let tokenPair = utils.readValue( + factoryContract.try_getPair(token0Address, wethAddress), + constants.NULL.TYPE_ADDRESS + ); + if (tokenPair.equals(constants.NULL.TYPE_ADDRESS)) { + tokenPair = utils.readValue( + factoryContract.try_getPair(wethAddress, token0Address), + constants.NULL.TYPE_ADDRESS + ); + } + if (tokenPair.equals(constants.NULL.TYPE_ADDRESS)) return priceFromRouter; + + const liquidityUSD = getLpTokenLiquidityUsdc(tokenPair, block); + priceFromRouter.setLiquidity(liquidityUSD.usdPrice); + + return priceFromRouter; } export function getLpTokenPriceUsdc( @@ -201,13 +230,17 @@ export function getLpTokenTotalLiquidityUsdc( reserve1.notEqual(constants.BIGINT_ZERO) ) { const liquidity0 = reserve0 - .div(constants.BIGINT_TEN.pow(token0Decimals.toI32() as u8)) .toBigDecimal() + .div( + constants.BIGINT_TEN.pow(token0Decimals.toI32() as u8).toBigDecimal() + ) .times(token0Price.usdPrice); const liquidity1 = reserve1 - .div(constants.BIGINT_TEN.pow(token1Decimals.toI32() as u8)) .toBigDecimal() + .div( + constants.BIGINT_TEN.pow(token1Decimals.toI32() as u8).toBigDecimal() + ) .times(token1Price.usdPrice); const totalLiquidity = liquidity0.plus(liquidity1); @@ -220,3 +253,47 @@ export function getLpTokenTotalLiquidityUsdc( } return new CustomPriceType(); } + +function getLpTokenLiquidityUsdc( + lpAddress: Address, + block: ethereum.Block | null = null +): CustomPriceType { + const uniSwapPair = UniswapPairContract.bind(lpAddress); + + const token1Address = utils.readValue
( + uniSwapPair.try_token1(), + constants.NULL.TYPE_ADDRESS + ); + if (token1Address.equals(constants.NULL.TYPE_ADDRESS)) { + return new CustomPriceType(); + } + + const token1Price = getTokenPriceUSDC(token1Address, block); + if (token1Price.reverted) { + return new CustomPriceType(); + } + + const token1Decimals = utils.getTokenDecimals(token1Address); + + const reservesCall = uniSwapPair.try_getReserves(); + if (reservesCall.reverted) return new CustomPriceType(); + + const reserves = reservesCall.value; + const reserve1 = reserves.value1; + + if (reserve1.notEqual(constants.BIGINT_ZERO)) { + const liquidity1 = reserve1 + .toBigDecimal() + .div( + constants.BIGINT_TEN.pow(token1Decimals.toI32() as u8).toBigDecimal() + ) + .times(token1Price.usdPrice); + + return CustomPriceType.initialize( + liquidity1, + constants.DEFAULT_USDC_DECIMALS, + constants.OracleType.UNISWAP_FORKS_ROUTER + ); + } + return new CustomPriceType(); +} From 6df8c2312b9c6f7a390ab5a9cd52fc75b3482532 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 7 Jul 2023 17:32:11 +0200 Subject: [PATCH 31/52] chore: include abi --- subgraphs/ebtc/abis/BorrowerOperations.json | 774 ++++++++++++++++++++ 1 file changed, 774 insertions(+) create mode 100644 subgraphs/ebtc/abis/BorrowerOperations.json diff --git a/subgraphs/ebtc/abis/BorrowerOperations.json b/subgraphs/ebtc/abis/BorrowerOperations.json new file mode 100644 index 0000000000..3bef74f9ae --- /dev/null +++ b/subgraphs/ebtc/abis/BorrowerOperations.json @@ -0,0 +1,774 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_cdpManagerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_activePoolAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_collSurplusPoolAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_priceFeedAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_sortedCdpsAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_ebtcTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_feeRecipientAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_collTokenAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_activePoolAddress", + "type": "address" + } + ], + "name": "ActivePoolAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract Authority", + "name": "newAuthority", + "type": "address" + } + ], + "name": "AuthorityUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "_cdpId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "_borrower", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "arrayIndex", + "type": "uint256" + } + ], + "name": "CdpCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_newCdpManagerAddress", + "type": "address" + } + ], + "name": "CdpManagerAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "_cdpId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "_borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_oldDebt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_oldColl", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_debt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_coll", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_stake", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IBorrowerOperations.BorrowerOperation", + "name": "_operation", + "type": "uint8" + } + ], + "name": "CdpUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_collSurplusPoolAddress", + "type": "address" + } + ], + "name": "CollSurplusPoolAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_collTokenAddress", + "type": "address" + } + ], + "name": "CollateralAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_ebtcTokenAddress", + "type": "address" + } + ], + "name": "EBTCTokenAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_feeRecipientAddress", + "type": "address" + } + ], + "name": "FeeRecipientAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_setter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_oldFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newFee", + "type": "uint256" + } + ], + "name": "FlashFeeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "FlashLoanSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_setter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_oldMaxFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newMaxFee", + "type": "uint256" + } + ], + "name": "MaxFlashFeeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_newPriceFeedAddress", + "type": "address" + } + ], + "name": "PriceFeedAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_sortedCdpsAddress", + "type": "address" + } + ], + "name": "SortedCdpsAddressChanged", + "type": "event" + }, + { + "inputs": [], + "name": "BORROWING_FEE_FLOOR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CCR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DECIMAL_PRECISION", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FLASH_SUCCESS_VALUE", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LICR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIQUIDATOR_REWARD", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_BPS", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REWARD_SPLIT", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MCR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_NET_COLL", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PERCENT_DIVISOR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_REWARD_SPLIT", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_100pct", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_105pct", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "_5pct", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "activePool", + "outputs": [ + { "internalType": "contract IActivePool", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_upperHint", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_lowerHint", "type": "bytes32" }, + { "internalType": "uint256", "name": "_collAmount", "type": "uint256" } + ], + "name": "addColl", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { + "internalType": "uint256", + "name": "_collWithdrawal", + "type": "uint256" + }, + { "internalType": "uint256", "name": "_EBTCChange", "type": "uint256" }, + { "internalType": "bool", "name": "_isDebtIncrease", "type": "bool" }, + { "internalType": "bytes32", "name": "_upperHint", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_lowerHint", "type": "bytes32" } + ], + "name": "adjustCdp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { + "internalType": "uint256", + "name": "_collWithdrawal", + "type": "uint256" + }, + { "internalType": "uint256", "name": "_EBTCChange", "type": "uint256" }, + { "internalType": "bool", "name": "_isDebtIncrease", "type": "bool" }, + { "internalType": "bytes32", "name": "_upperHint", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_lowerHint", "type": "bytes32" }, + { "internalType": "uint256", "name": "_collAddAmount", "type": "uint256" } + ], + "name": "adjustCdpWithColl", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "authority", + "outputs": [ + { "internalType": "contract Authority", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "authorityInitialized", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cdpManager", + "outputs": [ + { "internalType": "contract ICdpManager", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claimCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" } + ], + "name": "closeCdp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "collSurplusPool", + "outputs": [ + { + "internalType": "contract ICollSurplusPool", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "collateral", + "outputs": [ + { + "internalType": "contract ICollateralToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ebtcToken", + "outputs": [ + { "internalType": "contract IEBTCToken", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeBps", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeRecipientAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "flashFee", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC3156FlashBorrower", + "name": "receiver", + "type": "address" + }, + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "flashLoan", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getEntireSystemColl", + "outputs": [ + { + "internalType": "uint256", + "name": "entireSystemColl", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "locked", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxFeeBps", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" } + ], + "name": "maxFlashLoan", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_EBTCAmount", "type": "uint256" }, + { "internalType": "bytes32", "name": "_upperHint", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_lowerHint", "type": "bytes32" }, + { "internalType": "uint256", "name": "_collAmount", "type": "uint256" } + ], + "name": "openCdp", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "priceFeed", + "outputs": [ + { "internalType": "contract IPriceFeed", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { "internalType": "uint256", "name": "_EBTCAmount", "type": "uint256" }, + { "internalType": "bytes32", "name": "_upperHint", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_lowerHint", "type": "bytes32" } + ], + "name": "repayEBTC", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAuthority", "type": "address" } + ], + "name": "setAuthority", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_newFee", "type": "uint256" } + ], + "name": "setFeeBps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeRecipientAddress", + "type": "address" + } + ], + "name": "setFeeRecipientAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newMaxFlashFee", + "type": "uint256" + } + ], + "name": "setMaxFeeBps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sortedCdps", + "outputs": [ + { "internalType": "contract ISortedCdps", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { + "internalType": "uint256", + "name": "_collWithdrawal", + "type": "uint256" + }, + { "internalType": "bytes32", "name": "_upperHint", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_lowerHint", "type": "bytes32" } + ], + "name": "withdrawColl", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "_cdpId", "type": "bytes32" }, + { "internalType": "uint256", "name": "_EBTCAmount", "type": "uint256" }, + { "internalType": "bytes32", "name": "_upperHint", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_lowerHint", "type": "bytes32" } + ], + "name": "withdrawEBTC", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] From a6e35495dc02d1a63e4009340b0dbb7088671ea4 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 7 Jul 2023 17:50:46 +0200 Subject: [PATCH 32/52] chore: include `BorrowerOperations` in template --- .../ebtc-goerli/configurations.json | 3 ++- .../ebtc/config/templates/ebtc.template.yaml | 19 +++++++++++++++++++ .../ebtc/src/mapping/BorrowerOperations.ts | 7 +++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 subgraphs/ebtc/src/mapping/BorrowerOperations.ts diff --git a/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json b/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json index ec1c6a9b1c..e128e69b73 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json +++ b/subgraphs/ebtc/protocols/ebtc/config/deployments/ebtc-goerli/configurations.json @@ -29,7 +29,8 @@ }, "borrowerOperations": { "address": "0x11d823a74104A4E9D2E49672BAa6Ab9B5d321D06", - "verification": "https://goerli.etherscan.io/address/0x11d823a74104A4E9D2E49672BAa6Ab9B5d321D06#code" + "verification": "https://goerli.etherscan.io/address/0x11d823a74104A4E9D2E49672BAa6Ab9B5d321D06#code", + "startBlock": 9129638 }, "eBTCToken": { "address": "0x5F9Da4b8B81AB38649Aa5d2043eD58C313Bf4139", diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index ee55bf4db9..91548d8da6 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -45,6 +45,25 @@ dataSources: handler: handleActivePoolCollBalanceUpdated - event: ActivePoolEBTCDebtUpdated(uint256) handler: handleActivePoolEBTCDebtUpdated + - name: BorrowerOperations + kind: ethereum/contract + network: "{{ network.slug }}" + source: + abi: BorrowerOperations + address: "{{ borrowerOperations.address }}" + startBlock: {{ borrowerOperations.startBlock }} + mapping: + file: ./src/mapping/BorrowerOperations.ts + language: wasm/assemblyscript + kind: ethereum/events + apiVersion: 0.0.7 + entities: [] + abis: + - name: BorrowerOperations + file: ./abis/BorrowerOperations.json + eventHandlers: + - event: CdpCreated(indexed bytes32,indexed address,indexed address,uint256) + handler: handleCdpCreated - name: PriceFeed kind: ethereum/contract network: "{{ network.slug }}" diff --git a/subgraphs/ebtc/src/mapping/BorrowerOperations.ts b/subgraphs/ebtc/src/mapping/BorrowerOperations.ts new file mode 100644 index 0000000000..6bd1136697 --- /dev/null +++ b/subgraphs/ebtc/src/mapping/BorrowerOperations.ts @@ -0,0 +1,7 @@ +import { CdpCreated } from "../../generated/BorrowerOperations/BorrowerOperations"; + +/** + * Create a new position when a CDP is created. + * @param event The event emitted by BorrowerOperations when a CDP is created. + */ +export function handleCdpCreated(event: CdpCreated): void {} From e7901dee499f2c6f0766b6f7a008ac7d7b31d9c2 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 11 Jul 2023 12:57:20 +0200 Subject: [PATCH 33/52] feat: track all events for now --- .../ebtc/config/templates/ebtc.template.yaml | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index 91548d8da6..2463765778 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -45,6 +45,17 @@ dataSources: handler: handleActivePoolCollBalanceUpdated - event: ActivePoolEBTCDebtUpdated(uint256) handler: handleActivePoolEBTCDebtUpdated + # - event: ActivePoolFeeRecipientClaimableCollDecreased(uint256,uint256) + # - event: ActivePoolFeeRecipientClaimableCollIncreased(uint256,uint256) + # - event: AuthorityUpdated(indexed address,indexed address) + # - event: CollateralSent(address,uint256) + # - event: EBTCBalanceUpdated(uint256) + # - event: ETHBalanceUpdated(uint256) + # - event: FlashFeeSet(address,uint256,uint256) + - event: FlashLoanSuccess(address,address,uint256,uint256) + handler: handleFlashLoanSuccess + # - event: MaxFlashFeeSet(address,uint256,uint256) + # - event: SweepTokenSuccess(address,uint256,address) - name: BorrowerOperations kind: ethereum/contract network: "{{ network.slug }}" @@ -62,8 +73,14 @@ dataSources: - name: BorrowerOperations file: ./abis/BorrowerOperations.json eventHandlers: - - event: CdpCreated(indexed bytes32,indexed address,indexed address,uint256) - handler: handleCdpCreated + # - event: AuthorityUpdated(indexed address,indexed address) + # - event: CdpCreated(indexed bytes32,indexed address,indexed address,uint256) + - event: CdpUpdated(indexed bytes32,indexed address,uint256,uint256,uint256,uint256,uint256,uint8) + handler: handleCdpUpdated + # - event: FlashFeeSet(address,uint256,uint256) + - event: FlashLoanSuccess(address,address,uint256,uint256) + handler: handleFlashLoanSuccess + # - event: MaxFlashFeeSet(address,uint256,uint256) - name: PriceFeed kind: ethereum/contract network: "{{ network.slug }}" From 3156e2af5a9a963903ad526e207b8759052f27b7 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 11 Jul 2023 13:00:36 +0200 Subject: [PATCH 34/52] feat: handle user deposits and withdrawals --- .../ebtc/src/mapping/BorrowerOperations.ts | 82 ++++++++++++++++++- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/subgraphs/ebtc/src/mapping/BorrowerOperations.ts b/subgraphs/ebtc/src/mapping/BorrowerOperations.ts index 6bd1136697..d6a735648c 100644 --- a/subgraphs/ebtc/src/mapping/BorrowerOperations.ts +++ b/subgraphs/ebtc/src/mapping/BorrowerOperations.ts @@ -1,7 +1,81 @@ -import { CdpCreated } from "../../generated/BorrowerOperations/BorrowerOperations"; +import { Address } from "@graphprotocol/graph-ts"; +import { CdpUpdated } from "../../generated/BorrowerOperations/BorrowerOperations"; +import { getUsdPrice } from "../prices"; +import { BIGINT_TEN_TO_EIGHTEENTH, BIGINT_ZERO } from "../sdk/util/constants"; +import { getDataManager, STETH_ADDRESS } from "../constants"; /** - * Create a new position when a CDP is created. - * @param event The event emitted by BorrowerOperations when a CDP is created. + * Create withdrawals, deposits, borrows, and repays when a CDP is updated. + * @param event CdpUpdated The event emitted by BorrowerOperations when a CDP + * is updated. */ -export function handleCdpCreated(event: CdpCreated): void {} +export function handleCdpUpdated(event: CdpUpdated): void { + const dataManager = getDataManager(event); + const deltaColl = event.params._coll.minus(event.params._oldColl); + if (deltaColl > BIGINT_ZERO) { + dataManager.createDeposit( + STETH_ADDRESS, // asset: Bytes + event.params._borrower, // account: Bytes + deltaColl, // amount: BigInt + getUsdPrice( + Address.fromBytes(STETH_ADDRESS), + deltaColl.div(BIGINT_TEN_TO_EIGHTEENTH).toBigDecimal(), + event.block + ), // amountUSD: BigDecimal + event.params._debt // newBalance: BigInt + ); + } else { + dataManager.createWithdraw( + STETH_ADDRESS, // asset: Bytes + event.params._borrower, // account: Bytes + deltaColl, // amount: BigInt + getUsdPrice( + Address.fromBytes(STETH_ADDRESS), + deltaColl.div(BIGINT_TEN_TO_EIGHTEENTH).toBigDecimal(), + event.block + ), // amountUSD: BigDecimal + event.params._coll // newBalance: BigInt + ); + } + + const deltaDebt = event.params._debt.minus(event.params._oldDebt); + if (deltaDebt > BIGINT_ZERO) { + // createBorrow( + // asset: Bytes + // account: Bytes + // amount: BigInt + // amountUSD: BigDecimal + // newBalance: BigInt + // tokenPriceUSD: BigDecimal // used for different borrow token in CDP + // ) + } else { + // createRepay( + // asset: Bytes + // account: Bytes + // amount: BigInt + // amountUSD: BigDecimal + // newBalance: BigInt + // tokenPriceUSD: BigDecimal // used for different borrow token in CDP + // ) + } + + // createLiquidate( + // asset: Bytes + // liquidator: Address + // liquidatee: Address + // amount: BigInt + // amountUSD: BigDecimal + // profitUSD: BigDecimal + // newBalance: BigInt // repaid token balance for liquidatee + // ) + + // createTransfer( + // asset: Bytes + // sender: Address + // receiver: Address + // amount: BigInt + // amountUSD: BigDecimal + // senderNewBalance: BigInt + // receiverNewBalance: BigInt + // ) +} From 32a75e7d2cf06a40dc46a953d65fadd09b188fcd Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 11 Jul 2023 13:00:50 +0200 Subject: [PATCH 35/52] feat: handle flash loans --- subgraphs/ebtc/src/mapping/ActivePool.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/subgraphs/ebtc/src/mapping/ActivePool.ts b/subgraphs/ebtc/src/mapping/ActivePool.ts index 14adcb7fba..6cf7991b1e 100644 --- a/subgraphs/ebtc/src/mapping/ActivePool.ts +++ b/subgraphs/ebtc/src/mapping/ActivePool.ts @@ -1,9 +1,13 @@ +import { Address } from "@graphprotocol/graph-ts"; import { ActivePoolCollBalanceUpdated, ActivePoolEBTCDebtUpdated, + FlashLoanSuccess, } from "../../generated/ActivePool/ActivePool"; import { getDataManager, STETH_ADDRESS } from "../constants"; import { TokenManager } from "../sdk/token"; +import { getUsdPrice } from "../prices"; +import { BIGINT_TEN_TO_EIGHTEENTH } from "../sdk/util/constants"; /** * Total stETH collateral was updated @@ -36,3 +40,23 @@ export function handleActivePoolEBTCDebtUpdated( event.params._EBTCDebt // newVariableBorrowBalance: BigInt | null = null ); } + +/** + * Create a flashloan object and handle its fee when a flashloan is successful. + * @param event FlashLoanSuccess The event emitted by BorrowerOperations when + * a flashloan is successful. + */ +export function handleFlashLoanSuccess(event: FlashLoanSuccess): void { + const dataManager = getDataManager(event); + const flashloan = dataManager.createFlashloan( + Address.fromBytes(STETH_ADDRESS), // asset: Address + event.params._receiver, // account: Address + event.params._amount, // amount: BigInt + getUsdPrice( + Address.fromBytes(STETH_ADDRESS), + event.params._amount.div(BIGINT_TEN_TO_EIGHTEENTH).toBigDecimal(), + event.block + ) // amountUSD: BigDecimal + ); + // TODO: handle fee (event.params._fee) +} From 903a6796b3f910dc161777bab541d4e00dae2204 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 11 Jul 2023 13:21:42 +0200 Subject: [PATCH 36/52] fix: revert to previous price lib --- subgraphs/ebtc/src/prices/README.md | 75 ++------- subgraphs/ebtc/src/prices/common/constants.ts | 7 +- subgraphs/ebtc/src/prices/common/types.ts | 48 +----- subgraphs/ebtc/src/prices/common/utils.ts | 80 +-------- subgraphs/ebtc/src/prices/config/arbitrum.ts | 14 +- subgraphs/ebtc/src/prices/config/aurora.ts | 14 +- subgraphs/ebtc/src/prices/config/avalanche.ts | 14 +- subgraphs/ebtc/src/prices/config/bsc.ts | 13 +- subgraphs/ebtc/src/prices/config/celo.ts | 14 +- subgraphs/ebtc/src/prices/config/cronos.ts | 14 +- subgraphs/ebtc/src/prices/config/fantom.ts | 14 +- subgraphs/ebtc/src/prices/config/fuse.ts | 14 +- subgraphs/ebtc/src/prices/config/gnosis.ts | 14 +- subgraphs/ebtc/src/prices/config/goerli.ts | 12 +- subgraphs/ebtc/src/prices/config/harmony.ts | 14 +- subgraphs/ebtc/src/prices/config/mainnet.ts | 97 +---------- subgraphs/ebtc/src/prices/config/moonbeam.ts | 14 +- subgraphs/ebtc/src/prices/config/optimism.ts | 14 +- subgraphs/ebtc/src/prices/config/polygon.ts | 14 +- subgraphs/ebtc/src/prices/config/template.ts | 33 +--- subgraphs/ebtc/src/prices/index.ts | 153 ++++++++---------- .../ebtc/src/prices/routers/CurveRouter.ts | 43 +---- .../src/prices/routers/UniswapForksRouter.ts | 89 +--------- 23 files changed, 139 insertions(+), 679 deletions(-) diff --git a/subgraphs/ebtc/src/prices/README.md b/subgraphs/ebtc/src/prices/README.md index a21d78286a..51fc9fb576 100644 --- a/subgraphs/ebtc/src/prices/README.md +++ b/subgraphs/ebtc/src/prices/README.md @@ -3,7 +3,6 @@ ## Configuration In `subgraph.yaml`, add the following code snippet inside the `abis` section of the `datasources` which is going to fetch prices of token using the `Price Oracle`. -
**NOTE**: Include the following code snippet in each of the datasources, that is dependent on the `Price Oracle` and update imports in each file inside oracle folder. ``` @@ -47,21 +46,9 @@ Following are some ways through which you can get the prices of tokens: ``` import { BigDecimal } from "@graphprotocol/graph-ts"; -import { getUsdPrice, getUsdPricePerToken, getLiquidityBoundPrice } from "../Oracle"; +import { getUsdPricePerToken, getUsdPrice } from "../Oracle"; // Method 1 -// Using function getUsdPrice(tokenAddr: Address, amount: BigDecimal): BigDecimal - -let tokenPrice = getUsdPrice(tokenAddr, amount); -``` - -> Note: Preferred as it internally calls `getLiquidityBoundPrice(...)` and returns token price bounded by it's pool's liquidity. ->
-> To get the price per token, you can still use `getUsdPrice(...)` as: ->

> `let tokenPrice = getUsdPrice(tokenAddr, BIGDECIMAL_ONE);` - -``` -// Method 2 // Using function getUsdPricePerToken(tokenAddr: Address): CustomPriceType let tokenPrice: BigDecimal; @@ -70,33 +57,18 @@ let fetchPrice = getUsdPricePerToken(tokenAddr); // fetchPrice.reverted: Bool // fetchPrice.usdPrice: BigDecimal // fetchPrice.decimals: number -// fetchPrice.oracleType: string -// fetchPrice.liquidity: BigDecimal - -if (!fetchPrice.reverted) { - if ( - fetchPrice.oracleType == constants.OracleType.UNISWAP_FORKS_ROUTER || - fetchPrice.oracleType == constants.OracleType.CURVE_ROUTER - ) { - fetchPrice = getLiquidityBoundPrice(tokenAddr, fetchPrice, amount) - } - tokenPrice = fetchPrice.usdPrice * amount -} + +tokenPrice = fetchPrice.usdPrice * amount + +// Method 2 +// Using function getUsdPrice(tokenAddr: Address, amount: BigDecimal): BigDecimal + +let tokenPrice = getUsdPrice(tokenAddr, amount); ``` ## Optimizations -- Configure default `number of oracles` to fetch price from and their `order of preference` in OracleType's constructor, depending on which oracles _generally_ works best for you. -- Although querying multiple oracles for the same token's price mean more contract calls, this overhead can be beared for smaller subgraphs, and for specific tokens/block ranges for larger ones in favour of spotting and ignoring outlier values by avoiding complete reliance on a single source of truth and trusting the closer majority values, especially for low/distributed liquidity tokens, or during volatile markets. -

- The result is an average price on the k-closest reported values. -
- where, `k = ceil(reportedPrices.length/2)` -- For any observed pricing discrepancies, you may define an override on the default oracle configuration in network's config file which works better for the mispriced token(s). -
- An example override is defined under `ORACLE CONFIG OVERRIDES` section in `config/template.ts` -

- Any new overrides shall be maintained in both the subgraph as well as the reference pricelib directory, so the same inconsistencies do not have to be handled separately. +- Reorder the methods present in `index.ts`, depending on which method works best for you. ## Folder Structure @@ -114,17 +86,13 @@ Prices │ ├── aurora.ts │ ├── avalanche.ts │ ├── bsc.ts -│ ├── celo.ts -│ ├── cronos.ts │ ├── fantom.ts -│ ├── fuse.ts │ ├── gnosis.ts │ ├── harmony.ts │ ├── mainnet.ts │ ├── moonbeam.ts │ ├── optimism.ts -│ ├── polygon.ts -│ └── template.ts +│ └── polygon.ts ├── oracles │ ├── AaveOracle.ts │ ├── ChainLinkFeed.ts @@ -186,21 +154,6 @@ Prices | | `0x10ED43C718714eb63d5aA57B78B54704E256024E` | `6810080` | ✅ | | | `0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F` | `586899` | ✅ | -### Celo - -| **Method** | **Address** | **StartBlock** | **MultiCall** | -| ------------ | :------------------------------------------: | :------------: | :-----------: | -| UniswapForks | | | | -| | `0xe3d8bd6aed4f159bc8000a9cd47cffdb95f96121` | `5272598` | ✅ | -| | `0x1b02da8cb0d097eb8d57a175b88c7d8b47997506` | `7254057` | ✅ | - -### Cronos - -| **Method** | **Address** | **StartBlock** | **MultiCall** | -| ------------ | :------------------------------------------: | :------------: | :-----------: | -| UniswapForks | | | | -| | `0x145863eb42cf62847a6ca784e6416c1682b1b2ae` | `5247` | ✅ | - ### Fantom | **Method** | **Address** | **StartBlock** | **MultiCall** | @@ -216,14 +169,6 @@ Prices | | `0x16327E3FbDaCA3bcF7E38F5Af2599D2DDc33aE52` | `4250168` | ✅ | | | `0x1b02da8cb0d097eb8d57a175b88c7d8b47997506` | `2457904` | ✅ | -### Fuse - -| **Method** | **Address** | **StartBlock** | **MultiCall** | -| ------------ | :------------------------------------------: | :------------: | :-----------: | -| UniswapForks | | | | -| | `0xe3f85aad0c8dd7337427b9df5d0fb741d65eeeb5` | `15645719` | ✅ | -| | `0x1b02da8cb0d097eb8d57a175b88c7d8b47997506` | `12936314` | ✅ | - ### Gnosis | **Method** | **Address** | **StartBlock** | **MultiCall** | diff --git a/subgraphs/ebtc/src/prices/common/constants.ts b/subgraphs/ebtc/src/prices/common/constants.ts index c63322f4d2..32100b7a08 100644 --- a/subgraphs/ebtc/src/prices/common/constants.ts +++ b/subgraphs/ebtc/src/prices/common/constants.ts @@ -23,12 +23,7 @@ export const CHAIN_LINK_USD_ADDRESS = Address.fromString( "0x0000000000000000000000000000000000000348" ); -export const PRICE_LIB_VERSION = "1.3.0"; - -export const INT_ZERO = 0 as i32; -export const INT_ONE = 1 as i32; -export const INT_TWO = 2 as i32; -export const INT_NEGATIVE_ONE = -1 as i32; +export const PRICE_LIB_VERSION = "1.2.0"; export const BIGINT_ZERO = BigInt.fromI32(0); export const BIGINT_ONE = BigInt.fromI32(1); diff --git a/subgraphs/ebtc/src/prices/common/types.ts b/subgraphs/ebtc/src/prices/common/types.ts index bf2dfe1a41..7227bf05c5 100644 --- a/subgraphs/ebtc/src/prices/common/types.ts +++ b/subgraphs/ebtc/src/prices/common/types.ts @@ -1,5 +1,5 @@ import * as constants from "./constants"; -import { Address, BigDecimal, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Address, BigDecimal, BigInt } from "@graphprotocol/graph-ts"; export class Wrapped { inner: T; @@ -35,26 +35,22 @@ export class CustomPriceType { private _usdPrice: Wrapped; private _decimals: Wrapped; private _oracleType: string; - private _liquidity: Wrapped; constructor() { this._usdPrice = new Wrapped(constants.BIGDECIMAL_ZERO); this._decimals = new Wrapped(constants.BIGINT_ZERO.toI32() as u8); this._oracleType = ""; - this._liquidity = new Wrapped(constants.BIGDECIMAL_ZERO); } static initialize( _usdPrice: BigDecimal, _decimals: i32 = 0, - _oracleType: string = "", - _liquidity: BigDecimal | null = null + _oracleType: string = "" ): CustomPriceType { const result = new CustomPriceType(); result._usdPrice = new Wrapped(_usdPrice); result._decimals = new Wrapped(_decimals as u8); result._oracleType = _oracleType; - if (_liquidity) result._liquidity = new Wrapped(_liquidity); return result; } @@ -76,41 +72,6 @@ export class CustomPriceType { get oracleType(): string { return this._oracleType; } - - get liquidity(): BigDecimal { - return this._liquidity.inner; - } - - setLiquidity(liquidity: BigDecimal): void { - this._liquidity = new Wrapped(liquidity); - } -} - -export interface OracleConfig { - oracleCount(): number; - oracleOrder(): string[]; -} - -export class OracleType { - oracleCount: number; - oracleOrder: string[]; - - constructor() { - this.oracleCount = constants.INT_ONE; - this.oracleOrder = [ - constants.OracleType.YEARN_LENS_ORACLE, - constants.OracleType.CHAINLINK_FEED, - constants.OracleType.CURVE_CALCULATIONS, - constants.OracleType.SUSHI_CALCULATIONS, - constants.OracleType.CURVE_ROUTER, - constants.OracleType.UNISWAP_FORKS_ROUTER, - ]; - } - - setOracleConfig(override: OracleConfig): void { - this.oracleCount = override.oracleCount(); - this.oracleOrder = override.oracleOrder(); - } } export interface Configurations { @@ -139,9 +100,4 @@ export interface Configurations { usdcAddress(): Address; usdcTokenDecimals(): BigInt; - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null; } diff --git a/subgraphs/ebtc/src/prices/common/utils.ts b/subgraphs/ebtc/src/prices/common/utils.ts index 9d7678434c..450300e896 100644 --- a/subgraphs/ebtc/src/prices/common/utils.ts +++ b/subgraphs/ebtc/src/prices/common/utils.ts @@ -14,17 +14,11 @@ import * as OPTIMISM from "../config/optimism"; import * as AVALANCHE from "../config/avalanche"; import * as ARBITRUM_ONE from "../config/arbitrum"; -import { Configurations, CustomPriceType } from "./types"; +import { Configurations } from "./types"; import * as constants from "./constants"; import * as TEMPLATE from "../config/template"; import { _ERC20 } from "../../../generated/PriceFeed/_ERC20"; -import { - Address, - BigInt, - BigDecimal, - dataSource, - ethereum, -} from "@graphprotocol/graph-ts"; +import { Address, BigInt, dataSource, ethereum } from "@graphprotocol/graph-ts"; export function isNullAddress(tokenAddr: Address): boolean { return tokenAddr.equals(constants.NULL.TYPE_ADDRESS); @@ -103,73 +97,3 @@ export function getConfig(): Configurations { return new TEMPLATE.config(); } - -function sortByPrices(prices: CustomPriceType[]): CustomPriceType[] { - const pricesSorted = prices.sort(function (a, b) { - const x = a.usdPrice; - const y = b.usdPrice; - - if (x < y) return -1; - if (x > y) return 1; - return 0; - }); - - return pricesSorted; -} - -function pairwiseDiffOfPrices(prices: CustomPriceType[]): BigDecimal[] { - const diff: BigDecimal[] = []; - for (let i = 1; i < prices.length; i++) { - const x = prices[i].usdPrice; - const y = prices[i - 1].usdPrice; - - diff.push(x.minus(y)); - } - - return diff; -} - -export function kClosestPrices( - k: i32, - prices: CustomPriceType[] -): CustomPriceType[] { - // sort by USD prices - const pricesSorted = sortByPrices(prices); - - // pairwise difference in USD prices - const pairwiseDiff = pairwiseDiffOfPrices(pricesSorted); - - // k minimum difference values and their original indexes - const pairwiseDiffCopy = pairwiseDiff.map((x: BigDecimal) => x); - const pairwiseDiffSortedSlice = pairwiseDiffCopy.sort().slice(0, k); - const minDiffAtIdx: i32[] = []; - for (let i = 0; i < pairwiseDiffSortedSlice.length; i++) { - const idx = pairwiseDiff.indexOf(pairwiseDiffSortedSlice[i]); - minDiffAtIdx.push(idx as i32); - } - - // k closest USD price values - const kClosestPrices: CustomPriceType[] = []; - for (let i = 0; i < minDiffAtIdx.length; i++) { - if (!kClosestPrices.includes(pricesSorted[minDiffAtIdx[i]])) { - kClosestPrices.push(pricesSorted[minDiffAtIdx[i]]); - } - if (!kClosestPrices.includes(pricesSorted[minDiffAtIdx[i] + 1])) { - kClosestPrices.push(pricesSorted[minDiffAtIdx[i] + 1]); - } - } - - return kClosestPrices; -} - -export function averagePrice(prices: CustomPriceType[]): CustomPriceType { - let summationUSDPrice = constants.BIGDECIMAL_ZERO; - for (let i = 0; i < prices.length; i++) { - summationUSDPrice = summationUSDPrice.plus(prices[i].usdPrice); - } - - return CustomPriceType.initialize( - summationUSDPrice.div(new BigDecimal(BigInt.fromI32(prices.length as i32))), - constants.DEFAULT_USDC_DECIMALS - ); -} diff --git a/subgraphs/ebtc/src/prices/config/arbitrum.ts b/subgraphs/ebtc/src/prices/config/arbitrum.ts index 145692b274..b95c07b52c 100644 --- a/subgraphs/ebtc/src/prices/config/arbitrum.ts +++ b/subgraphs/ebtc/src/prices/config/arbitrum.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "arbitrum-one"; @@ -136,11 +135,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/aurora.ts b/subgraphs/ebtc/src/prices/config/aurora.ts index 628013c4bf..8cd2f4a42e 100644 --- a/subgraphs/ebtc/src/prices/config/aurora.ts +++ b/subgraphs/ebtc/src/prices/config/aurora.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "aurora"; @@ -123,11 +122,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/avalanche.ts b/subgraphs/ebtc/src/prices/config/avalanche.ts index 5d181039be..70e23839d8 100644 --- a/subgraphs/ebtc/src/prices/config/avalanche.ts +++ b/subgraphs/ebtc/src/prices/config/avalanche.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "avalanche"; @@ -130,11 +129,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/bsc.ts b/subgraphs/ebtc/src/prices/config/bsc.ts index ecef0f8d3e..d79139fca2 100644 --- a/subgraphs/ebtc/src/prices/config/bsc.ts +++ b/subgraphs/ebtc/src/prices/config/bsc.ts @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-magic-numbers */ import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "bsc"; @@ -120,11 +120,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/celo.ts b/subgraphs/ebtc/src/prices/config/celo.ts index 2318f6b643..45ad9469f4 100644 --- a/subgraphs/ebtc/src/prices/config/celo.ts +++ b/subgraphs/ebtc/src/prices/config/celo.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "celo"; @@ -122,11 +121,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/cronos.ts b/subgraphs/ebtc/src/prices/config/cronos.ts index f847104822..d47070c52b 100644 --- a/subgraphs/ebtc/src/prices/config/cronos.ts +++ b/subgraphs/ebtc/src/prices/config/cronos.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "cronos"; @@ -121,11 +120,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/fantom.ts b/subgraphs/ebtc/src/prices/config/fantom.ts index 9d461b497a..afec8235f5 100644 --- a/subgraphs/ebtc/src/prices/config/fantom.ts +++ b/subgraphs/ebtc/src/prices/config/fantom.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "fantom"; @@ -135,11 +134,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/fuse.ts b/subgraphs/ebtc/src/prices/config/fuse.ts index 2392dba83d..c8b308b2b7 100644 --- a/subgraphs/ebtc/src/prices/config/fuse.ts +++ b/subgraphs/ebtc/src/prices/config/fuse.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "fuse"; @@ -122,11 +121,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/gnosis.ts b/subgraphs/ebtc/src/prices/config/gnosis.ts index 8c4abb1db8..cacea20084 100644 --- a/subgraphs/ebtc/src/prices/config/gnosis.ts +++ b/subgraphs/ebtc/src/prices/config/gnosis.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING: string = "xdai"; @@ -124,11 +123,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/goerli.ts b/subgraphs/ebtc/src/prices/config/goerli.ts index fce77fa2fc..ff353b4923 100644 --- a/subgraphs/ebtc/src/prices/config/goerli.ts +++ b/subgraphs/ebtc/src/prices/config/goerli.ts @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/no-magic-numbers */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "goerli"; @@ -120,11 +119,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/harmony.ts b/subgraphs/ebtc/src/prices/config/harmony.ts index 4ed750f8ca..eeea74d9be 100644 --- a/subgraphs/ebtc/src/prices/config/harmony.ts +++ b/subgraphs/ebtc/src/prices/config/harmony.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "harmony"; @@ -126,11 +125,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/mainnet.ts b/subgraphs/ebtc/src/prices/config/mainnet.ts index b8681b603d..44d3589ab5 100644 --- a/subgraphs/ebtc/src/prices/config/mainnet.ts +++ b/subgraphs/ebtc/src/prices/config/mainnet.ts @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/no-magic-numbers */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "mainnet"; @@ -97,61 +96,6 @@ export const HARDCODED_STABLES: Address[] = [ Address.fromString("0xd71ecff9342a5ced620049e616c5035f1db98620"), // Synth sEUR ]; -/////////////////////////////////////////////////////////////////////////// -///////////////////////// ORACLE CONFIG OVERRIDES ///////////////////////// -/////////////////////////////////////////////////////////////////////////// - -// https://github.com/messari/subgraphs/issues/2090 -class spellOverride implements OracleConfig { - oracleCount(): number { - return constants.INT_ONE; - } - oracleOrder(): string[] { - return [ - constants.OracleType.CHAINLINK_FEED, - constants.OracleType.CURVE_CALCULATIONS, - constants.OracleType.SUSHI_CALCULATIONS, - constants.OracleType.CURVE_ROUTER, - constants.OracleType.UNISWAP_FORKS_ROUTER, - constants.OracleType.YEARN_LENS_ORACLE, - ]; - } -} - -// https://github.com/messari/subgraphs/issues/726 -class stETHOverride implements OracleConfig { - oracleCount(): number { - return constants.INT_ONE; - } - oracleOrder(): string[] { - return [ - constants.OracleType.CHAINLINK_FEED, - constants.OracleType.CURVE_CALCULATIONS, - constants.OracleType.SUSHI_CALCULATIONS, - constants.OracleType.CURVE_ROUTER, - constants.OracleType.UNISWAP_FORKS_ROUTER, - constants.OracleType.YEARN_LENS_ORACLE, - ]; - } -} - -// https://github.com/messari/subgraphs/issues/2097 -class baxaOverride implements OracleConfig { - oracleCount(): number { - return constants.INT_ONE; - } - oracleOrder(): string[] { - return [ - constants.OracleType.UNISWAP_FORKS_ROUTER, - constants.OracleType.YEARN_LENS_ORACLE, - constants.OracleType.CHAINLINK_FEED, - constants.OracleType.CURVE_CALCULATIONS, - constants.OracleType.CURVE_ROUTER, - constants.OracleType.SUSHI_CALCULATIONS, - ]; - } -} - /////////////////////////////////////////////////////////////////////////// ///////////////////////////////// HELPERS ///////////////////////////////// /////////////////////////////////////////////////////////////////////////// @@ -228,41 +172,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - if (tokenAddr || block) { - if ( - tokenAddr && - [ - Address.fromString("0x090185f2135308bad17527004364ebcc2d37e5f6"), // SPELL - ].includes(tokenAddr) - ) { - return new spellOverride(); - } - if ( - tokenAddr && - [ - Address.fromString("0xae7ab96520de3a18e5e111b5eaab095312d7fe84"), // stETH - ].includes(tokenAddr) && - block && - block.number.gt(BigInt.fromString("14019699")) && - block.number.lt(BigInt.fromString("14941265")) - ) { - return new stETHOverride(); - } - if ( - tokenAddr && - [ - Address.fromString("0x91b08f4a7c1251dfccf5440f8894f8daa10c8de5"), // BAXA - ].includes(tokenAddr) - ) { - return new baxaOverride(); - } - } - - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/moonbeam.ts b/subgraphs/ebtc/src/prices/config/moonbeam.ts index 91b3002639..85bf1c1ed7 100644 --- a/subgraphs/ebtc/src/prices/config/moonbeam.ts +++ b/subgraphs/ebtc/src/prices/config/moonbeam.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "moonbeam"; @@ -123,11 +122,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/optimism.ts b/subgraphs/ebtc/src/prices/config/optimism.ts index 14a271641f..5fa69e7e31 100644 --- a/subgraphs/ebtc/src/prices/config/optimism.ts +++ b/subgraphs/ebtc/src/prices/config/optimism.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ -import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "optimism"; @@ -135,11 +134,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/polygon.ts b/subgraphs/ebtc/src/prices/config/polygon.ts index 55d2778512..dbbc217c42 100644 --- a/subgraphs/ebtc/src/prices/config/polygon.ts +++ b/subgraphs/ebtc/src/prices/config/polygon.ts @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ -import * as constants from "../common/constants"; -import { BigInt, Address, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import { BigInt, Address } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "matic"; @@ -129,11 +128,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return null; - } } diff --git a/subgraphs/ebtc/src/prices/config/template.ts b/subgraphs/ebtc/src/prices/config/template.ts index b470ccbed3..622780c561 100644 --- a/subgraphs/ebtc/src/prices/config/template.ts +++ b/subgraphs/ebtc/src/prices/config/template.ts @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/no-magic-numbers, @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-magic-numbers */ import * as constants from "../common/constants"; -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; -import { Configurations, OracleConfig, OracleContract } from "../common/types"; +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { Configurations, OracleContract } from "../common/types"; export const NETWORK_STRING = "default"; @@ -42,26 +42,6 @@ export const SUSHI_CALCULATIONS_BLACKSLIST: Address[] = []; export const HARDCODED_STABLES: Address[] = []; -/////////////////////////////////////////////////////////////////////////// -///////////////////////// ORACLE CONFIG OVERRIDES ///////////////////////// -/////////////////////////////////////////////////////////////////////////// - -class someOverride implements OracleConfig { - oracleCount(): number { - return constants.INT_ONE; - } - oracleOrder(): string[] { - return [ - constants.OracleType.YEARN_LENS_ORACLE, - constants.OracleType.CHAINLINK_FEED, - constants.OracleType.CURVE_CALCULATIONS, - constants.OracleType.SUSHI_CALCULATIONS, - constants.OracleType.CURVE_ROUTER, - constants.OracleType.UNISWAP_FORKS_ROUTER, - ]; - } -} - /////////////////////////////////////////////////////////////////////////// ///////////////////////////////// HELPERS ///////////////////////////////// /////////////////////////////////////////////////////////////////////////// @@ -132,11 +112,4 @@ export class config implements Configurations { usdcTokenDecimals(): BigInt { return USDC_TOKEN_DECIMALS; } - - getOracleOverride( - tokenAddr: Address | null, - block: ethereum.Block | null - ): OracleConfig | null { - return new someOverride(); - } } diff --git a/subgraphs/ebtc/src/prices/index.ts b/subgraphs/ebtc/src/prices/index.ts index 7dcd1ced4f..3a2c0ce408 100644 --- a/subgraphs/ebtc/src/prices/index.ts +++ b/subgraphs/ebtc/src/prices/index.ts @@ -5,7 +5,7 @@ import { BigDecimal, dataSource, } from "@graphprotocol/graph-ts"; -import { CustomPriceType, OracleType } from "./common/types"; +import { CustomPriceType } from "./common/types"; import * as utils from "./common/utils"; import * as constants from "./common/constants"; @@ -41,93 +41,88 @@ export function getUsdPricePerToken( ); } - const oracle = new OracleType(); - const override = config.getOracleOverride(tokenAddr, block); - if (override) { - oracle.setOracleConfig(override); + // 1. Yearn Lens Oracle + const yearnLensPrice = YearnLensOracle.getTokenPriceUSDC(tokenAddr, block); + if (!yearnLensPrice.reverted) { + log.info("[YearnLensOracle] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + yearnLensPrice.usdPrice.toString(), + ]); + return yearnLensPrice; } - const oracleCount = oracle.oracleCount; - const oracleOrder = oracle.oracleOrder; - - const prices: CustomPriceType[] = []; - for (let i = 0; i < oracleOrder.length; i++) { - if (prices.length >= oracleCount) { - break; - } - - let oraclePrice = new CustomPriceType(); - - if (oracleOrder[i] == constants.OracleType.YEARN_LENS_ORACLE) { - oraclePrice = YearnLensOracle.getTokenPriceUSDC(tokenAddr, block); - } else if (oracleOrder[i] == constants.OracleType.CHAINLINK_FEED) { - oraclePrice = ChainLinkFeed.getTokenPriceUSDC(tokenAddr, block); - } else if (oracleOrder[i] == constants.OracleType.CURVE_CALCULATIONS) { - oraclePrice = CurveCalculations.getTokenPriceUSDC(tokenAddr, block); - } else if (oracleOrder[i] == constants.OracleType.SUSHI_CALCULATIONS) { - oraclePrice = SushiCalculations.getTokenPriceUSDC(tokenAddr, block); - } else if (oracleOrder[i] == constants.OracleType.AAVE_ORACLE) { - oraclePrice = AaveOracle.getTokenPriceUSDC(tokenAddr, block); - } else if (oracleOrder[i] == constants.OracleType.CURVE_ROUTER) { - oraclePrice = CurveRouter.getCurvePriceUsdc(tokenAddr, block); - } else if (oracleOrder[i] == constants.OracleType.UNISWAP_FORKS_ROUTER) { - oraclePrice = UniswapForksRouter.getTokenPriceUSDC(tokenAddr, block); - } - - if (!oraclePrice.reverted) { - prices.push(oraclePrice); - } + + // 2. ChainLink Feed Registry + const chainLinkPrice = ChainLinkFeed.getTokenPriceUSDC(tokenAddr, block); + if (!chainLinkPrice.reverted) { + log.info("[ChainLinkFeed] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + chainLinkPrice.usdPrice.toString(), + ]); + return chainLinkPrice; } - if (prices.length == constants.INT_ZERO) { - log.warning("[Oracle] Failed to Fetch Price, tokenAddr: {}", [ + // 3. CalculationsCurve + const calculationsCurvePrice = CurveCalculations.getTokenPriceUSDC( + tokenAddr, + block + ); + if (!calculationsCurvePrice.reverted) { + log.info("[CalculationsCurve] tokenAddress: {}, Price: {}", [ tokenAddr.toHexString(), + calculationsCurvePrice.usdPrice.toString(), ]); + return calculationsCurvePrice; + } - return new CustomPriceType(); - } else if (prices.length == constants.INT_ONE) { - return prices[constants.INT_ZERO]; - } else if (prices.length == constants.INT_TWO) { - return utils.averagePrice(prices); + // 4. CalculationsSushiSwap + const calculationsSushiSwapPrice = SushiCalculations.getTokenPriceUSDC( + tokenAddr, + block + ); + if (!calculationsSushiSwapPrice.reverted) { + log.info("[CalculationsSushiSwap] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + calculationsSushiSwapPrice.usdPrice.toString(), + ]); + return calculationsSushiSwapPrice; } - const k = Math.ceil(prices.length / constants.INT_TWO) as i32; - const closestPrices = utils.kClosestPrices(k, prices); + // 6. Aave Oracle + const aaveOraclePrice = AaveOracle.getTokenPriceUSDC(tokenAddr, block); + if (!aaveOraclePrice.reverted) { + log.info("[AaveOracle] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + aaveOraclePrice.usdPrice.toString(), + ]); + return aaveOraclePrice; + } - return utils.averagePrice(closestPrices); -} + // 7. Curve Router + const curvePrice = CurveRouter.getCurvePriceUsdc(tokenAddr, block); + if (!curvePrice.reverted) { + log.info("[CurveRouter] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + curvePrice.usdPrice.toString(), + ]); + return curvePrice; + } -export function getLiquidityBoundPrice( - tokenAddress: Address, - tokenPrice: CustomPriceType, - amount: BigDecimal -): BigDecimal { - const reportedPriceUSD = tokenPrice.usdPrice.times(amount); - const liquidity = tokenPrice.liquidity; - - let liquidityBoundPriceUSD = reportedPriceUSD; - if (liquidity > constants.BIGDECIMAL_ZERO && reportedPriceUSD > liquidity) { - liquidityBoundPriceUSD = liquidity - .div( - constants.BIGINT_TEN.pow( - constants.DEFAULT_USDC_DECIMALS as u8 - ).toBigDecimal() - ) - .times(constants.BIGINT_TEN.pow(tokenPrice.decimals as u8).toBigDecimal()) - .div(amount); - - log.warning( - "[getLiquidityBoundPrice] reported (token price * amount): ({} * {}) bound to: {} for token: {} due to insufficient liquidity: {}", - [ - tokenPrice.usdPrice.toString(), - amount.toString(), - liquidityBoundPriceUSD.toString(), - tokenAddress.toHexString(), - liquidity.toString(), - ] - ); + // 8. Uniswap Router + const uniswapPrice = UniswapForksRouter.getTokenPriceUSDC(tokenAddr, block); + if (!uniswapPrice.reverted) { + log.info("[UniswapRouter] tokenAddress: {}, Price: {}", [ + tokenAddr.toHexString(), + uniswapPrice.usdPrice.toString(), + ]); + return uniswapPrice; } - return liquidityBoundPriceUSD; + log.warning("[Oracle] Failed to Fetch Price, Name: {} Address: {}", [ + utils.getTokenName(tokenAddr), + tokenAddr.toHexString(), + ]); + + return new CustomPriceType(); } export function getUsdPrice( @@ -138,12 +133,6 @@ export function getUsdPrice( const tokenPrice = getUsdPricePerToken(tokenAddr, block); if (!tokenPrice.reverted) { - if ( - tokenPrice.oracleType == constants.OracleType.UNISWAP_FORKS_ROUTER || - tokenPrice.oracleType == constants.OracleType.CURVE_ROUTER - ) { - return getLiquidityBoundPrice(tokenAddr, tokenPrice, amount); - } return tokenPrice.usdPrice.times(amount); } diff --git a/subgraphs/ebtc/src/prices/routers/CurveRouter.ts b/subgraphs/ebtc/src/prices/routers/CurveRouter.ts index 36d8349e42..f25e55d86e 100644 --- a/subgraphs/ebtc/src/prices/routers/CurveRouter.ts +++ b/subgraphs/ebtc/src/prices/routers/CurveRouter.ts @@ -91,13 +91,10 @@ export function getCurvePriceUsdc( constants.BIGINT_TEN.pow(decimalsAdjustment.toI32() as u8).toBigDecimal() ); - const liquidity = getLpTokenLiquidityUsdc(lpAddress, block); - return CustomPriceType.initialize( priceUsdc, decimalsAdjustment.plus(constants.DEFAULT_DECIMALS).toI32() as u8, - constants.OracleType.CURVE_ROUTER, - liquidity.usdPrice + constants.OracleType.CURVE_ROUTER ); } @@ -328,41 +325,3 @@ export function getPriceUsdc( constants.OracleType.CURVE_ROUTER ); } - -function getLpTokenLiquidityUsdc( - lpAddress: Address, - block: ethereum.Block | null = null -): CustomPriceType { - const poolAddress = getPoolFromLpToken(lpAddress, block); - const poolContract = CurvePoolContract.bind(poolAddress); - - let liquidity = constants.BIGDECIMAL_ZERO; - for (let i = 0; i < 8; i++) { - const coin = utils.readValue
( - poolContract.try_coins(BigInt.fromI32(i)), - constants.NULL.TYPE_ADDRESS - ); - if (coin.equals(constants.NULL.TYPE_ADDRESS) || coin.equals(lpAddress)) - continue; - - const decimals = utils.getTokenDecimals(coin); - const balance = utils.readValue( - poolContract.try_balances(BigInt.fromI32(i as i32)), - constants.BIGINT_ZERO - ); - - const price = getPriceUsdcRecommended(coin, block); - liquidity = liquidity.plus( - balance - .div(constants.BIGINT_TEN.pow(decimals.toI32() as u8)) - .toBigDecimal() - .times(price.usdPrice) - ); - } - - return CustomPriceType.initialize( - liquidity, - constants.DEFAULT_USDC_DECIMALS, - constants.OracleType.CURVE_ROUTER - ); -} diff --git a/subgraphs/ebtc/src/prices/routers/UniswapForksRouter.ts b/subgraphs/ebtc/src/prices/routers/UniswapForksRouter.ts index ec2031aad6..a39cb74cbb 100644 --- a/subgraphs/ebtc/src/prices/routers/UniswapForksRouter.ts +++ b/subgraphs/ebtc/src/prices/routers/UniswapForksRouter.ts @@ -5,7 +5,6 @@ import { CustomPriceType } from "../common/types"; import { Address, BigInt, ethereum, log } from "@graphprotocol/graph-ts"; import { UniswapPair as UniswapPairContract } from "../../../generated/PriceFeed/UniswapPair"; import { UniswapRouter as UniswapRouterContract } from "../../../generated/PriceFeed/UniswapRouter"; -import { UniswapFactory as UniswapFactoryContract } from "../../../generated/PriceFeed/UniswapFactory"; export function isLpToken(tokenAddress: Address, ethAddress: Address): bool { if (tokenAddress.equals(ethAddress)) return false; @@ -86,17 +85,15 @@ export function getPriceFromRouter( const routerAddresses = config.uniswapForks(); - let routerAddress = constants.NULL.TYPE_ADDRESS; let amountOut = constants.BIGINT_ZERO; for (let idx = 0; idx < routerAddresses.length; idx++) { - const router = routerAddresses[idx]; - if (block && router.startBlock.gt(block.number)) continue; + const routerAddress = routerAddresses[idx]; + if (block && routerAddress.startBlock.gt(block.number)) continue; - const uniswapForkRouter = UniswapRouterContract.bind(router.address); + const uniswapForkRouter = UniswapRouterContract.bind(routerAddress.address); const amountOutArray = uniswapForkRouter.try_getAmountsOut(amountIn, path); if (!amountOutArray.reverted) { - routerAddress = router.address; amountOut = amountOutArray.value[amountOutArray.value.length - 1]; break; } @@ -109,37 +106,11 @@ export function getPriceFromRouter( .div(constants.BIGINT_TEN_THOUSAND.minus(feeBips.times(numberOfJumps))) .toBigDecimal(); - const priceFromRouter = CustomPriceType.initialize( + return CustomPriceType.initialize( amountOutBigDecimal, config.usdcTokenDecimals().toI32() as u8, constants.OracleType.UNISWAP_FORKS_ROUTER ); - - const routerContract = UniswapRouterContract.bind(routerAddress); - const factoryAddress = utils.readValue( - routerContract.try_factory(), - constants.NULL.TYPE_ADDRESS - ); - if (factoryAddress.equals(constants.NULL.TYPE_ADDRESS)) - return priceFromRouter; - - const factoryContract = UniswapFactoryContract.bind(factoryAddress); - let tokenPair = utils.readValue( - factoryContract.try_getPair(token0Address, wethAddress), - constants.NULL.TYPE_ADDRESS - ); - if (tokenPair.equals(constants.NULL.TYPE_ADDRESS)) { - tokenPair = utils.readValue( - factoryContract.try_getPair(wethAddress, token0Address), - constants.NULL.TYPE_ADDRESS - ); - } - if (tokenPair.equals(constants.NULL.TYPE_ADDRESS)) return priceFromRouter; - - const liquidityUSD = getLpTokenLiquidityUsdc(tokenPair, block); - priceFromRouter.setLiquidity(liquidityUSD.usdPrice); - - return priceFromRouter; } export function getLpTokenPriceUsdc( @@ -230,17 +201,13 @@ export function getLpTokenTotalLiquidityUsdc( reserve1.notEqual(constants.BIGINT_ZERO) ) { const liquidity0 = reserve0 + .div(constants.BIGINT_TEN.pow(token0Decimals.toI32() as u8)) .toBigDecimal() - .div( - constants.BIGINT_TEN.pow(token0Decimals.toI32() as u8).toBigDecimal() - ) .times(token0Price.usdPrice); const liquidity1 = reserve1 + .div(constants.BIGINT_TEN.pow(token1Decimals.toI32() as u8)) .toBigDecimal() - .div( - constants.BIGINT_TEN.pow(token1Decimals.toI32() as u8).toBigDecimal() - ) .times(token1Price.usdPrice); const totalLiquidity = liquidity0.plus(liquidity1); @@ -253,47 +220,3 @@ export function getLpTokenTotalLiquidityUsdc( } return new CustomPriceType(); } - -function getLpTokenLiquidityUsdc( - lpAddress: Address, - block: ethereum.Block | null = null -): CustomPriceType { - const uniSwapPair = UniswapPairContract.bind(lpAddress); - - const token1Address = utils.readValue
( - uniSwapPair.try_token1(), - constants.NULL.TYPE_ADDRESS - ); - if (token1Address.equals(constants.NULL.TYPE_ADDRESS)) { - return new CustomPriceType(); - } - - const token1Price = getTokenPriceUSDC(token1Address, block); - if (token1Price.reverted) { - return new CustomPriceType(); - } - - const token1Decimals = utils.getTokenDecimals(token1Address); - - const reservesCall = uniSwapPair.try_getReserves(); - if (reservesCall.reverted) return new CustomPriceType(); - - const reserves = reservesCall.value; - const reserve1 = reserves.value1; - - if (reserve1.notEqual(constants.BIGINT_ZERO)) { - const liquidity1 = reserve1 - .toBigDecimal() - .div( - constants.BIGINT_TEN.pow(token1Decimals.toI32() as u8).toBigDecimal() - ) - .times(token1Price.usdPrice); - - return CustomPriceType.initialize( - liquidity1, - constants.DEFAULT_USDC_DECIMALS, - constants.OracleType.UNISWAP_FORKS_ROUTER - ); - } - return new CustomPriceType(); -} From fcaca037e98d6d02d80808cafc61794744e40e75 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 11 Jul 2023 13:29:03 +0200 Subject: [PATCH 37/52] chore: move `handelSystemDeployed` to `ActivePool` --- subgraphs/ebtc/src/mapping/ActivePool.ts | 56 ++++++++++++++++++++-- subgraphs/ebtc/src/mapping/CdpManager.ts | 61 +----------------------- 2 files changed, 55 insertions(+), 62 deletions(-) diff --git a/subgraphs/ebtc/src/mapping/ActivePool.ts b/subgraphs/ebtc/src/mapping/ActivePool.ts index 6cf7991b1e..4105488593 100644 --- a/subgraphs/ebtc/src/mapping/ActivePool.ts +++ b/subgraphs/ebtc/src/mapping/ActivePool.ts @@ -1,13 +1,63 @@ -import { Address } from "@graphprotocol/graph-ts"; +import { Address, log } from "@graphprotocol/graph-ts"; import { + ActivePool, ActivePoolCollBalanceUpdated, ActivePoolEBTCDebtUpdated, + CdpManagerAddressChanged, FlashLoanSuccess, } from "../../generated/ActivePool/ActivePool"; -import { getDataManager, STETH_ADDRESS } from "../constants"; +import { + ACTIVE_POOL, + EBTC_ADDRESS, + LIQUIDATION_FEE_PERCENT, + MAXIMUM_LTV, + PRICE_FEED, + STETH_ADDRESS, + getDataManager, + getProtocolData, +} from "../constants"; import { TokenManager } from "../sdk/token"; import { getUsdPrice } from "../prices"; -import { BIGINT_TEN_TO_EIGHTEENTH } from "../sdk/util/constants"; +import { BIGINT_TEN_TO_EIGHTEENTH, OracleSource } from "../sdk/util/constants"; + +/** + * On deployment of the pool, initialise and populate the market, + * lendingProtocol and oracle entities. + * @param event An event emitted by the constructor of the ActivePool proving + * it was deployed successfully. + */ +export function handleSystemDeployed(event: CdpManagerAddressChanged): void { + const activePool = ActivePool.bind(event.address); + if (activePool._address != ACTIVE_POOL) { + // quick check to make sure our configurations.json is correct + log.error( + "deployed ActivePool address {} does not match expected address", + [event.address.toHexString()] + ); + return; + } + + const dataManager = getDataManager(event); + + // update market with ebtc specifics + const market = dataManager.getMarket(); + market.canBorrowFrom = true; + market.maximumLTV = MAXIMUM_LTV; + market.liquidationThreshold = MAXIMUM_LTV; + market.liquidationPenalty = LIQUIDATION_FEE_PERCENT; + market.borrowedToken = EBTC_ADDRESS; + market.save(); + + const lendingProtocol = dataManager.getOrCreateLendingProtocol( + getProtocolData() // data: ProtocolData + ); + + const oracle = dataManager.getOrCreateOracle( + Address.fromBytes(PRICE_FEED), // oracleAddress: Address + false, // isUSD: boolean + OracleSource.CHAINLINK // source?: string + ); +} /** * Total stETH collateral was updated diff --git a/subgraphs/ebtc/src/mapping/CdpManager.ts b/subgraphs/ebtc/src/mapping/CdpManager.ts index 1077a21174..5284222b80 100644 --- a/subgraphs/ebtc/src/mapping/CdpManager.ts +++ b/subgraphs/ebtc/src/mapping/CdpManager.ts @@ -1,66 +1,9 @@ -import { Address, log } from "@graphprotocol/graph-ts"; -import { - ActivePool, - CdpManagerAddressChanged, -} from "../../generated/ActivePool/ActivePool"; import { CdpUpdated } from "../../generated/CdpManager/CdpManager"; import { AccountManager } from "../sdk/account"; import { PositionManager } from "../sdk/position"; import { TokenManager } from "../sdk/token"; -import { - OracleSource, - PositionSide, - TransactionType, -} from "../sdk/util/constants"; -import { - ACTIVE_POOL, - EBTC_ADDRESS, - LIQUIDATION_FEE_PERCENT, - MAXIMUM_LTV, - PRICE_FEED, - getProtocolData, - getDataManager, - STETH_ADDRESS, -} from "../constants"; - -/** - * On deployment of the pool, initialise and populate the market, - * lendingProtocol and oracle entities. - * @param event An event emitted by the constructor of the ActivePool proving - * it was deployed successfully. - */ -export function handleSystemDeployed(event: CdpManagerAddressChanged): void { - const activePool = ActivePool.bind(event.address); - if (activePool._address != ACTIVE_POOL) { - // quick check to make sure our configurations.json is correct - log.error( - "deployed ActivePool address {} does not match expected address", - [event.address.toHexString()] - ); - return; - } - - const dataManager = getDataManager(event); - - // update market with ebtc specifics - const market = dataManager.getMarket(); - market.canBorrowFrom = true; - market.maximumLTV = MAXIMUM_LTV; - market.liquidationThreshold = MAXIMUM_LTV; - market.liquidationPenalty = LIQUIDATION_FEE_PERCENT; - market.borrowedToken = EBTC_ADDRESS; - market.save(); - - const lendingProtocol = dataManager.getOrCreateLendingProtocol( - getProtocolData() // data: ProtocolData - ); - - const oracle = dataManager.getOrCreateOracle( - Address.fromBytes(PRICE_FEED), // oracleAddress: Address - false, // isUSD: boolean - OracleSource.CHAINLINK // source?: string - ); -} +import { PositionSide, TransactionType } from "../sdk/util/constants"; +import { getProtocolData, getDataManager, STETH_ADDRESS } from "../constants"; /** * Make necessary adjustments to the system when a CDP changes. From 0b7e947a05998e6dd95ab6ca022e35472d3fa442 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 11 Jul 2023 13:31:03 +0200 Subject: [PATCH 38/52] fix: `handleSystemDeployed` is now in `ActivePool` --- .../ebtc/protocols/ebtc/config/templates/ebtc.template.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index 2463765778..1a27054c94 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -20,8 +20,6 @@ dataSources: - name: CdpManager file: ./abis/CdpManager.json eventHandlers: - - event: ActivePoolAddressChanged(address) - handler: handleSystemDeployed - event: CdpUpdated(indexed bytes32,indexed address,uint256,uint256,uint256,uint256,uint256,uint8) handler: handleCdpUpdated - name: ActivePool @@ -41,6 +39,8 @@ dataSources: - name: ActivePool file: ./abis/ActivePool.json eventHandlers: + - event: ActivePoolAddressChanged(address) + handler: handleSystemDeployed - event: ActivePoolCollBalanceUpdated(uint256) handler: handleActivePoolCollBalanceUpdated - event: ActivePoolEBTCDebtUpdated(uint256) From af160cd9d5063f88221480343ea811bf68184719 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 11 Jul 2023 14:49:52 +0200 Subject: [PATCH 39/52] fix: each data source needs its reference to the jsons --- .../ebtc/config/templates/ebtc.template.yaml | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index 1a27054c94..e62f8b0e14 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -38,6 +38,44 @@ dataSources: abis: - name: ActivePool file: ./abis/ActivePool.json + ########################################### + ############## Price Oracle ############### + ########################################### + # ERC20 + - name: _ERC20 + file: ./abis/Prices/ERC20.json + - name: ERC20 + file: ./abis/ERC20.json + - name: ERC20NameBytes + file: ./abis/ERC20NameBytes.json + - name: ERC20SymbolBytes + file: ./abis/ERC20SymbolBytes.json + # Curve Contracts + - name: CurvePool + file: ./abis/Prices/Curve/Pool.json + - name: CurveRegistry + file: ./abis/Prices/Curve/Registry.json + - name: CalculationsCurve + file: ./abis/Prices/Calculations/Curve.json + # YearnLens Contracts + - name: YearnLensContract + file: ./abis/Prices/YearnLens.json + # Aave Oracle Contract + - name: AaveOracleContract + file: ./abis/Prices/AaveOracle.json + # SushiSwap Contracts + - name: CalculationsSushiSwap + file: ./abis/Prices/Calculations/SushiSwap.json + # ChainLink Contracts + - name: ChainLinkContract + file: ./abis/Prices/ChainLink.json + # Uniswap Contracts + - name: UniswapRouter + file: ./abis/Prices/Uniswap/Router.json + - name: UniswapFactory + file: ./abis/Prices/Uniswap/Factory.json + - name: UniswapPair + file: ./abis/Prices/Uniswap/Pair.json eventHandlers: - event: ActivePoolAddressChanged(address) handler: handleSystemDeployed @@ -72,6 +110,44 @@ dataSources: abis: - name: BorrowerOperations file: ./abis/BorrowerOperations.json + ########################################### + ############## Price Oracle ############### + ########################################### + # ERC20 + - name: _ERC20 + file: ./abis/Prices/ERC20.json + - name: ERC20 + file: ./abis/ERC20.json + - name: ERC20NameBytes + file: ./abis/ERC20NameBytes.json + - name: ERC20SymbolBytes + file: ./abis/ERC20SymbolBytes.json + # Curve Contracts + - name: CurvePool + file: ./abis/Prices/Curve/Pool.json + - name: CurveRegistry + file: ./abis/Prices/Curve/Registry.json + - name: CalculationsCurve + file: ./abis/Prices/Calculations/Curve.json + # YearnLens Contracts + - name: YearnLensContract + file: ./abis/Prices/YearnLens.json + # Aave Oracle Contract + - name: AaveOracleContract + file: ./abis/Prices/AaveOracle.json + # SushiSwap Contracts + - name: CalculationsSushiSwap + file: ./abis/Prices/Calculations/SushiSwap.json + # ChainLink Contracts + - name: ChainLinkContract + file: ./abis/Prices/ChainLink.json + # Uniswap Contracts + - name: UniswapRouter + file: ./abis/Prices/Uniswap/Router.json + - name: UniswapFactory + file: ./abis/Prices/Uniswap/Factory.json + - name: UniswapPair + file: ./abis/Prices/Uniswap/Pair.json eventHandlers: # - event: AuthorityUpdated(indexed address,indexed address) # - event: CdpCreated(indexed bytes32,indexed address,indexed address,uint256) From 3bccffb4d1a1eeef9815cb53cd7f34e6df8f4825 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 11 Jul 2023 14:50:16 +0200 Subject: [PATCH 40/52] fix: functions need to be exported explicitly --- .../ebtc/src/mapping/BorrowerOperations.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/subgraphs/ebtc/src/mapping/BorrowerOperations.ts b/subgraphs/ebtc/src/mapping/BorrowerOperations.ts index d6a735648c..0ae6cc3cb3 100644 --- a/subgraphs/ebtc/src/mapping/BorrowerOperations.ts +++ b/subgraphs/ebtc/src/mapping/BorrowerOperations.ts @@ -1,5 +1,6 @@ import { Address } from "@graphprotocol/graph-ts"; import { CdpUpdated } from "../../generated/BorrowerOperations/BorrowerOperations"; +import { FlashLoanSuccess } from "../../generated/ActivePool/ActivePool"; import { getUsdPrice } from "../prices"; import { BIGINT_TEN_TO_EIGHTEENTH, BIGINT_ZERO } from "../sdk/util/constants"; import { getDataManager, STETH_ADDRESS } from "../constants"; @@ -79,3 +80,25 @@ export function handleCdpUpdated(event: CdpUpdated): void { // receiverNewBalance: BigInt // ) } + +/** + * Create a flashloan object and handle its fee when a flashloan is successful. + * @param event FlashLoanSuccess The event emitted by BorrowerOperations when + * a flashloan is successful. + */ +export function handleFlashLoanSuccess(event: FlashLoanSuccess): void { + // TODO: this is a dupe of the same function in ActivePool.ts + // TODO: how to export imported functions? + const dataManager = getDataManager(event); + const flashloan = dataManager.createFlashloan( + Address.fromBytes(STETH_ADDRESS), // asset: Address + event.params._receiver, // account: Address + event.params._amount, // amount: BigInt + getUsdPrice( + Address.fromBytes(STETH_ADDRESS), + event.params._amount.div(BIGINT_TEN_TO_EIGHTEENTH).toBigDecimal(), + event.block + ) // amountUSD: BigDecimal + ); + // TODO: handle fee (event.params._fee) +} From 08e8a867c113c2dafcdbb3b358c6a6d82b4cefa3 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 12 Jul 2023 19:25:26 +0200 Subject: [PATCH 41/52] docs: add instructions for deploying a scaffold subgraph --- subgraphs/ebtc/NOTES.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/subgraphs/ebtc/NOTES.md b/subgraphs/ebtc/NOTES.md index e422636c8e..8ebee27b29 100644 --- a/subgraphs/ebtc/NOTES.md +++ b/subgraphs/ebtc/NOTES.md @@ -24,6 +24,18 @@ graph auth --product hosted-service *** messari b -l -s hosted-service ebtc -r badger-finance -d ``` +``` +graph init --product=hosted-service --protocol=ethereum --from-contract=0x7Cbde961F8aDB94c8A7660Abe1f3e647dbB8513f --network=goerli --index-events --start-block=9129595 --contract-name=CdpManager badger-finance/ebtc-goerli-scaffold + +cd ebtc-goerli-scaffold + +***change graph-cli and graph-ts version to "*" in package.json*** + +yarn + +yarn codegen && yarn build && yarn deploy +``` + **NOTE: Omit the `-d` for a dry run without deployment** ### Test GQL Queries From a5c7aed1c8ec1440c06ab3df3323c4b1f6a470c8 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 12 Jul 2023 19:38:52 +0200 Subject: [PATCH 42/52] chore: move `createLiquidate` to `CdpManager` --- .../ebtc/config/templates/ebtc.template.yaml | 29 +++++++++++++++++++ subgraphs/ebtc/src/mapping/CdpManager.ts | 10 +++++++ 2 files changed, 39 insertions(+) diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index e62f8b0e14..3523910112 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -20,8 +20,37 @@ dataSources: - name: CdpManager file: ./abis/CdpManager.json eventHandlers: + # - event: ActivePoolAddressChanged(address) + # - event: AuthorityUpdated(indexed address,indexed address) + # - event: BaseRateUpdated(uint256) + # - event: BetaSet(uint256) + # - event: BorrowerOperationsAddressChanged(address) + # - event: CdpFeeSplitApplied(bytes32,uint256,uint256,uint256,uint256) + # - event: CdpIndexUpdated(bytes32,uint256) + # - event: CdpLiquidated(indexed bytes32,indexed address,uint256,uint256,uint8) + # - event: CdpPartiallyLiquidated(indexed bytes32,indexed address,uint256,uint256,uint8) + # - event: CdpSnapshotsUpdated(bytes32,uint256) - event: CdpUpdated(indexed bytes32,indexed address,uint256,uint256,uint256,uint256,uint256,uint8) handler: handleCdpUpdated + # - event: CollSurplusPoolAddressChanged(address) + # - event: CollateralAddressChanged(address) + # - event: CollateralFeePerUnitUpdated(uint256,uint256,uint256) + # - event: CollateralGlobalIndexUpdated(uint256,uint256,uint256) + # - event: CollateralIndexUpdateIntervalUpdated(uint256,uint256) + # - event: EBTCTokenAddressChanged(address) + # - event: FeeRecipientAddressChanged(address) + # - event: LTermsUpdated(uint256) + # - event: LastFeeOpTimeUpdated(uint256) + # - event: Liquidation(uint256,uint256,uint256) + # - event: LiquidationLibraryAddressChanged(address) + # - event: MinuteDecayFactorSet(uint256) + # - event: PriceFeedAddressChanged(address) + # - event: Redemption(uint256,uint256,uint256,uint256) + # - event: RedemptionFeeFloorSet(uint256) + # - event: SortedCdpsAddressChanged(address) + # - event: StakingRewardSplitSet(uint256) + # - event: SystemSnapshotsUpdated(uint256,uint256) + # - event: TotalStakesUpdated(uint256) - name: ActivePool kind: ethereum/contract network: "{{ network.slug }}" diff --git a/subgraphs/ebtc/src/mapping/CdpManager.ts b/subgraphs/ebtc/src/mapping/CdpManager.ts index 5284222b80..3a0efe943a 100644 --- a/subgraphs/ebtc/src/mapping/CdpManager.ts +++ b/subgraphs/ebtc/src/mapping/CdpManager.ts @@ -33,4 +33,14 @@ export function handleCdpUpdated(event: CdpUpdated): void { positionManager.setCollateral(true); positionManager.setIsolation(true); } + + // createLiquidate( + // asset: Bytes + // liquidator: Address + // liquidatee: Address + // amount: BigInt + // amountUSD: BigDecimal + // profitUSD: BigDecimal + // newBalance: BigInt // repaid token balance for liquidatee + // ) } From a9c3dc3c4c7651a640ba8c383c1b4b32a0f24e70 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 14 Jul 2023 20:04:31 +0200 Subject: [PATCH 43/52] docs: extend query with lending protocol fields --- subgraphs/ebtc/QUERY.gql | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/subgraphs/ebtc/QUERY.gql b/subgraphs/ebtc/QUERY.gql index 993a2d4702..826f24eb29 100644 --- a/subgraphs/ebtc/QUERY.gql +++ b/subgraphs/ebtc/QUERY.gql @@ -22,6 +22,52 @@ totalPoolCount totalValueLockedUSD type + ... on LendingProtocol { + borrowCount + borrowerPermissionType + collateralizationType + cumulativeBorrowUSD + cumulativeDepositUSD + cumulativeLiquidateUSD + cumulativePositionCount + cumulativeProtocolSideRevenueUSD + cumulativeSupplySideRevenueUSD + cumulativeTotalRevenueUSD + cumulativeUniqueBorrowers + cumulativeUniqueDepositors + cumulativeUniqueLiquidatees + cumulativeUniqueLiquidators + cumulativeUniqueUsers + depositCount + flashloanCount + id + lenderPermissionType + lendingType + liquidationCount + methodologyVersion + mintedTokenSupplies + name + network + openPositionCount + poolCreatorPermissionType + protocol + protocolControlledValueUSD + repayCount + rewardTokenEmissionsAmount + rewardTokenEmissionsUSD + riskType + schemaVersion + slug + subgraphVersion + totalBorrowBalanceUSD + totalDepositBalanceUSD + totalPoolCount + totalValueLockedUSD + transactionCount + transferCount + type + withdrawCount + } } tokens { decimals From 1b9be2f764464035b8f5fc69f1247efdc88fb0e3 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 14 Jul 2023 20:14:22 +0200 Subject: [PATCH 44/52] feat: handle liquidations --- .../ebtc/config/templates/ebtc.template.yaml | 3 +- subgraphs/ebtc/src/mapping/CdpManager.ts | 69 +++++++++---------- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index 3523910112..5981797537 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -41,7 +41,8 @@ dataSources: # - event: FeeRecipientAddressChanged(address) # - event: LTermsUpdated(uint256) # - event: LastFeeOpTimeUpdated(uint256) - # - event: Liquidation(uint256,uint256,uint256) + - event: Liquidation(uint256,uint256,uint256) + handler: handleLiquidation # - event: LiquidationLibraryAddressChanged(address) # - event: MinuteDecayFactorSet(uint256) # - event: PriceFeedAddressChanged(address) diff --git a/subgraphs/ebtc/src/mapping/CdpManager.ts b/subgraphs/ebtc/src/mapping/CdpManager.ts index 3a0efe943a..b0a0bee26f 100644 --- a/subgraphs/ebtc/src/mapping/CdpManager.ts +++ b/subgraphs/ebtc/src/mapping/CdpManager.ts @@ -1,46 +1,43 @@ -import { CdpUpdated } from "../../generated/CdpManager/CdpManager"; -import { AccountManager } from "../sdk/account"; -import { PositionManager } from "../sdk/position"; -import { TokenManager } from "../sdk/token"; -import { PositionSide, TransactionType } from "../sdk/util/constants"; -import { getProtocolData, getDataManager, STETH_ADDRESS } from "../constants"; +import { CdpUpdated, Liquidation } from "../../generated/CdpManager/CdpManager"; +import { BIGINT_ZERO } from "../sdk/util/constants"; +import { getDataManager, STETH_ADDRESS } from "../constants"; +import { Address } from "@graphprotocol/graph-ts"; +import { getUsdPrice } from "../prices"; /** * Make necessary adjustments to the system when a CDP changes. * @param event The event emitted by the CdpManager when a CDP changes. */ export function handleCdpUpdated(event: CdpUpdated): void { - const dataManager = getDataManager(event); - const accountManager = new AccountManager(event.params._borrower); - const positionManager = new PositionManager( - accountManager.getAccount(), // account: Account - dataManager.getMarket(), // market: Market - PositionSide.COLLATERAL //side - ); - const stEthTokenManager = new TokenManager(STETH_ADDRESS, event); + // TODO +} - // TODO: there is also a subtractPosition method - positionManager.addPosition( - event, // event: ethereum.Event +/** + * Register a liquidation event. + * @param event Liquidation The event emitted by the CdpManager when a CDP is + * liquidated. + */ +export function handleLiquidation(event: Liquidation): void { + // TODO: event is missing the following data points: + // - liquidator + // - liquidatee + // - newBalance + const dataManager = getDataManager(event); + dataManager.createLiquidate( STETH_ADDRESS, // asset: Bytes - dataManager.getOrCreateLendingProtocol(getProtocolData()), // protocol: LendingProtocol - event.params._coll, // newBalance: BigInt - // TODO: obivously the transaction type needs to be determined properly - TransactionType.BORROW, // transactionType: string - stEthTokenManager.getPriceUSD() // priceUSD: BigDecimal + new Address(0), // liquidator: Address + new Address(0), // liquidatee: Address + event.params._liquidatedColl, // amount: BigInt + getUsdPrice( + Address.fromBytes(STETH_ADDRESS), + event.params._liquidatedColl.toBigDecimal(), + event.block + ), // amountUSD: BigDecimal + getUsdPrice( + Address.fromBytes(STETH_ADDRESS), + event.params._liqReward.toBigDecimal(), + event.block + ), // profitUSD: BigDecimal + BIGINT_ZERO // newBalance: BigInt // repaid token balance for liquidatee ); - if (positionManager.getPositionID()) { - positionManager.setCollateral(true); - positionManager.setIsolation(true); - } - - // createLiquidate( - // asset: Bytes - // liquidator: Address - // liquidatee: Address - // amount: BigInt - // amountUSD: BigDecimal - // profitUSD: BigDecimal - // newBalance: BigInt // repaid token balance for liquidatee - // ) } From 7714e365726f40fc01cb09d2d8f3761707b6466e Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 14 Jul 2023 20:16:27 +0200 Subject: [PATCH 45/52] fix: `CdpManager` needs price oracle abis --- .../ebtc/config/templates/ebtc.template.yaml | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index 5981797537..1f7ddc6c0d 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -19,6 +19,44 @@ dataSources: abis: - name: CdpManager file: ./abis/CdpManager.json + ########################################### + ############## Price Oracle ############### + ########################################### + # ERC20 + - name: _ERC20 + file: ./abis/Prices/ERC20.json + - name: ERC20 + file: ./abis/ERC20.json + - name: ERC20NameBytes + file: ./abis/ERC20NameBytes.json + - name: ERC20SymbolBytes + file: ./abis/ERC20SymbolBytes.json + # Curve Contracts + - name: CurvePool + file: ./abis/Prices/Curve/Pool.json + - name: CurveRegistry + file: ./abis/Prices/Curve/Registry.json + - name: CalculationsCurve + file: ./abis/Prices/Calculations/Curve.json + # YearnLens Contracts + - name: YearnLensContract + file: ./abis/Prices/YearnLens.json + # Aave Oracle Contract + - name: AaveOracleContract + file: ./abis/Prices/AaveOracle.json + # SushiSwap Contracts + - name: CalculationsSushiSwap + file: ./abis/Prices/Calculations/SushiSwap.json + # ChainLink Contracts + - name: ChainLinkContract + file: ./abis/Prices/ChainLink.json + # Uniswap Contracts + - name: UniswapRouter + file: ./abis/Prices/Uniswap/Router.json + - name: UniswapFactory + file: ./abis/Prices/Uniswap/Factory.json + - name: UniswapPair + file: ./abis/Prices/Uniswap/Pair.json eventHandlers: # - event: ActivePoolAddressChanged(address) # - event: AuthorityUpdated(indexed address,indexed address) From de0af46a5cf3161852ab1227dd3fa00477b1383f Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 14 Jul 2023 20:18:56 +0200 Subject: [PATCH 46/52] feat: add borrows and repays, fix when delta is zero --- .../ebtc/src/mapping/BorrowerOperations.ts | 70 ++++++++----------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/subgraphs/ebtc/src/mapping/BorrowerOperations.ts b/subgraphs/ebtc/src/mapping/BorrowerOperations.ts index 0ae6cc3cb3..62b4a60321 100644 --- a/subgraphs/ebtc/src/mapping/BorrowerOperations.ts +++ b/subgraphs/ebtc/src/mapping/BorrowerOperations.ts @@ -1,9 +1,9 @@ import { Address } from "@graphprotocol/graph-ts"; import { CdpUpdated } from "../../generated/BorrowerOperations/BorrowerOperations"; import { FlashLoanSuccess } from "../../generated/ActivePool/ActivePool"; -import { getUsdPrice } from "../prices"; +import { getUsdPrice, getUsdPricePerToken } from "../prices"; import { BIGINT_TEN_TO_EIGHTEENTH, BIGINT_ZERO } from "../sdk/util/constants"; -import { getDataManager, STETH_ADDRESS } from "../constants"; +import { EBTC_ADDRESS, getDataManager, STETH_ADDRESS } from "../constants"; /** * Create withdrawals, deposits, borrows, and repays when a CDP is updated. @@ -25,7 +25,8 @@ export function handleCdpUpdated(event: CdpUpdated): void { ), // amountUSD: BigDecimal event.params._debt // newBalance: BigInt ); - } else { + } + if (deltaColl < BIGINT_ZERO) { dataManager.createWithdraw( STETH_ADDRESS, // asset: Bytes event.params._borrower, // account: Bytes @@ -41,44 +42,33 @@ export function handleCdpUpdated(event: CdpUpdated): void { const deltaDebt = event.params._debt.minus(event.params._oldDebt); if (deltaDebt > BIGINT_ZERO) { - // createBorrow( - // asset: Bytes - // account: Bytes - // amount: BigInt - // amountUSD: BigDecimal - // newBalance: BigInt - // tokenPriceUSD: BigDecimal // used for different borrow token in CDP - // ) - } else { - // createRepay( - // asset: Bytes - // account: Bytes - // amount: BigInt - // amountUSD: BigDecimal - // newBalance: BigInt - // tokenPriceUSD: BigDecimal // used for different borrow token in CDP - // ) + dataManager.createBorrow( + EBTC_ADDRESS, // asset: Bytes + event.params._borrower, // account: Bytes + deltaDebt, // amount: BigInt + getUsdPrice( + Address.fromBytes(EBTC_ADDRESS), + deltaColl.div(BIGINT_TEN_TO_EIGHTEENTH).toBigDecimal(), + event.block + ), // amountUSD: BigDecimal + event.params._debt, // newBalance: BigInt + getUsdPricePerToken(Address.fromBytes(EBTC_ADDRESS)).usdPrice // tokenPriceUSD: BigDecimal // used for different borrow token in CDP + ); + } + if (deltaDebt < BIGINT_ZERO) { + dataManager.createRepay( + EBTC_ADDRESS, // asset: Bytes + event.params._borrower, // account: Bytes + deltaDebt, // amount: BigInt + getUsdPrice( + Address.fromBytes(EBTC_ADDRESS), + deltaColl.div(BIGINT_TEN_TO_EIGHTEENTH).toBigDecimal(), + event.block + ), // amountUSD: BigDecimal + event.params._coll, // newBalance: BigInt + getUsdPricePerToken(Address.fromBytes(EBTC_ADDRESS)).usdPrice // tokenPriceUSD: BigDecimal // used for different borrow token in CDP + ); } - - // createLiquidate( - // asset: Bytes - // liquidator: Address - // liquidatee: Address - // amount: BigInt - // amountUSD: BigDecimal - // profitUSD: BigDecimal - // newBalance: BigInt // repaid token balance for liquidatee - // ) - - // createTransfer( - // asset: Bytes - // sender: Address - // receiver: Address - // amount: BigInt - // amountUSD: BigDecimal - // senderNewBalance: BigInt - // receiverNewBalance: BigInt - // ) } /** From 1795d2bda35f082d156f378e0c8acd971d0ab4e9 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 14 Jul 2023 20:54:30 +0200 Subject: [PATCH 47/52] docs: add `flashloans` to query --- subgraphs/ebtc/QUERY.gql | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/subgraphs/ebtc/QUERY.gql b/subgraphs/ebtc/QUERY.gql index 826f24eb29..de419c765a 100644 --- a/subgraphs/ebtc/QUERY.gql +++ b/subgraphs/ebtc/QUERY.gql @@ -115,4 +115,19 @@ type withdrawCount } + flashloans { + amount + amountUSD + blockNumber + feeAmount + feeAmountUSD + gasLimit + gasPrice + gasUsed + hash + id + logIndex + nonce + timestamp + } } From 807411191242d474340f4cabdd731ee6a9dfdae0 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 14 Jul 2023 20:56:33 +0200 Subject: [PATCH 48/52] fix: listen for `CdpLiquidated` instead of `Liquidation` --- .../ebtc/config/templates/ebtc.template.yaml | 6 ++-- subgraphs/ebtc/src/mapping/CdpManager.ts | 28 +++++++++---------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index 1f7ddc6c0d..5772fd38b8 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -65,7 +65,8 @@ dataSources: # - event: BorrowerOperationsAddressChanged(address) # - event: CdpFeeSplitApplied(bytes32,uint256,uint256,uint256,uint256) # - event: CdpIndexUpdated(bytes32,uint256) - # - event: CdpLiquidated(indexed bytes32,indexed address,uint256,uint256,uint8) + - event: CdpLiquidated(indexed bytes32,indexed address,uint256,uint256,uint8) + handler: handleCdpLiquidated # - event: CdpPartiallyLiquidated(indexed bytes32,indexed address,uint256,uint256,uint8) # - event: CdpSnapshotsUpdated(bytes32,uint256) - event: CdpUpdated(indexed bytes32,indexed address,uint256,uint256,uint256,uint256,uint256,uint8) @@ -79,8 +80,7 @@ dataSources: # - event: FeeRecipientAddressChanged(address) # - event: LTermsUpdated(uint256) # - event: LastFeeOpTimeUpdated(uint256) - - event: Liquidation(uint256,uint256,uint256) - handler: handleLiquidation + # - event: Liquidation(uint256,uint256,uint256) # - event: LiquidationLibraryAddressChanged(address) # - event: MinuteDecayFactorSet(uint256) # - event: PriceFeedAddressChanged(address) diff --git a/subgraphs/ebtc/src/mapping/CdpManager.ts b/subgraphs/ebtc/src/mapping/CdpManager.ts index b0a0bee26f..ae2b1d52c2 100644 --- a/subgraphs/ebtc/src/mapping/CdpManager.ts +++ b/subgraphs/ebtc/src/mapping/CdpManager.ts @@ -1,5 +1,8 @@ -import { CdpUpdated, Liquidation } from "../../generated/CdpManager/CdpManager"; -import { BIGINT_ZERO } from "../sdk/util/constants"; +import { + CdpLiquidated, + CdpUpdated, +} from "../../generated/CdpManager/CdpManager"; +import { BIGDECIMAL_ZERO, BIGINT_ZERO } from "../sdk/util/constants"; import { getDataManager, STETH_ADDRESS } from "../constants"; import { Address } from "@graphprotocol/graph-ts"; import { getUsdPrice } from "../prices"; @@ -17,27 +20,22 @@ export function handleCdpUpdated(event: CdpUpdated): void { * @param event Liquidation The event emitted by the CdpManager when a CDP is * liquidated. */ -export function handleLiquidation(event: Liquidation): void { - // TODO: event is missing the following data points: - // - liquidator - // - liquidatee - // - newBalance +export function handleCdpLiquidated(event: CdpLiquidated): void { const dataManager = getDataManager(event); dataManager.createLiquidate( STETH_ADDRESS, // asset: Bytes + // TODO: liquidator address missing in event new Address(0), // liquidator: Address - new Address(0), // liquidatee: Address - event.params._liquidatedColl, // amount: BigInt + Address.fromBytes(event.params._borrower), // liquidatee: Address + event.params._coll, // amount: BigInt getUsdPrice( Address.fromBytes(STETH_ADDRESS), - event.params._liquidatedColl.toBigDecimal(), + event.params._coll.toBigDecimal(), event.block ), // amountUSD: BigDecimal - getUsdPrice( - Address.fromBytes(STETH_ADDRESS), - event.params._liqReward.toBigDecimal(), - event.block - ), // profitUSD: BigDecimal + // TODO: what is profit? + getUsdPrice(Address.fromBytes(STETH_ADDRESS), BIGDECIMAL_ZERO, event.block), // profitUSD: BigDecimal + // TODO: add logic for partial liquidations BIGINT_ZERO // newBalance: BigInt // repaid token balance for liquidatee ); } From af0b95d0146b0ce29ba3c0f32c7ba6e6a3786623 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 14 Jul 2023 21:15:48 +0200 Subject: [PATCH 49/52] docs: add liquidates to query --- subgraphs/ebtc/QUERY.gql | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/subgraphs/ebtc/QUERY.gql b/subgraphs/ebtc/QUERY.gql index de419c765a..585a164807 100644 --- a/subgraphs/ebtc/QUERY.gql +++ b/subgraphs/ebtc/QUERY.gql @@ -130,4 +130,18 @@ nonce timestamp } + liquidates { + amount + amountUSD + blockNumber + gasLimit + gasPrice + gasUsed + hash + id + logIndex + nonce + profitUSD + timestamp + } } From f2c9109367146fd9059273515106267e282226c1 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Fri, 14 Jul 2023 21:16:10 +0200 Subject: [PATCH 50/52] chore: add note about price calc --- subgraphs/ebtc/src/mapping/BorrowerOperations.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subgraphs/ebtc/src/mapping/BorrowerOperations.ts b/subgraphs/ebtc/src/mapping/BorrowerOperations.ts index 62b4a60321..84a590ca3b 100644 --- a/subgraphs/ebtc/src/mapping/BorrowerOperations.ts +++ b/subgraphs/ebtc/src/mapping/BorrowerOperations.ts @@ -40,6 +40,8 @@ export function handleCdpUpdated(event: CdpUpdated): void { ); } + // TODO: ebtc price can be determined as below (via price lib), but it might + // be better to not take market price but use theoretical price instead. const deltaDebt = event.params._debt.minus(event.params._oldDebt); if (deltaDebt > BIGINT_ZERO) { dataManager.createBorrow( From 69966f8490280623330bc9997c17f932aaa193d7 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Thu, 27 Jul 2023 22:15:36 +0200 Subject: [PATCH 51/52] style: lint for upstream --- subgraphs/_reference_/src/prices/config/goerli.ts | 6 +++--- .../ebtc/config/templates/ebtc.template.yaml | 4 ++-- subgraphs/ebtc/src/mapping/ActivePool.ts | 12 +----------- subgraphs/ebtc/src/mapping/BorrowerOperations.ts | 2 +- subgraphs/ebtc/src/mapping/CdpManager.ts | 6 +++--- subgraphs/ebtc/src/prices/config/goerli.ts | 6 +++--- 6 files changed, 13 insertions(+), 23 deletions(-) diff --git a/subgraphs/_reference_/src/prices/config/goerli.ts b/subgraphs/_reference_/src/prices/config/goerli.ts index ff353b4923..b1e8f2df34 100644 --- a/subgraphs/_reference_/src/prices/config/goerli.ts +++ b/subgraphs/_reference_/src/prices/config/goerli.ts @@ -50,13 +50,13 @@ export const HARDCODED_STABLES: Address[] = []; export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); export const ETH_ADDRESS = Address.fromString( - "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" ); export const WETH_ADDRESS = Address.fromString( - "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6" + "0xb4fbf271143f4fbf7b91a5ded31805e42b2208d6" ); export const USDC_ADDRESS = Address.fromString( - "0xD87Ba7A50B2E7E660f678A895E4B72E7CB4CCd9C" + "0xd87ba7a50b2e7e660f678a895e4b72e7cb4ccd9c" ); export class config implements Configurations { diff --git a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml index 5772fd38b8..2351d0366c 100644 --- a/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml +++ b/subgraphs/ebtc/protocols/ebtc/config/templates/ebtc.template.yaml @@ -69,8 +69,8 @@ dataSources: handler: handleCdpLiquidated # - event: CdpPartiallyLiquidated(indexed bytes32,indexed address,uint256,uint256,uint8) # - event: CdpSnapshotsUpdated(bytes32,uint256) - - event: CdpUpdated(indexed bytes32,indexed address,uint256,uint256,uint256,uint256,uint256,uint8) - handler: handleCdpUpdated + # - event: CdpUpdated(indexed bytes32,indexed address,uint256,uint256,uint256,uint256,uint256,uint8) + # handler: handleCdpUpdated # - event: CollSurplusPoolAddressChanged(address) # - event: CollateralAddressChanged(address) # - event: CollateralFeePerUnitUpdated(uint256,uint256,uint256) diff --git a/subgraphs/ebtc/src/mapping/ActivePool.ts b/subgraphs/ebtc/src/mapping/ActivePool.ts index 4105488593..4ac1e47d82 100644 --- a/subgraphs/ebtc/src/mapping/ActivePool.ts +++ b/subgraphs/ebtc/src/mapping/ActivePool.ts @@ -47,16 +47,6 @@ export function handleSystemDeployed(event: CdpManagerAddressChanged): void { market.liquidationPenalty = LIQUIDATION_FEE_PERCENT; market.borrowedToken = EBTC_ADDRESS; market.save(); - - const lendingProtocol = dataManager.getOrCreateLendingProtocol( - getProtocolData() // data: ProtocolData - ); - - const oracle = dataManager.getOrCreateOracle( - Address.fromBytes(PRICE_FEED), // oracleAddress: Address - false, // isUSD: boolean - OracleSource.CHAINLINK // source?: string - ); } /** @@ -98,7 +88,7 @@ export function handleActivePoolEBTCDebtUpdated( */ export function handleFlashLoanSuccess(event: FlashLoanSuccess): void { const dataManager = getDataManager(event); - const flashloan = dataManager.createFlashloan( + dataManager.createFlashloan( Address.fromBytes(STETH_ADDRESS), // asset: Address event.params._receiver, // account: Address event.params._amount, // amount: BigInt diff --git a/subgraphs/ebtc/src/mapping/BorrowerOperations.ts b/subgraphs/ebtc/src/mapping/BorrowerOperations.ts index 84a590ca3b..8e25560a7c 100644 --- a/subgraphs/ebtc/src/mapping/BorrowerOperations.ts +++ b/subgraphs/ebtc/src/mapping/BorrowerOperations.ts @@ -82,7 +82,7 @@ export function handleFlashLoanSuccess(event: FlashLoanSuccess): void { // TODO: this is a dupe of the same function in ActivePool.ts // TODO: how to export imported functions? const dataManager = getDataManager(event); - const flashloan = dataManager.createFlashloan( + dataManager.createFlashloan( Address.fromBytes(STETH_ADDRESS), // asset: Address event.params._receiver, // account: Address event.params._amount, // amount: BigInt diff --git a/subgraphs/ebtc/src/mapping/CdpManager.ts b/subgraphs/ebtc/src/mapping/CdpManager.ts index ae2b1d52c2..8b497982c0 100644 --- a/subgraphs/ebtc/src/mapping/CdpManager.ts +++ b/subgraphs/ebtc/src/mapping/CdpManager.ts @@ -11,9 +11,9 @@ import { getUsdPrice } from "../prices"; * Make necessary adjustments to the system when a CDP changes. * @param event The event emitted by the CdpManager when a CDP changes. */ -export function handleCdpUpdated(event: CdpUpdated): void { - // TODO -} +// export function handleCdpUpdated(event: CdpUpdated): void { +// TODO +// } /** * Register a liquidation event. diff --git a/subgraphs/ebtc/src/prices/config/goerli.ts b/subgraphs/ebtc/src/prices/config/goerli.ts index ff353b4923..b1e8f2df34 100644 --- a/subgraphs/ebtc/src/prices/config/goerli.ts +++ b/subgraphs/ebtc/src/prices/config/goerli.ts @@ -50,13 +50,13 @@ export const HARDCODED_STABLES: Address[] = []; export const USDC_TOKEN_DECIMALS = BigInt.fromI32(6); export const ETH_ADDRESS = Address.fromString( - "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" ); export const WETH_ADDRESS = Address.fromString( - "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6" + "0xb4fbf271143f4fbf7b91a5ded31805e42b2208d6" ); export const USDC_ADDRESS = Address.fromString( - "0xD87Ba7A50B2E7E660f678A895E4B72E7CB4CCd9C" + "0xd87ba7a50b2e7e660f678a895e4b72e7cb4ccd9c" ); export class config implements Configurations { From e06587e5f9053cd1e8bcd44e754f3ddd184a4f77 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Thu, 27 Jul 2023 22:20:43 +0200 Subject: [PATCH 52/52] perf: remove unused imports --- subgraphs/ebtc/src/mapping/ActivePool.ts | 4 +--- subgraphs/ebtc/src/mapping/CdpManager.ts | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/subgraphs/ebtc/src/mapping/ActivePool.ts b/subgraphs/ebtc/src/mapping/ActivePool.ts index 4ac1e47d82..914f886782 100644 --- a/subgraphs/ebtc/src/mapping/ActivePool.ts +++ b/subgraphs/ebtc/src/mapping/ActivePool.ts @@ -11,14 +11,12 @@ import { EBTC_ADDRESS, LIQUIDATION_FEE_PERCENT, MAXIMUM_LTV, - PRICE_FEED, STETH_ADDRESS, getDataManager, - getProtocolData, } from "../constants"; import { TokenManager } from "../sdk/token"; import { getUsdPrice } from "../prices"; -import { BIGINT_TEN_TO_EIGHTEENTH, OracleSource } from "../sdk/util/constants"; +import { BIGINT_TEN_TO_EIGHTEENTH } from "../sdk/util/constants"; /** * On deployment of the pool, initialise and populate the market, diff --git a/subgraphs/ebtc/src/mapping/CdpManager.ts b/subgraphs/ebtc/src/mapping/CdpManager.ts index 8b497982c0..0053802df6 100644 --- a/subgraphs/ebtc/src/mapping/CdpManager.ts +++ b/subgraphs/ebtc/src/mapping/CdpManager.ts @@ -1,6 +1,6 @@ import { CdpLiquidated, - CdpUpdated, + // CdpUpdated, } from "../../generated/CdpManager/CdpManager"; import { BIGDECIMAL_ZERO, BIGINT_ZERO } from "../sdk/util/constants"; import { getDataManager, STETH_ADDRESS } from "../constants";