From abf57f542c21003e3f83378814b26c784f368cb4 Mon Sep 17 00:00:00 2001 From: Facu Spagnuolo Date: Sat, 12 Aug 2023 21:10:52 +0200 Subject: [PATCH] schema: implement authorizer handlers --- schema.graphql | 17 +++++++++++ src/Authorizer.ts | 68 ++++++++++++++++++++++++++++++++++++++++++ subgraph.template.yaml | 5 ++++ 3 files changed, 90 insertions(+) create mode 100644 src/Authorizer.ts diff --git a/schema.graphql b/schema.graphql index 5adc4d7..87169a2 100644 --- a/schema.graphql +++ b/schema.graphql @@ -23,6 +23,23 @@ type Authorizer @entity { name: String! implementation: Implementation! environment: Environment! + permissions: [Permission!] @derivedFrom(field: "authorizer") +} + +type Permission @entity { + id: ID! + authorizer: Authorizer! + who: String! + where: String! + what: String! + params: [PermissionParam!] @derivedFrom(field: "permission") +} + +type PermissionParam @entity { + id: ID! + permission: Permission! + op: String! + value: String! } type PriceOracle @entity { diff --git a/src/Authorizer.ts b/src/Authorizer.ts new file mode 100644 index 0000000..4937b50 --- /dev/null +++ b/src/Authorizer.ts @@ -0,0 +1,68 @@ +import { Address, Bytes, crypto, log, store } from '@graphprotocol/graph-ts' + +import { Permission, PermissionParam } from '../types/schema' +import { Authorized, Unauthorized, Authorizer as AuthorizerContract } from '../types/templates/Authorizer/Authorizer' + +export function handleAuthorized(event: Authorized): void { + let permissionId = getPermissionId(event.address, event.params.who, event.params.where, event.params.what) + let permission = new Permission(permissionId) + permission.authorizer = event.address.toHexString() + permission.who = event.params.who.toHexString() + permission.where = event.params.where.toHexString() + permission.what = event.params.what.toHexString() + permission.save() + + let authorizerContract = AuthorizerContract.bind(event.address) + let getPermissionParamsCall = authorizerContract.try_getPermissionParams( + event.params.who, + event.params.where, + event.params.what + ) + + if (getPermissionParamsCall.reverted) { + log.warning('getPermissionParams() call reverted for authorizer {}', [event.address.toHexString()]) + return + } + + let params = getPermissionParamsCall.value + for (let i: i32 = 0; i < params.length; i++) { + let paramId = permissionId + '/param/' + i.toString() + let param = new PermissionParam(paramId) + param.op = parseOp(params[i].op) + param.value = params[i].value.toHexString() + param.save() + } +} + +export function handleUnauthorized(event: Unauthorized): void { + let permissionId = getPermissionId(event.address, event.params.who, event.params.where, event.params.what) + let permission = Permission.load(permissionId) + + if (permission != null) { + let params = permission.params.load() + for (let i: i32 = 0; i < params.length; i++) store.remove('PermissionParam', params[i].id) + store.remove('Permission', permissionId) + } +} + +function parseOp(op: i32): string { + if (op == 0) return 'NONE' + if (op == 1) return 'EQ' + if (op == 2) return 'NEQ' + if (op == 3) return 'GT' + if (op == 4) return 'LT' + if (op == 5) return 'GTE' + if (op == 6) return 'LTE' + return 'Unknown' +} + +function getPermissionId(authorizer: Address, who: Address, where: Address, what: Bytes): string { + return crypto.keccak256( + Bytes.fromHexString( + authorizer.toHexString() + + who.toHexString().slice(2) + + where.toHexString().slice(2) + + what.toHexString().slice(2), + ), + ).toHexString() +} diff --git a/subgraph.template.yaml b/subgraph.template.yaml index 6c35025..6c4f392 100644 --- a/subgraph.template.yaml +++ b/subgraph.template.yaml @@ -67,6 +67,11 @@ templates: abis: - name: Authorizer file: ./node_modules/@mimic-fi/v3-authorizer/artifacts/contracts/interfaces/IAuthorizer.sol/IAuthorizer.json + eventHandlers: + - event: Authorized(indexed address,indexed address,indexed bytes4,(uint8,uint248)[]) + handler: handleAuthorized + - event: Unauthorized(indexed address,indexed address,indexed bytes4) + handler: handleUnauthorized file: ./src/Authorizer.ts - kind: ethereum/contract name: SmartVault