@nomicfoundation/edr 0.12.0-next.31 → 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 +38 -0
- package/dist/src/ts/coverage.d.ts +6 -0
- package/dist/src/ts/coverage.d.ts.map +1 -0
- package/dist/src/ts/coverage.js +51 -0
- package/dist/src/ts/coverage.js.map +1 -0
- package/dist/src/ts/solidity_tests.d.ts +17 -0
- package/dist/src/ts/solidity_tests.d.ts.map +1 -0
- package/dist/src/ts/solidity_tests.js +32 -0
- package/dist/src/ts/solidity_tests.js.map +1 -0
- package/index.d.ts +37 -1
- package/index.js +2 -1
- package/package.json +13 -10
- package/src/instrument.rs +6 -8
- package/src/solidity_tests/config.rs +44 -0
- package/src/ts/coverage.ts +23 -0
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 @@
|
|
|
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
|
|
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 {
|
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.
|
|
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.
|
|
62
|
-
"@nomicfoundation/edr-darwin-x64": "0.12.0-next.
|
|
63
|
-
"@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.
|
|
64
|
-
"@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.
|
|
65
|
-
"@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.
|
|
66
|
-
"@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.
|
|
67
|
-
"@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.
|
|
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
|
-
|
|
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(
|
|
@@ -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
|
+
}
|