diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b9aa327..a7a2829 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,7 +12,7 @@ importers: specifier: ^4.1.0 version: 4.1.0 - subgraphs/pools: + subgraphs/gauges: dependencies: '@graphprotocol/graph-cli': specifier: 0.66.0 @@ -25,7 +25,33 @@ importers: specifier: 0.5.0 version: 0.5.0 - subgraphs/vault: + subgraphs/v2-vault: + dependencies: + '@graphprotocol/graph-cli': + specifier: 0.66.0 + version: 0.66.0(@types/node@22.5.0)(node-fetch@3.3.2)(typescript@5.5.4) + '@graphprotocol/graph-ts': + specifier: 0.32.0 + version: 0.32.0 + devDependencies: + matchstick-as: + specifier: 0.5.0 + version: 0.5.0 + + subgraphs/v3-pools: + dependencies: + '@graphprotocol/graph-cli': + specifier: 0.66.0 + version: 0.66.0(@types/node@22.5.0)(node-fetch@3.3.2)(typescript@5.5.4) + '@graphprotocol/graph-ts': + specifier: 0.32.0 + version: 0.32.0 + devDependencies: + matchstick-as: + specifier: 0.5.0 + version: 0.5.0 + + subgraphs/v3-vault: dependencies: '@graphprotocol/graph-cli': specifier: 0.66.0 @@ -570,19 +596,19 @@ packages: /@types/concat-stream@1.6.1: resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} dependencies: - '@types/node': 8.10.66 + '@types/node': 22.5.0 dev: false /@types/connect@3.4.38: resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} dependencies: - '@types/node': 12.20.55 + '@types/node': 22.5.0 dev: false /@types/form-data@0.0.33: resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} dependencies: - '@types/node': 8.10.66 + '@types/node': 22.5.0 dev: false /@types/long@4.0.2: @@ -634,7 +660,7 @@ packages: /@types/ws@7.4.7: resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} dependencies: - '@types/node': 12.20.55 + '@types/node': 22.5.0 dev: false /@whatwg-node/events@0.0.3: diff --git a/subgraphs/gauges/.github/workflows/ci.yaml b/subgraphs/gauges/.github/workflows/ci.yaml new file mode 100644 index 0000000..1f44a18 --- /dev/null +++ b/subgraphs/gauges/.github/workflows/ci.yaml @@ -0,0 +1,35 @@ +name: CI + +on: + push: + branches: master + pull_request: + branches: "*" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - name: Build + run: yarn build + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Lint + run: yarn lint diff --git a/subgraphs/gauges/.github/workflows/graph-studio-staging.yaml b/subgraphs/gauges/.github/workflows/graph-studio-staging.yaml new file mode 100644 index 0000000..a09392b --- /dev/null +++ b/subgraphs/gauges/.github/workflows/graph-studio-staging.yaml @@ -0,0 +1,223 @@ +name: Deploy Graph Studio to Staging + +on: + push: + branches: [staging] + +jobs: + deploy-mainnet: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-beta" + graph_account: "balancer-labs" + graph_config_file: "subgraph.yaml" + graph_deploy_studio: true + deploy-goerli: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-goerli-beta" + graph_account: "balancer-labs" + graph_config_file: "subgraph.goerli.yaml" + graph_deploy_studio: true + deploy-arbitrum: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-arbitrum-beta" + graph_account: "balancer-labs" + graph_config_file: "subgraph.arbitrum.yaml" + graph_deploy_studio: true + deploy-polygon: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-polygon-beta" + graph_account: "balancer-labs" + graph_config_file: "subgraph.polygon.yaml" + graph_deploy_studio: true + deploy-optimism: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-optimism-beta" + graph_account: "balancer-labs" + graph_config_file: "subgraph.optimism.yaml" + graph_deploy_studio: true + deploy-gnosis: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-gnosis-chain-b" + graph_account: "balancer-labs" + graph_config_file: "subgraph.gnosis.yaml" + graph_deploy_studio: true + deploy-avalanche: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-avalanche-beta" + graph_account: "balancer-labs" + graph_config_file: "subgraph.avalanche.yaml" + graph_deploy_studio: true + deploy-polygon-zkevm: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - name: Build + run: yarn build + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-polygon-zk-b" + graph_account: "balancer-labs" + graph_config_file: "subgraph.polygon-zkevm.yaml" + graph_deploy_studio: true + deploy-sepolia: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - name: Build + run: yarn build + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-sepolia-beta" + graph_account: "balancer-labs" + graph_config_file: "subgraph.sepolia.yaml" + graph_deploy_studio: true + deploy-base: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - name: Build + run: yarn build + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-base-beta" + graph_account: "balancer-labs" + graph_config_file: "subgraph.base.yaml" + graph_deploy_studio: true diff --git a/subgraphs/gauges/.github/workflows/graph-studio.yaml b/subgraphs/gauges/.github/workflows/graph-studio.yaml new file mode 100644 index 0000000..4354740 --- /dev/null +++ b/subgraphs/gauges/.github/workflows/graph-studio.yaml @@ -0,0 +1,223 @@ +name: Deploy Graph Studio + +on: + push: + branches: [master] + +jobs: + deploy-mainnet: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges" + graph_account: "balancer-labs" + graph_config_file: "subgraph.yaml" + graph_deploy_studio: true + deploy-goerli: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-goerli" + graph_account: "balancer-labs" + graph_config_file: "subgraph.goerli.yaml" + graph_deploy_studio: true + deploy-arbitrum: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-arbitrum" + graph_account: "balancer-labs" + graph_config_file: "subgraph.arbitrum.yaml" + graph_deploy_studio: true + deploy-polygon: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-polygon" + graph_account: "balancer-labs" + graph_config_file: "subgraph.polygon.yaml" + graph_deploy_studio: true + deploy-optimism: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-optimism" + graph_account: "balancer-labs" + graph_config_file: "subgraph.optimism.yaml" + graph_deploy_studio: true + deploy-gnosis: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-gnosis-chain" + graph_account: "balancer-labs" + graph_config_file: "subgraph.gnosis.yaml" + graph_deploy_studio: true + deploy-avalanche: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_NEW_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-avalanche" + graph_account: "balancer-labs" + graph_config_file: "subgraph.avalanche.yaml" + graph_deploy_studio: true + deploy-polygon-zkevm: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - name: Build + run: yarn build + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-polygon-zk" + graph_account: "balancer-labs" + graph_config_file: "subgraph.polygon-zkevm.yaml" + graph_deploy_studio: true + deploy-sepolia: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - name: Build + run: yarn build + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-sepolia" + graph_account: "balancer-labs" + graph_config_file: "subgraph.sepolia.yaml" + graph_deploy_studio: true + deploy-base: + runs-on: ubuntu-latest + environment: graph + steps: + - uses: actions/checkout@v2 + - name: Install node + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install + run: yarn --frozen-lockfile + - name: Codegen + run: yarn codegen + - name: Build + run: yarn build + - uses: balancer-labs/graph-deploy@v0.0.1 + with: + graph_deploy_key: ${{secrets.GRAPH_DEPLOY_KEY}} + graph_version_label: ${GITHUB_SHA::8} + graph_subgraph_name: "balancer-gauges-base" + graph_account: "balancer-labs" + graph_config_file: "subgraph.base.yaml" + graph_deploy_studio: true diff --git a/subgraphs/gauges/README.md b/subgraphs/gauges/README.md new file mode 100644 index 0000000..0e8d116 --- /dev/null +++ b/subgraphs/gauges/README.md @@ -0,0 +1 @@ +# Balancer Gauges Subgraph diff --git a/subgraphs/vault/package.json b/subgraphs/gauges/package.json similarity index 91% rename from subgraphs/vault/package.json rename to subgraphs/gauges/package.json index f09d9d0..efa5049 100644 --- a/subgraphs/vault/package.json +++ b/subgraphs/gauges/package.json @@ -1,5 +1,5 @@ { - "name": "@subgraphs/vault", + "name": "@subgraphs/gauges", "private": true, "scripts": { "codegen": "graph codegen --output-dir src/types/", diff --git a/subgraphs/gauges/schema.graphql b/subgraphs/gauges/schema.graphql new file mode 100644 index 0000000..0b77e03 --- /dev/null +++ b/subgraphs/gauges/schema.graphql @@ -0,0 +1,321 @@ +type VotingEscrow @entity { + " VotingEscrow contract address " + id: ID! + + " Amount of B-80BAL-20WETH BPT locked, only applies on mainnet " + stakedSupply: BigDecimal + + " List of veBAL locks created " + locks: [VotingEscrowLock!] @derivedFrom(field: "votingEscrowID") + + " List of veBAL locks created " + omniLocks: [OmniVotingEscrowLock!] @derivedFrom(field: "votingEscrowID") +} + +type OmniVotingEscrowLock @entity { + " Equal to: - " + id: ID! + + " User on the local chain (reference to User entity) " + localUser: User! + + " User address on the remote chain " + remoteUser: Bytes! + + " Chain where the lock was bridged to " + dstChainId: Int! + + " veBAL balance at the moment user locks " + bias: BigDecimal! + + " veBAL decay rate (per second) " + slope: BigDecimal! + + " Timestamp the lock was created [seconds] " + timestamp: Int! + + " Reference to VotingEscrow entity " + votingEscrowID: VotingEscrow! +} + +type VotingEscrowLock @entity { + " Equal to: - " + id: ID! + + " Reference to User entity " + user: User! + + " veBAL balance at the moment user locks " + bias: BigDecimal! + + " veBAL decay rate (per second) " + slope: BigDecimal! + + " Timestamp at which the lock was created [seconds] " + timestamp: Int! + + " Timestamp at which B-80BAL-20WETH BPT can be unlocked by user [seconds] " + unlockTime: BigInt! + + " Amount of B-80BAL-20WETH BPT the user has locked " + lockedBalance: BigDecimal! + + " Reference to VotingEscrow entity " + votingEscrowID: VotingEscrow! + + " Timestamp at which the lcok was created [seconds]. Same as timestamp " + updatedAt: Int! +} + +type LockSnapshot @entity { + " Equal to - " + id: ID! + + " Reference to User entity " + user: User! + + " veBAL balance at the moment user locks " + bias: BigDecimal! + + " veBAL decay rate (per second) " + slope: BigDecimal! + + " Timestamp at which the snapshot was taken [seconds] " + timestamp: Int! +} + +type GaugeFactory @entity { + " Factory contract address " + id: ID! + + " Number of gauges created through the factory " + numGauges: Int! + + " List of gauges created through the factory " + gauges: [LiquidityGauge!] @derivedFrom(field: "factory") +} + +type LiquidityGauge @entity { + " LiquidityGauge contract address " + id: ID! + + " ERC20 token symbol " + symbol: String! + + " Reference to Gauge entity - created when LiquidityGauge is added to GaugeController" + gauge: Gauge + + " Reference to Pool entity " + pool: Pool + + " Address of the pool (lp_token of the gauge) " + poolAddress: Bytes! + + " Pool ID if lp_token is a Balancer v2 pool; null otherwise " + poolId: Bytes + + " Whether Balancer DAO killed the gauge " + isKilled: Boolean! + + " Whether the LiquidityGauge is the most recent added to GaugeController " + isPreferentialGauge: Boolean! + + " Relative weight cap of the gauge (0.01 = 1%) - V2 factories only " + relativeWeightCap: BigDecimal + + " Address of the contract that streams reward tokens to the gauge - ChildChainLiquidityGauge only " + streamer: Bytes + + " Factory contract address " + factory: GaugeFactory! + + " Total of BPTs users have staked in the LiquidityGauge " + totalSupply: BigDecimal! + + " List of reward tokens depositted in the gauge - ChildChainLiquidityGauge only " + rewardTokensList: [Bytes!] + + " List of user shares " + shares: [GaugeShare!] @derivedFrom(field: "gauge") + + " List of reward tokens depositted in the gauge " + tokens: [RewardToken!] @derivedFrom(field: "gauge") +} + +enum Chain { + Arbitrum + Gnosis + Polygon + Optimism + Avalanche + PolygonZkEvm + Base + Fraxtal +} + +type RootGauge @entity { + " RootGauge contract address" + id: ID! + + " Chain where emissions by this gauge will be bridged to " + chain: Chain! + + " Address where emissions by this gauge will be bridged to " + recipient: Bytes! + + " Reference to Gauge entity - created when LiquidityGauge is added to GaugeController" + gauge: Gauge + + " Whether Balancer DAO killed the gauge " + isKilled: Boolean! + + " Relative weight cap of the gauge (0.01 = 1%) - V2 factories only " + relativeWeightCap: BigDecimal + + " Factory contract address " + factory: GaugeFactory! +} + +type SingleRecipientGauge @entity { + " SingleRecipientGauge contract address" + id: ID! + + " Address where emissions for this gauge will be sent to " + recipient: Bytes! + + " Reference to Gauge entity - created when SingleRecipientGauge is added to GaugeController" + gauge: Gauge + + " Whether Balancer DAO killed the gauge " + isKilled: Boolean! + + " Relative weight cap of the gauge (0.01 = 1%) - V2 factories only " + relativeWeightCap: BigDecimal + + " Factory contract address " + factory: GaugeFactory! +} + +type Gauge @entity { + " Equal to: - " + id: ID! + + " Address of the gauge " + address: Bytes! + + " Type of the gauge " + type: GaugeType! + + " Timestamp at which Balancer DAO added the gauge to GaugeController [seconds] " + addedTimestamp: Int! + + " Reference to LiquidityGauge " + liquidityGauge: LiquidityGauge + + " Reference to RootGauge " + rootGauge: RootGauge +} + +type Pool @entity { + " Address of the pool (lp_token of the gauge) " + id: ID! + + " Pool ID if lp_token is a Balancer pool; null otherwise " + poolId: Bytes + + " Address of the pool (lp_token of the gauge) " + address: Bytes! + + " Most recent, unkilled gauge in the GaugeController " + preferentialGauge: LiquidityGauge + + " List of the pool's gauges addresses " + gaugesList: [Bytes!]! + + " List of gauges created for the pool " + gauges: [LiquidityGauge!] @derivedFrom(field: "pool") +} + +type RewardToken @entity { + " Equal to: - " + id: ID! + + " ERC20 token symbol - empty string if call to symbol() reverts " + symbol: String! + + " ERC20 token decimals - zero if call to decimals() reverts " + decimals: Int! + + " Reference to LiquidityGauge entity " + gauge: LiquidityGauge! + + " Rate of reward tokens streamed per second " + rate: BigDecimal + + " Timestamp at which finishes the period of rewards " + periodFinish: BigInt + + " Amount of reward tokens that has been deposited into the gauge " + totalDeposited: BigDecimal! +} + +type GaugeShare @entity { + " Equal to: - " + id: ID! + + " Reference to User entity " + user: User! + + " Reference to LiquidityGauge entity " + gauge: LiquidityGauge! + + " User's balance of gauge deposit tokens " + balance: BigDecimal! +} + +type GaugeType @entity { + " Type ID " + id: ID! + + " Name of the type - empty string if call reverts " + name: String! +} + +type GaugeVote @entity { + " Equal to: - " + id: ID! + + " Reference to User entity " + user: User! + + " Reference to Gauge entity " + gauge: Gauge! + + " Weight of veBAL power user has used to vote " + weight: BigDecimal + + " Timestamp at which user voted [seconds] " + timestamp: BigInt +} + +type User @entity { + " User address " + id: ID! + + " List of votes on gauges " + gaugeVotes: [GaugeVote!] @derivedFrom(field: "user") + + " List of gauge the user has shares " + gaugeShares: [GaugeShare!] @derivedFrom(field: "user") + + " List of locks the user created " + votingLocks: [VotingEscrowLock!] @derivedFrom(field: "user") + + " List of omni locks the user created " + omniVotingLocks: [OmniVotingEscrowLock!] @derivedFrom(field: "localUser") +} + +type GaugeInjector @entity { + " GaugeInjector contract address " + id: ID! +} diff --git a/subgraphs/gauges/src/helpers/constants.ts b/subgraphs/gauges/src/helpers/constants.ts new file mode 100644 index 0000000..3edd84f --- /dev/null +++ b/subgraphs/gauges/src/helpers/constants.ts @@ -0,0 +1,154 @@ +import { Address, BigInt, dataSource } from "@graphprotocol/graph-ts"; + +export const ZERO = BigInt.fromI32(0); +export const ONE = BigInt.fromI32(1); +export const ZERO_BD = ZERO.toBigDecimal(); +export const ONE_BD = ZERO.toBigDecimal(); + +export const LOCK_MAXTIME = BigInt.fromI32(365 * 86400); // 1 YEAR + +export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; +export class AddressByNetwork { + public mainnet: string; + public sepolia: string; + public goerli: string; +} + +let network: string = dataSource.network(); + +let controllerAddressByNetwork: AddressByNetwork = { + mainnet: "0xC128468b7Ce63eA702C1f104D55A2566b13D3ABD", + sepolia: "0x577e5993B9Cc480F07F98B5Ebd055604bd9071C4", + goerli: "0xBB1CE49b16d55A1f2c6e88102f32144C7334B116", +}; + +function forNetwork( + addressByNetwork: AddressByNetwork, + network: string +): Address { + if (network == "mainnet") { + return Address.fromString(addressByNetwork.mainnet); + } else if (network == "sepolia") { + return Address.fromString(addressByNetwork.sepolia); + } + return Address.fromString(addressByNetwork.goerli); +} + +export const CONTROLLER_ADDRESS = forNetwork( + controllerAddressByNetwork, + network +); + +export const VAULT_V2_ADDRESS = Address.fromString( + "0xBA12222222228d8Ba445958a75a0704d566BF2C8" +); +export const VAULT_V3_ADDRESS = Address.fromString( + "0xBA12222222228d8Ba445958a75a0704d566BF2C8" // TODO: update when v3 launches +); + +export const ARBITRUM_ROOT_GAUGE_FACTORY = Address.fromString( + "0xad901309d9e9DbC5Df19c84f729f429F0189a633" +); +export const OPTIMISM_ROOT_GAUGE_FACTORY = Address.fromString( + "0x3083A1C455ff38d39e58Dbac5040f465cF73C5c8" +); +export const POLYGON_ROOT_GAUGE_FACTORY = Address.fromString( + "0x4C4287b07d293E361281bCeEe8715c8CDeB64E34" +); + +export const MAINNET_GAUGE_V1_FACTORY = Address.fromString( + "0x4E7bBd911cf1EFa442BC1b2e9Ea01ffE785412EC" +); +export const MAINNET_GAUGE_V2_FACTORY = Address.fromString( + "0xf1665E19bc105BE4EDD3739F88315cC699cc5b65" +); +export const GOERLI_GAUGE_V1_FACTORY = Address.fromString( + "0x224E808FBD9e491Be8988B8A0451FBF777C81B8A" +); +export const GOERLI_GAUGE_V2_FACTORY = Address.fromString( + "0x3b8cA519122CdD8efb272b0D3085453404B25bD0" +); +export const SEPOLIA_GAUGE_V2_FACTORY = Address.fromString( + "0x2FF226CD12C80511a641A6101F071d853A4e5363" +); +export const ARBITRUM_ROOT_GAUGE_V2_FACTORY = Address.fromString( + "0x1c99324EDC771c82A0DCCB780CC7DDA0045E50e7" +); +export const GNOSIS_ROOT_GAUGE_V2_FACTORY = Address.fromString( + "0x2a18B396829bc29F66a1E59fAdd7a0269A6605E8" +); +export const OPTIMISM_ROOT_GAUGE_V2_FACTORY = Address.fromString( + "0x866D4B65694c66fbFD15Dd6fa933D0A6b3940A36" +); +export const BASE_ROOT_GAUGE_V2_FACTORY = Address.fromString( + "0x8e3B64b3737097F283E965869e3503AA20F31E4D" +); +export const POLYGON_ROOT_GAUGE_V2_FACTORY = Address.fromString( + "0xa98Bce70c92aD2ef3288dbcd659bC0d6b62f8F13" +); +export const AVALANCHE_ROOT_GAUGE_V2_FACTORY = Address.fromString( + "0x22625eEDd92c81a219A83e1dc48f88d54786B017" +); +export const POLYGON_ZKEVM_ROOT_GAUGE_V2_FACTORY = Address.fromString( + "0x9bF951848288cCD87d06FaC426150262cD3447De" +); + +export const FRAXTAL_ROOT_GAUGE_V2_FACTORY = Address.fromString( + "0x18CC3C68A5e64b40c846Aa6E45312cbcBb94f71b" +); + +export function isArbitrumFactory(factory: Address): boolean { + return [ARBITRUM_ROOT_GAUGE_FACTORY, ARBITRUM_ROOT_GAUGE_V2_FACTORY].includes( + factory + ); +} + +export function isMainnetFactory(factory: Address): boolean { + return [MAINNET_GAUGE_V1_FACTORY, MAINNET_GAUGE_V2_FACTORY].includes(factory); +} + +export function isGoerliFactory(factory: Address): boolean { + return [GOERLI_GAUGE_V1_FACTORY, GOERLI_GAUGE_V2_FACTORY].includes(factory); +} +export function isSepoliaFactory(factory: Address): boolean { + return factory == SEPOLIA_GAUGE_V2_FACTORY; +} +export function isL1Factory(factory: Address): boolean { + return ( + isMainnetFactory(factory) || + isGoerliFactory(factory) || + isSepoliaFactory(factory) + ); +} + +export function isOptimismFactory(factory: Address): boolean { + return [OPTIMISM_ROOT_GAUGE_FACTORY, OPTIMISM_ROOT_GAUGE_V2_FACTORY].includes( + factory + ); +} + +export function isPolygonFactory(factory: Address): boolean { + return [POLYGON_ROOT_GAUGE_FACTORY, POLYGON_ROOT_GAUGE_V2_FACTORY].includes( + factory + ); +} + +export function isGnosisFactory(factory: Address): boolean { + return factory == GNOSIS_ROOT_GAUGE_V2_FACTORY; +} + +export function isAvalancheFactory(factory: Address): boolean { + return factory == AVALANCHE_ROOT_GAUGE_V2_FACTORY; +} + +export function isPolygonZkEVMFactory(factory: Address): boolean { + return factory == POLYGON_ZKEVM_ROOT_GAUGE_V2_FACTORY; +} + +export function isBaseFactory(factory: Address): boolean { + return factory == BASE_ROOT_GAUGE_V2_FACTORY; +} + +export function isFraxtalFactory(factory: Address): boolean { + return factory == FRAXTAL_ROOT_GAUGE_V2_FACTORY; +} diff --git a/subgraphs/gauges/src/helpers/gauge.ts b/subgraphs/gauges/src/helpers/gauge.ts new file mode 100644 index 0000000..cd87923 --- /dev/null +++ b/subgraphs/gauges/src/helpers/gauge.ts @@ -0,0 +1,336 @@ +import { Address, BigInt, Bytes, log } from '@graphprotocol/graph-ts'; + +import { + LiquidityGauge, + GaugeShare, + RewardToken, + GaugeVote, + GaugeType, +} from '../types/schema'; +import { + CONTROLLER_ADDRESS, + ZERO, + ZERO_ADDRESS, + ZERO_BD, + isL1Factory, +} from './constants'; +import { LiquidityGauge as LiquidityGaugeTemplate } from '../types/templates/LiquidityGauge/LiquidityGauge'; +import { + bytesToAddress, + createUserEntity, + getTokenDecimals, + getTokenSymbol, +} from './misc'; +import { GaugeController } from '../types/GaugeController/GaugeController'; +import { scaleDown } from './maths'; +import { ChildChainStreamer } from '../types/templates/ChildChainStreamer/ChildChainStreamer'; +import { ChildChainLiquidityGaugeV2 } from '../types/templates/ChildChainStreamer/ChildChainLiquidityGaugeV2'; + +export function getRewardTokenId( + tokenAddress: Address, + gaugeAddress: Address, +): string { + return tokenAddress.toHex().concat('-').concat(gaugeAddress.toHex()); +} + +/** + * Returns the reward token entity for a given gauge and token address + * Creates the entity if it does not exist, as well as an entry in the gauge's rewardTokensList + */ +export function getRewardToken( + tokenAddress: Address, + gaugeAddress: Address, +): RewardToken { + let id = getRewardTokenId(tokenAddress, gaugeAddress); + let rewardToken = RewardToken.load(id); + + if (rewardToken == null) { + rewardToken = new RewardToken(id); + rewardToken.gauge = gaugeAddress.toHexString(); + rewardToken.symbol = getTokenSymbol(tokenAddress); + rewardToken.decimals = getTokenDecimals(tokenAddress); + rewardToken.totalDeposited = ZERO_BD; + rewardToken.save(); + + let gauge = LiquidityGauge.load(gaugeAddress.toHex()); + if (!gauge) return rewardToken; + let rewardTokensList = gauge.rewardTokensList; + if (rewardTokensList == null) { + rewardTokensList = new Array(1); + rewardTokensList[0] = tokenAddress; + } else { + rewardTokensList.push(tokenAddress); + } + gauge.rewardTokensList = rewardTokensList; + gauge.save(); + } + + return rewardToken; +} + +export function getLiquidityGauge( + gaugeAddress: Address, + poolAddress: Address, +): LiquidityGauge { + let gauge = LiquidityGauge.load(gaugeAddress.toHexString()); + + if (gauge == null) { + gauge = new LiquidityGauge(gaugeAddress.toHexString()); + gauge.poolAddress = poolAddress; + gauge.factory = ZERO_ADDRESS; + gauge.totalSupply = ZERO_BD; + gauge.isPreferentialGauge = false; + gauge.isKilled = false; + + let gaugeToken = LiquidityGaugeTemplate.bind(gaugeAddress); + let symbolCall = gaugeToken.try_symbol(); + if (!symbolCall.reverted) { + gauge.symbol = symbolCall.value; + } + + gauge.save(); + } + + return gauge; +} + +export function getGaugeShareId( + userAddress: Address, + gaugeAddress: Address, +): string { + return userAddress.toHex().concat('-').concat(gaugeAddress.toHex()); +} + +export function createGaugeShare( + userAddress: Address, + gaugeAddress: Address, +): GaugeShare { + createUserEntity(userAddress); + let id = getGaugeShareId(userAddress, gaugeAddress); + + let gaugeShare = new GaugeShare(id); + gaugeShare.user = userAddress.toHexString(); + gaugeShare.gauge = gaugeAddress.toHexString(); + gaugeShare.balance = ZERO_BD; + gaugeShare.save(); + + return gaugeShare; +} + +export function getGaugeShare( + userAddress: Address, + gaugeAddress: Address, +): GaugeShare { + let id = getGaugeShareId(userAddress, gaugeAddress); + let gaugeShare = GaugeShare.load(id); + + if (gaugeShare == null) { + return createGaugeShare(userAddress, gaugeAddress); + } + + return gaugeShare; +} + +export function getGaugeId(gaugeAddress: Address, gaugeType: BigInt): string { + return gaugeAddress.toHex().concat('-').concat(gaugeType.toString()); +} + +export function getGaugeIdFromController(gaugeAddress: Address): string { + let controller = GaugeController.bind(CONTROLLER_ADDRESS); + let gaugeTypesCall = controller.try_gauge_types(gaugeAddress); + let gaugeType = gaugeTypesCall.reverted ? ZERO : gaugeTypesCall.value; + let gaugeId = getGaugeId(gaugeAddress, gaugeType); + + return gaugeId; +} + +export function getOmniVotingEscrowId( + userAddress: Address, + votingEscrowAddress: Address, + chainId: i32, +): string { + return userAddress + .toHex() + .concat('-') + .concat(votingEscrowAddress.toHex()) + .concat('-') + .concat(chainId.toString()); +} + +export function getVotingEscrowId( + userAddress: Address, + votingEscrowAddress: Address, +): string { + return userAddress.toHex().concat('-').concat(votingEscrowAddress.toHex()); +} + +export function getLockSnapshotId( + userAddress: Address, + timestamp: i32, +): string { + return userAddress.toHex().concat('-').concat(timestamp.toString()); +} + +export function getGaugeVoteId( + userAddress: Address, + gaugeAddress: Address, +): string { + return userAddress.toHex().concat('-').concat(gaugeAddress.toHex()); +} + +export function getGaugeVote( + userAddress: Address, + gaugeAddress: Address, +): GaugeVote { + let id = getGaugeVoteId(userAddress, gaugeAddress); + let gaugeVote = GaugeVote.load(id); + + if (gaugeVote == null) { + gaugeVote = new GaugeVote(id); + gaugeVote.user = userAddress.toHexString(); + gaugeVote.gauge = getGaugeIdFromController(gaugeAddress); + gaugeVote.save(); + } + + return gaugeVote; +} + +function getTypeName(typeNumber: BigInt): string { + let controller = GaugeController.bind(CONTROLLER_ADDRESS); + let nameCall = controller.try_gauge_type_names(typeNumber); + let name = nameCall.reverted ? '' : nameCall.value; + + return name; +} + +export function getGaugeType(typeNumber: BigInt): GaugeType { + let typeId = typeNumber.toString(); + let type = GaugeType.load(typeId); + + if (type == null) { + type = new GaugeType(typeId); + type.name = getTypeName(typeNumber); + } + + type.save(); + + return type; +} + +// Define a simple struct to hold the data returned by calls to reward_data() +class RewardData { + rate: BigInt = ZERO; + + period_finish: BigInt = ZERO; + + received: BigInt = ZERO; + + // eslint-disable-next-line + reverted: boolean = false; +} + +/** + * Sets the reward data for a reward token of a given gauge + * If the token does not exist on the gauge, it will be created + */ +export function setRewardData( + gaugeAddress: Address, + tokenAddress: Address, +): void { + let gauge = LiquidityGauge.load(gaugeAddress.toHex()); + if (!gauge) return; + + // On L1 gauges and child chains gauges V2, reward data is stored in the gauge itself + // On child chains gauges V1, reward data is stored in the streamer contract + // Moreover, the output of reward_data() is different for mainnet vs child chain gauges V1 vs child chain gauges V2. + // This means we can't reuse the same contract on .bind, so we make speficic functions for each case + + let reward_data: RewardData; + let streamer = gauge.streamer; + if (streamer) { + let streamerAddress = bytesToAddress(streamer); + reward_data = readRewardDataFromStreamer(streamerAddress, tokenAddress); + } else if (isL1Factory(Address.fromString(gauge.factory))) { + reward_data = readRewardDataFromL1Gauge(gaugeAddress, tokenAddress); + } else { + reward_data = readRewardDataFromChildChainLiquidityGaugeV2( + gaugeAddress, + tokenAddress, + ); + } + + if (reward_data.reverted) return; + + // getRewardToken will create the token if it does not exist + const rewardToken = getRewardToken(tokenAddress, gaugeAddress); + rewardToken.periodFinish = reward_data.period_finish; + rewardToken.rate = scaleDown(reward_data.rate, rewardToken.decimals); + if (reward_data.received.gt(ZERO)) { + rewardToken.totalDeposited = scaleDown( + reward_data.received, + rewardToken.decimals, + ); + } + rewardToken.save(); +} + +function readRewardDataFromStreamer( + streamerAddress: Address, + tokenAddress: Address, +): RewardData { + let rewardData = new RewardData(); + let streamerContract = ChildChainStreamer.bind(streamerAddress); + let rewardDataCall = streamerContract.try_reward_data(tokenAddress); + if (rewardDataCall.reverted) { + log.warning( + 'readRewardDataFromStreamer Call to reward_data() failed: {} {}', + [streamerAddress.toHexString(), tokenAddress.toHexString()], + ); + rewardData.reverted = true; + } else { + rewardData.rate = rewardDataCall.value.rate; + rewardData.period_finish = rewardDataCall.value.period_finish; + rewardData.received = rewardDataCall.value.received; + } + return rewardData; +} + +function readRewardDataFromL1Gauge( + gaugeAddress: Address, + tokenAddress: Address, +): RewardData { + let rewardData = new RewardData(); + let gaugeContract = LiquidityGaugeTemplate.bind(gaugeAddress); + let rewardDataCall = gaugeContract.try_reward_data(tokenAddress); + if (rewardDataCall.reverted) { + log.warning( + 'readRewardDataFromL1Gauge Call to reward_data() failed: {} {}', + [gaugeAddress.toHexString(), tokenAddress.toHexString()], + ); + rewardData.reverted = true; + } else { + rewardData.rate = rewardDataCall.value.rate; + rewardData.period_finish = rewardDataCall.value.period_finish; + } + return rewardData; +} + +function readRewardDataFromChildChainLiquidityGaugeV2( + gaugeAddress: Address, + tokenAddress: Address, +): RewardData { + let rewardData = new RewardData(); + let gaugeContract = ChildChainLiquidityGaugeV2.bind(gaugeAddress); + let rewardDataCall = gaugeContract.try_reward_data(tokenAddress); + if (rewardDataCall.reverted) { + log.warning( + 'readRewardDataFromChildChainLiquidityGaugeV2 Call to reward_data() failed: {} {}', + [gaugeAddress.toHexString(), tokenAddress.toHexString()], + ); + rewardData.reverted = true; + } else { + rewardData.rate = rewardDataCall.value.rate; + rewardData.period_finish = rewardDataCall.value.period_finish; + } + return rewardData; +} diff --git a/subgraphs/gauges/src/helpers/maths.ts b/subgraphs/gauges/src/helpers/maths.ts new file mode 100644 index 0000000..53fd2f3 --- /dev/null +++ b/subgraphs/gauges/src/helpers/maths.ts @@ -0,0 +1,18 @@ +import { BigDecimal, BigInt } from '@graphprotocol/graph-ts'; + +export function scaleDown(num: BigInt, decimals: i32): BigDecimal { + return num.divDecimal(BigInt.fromI32(10).pow(u8(decimals)).toBigDecimal()); +} + +export function scaleDownBPT(num: BigInt): BigDecimal { + return scaleDown(num, 18); +} + +export function scaleUp(num: BigDecimal, decimals: i32): BigInt { + return BigInt.fromString( + num + .truncate(decimals) + .times(BigInt.fromI32(10).pow(u8(decimals)).toBigDecimal()) + .toString(), + ); +} diff --git a/subgraphs/gauges/src/helpers/misc.ts b/subgraphs/gauges/src/helpers/misc.ts new file mode 100644 index 0000000..b496054 --- /dev/null +++ b/subgraphs/gauges/src/helpers/misc.ts @@ -0,0 +1,77 @@ +import { Address, Bytes } from "@graphprotocol/graph-ts"; + +import { Pool, User } from "../types/schema"; +import { ERC20 } from "../types/templates/LiquidityGauge/ERC20"; +import { WeightedPool } from "../types/GaugeFactory/WeightedPool"; +import { Vault } from "../types/GaugeFactory/Vault"; +import { VAULT_ADDRESS, VAULT_V2_ADDRESS } from "./constants"; + +export function bytesToAddress(address: Bytes): Address { + return Address.fromString(address.toHexString()); +} + +export function createUserEntity(address: Address): void { + let addressHex = address.toHex(); + if (User.load(addressHex) == null) { + let user = new User(addressHex); + user.save(); + } +} + +export function getTokenDecimals(tokenAddress: Address): i32 { + let token = ERC20.bind(tokenAddress); + let result = token.try_decimals(); + + return result.reverted ? 0 : result.value; +} + +export function getTokenSymbol(tokenAddress: Address): string { + let token = ERC20.bind(tokenAddress); + let result = token.try_symbol(); + + return result.reverted ? "" : result.value; +} + +export function getPoolId(poolAddress: Address): Bytes | null { + let pool = WeightedPool.bind(poolAddress); + let result = pool.try_getPoolId(); + + return result.reverted ? null : result.value; +} + +export function getPoolEntity( + poolAddress: Address, + gaugeAddress: Address +): Pool { + let pool = Pool.load(poolAddress.toHex()); + + if (pool == null) { + pool = new Pool(poolAddress.toHex()); + pool.address = poolAddress; + pool.poolId = getPoolId(poolAddress); + pool.gaugesList = [gaugeAddress]; + pool.save(); + return pool; + } + + const gaugesList = pool.gaugesList; + gaugesList.push(gaugeAddress); + pool.gaugesList = gaugesList; + + return pool; +} + +export function isPoolRegistered(poolAddress: Address): boolean { + let poolId = getPoolId(poolAddress); + if (!poolId) return false; // TODO: fix once v3 launches, uncomment code below + + let vaultV2 = Vault.bind(VAULT_V2_ADDRESS); + let getV2PoolCall = vaultV2.try_getPool(poolId); + if (!getV2PoolCall.reverted && getV2PoolCall.value.value0) return true; + + // let vaultV3 = Vault.bind(VAULT_ADDRESS); + // let getPoolCall = vaultV3.try_getPool(poolAddress); + // if (!getPoolCall.reverted && getPoolCall.value.value0) return true; + + return false; +} diff --git a/subgraphs/gauges/src/mappings/authorizerAdaptorEntrypoint.ts b/subgraphs/gauges/src/mappings/authorizerAdaptorEntrypoint.ts new file mode 100644 index 0000000..43d46b4 --- /dev/null +++ b/subgraphs/gauges/src/mappings/authorizerAdaptorEntrypoint.ts @@ -0,0 +1,30 @@ +import { Bytes } from "@graphprotocol/graph-ts"; +import { ActionPerformed } from "../types/AuthorizerAdaptorEntrypoint/authorizerAdaptorEntrypoint"; +import { bytesToAddress } from "../helpers/misc"; +import { setRewardData } from "../helpers/gauge"; +import { LiquidityGauge } from "../types/schema"; + +/** + * When a reward token is added to a gauge via the AuthorizerAdaptorEntrypoint, we set the reward data for that token + * In doing so, we create the reward token entity if it does not exist, as well as an entry in the gauge's rewardTokensList + */ +function handleAddRewardToken(event: ActionPerformed): void { + const gaugeAddress = event.params.target; + const callData = event.params.data; + // parse callData, which is a 4-byte selector, followed by a 32-byte token address followed by a 32-byte distributor address + let token = Bytes.fromUint8Array(callData.subarray(16, 36)); + let tokenAddress = bytesToAddress(token); + + let gauge = LiquidityGauge.load(gaugeAddress.toHexString()); + if (!gauge) return; + + setRewardData(gaugeAddress, tokenAddress); +} + +export function handleActionPerformed(event: ActionPerformed): void { + const selector = event.params.selector.toHexString(); + if (selector == "0xe8de0d4d") { + // add_reward(_reward_token (address), _distributor (address)) + handleAddRewardToken(event); + } +} diff --git a/subgraphs/gauges/src/mappings/eventEmitter.ts b/subgraphs/gauges/src/mappings/eventEmitter.ts new file mode 100644 index 0000000..85d2220 --- /dev/null +++ b/subgraphs/gauges/src/mappings/eventEmitter.ts @@ -0,0 +1,111 @@ +import { LogArgument } from "../types/EventEmitter/EventEmitter"; +import { Pool, LiquidityGauge, GaugeInjector } from "../types/schema"; +import { GaugeInjector as GaugeInjectorTemplate } from "../types/templates"; +import { setRewardData } from "../helpers/gauge"; +import { bytesToAddress } from "../helpers/misc"; + +export function handleLogArgument(event: LogArgument): void { + const identifier = event.params.identifier.toHexString(); + + // convention: identifier = keccak256(function_name) + // keccak256(setPreferentialGauge) = 0x88aea7780a038b8536bb116545f59b8a089101d5e526639d3c54885508ce50e2 + if ( + identifier == + "0x88aea7780a038b8536bb116545f59b8a089101d5e526639d3c54885508ce50e2" + ) { + setPreferentialGauge(event); + } + // keccak256(setChildChainGaugeRewardsData) = 0x685ed9250f0df428a962860f87b2d95fbbd38473b0f6773f3650d19ffbbb9fb5 + if ( + identifier == + "0x94e5a0dff823a8fce9322f522279854e2370a9ef309a74a7a86367e2a2872b2d" + ) { + setGaugeRewardsData(event); + } + // keccak256(setGaugeInjector) = 0x109783b117ecbf8caf4e937abaf494b965e5d90c4d1b010b27eb2a3be80eaf21 + if ( + identifier == + "0x109783b117ecbf8caf4e937abaf494b965e5d90c4d1b010b27eb2a3be80eaf21" + ) { + setGaugeInjector(event); + } +} + +function setGaugeRewardsData(event: LogArgument): void { + /** + * Sets the reward data for all reward tokens of a given gauge + * + * @param message - The gauge address (eg. 0x12345abce... - all lowercase) + */ + const gaugeAddress = event.params.message; + const gauge = LiquidityGauge.load(gaugeAddress.toHexString()); + if (!gauge) return; + + const rewardTokens = gauge.rewardTokensList; + if (!rewardTokens) return; + + for (let i: i32 = 0; i < rewardTokens.length; i++) { + setRewardData( + bytesToAddress(gaugeAddress), + bytesToAddress(rewardTokens[i]) + ); + } +} + +function setPreferentialGauge(event: LogArgument): void { + /** + * Sets/Unsets a gauge as the preferential gauge + * It is expected that a new gauge will be set as preferential after unsetting the old one + * + * @param message - The gauge address (eg. 0x12345abce... - all lowercase) + * @param value - 0 if prefentialGauge is to be set false; any other value sets it to true + */ // + const gaugeId = event.params.message.toHexString(); + const gauge = LiquidityGauge.load(gaugeId); + if (!gauge) return; + + if (event.params.value.toI32() == 0) { + gauge.isPreferentialGauge = false; + // Update Pool's preferentialGauge + + let poolId = gauge.pool; + if (poolId === null) return; + + let pool = Pool.load(poolId); + if (pool == null) return; + + pool.preferentialGauge = ""; + pool.save(); + } else { + gauge.isPreferentialGauge = true; + // Update Pool's preferentialGauge + + let poolId = gauge.pool; + if (poolId === null) return; + + let pool = Pool.load(poolId); + if (pool == null) return; + + pool.preferentialGauge = gaugeId; + pool.save(); + } + gauge.save(); +} + +export function setGaugeInjector(event: LogArgument): void { + /** + * Sets a new GaugeInjector - creates entity and template + * + * @param message - The GaugeInjector address (eg. 0x12345abce... - all lowercase) + */ + const injectorId = event.params.message.toHexString(); + + let injector = GaugeInjector.load(injectorId); + if (injector) return; // already exists, no need to re-create it + + injector = new GaugeInjector(injectorId); + injector.save(); + + const injectorAddress = bytesToAddress(event.params.message); + GaugeInjectorTemplate.create(injectorAddress); +} diff --git a/subgraphs/gauges/src/mappings/gauge.ts b/subgraphs/gauges/src/mappings/gauge.ts new file mode 100644 index 0000000..1743577 --- /dev/null +++ b/subgraphs/gauges/src/mappings/gauge.ts @@ -0,0 +1,303 @@ +import { ZERO_ADDRESS } from "../helpers/constants"; +import { getGaugeShare, getRewardToken, setRewardData } from "../helpers/gauge"; +import { scaleDown, scaleDownBPT } from "../helpers/maths"; +import { + Gauge, + LiquidityGauge, + Pool, + RootGauge, + SingleRecipientGauge, +} from "../types/schema"; + +import { + Transfer, + // eslint-disable-next-line camelcase + Deposit_reward_tokenCall, +} from "../types/templates/LiquidityGauge/LiquidityGauge"; +import { + KillGaugeCall, + UnkillGaugeCall, +} from "../types/templates/RootGauge/ArbitrumRootGauge"; +import { RelativeWeightCapChanged } from "../types/GaugeV2Factory/LiquidityGauge"; +import { + ChildChainStreamer, + RewardDurationUpdated, +} from "../types/templates/ChildChainStreamer/ChildChainStreamer"; +import { bytesToAddress } from "../helpers/misc"; + +/** + * On mainnet we can detect when a reward token is deposited into a gauge by listening for the Deposit_reward_tokenCall + * When a reward token is deposited in the gauge, we set its reward data, creating the reward token entity in the process if it doesn't exist + */ +// eslint-disable-next-line camelcase +export function handleDepositRewardToken(call: Deposit_reward_tokenCall): void { + /* eslint-disable no-underscore-dangle */ + const gaugeAddress = call.to; + const tokenAddress = call.inputs._reward_token; + const amount = call.inputs._amount; + /* eslint-enable no-underscore-dangle */ + + let gauge = LiquidityGauge.load(gaugeAddress.toHexString()); + if (!gauge) return; + setRewardData(gaugeAddress, tokenAddress); + + const rewardToken = getRewardToken(tokenAddress, gaugeAddress); + const amountScaled = scaleDown(amount, rewardToken.decimals); + rewardToken.totalDeposited = rewardToken.totalDeposited.plus(amountScaled); + rewardToken.save(); +} + +export function handleTransfer(event: Transfer): void { + let gaugeAddress = event.address; + + let gauge = LiquidityGauge.load(gaugeAddress.toHexString()) as LiquidityGauge; + + /* eslint-disable no-underscore-dangle */ + let fromAddress = event.params._from; + let toAddress = event.params._to; + let value = event.params._value; + /* eslint-enable no-underscore-dangle */ + + let isMint = fromAddress.toHexString() == ZERO_ADDRESS; + let isBurn = toAddress.toHexString() == ZERO_ADDRESS; + + if (isMint) { + let userShareTo = getGaugeShare(toAddress, gaugeAddress); + userShareTo.balance = userShareTo.balance.plus(scaleDownBPT(value)); + userShareTo.save(); + gauge.totalSupply = gauge.totalSupply.plus(scaleDownBPT(value)); + } else if (isBurn) { + let userShareFrom = getGaugeShare(fromAddress, gaugeAddress); + userShareFrom.balance = userShareFrom.balance.minus(scaleDownBPT(value)); + userShareFrom.save(); + gauge.totalSupply = gauge.totalSupply.minus(scaleDownBPT(value)); + } else { + let userShareTo = getGaugeShare(toAddress, gaugeAddress); + userShareTo.balance = userShareTo.balance.plus(scaleDownBPT(value)); + userShareTo.save(); + + let userShareFrom = getGaugeShare(fromAddress, gaugeAddress); + userShareFrom.balance = userShareFrom.balance.minus(scaleDownBPT(value)); + userShareFrom.save(); + } + + gauge.save(); + + const rewardTokens = gauge.rewardTokensList; + if (!rewardTokens) return; + + for (let i: i32 = 0; i < rewardTokens.length; i++) { + setRewardData(gaugeAddress, bytesToAddress(rewardTokens[i])); + } +} + +export function handleRootKillGauge(call: KillGaugeCall): void { + // eslint-disable-next-line no-underscore-dangle + let gauge = RootGauge.load(call.to.toHexString()) as RootGauge; + gauge.isKilled = true; + gauge.save(); +} + +export function handleRootUnkillGauge(call: UnkillGaugeCall): void { + // eslint-disable-next-line no-underscore-dangle + let gauge = RootGauge.load(call.to.toHexString()) as RootGauge; + gauge.isKilled = false; + gauge.save(); +} + +export function handleSingleRecipientKillGauge(call: KillGaugeCall): void { + // eslint-disable-next-line no-underscore-dangle + let gauge = SingleRecipientGauge.load( + call.to.toHexString() + ) as SingleRecipientGauge; + gauge.isKilled = true; + gauge.save(); +} + +export function handleSingleRecipientUnkillGauge(call: UnkillGaugeCall): void { + // eslint-disable-next-line no-underscore-dangle + let gauge = SingleRecipientGauge.load( + call.to.toHexString() + ) as SingleRecipientGauge; + gauge.isKilled = false; + gauge.save(); +} + +export function handleKillGauge(call: KillGaugeCall): void { + // eslint-disable-next-line no-underscore-dangle + let killedGaugeId = call.to.toHexString(); + let killedGauge = LiquidityGauge.load(killedGaugeId); + if (killedGauge == null) return; + killedGauge.isKilled = true; + killedGauge.isPreferentialGauge = false; + killedGauge.save(); + + // Update Pool's preferentialGauge + + let poolId = killedGauge.pool; + if (poolId === null) return; + + let pool = Pool.load(poolId); + if (pool == null) return; + + let currentPreferentialGaugeId = pool.preferentialGauge; + + if ( + currentPreferentialGaugeId && + currentPreferentialGaugeId == killedGaugeId + ) { + pool.preferentialGauge = ""; + + let preferencialGaugeTimestamp = 0; + for (let i: i32 = 0; i < pool.gaugesList.length; i++) { + if (currentPreferentialGaugeId == pool.gaugesList[i].toHex()) continue; + + let liquidityGauge = LiquidityGauge.load( + pool.gaugesList[i].toHex() + ) as LiquidityGauge; + + let gaugeId = liquidityGauge.gauge; + if (gaugeId === null) continue; // Gauge not added to GaugeController + + let gauge = Gauge.load(gaugeId) as Gauge; + + if ( + !liquidityGauge.isKilled && + gauge.addedTimestamp > preferencialGaugeTimestamp + ) { + pool.preferentialGauge = liquidityGauge.id; + preferencialGaugeTimestamp = gauge.addedTimestamp; + } + } + } + + pool.save(); + + let poolPreferentialGauge = pool.preferentialGauge; + if (poolPreferentialGauge === null) return; + + let preferentialGauge = LiquidityGauge.load(poolPreferentialGauge); + if (preferentialGauge == null) return; + + preferentialGauge.isPreferentialGauge = true; + preferentialGauge.save(); +} + +export function handleUnkillGauge(call: UnkillGaugeCall): void { + // eslint-disable-next-line no-underscore-dangle + let unkilledLiquidityGaugeId = call.to.toHexString(); + let unkilledLiquidityGauge = LiquidityGauge.load(unkilledLiquidityGaugeId); + if (unkilledLiquidityGauge == null) return; + unkilledLiquidityGauge.isKilled = false; + unkilledLiquidityGauge.save(); + + let unkilledGaugeId = unkilledLiquidityGauge.gauge; + if (unkilledGaugeId === null) return; // Gauge not added to GaugeController + + // Update Pool's preferentialGauge + + let poolId = unkilledLiquidityGauge.pool; + if (poolId === null) return; + let pool = Pool.load(poolId); + if (pool == null) return; + + let preferentialGaugeId = pool.preferentialGauge; + if (preferentialGaugeId === null) { + pool.preferentialGauge = unkilledLiquidityGaugeId; + pool.save(); + + unkilledLiquidityGauge.isPreferentialGauge = true; + unkilledLiquidityGauge.save(); + + return; + } + + let preferentialGauge = LiquidityGauge.load( + preferentialGaugeId + ) as LiquidityGauge; + + let currentPreferentialGaugeId = preferentialGauge.gauge; + if (currentPreferentialGaugeId === null) { + pool.preferentialGauge = unkilledLiquidityGaugeId; + pool.save(); + + unkilledLiquidityGauge.isPreferentialGauge = true; + unkilledLiquidityGauge.save(); + + return; + } + + let unkilledGauge = Gauge.load(unkilledGaugeId) as Gauge; + let currentPreferentialGauge = Gauge.load( + currentPreferentialGaugeId + ) as Gauge; + + if (unkilledGauge.addedTimestamp > currentPreferentialGauge.addedTimestamp) { + pool.preferentialGauge = unkilledLiquidityGaugeId; + pool.save(); + + unkilledLiquidityGauge.isPreferentialGauge = true; + unkilledLiquidityGauge.save(); + + let currentPreferentialLiquidityGaugeId = + currentPreferentialGauge.liquidityGauge; + if (currentPreferentialLiquidityGaugeId) { + let currentPreferentialLiquidityGauge = LiquidityGauge.load( + currentPreferentialLiquidityGaugeId + ) as LiquidityGauge; + currentPreferentialLiquidityGauge.isPreferentialGauge = false; + currentPreferentialLiquidityGauge.save(); + } + } +} + +export function handleRelativeWeightCapChanged( + event: RelativeWeightCapChanged +): void { + let gauge = LiquidityGauge.load( + event.address.toHexString() + ) as LiquidityGauge; + gauge.relativeWeightCap = scaleDownBPT(event.params.new_relative_weight_cap); + gauge.save(); +} + +export function handleRootGaugeRelativeWeightCapChanged( + event: RelativeWeightCapChanged +): void { + let gauge = RootGauge.load(event.address.toHexString()) as RootGauge; + gauge.relativeWeightCap = scaleDownBPT(event.params.new_relative_weight_cap); + gauge.save(); +} + +export function handleSingleRecipientGaugeRelativeWeightCapChanged( + event: RelativeWeightCapChanged +): void { + let gauge = SingleRecipientGauge.load( + event.address.toHexString() + ) as SingleRecipientGauge; + gauge.relativeWeightCap = scaleDownBPT(event.params.new_relative_weight_cap); + gauge.save(); +} + +/** + * RewardDurationUpdated is an event emitted by the ChildChainStreamer contract + * It is emitted when a token if added to the ChildChainStreamer contract, so + * we use it as a trigger to update the reward data of the respecitve token + * on the gauge asssociated with the ChildChainStreamer contract in question. + * If the token does not exist on the gauge, we create it. + */ +export function handleRewardDurationUpdated( + event: RewardDurationUpdated +): void { + // find the gauge associated with the ChildChainStreamer contract + let streamer = ChildChainStreamer.bind(event.address); + let gaugeCall = streamer.try_reward_receiver(); + if (gaugeCall.reverted) return; + + const gaugeAddress = gaugeCall.value; + let gauge = LiquidityGauge.load(gaugeAddress.toHexString()); + if (!gauge) return; + + const rewardToken = event.params.reward_token; + setRewardData(gaugeAddress, rewardToken); +} diff --git a/subgraphs/gauges/src/mappings/gaugeController.ts b/subgraphs/gauges/src/mappings/gaugeController.ts new file mode 100644 index 0000000..3ea9d36 --- /dev/null +++ b/subgraphs/gauges/src/mappings/gaugeController.ts @@ -0,0 +1,93 @@ +import { + AddType, + NewGauge, + VoteForGauge, +} from "../types/GaugeController/GaugeController"; +import { + Gauge, + LiquidityGauge, + Pool, + RootGauge, + SingleRecipientGauge, +} from "../types/schema"; +import { getGaugeVote, getGaugeId, getGaugeType } from "../helpers/gauge"; +import { scaleDownBPT } from "../helpers/maths"; + +export function handleVoteForGauge(event: VoteForGauge): void { + let userAddress = event.params.user; + let gaugeAddress = event.params.gauge_addr; + + let gaugeVote = getGaugeVote(userAddress, gaugeAddress); + gaugeVote.weight = scaleDownBPT(event.params.weight); + gaugeVote.timestamp = event.params.time; + gaugeVote.save(); +} + +export function handleAddType(event: AddType): void { + let type = getGaugeType(event.params.type_id); + type.save(); +} + +export function handleNewGauge(event: NewGauge): void { + let gaugeId = getGaugeId(event.params.addr, event.params.gauge_type); + let type = getGaugeType(event.params.gauge_type); + let gauge = Gauge.load(gaugeId); + + const gaugeHex = event.params.addr.toHexString(); + let singleRecipientGauge = SingleRecipientGauge.load(gaugeHex); + let liquidityGauge = LiquidityGauge.load(gaugeHex); + let rootGauge = RootGauge.load(gaugeHex); + + if (gauge == null) { + gauge = new Gauge(gaugeId); + gauge.address = event.params.addr; + gauge.type = type.id; + gauge.addedTimestamp = event.block.timestamp.toI32(); + gauge.liquidityGauge = liquidityGauge ? liquidityGauge.id : null; + gauge.rootGauge = rootGauge ? rootGauge.id : null; + } + + gauge.save(); + + if (rootGauge != null) { + rootGauge.gauge = gaugeId; + rootGauge.save(); + } + + if (singleRecipientGauge != null) { + singleRecipientGauge.gauge = gaugeId; + singleRecipientGauge.save(); + } + + // If LiquidityGauge, update Pool's prefentialGauge + + if (liquidityGauge != null) { + liquidityGauge.gauge = gaugeId; + liquidityGauge.save(); + + let poolId = liquidityGauge.pool; + if (poolId === null) return; + + let pool = Pool.load(poolId); + if (pool == null) return; + + liquidityGauge.isPreferentialGauge = true; + liquidityGauge.save(); + + let currentPreferentialGaugeId = pool.preferentialGauge; + + pool.preferentialGauge = liquidityGauge.id; + pool.save(); + + if ( + currentPreferentialGaugeId === null || + currentPreferentialGaugeId == liquidityGauge.id + ) + return; + let currentPreferentialGauge = LiquidityGauge.load( + currentPreferentialGaugeId + ) as LiquidityGauge; + currentPreferentialGauge.isPreferentialGauge = false; + currentPreferentialGauge.save(); + } +} diff --git a/subgraphs/gauges/src/mappings/gaugeFactory.ts b/subgraphs/gauges/src/mappings/gaugeFactory.ts new file mode 100644 index 0000000..c6e1e4a --- /dev/null +++ b/subgraphs/gauges/src/mappings/gaugeFactory.ts @@ -0,0 +1,206 @@ +import { Address, log } from "@graphprotocol/graph-ts"; + +import { GaugeFactory, RootGauge, SingleRecipientGauge } from "../types/schema"; +import { getLiquidityGauge } from "../helpers/gauge"; + +import { + RootGauge as RootGaugeTemplate, + LiquidityGauge as LiquidityGaugeTemplate, + RewardsOnlyGauge as RewardsOnlyGaugeTemplate, + ChildChainStreamer as ChildChainStreamerTemplate, + SingleRecipientGauge as SingleRecipientGaugeTemplate, +} from "../types/templates"; +import { getPoolEntity, getPoolId, isPoolRegistered } from "../helpers/misc"; +import { RewardsOnlyGaugeCreated } from "../types/ChildChainLiquidityGaugeFactory/ChildChainLiquidityGaugeFactory"; +import { + isArbitrumFactory, + isAvalancheFactory, + isBaseFactory, + isFraxtalFactory, + isGnosisFactory, + isOptimismFactory, + isPolygonFactory, + isPolygonZkEVMFactory, +} from "../helpers/constants"; +import { GaugeCreated as LiquidityGaugeCreated } from "../types/GaugeV2Factory/GaugeV2Factory"; +import { GaugeCreated as RootGaugeCreated } from "../types/ArbitrumRootGaugeV2Factory/ArbitrumRootGaugeV2Factory"; +import { LiquidityGauge as LiquidityGaugeV2 } from "../types/GaugeV2Factory/LiquidityGauge"; +import { ArbitrumRootGauge as RootGaugeContract } from "../types/templates/RootGauge/ArbitrumRootGauge"; + +function getGaugeFactory(address: Address): GaugeFactory { + let factory = GaugeFactory.load(address.toHexString()); + + if (factory == null) { + factory = new GaugeFactory(address.toHexString()); + factory.numGauges = 0; + factory.save(); + } + + return factory; +} + +export function handleMainnetLiquidityGaugeCreated( + event: LiquidityGaugeCreated +): void { + handleLiquidityGaugeCreated(event, false); +} + +export function handleChildChainV2LiquidityGaugeCreated( + event: LiquidityGaugeCreated +): void { + handleLiquidityGaugeCreated(event, true); +} + +function handleLiquidityGaugeCreated( + event: LiquidityGaugeCreated, + childChainGauge: boolean +): void { + const gaugeAddress = event.params.gauge; + const factoryAddress = event.address; + let factory = getGaugeFactory(factoryAddress); + factory.numGauges += 1; + factory.save(); + + const gaugeContract = LiquidityGaugeV2.bind(gaugeAddress); + const lpTokenCall = gaugeContract.try_lp_token(); + if (lpTokenCall.reverted) { + log.warning("Call to lp_token() failed: {} {}", [ + gaugeAddress.toHexString(), + event.transaction.hash.toHexString(), + ]); + return; + } + + const poolAddress = lpTokenCall.value; + const poolRegistered = isPoolRegistered(poolAddress); + + let gauge = getLiquidityGauge(gaugeAddress, poolAddress); + + if (poolRegistered) { + const pool = getPoolEntity(lpTokenCall.value, gaugeAddress); + // If we're on a child chain and the pool doesn't have a preferential gauge yet + if (childChainGauge && pool.preferentialGauge === null) { + pool.preferentialGauge = gauge.id; + gauge.isPreferentialGauge = true; + } + pool.save(); + } + + gauge.pool = poolRegistered ? poolAddress.toHexString() : null; + gauge.poolId = poolRegistered ? getPoolId(poolAddress) : null; + gauge.factory = factory.id; + gauge.save(); + + // Gauge's relativeWeightCap is set on event RelativeWeightCapChanged + + LiquidityGaugeTemplate.create(gaugeAddress); +} + +export function handleRewardsOnlyGaugeCreated( + event: RewardsOnlyGaugeCreated +): void { + let factory = getGaugeFactory(event.address); + factory.numGauges += 1; + factory.save(); + + let poolAddress = event.params.pool; + const poolRegistered = isPoolRegistered(poolAddress); + + let gauge = getLiquidityGauge(event.params.gauge, poolAddress); + gauge.streamer = event.params.streamer; + gauge.pool = poolRegistered ? poolAddress.toHexString() : null; + gauge.poolId = poolRegistered ? getPoolId(poolAddress) : null; + gauge.factory = factory.id; + + if (poolRegistered) { + let pool = getPoolEntity(poolAddress, event.params.gauge); + pool.address = poolAddress; + pool.poolId = getPoolId(poolAddress); + pool.preferentialGauge = gauge.id; + gauge.isPreferentialGauge = true; + pool.save(); + } + + gauge.save(); + + RewardsOnlyGaugeTemplate.create(event.params.gauge); + ChildChainStreamerTemplate.create(event.params.streamer); +} + +export function handleSingleRecipientGaugeCreated( + event: LiquidityGaugeCreated +): void { + const gaugeAddress = event.params.gauge; + const factoryAddress = event.address; + let factory = getGaugeFactory(factoryAddress); + factory.numGauges += 1; + factory.save(); + + const rootGaugeContract = RootGaugeContract.bind(gaugeAddress); + const recipientCall = rootGaugeContract.try_getRecipient(); + if (recipientCall.reverted) { + log.warning("Call to getRecipient() failed: {} {}", [ + gaugeAddress.toHexString(), + event.transaction.hash.toHexString(), + ]); + return; + } + + let gauge = new SingleRecipientGauge(gaugeAddress.toHexString()); + gauge.recipient = recipientCall.value; + gauge.isKilled = false; + gauge.factory = factoryAddress.toHexString(); + + gauge.save(); + + // Gauge's relativeWeightCap is set on event RelativeWeightCapChanged + + SingleRecipientGaugeTemplate.create(gaugeAddress); +} + +export function handleRootGaugeCreated(event: RootGaugeCreated): void { + const gaugeAddress = event.params.gauge; + const factoryAddress = event.address; + let factory = getGaugeFactory(factoryAddress); + factory.numGauges += 1; + factory.save(); + + const rootGaugeContract = RootGaugeContract.bind(gaugeAddress); + const recipientCall = rootGaugeContract.try_getRecipient(); + if (recipientCall.reverted) { + log.warning("Call to getRecipient() failed: {} {}", [ + gaugeAddress.toHexString(), + event.transaction.hash.toHexString(), + ]); + return; + } + + let gauge = new RootGauge(gaugeAddress.toHexString()); + gauge.recipient = recipientCall.value; + gauge.isKilled = false; + gauge.factory = factoryAddress.toHexString(); + + if (isArbitrumFactory(factoryAddress)) { + gauge.chain = "Arbitrum"; + } else if (isOptimismFactory(factoryAddress)) { + gauge.chain = "Optimism"; + } else if (isPolygonFactory(factoryAddress)) { + gauge.chain = "Polygon"; + } else if (isGnosisFactory(factoryAddress)) { + gauge.chain = "Gnosis"; + } else if (isAvalancheFactory(factoryAddress)) { + gauge.chain = "Avalanche"; + } else if (isPolygonZkEVMFactory(factoryAddress)) { + gauge.chain = "PolygonZkEvm"; + } else if (isBaseFactory(factoryAddress)) { + gauge.chain = "Base"; + } else if (isFraxtalFactory(factoryAddress)) { + gauge.chain = "Fraxtal"; + } + + gauge.save(); + + // Gauge's relativeWeightCap is set on event RelativeWeightCapChanged + + RootGaugeTemplate.create(gaugeAddress); +} diff --git a/subgraphs/gauges/src/mappings/gaugeInjector.ts b/subgraphs/gauges/src/mappings/gaugeInjector.ts new file mode 100644 index 0000000..9004459 --- /dev/null +++ b/subgraphs/gauges/src/mappings/gaugeInjector.ts @@ -0,0 +1,6 @@ +import { EmissionsInjection } from "../types/templates/GaugeInjector/GaugeInjector"; +import { setRewardData } from "../helpers/gauge"; + +export function handleEmissionsInjection(event: EmissionsInjection): void { + setRewardData(event.params.gauge, event.params.token); +} diff --git a/subgraphs/gauges/src/mappings/voting.ts b/subgraphs/gauges/src/mappings/voting.ts new file mode 100644 index 0000000..6452596 --- /dev/null +++ b/subgraphs/gauges/src/mappings/voting.ts @@ -0,0 +1,154 @@ +import { + VotingEscrowLock, + VotingEscrow, + LockSnapshot, + OmniVotingEscrowLock, +} from "../types/schema"; +import { UserBalToChain } from "../types/OmniVotingEscrow/omniVotingEscrow"; +import { UserBalFromChain } from "../types/OmniVotingEscrowChild/omniVotingEscrowChild"; +import { Deposit, Supply, Withdraw } from "../types/VotingEscrow/votingEscrow"; +import { LOCK_MAXTIME, ZERO, ZERO_BD } from "../helpers/constants"; +import { + getLockSnapshotId, + getOmniVotingEscrowId, + getVotingEscrowId, +} from "../helpers/gauge"; +import { scaleDownBPT, scaleUp } from "../helpers/maths"; +import { createUserEntity } from "../helpers/misc"; + +export function handleDeposit(event: Deposit): void { + let userAddress = event.params.provider; + createUserEntity(userAddress); + + let id = getVotingEscrowId(userAddress, event.address); + let votingShare = VotingEscrowLock.load(id); + + if (votingShare == null) { + votingShare = new VotingEscrowLock(id); + votingShare.user = userAddress.toHexString(); + votingShare.votingEscrowID = event.address.toHexString(); + votingShare.lockedBalance = ZERO_BD; + } + + let blockTimestamp = event.block.timestamp; + let depositAmount = scaleDownBPT(event.params.value); + + votingShare.unlockTime = event.params.locktime; + votingShare.updatedAt = blockTimestamp.toI32(); + + votingShare.lockedBalance = votingShare.lockedBalance.plus(depositAmount); + + const slopeBI = scaleUp(votingShare.lockedBalance, 18).div(LOCK_MAXTIME); + const biasBI = slopeBI.times(votingShare.unlockTime.minus(blockTimestamp)); + votingShare.slope = scaleDownBPT(slopeBI); + votingShare.bias = scaleDownBPT(biasBI); + votingShare.timestamp = blockTimestamp.toI32(); + + votingShare.save(); + + const snapshotId = getLockSnapshotId(userAddress, blockTimestamp.toI32()); + let lockSnapshot = LockSnapshot.load(snapshotId); + + if (lockSnapshot == null) { + lockSnapshot = new LockSnapshot(snapshotId); + lockSnapshot.timestamp = votingShare.updatedAt; + lockSnapshot.user = userAddress.toHexString(); + lockSnapshot.slope = votingShare.slope; + lockSnapshot.bias = votingShare.bias; + } + + lockSnapshot.save(); +} + +export function handleWithdraw(event: Withdraw): void { + let userAddress = event.params.provider; + createUserEntity(userAddress); + + let id = getVotingEscrowId(userAddress, event.address); + let votingShare = VotingEscrowLock.load(id); + + if (votingShare == null) return; + + votingShare = new VotingEscrowLock(id); + votingShare.user = userAddress.toHexString(); + votingShare.votingEscrowID = event.address.toHexString(); + votingShare.lockedBalance = ZERO_BD; + votingShare.updatedAt = event.block.timestamp.toI32(); + votingShare.save(); +} + +export function handleSupply(event: Supply): void { + let id = event.address.toHexString(); + let votingEscrow = VotingEscrow.load(id); + + if (votingEscrow == null) { + votingEscrow = new VotingEscrow(id); + } + + votingEscrow.stakedSupply = scaleDownBPT(event.params.supply); + votingEscrow.save(); +} + +export function handleUserBalFromChain(event: UserBalFromChain): void { + if (event.params.userPoint.slope.equals(ZERO)) return; + + let userAddress = event.params.user; + createUserEntity(userAddress); + + let id = getVotingEscrowId(userAddress, event.address); + let votingShare = VotingEscrowLock.load(id); + + if (votingShare == null) { + votingShare = new VotingEscrowLock(id); + votingShare.user = userAddress.toHexString(); + + // if the VotingEscrow entity doesn't exist, create it + let votingEscrowID = event.address.toHexString(); + let votingEscrow = VotingEscrow.load(votingEscrowID); + if (votingEscrow == null) { + votingEscrow = new VotingEscrow(votingEscrowID); + votingEscrow.save(); + } + + votingShare.votingEscrowID = votingEscrowID; + } + + votingShare.updatedAt = event.block.timestamp.toI32(); + + const lockedBalanceBI = event.params.userPoint.slope.times(LOCK_MAXTIME); + votingShare.lockedBalance = scaleDownBPT(lockedBalanceBI); + + votingShare.slope = scaleDownBPT(event.params.userPoint.slope); + votingShare.bias = scaleDownBPT(event.params.userPoint.bias); + votingShare.timestamp = event.params.userPoint.ts.toI32(); + votingShare.unlockTime = event.params.userPoint.ts.plus( + event.params.userPoint.bias.div(event.params.userPoint.slope) + ); + + votingShare.save(); +} + +export function handleUserBalToChain(event: UserBalToChain): void { + let userAddress = event.params.localUser; + createUserEntity(userAddress); + + let contractAddress = event.address; + let dstChainId = event.params.dstChainId; + + let id = getOmniVotingEscrowId(userAddress, contractAddress, dstChainId); + let omniLock = OmniVotingEscrowLock.load(id); + + if (omniLock == null) { + omniLock = new OmniVotingEscrowLock(id); + omniLock.localUser = userAddress.toHexString(); + omniLock.votingEscrowID = "0xc128a9954e6c874ea3d62ce62b468ba073093f25"; + omniLock.dstChainId = event.params.dstChainId; + } + + omniLock.bias = scaleDownBPT(event.params.userPoint.bias); + omniLock.slope = scaleDownBPT(event.params.userPoint.slope); + omniLock.timestamp = event.params.userPoint.ts.toI32(); + omniLock.remoteUser = event.params.remoteUser; + + omniLock.save(); +} diff --git a/subgraphs/pools/tsconfig.json b/subgraphs/gauges/tsconfig.json similarity index 100% rename from subgraphs/pools/tsconfig.json rename to subgraphs/gauges/tsconfig.json diff --git a/subgraphs/v2-vault/README.md b/subgraphs/v2-vault/README.md new file mode 100644 index 0000000..08c8886 --- /dev/null +++ b/subgraphs/v2-vault/README.md @@ -0,0 +1 @@ +# Vault v2 Subgraph diff --git a/subgraphs/v2-vault/abis/BasePool.json b/subgraphs/v2-vault/abis/BasePool.json new file mode 100644 index 0000000..95d908d --- /dev/null +++ b/subgraphs/v2-vault/abis/BasePool.json @@ -0,0 +1,901 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "vault", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "normalizedWeights", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "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": false, + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "PausedStateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + } + ], + "name": "SwapFeePercentageChanged", + "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" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getInvariant", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastInvariant", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNormalizedWeights", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPausedState", + "outputs": [ + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "pauseWindowEndTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodEndTime", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPoolId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSwapFeePercentage", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "protocolSwapFeePercentage", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "name": "onExitPool", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "protocolSwapFeePercentage", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "name": "onJoinPool", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum IVault.SwapKind", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "contract IERC20", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "internalType": "struct IPoolSwapStructs.SwapRequest", + "name": "request", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "balanceTokenIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceTokenOut", + "type": "uint256" + } + ], + "name": "onSwap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "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": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "protocolSwapFeePercentage", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "name": "queryExit", + "outputs": [ + { + "internalType": "uint256", + "name": "bptIn", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "amountsOut", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "protocolSwapFeePercentage", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "name": "queryJoin", + "outputs": [ + { + "internalType": "uint256", + "name": "bptOut", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "amountsIn", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "setPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + } + ], + "name": "setSwapFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/subgraphs/v2-vault/abis/BasePoolFactory.json b/subgraphs/v2-vault/abis/BasePoolFactory.json new file mode 100644 index 0000000..79e5149 --- /dev/null +++ b/subgraphs/v2-vault/abis/BasePoolFactory.json @@ -0,0 +1,47 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "isPoolFromFactory", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/subgraphs/v2-vault/abis/ERC20.json b/subgraphs/v2-vault/abis/ERC20.json new file mode 100644 index 0000000..50368ab --- /dev/null +++ b/subgraphs/v2-vault/abis/ERC20.json @@ -0,0 +1,288 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + } + ], + "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": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/subgraphs/v2-vault/abis/PreMintedBPT.json b/subgraphs/v2-vault/abis/PreMintedBPT.json new file mode 100644 index 0000000..6cfc7aa --- /dev/null +++ b/subgraphs/v2-vault/abis/PreMintedBPT.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [], + "name": "getActualSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/subgraphs/v2-vault/abis/ProtocolFeeCollector.json b/subgraphs/v2-vault/abis/ProtocolFeeCollector.json new file mode 100644 index 0000000..544d405 --- /dev/null +++ b/subgraphs/v2-vault/abis/ProtocolFeeCollector.json @@ -0,0 +1,132 @@ +[ + { + "inputs": [ + { "internalType": "contract IVault", "name": "_vault", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newFlashLoanFeePercentage", + "type": "uint256" + } + ], + "name": "FlashLoanFeePercentageChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newSwapFeePercentage", + "type": "uint256" + } + ], + "name": "SwapFeePercentageChanged", + "type": "event" + }, + { + "inputs": [ + { "internalType": "bytes4", "name": "selector", "type": "bytes4" } + ], + "name": "getActionId", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { "internalType": "contract IAuthorizer", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "getCollectedFeeAmounts", + "outputs": [ + { "internalType": "uint256[]", "name": "feeAmounts", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFlashLoanFeePercentage", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSwapFeePercentage", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newFlashLoanFeePercentage", + "type": "uint256" + } + ], + "name": "setFlashLoanFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newSwapFeePercentage", + "type": "uint256" + } + ], + "name": "setSwapFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vault", + "outputs": [ + { "internalType": "contract IVault", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" }, + { "internalType": "address", "name": "recipient", "type": "address" } + ], + "name": "withdrawCollectedFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/subgraphs/v2-vault/abis/RateProviders.json b/subgraphs/v2-vault/abis/RateProviders.json new file mode 100644 index 0000000..6bd4427 --- /dev/null +++ b/subgraphs/v2-vault/abis/RateProviders.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [], + "name": "getRateProviders", + "outputs": [ + { + "internalType": "contract IRateProvider[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/subgraphs/v2-vault/abis/Vault.json b/subgraphs/v2-vault/abis/Vault.json new file mode 100644 index 0000000..15b724d --- /dev/null +++ b/subgraphs/v2-vault/abis/Vault.json @@ -0,0 +1,1179 @@ +[ + { + "inputs": [ + { + "internalType": "contract IAuthorizer", + "name": "authorizer", + "type": "address" + }, + { + "internalType": "contract IWETH", + "name": "weth", + "type": "address" + }, + { + "internalType": "uint256", + "name": "pauseWindowDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodDuration", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IAuthorizer", + "name": "newAuthorizer", + "type": "address" + } + ], + "name": "AuthorizerChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ExternalBalanceTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IFlashLoanRecipient", + "name": "recipient", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + } + ], + "name": "FlashLoan", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "int256", + "name": "delta", + "type": "int256" + } + ], + "name": "InternalBalanceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "PausedStateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "liquidityProvider", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "int256[]", + "name": "deltas", + "type": "int256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "protocolFeeAmounts", + "type": "uint256[]" + } + ], + "name": "PoolBalanceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "assetManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "int256", + "name": "cashDelta", + "type": "int256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "managedDelta", + "type": "int256" + } + ], + "name": "PoolBalanceManaged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "poolAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum IVault.PoolSpecialization", + "name": "specialization", + "type": "uint8" + } + ], + "name": "PoolRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "relayer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "RelayerApprovalChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Swap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "TokensDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "assetManagers", + "type": "address[]" + } + ], + "name": "TokensRegistered", + "type": "event" + }, + { + "inputs": [], + "name": "WETH", + "outputs": [ + { + "internalType": "contract IWETH", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IVault.SwapKind", + "name": "kind", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "assetInIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "assetOutIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "internalType": "struct IVault.BatchSwapStep[]", + "name": "swaps", + "type": "tuple[]" + }, + { + "internalType": "contract IAsset[]", + "name": "assets", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bool", + "name": "fromInternalBalance", + "type": "bool" + }, + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bool", + "name": "toInternalBalance", + "type": "bool" + } + ], + "internalType": "struct IVault.FundManagement", + "name": "funds", + "type": "tuple" + }, + { + "internalType": "int256[]", + "name": "limits", + "type": "int256[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "batchSwap", + "outputs": [ + { + "internalType": "int256[]", + "name": "assetDeltas", + "type": "int256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "deregisterTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "components": [ + { + "internalType": "contract IAsset[]", + "name": "assets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "minAmountsOut", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "toInternalBalance", + "type": "bool" + } + ], + "internalType": "struct IVault.ExitPoolRequest", + "name": "request", + "type": "tuple" + } + ], + "name": "exitPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IFlashLoanRecipient", + "name": "recipient", + "type": "address" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "name": "flashLoan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDomainSeparator", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "getInternalBalance", + "outputs": [ + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getNextNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPausedState", + "outputs": [ + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "pauseWindowEndTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "bufferPeriodEndTime", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + } + ], + "name": "getPool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "enum IVault.PoolSpecialization", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + } + ], + "name": "getPoolTokenInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "managed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + }, + { + "internalType": "address", + "name": "assetManager", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + } + ], + "name": "getPoolTokens", + "outputs": [ + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "balances", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "lastChangeBlock", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProtocolFeesCollector", + "outputs": [ + { + "internalType": "contract ProtocolFeesCollector", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "relayer", + "type": "address" + } + ], + "name": "hasApprovedRelayer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "components": [ + { + "internalType": "contract IAsset[]", + "name": "assets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "maxAmountsIn", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "fromInternalBalance", + "type": "bool" + } + ], + "internalType": "struct IVault.JoinPoolRequest", + "name": "request", + "type": "tuple" + } + ], + "name": "joinPool", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum IVault.PoolBalanceOpKind", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct IVault.PoolBalanceOp[]", + "name": "ops", + "type": "tuple[]" + } + ], + "name": "managePoolBalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum IVault.UserBalanceOpKind", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "contract IAsset", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "internalType": "struct IVault.UserBalanceOp[]", + "name": "ops", + "type": "tuple[]" + } + ], + "name": "manageUserBalance", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IVault.SwapKind", + "name": "kind", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "assetInIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "assetOutIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "internalType": "struct IVault.BatchSwapStep[]", + "name": "swaps", + "type": "tuple[]" + }, + { + "internalType": "contract IAsset[]", + "name": "assets", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bool", + "name": "fromInternalBalance", + "type": "bool" + }, + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bool", + "name": "toInternalBalance", + "type": "bool" + } + ], + "internalType": "struct IVault.FundManagement", + "name": "funds", + "type": "tuple" + } + ], + "name": "queryBatchSwap", + "outputs": [ + { + "internalType": "int256[]", + "name": "", + "type": "int256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IVault.PoolSpecialization", + "name": "specialization", + "type": "uint8" + } + ], + "name": "registerPool", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "assetManagers", + "type": "address[]" + } + ], + "name": "registerTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IAuthorizer", + "name": "newAuthorizer", + "type": "address" + } + ], + "name": "setAuthorizer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "setPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "relayer", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setRelayerApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "enum IVault.SwapKind", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "contract IAsset", + "name": "assetIn", + "type": "address" + }, + { + "internalType": "contract IAsset", + "name": "assetOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "internalType": "struct IVault.SingleSwap", + "name": "singleSwap", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bool", + "name": "fromInternalBalance", + "type": "bool" + }, + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bool", + "name": "toInternalBalance", + "type": "bool" + } + ], + "internalType": "struct IVault.FundManagement", + "name": "funds", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swap", + "outputs": [ + { + "internalType": "uint256", + "name": "amountCalculated", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] \ No newline at end of file diff --git a/subgraphs/v2-vault/package.json b/subgraphs/v2-vault/package.json new file mode 100644 index 0000000..cac4c30 --- /dev/null +++ b/subgraphs/v2-vault/package.json @@ -0,0 +1,17 @@ +{ + "name": "@subgraphs/v2-vault", + "private": true, + "scripts": { + "codegen": "graph codegen --output-dir src/types/", + "deploy": "graph deploy", + "build": "graph build", + "test": "graph test" + }, + "dependencies": { + "@graphprotocol/graph-cli": "0.66.0", + "@graphprotocol/graph-ts": "0.32.0" + }, + "devDependencies": { + "matchstick-as": "0.5.0" + } +} diff --git a/subgraphs/v2-vault/schema.graphql b/subgraphs/v2-vault/schema.graphql new file mode 100644 index 0000000..e9c4f2c --- /dev/null +++ b/subgraphs/v2-vault/schema.graphql @@ -0,0 +1,229 @@ +type Vault @entity { + "Unique identifier for the Vault" + id: Bytes! + "Address of the authorizer" + authorizer: Bytes! + "Address of the protocol fee collector" + protocolFeesCollector: Bytes! + "Indicates whether the Vault is currently paused" + isPaused: Boolean! + "Protocol swap fee percentage" + protocolSwapFee: BigDecimal! + "Protocol yield fee percentage" + protocolYieldFee: BigDecimal! + "Protocol flash loan fee percentage" + protocolFlashLoanFee: BigDecimal! + "Pools associated with this Vault" + pools: [Pool!] @derivedFrom(field: "vault") +} + +type Pool @entity { + "Unique identifier for the Pool" + id: Bytes! + "The Vault this Pool belongs to" + vault: Vault! + "Address of the factory that created this Pool" + factory: Bytes! + "Address of the Pool" + address: Bytes! + "Name of the Pool" + name: String! + "Symbol of the Pool" + symbol: String! + "Swap fee percentage for this Pool" + swapFee: BigDecimal! + "Total shares of the Pool" + totalShares: BigDecimal! + "Address of the pause manager for this Pool" + pauseManager: Bytes! + "Timestamp when the pause window ends" + pauseWindowEndTime: BigInt! + "Block number when the Pool was created" + blockNumber: BigInt! + "Timestamp of the block when the Pool was created" + blockTimestamp: BigInt! + "Hash of the transaction that created the Pool" + transactionHash: Bytes! + "Indicates whether the Pool has been initialized" + isInitialized: Boolean! + + "Total number of swaps performed in this Pool" + swapsCount: BigInt! + "Number of unique holders of this Pool's tokens" + holdersCount: BigInt! + + "Tokens in this Pool" + tokens: [PoolToken!]! @derivedFrom(field: "pool") + "Rate providers associated with this Pool" + rateProviders: [RateProvider!]! @derivedFrom(field: "pool") + + "Snapshots of this Pool's state over time" + snapshots: [PoolSnapshot!]! @derivedFrom(field: "pool") +} + +type PoolToken @entity { + "Unique identifier for the PoolToken" + id: Bytes! + "The Pool this token belongs to" + pool: Pool! + "Index of this token in the Pool" + index: Int! + "Name of the token" + name: String! + "Symbol of the token" + symbol: String! + "Number of decimal places for the token" + decimals: Int! + "Address of the token" + address: Bytes! + "Current balance of this token in the Pool" + balance: BigDecimal! + "Total volume of this token traded in the Pool" + volume: BigDecimal! + "Nested Pool associated with this token, if any" + nestedPool: Pool + "Current price rate for this token" + priceRate: BigDecimal! + "Scaling factor for this token" + scalingFactor: BigInt! + "Total protocol fees collected for this token" + totalProtocolFee: BigDecimal! + "Total protocol swap fees collected for this token" + totalProtocolSwapFee: BigDecimal! + "Total protocol yield fees collected for this token" + totalProtocolYieldFee: BigDecimal! + "Indicates whether this token pays yield fees" + paysYieldFees: Boolean! +} + +type Token @entity { + "Unique identifier for the Token" + id: Bytes! + "Name of the token" + name: String! + "Symbol of the token" + symbol: String! + "Number of decimal places for the token" + decimals: Int! + "Address of the token" + address: Bytes! +} + +type RateProvider @entity { + "Unique identifier for the RateProvider" + id: Bytes! + "The Pool this RateProvider is associated with" + pool: Pool! + "The token this RateProvider is for" + token: PoolToken! + "Address of the RateProvider" + address: Bytes! +} + +type Swap @entity(immutable: true) { + "Unique identifier for the Swap" + id: Bytes! + "Address of the Pool where the swap occurred" + pool: Bytes! + "Address of the token being swapped in" + tokenIn: Bytes! + "Symbol of the token being swapped in" + tokenInSymbol: String! + "Symbol of the token being swapped out" + tokenOutSymbol: String! + "Amount of tokens swapped out" + tokenAmountOut: BigDecimal! + "Address of the token being swapped out" + tokenOut: Bytes! + "Amount of tokens swapped in" + tokenAmountIn: BigDecimal! + "Address of the token used for swap fees" + swapFeeToken: Bytes! + "Amount of swap fees" + swapFeeAmount: BigDecimal! + "User who performed the swap" + user: User! + "Block number when the swap occurred" + blockNumber: BigInt! + "Timestamp of the block when the swap occurred" + blockTimestamp: BigInt! + "Hash of the transaction containing the swap" + transactionHash: Bytes! + "Log index of the swap event in the transaction" + logIndex: BigInt! +} + +enum InvestType { + Add + Remove +} + +type AddRemove @entity(immutable: true) { + "Unique identifier for the AddRemove event" + id: Bytes! + "Type of investment (Add or Remove)" + type: InvestType! + "Address of the sender" + sender: Bytes! + "Amounts of tokens added or removed" + amounts: [BigDecimal!]! + "The Pool where liquidity was added or removed" + pool: Pool! + "User who performed the add or remove action" + user: User! + "Block number when the event occurred" + blockNumber: BigInt! + "Timestamp of the block when the event occurred" + blockTimestamp: BigInt! + "Hash of the transaction containing the event" + transactionHash: Bytes! + "Log index of the event in the transaction" + logIndex: BigInt! +} + +type PoolShare @entity { + "Unique identifier for the PoolShare" + id: ID! + "The Pool this share is for" + pool: Pool! + "The user who owns this share" + user: User! + "Balance of this share" + balance: BigDecimal! +} + +type PoolSnapshot @entity { + "Unique identifier for the PoolSnapshot" + id: ID! + "The Pool this snapshot is for" + pool: Pool! + "Timestamp when this snapshot was taken" + timestamp: Int! + "Total shares of the Pool at the time of the snapshot" + totalShares: BigDecimal! + "Number of swaps performed in the Pool at the time of the snapshot" + swapsCount: BigInt! + "Number of unique holders of the Pool's tokens at the time of the snapshot" + holdersCount: BigInt! + "Balances of each token in the Pool at the time of the snapshot" + balances: [BigDecimal!]! + "Total swap fees collected for each token at the time of the snapshot" + totalSwapFees: [BigDecimal!]! + "Total swap volumes for each token at the time of the snapshot" + totalSwapVolumes: [BigDecimal!]! + "Total protocol swap fees collected for each token at the time of the snapshot" + totalProtocolSwapFees: [BigDecimal!]! + "Total protocol yield fees collected for each token at the time of the snapshot" + totalProtocolYieldFees: [BigDecimal!]! +} + +type User @entity { + "Unique identifier for the User (typically their address)" + id: Bytes! + "Swaps performed by this user" + swaps: [Swap!] @derivedFrom(field: "user") + "Pool shares owned by this user" + shares: [PoolShare!] @derivedFrom(field: "user") + "Add/Remove liquidity events performed by this user" + addRemoves: [AddRemove!] @derivedFrom(field: "user") +} diff --git a/subgraphs/v2-vault/src/helpers/constants.ts b/subgraphs/v2-vault/src/helpers/constants.ts new file mode 100644 index 0000000..5056e8c --- /dev/null +++ b/subgraphs/v2-vault/src/helpers/constants.ts @@ -0,0 +1,48 @@ +import { + BigDecimal, + BigInt, + Address, + dataSource, +} from "@graphprotocol/graph-ts"; + +export const ZERO_BI = BigInt.fromI32(0); +export const ONE_BI = BigInt.fromI32(1); +export const ZERO_BD = BigDecimal.fromString("0"); +export const ONE_BD = BigDecimal.fromString("1"); + +export const ZERO_ADDRESS = Address.fromString( + "0x0000000000000000000000000000000000000000" +); + +class AddressByNetwork { + public canonical: string; + public custom: string; + public fantom: string; +} + +let network: string = dataSource.network(); + +// this list should be updated only if vault is deployed on a new chain +// with an address different than the standard vanity address +// in that case, AddressByNetwork and forNetwork must be updated accordingly +// with a new entry for the new network - folowwing subgraph slugs +let vaultAddressByNetwork: AddressByNetwork = { + canonical: "0xBA12222222228d8Ba445958a75a0704d566BF2C8", + custom: "0x0000000000000000000000000000000000000000", + fantom: "0x20dd72Ed959b6147912C2e529F0a0C651c33c9ce", +}; + +function forNetwork( + addressByNetwork: AddressByNetwork, + network: string +): Address { + if (network == "custom") { + return Address.fromString(addressByNetwork.custom); + } else if (network == "fantom") { + return Address.fromString(addressByNetwork.fantom); + } else { + return Address.fromString(addressByNetwork.canonical); + } +} + +export let VAULT_ADDRESS = forNetwork(vaultAddressByNetwork, network); diff --git a/subgraphs/v2-vault/src/helpers/entities.ts b/subgraphs/v2-vault/src/helpers/entities.ts new file mode 100644 index 0000000..bd41f09 --- /dev/null +++ b/subgraphs/v2-vault/src/helpers/entities.ts @@ -0,0 +1,220 @@ +import { Address, BigDecimal, BigInt, Bytes } from "@graphprotocol/graph-ts"; +import { + Pool, + PoolSnapshot, + PoolToken, + RateProvider, + Token, + User, + Vault, +} from "../types/schema"; +import { PoolShare } from "../types/schema"; +import { ERC20 } from "../types/Vault/ERC20"; +import { Vault as VaultContract } from "../types/Vault/Vault"; +import { ONE_BD, ZERO_BD } from "./constants"; +import { ProtocolFeeCollector } from "../types/ProtocolFeeCollector/ProtocolFeeCollector"; +import { scaleDown } from "./misc"; + +const DAY = 24 * 60 * 60; + +export function getVault(vaultAddress: Bytes): Vault { + let vault: Vault | null = Vault.load(vaultAddress); + if (vault != null) return vault; + + let vaultContract = VaultContract.bind(changetype
(vaultAddress)); + let feeCollector = vaultContract.getProtocolFeesCollector(); + let authorizer = vaultContract.getAuthorizer(); + + let feeCollectorContract = ProtocolFeeCollector.bind(feeCollector); + let protocolSwapFee = feeCollectorContract.getSwapFeePercentage(); + let protocolFlashLoanFee = feeCollectorContract.getFlashLoanFeePercentage(); + + vault = new Vault(vaultAddress); + vault.isPaused = false; + vault.authorizer = authorizer; + vault.protocolFeesCollector = feeCollector; + vault.protocolSwapFee = scaleDown(protocolSwapFee, 18); + vault.protocolYieldFee = scaleDown(protocolSwapFee, 18); + vault.protocolFlashLoanFee = scaleDown(protocolFlashLoanFee, 18); + vault.save(); + + return vault; +} + +export function getPoolShareId( + poolAddress: Address, + userAddress: Address +): string { + return poolAddress.toHex().concat("-").concat(userAddress.toHex()); +} + +export function getPoolShare( + poolAddress: Address, + userAddress: Address +): PoolShare { + let poolShareId = getPoolShareId(poolAddress, userAddress); + let poolShare = PoolShare.load(poolShareId); + + if (!poolShare) { + poolShare = createPoolShare(poolAddress, userAddress); + } + + return poolShare; +} + +export function createPoolToken( + poolAddress: Address, + tokenAddress: Address, + paysYieldFees: boolean, + index: i32 +): void { + let poolTokenId = poolAddress.concat(tokenAddress); + let poolToken = PoolToken.load(poolTokenId); + + if (!poolToken) { + poolToken = new PoolToken(poolTokenId); + } + + let nestedPool = Pool.load(tokenAddress); + + let token = getToken(tokenAddress); + + poolToken.name = token.name; + poolToken.symbol = token.symbol; + poolToken.decimals = token.decimals; + + let decimalDiff = 18 - poolToken.decimals; + poolToken.scalingFactor = BigInt.fromI32(10).pow(u8(decimalDiff)); + + poolToken.pool = poolAddress; + poolToken.address = tokenAddress; + poolToken.index = index; + poolToken.priceRate = ONE_BD; // TODO: remove to avoid confusion + poolToken.balance = ZERO_BD; + poolToken.volume = ZERO_BD; + poolToken.totalProtocolFee = ZERO_BD; + poolToken.totalProtocolSwapFee = ZERO_BD; + poolToken.totalProtocolYieldFee = ZERO_BD; + poolToken.nestedPool = nestedPool ? nestedPool.id : null; + poolToken.paysYieldFees = paysYieldFees; + poolToken.save(); +} + +export function createRateProvider( + poolAddress: Address, + tokenAddress: Address, + rateProviderAddress: Address +): void { + let rateProviderId = poolAddress + .concat(tokenAddress) + .concat(rateProviderAddress); + let rateProvider = RateProvider.load(rateProviderId); + + if (!rateProvider) { + rateProvider = new RateProvider(rateProviderId); + } + + rateProvider.pool = poolAddress; + rateProvider.address = rateProviderAddress; + rateProvider.token = poolAddress.concat(tokenAddress); + rateProvider.save(); +} + +export function createPoolSnapshot(pool: Pool, timestamp: i32): void { + let poolAddress = pool.id; + let dayTimestamp = timestamp - (timestamp % DAY); + + let snapshotId = poolAddress.toHex() + "-" + dayTimestamp.toString(); + let snapshot = PoolSnapshot.load(snapshotId); + + if (!snapshot) { + snapshot = new PoolSnapshot(snapshotId); + } + + let poolTokens = pool.tokens.load(); + let balances = new Array(poolTokens.length); + let totalSwapFees = new Array(poolTokens.length); + let totalSwapVolumes = new Array(poolTokens.length); + let totalProtocolSwapFees = new Array(poolTokens.length); + let totalProtocolYieldFees = new Array(poolTokens.length); + for (let i = 0; i < poolTokens.length; i++) { + totalSwapVolumes[i] = poolTokens[i].volume; + balances[i] = poolTokens[i].balance; + totalSwapFees[i] = poolTokens[i].totalProtocolSwapFee; + totalProtocolSwapFees[i] = poolTokens[i].totalProtocolSwapFee; + totalProtocolYieldFees[i] = poolTokens[i].totalProtocolYieldFee; + } + + snapshot.pool = poolAddress; + snapshot.balances = balances; + snapshot.timestamp = dayTimestamp; + snapshot.swapsCount = pool.swapsCount; + snapshot.totalShares = pool.totalShares; + snapshot.holdersCount = pool.holdersCount; + snapshot.totalSwapFees = totalSwapFees; + snapshot.totalSwapVolumes = totalSwapVolumes; + snapshot.totalProtocolSwapFees = totalProtocolSwapFees; + snapshot.totalProtocolYieldFees = totalProtocolYieldFees; + snapshot.save(); +} + +export function loadPoolToken( + poolAddress: Address, + tokenAddress: Address +): PoolToken { + let poolTokenId = poolAddress.concat(tokenAddress); + let poolToken = PoolToken.load(poolTokenId) as PoolToken; + + return poolToken; +} + +export function createUser(userAddress: Address): void { + let user = User.load(userAddress); + + if (!user) { + user = new User(userAddress); + user.save(); + } +} + +export function createToken(tokenAddress: Address): void { + let tokenContract = ERC20.bind(tokenAddress); + + let nameCall = tokenContract.try_name(); + let symbolCall = tokenContract.try_symbol(); + let decimalsCall = tokenContract.try_decimals(); + + let token = new Token(tokenAddress); + token.name = nameCall.reverted ? "" : nameCall.value; + token.symbol = symbolCall.reverted ? "" : symbolCall.value; + token.decimals = decimalsCall.reverted ? 0 : decimalsCall.value; + token.address = tokenAddress; + token.save(); +} + +export function getToken(tokenAddress: Address): Token { + let token = Token.load(tokenAddress); + + if (!token) { + createToken(tokenAddress); + token = Token.load(tokenAddress); + } + + return token as Token; +} + +export function createPoolShare( + poolAddress: Address, + userAddress: Address +): PoolShare { + createUser(userAddress); + + let poolShareId = getPoolShareId(poolAddress, userAddress); + let poolShare = new PoolShare(poolShareId); + poolShare.user = userAddress; + poolShare.pool = poolAddress; + poolShare.balance = ZERO_BD; + poolShare.save(); + + return poolShare; +} diff --git a/subgraphs/v2-vault/src/helpers/misc.ts b/subgraphs/v2-vault/src/helpers/misc.ts new file mode 100644 index 0000000..2abbedd --- /dev/null +++ b/subgraphs/v2-vault/src/helpers/misc.ts @@ -0,0 +1,33 @@ +import { + Address, + BigDecimal, + BigInt, + ByteArray, + Bytes, +} from "@graphprotocol/graph-ts"; + +export function tokenToDecimal(amount: BigInt, decimals: i32): BigDecimal { + let scale = BigInt.fromI32(10) + .pow(decimals as u8) + .toBigDecimal(); + return amount.toBigDecimal().div(scale); +} + +export function scaleDown(num: BigInt, decimals: i32): BigDecimal { + return num.divDecimal(BigInt.fromI32(10).pow(u8(decimals)).toBigDecimal()); +} + +export function scaleUp(num: BigDecimal, decimals: i32): BigInt { + return BigInt.fromString( + num + .truncate(decimals) + .times(BigInt.fromI32(10).pow(u8(decimals)).toBigDecimal()) + .toString() + ); +} + +export function getPoolAddress(poolId: Bytes): Address { + return changetype
( + Address.fromHexString(poolId.toHexString().slice(0, 42)) + ); +} diff --git a/subgraphs/v2-vault/src/mappings/pool.ts b/subgraphs/v2-vault/src/mappings/pool.ts new file mode 100644 index 0000000..d8fdffc --- /dev/null +++ b/subgraphs/v2-vault/src/mappings/pool.ts @@ -0,0 +1,116 @@ +import { BigInt } from "@graphprotocol/graph-ts"; +import { SwapFeePercentageChanged } from "../types/templates/WeightedPool/WeightedPool"; +import { Pool } from "../types/schema"; + +import { tokenToDecimal, scaleDown } from "../helpers/misc"; +import { VAULT_ADDRESS, ZERO_ADDRESS, ZERO_BD } from "../helpers/constants"; +import { Transfer } from "../types/Vault/ERC20"; +import { + createPoolSnapshot, + getPoolShare, + getVault, + loadPoolToken, +} from "../helpers/entities"; + +/************************************ + *********** SWAP FEES ************ + ************************************/ + +export function handleSwapFeePercentageChange( + event: SwapFeePercentageChanged +): void { + let poolAddress = event.address; + + let pool = Pool.load(poolAddress) as Pool; + const newSwapFee = scaleDown(event.params.swapFeePercentage, 18); + pool.swapFee = newSwapFee; + pool.save(); +} + +/************************************ + *********** POOL SHARES ************ + ************************************/ + +export function handleTransfer(event: Transfer): void { + let poolAddress = event.address; + + let isMint = event.params.from == ZERO_ADDRESS; + let isBurn = event.params.to == ZERO_ADDRESS; + + // skip pre-minted BPTs to the Vault + if ( + (isMint && event.params.to == poolAddress) || + (event.params.from == poolAddress && event.params.to == VAULT_ADDRESS) + ) + return; + + let poolShareFrom = getPoolShare(poolAddress, event.params.from); + let poolShareFromBalance = + poolShareFrom == null ? ZERO_BD : poolShareFrom.balance; + + let poolShareTo = getPoolShare(poolAddress, event.params.to); + let poolShareToBalance = poolShareTo == null ? ZERO_BD : poolShareTo.balance; + + let pool = Pool.load(poolAddress) as Pool; + + let BPT_DECIMALS = 18; + + if (isMint) { + poolShareTo.balance = poolShareTo.balance.plus( + tokenToDecimal(event.params.value, BPT_DECIMALS) + ); + poolShareTo.save(); + pool.totalShares = pool.totalShares.plus( + tokenToDecimal(event.params.value, BPT_DECIMALS) + ); + + // Mint of BPTs to ProtocolFeeController means protocol fee collection + let vault = getVault(VAULT_ADDRESS); + + if (poolShareTo.user == vault.protocolFeesCollector) { + let poolToken = loadPoolToken(poolAddress, poolAddress); + let protocolFee = tokenToDecimal(event.params.value, BPT_DECIMALS); + poolToken.totalProtocolFee = poolToken.totalProtocolFee.plus(protocolFee); + + createPoolSnapshot(pool, event.block.timestamp.toI32()); + } + } else if (isBurn) { + poolShareFrom.balance = poolShareFrom.balance.minus( + tokenToDecimal(event.params.value, BPT_DECIMALS) + ); + poolShareFrom.save(); + pool.totalShares = pool.totalShares.minus( + tokenToDecimal(event.params.value, BPT_DECIMALS) + ); + } else { + poolShareTo.balance = poolShareTo.balance.plus( + tokenToDecimal(event.params.value, BPT_DECIMALS) + ); + poolShareTo.save(); + + poolShareFrom.balance = poolShareFrom.balance.minus( + tokenToDecimal(event.params.value, BPT_DECIMALS) + ); + poolShareFrom.save(); + } + + if ( + poolShareTo !== null && + poolShareTo.balance.notEqual(ZERO_BD) && + poolShareToBalance.equals(ZERO_BD) && + poolShareTo.user != VAULT_ADDRESS + ) { + pool.holdersCount = pool.holdersCount.plus(BigInt.fromI32(1)); + } + + if ( + poolShareFrom !== null && + poolShareFrom.balance.equals(ZERO_BD) && + poolShareFromBalance.notEqual(ZERO_BD) && + poolShareFrom.user != VAULT_ADDRESS + ) { + pool.holdersCount = pool.holdersCount.minus(BigInt.fromI32(1)); + } + + pool.save(); +} diff --git a/subgraphs/v2-vault/src/mappings/vault.ts b/subgraphs/v2-vault/src/mappings/vault.ts new file mode 100644 index 0000000..ed67353 --- /dev/null +++ b/subgraphs/v2-vault/src/mappings/vault.ts @@ -0,0 +1,336 @@ +import { BigInt, BigDecimal, log } from "@graphprotocol/graph-ts"; +import { + Swap as SwapEvent, + PoolBalanceChanged, + TokensRegistered, +} from "../types/Vault/Vault"; +import { Pool, Swap, AddRemove } from "../types/schema"; +import { getPoolAddress, scaleDown } from "../helpers/misc"; +import { VAULT_ADDRESS, ZERO_ADDRESS, ZERO_BD } from "../helpers/constants"; +import { ERC20 } from "../types/Vault/ERC20"; +import { + createPoolSnapshot, + createPoolToken, + createRateProvider, + createUser, + getPoolShare, + getToken, + getVault, + loadPoolToken, +} from "../helpers/entities"; +import { ZERO_BI } from "../helpers/constants"; +import { BasePool } from "../types/templates"; +import { + FlashLoanFeePercentageChanged, + SwapFeePercentageChanged, +} from "../types/ProtocolFeeCollector/ProtocolFeeCollector"; +import { PreMintedBPT } from "../types/Vault/PreMintedBPT"; +import { RateProviders } from "../types/Vault/RateProviders"; + +/************************************ + ******* POOLS REGISTRATIONS ******** + ************************************/ + +export function handleTokensRegistered(event: TokensRegistered): void { + let vault = getVault(event.address); + let poolAddress = getPoolAddress(event.params.poolId); + + let pool = new Pool(poolAddress); + pool.vault = vault.id; + pool.address = poolAddress; + pool.factory = ZERO_ADDRESS; // TODO: isPoolFromFactory or remove it + pool.pauseWindowEndTime = ZERO_BI; // TODO: remove or hardcode 1y? + pool.pauseManager = ZERO_ADDRESS; // TODO: should be the owner + pool.totalShares = ZERO_BD; + pool.isInitialized = false; + pool.swapsCount = ZERO_BI; + pool.holdersCount = ZERO_BI; + + let poolContract = ERC20.bind(poolAddress); + let symbolCall = poolContract.try_symbol(); + let nameCall = poolContract.try_name(); + + pool.name = nameCall.reverted ? "" : nameCall.value; + pool.symbol = symbolCall.reverted ? "" : symbolCall.value; + pool.swapFee = ZERO_BD; // TODO: check if event updates this value + + pool.blockNumber = event.block.number; + pool.blockTimestamp = event.block.timestamp; + pool.transactionHash = event.transaction.hash; + + let rateProviderContract = RateProviders.bind(poolAddress); + let rateProviders = rateProviderContract.try_getRateProviders(); + let hasRateProviders = !rateProviders.reverted; + + for (let i: i32 = 0; i < event.params.tokens.length; i++) { + let tokenAddress = event.params.tokens[i]; + createPoolToken(poolAddress, tokenAddress, false, i); + if (!hasRateProviders) continue; + createRateProvider(poolAddress, tokenAddress, rateProviders.value[i]); + } + + pool.save(); + + createPoolSnapshot(pool, event.block.timestamp.toI32()); + + BasePool.create(poolAddress); +} + +/************************************ + ****** DEPOSITS & WITHDRAWALS ****** + ************************************/ + +export function handlePoolBalanceChanged(event: PoolBalanceChanged): void { + let amounts: BigInt[] = event.params.deltas; + + if (amounts.length === 0) { + return; + } + + createUser(event.params.liquidityProvider); + + let total: BigInt = amounts.reduce( + (sum, amount) => sum.plus(amount), + ZERO_BI + ); + if (total.gt(ZERO_BI)) { + handlePoolJoined(event); + } else { + handlePoolExited(event); + } +} + +function handlePoolJoined(event: PoolBalanceChanged): void { + let poolAddress = getPoolAddress(event.params.poolId); + let amounts: BigInt[] = event.params.deltas; + + let transactionHash = event.transaction.hash; + let logIndex = event.logIndex; + + let pool = Pool.load(poolAddress); + if (pool == null) { + log.warning("Pool not found in handlePoolJoined: {} {}", [ + poolAddress.toHex(), + transactionHash.toHex(), + ]); + return; + } + + let poolTokens = pool.tokens.load(); + + if (pool.isInitialized == false) { + let hasPreMintedBPT = false; + for (let i = 0; i < poolTokens.length; i++) { + if (poolTokens[i].address == poolAddress) { + hasPreMintedBPT = true; + break; + } + } + if (hasPreMintedBPT) { + let preMintedBPT = PreMintedBPT.bind(poolAddress); + let totalSupplyCall = preMintedBPT.try_getActualSupply(); + pool.totalShares = totalSupplyCall.reverted + ? ZERO_BD + : scaleDown(totalSupplyCall.value, 18); + } + pool.isInitialized = true; + } + + pool.save(); + + let joinId = transactionHash.concatI32(logIndex.toI32()); + let join = new AddRemove(joinId); + + let joinAmounts = new Array(amounts.length); + + for (let i: i32 = 0; i < poolTokens.length; i++) { + let poolToken = poolTokens[i]; + let joinAmount = scaleDown(event.params.deltas[i], poolToken.decimals); + joinAmounts[i] = joinAmount; + poolToken.balance = poolToken.balance.plus(joinAmount); + let protocolFee = scaleDown( + event.params.protocolFeeAmounts[i], + poolToken.decimals + ); + poolToken.totalProtocolFee = poolToken.totalProtocolFee.plus(protocolFee); + poolToken.save(); + } + + join.type = "Add"; + join.sender = event.params.liquidityProvider; + join.amounts = joinAmounts; + join.pool = poolAddress; + join.user = event.params.liquidityProvider; + join.logIndex = logIndex; + join.blockNumber = event.block.number; + join.blockTimestamp = event.block.timestamp; + join.transactionHash = transactionHash; + join.save(); + + createPoolSnapshot(pool, event.block.timestamp.toI32()); +} + +function handlePoolExited(event: PoolBalanceChanged): void { + let poolAddress = getPoolAddress(event.params.poolId); + let amounts: BigInt[] = event.params.deltas; + + let transactionHash = event.transaction.hash; + let logIndex = event.logIndex; + + let pool = Pool.load(poolAddress); + if (pool == null) { + log.warning("Pool not found in handlePoolJoined: {} {}", [ + poolAddress.toHex(), + transactionHash.toHex(), + ]); + return; + } + + let exitId = transactionHash.concatI32(logIndex.toI32()); + let exit = new AddRemove(exitId); + + let poolTokens = pool.tokens.load(); + let exitAmounts = new Array(amounts.length); + + for (let i: i32 = 0; i < poolTokens.length; i++) { + let poolToken = poolTokens[i]; + let exitAmount = scaleDown( + event.params.deltas[i].neg(), + poolToken.decimals + ); + exitAmounts[i] = exitAmount; + poolToken.balance = poolToken.balance.minus(exitAmount); + let protocolFee = scaleDown( + event.params.protocolFeeAmounts[i], + poolToken.decimals + ); + poolToken.totalProtocolFee = poolToken.totalProtocolFee.plus(protocolFee); + poolToken.save(); + } + + exit.type = "Remove"; + exit.sender = event.params.liquidityProvider; + exit.amounts = exitAmounts; + exit.pool = poolAddress; + exit.user = event.params.liquidityProvider; + exit.logIndex = logIndex; + exit.blockNumber = event.block.number; + exit.blockTimestamp = event.block.timestamp; + exit.transactionHash = transactionHash; + exit.save(); + + createPoolSnapshot(pool, event.block.timestamp.toI32()); +} + +/************************************ + ************** SWAPS *************** + ************************************/ + +export function handleSwap(event: SwapEvent): void { + let poolAddress = getPoolAddress(event.params.poolId); + + let pool = Pool.load(poolAddress); + if (pool == null) { + log.warning("Pool not found in handleSwap: {} {}", [ + poolAddress.toHex(), + event.transaction.hash.toHex(), + ]); + return; + } + + pool.swapsCount = pool.swapsCount.plus(BigInt.fromI32(1)); + pool.save(); + + createUser(event.transaction.from); + + let swap = new Swap(event.transaction.hash.concatI32(event.logIndex.toI32())); + + let tokenIn = getToken(event.params.tokenIn); + let tokenOut = getToken(event.params.tokenOut); + let swapFeeToken = getToken(event.params.tokenOut); // TODO: check if estimation works + + let tokenAmountIn = scaleDown(event.params.amountIn, tokenIn.decimals); + let tokenAmountOut = scaleDown(event.params.amountOut, tokenOut.decimals); + let swapFeeAmount = tokenAmountIn.times(pool.swapFee); + + swap.pool = event.params.poolId; + swap.tokenIn = event.params.tokenIn; + swap.tokenInSymbol = tokenIn.symbol; + swap.tokenAmountIn = tokenAmountIn; + swap.tokenOut = event.params.tokenOut; + swap.tokenOutSymbol = tokenOut.symbol; + swap.tokenAmountOut = tokenAmountOut; + swap.swapFeeToken = swapFeeToken.id; + swap.swapFeeAmount = swapFeeAmount; + swap.user = event.transaction.from; + + swap.logIndex = event.logIndex; + swap.blockNumber = event.block.number; + swap.blockTimestamp = event.block.timestamp; + swap.transactionHash = event.transaction.hash; + + swap.save(); + + let tokenInAddress = event.params.tokenIn; + let tokenOutAddress = event.params.tokenOut; + + if (tokenInAddress == poolAddress) { + pool.totalShares = pool.totalShares.minus(tokenAmountIn); + let vaultPoolShare = getPoolShare(poolAddress, VAULT_ADDRESS); + vaultPoolShare.balance = vaultPoolShare.balance.minus(tokenAmountIn); + vaultPoolShare.save(); + } else if (tokenOutAddress == poolAddress) { + pool.totalShares = pool.totalShares.plus(tokenAmountOut); + let vaultPoolShare = getPoolShare(poolAddress, VAULT_ADDRESS); + vaultPoolShare.balance = vaultPoolShare.balance.plus(tokenAmountOut); + vaultPoolShare.save(); + } + + let poolTokenIn = loadPoolToken(poolAddress, tokenInAddress); + let poolTokenOut = loadPoolToken(poolAddress, tokenOutAddress); + if (poolTokenIn == null || poolTokenOut == null) { + log.warning( + "PoolToken not found in handleSwap: (tokenIn: {}), (tokenOut: {})", + [tokenInAddress.toHexString(), tokenOutAddress.toHexString()] + ); + return; + } + + let vault = getVault(event.address); + + let newInAmount = poolTokenIn.balance.plus(tokenAmountIn); + poolTokenIn.balance = newInAmount; + poolTokenIn.volume = poolTokenIn.volume.plus(tokenAmountIn); + poolTokenIn.totalProtocolSwapFee = poolTokenIn.totalProtocolSwapFee.plus( + swapFeeAmount.times(vault.protocolSwapFee) + ); + poolTokenIn.save(); + + let newOutAmount = poolTokenOut.balance.minus(tokenAmountOut); + poolTokenOut.balance = newOutAmount; + poolTokenOut.volume = poolTokenOut.volume.plus(tokenAmountOut); + poolTokenOut.save(); + + // updateProtocolFeeAmounts(pool); + createPoolSnapshot(pool, event.block.timestamp.toI32()); +} + +export function handleFlashLoanFeePercentageChanged( + event: FlashLoanFeePercentageChanged +): void { + let vault = getVault(event.address); + vault.protocolFlashLoanFee = scaleDown( + event.params.newFlashLoanFeePercentage, + 18 + ); + vault.save(); +} + +export function handleSwapFeePercentageChanged( + event: SwapFeePercentageChanged +): void { + let vault = getVault(event.address); + vault.protocolSwapFee = scaleDown(event.params.newSwapFeePercentage, 18); + vault.protocolYieldFee = scaleDown(event.params.newSwapFeePercentage, 18); + vault.save(); +} diff --git a/subgraphs/vault/tsconfig.json b/subgraphs/v2-vault/tsconfig.json similarity index 100% rename from subgraphs/vault/tsconfig.json rename to subgraphs/v2-vault/tsconfig.json diff --git a/subgraphs/pools/README.md b/subgraphs/v3-pools/README.md similarity index 100% rename from subgraphs/pools/README.md rename to subgraphs/v3-pools/README.md diff --git a/subgraphs/pools/abis/StablePool.json b/subgraphs/v3-pools/abis/StablePool.json similarity index 100% rename from subgraphs/pools/abis/StablePool.json rename to subgraphs/v3-pools/abis/StablePool.json diff --git a/subgraphs/pools/abis/StablePoolFactory.json b/subgraphs/v3-pools/abis/StablePoolFactory.json similarity index 100% rename from subgraphs/pools/abis/StablePoolFactory.json rename to subgraphs/v3-pools/abis/StablePoolFactory.json diff --git a/subgraphs/pools/abis/WeightedPool.json b/subgraphs/v3-pools/abis/WeightedPool.json similarity index 100% rename from subgraphs/pools/abis/WeightedPool.json rename to subgraphs/v3-pools/abis/WeightedPool.json diff --git a/subgraphs/pools/abis/WeightedPoolFactory.json b/subgraphs/v3-pools/abis/WeightedPoolFactory.json similarity index 100% rename from subgraphs/pools/abis/WeightedPoolFactory.json rename to subgraphs/v3-pools/abis/WeightedPoolFactory.json diff --git a/subgraphs/pools/package.json b/subgraphs/v3-pools/package.json similarity index 92% rename from subgraphs/pools/package.json rename to subgraphs/v3-pools/package.json index 627ccff..b767925 100644 --- a/subgraphs/pools/package.json +++ b/subgraphs/v3-pools/package.json @@ -1,5 +1,5 @@ { - "name": "@subgraphs/pools", + "name": "@subgraphs/v3-pools", "private": true, "scripts": { "add-pool": "node scripts/cli.js", diff --git a/subgraphs/pools/schema.graphql b/subgraphs/v3-pools/schema.graphql similarity index 100% rename from subgraphs/pools/schema.graphql rename to subgraphs/v3-pools/schema.graphql diff --git a/subgraphs/pools/scripts/add-factory.js b/subgraphs/v3-pools/scripts/add-factory.js similarity index 100% rename from subgraphs/pools/scripts/add-factory.js rename to subgraphs/v3-pools/scripts/add-factory.js diff --git a/subgraphs/pools/scripts/add-pool.js b/subgraphs/v3-pools/scripts/add-pool.js similarity index 100% rename from subgraphs/pools/scripts/add-pool.js rename to subgraphs/v3-pools/scripts/add-pool.js diff --git a/subgraphs/pools/src/helpers/constants.ts b/subgraphs/v3-pools/src/helpers/constants.ts similarity index 100% rename from subgraphs/pools/src/helpers/constants.ts rename to subgraphs/v3-pools/src/helpers/constants.ts diff --git a/subgraphs/pools/src/helpers/entities.ts b/subgraphs/v3-pools/src/helpers/entities.ts similarity index 100% rename from subgraphs/pools/src/helpers/entities.ts rename to subgraphs/v3-pools/src/helpers/entities.ts diff --git a/subgraphs/pools/src/helpers/misc.ts b/subgraphs/v3-pools/src/helpers/misc.ts similarity index 100% rename from subgraphs/pools/src/helpers/misc.ts rename to subgraphs/v3-pools/src/helpers/misc.ts diff --git a/subgraphs/pools/src/mappings/factories.ts b/subgraphs/v3-pools/src/mappings/factories.ts similarity index 100% rename from subgraphs/pools/src/mappings/factories.ts rename to subgraphs/v3-pools/src/mappings/factories.ts diff --git a/subgraphs/pools/template.yaml b/subgraphs/v3-pools/template.yaml similarity index 100% rename from subgraphs/pools/template.yaml rename to subgraphs/v3-pools/template.yaml diff --git a/subgraphs/v3-pools/tsconfig.json b/subgraphs/v3-pools/tsconfig.json new file mode 100644 index 0000000..4e86672 --- /dev/null +++ b/subgraphs/v3-pools/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@graphprotocol/graph-ts/types/tsconfig.base.json", + "include": ["src", "tests"] +} diff --git a/subgraphs/vault/README.md b/subgraphs/v3-vault/README.md similarity index 100% rename from subgraphs/vault/README.md rename to subgraphs/v3-vault/README.md diff --git a/subgraphs/vault/abis/ERC20.json b/subgraphs/v3-vault/abis/ERC20.json similarity index 100% rename from subgraphs/vault/abis/ERC20.json rename to subgraphs/v3-vault/abis/ERC20.json diff --git a/subgraphs/vault/abis/ERC4626.json b/subgraphs/v3-vault/abis/ERC4626.json similarity index 100% rename from subgraphs/vault/abis/ERC4626.json rename to subgraphs/v3-vault/abis/ERC4626.json diff --git a/subgraphs/v3-vault/abis/ProtocolFeeController.json b/subgraphs/v3-vault/abis/ProtocolFeeController.json new file mode 100644 index 0000000..0b26a4b --- /dev/null +++ b/subgraphs/v3-vault/abis/ProtocolFeeController.json @@ -0,0 +1,781 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "vault_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "AddressInsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "CallerIsNotPoolCreator", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "FeePrecisionTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "PoolCreatorFeePercentageTooHigh", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreatorNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "ProtocolSwapFeePercentageTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "ProtocolYieldFeePercentageTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderIsNotVault", + "type": "error" + }, + { + "inputs": [], + "name": "SenderNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroDivision", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + } + ], + "name": "GlobalProtocolSwapFeePercentageChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "yieldFeePercentage", + "type": "uint256" + } + ], + "name": "GlobalProtocolYieldFeePercentageChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "PoolCreatorFeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "poolCreatorSwapFeePercentage", + "type": "uint256" + } + ], + "name": "PoolCreatorSwapFeePercentageChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "poolCreatorYieldFeePercentage", + "type": "uint256" + } + ], + "name": "PoolCreatorYieldFeePercentageChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ProtocolFeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ProtocolSwapFeeCollected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "swapFeePercentage", + "type": "uint256" + } + ], + "name": "ProtocolSwapFeePercentageChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ProtocolYieldFeeCollected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "yieldFeePercentage", + "type": "uint256" + } + ], + "name": "ProtocolYieldFeePercentageChanged", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "collectAggregateFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "collectAggregateFeesHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "protocolFeePercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "poolCreatorFeePercentage", + "type": "uint256" + } + ], + "name": "computeAggregateFeePercentage", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getActionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { + "internalType": "contract IAuthorizer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGlobalProtocolSwapFeePercentage", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGlobalProtocolYieldFeePercentage", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "getPoolCreatorFeeAmounts", + "outputs": [ + { + "internalType": "uint256[]", + "name": "feeAmounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "getPoolProtocolSwapFeeInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "getPoolProtocolYieldFeeInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "getProtocolFeeAmounts", + "outputs": [ + { + "internalType": "uint256[]", + "name": "feeAmounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "poolCreator", + "type": "address" + }, + { + "internalType": "bool", + "name": "protocolFeeExempt", + "type": "bool" + } + ], + "name": "registerPool", + "outputs": [ + { + "internalType": "uint256", + "name": "aggregateSwapFeePercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "aggregateYieldFeePercentage", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newProtocolSwapFeePercentage", + "type": "uint256" + } + ], + "name": "setGlobalProtocolSwapFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newProtocolYieldFeePercentage", + "type": "uint256" + } + ], + "name": "setGlobalProtocolYieldFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "poolCreatorSwapFeePercentage", + "type": "uint256" + } + ], + "name": "setPoolCreatorSwapFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "poolCreatorYieldFeePercentage", + "type": "uint256" + } + ], + "name": "setPoolCreatorYieldFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newProtocolSwapFeePercentage", + "type": "uint256" + } + ], + "name": "setProtocolSwapFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newProtocolYieldFeePercentage", + "type": "uint256" + } + ], + "name": "setProtocolYieldFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "updateProtocolSwapFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "updateProtocolYieldFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vault", + "outputs": [ + { + "internalType": "contract IVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "withdrawPoolCreatorFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawPoolCreatorFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawProtocolFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/subgraphs/vault/abis/Vault.json b/subgraphs/v3-vault/abis/Vault.json similarity index 88% rename from subgraphs/vault/abis/Vault.json rename to subgraphs/v3-vault/abis/Vault.json index 4ac4e1e..45e7042 100644 --- a/subgraphs/vault/abis/Vault.json +++ b/subgraphs/v3-vault/abis/Vault.json @@ -76,17 +76,17 @@ "inputs": [ { "internalType": "contract IERC20", - "name": "token", + "name": "tokenIn", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "amountIn", "type": "uint256" }, { "internalType": "uint256", - "name": "limit", + "name": "maxAmountIn", "type": "uint256" } ], @@ -97,17 +97,17 @@ "inputs": [ { "internalType": "contract IERC20", - "name": "token", + "name": "tokenOut", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "amountOut", "type": "uint256" }, { "internalType": "uint256", - "name": "limit", + "name": "minAmountOut", "type": "uint256" } ], @@ -148,12 +148,12 @@ "inputs": [ { "internalType": "uint256", - "name": "amount", + "name": "amountIn", "type": "uint256" }, { "internalType": "uint256", - "name": "limit", + "name": "maxAmountIn", "type": "uint256" } ], @@ -164,18 +164,61 @@ "inputs": [ { "internalType": "uint256", - "name": "amount", + "name": "amountOut", "type": "uint256" }, { "internalType": "uint256", - "name": "limit", + "name": "minAmountOut", "type": "uint256" } ], "name": "BptAmountOutBelowMin", "type": "error" }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + } + ], + "name": "BufferAlreadyInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + } + ], + "name": "BufferNotInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "BufferSharesInvalidOwner", + "type": "error" + }, + { + "inputs": [], + "name": "BufferSharesInvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "BufferTotalSupplyTooLow", + "type": "error" + }, { "inputs": [], "name": "CannotReceiveEth", @@ -311,17 +354,17 @@ "inputs": [ { "internalType": "contract IERC20", - "name": "token", + "name": "tokenIn", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "amountIn", "type": "uint256" }, { "internalType": "uint256", - "name": "limit", + "name": "maxAmountIn", "type": "uint256" } ], @@ -332,17 +375,17 @@ "inputs": [ { "internalType": "contract IERC20", - "name": "token", + "name": "tokenOut", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "amountOut", "type": "uint256" }, { "internalType": "uint256", - "name": "limit", + "name": "minAmountOut", "type": "uint256" } ], @@ -416,6 +459,17 @@ "name": "InvalidTokenType", "type": "error" }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + } + ], + "name": "InvalidUnderlyingToken", + "type": "error" + }, { "inputs": [ { @@ -468,6 +522,48 @@ "name": "NotEnoughBufferShares", "type": "error" }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "expectedUnderlyingAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualUnderlyingAmount", + "type": "uint256" + } + ], + "name": "NotEnoughUnderlying", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "expectedWrappedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualWrappedAmount", + "type": "uint256" + } + ], + "name": "NotEnoughWrapped", + "type": "error" + }, { "inputs": [], "name": "NotStaticCall", @@ -480,12 +576,12 @@ }, { "inputs": [], - "name": "OperationNotSupported", + "name": "PauseBufferPeriodDurationTooLarge", "type": "error" }, { "inputs": [], - "name": "PauseBufferPeriodDurationTooLarge", + "name": "PercentageAboveMax", "type": "error" }, { @@ -587,6 +683,17 @@ "name": "PoolPaused", "type": "error" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "PoolTotalSupplyTooLow", + "type": "error" + }, { "inputs": [], "name": "ProtocolFeesExceedTotalCollected", @@ -612,6 +719,17 @@ "name": "RouterNotTrusted", "type": "error" }, + { + "inputs": [ + { + "internalType": "int256", + "name": "value", + "type": "int256" + } + ], + "name": "SafeCastOverflowedIntToUint", + "type": "error" + }, { "inputs": [ { @@ -714,32 +832,11 @@ "name": "TokensMismatch", "type": "error" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "limit", - "type": "uint256" - } - ], - "name": "TotalSupplyTooLow", - "type": "error" - }, { "inputs": [], "name": "TradeAmountTooSmall", "type": "error" }, - { - "inputs": [], - "name": "UserDataNotSupported", - "type": "error" - }, { "inputs": [], "name": "VaultBuffersArePaused", @@ -773,7 +870,7 @@ { "inputs": [ { - "internalType": "address", + "internalType": "contract IERC4626", "name": "wrappedToken", "type": "address" } @@ -789,12 +886,17 @@ { "inputs": [ { - "internalType": "address", + "internalType": "contract IERC4626", "name": "wrappedToken", "type": "address" + }, + { + "internalType": "address", + "name": "underlyingToken", + "type": "address" } ], - "name": "WrongUnderlyingAmount", + "name": "WrongUnderlyingToken", "type": "error" }, { @@ -808,31 +910,47 @@ "type": "error" }, { + "inputs": [], + "name": "ZeroDivision", + "type": "error" + }, + { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "wrappedToken", + "name": "pool", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "aggregateSwapFeePercentage", + "type": "uint256" } ], - "name": "WrongWrappedAmount", - "type": "error" + "name": "AggregateSwapFeePercentageChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "token", + "name": "pool", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "aggregateYieldFeePercentage", + "type": "uint256" } ], - "name": "WrongWrappedTokenAsset", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroDivision", - "type": "error" + "name": "AggregateYieldFeePercentageChanged", + "type": "event" }, { "anonymous": false, @@ -890,20 +1008,33 @@ { "indexed": true, "internalType": "address", - "name": "sharesOwner", + "name": "from", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "amountWrapped", + "name": "burnedShares", "type": "uint256" + } + ], + "name": "BufferSharesBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "amountUnderlying", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" }, { "indexed": false, @@ -912,7 +1043,7 @@ "type": "uint256" } ], - "name": "LiquidityAddedToBuffer", + "name": "BufferSharesMinted", "type": "event" }, { @@ -925,16 +1056,29 @@ "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "sharesOwner", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "amountUnderlying", + "type": "uint256" }, { "indexed": false, "internalType": "uint256", "name": "amountWrapped", "type": "uint256" + } + ], + "name": "LiquidityAddedToBuffer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" }, { "indexed": false, @@ -945,7 +1089,7 @@ { "indexed": false, "internalType": "uint256", - "name": "removedShares", + "name": "amountWrapped", "type": "uint256" } ], @@ -967,11 +1111,23 @@ "name": "liquidityProvider", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, { "indexed": false, "internalType": "int256[]", "name": "deltas", "type": "int256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "swapFeeAmountsRaw", + "type": "uint256[]" } ], "name": "PoolBalanceChanged", @@ -1258,12 +1414,6 @@ "internalType": "uint256", "name": "swapFeeAmount", "type": "uint256" - }, - { - "indexed": false, - "internalType": "contract IERC20", - "name": "swapFeeToken", - "type": "address" } ], "name": "Swap", @@ -1350,6 +1500,19 @@ "name": "Unwrap", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "VaultBuffersPausedStateChanged", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1363,6 +1526,12 @@ "name": "VaultPausedStateChanged", "type": "event" }, + { + "anonymous": false, + "inputs": [], + "name": "VaultQueriesDisabled", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1487,11 +1656,6 @@ "internalType": "uint256", "name": "limitRaw", "type": "uint256" - }, - { - "internalType": "bytes", - "name": "userData", - "type": "bytes" } ], "internalType": "struct BufferWrapOrUnwrapParams", @@ -1736,8 +1900,8 @@ "type": "bytes" } ], - "internalType": "struct SwapParams", - "name": "params", + "internalType": "struct VaultSwapParams", + "name": "vaultSwapParams", "type": "tuple" } ], @@ -1785,4 +1949,4 @@ "stateMutability": "payable", "type": "receive" } -] \ No newline at end of file +] diff --git a/subgraphs/vault/abis/VaultExtension.json b/subgraphs/v3-vault/abis/VaultExtension.json similarity index 91% rename from subgraphs/vault/abis/VaultExtension.json rename to subgraphs/v3-vault/abis/VaultExtension.json index d5c0d9d..e06965c 100644 --- a/subgraphs/vault/abis/VaultExtension.json +++ b/subgraphs/v3-vault/abis/VaultExtension.json @@ -66,17 +66,17 @@ "inputs": [ { "internalType": "contract IERC20", - "name": "token", + "name": "tokenIn", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "amountIn", "type": "uint256" }, { "internalType": "uint256", - "name": "limit", + "name": "maxAmountIn", "type": "uint256" } ], @@ -87,17 +87,17 @@ "inputs": [ { "internalType": "contract IERC20", - "name": "token", + "name": "tokenOut", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "amountOut", "type": "uint256" }, { "internalType": "uint256", - "name": "limit", + "name": "minAmountOut", "type": "uint256" } ], @@ -138,12 +138,12 @@ "inputs": [ { "internalType": "uint256", - "name": "amount", + "name": "amountIn", "type": "uint256" }, { "internalType": "uint256", - "name": "limit", + "name": "maxAmountIn", "type": "uint256" } ], @@ -154,18 +154,61 @@ "inputs": [ { "internalType": "uint256", - "name": "amount", + "name": "amountOut", "type": "uint256" }, { "internalType": "uint256", - "name": "limit", + "name": "minAmountOut", "type": "uint256" } ], "name": "BptAmountOutBelowMin", "type": "error" }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + } + ], + "name": "BufferAlreadyInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + } + ], + "name": "BufferNotInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "BufferSharesInvalidOwner", + "type": "error" + }, + { + "inputs": [], + "name": "BufferSharesInvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "BufferTotalSupplyTooLow", + "type": "error" + }, { "inputs": [], "name": "CannotReceiveEth", @@ -311,17 +354,17 @@ "inputs": [ { "internalType": "contract IERC20", - "name": "token", + "name": "tokenIn", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "amountIn", "type": "uint256" }, { "internalType": "uint256", - "name": "limit", + "name": "maxAmountIn", "type": "uint256" } ], @@ -332,17 +375,17 @@ "inputs": [ { "internalType": "contract IERC20", - "name": "token", + "name": "tokenOut", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "amountOut", "type": "uint256" }, { "internalType": "uint256", - "name": "limit", + "name": "minAmountOut", "type": "uint256" } ], @@ -396,17 +439,6 @@ "name": "InvalidAddLiquidityKind", "type": "error" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "InvalidPercentage", - "type": "error" - }, { "inputs": [], "name": "InvalidRemoveLiquidityKind", @@ -427,6 +459,17 @@ "name": "InvalidTokenType", "type": "error" }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + } + ], + "name": "InvalidUnderlyingToken", + "type": "error" + }, { "inputs": [], "name": "MaxTokens", @@ -442,6 +485,48 @@ "name": "NotEnoughBufferShares", "type": "error" }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "expectedUnderlyingAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualUnderlyingAmount", + "type": "uint256" + } + ], + "name": "NotEnoughUnderlying", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "expectedWrappedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualWrappedAmount", + "type": "uint256" + } + ], + "name": "NotEnoughWrapped", + "type": "error" + }, { "inputs": [], "name": "NotStaticCall", @@ -454,17 +539,17 @@ }, { "inputs": [], - "name": "OperationNotSupported", + "name": "OutOfBounds", "type": "error" }, { "inputs": [], - "name": "OutOfBounds", + "name": "PauseBufferPeriodDurationTooLarge", "type": "error" }, { "inputs": [], - "name": "PauseBufferPeriodDurationTooLarge", + "name": "PercentageAboveMax", "type": "error" }, { @@ -566,6 +651,17 @@ "name": "PoolPaused", "type": "error" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "PoolTotalSupplyTooLow", + "type": "error" + }, { "inputs": [], "name": "ProtocolFeesExceedTotalCollected", @@ -698,32 +794,11 @@ "name": "TokensNotSorted", "type": "error" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "limit", - "type": "uint256" - } - ], - "name": "TotalSupplyTooLow", - "type": "error" - }, { "inputs": [], "name": "TradeAmountTooSmall", "type": "error" }, - { - "inputs": [], - "name": "UserDataNotSupported", - "type": "error" - }, { "inputs": [], "name": "VaultBuffersArePaused", @@ -757,7 +832,7 @@ { "inputs": [ { - "internalType": "address", + "internalType": "contract IERC4626", "name": "wrappedToken", "type": "address" } @@ -773,12 +848,17 @@ { "inputs": [ { - "internalType": "address", + "internalType": "contract IERC4626", "name": "wrappedToken", "type": "address" + }, + { + "internalType": "address", + "name": "underlyingToken", + "type": "address" } ], - "name": "WrongUnderlyingAmount", + "name": "WrongUnderlyingToken", "type": "error" }, { @@ -792,26 +872,42 @@ "type": "error" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "wrappedToken", + "name": "pool", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "aggregateSwapFeePercentage", + "type": "uint256" } ], - "name": "WrongWrappedAmount", - "type": "error" + "name": "AggregateSwapFeePercentageChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "token", + "name": "pool", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "aggregateYieldFeePercentage", + "type": "uint256" } ], - "name": "WrongWrappedTokenAsset", - "type": "error" + "name": "AggregateYieldFeePercentageChanged", + "type": "event" }, { "anonymous": false, @@ -869,20 +965,33 @@ { "indexed": true, "internalType": "address", - "name": "sharesOwner", + "name": "from", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "amountWrapped", + "name": "burnedShares", "type": "uint256" + } + ], + "name": "BufferSharesBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "amountUnderlying", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" }, { "indexed": false, @@ -891,7 +1000,7 @@ "type": "uint256" } ], - "name": "LiquidityAddedToBuffer", + "name": "BufferSharesMinted", "type": "event" }, { @@ -904,16 +1013,29 @@ "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "sharesOwner", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "amountUnderlying", + "type": "uint256" }, { "indexed": false, "internalType": "uint256", "name": "amountWrapped", "type": "uint256" + } + ], + "name": "LiquidityAddedToBuffer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" }, { "indexed": false, @@ -924,7 +1046,7 @@ { "indexed": false, "internalType": "uint256", - "name": "removedShares", + "name": "amountWrapped", "type": "uint256" } ], @@ -946,11 +1068,23 @@ "name": "liquidityProvider", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, { "indexed": false, "internalType": "int256[]", "name": "deltas", "type": "int256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "swapFeeAmountsRaw", + "type": "uint256[]" } ], "name": "PoolBalanceChanged", @@ -1237,12 +1371,6 @@ "internalType": "uint256", "name": "swapFeeAmount", "type": "uint256" - }, - { - "indexed": false, - "internalType": "contract IERC20", - "name": "swapFeeToken", - "type": "address" } ], "name": "Swap", @@ -1329,6 +1457,19 @@ "name": "Unwrap", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "VaultBuffersPausedStateChanged", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1342,6 +1483,12 @@ "name": "VaultPausedStateChanged", "type": "event" }, + { + "anonymous": false, + "inputs": [], + "name": "VaultQueriesDisabled", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1511,11 +1658,6 @@ ], "name": "computeDynamicSwapFeePercentage", "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, { "internalType": "uint256", "name": "dynamicSwapFeePercentage", @@ -2157,6 +2299,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + } + ], + "name": "isERC4626BufferInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -2275,7 +2436,7 @@ "type": "bytes" } ], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { @@ -2288,7 +2449,7 @@ ], "name": "quoteAndRevert", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { @@ -2541,4 +2702,4 @@ "stateMutability": "payable", "type": "receive" } -] \ No newline at end of file +] diff --git a/subgraphs/v3-vault/package.json b/subgraphs/v3-vault/package.json new file mode 100644 index 0000000..290e351 --- /dev/null +++ b/subgraphs/v3-vault/package.json @@ -0,0 +1,17 @@ +{ + "name": "@subgraphs/v3-vault", + "private": true, + "scripts": { + "codegen": "graph codegen --output-dir src/types/", + "deploy": "graph deploy", + "build": "graph build", + "test": "graph test" + }, + "dependencies": { + "@graphprotocol/graph-cli": "0.66.0", + "@graphprotocol/graph-ts": "0.32.0" + }, + "devDependencies": { + "matchstick-as": "0.5.0" + } +} diff --git a/subgraphs/vault/schema.graphql b/subgraphs/v3-vault/schema.graphql similarity index 98% rename from subgraphs/vault/schema.graphql rename to subgraphs/v3-vault/schema.graphql index 0618cb2..e2f40a6 100644 --- a/subgraphs/vault/schema.graphql +++ b/subgraphs/v3-vault/schema.graphql @@ -143,6 +143,8 @@ type PoolToken @entity { nestedPool: Pool "Current price rate for this token" priceRate: BigDecimal! + "Scaling factor for this token" + scalingFactor: BigInt! "Total protocol swap fees collected for this token" totalProtocolSwapFee: BigDecimal! "Total protocol yield fees collected for this token" @@ -222,6 +224,8 @@ type Swap @entity(immutable: true) { swapFeeToken: Bytes! "Amount of swap fees" swapFeeAmount: BigDecimal! + "Swap fee percentage" + swapFeePercentage: BigDecimal! "User who performed the swap" user: User! "Block number when the swap occurred" diff --git a/subgraphs/vault/src/helpers/constants.ts b/subgraphs/v3-vault/src/helpers/constants.ts similarity index 100% rename from subgraphs/vault/src/helpers/constants.ts rename to subgraphs/v3-vault/src/helpers/constants.ts diff --git a/subgraphs/vault/src/helpers/entities.ts b/subgraphs/v3-vault/src/helpers/entities.ts similarity index 98% rename from subgraphs/vault/src/helpers/entities.ts rename to subgraphs/v3-vault/src/helpers/entities.ts index 47f970b..b6b295b 100644 --- a/subgraphs/vault/src/helpers/entities.ts +++ b/subgraphs/v3-vault/src/helpers/entities.ts @@ -14,7 +14,6 @@ import { ONE_BD, ZERO_ADDRESS, ZERO_BD } from "./constants"; import { PoolRegisteredTokenConfigStruct } from "../types/Vault/Vault"; import { ERC20 } from "../types/Vault/ERC20"; import { VaultExtension } from "../types/Vault/VaultExtension"; -import { ProtocolFeeController } from "../types/Vault/ProtocolFeeController"; import { scaleDown } from "./misc"; const DAY = 24 * 60 * 60; @@ -120,6 +119,9 @@ export function createPoolToken( let buffer = Buffer.load(tokenConfig.token); + let decimalDiff = 18 - poolToken.decimals; + poolToken.scalingFactor = BigInt.fromI32(10).pow(u8(decimalDiff)); + poolToken.pool = poolAddress; poolToken.address = tokenConfig.token; poolToken.index = index; diff --git a/subgraphs/vault/src/helpers/misc.ts b/subgraphs/v3-vault/src/helpers/misc.ts similarity index 100% rename from subgraphs/vault/src/helpers/misc.ts rename to subgraphs/v3-vault/src/helpers/misc.ts diff --git a/subgraphs/vault/src/mappings/bpt.ts b/subgraphs/v3-vault/src/mappings/bpt.ts similarity index 100% rename from subgraphs/vault/src/mappings/bpt.ts rename to subgraphs/v3-vault/src/mappings/bpt.ts diff --git a/subgraphs/vault/src/mappings/vault.ts b/subgraphs/v3-vault/src/mappings/vault.ts similarity index 83% rename from subgraphs/vault/src/mappings/vault.ts rename to subgraphs/v3-vault/src/mappings/vault.ts index 223f373..d706f9b 100644 --- a/subgraphs/vault/src/mappings/vault.ts +++ b/subgraphs/v3-vault/src/mappings/vault.ts @@ -1,5 +1,7 @@ -import { BigDecimal, BigInt, log } from "@graphprotocol/graph-ts"; +import { Address, BigDecimal, BigInt, log } from "@graphprotocol/graph-ts"; import { + BufferSharesBurned, + BufferSharesMinted, LiquidityAddedToBuffer, LiquidityRemovedFromBuffer, PoolBalanceChanged, @@ -26,7 +28,7 @@ import { loadPoolToken, updateProtocolFeeAmounts, } from "../helpers/entities"; -import { ZERO_BD, ZERO_BI } from "../helpers/constants"; +import { ZERO_ADDRESS, ZERO_BD, ZERO_BI } from "../helpers/constants"; import { scaleDown } from "../helpers/misc"; import { BPT } from "../types/templates"; import { ERC20 } from "../types/Vault/ERC20"; @@ -145,7 +147,7 @@ export function handlePoolBalanceChanged(event: PoolBalanceChanged): void { let total: BigInt = amounts.reduce( (sum, amount) => sum.plus(amount), - new BigInt(0) + ZERO_BI ); if (total.gt(ZERO_BI)) { handlePoolJoined(event); @@ -259,7 +261,7 @@ export function handleSwap(event: SwapEvent): void { let tokenIn = getToken(event.params.tokenIn); let tokenOut = getToken(event.params.tokenOut); - let swapFeeToken = getToken(event.params.swapFeeToken); + let swapFeeToken = getToken(event.params.tokenIn); let tokenAmountIn = scaleDown(event.params.amountIn, tokenIn.decimals); let tokenAmountOut = scaleDown(event.params.amountOut, tokenOut.decimals); @@ -275,8 +277,9 @@ export function handleSwap(event: SwapEvent): void { swap.tokenOut = event.params.tokenOut; swap.tokenOutSymbol = tokenOut.symbol; swap.tokenAmountOut = tokenAmountOut; - swap.swapFeeToken = event.params.swapFeeToken; swap.swapFeeAmount = swapFeeAmount; + swap.swapFeeToken = event.params.tokenIn; + swap.swapFeePercentage = scaleDown(event.params.swapFeePercentage, 18); swap.user = event.transaction.from; swap.logIndex = event.logIndex; @@ -331,102 +334,114 @@ export function handleSwap(event: SwapEvent): void { ************* BUFFERS ************** ************************************/ +export function getBuffer(wrappedTokenAddress: Address): Buffer { + let buffer = Buffer.load(wrappedTokenAddress); + + if (buffer) return buffer; + + let erc4626Contract = ERC4626.bind(wrappedTokenAddress); + let asset = erc4626Contract.try_asset(); + let underlyingTokenAddress = asset.reverted ? ZERO_ADDRESS : asset.value; + + let wrappedToken = getToken(wrappedTokenAddress); + let underlyingToken = getToken(underlyingTokenAddress); + + buffer = new Buffer(wrappedTokenAddress); + buffer.wrappedToken = wrappedToken.id; + buffer.underlyingToken = underlyingToken.id; + buffer.wrappedBalance = ZERO_BD; + buffer.underlyingBalance = ZERO_BD; + buffer.totalShares = ZERO_BD; + + return buffer; +} + export function handleLiquidityAddedToBuffer( event: LiquidityAddedToBuffer ): void { - let erc4626 = ERC4626.bind(event.params.wrappedToken); - let asset = erc4626.try_asset(); - if (asset.reverted) return; - - let wrappedToken = getToken(event.params.wrappedToken); - let underlyingToken = getToken(asset.value); - - let buffer = Buffer.load(wrappedToken.address); - - if (!buffer) { - buffer = new Buffer(wrappedToken.address); - buffer.wrappedToken = wrappedToken.id; - buffer.underlyingToken = underlyingToken.id; - buffer.wrappedBalance = ZERO_BD; - buffer.underlyingBalance = ZERO_BD; - buffer.totalShares = ZERO_BD; - } + let buffer = getBuffer(event.params.wrappedToken); + + let wrappedToken = getToken(changetype
(buffer.wrappedToken)); + let underlyingToken = getToken(changetype
(buffer.underlyingToken)); - let issuedShares = scaleDown(event.params.issuedShares, 18); let amountWrapped = scaleDown( event.params.amountWrapped, wrappedToken.decimals ); let amountUnderlying = scaleDown( event.params.amountUnderlying, - wrappedToken.decimals + underlyingToken.decimals ); - buffer.totalShares = buffer.totalShares.plus(issuedShares); buffer.wrappedBalance = buffer.wrappedBalance.plus(amountWrapped); buffer.underlyingBalance = buffer.underlyingBalance.plus(amountUnderlying); buffer.save(); - - createUser(event.params.sharesOwner); - - let bufferShareId = wrappedToken.address.concat(event.params.sharesOwner); - let bufferShare = BufferShare.load(bufferShareId); - - if (!bufferShare) { - bufferShare = new BufferShare(bufferShareId); - bufferShare.user = event.params.sharesOwner; - bufferShare.buffer = buffer.id; - bufferShare.balance = ZERO_BD; - } - - bufferShare.balance = bufferShare.balance.plus(issuedShares); - bufferShare.save(); } export function handleLiquidityRemovedFromBuffer( event: LiquidityRemovedFromBuffer ): void { - let wrappedToken = getToken(event.params.wrappedToken); + let buffer = getBuffer(event.params.wrappedToken); - let buffer = Buffer.load(wrappedToken.address); + let wrappedToken = getToken(changetype
(buffer.wrappedToken)); + let underlyingToken = getToken(changetype
(buffer.underlyingToken)); - if (!buffer) { - buffer = new Buffer(wrappedToken.address); - buffer.wrappedToken = wrappedToken.id; - buffer.wrappedBalance = ZERO_BD; - buffer.underlyingBalance = ZERO_BD; - buffer.totalShares = ZERO_BD; - } - - let removedShares = scaleDown(event.params.removedShares, 18); let amountWrapped = scaleDown( event.params.amountWrapped, wrappedToken.decimals ); let amountUnderlying = scaleDown( event.params.amountUnderlying, - wrappedToken.decimals + underlyingToken.decimals ); - buffer.totalShares = buffer.totalShares.minus(removedShares); buffer.wrappedBalance = buffer.wrappedBalance.minus(amountWrapped); buffer.underlyingBalance = buffer.underlyingBalance.minus(amountUnderlying); buffer.save(); +} + +export function handleBufferSharesMinted(event: BufferSharesMinted): void { + createUser(event.params.to); + + let buffer = getBuffer(event.params.wrappedToken); + let issuedShares = scaleDown(event.params.issuedShares, 18); + buffer.totalShares = buffer.totalShares.plus(issuedShares); + buffer.save(); - createUser(event.params.sharesOwner); + let bufferShareId = buffer.id.concat(event.params.to); + let bufferShare = BufferShare.load(bufferShareId); + + if (!bufferShare) { + bufferShare = new BufferShare(bufferShareId); + bufferShare.user = event.params.to; + bufferShare.buffer = buffer.id; + bufferShare.balance = ZERO_BD; + } + + bufferShare.balance = bufferShare.balance.plus(issuedShares); + bufferShare.save(); +} + +export function handleBufferSharesBurned(event: BufferSharesBurned): void { + createUser(event.params.from); + + let buffer = getBuffer(event.params.wrappedToken); + let burnedShares = scaleDown(event.params.burnedShares, 18); + buffer.totalShares = buffer.totalShares.minus(burnedShares); + buffer.save(); - let bufferShareId = wrappedToken.address.concat(event.params.sharesOwner); + let bufferShareId = event.params.wrappedToken.concat(event.params.from); let bufferShare = BufferShare.load(bufferShareId); if (!bufferShare) { bufferShare = new BufferShare(bufferShareId); - bufferShare.user = event.params.sharesOwner; + bufferShare.user = event.params.from; bufferShare.buffer = buffer.id; bufferShare.balance = ZERO_BD; } - bufferShare.balance = bufferShare.balance.minus(removedShares); + bufferShare.balance = bufferShare.balance.minus(burnedShares); bufferShare.save(); } diff --git a/subgraphs/vault/template.yaml b/subgraphs/v3-vault/template.yaml similarity index 82% rename from subgraphs/vault/template.yaml rename to subgraphs/v3-vault/template.yaml index 45011fe..ad9febe 100644 --- a/subgraphs/vault/template.yaml +++ b/subgraphs/v3-vault/template.yaml @@ -4,11 +4,11 @@ schema: dataSources: - kind: ethereum name: Vault - network: {{ network }} + network: { { network } } source: abi: Vault address: "{{ Vault.address }}" - startBlock: {{ Vault.startBlock }} + startBlock: { { Vault.startBlock } } mapping: kind: ethereum/events apiVersion: 0.0.7 @@ -30,19 +30,19 @@ dataSources: eventHandlers: - event: PoolRegistered(indexed address,indexed address,(address,uint8,address,bool)[],uint256,uint32,(address,address,address),(bool,bool,bool,bool,bool,bool,bool,bool,bool,bool,address),(bool,bool,bool,bool)) handler: handlePoolRegistered - - event: PoolBalanceChanged(indexed address,indexed address,int256[]) + - event: PoolBalanceChanged(indexed address,indexed address,uint256,int256[],uint256[]) handler: handlePoolBalanceChanged - - event: Swap(indexed address,indexed address,indexed address,uint256,uint256,uint256,uint256,address) + - event: Swap(indexed address,indexed address,indexed address,uint256,uint256,uint256,uint256) handler: handleSwap - - event: LiquidityAddedToBuffer(indexed address,indexed address,uint256,uint256,uint256) + - event: LiquidityAddedToBuffer(indexed address,uint256,uint256) handler: handleLiquidityAddedToBuffer - - event: LiquidityRemovedFromBuffer(indexed address,indexed address,uint256,uint256,uint256) + - event: LiquidityAddedToBuffer(indexed address,uint256,uint256) handler: handleLiquidityRemovedFromBuffer file: ./src/mappings/vault.ts templates: - kind: ethereum/contract name: BPT - network: {{ network }} + network: { { network } } source: abi: BPT mapping: diff --git a/subgraphs/v3-vault/tsconfig.json b/subgraphs/v3-vault/tsconfig.json new file mode 100644 index 0000000..4e86672 --- /dev/null +++ b/subgraphs/v3-vault/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@graphprotocol/graph-ts/types/tsconfig.base.json", + "include": ["src", "tests"] +} diff --git a/subgraphs/vault/abis/ProtocolFeeController.json b/subgraphs/vault/abis/ProtocolFeeController.json deleted file mode 100644 index ac2e615..0000000 --- a/subgraphs/vault/abis/ProtocolFeeController.json +++ /dev/null @@ -1,695 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract IVault", - "name": "vault_", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "AddressEmptyCode", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "AddressInsufficientBalance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "caller", - "type": "address" - } - ], - "name": "CallerIsNotPoolCreator", - "type": "error" - }, - { - "inputs": [], - "name": "FailedInnerCall", - "type": "error" - }, - { - "inputs": [], - "name": "FeePrecisionTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "PoolCreatorFeePercentageTooHigh", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - } - ], - "name": "PoolCreatorNotRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "ProtocolSwapFeePercentageTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "ProtocolYieldFeePercentageTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrancyGuardReentrantCall", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "SafeERC20FailedOperation", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderIsNotVault", - "type": "error" - }, - { - "inputs": [], - "name": "SenderNotAllowed", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroDivision", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "swapFeePercentage", - "type": "uint256" - } - ], - "name": "GlobalProtocolSwapFeePercentageChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "yieldFeePercentage", - "type": "uint256" - } - ], - "name": "GlobalProtocolYieldFeePercentageChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "poolCreatorSwapFeePercentage", - "type": "uint256" - } - ], - "name": "PoolCreatorSwapFeePercentageChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "poolCreatorYieldFeePercentage", - "type": "uint256" - } - ], - "name": "PoolCreatorYieldFeePercentageChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "indexed": true, - "internalType": "contract IERC20", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ProtocolSwapFeeCollected", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "swapFeePercentage", - "type": "uint256" - } - ], - "name": "ProtocolSwapFeePercentageChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "indexed": true, - "internalType": "contract IERC20", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ProtocolYieldFeeCollected", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "yieldFeePercentage", - "type": "uint256" - } - ], - "name": "ProtocolYieldFeePercentageChanged", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "protocolFeePercentage", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "poolCreatorFeePercentage", - "type": "uint256" - } - ], - "name": "computeAggregateFeePercentage", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "selector", - "type": "bytes4" - } - ], - "name": "getActionId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAuthorizer", - "outputs": [ - { - "internalType": "contract IAuthorizer", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getGlobalProtocolSwapFeePercentage", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getGlobalProtocolYieldFeePercentage", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - } - ], - "name": "getPoolCreatorFeeAmounts", - "outputs": [ - { - "internalType": "uint256[]", - "name": "feeAmounts", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - } - ], - "name": "getPoolProtocolSwapFeeInfo", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - } - ], - "name": "getPoolProtocolYieldFeeInfo", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - } - ], - "name": "getProtocolFeeAmounts", - "outputs": [ - { - "internalType": "uint256[]", - "name": "feeAmounts", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getVault", - "outputs": [ - { - "internalType": "contract IVault", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "swapFeeAmounts", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "yieldFeeAmounts", - "type": "uint256[]" - } - ], - "name": "receiveAggregateFees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "internalType": "address", - "name": "poolCreator", - "type": "address" - }, - { - "internalType": "bool", - "name": "protocolFeeExempt", - "type": "bool" - } - ], - "name": "registerPool", - "outputs": [ - { - "internalType": "uint256", - "name": "aggregateSwapFeePercentage", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "aggregateYieldFeePercentage", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "newProtocolSwapFeePercentage", - "type": "uint256" - } - ], - "name": "setGlobalProtocolSwapFeePercentage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "newProtocolYieldFeePercentage", - "type": "uint256" - } - ], - "name": "setGlobalProtocolYieldFeePercentage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "internalType": "uint256", - "name": "poolCreatorSwapFeePercentage", - "type": "uint256" - } - ], - "name": "setPoolCreatorSwapFeePercentage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "internalType": "uint256", - "name": "poolCreatorYieldFeePercentage", - "type": "uint256" - } - ], - "name": "setPoolCreatorYieldFeePercentage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "internalType": "uint256", - "name": "newProtocolSwapFeePercentage", - "type": "uint256" - } - ], - "name": "setProtocolSwapFeePercentage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "internalType": "uint256", - "name": "newProtocolYieldFeePercentage", - "type": "uint256" - } - ], - "name": "setProtocolYieldFeePercentage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - } - ], - "name": "updateProtocolSwapFeePercentage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - } - ], - "name": "updateProtocolYieldFeePercentage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "vault", - "outputs": [ - { - "internalType": "contract IVault", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - } - ], - "name": "withdrawPoolCreatorFees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawPoolCreatorFees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawProtocolFees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] \ No newline at end of file