From dc02f5b680a531c738d8dd15ba31ec551aff69c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Pr=C3=A9vost?= <998369+prevostc@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:08:31 +0200 Subject: [PATCH] Add support for initializable contract deployed with deployer --- abis/beefy/Initializable.json | 8 +++++ src/common/interaction.ts | 2 -- .../contract-deployer-initializable.ts | 35 +++++++++++++++++++ src/common/mapping/contract-deployer.ts | 20 +++++++---- src/common/utils/token.ts | 7 ++-- subgraph.template.yaml | 20 +++++++++++ 6 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 abis/beefy/Initializable.json create mode 100644 src/common/mapping/contract-deployer-initializable.ts diff --git a/abis/beefy/Initializable.json b/abis/beefy/Initializable.json new file mode 100644 index 0000000..ef2d394 --- /dev/null +++ b/abis/beefy/Initializable.json @@ -0,0 +1,8 @@ +[ + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "uint8", "name": "version", "type": "uint8" }], + "name": "Initialized", + "type": "event" + } +] diff --git a/src/common/interaction.ts b/src/common/interaction.ts index 97a5358..300509b 100644 --- a/src/common/interaction.ts +++ b/src/common/interaction.ts @@ -44,8 +44,6 @@ export function handleProductTransfer(event: TransferEvent): void { function updateAccountBalance(tokenAddress: Bytes, accountAddress: Bytes, amountDiff: BigInt): BalanceDiff { const account = createAccount(accountAddress) const token = getToken(tokenAddress) - token.save() - const balance = getTokenBalance(token, account) const before = balance.amount const after = balance.amount.plus(amountDiff) diff --git a/src/common/mapping/contract-deployer-initializable.ts b/src/common/mapping/contract-deployer-initializable.ts new file mode 100644 index 0000000..15fa534 --- /dev/null +++ b/src/common/mapping/contract-deployer-initializable.ts @@ -0,0 +1,35 @@ +import { BeefyERC20Product as BeefyERC20ProductTemplate } from "../../../generated/templates" +import { Initialized as InitializedEvent } from "../../../generated/ContractDeployer/Initializable" +import { IERC20 as IERC20Contract } from "../../../generated/templates/BeefyERC20Product/IERC20" +import { Address, log } from "@graphprotocol/graph-ts" +import { fetchAndSaveTokenData } from "../utils/token" + +export function handleContractDeployedInitializableInitialized(event: InitializedEvent): void { + const tokenAddress = event.address + + // detect if we are creating an erc20 token + const tokenContract = IERC20Contract.bind(Address.fromBytes(tokenAddress)) + + const tokenDecimalsRes = tokenContract.try_decimals() + if (tokenDecimalsRes.reverted) { + log.info("Contract {} is not an ERC20 token, decimals() reverted", [tokenAddress.toHexString()]) + return + } + + const tokenNameRes = tokenContract.try_name() + if (tokenNameRes.reverted) { + log.info("Contract {} is not an ERC20 token, name() reverted", [tokenAddress.toHexString()]) + return + } + + const tokenSymbolRes = tokenContract.try_symbol() + if (tokenSymbolRes.reverted) { + log.info("Contract {} is not an ERC20 token, symbol() reverted", [tokenAddress.toHexString()]) + return + } + + log.debug("Creating BeefyERC20Product template for {} from contract-deployer", [tokenAddress.toHexString()]) + + fetchAndSaveTokenData(tokenAddress) + BeefyERC20ProductTemplate.create(tokenAddress) +} diff --git a/src/common/mapping/contract-deployer.ts b/src/common/mapping/contract-deployer.ts index 6c3b7d5..a245f1d 100644 --- a/src/common/mapping/contract-deployer.ts +++ b/src/common/mapping/contract-deployer.ts @@ -1,4 +1,7 @@ -import { BeefyERC20Product as BeefyERC20ProductTemplate } from "../../../generated/templates" +import { + BeefyERC20Product as BeefyERC20ProductTemplate, + ContractDeployerInitializable as ContractDeployerInitializableTemplate, +} from "../../../generated/templates" import { ContractDeployed as ContractDeployedEvent } from "../../../generated/ContractDeployer/ContractDeployer" import { IERC20 as IERC20Contract } from "../../../generated/templates/BeefyERC20Product/IERC20" import { fetchAndSaveTokenData } from "../utils/token" @@ -9,27 +12,30 @@ export function handleContractDeployedWithDeployer(event: ContractDeployedEvent) // detect if we are creating an erc20 token const tokenContract = IERC20Contract.bind(Address.fromBytes(address)) - const tokenDecimalsRes = tokenContract.try_decimals() if (tokenDecimalsRes.reverted) { log.info("Contract {} is not an ERC20 token, decimals() reverted", [address.toHexString()]) return } - const tokenNameRes = tokenContract.try_name() if (tokenNameRes.reverted) { log.info("Contract {} is not an ERC20 token, name() reverted", [address.toHexString()]) return } - const tokenSymbolRes = tokenContract.try_symbol() if (tokenSymbolRes.reverted) { log.info("Contract {} is not an ERC20 token, symbol() reverted", [address.toHexString()]) return } - log.debug("Creating BeefyERC20Product template for {} from contract-deployer", [address.toHexString()]) + // if any of the calls return null, this is most likely an initializable contract + if (tokenDecimalsRes.value == null || tokenNameRes.value == null || tokenSymbolRes.value == null) { + log.info("Contract {} is probably innitializable, one of the metadata calls returned null", [address.toHexString()]) - fetchAndSaveTokenData(address) - BeefyERC20ProductTemplate.create(address) + ContractDeployerInitializableTemplate.create(address) + } else { + log.debug("Creating BeefyERC20Product template for {} from contract-deployer", [address.toHexString()]) + fetchAndSaveTokenData(address) + BeefyERC20ProductTemplate.create(address) + } } diff --git a/src/common/utils/token.ts b/src/common/utils/token.ts index a1935ec..6a5e425 100644 --- a/src/common/utils/token.ts +++ b/src/common/utils/token.ts @@ -10,12 +10,11 @@ export function fetchAndSaveTokenData(tokenAddress: Bytes): Token { // if any of these calls revert, we will just use the default values to avoid a subgraph crash const tokenDecimalsRes = tokenContract.try_decimals() - const tokenDecimals = tokenDecimalsRes.reverted ? 18 : tokenDecimalsRes.value - const tokenNameRes = tokenContract.try_name() - const tokenName = tokenNameRes.reverted ? "Unknown" : tokenNameRes.value - const tokenSymbolRes = tokenContract.try_symbol() + + const tokenDecimals = tokenDecimalsRes.reverted ? 18 : tokenDecimalsRes.value + const tokenName = tokenNameRes.reverted ? "Unknown" : tokenNameRes.value const tokenSymbol = tokenSymbolRes.reverted ? "UNKNOWN" : tokenSymbolRes.value const token = getToken(tokenAddress) diff --git a/subgraph.template.yaml b/subgraph.template.yaml index 3d6be8e..c2a6551 100644 --- a/subgraph.template.yaml +++ b/subgraph.template.yaml @@ -196,6 +196,8 @@ dataSources: file: ./abis/beefy/ContractDeployer.json - name: IERC20 file: ./abis/IERC20/IERC20.json + - name: Initializable + file: ./abis/beefy/Initializable.json eventHandlers: - event: ContractDeployed(indexed bytes32,address) handler: handleContractDeployedWithDeployer @@ -268,6 +270,24 @@ templates: handler: handleClassicVaultInitialized {{/beefyClassicVaultFactoryAddress}} + {{#beefyContractDeployerAddress}} + - name: ContractDeployerInitializable + kind: ethereum/contract + network: {{network}} + source: + abi: Initializable + mapping: + kind: ethereum/events + apiVersion: 0.0.7 # 0xgraph's version + language: wasm/assemblyscript + file: ./src/common/mapping/contract-deployer-initializable.ts + entities: *contractDeployerEntities + abis: *contractDeployerAbis + eventHandlers: + - event: Initialized(uint8) + handler: handleContractDeployedInitializableInitialized + {{/beefyContractDeployerAddress}} + - name: BeefyERC20Product kind: ethereum/contract network: {{network}}