@diamondslab/diamonds-hardhat-foundry 2.2.1 → 2.2.3

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.
@@ -102,7 +102,15 @@ abstract contract DiamondFuzzBase is Test {
102
102
  /// }
103
103
  /// ```
104
104
  function _getDiamondABIPath() internal view virtual returns (string memory abiPath) {
105
- return "./diamond-abi/ExampleDiamond.json";
105
+ // Try to load from environment variable first
106
+ try vm.envString("DIAMOND_ABI_PATH") returns (string memory path) {
107
+ return path;
108
+ } catch {
109
+ // Fallback: This should be overridden by test contracts to use DiamondDeployment.getDiamondABIPath()
110
+ revert(
111
+ "DiamondFuzzBase: _getDiamondABIPath() must be overridden in test contract or set env var DIAMOND_ABI_PATH. Use: return DiamondDeployment.getDiamondABIPath();"
112
+ );
113
+ }
106
114
  }
107
115
 
108
116
  /// @notice Load and parse Diamond ABI file
@@ -1 +1 @@
1
- {"version":3,"file":"ForgeFuzzingFramework.d.ts","sourceRoot":"","sources":["../../src/framework/ForgeFuzzingFramework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAM1D,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qCAAqC;IACrC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mEAAmE;IACnE,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2CAA2C;IAC3C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,qBAAa,qBAAqB;IAIpB,OAAO,CAAC,GAAG;IAHvB,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,eAAe,CAAkB;gBAErB,GAAG,EAAE,yBAAyB;IAKlD;;;;;;;;;;;OAWG;IACG,QAAQ,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC;IA8GhE;;OAEG;IACG,UAAU,CACd,WAAW,GAAE,MAAyB,EACtC,WAAW,GAAE,MAAkB,EAC/B,KAAK,GAAE,OAAe;IASxB;;OAEG;IACG,mBAAmB,CACvB,WAAW,GAAE,MAAyB,EACtC,WAAW,GAAE,MAAkB;CAwBlC"}
1
+ {"version":3,"file":"ForgeFuzzingFramework.d.ts","sourceRoot":"","sources":["../../src/framework/ForgeFuzzingFramework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAM1D,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qCAAqC;IACrC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mEAAmE;IACnE,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2CAA2C;IAC3C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,qBAAa,qBAAqB;IAIpB,OAAO,CAAC,GAAG;IAHvB,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,eAAe,CAAkB;gBAErB,GAAG,EAAE,yBAAyB;IAKlD;;;;;;;;;;;OAWG;IACG,QAAQ,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC;IAgHhE;;OAEG;IACG,UAAU,CACd,WAAW,GAAE,MAAyB,EACtC,WAAW,GAAE,MAAkB,EAC/B,KAAK,GAAE,OAAe;IASxB;;OAEG;IACG,mBAAmB,CACvB,WAAW,GAAE,MAAyB,EACtC,WAAW,GAAE,MAAkB;CA0BlC"}
@@ -63,7 +63,9 @@ class ForgeFuzzingFramework {
63
63
  const network = await provider.getNetwork();
64
64
  const chainId = Number(network.chainId);
65
65
  const deploymentData = deployment.getDeployedDiamondData();
66
- await this.helperGenerator.generateDeploymentHelpers(diamondName, networkName, chainId, deploymentData);
66
+ // Generate helpers and set environment variables
67
+ await this.helperGenerator.generateDeploymentHelpers(diamondName, networkName, chainId, deploymentData, deployment // Pass Diamond instance for env var setup
68
+ );
67
69
  }
68
70
  else {
69
71
  logger_1.Logger.info("Skipping helper generation");
@@ -126,7 +128,9 @@ class ForgeFuzzingFramework {
126
128
  const network = await provider.getNetwork();
127
129
  const chainId = Number(network.chainId);
128
130
  const deploymentData = deployment.getDeployedDiamondData();
129
- return await this.helperGenerator.generateDeploymentHelpers(diamondName, networkName, chainId, deploymentData);
131
+ // Generate helpers and set environment variables
132
+ return await this.helperGenerator.generateDeploymentHelpers(diamondName, networkName, chainId, deploymentData, deployment // Pass Diamond instance for env var setup
133
+ );
130
134
  }
131
135
  }
132
136
  exports.ForgeFuzzingFramework = ForgeFuzzingFramework;
@@ -1 +1 @@
1
- {"version":3,"file":"ForgeFuzzingFramework.js","sourceRoot":"","sources":["../../src/framework/ForgeFuzzingFramework.ts"],"names":[],"mappings":"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","sourcesContent":["import { HardhatRuntimeEnvironment } from \"hardhat/types\";\nimport { compileForge, isFoundryInstalled, runForgeTest } from \"../utils/foundry\";\nimport { Logger } from \"../utils/logger\";\nimport { DeploymentManager } from \"./DeploymentManager\";\nimport { HelperGenerator } from \"./HelperGenerator\";\n\nexport interface ForgeTestOptions {\n /** Name of the Diamond to deploy */\n diamondName?: string;\n /** Network to deploy on */\n networkName?: string;\n /** Force redeployment */\n force?: boolean;\n /** Match test pattern */\n matchTest?: string;\n /** Match contract pattern */\n matchContract?: string;\n /** Verbosity level (1-5) */\n verbosity?: number;\n /** Show gas report */\n gasReport?: boolean;\n /** Skip helper generation */\n skipHelpers?: boolean;\n /** Skip deployment (use existing) */\n skipDeployment?: boolean;\n /** Write deployment data to file (default: false for ephemeral) */\n writeDeployedDiamondData?: boolean;\n /** Use EVM snapshots for test isolation */\n useSnapshot?: boolean;\n}\n\n/**\n * ForgeFuzzingFramework - Main orchestration class for Forge testing with Diamonds\n * \n * Coordinates:\n * 1. Diamond deployment via DeploymentManager\n * 2. Helper generation via HelperGenerator\n * 3. Forge test execution\n */\nexport class ForgeFuzzingFramework {\n private deploymentManager: DeploymentManager;\n private helperGenerator: HelperGenerator;\n\n constructor(private hre: HardhatRuntimeEnvironment) {\n this.deploymentManager = new DeploymentManager(hre);\n this.helperGenerator = new HelperGenerator(hre);\n }\n\n /**\n * Run complete Forge testing workflow\n * \n * Workflow:\n * 1. Validate Foundry installation\n * 2. Deploy or reuse Diamond\n * 3. Generate Solidity helpers\n * 4. Compile Forge contracts\n * 5. Run Forge tests\n * \n * @param options - Test execution options\n */\n async runTests(options: ForgeTestOptions = {}): Promise<boolean> {\n const {\n diamondName = \"ExampleDiamond\",\n networkName = \"hardhat\",\n writeDeployedDiamondData = false,\n useSnapshot = false,\n force = false,\n matchTest,\n matchContract,\n verbosity = 2,\n gasReport = false,\n skipHelpers = false,\n skipDeployment = false,\n } = options;\n\n Logger.section(\"Forge Fuzzing Framework - Test Execution\");\n\n // Step 1: Validate Foundry\n if (!isFoundryInstalled()) {\n Logger.error(\"Foundry is not installed. Please install it: https://book.getfoundry.sh/getting-started/installation\");\n return false;\n }\n\n try {\n // Step 2: Ensure Diamond deployment\n if (!skipDeployment) {\n Logger.section(\"Step 1/4: Ensuring Diamond Deployment\");\n await this.deploymentManager.ensureDeployment(\n diamondName,\n networkName,\n force,\n writeDeployedDiamondData\n );\n } else {\n Logger.info(\"Skipping deployment (using existing)\");\n }\n\n // Step 3: Generate helpers\n if (!skipHelpers) {\n Logger.section(\"Step 2/4: Generating Solidity Helpers\");\n const deployment = await this.deploymentManager.getDeployment(\n diamondName,\n networkName\n );\n\n if (!deployment) {\n Logger.error(\"No deployment found. Cannot generate helpers.\");\n return false;\n }\n\n const provider = this.hre.ethers.provider;\n const network = await provider.getNetwork();\n const chainId = Number(network.chainId);\n\n const deploymentData = deployment.getDeployedDiamondData();\n \n await this.helperGenerator.generateDeploymentHelpers(\n diamondName,\n networkName,\n chainId,\n deploymentData\n );\n } else {\n Logger.info(\"Skipping helper generation\");\n }\n\n // Step 4: Compile Forge contracts\n Logger.section(\"Step 3/4: Compiling Forge Contracts\");\n const compileResult = await compileForge({\n cwd: this.hre.config.paths.root,\n verbose: verbosity >= 3,\n });\n\n if (!compileResult.success) {\n Logger.error(\"Forge compilation failed\");\n return false;\n }\n\n // Step 5: Run tests\n Logger.section(\"Step 4/4: Running Forge Tests\");\n \n // Only fork when using persistent networks (localhost, sepolia, mainnet, etc.)\n // The ephemeral \"hardhat\" network cannot be forked from\n let forkUrl: string | undefined;\n if (networkName !== \"hardhat\") {\n const provider = this.hre.ethers.provider;\n forkUrl = (provider as any)._hardhatProvider?._wrapped?.url || \"http://127.0.0.1:8545\";\n Logger.info(`Forking from ${networkName}: ${forkUrl}`);\n } else {\n Logger.warn(`⚠️ Using ephemeral \"${networkName}\" network - tests requiring deployed Diamond will fail`);\n Logger.warn(`💡 For deployed Diamond testing, use: npx hardhat diamonds-forge:test --network localhost`);\n Logger.warn(`💡 Make sure to start Hardhat node first: npx hardhat node`);\n }\n \n const testResult = await runForgeTest({\n matchTest,\n matchContract,\n verbosity,\n gasReport,\n forkUrl, // Only set for persistent networks\n cwd: this.hre.config.paths.root,\n });\n\n return testResult.success;\n } catch (error: any) {\n Logger.error(`Test execution failed: ${error.message}`);\n return false;\n }\n }\n\n /**\n * Deploy Diamond only (no testing)\n */\n async deployOnly(\n diamondName: string = \"ExampleDiamond\",\n networkName: string = \"hardhat\",\n force: boolean = false\n ) {\n return await this.deploymentManager.ensureDeployment(\n diamondName,\n networkName,\n force\n );\n }\n\n /**\n * Generate helpers only (no deployment or testing)\n */\n async generateHelpersOnly(\n diamondName: string = \"ExampleDiamond\",\n networkName: string = \"hardhat\"\n ) {\n const deployment = await this.deploymentManager.getDeployment(\n diamondName,\n networkName\n );\n\n if (!deployment) {\n throw new Error(\"No deployment found. Deploy first using deployOnly()\");\n }\n\n const provider = this.hre.ethers.provider;\n const network = await provider.getNetwork();\n const chainId = Number(network.chainId);\n\n const deploymentData = deployment.getDeployedDiamondData();\n\n return await this.helperGenerator.generateDeploymentHelpers(\n diamondName,\n networkName,\n chainId,\n deploymentData\n );\n }\n}\n\n"]}
1
+ {"version":3,"file":"ForgeFuzzingFramework.js","sourceRoot":"","sources":["../../src/framework/ForgeFuzzingFramework.ts"],"names":[],"mappings":"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","sourcesContent":["import { HardhatRuntimeEnvironment } from \"hardhat/types\";\nimport { compileForge, isFoundryInstalled, runForgeTest } from \"../utils/foundry\";\nimport { Logger } from \"../utils/logger\";\nimport { DeploymentManager } from \"./DeploymentManager\";\nimport { HelperGenerator } from \"./HelperGenerator\";\n\nexport interface ForgeTestOptions {\n /** Name of the Diamond to deploy */\n diamondName?: string;\n /** Network to deploy on */\n networkName?: string;\n /** Force redeployment */\n force?: boolean;\n /** Match test pattern */\n matchTest?: string;\n /** Match contract pattern */\n matchContract?: string;\n /** Verbosity level (1-5) */\n verbosity?: number;\n /** Show gas report */\n gasReport?: boolean;\n /** Skip helper generation */\n skipHelpers?: boolean;\n /** Skip deployment (use existing) */\n skipDeployment?: boolean;\n /** Write deployment data to file (default: false for ephemeral) */\n writeDeployedDiamondData?: boolean;\n /** Use EVM snapshots for test isolation */\n useSnapshot?: boolean;\n}\n\n/**\n * ForgeFuzzingFramework - Main orchestration class for Forge testing with Diamonds\n * \n * Coordinates:\n * 1. Diamond deployment via DeploymentManager\n * 2. Helper generation via HelperGenerator\n * 3. Forge test execution\n */\nexport class ForgeFuzzingFramework {\n private deploymentManager: DeploymentManager;\n private helperGenerator: HelperGenerator;\n\n constructor(private hre: HardhatRuntimeEnvironment) {\n this.deploymentManager = new DeploymentManager(hre);\n this.helperGenerator = new HelperGenerator(hre);\n }\n\n /**\n * Run complete Forge testing workflow\n * \n * Workflow:\n * 1. Validate Foundry installation\n * 2. Deploy or reuse Diamond\n * 3. Generate Solidity helpers\n * 4. Compile Forge contracts\n * 5. Run Forge tests\n * \n * @param options - Test execution options\n */\n async runTests(options: ForgeTestOptions = {}): Promise<boolean> {\n const {\n diamondName = \"ExampleDiamond\",\n networkName = \"hardhat\",\n writeDeployedDiamondData = false,\n useSnapshot = false,\n force = false,\n matchTest,\n matchContract,\n verbosity = 2,\n gasReport = false,\n skipHelpers = false,\n skipDeployment = false,\n } = options;\n\n Logger.section(\"Forge Fuzzing Framework - Test Execution\");\n\n // Step 1: Validate Foundry\n if (!isFoundryInstalled()) {\n Logger.error(\"Foundry is not installed. Please install it: https://book.getfoundry.sh/getting-started/installation\");\n return false;\n }\n\n try {\n // Step 2: Ensure Diamond deployment\n if (!skipDeployment) {\n Logger.section(\"Step 1/4: Ensuring Diamond Deployment\");\n await this.deploymentManager.ensureDeployment(\n diamondName,\n networkName,\n force,\n writeDeployedDiamondData\n );\n } else {\n Logger.info(\"Skipping deployment (using existing)\");\n }\n\n // Step 3: Generate helpers\n if (!skipHelpers) {\n Logger.section(\"Step 2/4: Generating Solidity Helpers\");\n const deployment = await this.deploymentManager.getDeployment(\n diamondName,\n networkName\n );\n\n if (!deployment) {\n Logger.error(\"No deployment found. Cannot generate helpers.\");\n return false;\n }\n\n const provider = this.hre.ethers.provider;\n const network = await provider.getNetwork();\n const chainId = Number(network.chainId);\n\n const deploymentData = deployment.getDeployedDiamondData();\n \n // Generate helpers and set environment variables\n await this.helperGenerator.generateDeploymentHelpers(\n diamondName,\n networkName,\n chainId,\n deploymentData,\n deployment // Pass Diamond instance for env var setup\n );\n } else {\n Logger.info(\"Skipping helper generation\");\n }\n\n // Step 4: Compile Forge contracts\n Logger.section(\"Step 3/4: Compiling Forge Contracts\");\n const compileResult = await compileForge({\n cwd: this.hre.config.paths.root,\n verbose: verbosity >= 3,\n });\n\n if (!compileResult.success) {\n Logger.error(\"Forge compilation failed\");\n return false;\n }\n\n // Step 5: Run tests\n Logger.section(\"Step 4/4: Running Forge Tests\");\n \n // Only fork when using persistent networks (localhost, sepolia, mainnet, etc.)\n // The ephemeral \"hardhat\" network cannot be forked from\n let forkUrl: string | undefined;\n if (networkName !== \"hardhat\") {\n const provider = this.hre.ethers.provider;\n forkUrl = (provider as any)._hardhatProvider?._wrapped?.url || \"http://127.0.0.1:8545\";\n Logger.info(`Forking from ${networkName}: ${forkUrl}`);\n } else {\n Logger.warn(`⚠️ Using ephemeral \"${networkName}\" network - tests requiring deployed Diamond will fail`);\n Logger.warn(`💡 For deployed Diamond testing, use: npx hardhat diamonds-forge:test --network localhost`);\n Logger.warn(`💡 Make sure to start Hardhat node first: npx hardhat node`);\n }\n \n const testResult = await runForgeTest({\n matchTest,\n matchContract,\n verbosity,\n gasReport,\n forkUrl, // Only set for persistent networks\n cwd: this.hre.config.paths.root,\n });\n\n return testResult.success;\n } catch (error: any) {\n Logger.error(`Test execution failed: ${error.message}`);\n return false;\n }\n }\n\n /**\n * Deploy Diamond only (no testing)\n */\n async deployOnly(\n diamondName: string = \"ExampleDiamond\",\n networkName: string = \"hardhat\",\n force: boolean = false\n ) {\n return await this.deploymentManager.ensureDeployment(\n diamondName,\n networkName,\n force\n );\n }\n\n /**\n * Generate helpers only (no deployment or testing)\n */\n async generateHelpersOnly(\n diamondName: string = \"ExampleDiamond\",\n networkName: string = \"hardhat\"\n ) {\n const deployment = await this.deploymentManager.getDeployment(\n diamondName,\n networkName\n );\n\n if (!deployment) {\n throw new Error(\"No deployment found. Deploy first using deployOnly()\");\n }\n\n const provider = this.hre.ethers.provider;\n const network = await provider.getNetwork();\n const chainId = Number(network.chainId);\n\n const deploymentData = deployment.getDeployedDiamondData();\n\n // Generate helpers and set environment variables\n return await this.helperGenerator.generateDeploymentHelpers(\n diamondName,\n networkName,\n chainId,\n deploymentData,\n deployment // Pass Diamond instance for env var setup\n );\n }\n}\n\n"]}
@@ -12,8 +12,14 @@ export declare class HelperGenerator {
12
12
  scaffoldProject(outputDir?: string): Promise<void>;
13
13
  /**
14
14
  * Generate DiamondDeployment.sol from deployment record
15
+ * Also sets DIAMOND_ADDRESS and DIAMOND_ABI_PATH environment variables for Forge tests
15
16
  */
16
- generateDeploymentHelpers(diamondName: string, networkName: string, chainId: number, deploymentData: DeployedDiamondData): Promise<string>;
17
+ generateDeploymentHelpers(diamondName: string, networkName: string, chainId: number, deploymentData: DeployedDiamondData, diamond?: any): Promise<string>;
18
+ /**
19
+ * Set environment variables for Forge tests
20
+ * @private
21
+ */
22
+ private setForgeEnvironmentVariables;
17
23
  /**
18
24
  * Generate example test files
19
25
  */
@@ -1 +1 @@
1
- {"version":3,"file":"HelperGenerator.d.ts","sourceRoot":"","sources":["../../src/framework/HelperGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAI1D;;GAEG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,yBAAyB;IAElD;;OAEG;IACG,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBxD;;OAEG;IACG,yBAAyB,CAC7B,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,mBAAmB,GAClC,OAAO,CAAC,MAAM,CAAC;IA6BlB;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAuE/C;;;OAGG;IACH,OAAO,CAAC,qBAAqB;CA0I9B"}
1
+ {"version":3,"file":"HelperGenerator.d.ts","sourceRoot":"","sources":["../../src/framework/HelperGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAW,MAAM,uBAAuB,CAAC;AAErE,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAI1D;;GAEG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,yBAAyB;IAElD;;OAEG;IACG,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBxD;;;OAGG;IACG,yBAAyB,CAC7B,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,mBAAmB,EACnC,OAAO,CAAC,EAAE,GAAG,GACZ,OAAO,CAAC,MAAM,CAAC;IAmClB;;;OAGG;IACH,OAAO,CAAC,4BAA4B;IA2BpC;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAuE/C;;;OAGG;IACH,OAAO,CAAC,qBAAqB;CA0I9B"}
@@ -29,8 +29,10 @@ class HelperGenerator {
29
29
  }
30
30
  /**
31
31
  * Generate DiamondDeployment.sol from deployment record
32
+ * Also sets DIAMOND_ADDRESS and DIAMOND_ABI_PATH environment variables for Forge tests
32
33
  */
33
- async generateDeploymentHelpers(diamondName, networkName, chainId, deploymentData) {
34
+ async generateDeploymentHelpers(diamondName, networkName, chainId, deploymentData, diamond // Diamond instance from @diamondslab/hardhat-diamonds
35
+ ) {
34
36
  logger_1.Logger.section("Generating Diamond Deployment Helper");
35
37
  const helpersDir = this.hre.diamondsFoundry.helpersDir;
36
38
  const outputPath = (0, path_1.join)(this.hre.config.paths.root, helpersDir, "DiamondDeployment.sol");
@@ -42,8 +44,37 @@ class HelperGenerator {
42
44
  // Write file
43
45
  (0, fs_1.writeFileSync)(outputPath, content, "utf8");
44
46
  logger_1.Logger.success(`Generated: ${outputPath}`);
47
+ // Set environment variables for Forge tests (if Diamond instance provided)
48
+ if (diamond) {
49
+ this.setForgeEnvironmentVariables(diamond, deploymentData);
50
+ }
45
51
  return outputPath;
46
52
  }
53
+ /**
54
+ * Set environment variables for Forge tests
55
+ * @private
56
+ */
57
+ setForgeEnvironmentVariables(diamond, deploymentData) {
58
+ try {
59
+ // Get Diamond ABI path - remove leading "./" for Foundry compatibility
60
+ let abiPath = diamond.getDiamondAbiFilePath?.() || `diamond-abi/${diamond.getDiamondConfig().diamondName}.json` || `diamond-abi/Diamond.json`;
61
+ // Normalize path - remove leading "./" if present
62
+ if (abiPath.startsWith('./')) {
63
+ abiPath = abiPath.substring(2);
64
+ }
65
+ // Get Diamond address
66
+ const diamondAddress = deploymentData.DiamondAddress;
67
+ // Set environment variables
68
+ process.env.DIAMOND_ABI_PATH = abiPath;
69
+ process.env.DIAMOND_ADDRESS = diamondAddress;
70
+ logger_1.Logger.info(`Set DIAMOND_ABI_PATH: ${abiPath}`);
71
+ logger_1.Logger.info(`Set DIAMOND_ADDRESS: ${diamondAddress}`);
72
+ }
73
+ catch (error) {
74
+ logger_1.Logger.warn(`Failed to set environment variables: ${error.message}`);
75
+ logger_1.Logger.warn("Tests can still use DiamondDeployment.sol overrides");
76
+ }
77
+ }
47
78
  /**
48
79
  * Generate example test files
49
80
  */
@@ -143,7 +174,7 @@ class HelperGenerator {
143
174
  // Diamond ABI path
144
175
  source += ` /// @notice Path to the Diamond ABI file\n`;
145
176
  source += ` /// @dev Used by DiamondFuzzBase to load ABI for testing\n`;
146
- source += ` string constant DIAMOND_ABI_PATH = "./diamond-abi/${diamondName}.json";\n\n`;
177
+ source += ` string constant DIAMOND_ABI_PATH = "diamond-abi/${diamondName}.json";\n\n`;
147
178
  // Diamond address
148
179
  source += ` /// @notice Address of the deployed ${diamondName} contract\n`;
149
180
  source += ` /// @dev This is the main Diamond proxy address\n`;
@@ -1 +1 @@
1
- {"version":3,"file":"HelperGenerator.js","sourceRoot":"","sources":["../../src/framework/HelperGenerator.ts"],"names":[],"mappings":"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","sourcesContent":["import { DeployedDiamondData } from \"@diamondslab/diamonds\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { HardhatRuntimeEnvironment } from \"hardhat/types\";\nimport { join } from \"path\";\nimport { Logger } from \"../utils/logger\";\n\n/**\n * HelperGenerator - Generates Solidity helper files for testing\n */\nexport class HelperGenerator {\n constructor(private hre: HardhatRuntimeEnvironment) {}\n\n /**\n * Scaffold project with initial test structure\n */\n async scaffoldProject(outputDir?: string): Promise<void> {\n const helpersDir = outputDir || this.hre.diamondsFoundry.helpersDir;\n const basePath = join(this.hre.config.paths.root, helpersDir);\n\n Logger.section(\"Scaffolding Forge Test Structure\");\n \n // Create directories\n Logger.step(\"Creating directories...\");\n mkdirSync(basePath, { recursive: true });\n mkdirSync(join(basePath, \"../unit\"), { recursive: true });\n mkdirSync(join(basePath, \"../integration\"), { recursive: true });\n mkdirSync(join(basePath, \"../fuzz\"), { recursive: true });\n\n Logger.success(`Test structure created at ${basePath}`);\n }\n\n /**\n * Generate DiamondDeployment.sol from deployment record\n */\n async generateDeploymentHelpers(\n diamondName: string,\n networkName: string,\n chainId: number,\n deploymentData: DeployedDiamondData\n ): Promise<string> {\n Logger.section(\"Generating Diamond Deployment Helper\");\n\n const helpersDir = this.hre.diamondsFoundry.helpersDir;\n const outputPath = join(\n this.hre.config.paths.root,\n helpersDir,\n \"DiamondDeployment.sol\"\n );\n\n const content = this.generateLibrarySource(\n diamondName,\n networkName,\n chainId,\n deploymentData\n );\n\n // Ensure directory exists\n mkdirSync(join(this.hre.config.paths.root, helpersDir), {\n recursive: true,\n });\n\n // Write file\n writeFileSync(outputPath, content, \"utf8\");\n\n Logger.success(`Generated: ${outputPath}`);\n return outputPath;\n }\n\n /**\n * Generate example test files\n */\n async generateExampleTests(): Promise<string[]> {\n const generated: string[] = [];\n const examples = this.hre.diamondsFoundry.exampleTests;\n\n if (!this.hre.diamondsFoundry.generateExamples) {\n Logger.info(\"Example generation disabled in config\");\n return generated;\n }\n\n Logger.section(\"Generating Example Tests\");\n\n const basePath = join(this.hre.config.paths.root, \"test\", \"foundry\");\n const templatesPath = join(__dirname, \"../templates\");\n\n for (const type of examples) {\n let templateFile = \"\";\n let outputPath = \"\";\n\n switch (type) {\n case \"unit\":\n templateFile = join(templatesPath, \"ExampleUnitTest.t.sol.template\");\n outputPath = join(basePath, \"unit\", \"ExampleUnit.t.sol\");\n break;\n case \"integration\":\n templateFile = join(templatesPath, \"ExampleIntegrationTest.t.sol.template\");\n outputPath = join(basePath, \"integration\", \"ExampleIntegration.t.sol\");\n break;\n case \"fuzz\":\n templateFile = join(templatesPath, \"ExampleFuzzTest.t.sol.template\");\n outputPath = join(basePath, \"fuzz\", \"ExampleFuzz.t.sol\");\n break;\n default:\n Logger.warn(`Unknown example type: ${type}`);\n continue;\n }\n\n try {\n // Check if template exists\n if (!existsSync(templateFile)) {\n Logger.warn(`Template not found: ${templateFile}`);\n continue;\n }\n\n // Read template content\n const templateContent = readFileSync(templateFile, \"utf8\");\n\n // Ensure output directory exists\n mkdirSync(join(basePath, type), { recursive: true });\n\n // Check if file already exists\n if (existsSync(outputPath)) {\n Logger.info(`Skipping ${type} example (already exists): ${outputPath}`);\n continue;\n }\n\n // Write example test file\n writeFileSync(outputPath, templateContent, \"utf8\");\n Logger.success(`Generated ${type} example: ${outputPath}`);\n generated.push(outputPath);\n } catch (error: any) {\n Logger.error(`Failed to generate ${type} example: ${error.message}`);\n }\n }\n\n if (generated.length === 0) {\n Logger.info(\"No new example tests generated (may already exist)\");\n }\n\n return generated;\n }\n\n /**\n * Generate Solidity library source from deployment data\n * @private\n */\n private generateLibrarySource(\n diamondName: string,\n networkName: string,\n chainId: number,\n deploymentData: DeployedDiamondData\n ): string {\n const timestamp = new Date().toISOString();\n const networkInfo = `${networkName}-${chainId}`;\n const deploymentFileName = `${diamondName.toLowerCase()}-${networkInfo}.json`;\n const deploymentFilePath = `diamonds/${diamondName}/deployments/${deploymentFileName}`;\n\n let source = \"\";\n\n // SPDX and pragma\n source += \"// SPDX-License-Identifier: MIT\\n\";\n source += \"pragma solidity ^0.8.19;\\n\\n\";\n\n // Header comments\n source += \"/**\\n\";\n source += ` * @title DiamondDeployment\\n`;\n source += ` * @notice Auto-generated deployment data for ${diamondName}\\n`;\n source += ` * @dev This library provides constants and helper functions for accessing\\n`;\n source += ` * deployment data in Forge tests. It is auto-generated from the deployment\\n`;\n source += ` * record and should not be edited manually.\\n`;\n source += ` *\\n`;\n source += ` * Generated from: ${deploymentFilePath}\\n`;\n source += ` * Generated at: ${timestamp}\\n`;\n source += ` *\\n`;\n source += ` * To regenerate this file:\\n`;\n source += ` * npx hardhat diamonds-forge:generate-helpers --diamond ${diamondName}\\n`;\n source += ` *\\n`;\n source += ` * ⚠️ DO NOT EDIT MANUALLY - Changes will be overwritten on next generation\\n`;\n source += \" */\\n\";\n source += \"library DiamondDeployment {\\n\";\n\n // Diamond name\n source += ` /// @notice Name of the Diamond contract\\n`;\n source += ` /// @dev Used for identifying the Diamond in tests\\n`;\n source += ` string constant DIAMOND_NAME = \"${diamondName}\";\\n\\n`;\n\n // Diamond ABI path\n source += ` /// @notice Path to the Diamond ABI file\\n`;\n source += ` /// @dev Used by DiamondFuzzBase to load ABI for testing\\n`;\n source += ` string constant DIAMOND_ABI_PATH = \"./diamond-abi/${diamondName}.json\";\\n\\n`;\n\n // Diamond address\n source += ` /// @notice Address of the deployed ${diamondName} contract\\n`;\n source += ` /// @dev This is the main Diamond proxy address\\n`;\n source += ` address constant DIAMOND_ADDRESS = ${deploymentData.DiamondAddress};\\n\\n`;\n\n // Deployer address\n source += ` /// @notice Address of the deployer account\\n`;\n source += ` /// @dev Account that deployed the Diamond\\n`;\n source += ` address constant DEPLOYER_ADDRESS = ${deploymentData.DeployerAddress};\\n\\n`;\n\n // Facet addresses\n source += \" // ========================================\\n\";\n source += \" // Facet Addresses\\n\";\n source += \" // ========================================\\n\\n\";\n\n const facets = deploymentData.DeployedFacets ?? {};\n for (const [facetName, facetData] of Object.entries(facets)) {\n const constantName = facetName\n .replace(/Facet$/, \"\")\n .replace(/([A-Z])/g, \"_$1\")\n .toUpperCase()\n .replace(/^_/, \"\") + \"_FACET\";\n\n source += ` /// @notice Address of ${facetName} implementation\\n`;\n source += ` address constant ${constantName} = ${facetData.address};\\n`;\n }\n source += \"\\n\";\n\n // Helper functions\n source += \" // ========================================\\n\";\n source += \" // Helper Functions\\n\";\n source += \" // ========================================\\n\\n\";\n\n source += \" /**\\n\";\n source += \" * @notice Get the Diamond name\\n\";\n source += \" * @return The name of the Diamond contract\\n\";\n source += \" */\\n\";\n source += \" function getDiamondName() internal pure returns (string memory) {\\n\";\n source += \" return DIAMOND_NAME;\\n\";\n source += \" }\\n\\n\";\n\n source += \" /**\\n\";\n source += \" * @notice Get the path to the Diamond ABI file\\n\";\n source += \" * @return The path to the Diamond ABI JSON file\\n\";\n source += \" */\\n\";\n source += \" function getDiamondABIPath() internal pure returns (string memory) {\\n\";\n source += \" return DIAMOND_ABI_PATH;\\n\";\n source += \" }\\n\\n\";\n\n source += \" /**\\n\";\n source += \" * @notice Get the Diamond contract address\\n\";\n source += \" * @return The address of the deployed Diamond proxy\\n\";\n source += \" */\\n\";\n source += \" function getDiamondAddress() internal pure returns (address) {\\n\";\n source += \" return DIAMOND_ADDRESS;\\n\";\n source += \" }\\n\\n\";\n\n source += \" /**\\n\";\n source += \" * @notice Get the deployer address\\n\";\n source += \" * @return The address of the deployer account\\n\";\n source += \" */\\n\";\n source += \" function getDeployerAddress() internal pure returns (address) {\\n\";\n source += \" return DEPLOYER_ADDRESS;\\n\";\n source += \" }\\n\\n\";\n\n source += \" /**\\n\";\n source += \" * @notice Get facet implementation address by name\\n\";\n source += \" * @param facetName The name of the facet\\n\";\n source += \" * @return The address of the facet implementation\\n\";\n source += \" */\\n\";\n source += \" function getFacetAddress(string memory facetName) internal pure returns (address) {\\n\";\n\n let firstFacet = true;\n for (const [facetName, facetData] of Object.entries(facets)) {\n const constantName = facetName\n .replace(/Facet$/, \"\")\n .replace(/([A-Z])/g, \"_$1\")\n .toUpperCase()\n .replace(/^_/, \"\") + \"_FACET\";\n\n const condition = firstFacet ? \"if\" : \"else if\";\n source += ` ${condition} (keccak256(bytes(facetName)) == keccak256(bytes(\"${facetName}\"))) {\\n`;\n source += ` return ${constantName};\\n`;\n source += \" }\\n\";\n firstFacet = false;\n }\n source += \" return address(0);\\n\";\n source += \" }\\n\";\n\n source += \"}\\n\";\n\n return source;\n }\n}\n"]}
1
+ {"version":3,"file":"HelperGenerator.js","sourceRoot":"","sources":["../../src/framework/HelperGenerator.ts"],"names":[],"mappings":"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","sourcesContent":["import { DeployedDiamondData, Diamond } from \"@diamondslab/diamonds\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { HardhatRuntimeEnvironment } from \"hardhat/types\";\nimport { join } from \"path\";\nimport { Logger } from \"../utils/logger\";\n\n/**\n * HelperGenerator - Generates Solidity helper files for testing\n */\nexport class HelperGenerator {\n constructor(private hre: HardhatRuntimeEnvironment) {}\n\n /**\n * Scaffold project with initial test structure\n */\n async scaffoldProject(outputDir?: string): Promise<void> {\n const helpersDir = outputDir || this.hre.diamondsFoundry.helpersDir;\n const basePath = join(this.hre.config.paths.root, helpersDir);\n\n Logger.section(\"Scaffolding Forge Test Structure\");\n \n // Create directories\n Logger.step(\"Creating directories...\");\n mkdirSync(basePath, { recursive: true });\n mkdirSync(join(basePath, \"../unit\"), { recursive: true });\n mkdirSync(join(basePath, \"../integration\"), { recursive: true });\n mkdirSync(join(basePath, \"../fuzz\"), { recursive: true });\n\n Logger.success(`Test structure created at ${basePath}`);\n }\n\n /**\n * Generate DiamondDeployment.sol from deployment record\n * Also sets DIAMOND_ADDRESS and DIAMOND_ABI_PATH environment variables for Forge tests\n */\n async generateDeploymentHelpers(\n diamondName: string,\n networkName: string,\n chainId: number,\n deploymentData: DeployedDiamondData,\n diamond?: any // Diamond instance from @diamondslab/hardhat-diamonds\n ): Promise<string> {\n Logger.section(\"Generating Diamond Deployment Helper\");\n\n const helpersDir = this.hre.diamondsFoundry.helpersDir;\n const outputPath = join(\n this.hre.config.paths.root,\n helpersDir,\n \"DiamondDeployment.sol\"\n );\n\n const content = this.generateLibrarySource(\n diamondName,\n networkName,\n chainId,\n deploymentData\n );\n\n // Ensure directory exists\n mkdirSync(join(this.hre.config.paths.root, helpersDir), {\n recursive: true,\n });\n\n // Write file\n writeFileSync(outputPath, content, \"utf8\");\n\n Logger.success(`Generated: ${outputPath}`);\n\n // Set environment variables for Forge tests (if Diamond instance provided)\n if (diamond) {\n this.setForgeEnvironmentVariables(diamond, deploymentData);\n }\n\n return outputPath;\n }\n\n /**\n * Set environment variables for Forge tests\n * @private\n */\n private setForgeEnvironmentVariables(\n diamond: Diamond,\n deploymentData: DeployedDiamondData\n ): void {\n try {\n // Get Diamond ABI path - remove leading \"./\" for Foundry compatibility\n let abiPath = diamond.getDiamondAbiFilePath?.() || `diamond-abi/${diamond.getDiamondConfig().diamondName}.json` || `diamond-abi/Diamond.json`;\n // Normalize path - remove leading \"./\" if present\n if (abiPath.startsWith('./')) {\n abiPath = abiPath.substring(2);\n }\n \n // Get Diamond address\n const diamondAddress = deploymentData.DiamondAddress;\n\n // Set environment variables\n process.env.DIAMOND_ABI_PATH = abiPath;\n process.env.DIAMOND_ADDRESS = diamondAddress;\n\n Logger.info(`Set DIAMOND_ABI_PATH: ${abiPath}`);\n Logger.info(`Set DIAMOND_ADDRESS: ${diamondAddress}`);\n } catch (error: any) {\n Logger.warn(`Failed to set environment variables: ${error.message}`);\n Logger.warn(\"Tests can still use DiamondDeployment.sol overrides\");\n }\n }\n\n /**\n * Generate example test files\n */\n async generateExampleTests(): Promise<string[]> {\n const generated: string[] = [];\n const examples = this.hre.diamondsFoundry.exampleTests;\n\n if (!this.hre.diamondsFoundry.generateExamples) {\n Logger.info(\"Example generation disabled in config\");\n return generated;\n }\n\n Logger.section(\"Generating Example Tests\");\n\n const basePath = join(this.hre.config.paths.root, \"test\", \"foundry\");\n const templatesPath = join(__dirname, \"../templates\");\n\n for (const type of examples) {\n let templateFile = \"\";\n let outputPath = \"\";\n\n switch (type) {\n case \"unit\":\n templateFile = join(templatesPath, \"ExampleUnitTest.t.sol.template\");\n outputPath = join(basePath, \"unit\", \"ExampleUnit.t.sol\");\n break;\n case \"integration\":\n templateFile = join(templatesPath, \"ExampleIntegrationTest.t.sol.template\");\n outputPath = join(basePath, \"integration\", \"ExampleIntegration.t.sol\");\n break;\n case \"fuzz\":\n templateFile = join(templatesPath, \"ExampleFuzzTest.t.sol.template\");\n outputPath = join(basePath, \"fuzz\", \"ExampleFuzz.t.sol\");\n break;\n default:\n Logger.warn(`Unknown example type: ${type}`);\n continue;\n }\n\n try {\n // Check if template exists\n if (!existsSync(templateFile)) {\n Logger.warn(`Template not found: ${templateFile}`);\n continue;\n }\n\n // Read template content\n const templateContent = readFileSync(templateFile, \"utf8\");\n\n // Ensure output directory exists\n mkdirSync(join(basePath, type), { recursive: true });\n\n // Check if file already exists\n if (existsSync(outputPath)) {\n Logger.info(`Skipping ${type} example (already exists): ${outputPath}`);\n continue;\n }\n\n // Write example test file\n writeFileSync(outputPath, templateContent, \"utf8\");\n Logger.success(`Generated ${type} example: ${outputPath}`);\n generated.push(outputPath);\n } catch (error: any) {\n Logger.error(`Failed to generate ${type} example: ${error.message}`);\n }\n }\n\n if (generated.length === 0) {\n Logger.info(\"No new example tests generated (may already exist)\");\n }\n\n return generated;\n }\n\n /**\n * Generate Solidity library source from deployment data\n * @private\n */\n private generateLibrarySource(\n diamondName: string,\n networkName: string,\n chainId: number,\n deploymentData: DeployedDiamondData\n ): string {\n const timestamp = new Date().toISOString();\n const networkInfo = `${networkName}-${chainId}`;\n const deploymentFileName = `${diamondName.toLowerCase()}-${networkInfo}.json`;\n const deploymentFilePath = `diamonds/${diamondName}/deployments/${deploymentFileName}`;\n\n let source = \"\";\n\n // SPDX and pragma\n source += \"// SPDX-License-Identifier: MIT\\n\";\n source += \"pragma solidity ^0.8.19;\\n\\n\";\n\n // Header comments\n source += \"/**\\n\";\n source += ` * @title DiamondDeployment\\n`;\n source += ` * @notice Auto-generated deployment data for ${diamondName}\\n`;\n source += ` * @dev This library provides constants and helper functions for accessing\\n`;\n source += ` * deployment data in Forge tests. It is auto-generated from the deployment\\n`;\n source += ` * record and should not be edited manually.\\n`;\n source += ` *\\n`;\n source += ` * Generated from: ${deploymentFilePath}\\n`;\n source += ` * Generated at: ${timestamp}\\n`;\n source += ` *\\n`;\n source += ` * To regenerate this file:\\n`;\n source += ` * npx hardhat diamonds-forge:generate-helpers --diamond ${diamondName}\\n`;\n source += ` *\\n`;\n source += ` * ⚠️ DO NOT EDIT MANUALLY - Changes will be overwritten on next generation\\n`;\n source += \" */\\n\";\n source += \"library DiamondDeployment {\\n\";\n\n // Diamond name\n source += ` /// @notice Name of the Diamond contract\\n`;\n source += ` /// @dev Used for identifying the Diamond in tests\\n`;\n source += ` string constant DIAMOND_NAME = \"${diamondName}\";\\n\\n`;\n\n // Diamond ABI path\n source += ` /// @notice Path to the Diamond ABI file\\n`;\n source += ` /// @dev Used by DiamondFuzzBase to load ABI for testing\\n`;\n source += ` string constant DIAMOND_ABI_PATH = \"diamond-abi/${diamondName}.json\";\\n\\n`;\n\n // Diamond address\n source += ` /// @notice Address of the deployed ${diamondName} contract\\n`;\n source += ` /// @dev This is the main Diamond proxy address\\n`;\n source += ` address constant DIAMOND_ADDRESS = ${deploymentData.DiamondAddress};\\n\\n`;\n\n // Deployer address\n source += ` /// @notice Address of the deployer account\\n`;\n source += ` /// @dev Account that deployed the Diamond\\n`;\n source += ` address constant DEPLOYER_ADDRESS = ${deploymentData.DeployerAddress};\\n\\n`;\n\n // Facet addresses\n source += \" // ========================================\\n\";\n source += \" // Facet Addresses\\n\";\n source += \" // ========================================\\n\\n\";\n\n const facets = deploymentData.DeployedFacets ?? {};\n for (const [facetName, facetData] of Object.entries(facets)) {\n const constantName = facetName\n .replace(/Facet$/, \"\")\n .replace(/([A-Z])/g, \"_$1\")\n .toUpperCase()\n .replace(/^_/, \"\") + \"_FACET\";\n\n source += ` /// @notice Address of ${facetName} implementation\\n`;\n source += ` address constant ${constantName} = ${facetData.address};\\n`;\n }\n source += \"\\n\";\n\n // Helper functions\n source += \" // ========================================\\n\";\n source += \" // Helper Functions\\n\";\n source += \" // ========================================\\n\\n\";\n\n source += \" /**\\n\";\n source += \" * @notice Get the Diamond name\\n\";\n source += \" * @return The name of the Diamond contract\\n\";\n source += \" */\\n\";\n source += \" function getDiamondName() internal pure returns (string memory) {\\n\";\n source += \" return DIAMOND_NAME;\\n\";\n source += \" }\\n\\n\";\n\n source += \" /**\\n\";\n source += \" * @notice Get the path to the Diamond ABI file\\n\";\n source += \" * @return The path to the Diamond ABI JSON file\\n\";\n source += \" */\\n\";\n source += \" function getDiamondABIPath() internal pure returns (string memory) {\\n\";\n source += \" return DIAMOND_ABI_PATH;\\n\";\n source += \" }\\n\\n\";\n\n source += \" /**\\n\";\n source += \" * @notice Get the Diamond contract address\\n\";\n source += \" * @return The address of the deployed Diamond proxy\\n\";\n source += \" */\\n\";\n source += \" function getDiamondAddress() internal pure returns (address) {\\n\";\n source += \" return DIAMOND_ADDRESS;\\n\";\n source += \" }\\n\\n\";\n\n source += \" /**\\n\";\n source += \" * @notice Get the deployer address\\n\";\n source += \" * @return The address of the deployer account\\n\";\n source += \" */\\n\";\n source += \" function getDeployerAddress() internal pure returns (address) {\\n\";\n source += \" return DEPLOYER_ADDRESS;\\n\";\n source += \" }\\n\\n\";\n\n source += \" /**\\n\";\n source += \" * @notice Get facet implementation address by name\\n\";\n source += \" * @param facetName The name of the facet\\n\";\n source += \" * @return The address of the facet implementation\\n\";\n source += \" */\\n\";\n source += \" function getFacetAddress(string memory facetName) internal pure returns (address) {\\n\";\n\n let firstFacet = true;\n for (const [facetName, facetData] of Object.entries(facets)) {\n const constantName = facetName\n .replace(/Facet$/, \"\")\n .replace(/([A-Z])/g, \"_$1\")\n .toUpperCase()\n .replace(/^_/, \"\") + \"_FACET\";\n\n const condition = firstFacet ? \"if\" : \"else if\";\n source += ` ${condition} (keccak256(bytes(facetName)) == keccak256(bytes(\"${facetName}\"))) {\\n`;\n source += ` return ${constantName};\\n`;\n source += \" }\\n\";\n firstFacet = false;\n }\n source += \" return address(0);\\n\";\n source += \" }\\n\";\n\n source += \"}\\n\";\n\n return source;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diamondslab/diamonds-hardhat-foundry",
3
- "version": "2.2.1",
3
+ "version": "2.2.3",
4
4
  "description": "Hardhat plugin that integrates Foundry testing with Diamond proxy contracts, providing deployment helpers and fuzzing support",
5
5
  "repository": {
6
6
  "type": "git",
@@ -114,11 +114,13 @@ export class ForgeFuzzingFramework {
114
114
 
115
115
  const deploymentData = deployment.getDeployedDiamondData();
116
116
 
117
+ // Generate helpers and set environment variables
117
118
  await this.helperGenerator.generateDeploymentHelpers(
118
119
  diamondName,
119
120
  networkName,
120
121
  chainId,
121
- deploymentData
122
+ deploymentData,
123
+ deployment // Pass Diamond instance for env var setup
122
124
  );
123
125
  } else {
124
126
  Logger.info("Skipping helper generation");
@@ -205,11 +207,13 @@ export class ForgeFuzzingFramework {
205
207
 
206
208
  const deploymentData = deployment.getDeployedDiamondData();
207
209
 
210
+ // Generate helpers and set environment variables
208
211
  return await this.helperGenerator.generateDeploymentHelpers(
209
212
  diamondName,
210
213
  networkName,
211
214
  chainId,
212
- deploymentData
215
+ deploymentData,
216
+ deployment // Pass Diamond instance for env var setup
213
217
  );
214
218
  }
215
219
  }
@@ -1,4 +1,4 @@
1
- import { DeployedDiamondData } from "@diamondslab/diamonds";
1
+ import { DeployedDiamondData, Diamond } from "@diamondslab/diamonds";
2
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
3
3
  import { HardhatRuntimeEnvironment } from "hardhat/types";
4
4
  import { join } from "path";
@@ -31,12 +31,14 @@ export class HelperGenerator {
31
31
 
32
32
  /**
33
33
  * Generate DiamondDeployment.sol from deployment record
34
+ * Also sets DIAMOND_ADDRESS and DIAMOND_ABI_PATH environment variables for Forge tests
34
35
  */
35
36
  async generateDeploymentHelpers(
36
37
  diamondName: string,
37
38
  networkName: string,
38
39
  chainId: number,
39
- deploymentData: DeployedDiamondData
40
+ deploymentData: DeployedDiamondData,
41
+ diamond?: any // Diamond instance from @diamondslab/hardhat-diamonds
40
42
  ): Promise<string> {
41
43
  Logger.section("Generating Diamond Deployment Helper");
42
44
 
@@ -63,9 +65,46 @@ export class HelperGenerator {
63
65
  writeFileSync(outputPath, content, "utf8");
64
66
 
65
67
  Logger.success(`Generated: ${outputPath}`);
68
+
69
+ // Set environment variables for Forge tests (if Diamond instance provided)
70
+ if (diamond) {
71
+ this.setForgeEnvironmentVariables(diamond, deploymentData);
72
+ }
73
+
66
74
  return outputPath;
67
75
  }
68
76
 
77
+ /**
78
+ * Set environment variables for Forge tests
79
+ * @private
80
+ */
81
+ private setForgeEnvironmentVariables(
82
+ diamond: Diamond,
83
+ deploymentData: DeployedDiamondData
84
+ ): void {
85
+ try {
86
+ // Get Diamond ABI path - remove leading "./" for Foundry compatibility
87
+ let abiPath = diamond.getDiamondAbiFilePath?.() || `diamond-abi/${diamond.getDiamondConfig().diamondName}.json` || `diamond-abi/Diamond.json`;
88
+ // Normalize path - remove leading "./" if present
89
+ if (abiPath.startsWith('./')) {
90
+ abiPath = abiPath.substring(2);
91
+ }
92
+
93
+ // Get Diamond address
94
+ const diamondAddress = deploymentData.DiamondAddress;
95
+
96
+ // Set environment variables
97
+ process.env.DIAMOND_ABI_PATH = abiPath;
98
+ process.env.DIAMOND_ADDRESS = diamondAddress;
99
+
100
+ Logger.info(`Set DIAMOND_ABI_PATH: ${abiPath}`);
101
+ Logger.info(`Set DIAMOND_ADDRESS: ${diamondAddress}`);
102
+ } catch (error: any) {
103
+ Logger.warn(`Failed to set environment variables: ${error.message}`);
104
+ Logger.warn("Tests can still use DiamondDeployment.sol overrides");
105
+ }
106
+ }
107
+
69
108
  /**
70
109
  * Generate example test files
71
110
  */
@@ -187,7 +226,7 @@ export class HelperGenerator {
187
226
  // Diamond ABI path
188
227
  source += ` /// @notice Path to the Diamond ABI file\n`;
189
228
  source += ` /// @dev Used by DiamondFuzzBase to load ABI for testing\n`;
190
- source += ` string constant DIAMOND_ABI_PATH = "./diamond-abi/${diamondName}.json";\n\n`;
229
+ source += ` string constant DIAMOND_ABI_PATH = "diamond-abi/${diamondName}.json";\n\n`;
191
230
 
192
231
  // Diamond address
193
232
  source += ` /// @notice Address of the deployed ${diamondName} contract\n`;