diff --git a/packages/hardhat-core/src/internal/hardhat-network/provider/provider.ts b/packages/hardhat-core/src/internal/hardhat-network/provider/provider.ts index bce954129a..023abf35af 100644 --- a/packages/hardhat-core/src/internal/hardhat-network/provider/provider.ts +++ b/packages/hardhat-core/src/internal/hardhat-network/provider/provider.ts @@ -370,6 +370,7 @@ export class EdrProviderWrapper const needsTraces = this._node._vm.evm.events.eventNames().length > 0 || + this._node._vm.events.eventNames().length > 0 || this._rawTraceCallbacks.onStep !== undefined || this._rawTraceCallbacks.onAfterMessage !== undefined || this._rawTraceCallbacks.onBeforeMessage !== undefined; @@ -378,7 +379,14 @@ export class EdrProviderWrapper const rawTraces = responseObject.traces; for (const rawTrace of rawTraces) { const trace = rawTrace.trace(); + + // beforeTx event + if (this._node._vm.events.listenerCount("beforeTx") > 0) { + this._node._vm.events.emit("beforeTx"); + } + for (const traceItem of trace) { + // step event if ("pc" in traceItem) { if (this._node._vm.evm.events.listenerCount("step") > 0) { this._node._vm.evm.events.emit( @@ -389,7 +397,9 @@ export class EdrProviderWrapper if (this._rawTraceCallbacks.onStep !== undefined) { await this._rawTraceCallbacks.onStep(traceItem); } - } else if ("executionResult" in traceItem) { + } + // afterMessage event + else if ("executionResult" in traceItem) { if (this._node._vm.evm.events.listenerCount("afterMessage") > 0) { this._node._vm.evm.events.emit( "afterMessage", @@ -401,7 +411,9 @@ export class EdrProviderWrapper traceItem.executionResult ); } - } else { + } + // beforeMessage event + else { if (this._node._vm.evm.events.listenerCount("beforeMessage") > 0) { this._node._vm.evm.events.emit( "beforeMessage", @@ -413,6 +425,11 @@ export class EdrProviderWrapper } } } + + // afterTx event + if (this._node._vm.events.listenerCount("afterTx") > 0) { + this._node._vm.events.emit("afterTx"); + } } } @@ -478,6 +495,10 @@ export class EdrProviderWrapper ); } + private _setVerboseTracing(enabled: boolean) { + this._provider.setVerboseTracing(enabled); + } + private _ethEventListener(event: SubscriptionEvent) { const subscription = `0x${event.filterId.toString(16)}`; const results = Array.isArray(event.result) ? event.result : [event.result]; diff --git a/packages/hardhat-core/src/internal/hardhat-network/provider/vm/minimal-vm.ts b/packages/hardhat-core/src/internal/hardhat-network/provider/vm/minimal-vm.ts index 155bcfa2e1..bf75d7d30a 100644 --- a/packages/hardhat-core/src/internal/hardhat-network/provider/vm/minimal-vm.ts +++ b/packages/hardhat-core/src/internal/hardhat-network/provider/vm/minimal-vm.ts @@ -13,8 +13,9 @@ import { AsyncEventEmitter } from "@nomicfoundation/ethereumjs-util"; * interface only has the things used by those plugins. */ export interface MinimalEthereumJsVm { + events: AsyncEventEmitter; evm: { - events: AsyncEventEmitter; + events: AsyncEventEmitter; }; stateManager: { putContractCode: (address: Address, code: Buffer) => Promise; @@ -27,10 +28,18 @@ export interface MinimalEthereumJsVm { }; } -// we need to use a type instead of an interface to satisfy the type constarint +// we need to use a type instead of an interface to satisfy the type constraint // of the AsyncEventEmitter type param // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type MinimalEthereumJsVmEvents = { + beforeTx: () => void; + afterTx: () => void; +}; + +// we need to use a type instead of an interface to satisfy the type constraint +// of the AsyncEventEmitter type param +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type MinimalEthereumJsEvmEvents = { beforeMessage: ( data: MinimalMessage, resolve?: (result?: any) => void @@ -46,13 +55,15 @@ type MinimalEthereumJsVmEvents = { }; export class MinimalEthereumJsVmEventEmitter extends AsyncEventEmitter {} +export class MinimalEthereumJsEvmEventEmitter extends AsyncEventEmitter {} export function getMinimalEthereumJsVm( provider: EdrProviderT ): MinimalEthereumJsVm { const minimalEthereumJsVm: MinimalEthereumJsVm = { + events: new MinimalEthereumJsVmEventEmitter(), evm: { - events: new MinimalEthereumJsVmEventEmitter(), + events: new MinimalEthereumJsEvmEventEmitter(), }, stateManager: { putContractCode: async (address: Address, code: Buffer) => {