@diamondslab/diamonds-hardhat-foundry 2.3.0 → 2.4.0
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/dist/framework/ForgeCoverageFramework.d.ts +17 -8
- package/dist/framework/ForgeCoverageFramework.d.ts.map +1 -1
- package/dist/framework/ForgeCoverageFramework.js +89 -21
- package/dist/framework/ForgeCoverageFramework.js.map +1 -1
- package/dist/framework/ForgeCoverageFramework.old.d.ts +61 -0
- package/dist/framework/ForgeCoverageFramework.old.d.ts.map +1 -0
- package/dist/framework/ForgeCoverageFramework.old.js +238 -0
- package/dist/framework/ForgeCoverageFramework.old.js.map +1 -0
- package/dist/tasks/coverage.js +88 -107
- package/dist/tasks/coverage.js.map +1 -1
- package/dist/tasks/coverage.old.d.ts +2 -0
- package/dist/tasks/coverage.old.d.ts.map +1 -0
- package/dist/tasks/coverage.old.js +173 -0
- package/dist/tasks/coverage.old.js.map +1 -0
- package/dist/types/config.d.ts +11 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js.map +1 -1
- package/package.json +1 -1
- package/src/framework/ForgeCoverageFramework.ts +125 -22
- package/src/tasks/coverage.ts +88 -137
- package/src/types/config.ts +13 -0
|
@@ -1,37 +1,138 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
2
|
import { HardhatRuntimeEnvironment } from "hardhat/types";
|
|
3
3
|
import { CoverageOptions } from "../types/config";
|
|
4
|
+
import { isFoundryInstalled } from "../utils/foundry";
|
|
4
5
|
import { Logger } from "../utils/logger";
|
|
6
|
+
import { DeploymentManager } from "./DeploymentManager";
|
|
7
|
+
import { HelperGenerator } from "./HelperGenerator";
|
|
5
8
|
|
|
6
9
|
/**
|
|
7
|
-
* ForgeCoverageFramework -
|
|
10
|
+
* ForgeCoverageFramework - Main orchestration class for Forge coverage with Diamonds
|
|
8
11
|
*
|
|
9
|
-
*
|
|
10
|
-
* 1.
|
|
11
|
-
* 2.
|
|
12
|
-
* 3.
|
|
13
|
-
*
|
|
12
|
+
* Coordinates:
|
|
13
|
+
* 1. Diamond deployment via DeploymentManager
|
|
14
|
+
* 2. Helper generation via HelperGenerator
|
|
15
|
+
* 3. Forge coverage execution
|
|
16
|
+
*
|
|
17
|
+
* Mirrors ForgeFuzzingFramework design for consistency and code reuse
|
|
14
18
|
*/
|
|
15
19
|
export class ForgeCoverageFramework {
|
|
16
|
-
|
|
20
|
+
private deploymentManager: DeploymentManager;
|
|
21
|
+
private helperGenerator: HelperGenerator;
|
|
22
|
+
|
|
23
|
+
constructor(private hre: HardhatRuntimeEnvironment) {
|
|
24
|
+
this.deploymentManager = new DeploymentManager(hre);
|
|
25
|
+
this.helperGenerator = new HelperGenerator(hre);
|
|
26
|
+
}
|
|
17
27
|
|
|
18
28
|
/**
|
|
19
|
-
* Run
|
|
29
|
+
* Run complete Forge coverage workflow
|
|
30
|
+
*
|
|
31
|
+
* Workflow:
|
|
32
|
+
* 1. Validate Foundry installation
|
|
33
|
+
* 2. Deploy or reuse Diamond
|
|
34
|
+
* 3. Generate Solidity helpers
|
|
35
|
+
* 4. Run forge coverage with options
|
|
20
36
|
*
|
|
21
37
|
* @param options - Coverage execution options
|
|
22
|
-
* @returns Promise<boolean> - true if coverage succeeds
|
|
38
|
+
* @returns Promise<boolean> - true if coverage succeeds
|
|
23
39
|
*/
|
|
24
40
|
async runCoverage(options: CoverageOptions = {}): Promise<boolean> {
|
|
25
|
-
|
|
41
|
+
const {
|
|
42
|
+
diamondName = "ExampleDiamond",
|
|
43
|
+
networkName = "hardhat",
|
|
44
|
+
force = false,
|
|
45
|
+
skipDeployment = false,
|
|
46
|
+
skipHelpers = false,
|
|
47
|
+
writeDeployedDiamondData = false,
|
|
48
|
+
} = options;
|
|
49
|
+
|
|
50
|
+
Logger.section("Running Forge Coverage with Diamond");
|
|
51
|
+
|
|
52
|
+
// Step 1: Validate Foundry
|
|
53
|
+
if (!isFoundryInstalled()) {
|
|
54
|
+
Logger.error(
|
|
55
|
+
"Foundry is not installed. Please install it: https://book.getfoundry.sh/getting-started/installation"
|
|
56
|
+
);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
26
59
|
|
|
27
60
|
try {
|
|
28
|
-
//
|
|
29
|
-
|
|
61
|
+
// Step 2: Ensure Diamond deployment
|
|
62
|
+
if (!skipDeployment) {
|
|
63
|
+
Logger.section("Step 1/3: Ensuring Diamond Deployment");
|
|
64
|
+
await this.deploymentManager.ensureDeployment(
|
|
65
|
+
diamondName,
|
|
66
|
+
networkName,
|
|
67
|
+
force,
|
|
68
|
+
writeDeployedDiamondData
|
|
69
|
+
);
|
|
70
|
+
} else {
|
|
71
|
+
Logger.info("Skipping deployment (using existing)");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Step 3: Generate helpers
|
|
75
|
+
if (!skipHelpers) {
|
|
76
|
+
Logger.section("Step 2/3: Generating Solidity Helpers");
|
|
77
|
+
|
|
78
|
+
const deployment = await this.deploymentManager.getDeployment(
|
|
79
|
+
diamondName,
|
|
80
|
+
networkName
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
if (!deployment) {
|
|
84
|
+
Logger.warn("⚠ No deployment record found");
|
|
85
|
+
if (!skipDeployment) {
|
|
86
|
+
Logger.info("ℹ Using cached deployment (ephemeral)");
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
Logger.info("Using deployment record");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const provider = this.hre.ethers.provider;
|
|
93
|
+
const network = await provider.getNetwork();
|
|
94
|
+
const chainId = Number(network.chainId);
|
|
95
|
+
|
|
96
|
+
const deploymentData = deployment
|
|
97
|
+
? deployment.getDeployedDiamondData()
|
|
98
|
+
: await this.deploymentManager
|
|
99
|
+
.ensureDeployment(diamondName, networkName, false, false)
|
|
100
|
+
.then((d) => d.getDeployedDiamondData());
|
|
101
|
+
|
|
102
|
+
await this.helperGenerator.generateDeploymentHelpers(
|
|
103
|
+
diamondName,
|
|
104
|
+
networkName,
|
|
105
|
+
chainId,
|
|
106
|
+
deploymentData,
|
|
107
|
+
deployment || undefined
|
|
108
|
+
);
|
|
109
|
+
} else {
|
|
110
|
+
Logger.info("Skipping helper generation");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Step 4: Run coverage
|
|
114
|
+
Logger.section("Step 3/3: Running Forge Coverage");
|
|
115
|
+
|
|
116
|
+
// Get fork URL for network (same pattern as ForgeFuzzingFramework)
|
|
117
|
+
const provider = this.hre.ethers.provider;
|
|
118
|
+
let forkUrl: string;
|
|
119
|
+
|
|
120
|
+
if (networkName !== "hardhat") {
|
|
121
|
+
forkUrl = (provider as any).connection?.url || "http://127.0.0.1:8545";
|
|
122
|
+
} else {
|
|
123
|
+
forkUrl = "http://127.0.0.1:8545";
|
|
124
|
+
Logger.warn(
|
|
125
|
+
"⚠️ Network is \"hardhat\" - defaulting to localhost fork: http://127.0.0.1:8545"
|
|
126
|
+
);
|
|
127
|
+
Logger.warn("💡 Make sure Hardhat node is running: npx hardhat node");
|
|
128
|
+
Logger.warn("💡 Or specify network explicitly: --network localhost");
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const args = this.buildCoverageCommand({ ...options, forkUrl });
|
|
30
132
|
|
|
31
133
|
Logger.info(`Executing: forge coverage ${args.join(" ")}`);
|
|
32
|
-
Logger.info("⏳ Running coverage analysis (this may take a while)
|
|
134
|
+
Logger.info("⏳ Running coverage analysis (this may take a while)...");
|
|
33
135
|
|
|
34
|
-
// Execute forge coverage
|
|
35
136
|
const success = await this.executeForge(args);
|
|
36
137
|
|
|
37
138
|
if (success) {
|
|
@@ -42,7 +143,7 @@ export class ForgeCoverageFramework {
|
|
|
42
143
|
|
|
43
144
|
return success;
|
|
44
145
|
} catch (error: any) {
|
|
45
|
-
Logger.error(`Coverage execution
|
|
146
|
+
Logger.error(`Coverage execution failed: ${error.message}`);
|
|
46
147
|
return false;
|
|
47
148
|
}
|
|
48
149
|
}
|
|
@@ -80,9 +181,9 @@ export class ForgeCoverageFramework {
|
|
|
80
181
|
|
|
81
182
|
// Multiple --report flags
|
|
82
183
|
if (options.report && options.report.length > 0) {
|
|
83
|
-
options.report
|
|
184
|
+
for (const reportType of options.report) {
|
|
84
185
|
args.push("--report", reportType);
|
|
85
|
-
}
|
|
186
|
+
}
|
|
86
187
|
}
|
|
87
188
|
|
|
88
189
|
if (options.reportFile) {
|
|
@@ -266,12 +367,13 @@ export class ForgeCoverageFramework {
|
|
|
266
367
|
*/
|
|
267
368
|
private executeForge(args: string[]): Promise<boolean> {
|
|
268
369
|
return new Promise((resolve, reject) => {
|
|
269
|
-
const
|
|
370
|
+
const forge = spawn("forge", ["coverage", ...args], {
|
|
270
371
|
cwd: this.hre.config.paths.root,
|
|
271
|
-
stdio: "inherit",
|
|
372
|
+
stdio: "inherit",
|
|
373
|
+
shell: true,
|
|
272
374
|
});
|
|
273
375
|
|
|
274
|
-
|
|
376
|
+
forge.on("close", (code) => {
|
|
275
377
|
if (code === 0) {
|
|
276
378
|
resolve(true);
|
|
277
379
|
} else {
|
|
@@ -279,8 +381,9 @@ export class ForgeCoverageFramework {
|
|
|
279
381
|
}
|
|
280
382
|
});
|
|
281
383
|
|
|
282
|
-
|
|
283
|
-
|
|
384
|
+
forge.on("error", (error) => {
|
|
385
|
+
Logger.error(`Failed to execute forge: ${error.message}`);
|
|
386
|
+
reject(error);
|
|
284
387
|
});
|
|
285
388
|
});
|
|
286
389
|
}
|
package/src/tasks/coverage.ts
CHANGED
|
@@ -11,18 +11,20 @@ import { Logger } from "../utils/logger";
|
|
|
11
11
|
* - Runs forge coverage with specified options
|
|
12
12
|
*
|
|
13
13
|
* Use Hardhat's built-in --network flag to specify the network
|
|
14
|
+
*
|
|
15
|
+
* Design: Mirrors diamonds-forge:test task structure for consistency
|
|
14
16
|
*/
|
|
15
17
|
task("diamonds-forge:coverage", "Run forge coverage for Diamond contracts")
|
|
16
|
-
.
|
|
18
|
+
.addOptionalParam(
|
|
17
19
|
"diamondName",
|
|
18
20
|
"Name of the Diamond to analyze",
|
|
19
|
-
|
|
21
|
+
"ExampleDiamond",
|
|
20
22
|
types.string
|
|
21
23
|
)
|
|
22
24
|
// Report options
|
|
23
25
|
.addOptionalParam(
|
|
24
26
|
"report",
|
|
25
|
-
"Report type (summary, lcov, debug, bytecode) -
|
|
27
|
+
"Report type (summary, lcov, debug, bytecode) - comma-separated for multiple",
|
|
26
28
|
undefined,
|
|
27
29
|
types.string
|
|
28
30
|
)
|
|
@@ -34,7 +36,7 @@ task("diamonds-forge:coverage", "Run forge coverage for Diamond contracts")
|
|
|
34
36
|
)
|
|
35
37
|
.addOptionalParam(
|
|
36
38
|
"lcovVersion",
|
|
37
|
-
"LCOV format version",
|
|
39
|
+
"LCOV format version (v1 or v2)",
|
|
38
40
|
undefined,
|
|
39
41
|
types.string
|
|
40
42
|
)
|
|
@@ -44,50 +46,50 @@ task("diamonds-forge:coverage", "Run forge coverage for Diamond contracts")
|
|
|
44
46
|
// Test filtering
|
|
45
47
|
.addOptionalParam(
|
|
46
48
|
"matchTest",
|
|
47
|
-
"Run tests matching pattern
|
|
49
|
+
"Run tests matching pattern",
|
|
48
50
|
undefined,
|
|
49
51
|
types.string
|
|
50
52
|
)
|
|
51
53
|
.addOptionalParam(
|
|
52
54
|
"noMatchTest",
|
|
53
|
-
"Exclude tests matching pattern
|
|
55
|
+
"Exclude tests matching pattern",
|
|
54
56
|
undefined,
|
|
55
57
|
types.string
|
|
56
58
|
)
|
|
57
59
|
.addOptionalParam(
|
|
58
60
|
"matchContract",
|
|
59
|
-
"Run contracts matching pattern
|
|
61
|
+
"Run contracts matching pattern",
|
|
60
62
|
undefined,
|
|
61
63
|
types.string
|
|
62
64
|
)
|
|
63
65
|
.addOptionalParam(
|
|
64
66
|
"noMatchContract",
|
|
65
|
-
"Exclude contracts matching pattern
|
|
67
|
+
"Exclude contracts matching pattern",
|
|
66
68
|
undefined,
|
|
67
69
|
types.string
|
|
68
70
|
)
|
|
69
71
|
.addOptionalParam(
|
|
70
72
|
"matchPath",
|
|
71
|
-
"Run files matching glob
|
|
73
|
+
"Run files matching glob",
|
|
72
74
|
undefined,
|
|
73
75
|
types.string
|
|
74
76
|
)
|
|
75
77
|
.addOptionalParam(
|
|
76
78
|
"noMatchPath",
|
|
77
|
-
"Exclude files matching glob
|
|
79
|
+
"Exclude files matching glob",
|
|
78
80
|
undefined,
|
|
79
81
|
types.string
|
|
80
82
|
)
|
|
81
83
|
.addOptionalParam(
|
|
82
84
|
"noMatchCoverage",
|
|
83
|
-
"Exclude files from coverage report
|
|
85
|
+
"Exclude files from coverage report",
|
|
84
86
|
undefined,
|
|
85
87
|
types.string
|
|
86
88
|
)
|
|
87
89
|
// Display options
|
|
88
90
|
.addOptionalParam(
|
|
89
91
|
"verbosity",
|
|
90
|
-
"Verbosity level (1-5
|
|
92
|
+
"Verbosity level (1-5)",
|
|
91
93
|
undefined,
|
|
92
94
|
types.int
|
|
93
95
|
)
|
|
@@ -141,7 +143,7 @@ task("diamonds-forge:coverage", "Run forge coverage for Diamond contracts")
|
|
|
141
143
|
types.string
|
|
142
144
|
)
|
|
143
145
|
.addFlag("ffi", "Enable FFI cheatcode")
|
|
144
|
-
// Build options
|
|
146
|
+
// Build/deployment options
|
|
145
147
|
.addFlag("force", "Force recompile and redeploy")
|
|
146
148
|
.addFlag("noCache", "Disable cache")
|
|
147
149
|
.addFlag("optimize", "Enable Solidity optimizer")
|
|
@@ -152,151 +154,100 @@ task("diamonds-forge:coverage", "Run forge coverage for Diamond contracts")
|
|
|
152
154
|
types.int
|
|
153
155
|
)
|
|
154
156
|
.addFlag("viaIr", "Use Yul IR compilation")
|
|
157
|
+
.addFlag("skipDeployment", "Skip Diamond deployment step")
|
|
158
|
+
.addFlag("skipHelpers", "Skip helper generation step")
|
|
159
|
+
.addFlag("saveDeployment", "Write deployment data to file for reuse")
|
|
155
160
|
.setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => {
|
|
156
161
|
Logger.section("Running Forge Coverage with Diamond");
|
|
157
162
|
|
|
158
163
|
const diamondName = taskArgs.diamondName;
|
|
159
164
|
const networkName = hre.network.name;
|
|
160
165
|
|
|
161
|
-
// Validate required parameters
|
|
162
|
-
if (!diamondName) {
|
|
163
|
-
Logger.error("--diamond-name is required");
|
|
164
|
-
process.exitCode = 1;
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
166
|
Logger.info(`Diamond: ${diamondName}`);
|
|
169
167
|
Logger.info(`Network: ${networkName}`);
|
|
170
168
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const deploymentManager = new DeploymentManager(hre);
|
|
180
|
-
|
|
181
|
-
await deploymentManager.ensureDeployment(
|
|
182
|
-
diamondName,
|
|
183
|
-
networkName,
|
|
184
|
-
taskArgs.force || false,
|
|
185
|
-
false // Don't write deployment data for coverage (ephemeral by default)
|
|
186
|
-
);
|
|
187
|
-
|
|
188
|
-
// Step 2: Generate helpers
|
|
189
|
-
Logger.section("Step 2/3: Generating Solidity Helpers");
|
|
190
|
-
|
|
191
|
-
const deployment = await deploymentManager.getDeployment(
|
|
192
|
-
diamondName,
|
|
193
|
-
networkName
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
if (!deployment) {
|
|
197
|
-
Logger.error("No deployment found. Cannot generate helpers.");
|
|
198
|
-
process.exitCode = 1;
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const provider = hre.ethers.provider;
|
|
203
|
-
const network = await provider.getNetwork();
|
|
204
|
-
const chainId = Number(network.chainId);
|
|
205
|
-
const deploymentData = deployment.getDeployedDiamondData();
|
|
206
|
-
|
|
207
|
-
const helperGenerator = new HelperGenerator(hre);
|
|
208
|
-
await helperGenerator.generateDeploymentHelpers(
|
|
209
|
-
diamondName,
|
|
210
|
-
networkName,
|
|
211
|
-
chainId,
|
|
212
|
-
deploymentData,
|
|
213
|
-
deployment
|
|
214
|
-
);
|
|
215
|
-
|
|
216
|
-
// Step 3: Run coverage
|
|
217
|
-
Logger.section("Step 3/3: Running Forge Coverage");
|
|
218
|
-
|
|
219
|
-
// Construct fork URL for network
|
|
220
|
-
// Coverage requires forking from a running network to access deployed contracts
|
|
221
|
-
let forkUrl: string;
|
|
222
|
-
if (networkName !== "hardhat") {
|
|
223
|
-
// Use the configured network's URL
|
|
224
|
-
forkUrl = (provider as any)._hardhatProvider?._wrapped?.url || "http://127.0.0.1:8545";
|
|
225
|
-
Logger.info(`Forking from ${networkName}: ${forkUrl}`);
|
|
226
|
-
} else {
|
|
227
|
-
// Default to localhost for hardhat network
|
|
228
|
-
// This assumes user has `npx hardhat node` running
|
|
229
|
-
forkUrl = "http://127.0.0.1:8545";
|
|
230
|
-
Logger.warn(`⚠️ Network is "${networkName}" - defaulting to localhost fork: ${forkUrl}`);
|
|
231
|
-
Logger.warn(`💡 Make sure Hardhat node is running: npx hardhat node`);
|
|
232
|
-
Logger.warn(`💡 Or specify network explicitly: --network localhost`);
|
|
233
|
-
}
|
|
169
|
+
// Log key options
|
|
170
|
+
if (taskArgs.report) Logger.info(`Report: ${taskArgs.report}`);
|
|
171
|
+
if (taskArgs.reportFile) Logger.info(`Report File: ${taskArgs.reportFile}`);
|
|
172
|
+
if (taskArgs.matchTest) Logger.info(`Match Test: ${taskArgs.matchTest}`);
|
|
173
|
+
if (taskArgs.matchContract) Logger.info(`Match Contract: ${taskArgs.matchContract}`);
|
|
174
|
+
if (taskArgs.skipDeployment) Logger.info("Skip Deployment: true");
|
|
175
|
+
if (taskArgs.skipHelpers) Logger.info("Skip Helpers: true");
|
|
176
|
+
if (taskArgs.saveDeployment) Logger.info("Save Deployment: true");
|
|
234
177
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
178
|
+
// Lazy-load framework to avoid circular dependency during config loading
|
|
179
|
+
const { ForgeCoverageFramework } = await import(
|
|
180
|
+
"../framework/ForgeCoverageFramework.js"
|
|
181
|
+
);
|
|
182
|
+
type CoverageOptions = Parameters<
|
|
183
|
+
InstanceType<typeof ForgeCoverageFramework>["runCoverage"]
|
|
184
|
+
>[0];
|
|
238
185
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
186
|
+
// Parse comma-separated report types
|
|
187
|
+
const reportTypes = taskArgs.report
|
|
188
|
+
? taskArgs.report.split(",").map((r: string) => r.trim())
|
|
189
|
+
: undefined;
|
|
243
190
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
191
|
+
// Create coverage options (matches test.ts pattern)
|
|
192
|
+
const options: CoverageOptions = {
|
|
193
|
+
diamondName,
|
|
194
|
+
networkName,
|
|
195
|
+
force: taskArgs.force,
|
|
196
|
+
skipDeployment: taskArgs.skipDeployment,
|
|
197
|
+
skipHelpers: taskArgs.skipHelpers,
|
|
198
|
+
writeDeployedDiamondData: taskArgs.saveDeployment,
|
|
199
|
+
// Report options
|
|
200
|
+
report: reportTypes,
|
|
201
|
+
reportFile: taskArgs.reportFile,
|
|
202
|
+
lcovVersion: taskArgs.lcovVersion,
|
|
203
|
+
includeLibs: taskArgs.includeLibs,
|
|
204
|
+
excludeTests: taskArgs.excludeTests,
|
|
205
|
+
irMinimum: taskArgs.irMinimum,
|
|
206
|
+
// Test filtering
|
|
207
|
+
matchTest: taskArgs.matchTest,
|
|
208
|
+
noMatchTest: taskArgs.noMatchTest,
|
|
209
|
+
matchContract: taskArgs.matchContract,
|
|
210
|
+
noMatchContract: taskArgs.noMatchContract,
|
|
211
|
+
matchPath: taskArgs.matchPath,
|
|
212
|
+
noMatchPath: taskArgs.noMatchPath,
|
|
213
|
+
noMatchCoverage: taskArgs.noMatchCoverage,
|
|
214
|
+
// Display options
|
|
215
|
+
verbosity: taskArgs.verbosity,
|
|
216
|
+
quiet: taskArgs.quiet,
|
|
217
|
+
json: taskArgs.json,
|
|
218
|
+
md: taskArgs.md,
|
|
219
|
+
color: taskArgs.color,
|
|
220
|
+
// Test execution
|
|
221
|
+
threads: taskArgs.threads,
|
|
222
|
+
fuzzRuns: taskArgs.fuzzRuns,
|
|
223
|
+
fuzzSeed: taskArgs.fuzzSeed,
|
|
224
|
+
failFast: taskArgs.failFast,
|
|
225
|
+
allowFailure: taskArgs.allowFailure,
|
|
226
|
+
// EVM options
|
|
227
|
+
forkBlockNumber: taskArgs.forkBlockNumber,
|
|
228
|
+
initialBalance: taskArgs.initialBalance,
|
|
229
|
+
sender: taskArgs.sender,
|
|
230
|
+
ffi: taskArgs.ffi,
|
|
231
|
+
// Build options
|
|
232
|
+
noCache: taskArgs.noCache,
|
|
233
|
+
optimize: taskArgs.optimize,
|
|
234
|
+
optimizerRuns: taskArgs.optimizerRuns,
|
|
235
|
+
viaIr: taskArgs.viaIr,
|
|
236
|
+
};
|
|
251
237
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
noMatchTest: taskArgs.noMatchTest,
|
|
255
|
-
matchContract: taskArgs.matchContract,
|
|
256
|
-
noMatchContract: taskArgs.noMatchContract,
|
|
257
|
-
matchPath: taskArgs.matchPath,
|
|
258
|
-
noMatchPath: taskArgs.noMatchPath,
|
|
259
|
-
noMatchCoverage: taskArgs.noMatchCoverage,
|
|
238
|
+
// Run coverage using the framework (same pattern as test.ts)
|
|
239
|
+
const framework = new ForgeCoverageFramework(hre);
|
|
260
240
|
|
|
261
|
-
|
|
262
|
-
verbosity: taskArgs.verbosity,
|
|
263
|
-
quiet: taskArgs.quiet,
|
|
264
|
-
json: taskArgs.json,
|
|
265
|
-
md: taskArgs.md,
|
|
266
|
-
color: taskArgs.color as "auto" | "always" | "never" | undefined,
|
|
267
|
-
|
|
268
|
-
// Test execution options
|
|
269
|
-
threads: taskArgs.threads,
|
|
270
|
-
fuzzRuns: taskArgs.fuzzRuns,
|
|
271
|
-
fuzzSeed: taskArgs.fuzzSeed,
|
|
272
|
-
failFast: taskArgs.failFast,
|
|
273
|
-
allowFailure: taskArgs.allowFailure,
|
|
274
|
-
|
|
275
|
-
// EVM options
|
|
276
|
-
forkBlockNumber: taskArgs.forkBlockNumber,
|
|
277
|
-
initialBalance: taskArgs.initialBalance,
|
|
278
|
-
sender: taskArgs.sender,
|
|
279
|
-
ffi: taskArgs.ffi,
|
|
280
|
-
|
|
281
|
-
// Build options
|
|
282
|
-
force: taskArgs.force,
|
|
283
|
-
noCache: taskArgs.noCache,
|
|
284
|
-
optimize: taskArgs.optimize,
|
|
285
|
-
optimizerRuns: taskArgs.optimizerRuns,
|
|
286
|
-
viaIr: taskArgs.viaIr,
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
// Run coverage
|
|
290
|
-
const framework = new ForgeCoverageFramework(hre);
|
|
241
|
+
try {
|
|
291
242
|
const success = await framework.runCoverage(options);
|
|
292
243
|
|
|
293
244
|
if (success) {
|
|
294
245
|
Logger.section("Coverage Analysis Complete");
|
|
295
|
-
Logger.success("Coverage
|
|
246
|
+
Logger.success("✅ Coverage completed successfully!");
|
|
296
247
|
process.exitCode = 0;
|
|
297
248
|
} else {
|
|
298
249
|
Logger.section("Coverage Analysis Complete");
|
|
299
|
-
Logger.error("Coverage analysis failed");
|
|
250
|
+
Logger.error("❌ Coverage analysis failed");
|
|
300
251
|
process.exitCode = 1;
|
|
301
252
|
}
|
|
302
253
|
} catch (error: any) {
|
package/src/types/config.ts
CHANGED
|
@@ -66,8 +66,21 @@ export type ColorMode = "auto" | "always" | "never";
|
|
|
66
66
|
/**
|
|
67
67
|
* Coverage options for forge coverage command
|
|
68
68
|
* Maps to all available forge coverage command-line options
|
|
69
|
+
* Plus orchestration options for Diamond deployment and helpers
|
|
69
70
|
*/
|
|
70
71
|
export interface CoverageOptions {
|
|
72
|
+
// Orchestration options (matching ForgeFuzzingFramework pattern)
|
|
73
|
+
/** Name of the Diamond to analyze */
|
|
74
|
+
diamondName?: string;
|
|
75
|
+
/** Network name for deployment (hardhat, localhost, etc.) */
|
|
76
|
+
networkName?: string;
|
|
77
|
+
/** Skip Diamond deployment step */
|
|
78
|
+
skipDeployment?: boolean;
|
|
79
|
+
/** Skip helper generation step */
|
|
80
|
+
skipHelpers?: boolean;
|
|
81
|
+
/** Write deployment data to file for reuse */
|
|
82
|
+
writeDeployedDiamondData?: boolean;
|
|
83
|
+
|
|
71
84
|
// Report options
|
|
72
85
|
/** Report type(s) - can specify multiple */
|
|
73
86
|
report?: CoverageReportType[];
|