From 30eb556b8163708552f5b32ea2d950fd16684a3f Mon Sep 17 00:00:00 2001 From: Facu Spagnuolo Date: Sat, 12 Aug 2023 13:48:59 +0200 Subject: [PATCH] schema: implement deployer handlers --- schema.graphql | 42 ++++++++++++++++++++++ src/Deployer.ts | 79 ++++++++++++++++++++++++++++++++++++++++++ src/SmartVault.ts | 39 +++++++++++++++++++++ src/Task.ts | 15 ++++++++ subgraph.template.yaml | 57 ++++++++++++++++++++++++++++++ 5 files changed, 232 insertions(+) create mode 100644 src/Deployer.ts create mode 100644 src/SmartVault.ts create mode 100644 src/Task.ts diff --git a/schema.graphql b/schema.graphql index 474a1b8..5adc4d7 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1,3 +1,45 @@ +type Environment @entity { + id: ID! + creator: String! + namespace: String! + authorizers: [Authorizer!] @derivedFrom(field: "environment") + priceOracles: [PriceOracle!] @derivedFrom(field: "environment") + smartVaults: [SmartVault!] @derivedFrom(field: "environment") + tasks: [Task!] @derivedFrom(field: "environment") +} + +type SmartVault @entity { + id: ID! + name: String! + registry: String! + implementation: Implementation! + environment: Environment! + authorizer: Authorizer! + priceOracle: PriceOracle! +} + +type Authorizer @entity { + id: ID! + name: String! + implementation: Implementation! + environment: Environment! +} + +type PriceOracle @entity { + id: ID! + name: String! + implementation: Implementation! + environment: Environment! +} + +type Task @entity { + id: ID! + name: String! + implementation: Implementation! + environment: Environment! + smartVault: SmartVault! +} + type Implementation @entity { id: ID! name: String! diff --git a/src/Deployer.ts b/src/Deployer.ts new file mode 100644 index 0000000..5c08e54 --- /dev/null +++ b/src/Deployer.ts @@ -0,0 +1,79 @@ +import { Address, Bytes, crypto, log } from '@graphprotocol/graph-ts' + +import { Authorizer, Environment, PriceOracle, SmartVault, Task } from '../types/schema' +import { AuthorizerDeployed, PriceOracleDeployed, SmartVaultDeployed, TaskDeployed } from '../types/Deployer/Deployer' + +import { getSmartVault } from './Task' +import { loadOrCreateImplementation } from './Registry' +import { getAuthorizer, getPriceOracle, getRegistry } from './SmartVault' + +export function handleAuthorizerDeployed(event: AuthorizerDeployed): void { + log.warning('New authorizer deployed {}', [event.params.instance.toHexString()]) + let implementation = loadOrCreateImplementation(event.params.implementation) + let environment = loadOrCreateEnvironment(event.transaction.from, event.params.namespace) + + let authorizerId = event.params.instance.toHexString() + let authorizer = new Authorizer(authorizerId) + authorizer.name = event.params.name + authorizer.implementation = implementation.id + authorizer.environment = environment.id + authorizer.save() +} + +export function handlePriceOracleDeployed(event: PriceOracleDeployed): void { + log.warning('New price oracle deployed {}', [event.params.instance.toHexString()]) + let implementation = loadOrCreateImplementation(event.params.implementation) + let environment = loadOrCreateEnvironment(event.transaction.from, event.params.namespace) + + let priceOracleId = event.params.instance.toHexString() + let priceOracle = new PriceOracle(priceOracleId) + priceOracle.name = event.params.name + priceOracle.implementation = implementation.id + priceOracle.environment = environment.id + priceOracle.save() +} + +export function handleSmartVaultDeployed(event: SmartVaultDeployed): void { + log.warning('New smart vault deployed {}', [event.params.instance.toHexString()]) + let implementation = loadOrCreateImplementation(event.params.implementation) + let environment = loadOrCreateEnvironment(event.transaction.from, event.params.namespace) + + let smartVaultId = event.params.instance.toHexString() + let smartVault = new SmartVault(smartVaultId) + smartVault.name = event.params.name + smartVault.implementation = implementation.id + smartVault.environment = environment.id + smartVault.registry = getRegistry(event.params.instance).toHexString() + smartVault.authorizer = getAuthorizer(event.params.instance).toHexString() + smartVault.priceOracle = getPriceOracle(event.params.instance).toHexString() + smartVault.save() +} + +export function handleTaskDeployed(event: TaskDeployed): void { + log.warning('New task deployed {}', [event.params.instance.toHexString()]) + let implementation = loadOrCreateImplementation(event.params.implementation) + let environment = loadOrCreateEnvironment(event.transaction.from, event.params.namespace) + + let taskId = event.params.instance.toHexString() + let task = new Task(taskId) + task.name = event.params.name + task.implementation = implementation.id + task.environment = environment.id + task.smartVault = getSmartVault(event.params.instance).toHexString() + task.save() +} + +export function loadOrCreateEnvironment(creator: Address, namespace: String): Environment { + let rawId = Bytes.fromHexString(creator.toHexString() + Bytes.fromUTF8(namespace.toString()).toHexString().slice(2)) + let id = crypto.keccak256(rawId).toHexString() + let environment = Environment.load(id) + + if (environment === null) { + environment = new Environment(id) + environment.creator = creator.toHexString() + environment.namespace = namespace + environment.save() + } + + return environment +} diff --git a/src/SmartVault.ts b/src/SmartVault.ts new file mode 100644 index 0000000..ca0edc2 --- /dev/null +++ b/src/SmartVault.ts @@ -0,0 +1,39 @@ +import { Address, log } from '@graphprotocol/graph-ts' + +import { SmartVault as SmartVaultContract } from '../types/templates/SmartVault/SmartVault' + +export function getRegistry(address: Address): Address { + let smartVaultContract = SmartVaultContract.bind(address) + let registryCall = smartVaultContract.try_registry() + + if (!registryCall.reverted) { + return registryCall.value + } + + log.warning('registry() call reverted for smart vault {}', [address.toHexString()]) + return Address.zero() +} + +export function getAuthorizer(address: Address): Address { + let smartVaultContract = SmartVaultContract.bind(address) + let authorizerCall = smartVaultContract.try_authorizer() + + if (!authorizerCall.reverted) { + return authorizerCall.value + } + + log.warning('authorizer() call reverted for smart vault {}', [address.toHexString()]) + return Address.zero() +} + +export function getPriceOracle(address: Address): Address { + let smartVaultContract = SmartVaultContract.bind(address) + let priceOracleCall = smartVaultContract.try_priceOracle() + + if (!priceOracleCall.reverted) { + return priceOracleCall.value + } + + log.warning('priceOracle() call reverted for smart vault {}', [address.toHexString()]) + return Address.zero() +} \ No newline at end of file diff --git a/src/Task.ts b/src/Task.ts new file mode 100644 index 0000000..47c4db2 --- /dev/null +++ b/src/Task.ts @@ -0,0 +1,15 @@ +import { Address, log } from '@graphprotocol/graph-ts' + +import { Task as TaskContract } from '../types/templates/Task/Task' + +export function getSmartVault(address: Address): Address { + let taskContract = TaskContract.bind(address) + let smartVaultCall = taskContract.try_smartVault() + + if (!smartVaultCall.reverted) { + return smartVaultCall.value + } + + log.warning('smartVault() call reverted for task {}', [address.toHexString()]) + return Address.zero() +} diff --git a/subgraph.template.yaml b/subgraph.template.yaml index ab3acb0..f50021d 100644 --- a/subgraph.template.yaml +++ b/subgraph.template.yaml @@ -26,3 +26,60 @@ dataSources: - event: Deprecated(indexed address) handler: handleDeprecated file: ./src/Registry.ts + - kind: ethereum/contract + name: Deployer + network: {{network}} + source: + address: '{{deployerAddress}}' + abi: Deployer + startBlock: {{blockNumber}} + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + entities: + - Deployer + abis: + - name: Deployer + file: ./node_modules/@mimic-fi/v3-deployer/artifacts/contracts/interfaces/IDeployer.sol/IDeployer.json + eventHandlers: + - event: AuthorizerDeployed(string,string,address,address) + handler: handleAuthorizerDeployed + - event: PriceOracleDeployed(string,string,address,address) + handler: handlePriceOracleDeployed + - event: SmartVaultDeployed(string,string,address,address) + handler: handleSmartVaultDeployed + - event: TaskDeployed(string,string,address,address) + handler: handleTaskDeployed + file: ./src/Deployer.ts +templates: + - kind: ethereum/contract + name: SmartVault + network: {{network}} + source: + abi: SmartVault + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + entities: + - SmartVault + abis: + - name: SmartVault + file: ./node_modules/@mimic-fi/v3-smart-vault/artifacts/contracts/interfaces/ISmartVault.sol/ISmartVault.json + file: ./src/SmartVault.ts + - kind: ethereum/contract + name: Task + network: {{network}} + source: + abi: Task + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + entities: + - Task + abis: + - name: Task + file: ./node_modules/@mimic-fi/v3-tasks/artifacts/contracts/interfaces/ITask.sol/ITask.json + file: ./src/Task.ts