@nomicfoundation/edr 0.12.0-next.30 → 0.12.0-next.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/coverage.sol ADDED
@@ -0,0 +1,38 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity >=0.4.22 <0.9.0;
3
+
4
+ library __NomicFoundationCoverage {
5
+ address constant COVERAGE_ADDRESS =
6
+ 0xc0bEc0BEc0BeC0bEC0beC0bEC0bEC0beC0beC0BE;
7
+
8
+ function _sendHitImplementation(uint256 coverageId) private view {
9
+ address coverageAddress = COVERAGE_ADDRESS;
10
+ /// @solidity memory-safe-assembly
11
+ assembly {
12
+ let ptr := mload(0x40) // Get free memory pointer
13
+ mstore(ptr, coverageId) // Store coverageId at free memory
14
+ pop(
15
+ staticcall(
16
+ gas(),
17
+ coverageAddress,
18
+ ptr,
19
+ 32, // Size of uint256 is 32 bytes
20
+ 0,
21
+ 0
22
+ )
23
+ )
24
+ }
25
+ }
26
+
27
+ function _castToPure(
28
+ function(uint256) internal view fnIn
29
+ ) private pure returns (function(uint256) pure fnOut) {
30
+ assembly {
31
+ fnOut := fnIn
32
+ }
33
+ }
34
+
35
+ function sendHit(uint256 coverageId) internal pure {
36
+ _castToPure(_sendHitImplementation)(coverageId);
37
+ }
38
+ }
@@ -0,0 +1,6 @@
1
+ export interface CoverageLib {
2
+ content: string;
3
+ filename: string;
4
+ }
5
+ export declare function getCoverageLibrary(): CoverageLib;
6
+ //# sourceMappingURL=coverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../../src/ts/coverage.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,kBAAkB,IAAI,WAAW,CAYhD"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getCoverageLibrary = getCoverageLibrary;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const edr_1 = require("@nomicfoundation/edr");
40
+ function getCoverageLibrary() {
41
+ const packageRoot = path.dirname(require.resolve("@nomicfoundation/edr"));
42
+ const sourcePath = path.join(packageRoot, "coverage.sol");
43
+ if (!fs.existsSync(sourcePath)) {
44
+ throw new Error(`Coverage library file not found at ${sourcePath}. It should be bundled with @nomicfoundation/edr.`);
45
+ }
46
+ return {
47
+ content: fs.readFileSync(sourcePath, "utf-8"),
48
+ filename: edr_1.COVERAGE_LIBRARY_FILE_NAME,
49
+ };
50
+ }
51
+ //# sourceMappingURL=coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../../src/ts/coverage.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,gDAYC;AAtBD,uCAAyB;AACzB,2CAA6B;AAE7B,8CAAkE;AAOlE,SAAgB,kBAAkB;IAChC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAC1E,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC1D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,sCAAsC,UAAU,mDAAmD,CACpG,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC;QAC7C,QAAQ,EAAE,gCAA0B;KACrC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { StandardTestKind, FuzzTestKind, InvariantTestKind } from "../../index";
2
+ export declare enum SortOrder {
3
+ Ascending = 0,
4
+ Descending = 1
5
+ }
6
+ export interface GasUsageFilter {
7
+ minThreshold?: bigint;
8
+ maxThreshold?: bigint;
9
+ }
10
+ export declare function extractGasUsage(testResults: {
11
+ name: string;
12
+ kind: StandardTestKind | FuzzTestKind | InvariantTestKind;
13
+ }[], filter?: GasUsageFilter, ordering?: SortOrder): {
14
+ name: string;
15
+ gas: bigint;
16
+ }[];
17
+ //# sourceMappingURL=solidity_tests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solidity_tests.d.ts","sourceRoot":"","sources":["../../../src/ts/solidity_tests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhF,oBAAY,SAAS;IACnB,SAAS,IAAA;IACT,UAAU,IAAA;CACX;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,eAAe,CAC7B,WAAW,EAAE;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,gBAAgB,GAAG,YAAY,GAAG,iBAAiB,CAAC;CAC3D,EAAE,EACH,MAAM,CAAC,EAAE,cAAc,EACvB,QAAQ,CAAC,EAAE,SAAS,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,CA0BjC"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SortOrder = void 0;
4
+ exports.extractGasUsage = extractGasUsage;
5
+ var SortOrder;
6
+ (function (SortOrder) {
7
+ SortOrder[SortOrder["Ascending"] = 0] = "Ascending";
8
+ SortOrder[SortOrder["Descending"] = 1] = "Descending";
9
+ })(SortOrder || (exports.SortOrder = SortOrder = {}));
10
+ function extractGasUsage(testResults, filter, ordering) {
11
+ const gasUsage = [];
12
+ for (const result of testResults) {
13
+ // Default to zero gas for invariant tests
14
+ const gas = "consumedGas" in result.kind
15
+ ? result.kind.consumedGas
16
+ : "medianGas" in result.kind
17
+ ? result.kind.medianGas
18
+ : BigInt(0);
19
+ if ((!filter?.minThreshold || gas >= filter.minThreshold) &&
20
+ (!filter?.maxThreshold || gas <= filter.maxThreshold)) {
21
+ gasUsage.push({ name: result.name, gas });
22
+ }
23
+ }
24
+ if (ordering === SortOrder.Ascending) {
25
+ gasUsage.sort((a, b) => (a.gas < b.gas ? -1 : a.gas > b.gas ? 1 : 0));
26
+ }
27
+ else if (ordering === SortOrder.Descending) {
28
+ gasUsage.sort((a, b) => (a.gas > b.gas ? -1 : a.gas < b.gas ? 1 : 0));
29
+ }
30
+ return gasUsage;
31
+ }
32
+ //# sourceMappingURL=solidity_tests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solidity_tests.js","sourceRoot":"","sources":["../../../src/ts/solidity_tests.ts"],"names":[],"mappings":";;;AAYA,0CAiCC;AA3CD,IAAY,SAGX;AAHD,WAAY,SAAS;IACnB,mDAAS,CAAA;IACT,qDAAU,CAAA;AACZ,CAAC,EAHW,SAAS,yBAAT,SAAS,QAGpB;AAOD,SAAgB,eAAe,CAC7B,WAGG,EACH,MAAuB,EACvB,QAAoB;IAEpB,MAAM,QAAQ,GAAoC,EAAE,CAAC;IAErD,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;QACjC,0CAA0C;QAC1C,MAAM,GAAG,GAAG,aAAa,IAAI,MAAM,CAAC,IAAI;YACtC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW;YACzB,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI;gBAC1B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS;gBACvB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAEhB,IACE,CAAC,CAAC,MAAM,EAAE,YAAY,IAAI,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC;YACrD,CAAC,CAAC,MAAM,EAAE,YAAY,IAAI,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,EACrD,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,KAAK,SAAS,CAAC,SAAS,EAAE,CAAC;QACrC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;SAAM,IAAI,QAAQ,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;QAC7C,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
package/index.d.ts CHANGED
@@ -460,11 +460,13 @@ export interface InstrumentationMetadata {
460
460
  */
461
461
  readonly endUtf16: number
462
462
  }
463
+ /** The instrumentation coverage library file name. */
464
+ export const COVERAGE_LIBRARY_FILE_NAME: string
463
465
  /**
464
466
  * Adds per-statement coverage instrumentation to the given Solidity source
465
467
  * code.
466
468
  */
467
- export declare function addStatementCoverageInstrumentation(sourceCode: string, sourceId: string, solidityVersion: string, coverageLibraryPath: string): InstrumentationResult
469
+ export declare function addStatementCoverageInstrumentation(sourceCode: string, sourceId: string, solidityVersion: string): InstrumentationResult
468
470
  /** Retrieves the latest version of `Solidity` supported for instrumentation. */
469
471
  export declare function latestSupportedSolidityVersion(): string
470
472
  /** Ethereum execution log. */
@@ -795,6 +797,40 @@ export interface SolidityTestRunnerConfigArgs {
795
797
  * Defaults to none.
796
798
  */
797
799
  testFunctionOverrides?: Array<TestFunctionOverride>
800
+ /**
801
+ * A list of EIP-712 canonical type definitions that can be referenced by
802
+ * type name in the `eip712HashType` and `eip712HashStruct` cheatcodes.
803
+ *
804
+ * Each entry is an independent, self-contained type definition. A
805
+ * definition that references nested struct types must inline those
806
+ * struct definitions, per the EIP-712 `encodeType` spec.
807
+ *
808
+ * Only the primary (leftmost) type of each entry is registered by name.
809
+ * Nested struct types referenced inside an entry are *not* registered
810
+ * under their own names. To look up a nested struct by name from a
811
+ * cheatcode, add it as a separate top-level entry whose primary type
812
+ * is the nested struct.
813
+ *
814
+ * The type of a struct is encoded as:
815
+ *
816
+ * `name ‖ "(" ‖ member₁ ‖ "," ‖ member₂ ‖ "," ‖ … ‖ memberₙ ")"`
817
+ *
818
+ * where each member is written as `type ‖ " " ‖ name`.
819
+ *
820
+ * Entries that fail to parse cause a startup error listing every bad
821
+ * entry.
822
+ *
823
+ * Example — to make both `Mail` and `Person` reachable by name:
824
+ *
825
+ * ```text
826
+ * "Mail(Person from,Person to,string contents)Person(address wallet,string name)"
827
+ * "Person(address wallet,string name)"
828
+ * ```
829
+ *
830
+ * With *only* the first entry, `vm.eip712HashType("Mail")` works but
831
+ * `vm.eip712HashType("Person")` fails with an unknown-type error.
832
+ */
833
+ eip712CanonicalTypes?: Array<string>
798
834
  }
799
835
  /** Fuzz testing configuration */
800
836
  export interface FuzzConfigArgs {
@@ -1018,6 +1054,20 @@ export interface TestFunctionConfigOverride {
1018
1054
  * as the test.
1019
1055
  */
1020
1056
  allowInternalExpectRevert?: boolean
1057
+ /**
1058
+ * Whether to enable isolation of calls for the test. In isolation mode all
1059
+ * top-level calls are executed as a separate transaction in a separate
1060
+ * EVM context, enabling more precise gas accounting and transaction
1061
+ * state changes.
1062
+ * Ignored when gas reporting is enabled, as isolation is required for
1063
+ * accurate gas measurements.
1064
+ */
1065
+ isolate?: boolean
1066
+ /**
1067
+ * The EVM version to use for this test, e.g. "Cancun". This will override
1068
+ * the global EVM version.
1069
+ */
1070
+ evmVersion?: string
1021
1071
  /** Configuration override for fuzz testing. */
1022
1072
  fuzz?: FuzzConfigOverride
1023
1073
  /** Configuration override for invariant testing. */
package/index.js CHANGED
@@ -310,7 +310,7 @@ if (!nativeBinding) {
310
310
  throw new Error(`Failed to load native binding`)
311
311
  }
312
312
 
313
- const { GENERIC_CHAIN_TYPE, genericChainProviderFactory, L1_CHAIN_TYPE, l1GenesisState, l1ProviderFactory, SpecId, l1HardforkFromString, l1HardforkToString, l1HardforkLatest, FRONTIER, FRONTIER_THAWING, HOMESTEAD, DAO_FORK, TANGERINE, SPURIOUS_DRAGON, BYZANTIUM, CONSTANTINOPLE, PETERSBURG, ISTANBUL, MUIR_GLACIER, BERLIN, LONDON, ARROW_GLACIER, GRAY_GLACIER, MERGE, SHANGHAI, CANCUN, PRAGUE, OSAKA, OpHardfork, opHardforkFromString, opHardforkToString, opLatestHardfork, OP_CHAIN_TYPE, opGenesisState, opProviderFactory, BEDROCK, REGOLITH, CANYON, ECOTONE, FJORD, GRANITE, HOLOCENE, ISTHMUS, MineOrdering, EdrContext, ContractDecoder, GasReportExecutionStatus, addStatementCoverageInstrumentation, latestSupportedSolidityVersion, Precompile, precompileP256Verify, ProviderFactory, Response, Provider, SuccessReason, ExceptionalHalt, CheatcodeErrorCode, CachedChains, CachedEndpoints, FsAccessPermission, CollectStackTraces, IncludeTraces, SolidityTestRunnerFactory, l1SolidityTestRunnerFactory, opSolidityTestRunnerFactory, SuiteResult, TestResult, TestStatus, CallKind, LogKind, linkHexStringBytecode, printStackTrace, Exit, ExitCode, BytecodeWrapper, ContractFunctionType, ReturnData, StackTraceEntryType, stackTraceEntryTypeToString, FALLBACK_FUNCTION_NAME, RECEIVE_FUNCTION_NAME, CONSTRUCTOR_FUNCTION_NAME, UNRECOGNIZED_FUNCTION_NAME, UNKNOWN_FUNCTION_NAME, PRECOMPILE_FUNCTION_NAME, UNRECOGNIZED_CONTRACT_NAME, RawTrace } = nativeBinding
313
+ const { GENERIC_CHAIN_TYPE, genericChainProviderFactory, L1_CHAIN_TYPE, l1GenesisState, l1ProviderFactory, SpecId, l1HardforkFromString, l1HardforkToString, l1HardforkLatest, FRONTIER, FRONTIER_THAWING, HOMESTEAD, DAO_FORK, TANGERINE, SPURIOUS_DRAGON, BYZANTIUM, CONSTANTINOPLE, PETERSBURG, ISTANBUL, MUIR_GLACIER, BERLIN, LONDON, ARROW_GLACIER, GRAY_GLACIER, MERGE, SHANGHAI, CANCUN, PRAGUE, OSAKA, OpHardfork, opHardforkFromString, opHardforkToString, opLatestHardfork, OP_CHAIN_TYPE, opGenesisState, opProviderFactory, BEDROCK, REGOLITH, CANYON, ECOTONE, FJORD, GRANITE, HOLOCENE, ISTHMUS, MineOrdering, EdrContext, ContractDecoder, GasReportExecutionStatus, COVERAGE_LIBRARY_FILE_NAME, addStatementCoverageInstrumentation, latestSupportedSolidityVersion, Precompile, precompileP256Verify, ProviderFactory, Response, Provider, SuccessReason, ExceptionalHalt, CheatcodeErrorCode, CachedChains, CachedEndpoints, FsAccessPermission, CollectStackTraces, IncludeTraces, SolidityTestRunnerFactory, l1SolidityTestRunnerFactory, opSolidityTestRunnerFactory, SuiteResult, TestResult, TestStatus, CallKind, LogKind, linkHexStringBytecode, printStackTrace, Exit, ExitCode, BytecodeWrapper, ContractFunctionType, ReturnData, StackTraceEntryType, stackTraceEntryTypeToString, FALLBACK_FUNCTION_NAME, RECEIVE_FUNCTION_NAME, CONSTRUCTOR_FUNCTION_NAME, UNRECOGNIZED_FUNCTION_NAME, UNKNOWN_FUNCTION_NAME, PRECOMPILE_FUNCTION_NAME, UNRECOGNIZED_CONTRACT_NAME, RawTrace } = nativeBinding
314
314
 
315
315
  module.exports.GENERIC_CHAIN_TYPE = GENERIC_CHAIN_TYPE
316
316
  module.exports.genericChainProviderFactory = genericChainProviderFactory
@@ -360,6 +360,7 @@ module.exports.MineOrdering = MineOrdering
360
360
  module.exports.EdrContext = EdrContext
361
361
  module.exports.ContractDecoder = ContractDecoder
362
362
  module.exports.GasReportExecutionStatus = GasReportExecutionStatus
363
+ module.exports.COVERAGE_LIBRARY_FILE_NAME = COVERAGE_LIBRARY_FILE_NAME
363
364
  module.exports.addStatementCoverageInstrumentation = addStatementCoverageInstrumentation
364
365
  module.exports.latestSupportedSolidityVersion = latestSupportedSolidityVersion
365
366
  module.exports.Precompile = Precompile
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nomicfoundation/edr",
3
- "version": "0.12.0-next.30",
3
+ "version": "0.12.0-next.32",
4
4
  "devDependencies": {
5
5
  "@napi-rs/cli": "^2.18.4",
6
6
  "@nomicfoundation/ethereumjs-util": "^9.0.4",
@@ -31,12 +31,15 @@
31
31
  },
32
32
  "exports": {
33
33
  ".": "./index.js",
34
- "./solidity-tests": "./dist/src/ts/solidity_tests.js"
34
+ "./solidity-tests": "./dist/src/ts/solidity_tests.js",
35
+ "./coverage": "./dist/src/ts/coverage.js"
35
36
  },
36
37
  "files": [
37
38
  "index.js",
38
39
  "index.d.ts",
39
- "src/"
40
+ "src/",
41
+ "dist/src/",
42
+ "coverage.sol"
40
43
  ],
41
44
  "license": "MIT",
42
45
  "main": "index.js",
@@ -58,13 +61,13 @@
58
61
  "repository": "NomicFoundation/edr.git",
59
62
  "types": "index.d.ts",
60
63
  "dependencies": {
61
- "@nomicfoundation/edr-darwin-arm64": "0.12.0-next.30",
62
- "@nomicfoundation/edr-darwin-x64": "0.12.0-next.30",
63
- "@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.30",
64
- "@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.30",
65
- "@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.30",
66
- "@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.30",
67
- "@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.30"
64
+ "@nomicfoundation/edr-darwin-arm64": "0.12.0-next.32",
65
+ "@nomicfoundation/edr-darwin-x64": "0.12.0-next.32",
66
+ "@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.32",
67
+ "@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.32",
68
+ "@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.32",
69
+ "@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.32",
70
+ "@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.32"
68
71
  },
69
72
  "scripts": {
70
73
  "artifacts": "napi artifacts",
package/src/instrument.rs CHANGED
@@ -76,6 +76,10 @@ impl TryFrom<edr_instrument::coverage::InstrumentationMetadata> for Instrumentat
76
76
  }
77
77
  }
78
78
 
79
+ /// The instrumentation coverage library file name.
80
+ #[napi]
81
+ pub const COVERAGE_LIBRARY_FILE_NAME: &str = coverage::LIBRARY_FILE_NAME;
82
+
79
83
  /// Adds per-statement coverage instrumentation to the given Solidity source
80
84
  /// code.
81
85
  #[napi(catch_unwind)]
@@ -83,7 +87,6 @@ pub fn add_statement_coverage_instrumentation(
83
87
  source_code: String,
84
88
  source_id: String,
85
89
  solidity_version: String,
86
- coverage_library_path: String,
87
90
  ) -> napi::Result<InstrumentationResult> {
88
91
  let solidity_version = Version::parse(&solidity_version).map_err(|error| {
89
92
  napi::Error::new(
@@ -92,13 +95,8 @@ pub fn add_statement_coverage_instrumentation(
92
95
  )
93
96
  })?;
94
97
 
95
- let instrumented = coverage::instrument_code(
96
- &source_code,
97
- &source_id,
98
- solidity_version,
99
- &coverage_library_path,
100
- )
101
- .map_err(|error| napi::Error::new(napi::Status::GenericFailure, error))?;
98
+ let instrumented = coverage::instrument_code(&source_code, &source_id, solidity_version)
99
+ .map_err(|error| napi::Error::new(napi::Status::GenericFailure, error))?;
102
100
 
103
101
  instrumented.try_into().map_err(|location| {
104
102
  napi::Error::new(
@@ -167,6 +167,38 @@ pub struct SolidityTestRunnerConfigArgs {
167
167
  /// Test function level config overrides.
168
168
  /// Defaults to none.
169
169
  pub test_function_overrides: Option<Vec<TestFunctionOverride>>,
170
+ /// A list of EIP-712 canonical type definitions that can be referenced by
171
+ /// type name in the `eip712HashType` and `eip712HashStruct` cheatcodes.
172
+ ///
173
+ /// Each entry is an independent, self-contained type definition. A
174
+ /// definition that references nested struct types must inline those
175
+ /// struct definitions, per the EIP-712 `encodeType` spec.
176
+ ///
177
+ /// Only the primary (leftmost) type of each entry is registered by name.
178
+ /// Nested struct types referenced inside an entry are *not* registered
179
+ /// under their own names. To look up a nested struct by name from a
180
+ /// cheatcode, add it as a separate top-level entry whose primary type
181
+ /// is the nested struct.
182
+ ///
183
+ /// The type of a struct is encoded as:
184
+ ///
185
+ /// `name ‖ "(" ‖ member₁ ‖ "," ‖ member₂ ‖ "," ‖ … ‖ memberₙ ")"`
186
+ ///
187
+ /// where each member is written as `type ‖ " " ‖ name`.
188
+ ///
189
+ /// Entries that fail to parse cause a startup error listing every bad
190
+ /// entry.
191
+ ///
192
+ /// Example — to make both `Mail` and `Person` reachable by name:
193
+ ///
194
+ /// ```text
195
+ /// "Mail(Person from,Person to,string contents)Person(address wallet,string name)"
196
+ /// "Person(address wallet,string name)"
197
+ /// ```
198
+ ///
199
+ /// With *only* the first entry, `vm.eip712HashType("Mail")` works but
200
+ /// `vm.eip712HashType("Person")` fails with an unknown-type error.
201
+ pub eip712_canonical_types: Option<Vec<String>>,
170
202
  }
171
203
 
172
204
  impl SolidityTestRunnerConfigArgs {
@@ -215,6 +247,7 @@ impl SolidityTestRunnerConfigArgs {
215
247
  test_pattern,
216
248
  generate_gas_report,
217
249
  test_function_overrides,
250
+ eip712_canonical_types,
218
251
  } = self;
219
252
 
220
253
  let test_pattern = TestFilterConfig {
@@ -294,6 +327,17 @@ impl SolidityTestRunnerConfigArgs {
294
327
  })
295
328
  .transpose()?
296
329
  .unwrap_or_default(),
330
+ eip712_types_by_name: foundry_cheatcodes::parse_eip712_canonical_types(
331
+ eip712_canonical_types.unwrap_or_default(),
332
+ )
333
+ .map_err(|errors| {
334
+ let msg = errors
335
+ .iter()
336
+ .map(ToString::to_string)
337
+ .collect::<Vec<_>>()
338
+ .join("; ");
339
+ napi::Error::new(Status::InvalidArg, msg)
340
+ })?,
297
341
  };
298
342
 
299
343
  let on_collected_coverage_fn = observability.map_or_else(
@@ -876,6 +920,16 @@ pub struct TestFunctionConfigOverride {
876
920
  /// Allow expecting reverts with `expectRevert` at the same callstack depth
877
921
  /// as the test.
878
922
  pub allow_internal_expect_revert: Option<bool>,
923
+ /// Whether to enable isolation of calls for the test. In isolation mode all
924
+ /// top-level calls are executed as a separate transaction in a separate
925
+ /// EVM context, enabling more precise gas accounting and transaction
926
+ /// state changes.
927
+ /// Ignored when gas reporting is enabled, as isolation is required for
928
+ /// accurate gas measurements.
929
+ pub isolate: Option<bool>,
930
+ /// The EVM version to use for this test, e.g. "Cancun". This will override
931
+ /// the global EVM version.
932
+ pub evm_version: Option<String>,
879
933
  /// Configuration override for fuzz testing.
880
934
  pub fuzz: Option<FuzzConfigOverride>,
881
935
  /// Configuration override for invariant testing.
@@ -886,6 +940,8 @@ impl From<TestFunctionConfigOverride> for edr_solidity_tests::TestFunctionConfig
886
940
  fn from(value: TestFunctionConfigOverride) -> Self {
887
941
  Self {
888
942
  allow_internal_expect_revert: value.allow_internal_expect_revert,
943
+ isolate: value.isolate,
944
+ evm_version: value.evm_version,
889
945
  fuzz: value.fuzz.map(Into::into),
890
946
  invariant: value.invariant.map(Into::into),
891
947
  }
@@ -0,0 +1,23 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+
4
+ import { COVERAGE_LIBRARY_FILE_NAME } from "@nomicfoundation/edr";
5
+
6
+ export interface CoverageLib {
7
+ content: string;
8
+ filename: string;
9
+ }
10
+
11
+ export function getCoverageLibrary(): CoverageLib {
12
+ const packageRoot = path.dirname(require.resolve("@nomicfoundation/edr"));
13
+ const sourcePath = path.join(packageRoot, "coverage.sol");
14
+ if (!fs.existsSync(sourcePath)) {
15
+ throw new Error(
16
+ `Coverage library file not found at ${sourcePath}. It should be bundled with @nomicfoundation/edr.`,
17
+ );
18
+ }
19
+ return {
20
+ content: fs.readFileSync(sourcePath, "utf-8"),
21
+ filename: COVERAGE_LIBRARY_FILE_NAME,
22
+ };
23
+ }