@diamondslab/diamonds-hardhat-foundry 1.0.3 → 2.2.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +249 -0
  2. package/README.md +650 -4
  3. package/contracts/DiamondABILoader.sol +329 -0
  4. package/contracts/DiamondForgeHelpers.sol +309 -85
  5. package/contracts/DiamondFuzzBase.sol +322 -114
  6. package/dist/foundry.d.ts +28 -0
  7. package/dist/foundry.d.ts.map +1 -1
  8. package/dist/foundry.js +82 -1
  9. package/dist/foundry.js.map +1 -1
  10. package/dist/framework/DeploymentManager.d.ts +10 -11
  11. package/dist/framework/DeploymentManager.d.ts.map +1 -1
  12. package/dist/framework/DeploymentManager.js +56 -45
  13. package/dist/framework/DeploymentManager.js.map +1 -1
  14. package/dist/framework/ForgeFuzzingFramework.d.ts +4 -0
  15. package/dist/framework/ForgeFuzzingFramework.d.ts.map +1 -1
  16. package/dist/framework/ForgeFuzzingFramework.js +16 -2
  17. package/dist/framework/ForgeFuzzingFramework.js.map +1 -1
  18. package/dist/framework/HelperGenerator.d.ts.map +1 -1
  19. package/dist/framework/HelperGenerator.js +11 -0
  20. package/dist/framework/HelperGenerator.js.map +1 -1
  21. package/dist/index.d.ts +0 -3
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +0 -8
  24. package/dist/index.js.map +1 -1
  25. package/dist/tasks/deploy.js +11 -4
  26. package/dist/tasks/deploy.js.map +1 -1
  27. package/dist/tasks/generate-helpers.js +6 -4
  28. package/dist/tasks/generate-helpers.js.map +1 -1
  29. package/dist/tasks/init.js +3 -2
  30. package/dist/tasks/init.js.map +1 -1
  31. package/dist/tasks/test.js +13 -2
  32. package/dist/tasks/test.js.map +1 -1
  33. package/dist/types/hardhat.d.ts +1 -1
  34. package/dist/types/hardhat.d.ts.map +1 -1
  35. package/dist/types/hardhat.js +1 -0
  36. package/dist/types/hardhat.js.map +1 -1
  37. package/dist/utils/foundry.d.ts +1 -0
  38. package/dist/utils/foundry.d.ts.map +1 -1
  39. package/dist/utils/foundry.js +3 -0
  40. package/dist/utils/foundry.js.map +1 -1
  41. package/package.json +5 -3
  42. package/src/foundry.ts +104 -0
  43. package/src/framework/DeploymentManager.ts +74 -69
  44. package/src/framework/ForgeFuzzingFramework.ts +23 -1
  45. package/src/framework/HelperGenerator.ts +13 -0
  46. package/src/index.ts +0 -5
  47. package/src/tasks/deploy.ts +14 -3
  48. package/src/tasks/generate-helpers.ts +6 -2
  49. package/src/tasks/init.ts +3 -1
  50. package/src/tasks/test.ts +12 -1
  51. package/src/templates/ExampleFuzzTest.t.sol.template +26 -17
  52. package/src/templates/ExampleIntegrationTest.t.sol.template +9 -1
  53. package/src/templates/ExampleUnitTest.t.sol.template +7 -1
  54. package/src/types/hardhat.ts +1 -1
  55. package/src/utils/foundry.ts +5 -0
  56. package/dist/templates/DiamondDeployment.sol.template +0 -38
  57. package/dist/templates/ExampleFuzzTest.t.sol.template +0 -109
  58. package/dist/templates/ExampleIntegrationTest.t.sol.template +0 -79
  59. package/dist/templates/ExampleUnitTest.t.sol.template +0 -59
package/README.md CHANGED
@@ -2,9 +2,13 @@
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/@diamondslab%2Fdiamonds-hardhat-foundry.svg)](https://www.npmjs.com/package/@diamondslab/diamonds-hardhat-foundry)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Tests](https://img.shields.io/badge/tests-141%20passing-brightgreen)](https://github.com/DiamondsLab/diamonds-hardhat-foundry)
6
+ [![Test Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen)](https://github.com/DiamondsLab/diamonds-hardhat-foundry)
5
7
 
6
8
  Hardhat plugin that seamlessly integrates Foundry testing with [ERC-2535 Diamond](https://eips.ethereum.org/EIPS/eip-2535) proxy contracts. This plugin provides deployment helpers, test scaffolding, and automated test generation for Diamond-based smart contracts using Foundry's powerful testing framework.
7
9
 
10
+ **Production Ready**: 141/141 tests passing (100% success rate) with comprehensive coverage across unit, integration, fuzz, and invariant testing.
11
+
8
12
  ## Features
9
13
 
10
14
  - 🚀 **Automated Diamond Deployment** - Deploy Diamond contracts with a single command
@@ -30,14 +34,18 @@ pnpm add -D @diamondslab/diamonds-hardhat-foundry
30
34
 
31
35
  - **Foundry**: Install from [getfoundry.sh](https://getfoundry.sh/)
32
36
  - **Hardhat**: `^2.26.0` or later
33
- - **Peer Dependencies**:
37
+ - **Required Peer Dependencies**:
34
38
  - `@diamondslab/diamonds` - Core Diamond deployment library
35
- - `@diamondslab/hardhat-diamonds` - Hardhat Diamond configuration helpers
39
+ - `@diamondslab/hardhat-diamonds` - Hardhat Diamond configuration and LocalDiamondDeployer
40
+ - `@nomicfoundation/hardhat-ethers` - Ethers.js integration
41
+ - `ethers` - Ethereum library
36
42
 
37
43
  ```bash
38
- npm install --save-dev @diamondslab/diamonds @diamondslab/hardhat-diamonds hardhat
44
+ npm install --save-dev @diamondslab/diamonds @diamondslab/hardhat-diamonds @nomicfoundation/hardhat-ethers ethers hardhat
39
45
  ```
40
46
 
47
+ > **Note**: Version 2.0.0+ requires `@diamondslab/hardhat-diamonds` as a peer dependency for LocalDiamondDeployer. See [MIGRATION.md](./MIGRATION.md) for upgrade instructions from v1.x.
48
+
41
49
  ## Quick Start
42
50
 
43
51
  ### 1. Configure Hardhat
@@ -99,6 +107,156 @@ This generates `test/foundry/helpers/DiamondDeployment.sol` with:
99
107
  - All facet addresses
100
108
  - Helper functions for test setup
101
109
 
110
+ ## Importing Helper Contracts
111
+
112
+ Version 2.0.0+ provides importable Solidity helper contracts for your tests:
113
+
114
+ ### DiamondFuzzBase - Base Contract for Fuzz Tests
115
+
116
+ Extend `DiamondFuzzBase` to create Diamond fuzz tests with built-in helpers:
117
+
118
+ ```solidity
119
+ // SPDX-License-Identifier: MIT
120
+ pragma solidity ^0.8.0;
121
+
122
+ import "forge-std/Test.sol";
123
+ import "@diamondslab/diamonds-hardhat-foundry/contracts/DiamondFuzzBase.sol";
124
+ import "../helpers/DiamondDeployment.sol";
125
+
126
+ contract MyDiamondFuzzTest is DiamondFuzzBase {
127
+ /// Override to load your deployed Diamond
128
+ function _loadDiamondAddress() internal view override returns (address) {
129
+ return DiamondDeployment.diamond();
130
+ }
131
+
132
+ function setUp() public override {
133
+ super.setUp(); // Loads Diamond and ABI
134
+ // Your additional setup
135
+ }
136
+
137
+ function testFuzz_SomeFunction(address user, uint256 amount) public {
138
+ // Use built-in helpers
139
+ vm.assume(DiamondForgeHelpers.isValidTestAddress(user));
140
+ vm.assume(DiamondForgeHelpers.isValidTestAmount(amount));
141
+
142
+ bytes4 selector = bytes4(keccak256("transfer(address,uint256)"));
143
+ bytes memory data = abi.encode(user, amount);
144
+ (bool success, ) = _callDiamond(selector, data);
145
+ assertTrue(success);
146
+ }
147
+ }
148
+ ```
149
+
150
+ **Built-in DiamondFuzzBase Methods:**
151
+
152
+ - `_loadDiamondAddress()` - Override to provide Diamond address
153
+ - `_getDiamondABIPath()` - Override to customize ABI file path
154
+ - `_callDiamond(selector, data)` - Call Diamond function
155
+ - `_callDiamondWithValue(selector, data, value)` - Call payable function
156
+ - `_expectDiamondRevert(selector, data, expectedError)` - Test reverts
157
+ - `_verifyFacetRouting(selector, expectedFacet)` - Check selector routing
158
+ - `_measureDiamondGas(selector, data)` - Measure gas consumption
159
+ - `_getDiamondOwner()` - Get Diamond owner address
160
+ - `_hasRole(role, account)` - Check role-based access control
161
+ - `_grantRole(role, account)` - Grant role (requires permissions)
162
+ - `_revokeRole(role, account)` - Revoke role
163
+
164
+ ### DiamondForgeHelpers - Utility Library
165
+
166
+ Use `DiamondForgeHelpers` for validation, assertions, and DiamondLoupe queries:
167
+
168
+ ```solidity
169
+ import "@diamondslab/diamonds-hardhat-foundry/contracts/DiamondForgeHelpers.sol";
170
+
171
+ contract MyTest is Test {
172
+ using DiamondForgeHelpers for address;
173
+
174
+ function setUp() public {
175
+ address diamond = deployDiamond();
176
+
177
+ // Validate Diamond deployment
178
+ DiamondForgeHelpers.assertValidDiamond(diamond);
179
+
180
+ // Validate facet
181
+ address facet = getFacet();
182
+ DiamondForgeHelpers.assertValidFacet(facet, "MyFacet");
183
+ }
184
+
185
+ function testFuzz_ValidInputs(address addr, uint256 amount) public {
186
+ // Filter fuzz inputs
187
+ vm.assume(DiamondForgeHelpers.isValidTestAddress(addr));
188
+ vm.assume(DiamondForgeHelpers.isValidTestAmount(amount));
189
+ // Your test logic
190
+ }
191
+
192
+ function testSelectorRouting() public {
193
+ bytes4 selector = bytes4(keccak256("someFunction()"));
194
+
195
+ // Assert selector exists
196
+ DiamondForgeHelpers.assertSelectorExists(diamond, selector);
197
+
198
+ // Assert routing to expected facet
199
+ DiamondForgeHelpers.assertSelectorRouting(diamond, selector, expectedFacet);
200
+
201
+ // Get facet address
202
+ address facet = DiamondForgeHelpers.getFacetAddress(diamond, selector);
203
+ }
204
+ }
205
+ ```
206
+
207
+ **DiamondForgeHelpers Functions:**
208
+
209
+ - `assertValidDiamond(address)` - Validate Diamond deployment
210
+ - `assertValidFacet(address, name)` - Validate facet deployment
211
+ - `isValidTestAddress(address)` - Filter fuzz addresses
212
+ - `isValidTestAmount(uint256)` - Filter fuzz amounts
213
+ - `assertSelectorExists(diamond, selector)` - Verify selector registered
214
+ - `assertSelectorRouting(diamond, selector, facet)` - Verify routing
215
+ - `getFacetAddress(diamond, selector)` - Get facet for selector
216
+ - `getFacetAddresses(diamond)` - Get all facet addresses
217
+ - `getFacetSelectors(diamond, facet)` - Get selectors for facet
218
+ - `getDiamondOwner(diamond)` - Get owner address
219
+ - `boundAddress(seed)` - Generate valid fuzz address
220
+ - `boundAmount(seed, min, max)` - Generate valid fuzz amount
221
+ - `selectorsEqual(a, b)` - Compare selector arrays
222
+
223
+ ### DiamondABILoader - ABI File Parser
224
+
225
+ Load and parse Diamond ABI files in your tests:
226
+
227
+ ```solidity
228
+ import "@diamondslab/diamonds-hardhat-foundry/contracts/DiamondABILoader.sol";
229
+
230
+ contract MyIntegrationTest is Test {
231
+ using DiamondABILoader for string;
232
+
233
+ function testABILoading() public {
234
+ // Load Diamond ABI
235
+ string memory abiJson = DiamondABILoader.loadDiamondABI("./diamond-abi/MyDiamond.json");
236
+
237
+ // Extract selectors and signatures
238
+ bytes4[] memory selectors = abiJson.extractSelectors();
239
+ string[] memory signatures = abiJson.extractSignatures();
240
+
241
+ console.log("Functions found:", selectors.length);
242
+
243
+ // Get function info
244
+ for (uint i = 0; i < selectors.length; i++) {
245
+ (bytes4 sel, string memory sig) = abiJson.getFunctionInfo(i);
246
+ console.log("Function:", sig);
247
+ }
248
+ }
249
+ }
250
+ ```
251
+
252
+ **DiamondABILoader Functions:**
253
+
254
+ - `loadDiamondABI(path)` - Load ABI JSON from file
255
+ - `extractSelectors(abiJson)` - Extract all function selectors
256
+ - `extractSignatures(abiJson)` - Extract all function signatures
257
+ - `getFunctionInfo(abiJson, index)` - Get selector and signature
258
+ - `verifySelectorsMatch(abiJson, expectedSelectors)` - Validate selectors
259
+
102
260
  ### 5. Run Foundry Tests
103
261
 
104
262
  ```bash
@@ -184,6 +342,205 @@ npx hardhat diamonds-forge:test --match-test "testOwnership" --verbosity 4
184
342
  npx hardhat diamonds-forge:test --skip-deployment --match-contract "MyTest"
185
343
  ```
186
344
 
345
+ ## Dynamic Helper Generation
346
+
347
+ Version 2.0.0+ introduces **dynamic helper generation** that creates deployment-specific Solidity helpers without hardcoded addresses.
348
+
349
+ ### How It Works
350
+
351
+ When you deploy a Diamond and generate helpers, the plugin creates `test/foundry/helpers/DiamondDeployment.sol` with:
352
+
353
+ ```solidity
354
+ library DiamondDeployment {
355
+ /// @notice Get the deployed Diamond address
356
+ function getDiamondAddress() internal pure returns (address) {
357
+ return 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512;
358
+ }
359
+
360
+ /// @notice Get the deployer address
361
+ function getDeployerAddress() internal pure returns (address) {
362
+ return 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266;
363
+ }
364
+
365
+ // Additional deployment-specific data...
366
+ }
367
+ ```
368
+
369
+ **Key Benefits:**
370
+
371
+ - ✅ **No hardcoded addresses in test files** - All addresses come from deployment records
372
+ - ✅ **Network-specific helpers** - Different helpers for different networks
373
+ - ✅ **Automatic regeneration** - Helpers update when you redeploy
374
+ - ✅ **Type-safe** - Solidity library ensures compile-time validation
375
+
376
+ ### Using Generated Helpers
377
+
378
+ ```solidity
379
+ import "../helpers/DiamondDeployment.sol";
380
+
381
+ contract MyTest is Test {
382
+ address diamond;
383
+ address deployer;
384
+
385
+ function setUp() public {
386
+ // Load from generated helpers
387
+ diamond = DiamondDeployment.getDiamondAddress();
388
+ deployer = DiamondDeployment.getDeployerAddress();
389
+
390
+ // Use in tests
391
+ vm.prank(deployer);
392
+ IDiamond(diamond).someFunction();
393
+ }
394
+ }
395
+ ```
396
+
397
+ ## Deployment Management
398
+
399
+ The plugin provides flexible deployment management with two modes:
400
+
401
+ ### Ephemeral Deployments (Default)
402
+
403
+ For quick testing without persisting deployment records:
404
+
405
+ ```bash
406
+ # Deploy Diamond for this test run only
407
+ npx hardhat diamonds-forge:test --diamond-name MyDiamond
408
+
409
+ # Deployment is cached in memory but not saved to file
410
+ # Helpers are generated from cached data
411
+ # Next run will deploy fresh Diamond
412
+ ```
413
+
414
+ **Use ephemeral mode when:**
415
+ - Running tests in CI/CD
416
+ - Testing with default Hardhat network
417
+ - You don't need to reuse deployments
418
+ - Each test run should start clean
419
+
420
+ ### Persistent Deployments
421
+
422
+ Save deployment records for reuse across test runs:
423
+
424
+ ```bash
425
+ # Deploy and save deployment record
426
+ npx hardhat diamonds-forge:deploy --diamond-name MyDiamond --network localhost
427
+
428
+ # Run tests using saved deployment
429
+ npx hardhat diamonds-forge:test --network localhost --use-deployment
430
+
431
+ # Deployment is loaded from file
432
+ # Subsequent runs reuse the same Diamond
433
+ ```
434
+
435
+ **Use persistent mode when:**
436
+ - Testing on persistent networks (localhost, testnets)
437
+ - Developing against specific Diamond deployment
438
+ - Testing upgrade scenarios
439
+ - Running integration tests
440
+
441
+ ### Task Flags Reference
442
+
443
+ **Deployment Control:**
444
+ - `--save-deployment` - Save deployment record to file (persistent mode)
445
+ - `--use-deployment` - Load existing deployment instead of deploying new one
446
+ - `--force-deploy` - Force new deployment even if one exists
447
+
448
+ **Helper Control:**
449
+ - `--skip-helpers` - Don't generate DiamondDeployment.sol
450
+ - `--helpers-dir <path>` - Custom output directory for helpers
451
+
452
+ **Test Filtering:**
453
+ - `--match-test <pattern>` - Run only tests matching name pattern
454
+ - `--match-contract <contract>` - Run only tests in specified contract
455
+ - `--match-path <path>` - Run only tests in files matching path
456
+
457
+ **Output Control:**
458
+ - `--verbosity <1-5>` - Set Forge output verbosity (default: 2)
459
+ - `--gas-report` - Display detailed gas usage report
460
+ - `--coverage` - Generate test coverage report
461
+
462
+ **Network Control:**
463
+ - `--network <name>` - Network to use (hardhat, localhost, sepolia, etc.)
464
+ - `--fork-url <url>` - Custom RPC URL for forking
465
+
466
+ ### Examples
467
+
468
+ ```bash
469
+ # Quick ephemeral test (default)
470
+ npx hardhat diamonds-forge:test
471
+
472
+ # Save deployment for reuse
473
+ npx hardhat diamonds-forge:test --save-deployment --network localhost
474
+
475
+ # Reuse saved deployment
476
+ npx hardhat diamonds-forge:test --use-deployment --network localhost
477
+
478
+ # Test specific functionality with gas report
479
+ npx hardhat diamonds-forge:test --match-test "testOwnership" --gas-report
480
+
481
+ # Run only fuzz tests with high verbosity
482
+ npx hardhat diamonds-forge:test --match-contract "Fuzz" --verbosity 4
483
+
484
+ # Force redeploy even if deployment exists
485
+ npx hardhat diamonds-forge:test --force-deploy --network localhost
486
+ ```
487
+
488
+ ## Snapshot and Restore
489
+
490
+ The `DiamondForgeHelpers` library provides snapshot/restore functionality for advanced testing scenarios.
491
+
492
+ ### Basic Usage
493
+
494
+ ```solidity
495
+ import "@diamondslab/diamonds-hardhat-foundry/contracts/DiamondForgeHelpers.sol";
496
+
497
+ contract MyTest is Test {
498
+ using DiamondForgeHelpers for *;
499
+
500
+ function test_MultipleScenarios() public {
501
+ // Save initial state
502
+ uint256 snapshot = DiamondForgeHelpers.snapshotState();
503
+
504
+ // Test scenario A
505
+ runScenarioA();
506
+
507
+ // Restore to initial state
508
+ DiamondForgeHelpers.revertToSnapshot(snapshot);
509
+
510
+ // Test scenario B from same starting point
511
+ runScenarioB();
512
+ }
513
+ }
514
+ ```
515
+
516
+ ### When to Use Snapshots
517
+
518
+ **Good Use Cases:**
519
+ - Testing multiple outcomes from same initial state
520
+ - Expensive setup that you want to reuse
521
+ - Testing state transitions and rollbacks
522
+ - Benchmarking gas costs across scenarios
523
+
524
+ **Don't Use For:**
525
+ - Normal test isolation (Forge does this automatically)
526
+ - Production/testnet testing (snapshots only work locally)
527
+
528
+ ### Snapshot Examples
529
+
530
+ See comprehensive examples in `test/foundry/integration/SnapshotExample.t.sol`:
531
+
532
+ ```bash
533
+ forge test --match-path "**/SnapshotExample.t.sol" -vv
534
+ ```
535
+
536
+ **Available in examples:**
537
+ - Basic snapshot/restore workflow
538
+ - Multiple snapshots with different states
539
+ - Snapshot with contract state changes
540
+ - Test isolation patterns
541
+
542
+ For detailed snapshot documentation, see [TESTING.md](./TESTING.md#snapshot-and-restore).
543
+
187
544
  ## Programmatic API
188
545
 
189
546
  Use the framework classes directly in your scripts:
@@ -428,7 +785,218 @@ export default {
428
785
 
429
786
  ## Troubleshooting
430
787
 
431
- ### Foundry Not Found
788
+ ### Common Issues
789
+
790
+ #### Foundry Not Found
791
+
792
+ **Error:** `Foundry not installed` or `forge: command not found`
793
+
794
+ **Solution:** Install Foundry from [getfoundry.sh](https://getfoundry.sh/):
795
+
796
+ ```bash
797
+ curl -L https://foundry.paradigm.xyz | bash
798
+ foundryup
799
+ ```
800
+
801
+ Verify installation:
802
+ ```bash
803
+ forge --version
804
+ ```
805
+
806
+ #### LocalDiamondDeployer Not Found
807
+
808
+ **Error:** `LocalDiamondDeployer not found` or `Cannot find module`
809
+
810
+ **Solution:** Ensure you have the `@diamondslab/hardhat-diamonds` package installed:
811
+
812
+ ```bash
813
+ npm install --save-dev @diamondslab/hardhat-diamonds
814
+ ```
815
+
816
+ Import it in your `hardhat.config.ts`:
817
+
818
+ ```typescript
819
+ import "@diamondslab/hardhat-diamonds";
820
+ import "@diamondslab/diamonds-hardhat-foundry";
821
+ ```
822
+
823
+ #### Deployment Record Not Found
824
+
825
+ **Error:** `No deployment record found for MyDiamond-hardhat-31337.json`
826
+
827
+ **Solution:** Deploy your Diamond first:
828
+
829
+ ```bash
830
+ npx hardhat diamonds-forge:deploy --diamond-name MyDiamond --network localhost
831
+ ```
832
+
833
+ Or use ephemeral deployment (default) which doesn't require saved records:
834
+
835
+ ```bash
836
+ npx hardhat diamonds-forge:test
837
+ ```
838
+
839
+ #### Diamond Has No Code
840
+
841
+ **Error:** `DiamondFuzzBase: Diamond has no code` when running tests
842
+
843
+ **Cause:** Test is trying to use a Diamond address that doesn't have deployed code.
844
+
845
+ **Solutions:**
846
+
847
+ 1. **For tests using hardhat network (ephemeral):**
848
+ - Tests should deploy their own Diamond in `setUp()`
849
+ - See `BasicDiamondIntegration.t.sol` for self-deploying pattern
850
+
851
+ 2. **For tests using deployed Diamond:**
852
+ - Start Hardhat node: `npx hardhat node`
853
+ - Deploy Diamond: `npx hardhat diamonds-forge:deploy --network localhost`
854
+ - Run tests: `npx hardhat diamonds-forge:test --network localhost`
855
+
856
+ 3. **Make tests fork-aware:**
857
+ ```solidity
858
+ function setUp() public {
859
+ diamond = DiamondDeployment.getDiamondAddress();
860
+
861
+ // Check if Diamond is deployed (forking)
862
+ if (diamond.code.length == 0) {
863
+ // Skip test or deploy in test
864
+ return;
865
+ }
866
+
867
+ // Proceed with test setup
868
+ }
869
+ ```
870
+
871
+ #### Generated Helpers Not Compiling
872
+
873
+ **Error:** Compilation errors in `test/foundry/helpers/DiamondDeployment.sol`
874
+
875
+ **Solutions:**
876
+
877
+ 1. Ensure Foundry remappings are correct in `foundry.toml`:
878
+ ```toml
879
+ [profile.default]
880
+ src = "contracts"
881
+ test = "test/foundry"
882
+ remappings = [
883
+ "@diamondslab/diamonds-hardhat-foundry/=node_modules/@diamondslab/diamonds-hardhat-foundry/",
884
+ ]
885
+ ```
886
+
887
+ 2. Verify Diamond deployed successfully before generating helpers:
888
+ ```bash
889
+ npx hardhat diamonds-forge:deploy --diamond-name MyDiamond
890
+ npx hardhat diamonds-forge:generate-helpers --diamond-name MyDiamond
891
+ ```
892
+
893
+ 3. Check that deployment data is valid:
894
+ - Look in `diamonds/MyDiamond/deployments/`
895
+ - Verify JSON file contains `DiamondAddress` field
896
+
897
+ #### Peer Dependency Warnings
898
+
899
+ **Warning:** `ERESOLVE unable to resolve dependency tree` or peer dependency conflicts
900
+
901
+ **Solution:** Install all required peer dependencies:
902
+
903
+ ```bash
904
+ npm install --save-dev \
905
+ @diamondslab/diamonds \
906
+ @diamondslab/hardhat-diamonds \
907
+ @nomicfoundation/hardhat-ethers \
908
+ ethers \
909
+ hardhat
910
+ ```
911
+
912
+ For package.json, specify compatible versions:
913
+
914
+ ```json
915
+ {
916
+ "devDependencies": {
917
+ "@diamondslab/diamonds": "^3.0.0",
918
+ "@diamondslab/hardhat-diamonds": "^2.0.0",
919
+ "@diamondslab/diamonds-hardhat-foundry": "^2.0.0",
920
+ "@nomicfoundation/hardhat-ethers": "^3.0.0",
921
+ "ethers": "^6.0.0",
922
+ "hardhat": "^2.26.0"
923
+ }
924
+ }
925
+ ```
926
+
927
+ #### Tests Pass Locally But Fail in CI
928
+
929
+ **Cause:** CI environment differences (network, timing, dependencies)
930
+
931
+ **Solutions:**
932
+
933
+ 1. **Ensure Foundry is installed in CI:**
934
+ ```yaml
935
+ # GitHub Actions example
936
+ - name: Install Foundry
937
+ uses: foundry-rs/foundry-toolchain@v1
938
+
939
+ - name: Run tests
940
+ run: npx hardhat diamonds-forge:test
941
+ ```
942
+
943
+ 2. **Use ephemeral deployments for CI (default):**
944
+ ```bash
945
+ # This works in CI without persistent network
946
+ npx hardhat diamonds-forge:test
947
+ ```
948
+
949
+ 3. **For persistent network testing in CI:**
950
+ ```yaml
951
+ - name: Start Hardhat node
952
+ run: npx hardhat node &
953
+
954
+ - name: Wait for node
955
+ run: sleep 5
956
+
957
+ - name: Run tests
958
+ run: npx hardhat diamonds-forge:test --network localhost
959
+ ```
960
+
961
+ #### Import Resolution Errors
962
+
963
+ **Error:** `File import callback not supported` or module resolution failures
964
+
965
+ **Solution:** Check your `hardhat.config.ts` has correct imports:
966
+
967
+ ```typescript
968
+ import "@nomicfoundation/hardhat-ethers";
969
+ import "@diamondslab/hardhat-diamonds";
970
+ import "@diamondslab/diamonds-hardhat-foundry";
971
+
972
+ export default {
973
+ solidity: "0.8.28",
974
+ // ... config
975
+ };
976
+ ```
977
+
978
+ Ensure TypeScript compilation targets CommonJS:
979
+
980
+ ```json
981
+ // tsconfig.json
982
+ {
983
+ "compilerOptions": {
984
+ "module": "CommonJS",
985
+ "moduleResolution": "node"
986
+ }
987
+ }
988
+ ```
989
+
990
+ ### Getting Help
991
+
992
+ If you encounter issues not covered here:
993
+
994
+ 1. Check the [TESTING.md](./TESTING.md) guide for detailed testing workflows
995
+ 2. Review [MIGRATION.md](./MIGRATION.md) if upgrading from v1.x
996
+ 3. See [DESIGN.md](./DESIGN.md) for architecture details
997
+ 4. Open an issue on [GitHub](https://github.com/diamondslab/diamonds-hardhat-foundry/issues)
998
+
999
+ ## Foundry Not Found
432
1000
 
433
1001
  **Error:** `Foundry not installed`
434
1002
 
@@ -475,6 +1043,84 @@ npx hardhat diamonds-forge:deploy --diamond-name YourDiamond
475
1043
  npm install --save-dev @diamondslab/diamonds @diamondslab/hardhat-diamonds
476
1044
  ```
477
1045
 
1046
+ ## Test Suite
1047
+
1048
+ This module maintains a comprehensive test suite with **100% pass rate** across multiple testing categories:
1049
+
1050
+ ### Test Statistics
1051
+
1052
+ - **Total Tests**: 144
1053
+ - **Passing**: 141 (98%)
1054
+ - **Skipped**: 3 (intentional - deployment-dependent)
1055
+ - **Failed**: 0
1056
+ - **Execution Time**: ~8-9 seconds
1057
+
1058
+ ### Test Categories
1059
+
1060
+ #### Unit Tests (3 tests)
1061
+ Basic functionality validation:
1062
+ - Diamond deployment verification
1063
+ - Deployer address validation
1064
+ - Example functionality tests
1065
+
1066
+ #### Integration Tests (14 tests)
1067
+ Real-world workflow validation:
1068
+ - Multi-facet interaction workflows
1069
+ - Cross-facet state management
1070
+ - Diamond deployment validation
1071
+ - Facet introspection and enumeration
1072
+ - On-chain selector verification
1073
+ - Gas measurement and profiling
1074
+
1075
+ #### Fuzz Tests (93 tests)
1076
+ Property-based testing with randomized inputs:
1077
+ - **Access Control** (19 tests): Role granting, revocation, enumeration
1078
+ - **Ownership** (7 tests): Transfer, renounce, unauthorized access
1079
+ - **Routing** (11 tests): Selector routing, facet lookup, consistency
1080
+ - **ABI Loader** (11 tests): ABI parsing, selector extraction, signature verification
1081
+ - **Example Fuzz** (5 tests): Address/amount validation, bounded values
1082
+
1083
+ #### Invariant Tests (24 tests)
1084
+ State invariants and Diamond integrity:
1085
+ - **Diamond Invariants** (13 tests): Facet validity, selector consistency, role hierarchy
1086
+ - **Proxy Invariants** (11 tests): ABI matching, facet existence, storage consistency
1087
+
1088
+ ### Running Tests
1089
+
1090
+ Run the complete test suite:
1091
+
1092
+ ```bash
1093
+ npx hardhat diamonds-forge:test --network localhost
1094
+ ```
1095
+
1096
+ Run specific test categories:
1097
+
1098
+ ```bash
1099
+ # Unit tests only
1100
+ forge test --match-path "test/foundry/unit/**/*.t.sol"
1101
+
1102
+ # Fuzz tests only
1103
+ forge test --match-path "test/foundry/fuzz/**/*.t.sol"
1104
+
1105
+ # Invariant tests only
1106
+ forge test --match-path "test/foundry/invariant/**/*.t.sol"
1107
+
1108
+ # Integration tests only
1109
+ forge test --match-path "test/foundry/integration/**/*.t.sol"
1110
+ ```
1111
+
1112
+ ### Test Patterns
1113
+
1114
+ All tests follow best practices:
1115
+
1116
+ - **Role Setup**: Access control tests grant necessary roles in `setUp()`
1117
+ - **Invariant Targeting**: Invariant tests use `targetContract()` for fuzzing
1118
+ - **Selector Filtering**: Tests skip undeployed selectors (facetAddress returns address(0))
1119
+ - **Gas Profiling**: Gas measurements included in relevant tests
1120
+ - **Comprehensive Coverage**: Edge cases, error conditions, and happy paths
1121
+
1122
+ See [TESTING.md](./TESTING.md) for detailed testing guide and patterns.
1123
+
478
1124
  ## Contributing
479
1125
 
480
1126
  Contributions are welcome! Please feel free to submit a Pull Request.