diff --git a/packages/hardhat-plugin/src/internal/FhevmEnvironment.ts b/packages/hardhat-plugin/src/internal/FhevmEnvironment.ts index b60f506..760b44e 100644 --- a/packages/hardhat-plugin/src/internal/FhevmEnvironment.ts +++ b/packages/hardhat-plugin/src/internal/FhevmEnvironment.ts @@ -498,6 +498,11 @@ export class FhevmEnvironment { return this._contractsRepository; } + // Non-throwing variant for use in error-handling paths where FHEVM may not be initialized. + public tryGetContractsRepository(): contracts.FhevmContractsRepository | undefined { + return this._contractsRepository; + } + public get isDeployed(): boolean { return this._deployCompleted; } diff --git a/packages/hardhat-plugin/src/internal/errors/FhevmContractError.ts b/packages/hardhat-plugin/src/internal/errors/FhevmContractError.ts index 75a1bf7..9956cd2 100644 --- a/packages/hardhat-plugin/src/internal/errors/FhevmContractError.ts +++ b/packages/hardhat-plugin/src/internal/errors/FhevmContractError.ts @@ -225,9 +225,12 @@ function _parseEdrError( return undefined; } - const fhevmContractEntry = fhevmEnv - .getContractsRepository() - .getContractFromAddress(lastCallContractAddress)?.properties; + const repo = fhevmEnv.tryGetContractsRepository(); + if (!repo) { + return undefined; + } + + const fhevmContractEntry = repo.getContractFromAddress(lastCallContractAddress)?.properties; if (!fhevmContractEntry) { return undefined; } @@ -308,14 +311,17 @@ export async function mutateErrorInPlace(fhevmEnv: FhevmEnvironment, e: Error, a const i = err.stack.indexOf("\n"); err.stack = "Error: " + err.message + err.stack.substring(i); - const map = fhevmEnv.getContractsRepository().addressToContractMap(); + const repo = fhevmEnv.tryGetContractsRepository(); + if (repo) { + const map = repo.addressToContractMap(); - Object.keys(map).forEach((contractAddress) => { - err.stack = err.stack?.replaceAll( - `at . (${contractAddress})`, - `at ${map[contractAddress].name}. (${contractAddress}, ${map[contractAddress].package}/contracts/${map[contractAddress].name}.sol:0:0)`, - ); - }); + Object.keys(map).forEach((contractAddress) => { + err.stack = err.stack?.replaceAll( + `at . (${contractAddress})`, + `at ${map[contractAddress].name}. (${contractAddress}, ${map[contractAddress].package}/contracts/${map[contractAddress].name}.sol:0:0)`, + ); + }); + } } /** @@ -417,7 +423,12 @@ async function __formatFhevmErrorMessages( txHash?: string, txFromTo?: { from: string; to: string | null }, ): Promise { - const map = fhevmEnv.getContractsRepository().addressToContractMap(); + const repo = fhevmEnv.tryGetContractsRepository(); + if (!repo) { + return undefined; + } + + const map = repo.addressToContractMap(); const res: { errorDesc: EthersT.ErrorDescription; contractWrapper: contracts.FhevmContractWrapper; diff --git a/packages/hardhat-plugin/src/internal/provider/FhevmProviderExtender.ts b/packages/hardhat-plugin/src/internal/provider/FhevmProviderExtender.ts index 4edf279..d76b9a5 100644 --- a/packages/hardhat-plugin/src/internal/provider/FhevmProviderExtender.ts +++ b/packages/hardhat-plugin/src/internal/provider/FhevmProviderExtender.ts @@ -36,8 +36,14 @@ export class FhevmProviderExtender extends ProviderWrapper { } public async request(args: RequestArguments) { - // test init - // if not init forward! + // When FHEVM is not deployed, pass all requests through unchanged. + // This allows non-FHE tasks and scripts to work without initializing + // the FHEVM module (e.g. contract.pause(), custom hardhat tasks, etc.) + // See: https://github.com/zama-ai/fhevm-mocks/issues/80 + if (!fhevmContext.fhevmEnv?.isDeployed) { + return this._wrappedProvider.request(args); + } + switch (args.method) { // window.ethereum case "eth_estimateGas":