diff --git a/schema.graphql b/schema.graphql index 9c80f0e3..1a0c15af 100644 --- a/schema.graphql +++ b/schema.graphql @@ -283,6 +283,7 @@ type GraphAccount @entity { # Transactions / activity feed "Name signal transactions created by this GraphAccount" nameSignalTransactions: [NameSignalTransaction!]! @derivedFrom(field: "signer") + bridgeWithdrawalTransactions: [BridgeWithdrawalTransaction!]! @derivedFrom(field: "signer") # Token Lock Wallets that this account is associated with tokenLockWallets: [TokenLockWallet!]! @@ -1146,6 +1147,33 @@ type SignalTransaction implements Transaction @entity { withdrawalFees: BigInt! } +""" +All relevant data for a bridge withdrawal Transaction in The Graph Network +""" +type BridgeWithdrawalTransaction implements Transaction @entity { + id: ID! + blockNumber: Int! + timestamp: Int! + signer: GraphAccount! + type: TransactionType! + + "On both subgraphs" + txHash: Bytes! + from: Bytes + to: Bytes + """ + transactionIndex is the unique value that allows matching an L2 transaction with its L1 counterpart + - On L1, Arbitrum's Outbox contract emits OutBoxTransactionExecuted event with a transactionIndex property + - On L2, the Graph gateway emits WithdrawalInitiated with the transaction index as l2ToL1Id + """ + transactionIndex: Int! + + "Only on L2 subgraph" + exitNum: Int + amount: BigInt + l1Token: Bytes +} + enum TransactionType { Stake Unstake @@ -1153,6 +1181,7 @@ enum TransactionType { BurnSignal MintNSignal BurnNSignal + BridgeWithdrawal } """ diff --git a/src/mappings/l1Gateway.ts b/src/mappings/l1Gateway.ts index 92343cbc..b0c90c60 100644 --- a/src/mappings/l1Gateway.ts +++ b/src/mappings/l1Gateway.ts @@ -1,5 +1,4 @@ import { DepositInitiated } from '../types/L1GraphTokenGateway/L1GraphTokenGateway' -import { GraphNetwork } from '../types/schema' import { createOrLoadGraphNetwork } from './helpers' export function handleDepositInitiated(event: DepositInitiated): void { diff --git a/src/mappings/l2Gateway.ts b/src/mappings/l2Gateway.ts index 9a9c109a..0669617a 100644 --- a/src/mappings/l2Gateway.ts +++ b/src/mappings/l2Gateway.ts @@ -1,9 +1,30 @@ import { WithdrawalInitiated } from '../types/L2GraphTokenGateway/L2GraphTokenGateway' -import { GraphNetwork } from '../types/schema' import { createOrLoadGraphNetwork } from './helpers' +import { BridgeWithdrawalTransaction } from '../types/schema' export function handleWithdrawalInitiated(event: WithdrawalInitiated): void { let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address) + + // Save the withdrawal transaction + let withdrawalTransaction = new BridgeWithdrawalTransaction( + event.transaction.hash.toHexString().concat('-').concat(event.logIndex.toString()), + ) + + // Note that this only runs on L2, so we can fix block number to the current L1 estimate + withdrawalTransaction.blockNumber = graphNetwork.currentL1BlockNumber!.toI32() + withdrawalTransaction.timestamp = event.block.timestamp.toI32() + withdrawalTransaction.signer = event.params.from.toHexString() + withdrawalTransaction.type = 'BridgeWithdrawal' + withdrawalTransaction.txHash = event.transaction.hash + withdrawalTransaction.from = event.params.from + withdrawalTransaction.to = event.params.to + withdrawalTransaction.transactionIndex = event.params.l2ToL1Id + withdrawalTransaction.exitNum = event.params.exitNum + withdrawalTransaction.amount = event.params.amount + withdrawalTransaction.l1Token = event.params.l1Token + withdrawalTransaction.save() + + // Update total GRT withdrawn graphNetwork.totalGRTWithdrawn = graphNetwork.totalGRTWithdrawn.plus(event.params.amount) graphNetwork.save() }