diff --git a/packages/executor/src/services/EventsService/versions/0.0.7.ts b/packages/executor/src/services/EventsService/versions/0.0.7.ts index e65aea40..6c865fd1 100644 --- a/packages/executor/src/services/EventsService/versions/0.0.7.ts +++ b/packages/executor/src/services/EventsService/versions/0.0.7.ts @@ -1,111 +1,22 @@ import { IDbController, Logger } from "@skandha/types/lib"; -import { - AccountDeployedEvent, - SignatureAggregatorChangedEvent, - UserOperationEventEvent, -} from "@skandha/types/lib/contracts/EPv7/core/EntryPoint"; import { MempoolEntryStatus } from "@skandha/types/lib/executor"; import { ReputationService } from "../../ReputationService"; import { MempoolService } from "../../MempoolService"; import { ExecutorEvent, ExecutorEventBus } from "../../SubscriptionService"; import { EntryPoint__factory } from "@skandha/types/lib/contracts/EPv7/factories/core"; -import { GetContractReturnType, Hex, PublicClient, Log, parseAbi } from "viem"; - -type UserOperationEventAbi = { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "bytes32", - name: "userOpHash", - type: "bytes32", - }, - { - indexed: true, - internalType: "address", - name: "sender", - type: "address", - }, - { - indexed: true, - internalType: "address", - name: "paymaster", - type: "address", - }, - { - indexed: false, - internalType: "uint256", - name: "nonce", - type: "uint256", - }, - { - indexed: false, - internalType: "bool", - name: "success", - type: "bool", - }, - { - indexed: false, - internalType: "uint256", - name: "actualGasCost", - type: "uint256", - }, - { - indexed: false, - internalType: "uint256", - name: "actualGasUsed", - type: "uint256", - }, - ], - name: "UserOperationEvent", - type: "event", -}; - -type AccountDeployedEventAbi = { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "bytes32", - name: "userOpHash", - type: "bytes32", - }, - { - indexed: true, - internalType: "address", - name: "sender", - type: "address", - }, - { - indexed: false, - internalType: "address", - name: "factory", - type: "address", - }, - { - indexed: false, - internalType: "address", - name: "paymaster", - type: "address", - }, - ], - name: "AccountDeployed", - type: "event", -}; - -type SignatureAggregatorChangedEventAbi = { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "aggregator", - type: "address", - }, - ], - name: "SignatureAggregatorChanged", - type: "event", -}; +import { GetContractReturnType, Hex, PublicClient, Log, parseAbi, AbiEvent } from "viem"; +import { + ACCOUNT_DEPLOYED_EVENT_HASH, + AccountDeployedAbi, + PrivateEventAbi, + SignatureAggregatorChangedAbi, + USER_OPERATION_EVENT_HASH, + UserOperationEventAbi, +} from '../../../utils/abi-events' +import { isPrivateEventLogWithArgs, unwrapPrivateEvent } from '../../../utils/unwrapPrivateEvent' + +type EventLog = Log +const PrivateEntryPointAbi = [ PrivateEventAbi, ...EntryPoint__factory.abi ] export class EntryPointV7EventsService { private lastBlock: bigint = BigInt(0); @@ -151,8 +62,8 @@ export class EntryPointV7EventsService { } const logs = await publicClient.getLogs({ events: parseAbi([ - 'event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed)', - 'event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster)', + // PrivateEvent: UserOperationEvent, AccountDeployed + 'event PrivateEvent(address[] allowedViewers, bytes32 indexed eventType, bytes payload)', 'event SignatureAggregatorChanged(address indexed aggregator)' ]), address: this.entryPoint, @@ -181,23 +92,17 @@ export class EntryPointV7EventsService { initEventListener(): void { if(!this.disableWatchContractevent) { + // Watching PrivateEvent for: UserOperationEvent and AccountDeployed this.publicClient.watchContractEvent({ - abi: EntryPoint__factory.abi, - eventName: "UserOperationEvent", + abi: PrivateEntryPointAbi, address: this.entryPoint, + eventName: "PrivateEvent", + args: { + eventType: [ACCOUNT_DEPLOYED_EVENT_HASH, USER_OPERATION_EVENT_HASH] + }, onLogs: async (args) => { const ev = args[args.length - 1]; - await this.handleUserOperationEvent(ev); - } - }); - - this.publicClient.watchContractEvent({ - abi: EntryPoint__factory.abi, - address: this.entryPoint, - eventName: "AccountDeployed", - onLogs: async (args) => { - const ev = args[args.length - 1]; - await this.handleAccountDeployedEvent(ev); + await this.handleEvent(ev); } }); @@ -218,10 +123,19 @@ export class EntryPointV7EventsService { } async handleEvent( - ev: Log | - Log | - Log + originalEvent: ( + | EventLog + | EventLog + ) ): Promise { + const ev = originalEvent.eventName === 'PrivateEvent' + ? this.handlePrivateEventUnwrap(originalEvent) + : originalEvent + + if (ev === null) { + return; + } + switch (ev.eventName) { case "UserOperationEvent": await this.handleUserOperationEvent(ev); @@ -235,8 +149,44 @@ export class EntryPointV7EventsService { } } + handlePrivateEventUnwrap( + ev: EventLog + ): ( + | EventLog + | EventLog + ) | null { + if (!isPrivateEventLogWithArgs(ev)) { + this.logger.error("Invalid PrivateEvent: missing required fields"); + return null + } + + const wrappedEventHashToAbi = { + [USER_OPERATION_EVENT_HASH]: UserOperationEventAbi, + [ACCOUNT_DEPLOYED_EVENT_HASH]: AccountDeployedAbi, + } + const abi = wrappedEventHashToAbi[ev.args.eventType] + + // if abi is not on the list, then we do not care about this event + if (!abi) { + return null + } + + try { + // type cast to unwrap EventLog + return unwrapPrivateEvent(abi, ev) as ( + | EventLog + | EventLog + ) + } catch (error) { + this.logger.error( + `Failed to unwrap PrivateEvent for ${abi.name}: ${error instanceof Error ? error.message : JSON.stringify(error)}` + ); + } + return null + } + async handleAggregatorChangedEvent( - ev: Log + ev: EventLog ): Promise { this.eventAggregator = ev.args.aggregator ?? null; this.eventAggregatorTxHash = ev.transactionHash; @@ -248,8 +198,8 @@ export class EntryPointV7EventsService { // aggregator event is sent once per events bundle for all UserOperationEvents in this bundle. // it is not sent at all if the transaction is handleOps getEventAggregator( - ev: Log | - Log + ev: EventLog | + EventLog ): string | null { if (ev.transactionHash !== this.eventAggregatorTxHash) { this.eventAggregator = null; @@ -260,13 +210,13 @@ export class EntryPointV7EventsService { // AccountDeployed event is sent before each UserOperationEvent that deploys a contract. async handleAccountDeployedEvent( - ev: Log + ev: EventLog ): Promise { await this.includedAddress(ev.args.factory ?? null); } async handleUserOperationEvent( - ev: Log + ev: EventLog ): Promise { const entry = await this.mempoolService.getEntryByHash(ev.args.userOpHash!); if (entry) {