diff --git a/.changeset/cool-radios-type.md b/.changeset/cool-radios-type.md new file mode 100644 index 00000000000..5560a14c19f --- /dev/null +++ b/.changeset/cool-radios-type.md @@ -0,0 +1,11 @@ +--- +"@nomicfoundation/hardhat-ethers": patch +"@nomicfoundation/hardhat-ignition-viem": patch +"@nomicfoundation/hardhat-ignition": patch +"@nomicfoundation/hardhat-toolbox-viem": patch +"@nomicfoundation/hardhat-viem-assertions": patch +"@nomicfoundation/hardhat-viem": patch +"hardhat": patch +--- + +Use code 3 for JSON-RPC revert error codes to align with standard node behavior and preserve error causes in viem/ethers. diff --git a/packages/example-project/package.json b/packages/example-project/package.json index 5c85d1f173a..ad7a348e89c 100644 --- a/packages/example-project/package.json +++ b/packages/example-project/package.json @@ -51,6 +51,6 @@ "prettier": "3.2.5", "rimraf": "^5.0.5", "typescript": "~5.8.0", - "viem": "^2.43.0" + "viem": "^2.47.6" } } diff --git a/packages/hardhat-ethers/test/revert-error-cause.ts b/packages/hardhat-ethers/test/revert-error-cause.ts new file mode 100644 index 00000000000..e961af23b52 --- /dev/null +++ b/packages/hardhat-ethers/test/revert-error-cause.ts @@ -0,0 +1,96 @@ +import type { HardhatEthers } from "../src/types.js"; +import type { JsonRpcServer } from "hardhat/types/network"; + +import assert from "node:assert/strict"; +import { after, before, beforeEach, describe, it } from "node:test"; + +import { ensureError } from "@nomicfoundation/hardhat-utils/error"; + +import { initializeTestEthers, spawnTestRpcServer } from "./helpers/helpers.js"; + +let ethers: HardhatEthers; + +describe("revert error cause chain", () => { + describe("in-process EDR network", async () => { + beforeEach(async () => { + ({ ethers } = await initializeTestEthers([ + { artifactName: "Contract", fileName: "error-messages" }, + ])); + }); + + it("should have SolidityError as the thrown error", async () => { + const contract = await ethers.deployContract("Contract"); + + let caughtError: Error | undefined; + try { + await contract.revertsWithReasonString(); + } catch (error) { + ensureError(error); + caughtError = error; + } + + assert.ok( + caughtError !== undefined && caughtError.name === "SolidityError", + `Expected SolidityError, got ${caughtError?.name}`, + ); + assert.ok( + "code" in caughtError && caughtError.code === 3, + `Expected error code 3, got ${"code" in caughtError ? String(caughtError.code) : "undefined"}`, + ); + assert.ok( + caughtError.message.includes("some reason"), + `Expected message to include "some reason", got: "${caughtError.message}"`, + ); + }); + }); + + describe("hardhat node (HTTP)", async () => { + let server: JsonRpcServer; + let port: number; + let address: string; + + before(async () => { + ({ server, port, address } = await spawnTestRpcServer()); + }); + + after(async () => { + await server.close(); + }); + + beforeEach(async () => { + ({ ethers } = await initializeTestEthers( + [{ artifactName: "Contract", fileName: "error-messages" }], + { + networks: { + localhost: { type: "http", url: `http://${address}:${port}` }, + }, + }, + )); + }); + + it("should have ProviderError as the thrown error", async () => { + const contract = await ethers.deployContract("Contract"); + + let caughtError: Error | undefined; + try { + await contract.revertsWithReasonString(); + } catch (error) { + ensureError(error); + caughtError = error; + } + + assert.ok( + caughtError !== undefined && caughtError.name === "ProviderError", + `Expected ProviderError, got ${caughtError?.name}`, + ); + assert.ok( + "code" in caughtError && caughtError.code === 3, + `Expected error code 3, got ${"code" in caughtError ? String(caughtError.code) : "undefined"}`, + ); + assert.ok( + caughtError.message.includes("some reason"), + `Expected message to include "some reason", got: "${caughtError.message}"`, + ); + }); + }); +}); diff --git a/packages/hardhat-ignition-viem/package.json b/packages/hardhat-ignition-viem/package.json index 56c84d97524..fba204576b0 100644 --- a/packages/hardhat-ignition-viem/package.json +++ b/packages/hardhat-ignition-viem/package.json @@ -64,7 +64,7 @@ "ts-node": "10.9.2", "tsx": "^4.19.3", "typescript": "~5.8.0", - "viem": "^2.43.0", + "viem": "^2.47.6", "@nomicfoundation/hardhat-verify": "workspace:^3.0.0" }, "dependencies": { @@ -76,6 +76,6 @@ "@nomicfoundation/ignition-core": "workspace:^3.0.7", "@nomicfoundation/hardhat-verify": "workspace:^3.0.0", "@nomicfoundation/hardhat-viem": "workspace:^3.0.4", - "viem": "^2.43.0" + "viem": "^2.47.6" } } diff --git a/packages/hardhat-ignition/package.json b/packages/hardhat-ignition/package.json index 572870e8991..4dd72f08527 100644 --- a/packages/hardhat-ignition/package.json +++ b/packages/hardhat-ignition/package.json @@ -80,7 +80,7 @@ "sinon": "^14.0.0", "ts-node": "10.9.2", "typescript": "~5.8.0", - "viem": "^2.43.0", + "viem": "^2.47.6", "@nomicfoundation/hardhat-verify": "workspace:^3.0.0" }, "dependencies": { diff --git a/packages/hardhat-toolbox-viem/package.json b/packages/hardhat-toolbox-viem/package.json index 52a65943717..cb396b54a99 100644 --- a/packages/hardhat-toolbox-viem/package.json +++ b/packages/hardhat-toolbox-viem/package.json @@ -63,7 +63,7 @@ "rimraf": "^5.0.5", "tsx": "^4.19.3", "typescript": "~5.8.0", - "viem": "^2.43.0", + "viem": "^2.47.6", "hardhat": "workspace:^3.0.0" }, "peerDependencies": { @@ -77,6 +77,6 @@ "@nomicfoundation/hardhat-verify": "workspace:^3.0.0", "@nomicfoundation/ignition-core": "workspace:^3.0.7", "hardhat": "workspace:^3.0.0", - "viem": "^2.43.0" + "viem": "^2.47.6" } } diff --git a/packages/hardhat-viem-assertions/package.json b/packages/hardhat-viem-assertions/package.json index e747ccf6c3c..f789387d8a2 100644 --- a/packages/hardhat-viem-assertions/package.json +++ b/packages/hardhat-viem-assertions/package.json @@ -58,7 +58,7 @@ "rimraf": "^5.0.5", "tsx": "^4.19.3", "typescript": "~5.8.0", - "viem": "^2.43.0", + "viem": "^2.47.6", "hardhat": "workspace:^3.0.0" }, "dependencies": { @@ -68,6 +68,6 @@ "peerDependencies": { "@nomicfoundation/hardhat-viem": "workspace:^3.0.4", "hardhat": "workspace:^3.0.0", - "viem": "^2.43.0" + "viem": "^2.47.6" } } diff --git a/packages/hardhat-viem/package.json b/packages/hardhat-viem/package.json index dcf530a9f9f..a6979b0ec75 100644 --- a/packages/hardhat-viem/package.json +++ b/packages/hardhat-viem/package.json @@ -55,7 +55,7 @@ "rimraf": "^5.0.5", "tsx": "^4.19.3", "typescript": "~5.8.0", - "viem": "^2.43.0", + "viem": "^2.47.6", "hardhat": "workspace:^3.1.11" }, "dependencies": { @@ -64,6 +64,6 @@ }, "peerDependencies": { "hardhat": "workspace:^3.1.11", - "viem": "^2.43.0" + "viem": "^2.47.6" } } diff --git a/packages/hardhat-viem/test/fixture-projects/default-ts-project/contracts/Revert.sol b/packages/hardhat-viem/test/fixture-projects/default-ts-project/contracts/Revert.sol new file mode 100644 index 00000000000..4ffa0ead120 --- /dev/null +++ b/packages/hardhat-viem/test/fixture-projects/default-ts-project/contracts/Revert.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.0; + +contract Revert { + function alwaysRevert() external pure { + revert("Intentional revert for testing purposes"); + } +} diff --git a/packages/hardhat-viem/test/revert-error-chain.ts b/packages/hardhat-viem/test/revert-error-chain.ts new file mode 100644 index 00000000000..bbfe42c6181 --- /dev/null +++ b/packages/hardhat-viem/test/revert-error-chain.ts @@ -0,0 +1,173 @@ +import type { HardhatViemHelpers } from "@nomicfoundation/hardhat-viem/types"; +import type { HardhatRuntimeEnvironment } from "hardhat/types/hre"; +import type { JsonRpcServer } from "hardhat/types/network"; + +import assert from "node:assert/strict"; +import { after, before, beforeEach, describe, it } from "node:test"; + +import { useEphemeralFixtureProject } from "@nomicfoundation/hardhat-test-utils"; +import { ensureError } from "@nomicfoundation/hardhat-utils/error"; +import { createHardhatRuntimeEnvironment } from "hardhat/hre"; +import { + ContractFunctionExecutionError, + ContractFunctionRevertedError, +} from "viem"; + +import hardhatViem from "../src/index.js"; + +describe("revert error cause chain", () => { + useEphemeralFixtureProject("default-ts-project"); + + describe("in-process hardhat network", () => { + let hre: HardhatRuntimeEnvironment; + let viem: HardhatViemHelpers; + + before(async () => { + hre = await createHardhatRuntimeEnvironment({ + plugins: [hardhatViem], + }); + + await hre.tasks.getTask("build").run({}); + }); + + beforeEach(async () => { + ({ viem } = await hre.network.connect()); + }); + + it("should have ContractFunctionExecutionError as the thrown error", async () => { + const contract = await viem.deployContract("Revert"); + + let caughtError: Error | undefined; + try { + await contract.read.alwaysRevert(); + } catch (error) { + ensureError(error); + caughtError = error; + } + + assert.ok( + caughtError !== undefined && + caughtError instanceof ContractFunctionExecutionError, + `Expected ContractFunctionExecutionError, got ${caughtError?.name}`, + ); + assert.ok( + caughtError.message.includes("Intentional revert for testing purposes"), + `Expected message to include "Intentional revert for testing purposes", got: "${caughtError.message}"`, + ); + }); + + it("should have SolidityError in cause chain", async () => { + const contract = await viem.deployContract("Revert"); + + let caughtError: Error | undefined; + try { + await contract.read.alwaysRevert(); + } catch (error) { + ensureError(error); + caughtError = error; + } + + let current: Error | undefined = caughtError; + let solidityError: Error | undefined; + + while (current !== undefined) { + if (current.name === "SolidityError") { + solidityError = current; + break; + } + + current = current.cause instanceof Error ? current.cause : undefined; + } + + assert.ok( + solidityError !== undefined, + "Expected to find SolidityError in the cause chain", + ); + assert.ok( + "code" in solidityError && solidityError.code === 3, + `Expected error code 3, got ${"code" in solidityError ? String(solidityError.code) : "undefined"}`, + ); + }); + }); + + describe("hardhat node (HTTP)", () => { + let hre: HardhatRuntimeEnvironment; + let viem: HardhatViemHelpers; + let server: JsonRpcServer; + let address: string; + let port: number; + + before(async () => { + hre = await createHardhatRuntimeEnvironment({ + plugins: [hardhatViem], + networks: { + localhost: { type: "http", url: "http://127.0.0.1:0" }, + }, + }); + + await hre.tasks.getTask("build").run({}); + + server = await hre.network.createServer(); + ({ address, port } = await server.listen()); + }); + + after(async () => { + await server.close(); + }); + + beforeEach(async () => { + ({ viem } = await hre.network.connect({ + network: "localhost", + override: { + url: `http://${address}:${port}`, + }, + })); + }); + + it("should have ContractFunctionExecutionError as the thrown error", async () => { + const contract = await viem.deployContract("Revert"); + + let caughtError: Error | undefined; + try { + await contract.read.alwaysRevert(); + } catch (error) { + ensureError(error); + caughtError = error; + } + + assert.ok( + caughtError !== undefined && + caughtError instanceof ContractFunctionExecutionError, + `Expected ContractFunctionExecutionError, got ${caughtError?.name}`, + ); + assert.ok( + caughtError.message.includes("Intentional revert for testing purposes"), + `Expected message to include "Intentional revert for testing purposes", got: "${caughtError.message}"`, + ); + + let current: Error | undefined = caughtError; + let errorWithCode3: Error | undefined; + + while (current !== undefined) { + if ("code" in current && current.code === 3) { + errorWithCode3 = current; + break; + } + + current = current.cause instanceof Error ? current.cause : undefined; + } + + assert.ok( + errorWithCode3 !== undefined, + "Expected to find an error with code 3 in the cause chain", + ); + + const cause = caughtError.cause; + ensureError(cause, ContractFunctionRevertedError); + assert.ok( + "raw" in cause && cause.raw !== undefined, + "Expected raw revert data to be present on ContractFunctionRevertedError", + ); + }); + }); +}); diff --git a/packages/hardhat/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-solidity-errors.ts b/packages/hardhat/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-solidity-errors.ts index 8357cb5ee01..9345df0ef90 100644 --- a/packages/hardhat/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-solidity-errors.ts +++ b/packages/hardhat/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-solidity-errors.ts @@ -9,6 +9,8 @@ import { assertHardhatInvariant } from "@nomicfoundation/hardhat-errors"; import { bytesToHexString } from "@nomicfoundation/hardhat-utils/bytes"; import { panicErrorCodeToMessage } from "@nomicfoundation/hardhat-utils/panic-errors"; +import { REVERT_ERROR_CODE } from "../../revert-error-code.js"; + import { StackTraceEntryType, CONSTRUCTOR_FUNCTION_NAME, @@ -293,11 +295,15 @@ function getMessageFromLastStackTraceEntry( } /** - * Note: This error class MUST NOT extend ProviderError, as libraries use the - * code property to detect if they are dealing with a JSON-RPC error, and take - * control of errors. + * Note: This error class does not extend ProviderError because it carries + * Solidity-specific data (stackTrace) that ProviderError does not model. + * It does carry `code = 3` to match the de facto standard used by geth and + * anvil for execution revert errors, allowing libraries like viem to + * properly detect and handle revert errors via the error cause chain. **/ export class SolidityError extends Error { + public readonly code: number = REVERT_ERROR_CODE; + constructor( message: string, public readonly stackTrace: SolidityStackTrace, @@ -305,6 +311,7 @@ export class SolidityError extends Error { public readonly transactionHash?: string, ) { super(message); + this.name = "SolidityError"; Object.defineProperty(this, Symbol.for("nodejs.util.inspect.custom"), { value: () => diff --git a/packages/hardhat/src/internal/builtin-plugins/network-manager/revert-error-code.ts b/packages/hardhat/src/internal/builtin-plugins/network-manager/revert-error-code.ts new file mode 100644 index 00000000000..0a0b1715348 --- /dev/null +++ b/packages/hardhat/src/internal/builtin-plugins/network-manager/revert-error-code.ts @@ -0,0 +1,2 @@ +// Error code used by geth/anvil for execution revert errors (e.g. Solidity reverts). +export const REVERT_ERROR_CODE: number = 3; diff --git a/packages/hardhat/src/internal/builtin-plugins/node/json-rpc/handler.ts b/packages/hardhat/src/internal/builtin-plugins/node/json-rpc/handler.ts index a17f1da8155..8f46ea56742 100644 --- a/packages/hardhat/src/internal/builtin-plugins/node/json-rpc/handler.ts +++ b/packages/hardhat/src/internal/builtin-plugins/node/json-rpc/handler.ts @@ -21,6 +21,7 @@ import { InvalidRequestError, ProviderError, } from "../../network-manager/provider-errors.js"; +import { REVERT_ERROR_CODE } from "../../network-manager/revert-error-code.js"; export class JsonRpcHandler { readonly #provider: EthereumProvider; @@ -256,8 +257,15 @@ const _handleError = (error: Error): JsonRpcResponse => { const txHash = extractTxHash(error); const returnData = extractReturnData(error); - // In case of non-hardhat error, treat it as internal and associate the appropriate error code. - if (!ProviderError.isProviderError(error)) { + // Check if this is a revert error (code 3) matching the geth/anvil convention. + const isRevertError = + "code" in error && + typeof error.code === "number" && + error.code === REVERT_ERROR_CODE; + + // In case of non-hardhat error that is not a revert, treat it as internal + // and associate the appropriate error code. + if (!ProviderError.isProviderError(error) && !isRevertError) { error = new InternalError(undefined, error); } diff --git a/packages/hardhat/templates/hardhat-2/04-mocha-viem-ts/package.json b/packages/hardhat/templates/hardhat-2/04-mocha-viem-ts/package.json index 8c7159c1c05..e4ef0d1a655 100644 --- a/packages/hardhat/templates/hardhat-2/04-mocha-viem-ts/package.json +++ b/packages/hardhat/templates/hardhat-2/04-mocha-viem-ts/package.json @@ -20,6 +20,6 @@ "solidity-coverage": "^0.8.0", "ts-node": ">=8.0.0", "typescript": "~5.0.4", - "viem": "^2.43.0" + "viem": "^2.47.6" } } diff --git a/packages/hardhat/templates/hardhat-3/01-node-test-runner-viem/package.json b/packages/hardhat/templates/hardhat-3/01-node-test-runner-viem/package.json index 3d509f73190..16e3b268bc6 100644 --- a/packages/hardhat/templates/hardhat-3/01-node-test-runner-viem/package.json +++ b/packages/hardhat/templates/hardhat-3/01-node-test-runner-viem/package.json @@ -11,7 +11,7 @@ "@types/node": "^22.8.5", "forge-std": "foundry-rs/forge-std#v1.9.4", "typescript": "~5.8.0", - "viem": "^2.43.0" + "viem": "^2.47.6" }, "peerDependencies": { "@nomicfoundation/hardhat-ignition-viem": "workspace:^3.1.1", diff --git a/packages/hardhat/test/internal/builtin-plugins/node/json-rpc/handler.ts b/packages/hardhat/test/internal/builtin-plugins/node/json-rpc/handler.ts index dc4c750989c..3b69df75714 100644 --- a/packages/hardhat/test/internal/builtin-plugins/node/json-rpc/handler.ts +++ b/packages/hardhat/test/internal/builtin-plugins/node/json-rpc/handler.ts @@ -64,9 +64,20 @@ describe("JSON-RPC handler", async function () { }; throw err; }, - nonProviderErrorWithRevertData: () => { - // Simulates SolidityError: a non-ProviderError with .data and .transactionHash - const err = new Error("revert Unauthorized"); + nonProviderErrorWithDataButNoCode3: () => { + // A non-ProviderError with .data and .transactionHash but WITHOUT .code=3 + const err = new Error("some error with data"); + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- allow in test + (err as any).data = "0xcafe"; + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- allow in test + (err as any).transactionHash = "0xdef456"; + throw err; + }, + revertWithDataAndTxHash: () => { + // Simulates a SolidityError (code 3) with both revert data and txHash + const err = new Error("execution reverted"); + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- allow in test + (err as any).code = 3; // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- allow in test (err as any).data = "0xdeadbeef"; // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- allow in test @@ -308,11 +319,10 @@ describe("JSON-RPC handler", async function () { assert.equal(rpcRes.error.data.data, "0xabad1dea"); }); - it("should preserve revert data from non-ProviderError errors", async function () { - // Simulates SolidityError which has .data and .transactionHash but is NOT a ProviderError + it("should wrap non-ProviderError with data but without code 3 as InternalError", async function () { const rpcReq: JsonRpcRequest = { jsonrpc: "2.0", - method: "nonProviderErrorWithRevertData", + method: "nonProviderErrorWithDataButNoCode3", id: 1, }; @@ -327,8 +337,39 @@ describe("JSON-RPC handler", async function () { isObject(rpcRes.error.data), "Expected error data to be an object", ); + assert.equal(rpcRes.error.data.txHash, "0xdef456"); + assert.equal(rpcRes.error.data.data, "0xcafe"); + }); + + it("should preserve code 3, revert data, and txHash for revert errors over HTTP", async function () { + const rpcReq: JsonRpcRequest = { + jsonrpc: "2.0", + method: "revertWithDataAndTxHash", + id: 1, + }; + + const rpcRes = await postRawJsonRpc(hostname, port, JSON.stringify(rpcReq)); + + assert.ok( + isJsonRpcResponse(rpcRes) && isFailedJsonRpcResponse(rpcRes), + "Expected a failed JSON-RPC response", + ); + assert.equal(rpcRes.error.code, 3, "Revert errors must use code 3"); + assert.equal( + rpcRes.error.message, + "execution reverted", + "Revert error must not be wrapped as InternalError", + ); + assert.ok( + isObject(rpcRes.error.data), + "Expected error data to be an object", + ); + assert.equal( + rpcRes.error.data.data, + "0xdeadbeef", + "error.data.data must contain the raw revert hex", + ); assert.equal(rpcRes.error.data.txHash, "0xabc123"); - assert.equal(rpcRes.error.data.data, "0xdeadbeef"); }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f030e852e48..9cb1fd0de3c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -159,8 +159,8 @@ importers: specifier: ~5.8.0 version: 5.8.3 viem: - specifier: ^2.43.0 - version: 2.43.5(typescript@5.8.3)(zod@3.25.76) + specifier: ^2.47.6 + version: 2.47.6(typescript@5.8.3)(zod@3.25.76) packages/hardhat: dependencies: @@ -567,8 +567,8 @@ importers: specifier: ~5.8.0 version: 5.8.3 viem: - specifier: ^2.43.0 - version: 2.43.5(typescript@5.8.3)(zod@3.25.76) + specifier: ^2.47.6 + version: 2.47.6(typescript@5.8.3)(zod@3.25.76) packages/hardhat-ignition-ethers: dependencies: @@ -695,8 +695,8 @@ importers: specifier: ~5.8.0 version: 5.8.3 viem: - specifier: ^2.43.0 - version: 2.43.5(typescript@5.8.3)(zod@3.25.76) + specifier: ^2.47.6 + version: 2.47.6(typescript@5.8.3)(zod@3.25.76) packages/hardhat-keystore: dependencies: @@ -1270,8 +1270,8 @@ importers: specifier: ~5.8.0 version: 5.8.3 viem: - specifier: ^2.43.0 - version: 2.43.5(typescript@5.8.3)(zod@3.25.76) + specifier: ^2.47.6 + version: 2.47.6(typescript@5.8.3)(zod@3.25.76) packages/hardhat-typechain: dependencies: @@ -1550,8 +1550,8 @@ importers: specifier: ~5.8.0 version: 5.8.3 viem: - specifier: ^2.43.0 - version: 2.43.5(typescript@5.8.3)(zod@3.25.76) + specifier: ^2.47.6 + version: 2.47.6(typescript@5.8.3)(zod@3.25.76) packages/hardhat-viem-assertions: dependencies: @@ -1599,8 +1599,8 @@ importers: specifier: ~5.8.0 version: 5.8.3 viem: - specifier: ^2.43.0 - version: 2.43.5(typescript@5.8.3)(zod@3.25.76) + specifier: ^2.47.6 + version: 2.47.6(typescript@5.8.3)(zod@3.25.76) packages/hardhat-zod-utils: dependencies: @@ -1691,8 +1691,8 @@ importers: specifier: ~5.8.0 version: 5.8.3 viem: - specifier: ^2.43.0 - version: 2.43.5(typescript@5.8.3)(zod@3.25.76) + specifier: ^2.47.6 + version: 2.47.6(typescript@5.8.3)(zod@3.25.76) packages/hardhat/templates/hardhat-3/02-mocha-ethers: dependencies: @@ -6174,8 +6174,8 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} - ox@0.11.1: - resolution: {integrity: sha512-1l1gOLAqg0S0xiN1dH5nkPna8PucrZgrIJOfS49MLNiMevxu07Iz4ZjuJS9N+xifvT+PsZyIptS7WHM8nC+0+A==} + ox@0.14.7: + resolution: {integrity: sha512-zSQ/cfBdolj7U4++NAvH7sI+VG0T3pEohITCgcQj8KlawvTDY4vGVhDT64Atsm0d6adWfIYHDpu88iUBMMp+AQ==} peerDependencies: typescript: '>=5.4.0' peerDependenciesMeta: @@ -7210,8 +7210,8 @@ packages: resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} engines: {'0': node >=0.6.0} - viem@2.43.5: - resolution: {integrity: sha512-QuJpuEMEPM3EreN+vX4mVY68Sci0+zDxozYfbh/WfV+SSy/Gthm74PH8XmitXdty1xY54uTCJ+/Gbbd1IiMPSA==} + viem@2.47.6: + resolution: {integrity: sha512-zExmbI99NGvMdYa7fmqSTLgkwh48dmhgEqFrUgkpL4kfG4XkVefZ8dZqIKVUhZo6Uhf0FrrEXOsHm9LUyIvI2Q==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -12192,7 +12192,7 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 - ox@0.11.1(typescript@5.8.3)(zod@3.25.76): + ox@0.14.7(typescript@5.8.3)(zod@3.25.76): dependencies: '@adraffy/ens-normalize': 1.11.1 '@noble/ciphers': 1.3.0 @@ -13422,7 +13422,7 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - viem@2.43.5(typescript@5.8.3)(zod@3.25.76): + viem@2.47.6(typescript@5.8.3)(zod@3.25.76): dependencies: '@noble/curves': 1.9.1 '@noble/hashes': 1.8.0 @@ -13430,7 +13430,7 @@ snapshots: '@scure/bip39': 1.6.0 abitype: 1.2.3(typescript@5.8.3)(zod@3.25.76) isows: 1.0.7(ws@8.18.3) - ox: 0.11.1(typescript@5.8.3)(zod@3.25.76) + ox: 0.14.7(typescript@5.8.3)(zod@3.25.76) ws: 8.18.3 optionalDependencies: typescript: 5.8.3