@diamondslab/diamonds-hardhat-foundry 2.2.0 → 2.2.2
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/contracts/DiamondFuzzBase.sol +32 -3
- package/dist/framework/ForgeFuzzingFramework.d.ts.map +1 -1
- package/dist/framework/ForgeFuzzingFramework.js +6 -2
- package/dist/framework/ForgeFuzzingFramework.js.map +1 -1
- package/dist/framework/HelperGenerator.d.ts +7 -1
- package/dist/framework/HelperGenerator.d.ts.map +1 -1
- package/dist/framework/HelperGenerator.js +50 -1
- package/dist/framework/HelperGenerator.js.map +1 -1
- package/dist/templates/DiamondDeployment.sol.template +38 -0
- package/dist/templates/ExampleFuzzTest.t.sol.template +118 -0
- package/dist/templates/ExampleIntegrationTest.t.sol.template +87 -0
- package/dist/templates/ExampleUnitTest.t.sol.template +65 -0
- package/package.json +1 -1
- package/src/framework/ForgeFuzzingFramework.ts +6 -2
- package/src/framework/HelperGenerator.ts +62 -1
|
@@ -63,8 +63,18 @@ abstract contract DiamondFuzzBase is Test {
|
|
|
63
63
|
|
|
64
64
|
/// @notice Load deployed Diamond address
|
|
65
65
|
/// @dev Override this function to provide custom Diamond address loading logic
|
|
66
|
-
/// @dev
|
|
66
|
+
/// @dev When using generated DiamondDeployment helper, return DiamondDeployment.getDiamondAddress()
|
|
67
67
|
/// @return diamondAddress The deployed Diamond contract address
|
|
68
|
+
/// @custom:example
|
|
69
|
+
/// ```solidity
|
|
70
|
+
/// // Import the generated helper
|
|
71
|
+
/// import {DiamondDeployment} from "test/foundry/helpers/DiamondDeployment.sol";
|
|
72
|
+
///
|
|
73
|
+
/// // Override to use helper's address (automatically matches --diamond-name)
|
|
74
|
+
/// function _loadDiamondAddress() internal view override returns (address) {
|
|
75
|
+
/// return DiamondDeployment.getDiamondAddress();
|
|
76
|
+
/// }
|
|
77
|
+
/// ```
|
|
68
78
|
function _loadDiamondAddress() internal view virtual returns (address diamondAddress) {
|
|
69
79
|
// Try to load from environment variable
|
|
70
80
|
try vm.envAddress("DIAMOND_ADDRESS") returns (address addr) {
|
|
@@ -78,10 +88,29 @@ abstract contract DiamondFuzzBase is Test {
|
|
|
78
88
|
}
|
|
79
89
|
|
|
80
90
|
/// @notice Get the path to the Diamond ABI file
|
|
81
|
-
/// @dev Override this to use a different ABI file path
|
|
91
|
+
/// @dev Override this to use a different ABI file path or return DiamondDeployment.getDiamondABIPath()
|
|
92
|
+
/// @dev When using generated DiamondDeployment helper, you can simply return DiamondDeployment.getDiamondABIPath()
|
|
82
93
|
/// @return abiPath The path to the Diamond ABI JSON file
|
|
94
|
+
/// @custom:example
|
|
95
|
+
/// ```solidity
|
|
96
|
+
/// // Import the generated helper
|
|
97
|
+
/// import {DiamondDeployment} from "test/foundry/helpers/DiamondDeployment.sol";
|
|
98
|
+
///
|
|
99
|
+
/// // Override to use helper's path (automatically matches --diamond-name)
|
|
100
|
+
/// function _getDiamondABIPath() internal view override returns (string memory) {
|
|
101
|
+
/// return DiamondDeployment.getDiamondABIPath();
|
|
102
|
+
/// }
|
|
103
|
+
/// ```
|
|
83
104
|
function _getDiamondABIPath() internal view virtual returns (string memory abiPath) {
|
|
84
|
-
|
|
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
|
+
}
|
|
85
114
|
}
|
|
86
115
|
|
|
87
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;
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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;;;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;IAuBpC;;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,33 @@ 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
|
|
60
|
+
const abiPath = diamond.getDiamondAbiFilePath?.() || `./diamond-abi/${deploymentData.DiamondAddress}.json`;
|
|
61
|
+
// Get Diamond address
|
|
62
|
+
const diamondAddress = deploymentData.DiamondAddress;
|
|
63
|
+
// Set environment variables
|
|
64
|
+
process.env.DIAMOND_ABI_PATH = abiPath;
|
|
65
|
+
process.env.DIAMOND_ADDRESS = diamondAddress;
|
|
66
|
+
logger_1.Logger.info(`Set DIAMOND_ABI_PATH: ${abiPath}`);
|
|
67
|
+
logger_1.Logger.info(`Set DIAMOND_ADDRESS: ${diamondAddress}`);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
logger_1.Logger.warn(`Failed to set environment variables: ${error.message}`);
|
|
71
|
+
logger_1.Logger.warn("Tests can still use DiamondDeployment.sol overrides");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
47
74
|
/**
|
|
48
75
|
* Generate example test files
|
|
49
76
|
*/
|
|
@@ -136,6 +163,14 @@ class HelperGenerator {
|
|
|
136
163
|
source += ` * ⚠️ DO NOT EDIT MANUALLY - Changes will be overwritten on next generation\n`;
|
|
137
164
|
source += " */\n";
|
|
138
165
|
source += "library DiamondDeployment {\n";
|
|
166
|
+
// Diamond name
|
|
167
|
+
source += ` /// @notice Name of the Diamond contract\n`;
|
|
168
|
+
source += ` /// @dev Used for identifying the Diamond in tests\n`;
|
|
169
|
+
source += ` string constant DIAMOND_NAME = "${diamondName}";\n\n`;
|
|
170
|
+
// Diamond ABI path
|
|
171
|
+
source += ` /// @notice Path to the Diamond ABI file\n`;
|
|
172
|
+
source += ` /// @dev Used by DiamondFuzzBase to load ABI for testing\n`;
|
|
173
|
+
source += ` string constant DIAMOND_ABI_PATH = "./diamond-abi/${diamondName}.json";\n\n`;
|
|
139
174
|
// Diamond address
|
|
140
175
|
source += ` /// @notice Address of the deployed ${diamondName} contract\n`;
|
|
141
176
|
source += ` /// @dev This is the main Diamond proxy address\n`;
|
|
@@ -164,6 +199,20 @@ class HelperGenerator {
|
|
|
164
199
|
source += " // Helper Functions\n";
|
|
165
200
|
source += " // ========================================\n\n";
|
|
166
201
|
source += " /**\n";
|
|
202
|
+
source += " * @notice Get the Diamond name\n";
|
|
203
|
+
source += " * @return The name of the Diamond contract\n";
|
|
204
|
+
source += " */\n";
|
|
205
|
+
source += " function getDiamondName() internal pure returns (string memory) {\n";
|
|
206
|
+
source += " return DIAMOND_NAME;\n";
|
|
207
|
+
source += " }\n\n";
|
|
208
|
+
source += " /**\n";
|
|
209
|
+
source += " * @notice Get the path to the Diamond ABI file\n";
|
|
210
|
+
source += " * @return The path to the Diamond ABI JSON file\n";
|
|
211
|
+
source += " */\n";
|
|
212
|
+
source += " function getDiamondABIPath() internal pure returns (string memory) {\n";
|
|
213
|
+
source += " return DIAMOND_ABI_PATH;\n";
|
|
214
|
+
source += " }\n\n";
|
|
215
|
+
source += " /**\n";
|
|
167
216
|
source += " * @notice Get the Diamond contract address\n";
|
|
168
217
|
source += " * @return The address of the deployed Diamond proxy\n";
|
|
169
218
|
source += " */\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 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 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 } 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: any,\n deploymentData: DeployedDiamondData\n ): void {\n try {\n // Get Diamond ABI path\n const abiPath = diamond.getDiamondAbiFilePath?.() || `./diamond-abi/${deploymentData.DiamondAddress}.json`;\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"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @title DiamondDeployment
|
|
6
|
+
* @notice Deployment data for {{DIAMOND_NAME}} on {{NETWORK_NAME}} (Chain ID: {{CHAIN_ID}})
|
|
7
|
+
* @dev Auto-generated by diamonds-hardhat-foundry
|
|
8
|
+
*
|
|
9
|
+
* Generated: {{TIMESTAMP}}
|
|
10
|
+
*/
|
|
11
|
+
library DiamondDeployment {
|
|
12
|
+
// Diamond Contract Address
|
|
13
|
+
address constant DIAMOND_ADDRESS = {{DIAMOND_ADDRESS}};
|
|
14
|
+
|
|
15
|
+
// Deployer Address
|
|
16
|
+
address constant DEPLOYER_ADDRESS = {{DEPLOYER_ADDRESS}};
|
|
17
|
+
|
|
18
|
+
// Facet Addresses
|
|
19
|
+
{{FACET_ADDRESSES}}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @notice Get the Diamond contract address
|
|
23
|
+
* @return The address of the Diamond contract
|
|
24
|
+
*/
|
|
25
|
+
function diamond() internal pure returns (address) {
|
|
26
|
+
return DIAMOND_ADDRESS;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @notice Get the deployer address
|
|
31
|
+
* @return The address that deployed the Diamond
|
|
32
|
+
*/
|
|
33
|
+
function deployer() internal pure returns (address) {
|
|
34
|
+
return DEPLOYER_ADDRESS;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
{{FACET_GETTERS}}
|
|
38
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import "forge-std/Test.sol";
|
|
5
|
+
import "forge-std/console.sol";
|
|
6
|
+
import "@diamondslab/diamonds-hardhat-foundry/contracts/DiamondFuzzBase.sol";
|
|
7
|
+
import "@diamondslab/diamonds-hardhat-foundry/contracts/DiamondForgeHelpers.sol";
|
|
8
|
+
import "../helpers/DiamondDeployment.sol";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @title ExampleFuzzTest
|
|
12
|
+
* @notice Example fuzz test for Diamond contract
|
|
13
|
+
* @dev Uses DiamondFuzzBase for common fuzz testing utilities
|
|
14
|
+
*/
|
|
15
|
+
contract ExampleFuzzTest is DiamondFuzzBase {
|
|
16
|
+
using DiamondForgeHelpers for address;
|
|
17
|
+
|
|
18
|
+
/// @notice Override to load Diamond from deployment
|
|
19
|
+
function _loadDiamondAddress() internal view override returns (address) {
|
|
20
|
+
return DiamondDeployment.diamond();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function setUp() public override {
|
|
24
|
+
super.setUp();
|
|
25
|
+
|
|
26
|
+
console.log("Fuzz test setup complete");
|
|
27
|
+
console.log("Diamond:", diamond);
|
|
28
|
+
console.log("Functions loaded:", diamondSelectors.length);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @notice Fuzz test with random address input
|
|
33
|
+
* @param randomAddress Fuzzed address parameter
|
|
34
|
+
*/
|
|
35
|
+
function testFuzz_AddressInput(address randomAddress) public {
|
|
36
|
+
// Filter invalid addresses
|
|
37
|
+
vm.assume(DiamondForgeHelpers.isValidTestAddress(randomAddress));
|
|
38
|
+
|
|
39
|
+
// TODO: Test your Diamond function with fuzzed address
|
|
40
|
+
// Example:
|
|
41
|
+
// bytes4 selector = bytes4(keccak256("someFunction(address)"));
|
|
42
|
+
// bytes memory data = abi.encode(randomAddress);
|
|
43
|
+
// (bool success,) = _callDiamond(selector, data);
|
|
44
|
+
// assertTrue(success);
|
|
45
|
+
|
|
46
|
+
assertTrue(true, "Replace with actual fuzz test");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @notice Fuzz test with random amount input
|
|
51
|
+
* @param amount Fuzzed amount parameter
|
|
52
|
+
*/
|
|
53
|
+
function testFuzz_AmountInput(uint256 amount) public {
|
|
54
|
+
// Bound the amount to valid range
|
|
55
|
+
vm.assume(DiamondForgeHelpers.isValidTestAmount(amount));
|
|
56
|
+
|
|
57
|
+
// TODO: Test your Diamond function with fuzzed amount
|
|
58
|
+
// Example:
|
|
59
|
+
// bytes4 selector = bytes4(keccak256("transfer(address,uint256)"));
|
|
60
|
+
// bytes memory data = abi.encode(user1, amount);
|
|
61
|
+
// (bool success,) = _callDiamond(selector, data);
|
|
62
|
+
|
|
63
|
+
assertTrue(true, "Replace with actual fuzz test");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @notice Fuzz test with multiple parameters
|
|
68
|
+
* @param addr Fuzzed address
|
|
69
|
+
* @param value Fuzzed value
|
|
70
|
+
* @param data Fuzzed bytes data
|
|
71
|
+
*/
|
|
72
|
+
function testFuzz_MultipleParams(
|
|
73
|
+
address addr,
|
|
74
|
+
uint256 value,
|
|
75
|
+
bytes memory data
|
|
76
|
+
) public {
|
|
77
|
+
// Filter inputs
|
|
78
|
+
vm.assume(DiamondForgeHelpers.isValidTestAddress(addr));
|
|
79
|
+
vm.assume(DiamondForgeHelpers.isValidTestAmount(value));
|
|
80
|
+
vm.assume(data.length > 0);
|
|
81
|
+
vm.assume(data.length < 1024); // Reasonable size limit
|
|
82
|
+
|
|
83
|
+
// TODO: Test with multiple fuzzed parameters
|
|
84
|
+
|
|
85
|
+
assertTrue(true, "Replace with actual multi-param fuzz test");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @notice Fuzz test for failure conditions
|
|
90
|
+
* @param badValue Value that should cause revert
|
|
91
|
+
*/
|
|
92
|
+
function testFuzz_ExpectedRevert(uint256 badValue) public {
|
|
93
|
+
// Set up conditions for expected revert
|
|
94
|
+
vm.assume(badValue > type(uint128).max);
|
|
95
|
+
|
|
96
|
+
// TODO: Test that function reverts with invalid input
|
|
97
|
+
// bytes4 selector = bytes4(keccak256("someFunction(uint256)"));
|
|
98
|
+
// bytes memory data = abi.encode(badValue);
|
|
99
|
+
// _expectDiamondRevert(selector, data, bytes(""));
|
|
100
|
+
|
|
101
|
+
assertTrue(true, "Replace with actual revert fuzz test");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @notice Fuzz test with bounded values
|
|
106
|
+
* @param rawValue Raw fuzzed value
|
|
107
|
+
*/
|
|
108
|
+
function testFuzz_BoundedValue(uint256 rawValue) public {
|
|
109
|
+
// Bound value to specific range (e.g., 1 to 1000)
|
|
110
|
+
uint256 boundedValue = bound(rawValue, 1, 1000);
|
|
111
|
+
|
|
112
|
+
// TODO: Test with bounded value
|
|
113
|
+
assertGe(boundedValue, 1, "Value should be >= 1");
|
|
114
|
+
assertLe(boundedValue, 1000, "Value should be <= 1000");
|
|
115
|
+
|
|
116
|
+
assertTrue(true, "Replace with actual bounded fuzz test");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import "forge-std/Test.sol";
|
|
5
|
+
import "forge-std/console.sol";
|
|
6
|
+
import "@diamondslab/diamonds-hardhat-foundry/contracts/DiamondForgeHelpers.sol";
|
|
7
|
+
import "@diamondslab/diamonds-hardhat-foundry/contracts/DiamondABILoader.sol";
|
|
8
|
+
import "../helpers/DiamondDeployment.sol";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @title ExampleIntegrationTest
|
|
12
|
+
* @notice Example integration test for Diamond contract
|
|
13
|
+
* @dev Tests interactions between multiple facets and Diamond functionality
|
|
14
|
+
*/
|
|
15
|
+
contract ExampleIntegrationTest is Test {
|
|
16
|
+
using DiamondForgeHelpers for address;
|
|
17
|
+
using DiamondABILoader for string;
|
|
18
|
+
|
|
19
|
+
address diamond;
|
|
20
|
+
address deployer;
|
|
21
|
+
|
|
22
|
+
// Test users
|
|
23
|
+
address user1;
|
|
24
|
+
address user2;
|
|
25
|
+
|
|
26
|
+
function setUp() public {
|
|
27
|
+
// Load Diamond deployment data
|
|
28
|
+
diamond = DiamondDeployment.diamond();
|
|
29
|
+
deployer = DiamondDeployment.deployer();
|
|
30
|
+
|
|
31
|
+
// Validate Diamond
|
|
32
|
+
DiamondForgeHelpers.assertValidDiamond(diamond);
|
|
33
|
+
|
|
34
|
+
// Set up test users
|
|
35
|
+
user1 = makeAddr("user1");
|
|
36
|
+
user2 = makeAddr("user2");
|
|
37
|
+
|
|
38
|
+
// Fund test users
|
|
39
|
+
vm.deal(user1, 100 ether);
|
|
40
|
+
vm.deal(user2, 100 ether);
|
|
41
|
+
|
|
42
|
+
console.log("Diamond:", diamond);
|
|
43
|
+
console.log("User1:", user1);
|
|
44
|
+
console.log("User2:", user2);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @notice Test multi-facet interaction workflow
|
|
49
|
+
*/
|
|
50
|
+
function test_MultiFacetWorkflow() public {
|
|
51
|
+
// TODO: Implement your multi-facet workflow test
|
|
52
|
+
// Example:
|
|
53
|
+
// 1. User1 calls function on Facet A
|
|
54
|
+
// 2. Verify state change
|
|
55
|
+
// 3. User2 calls function on Facet B
|
|
56
|
+
// 4. Verify combined state
|
|
57
|
+
|
|
58
|
+
vm.startPrank(user1);
|
|
59
|
+
// Your test logic here
|
|
60
|
+
vm.stopPrank();
|
|
61
|
+
|
|
62
|
+
assertTrue(true, "Replace with actual integration test");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @notice Test cross-facet state management
|
|
67
|
+
*/
|
|
68
|
+
function test_CrossFacetState() public {
|
|
69
|
+
// TODO: Test that state is properly shared/isolated between facets
|
|
70
|
+
|
|
71
|
+
assertTrue(true, "Replace with actual state test");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @notice Test Diamond upgrade scenario (if applicable)
|
|
76
|
+
*/
|
|
77
|
+
function test_DiamondUpgrade() public {
|
|
78
|
+
// TODO: Test facet addition/replacement/removal
|
|
79
|
+
// This requires diamondCut functionality
|
|
80
|
+
|
|
81
|
+
vm.startPrank(deployer);
|
|
82
|
+
// Your upgrade logic here
|
|
83
|
+
vm.stopPrank();
|
|
84
|
+
|
|
85
|
+
assertTrue(true, "Replace with actual upgrade test");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import "forge-std/Test.sol";
|
|
5
|
+
import "forge-std/console.sol";
|
|
6
|
+
import "@diamondslab/diamonds-hardhat-foundry/contracts/DiamondForgeHelpers.sol";
|
|
7
|
+
import "../helpers/DiamondDeployment.sol";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @title ExampleUnitTest
|
|
11
|
+
* @notice Example unit test for Diamond contract
|
|
12
|
+
* @dev This is a template - customize for your specific Diamond implementation
|
|
13
|
+
*/
|
|
14
|
+
contract ExampleUnitTest is Test {
|
|
15
|
+
using DiamondForgeHelpers for address;
|
|
16
|
+
|
|
17
|
+
address diamond;
|
|
18
|
+
address deployer;
|
|
19
|
+
|
|
20
|
+
function setUp() public {
|
|
21
|
+
// Load Diamond deployment data
|
|
22
|
+
diamond = DiamondDeployment.diamond();
|
|
23
|
+
deployer = DiamondDeployment.deployer();
|
|
24
|
+
|
|
25
|
+
console.log("Diamond deployed at:", diamond);
|
|
26
|
+
console.log("Deployed by:", deployer);
|
|
27
|
+
|
|
28
|
+
// Validate Diamond deployment
|
|
29
|
+
DiamondForgeHelpers.assertValidDiamond(diamond);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @notice Test that Diamond was deployed successfully
|
|
34
|
+
*/
|
|
35
|
+
function test_DiamondDeployed() public view {
|
|
36
|
+
// Check that Diamond address is not zero
|
|
37
|
+
assertNotEq(diamond, address(0), "Diamond address should not be zero");
|
|
38
|
+
|
|
39
|
+
// Check that Diamond has code
|
|
40
|
+
uint256 codeSize;
|
|
41
|
+
assembly {
|
|
42
|
+
codeSize := extcodesize(diamond)
|
|
43
|
+
}
|
|
44
|
+
assertGt(codeSize, 0, "Diamond should have code deployed");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @notice Test that deployer address is set correctly
|
|
49
|
+
*/
|
|
50
|
+
function test_DeployerSet() public view {
|
|
51
|
+
assertNotEq(deployer, address(0), "Deployer address should not be zero");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @notice Example test - customize for your Diamond's functionality
|
|
56
|
+
*/
|
|
57
|
+
function test_ExampleFunctionality() public {
|
|
58
|
+
// TODO: Add your Diamond-specific tests here
|
|
59
|
+
// Example:
|
|
60
|
+
// MyDiamond(diamond).someFunction();
|
|
61
|
+
// assertEq(result, expectedValue);
|
|
62
|
+
|
|
63
|
+
assertTrue(true, "Replace this with actual test");
|
|
64
|
+
}
|
|
65
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@diamondslab/diamonds-hardhat-foundry",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
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
|
}
|
|
@@ -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,42 @@ 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: any,
|
|
83
|
+
deploymentData: DeployedDiamondData
|
|
84
|
+
): void {
|
|
85
|
+
try {
|
|
86
|
+
// Get Diamond ABI path
|
|
87
|
+
const abiPath = diamond.getDiamondAbiFilePath?.() || `./diamond-abi/${deploymentData.DiamondAddress}.json`;
|
|
88
|
+
|
|
89
|
+
// Get Diamond address
|
|
90
|
+
const diamondAddress = deploymentData.DiamondAddress;
|
|
91
|
+
|
|
92
|
+
// Set environment variables
|
|
93
|
+
process.env.DIAMOND_ABI_PATH = abiPath;
|
|
94
|
+
process.env.DIAMOND_ADDRESS = diamondAddress;
|
|
95
|
+
|
|
96
|
+
Logger.info(`Set DIAMOND_ABI_PATH: ${abiPath}`);
|
|
97
|
+
Logger.info(`Set DIAMOND_ADDRESS: ${diamondAddress}`);
|
|
98
|
+
} catch (error: any) {
|
|
99
|
+
Logger.warn(`Failed to set environment variables: ${error.message}`);
|
|
100
|
+
Logger.warn("Tests can still use DiamondDeployment.sol overrides");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
69
104
|
/**
|
|
70
105
|
* Generate example test files
|
|
71
106
|
*/
|
|
@@ -179,6 +214,16 @@ export class HelperGenerator {
|
|
|
179
214
|
source += " */\n";
|
|
180
215
|
source += "library DiamondDeployment {\n";
|
|
181
216
|
|
|
217
|
+
// Diamond name
|
|
218
|
+
source += ` /// @notice Name of the Diamond contract\n`;
|
|
219
|
+
source += ` /// @dev Used for identifying the Diamond in tests\n`;
|
|
220
|
+
source += ` string constant DIAMOND_NAME = "${diamondName}";\n\n`;
|
|
221
|
+
|
|
222
|
+
// Diamond ABI path
|
|
223
|
+
source += ` /// @notice Path to the Diamond ABI file\n`;
|
|
224
|
+
source += ` /// @dev Used by DiamondFuzzBase to load ABI for testing\n`;
|
|
225
|
+
source += ` string constant DIAMOND_ABI_PATH = "./diamond-abi/${diamondName}.json";\n\n`;
|
|
226
|
+
|
|
182
227
|
// Diamond address
|
|
183
228
|
source += ` /// @notice Address of the deployed ${diamondName} contract\n`;
|
|
184
229
|
source += ` /// @dev This is the main Diamond proxy address\n`;
|
|
@@ -212,6 +257,22 @@ export class HelperGenerator {
|
|
|
212
257
|
source += " // Helper Functions\n";
|
|
213
258
|
source += " // ========================================\n\n";
|
|
214
259
|
|
|
260
|
+
source += " /**\n";
|
|
261
|
+
source += " * @notice Get the Diamond name\n";
|
|
262
|
+
source += " * @return The name of the Diamond contract\n";
|
|
263
|
+
source += " */\n";
|
|
264
|
+
source += " function getDiamondName() internal pure returns (string memory) {\n";
|
|
265
|
+
source += " return DIAMOND_NAME;\n";
|
|
266
|
+
source += " }\n\n";
|
|
267
|
+
|
|
268
|
+
source += " /**\n";
|
|
269
|
+
source += " * @notice Get the path to the Diamond ABI file\n";
|
|
270
|
+
source += " * @return The path to the Diamond ABI JSON file\n";
|
|
271
|
+
source += " */\n";
|
|
272
|
+
source += " function getDiamondABIPath() internal pure returns (string memory) {\n";
|
|
273
|
+
source += " return DIAMOND_ABI_PATH;\n";
|
|
274
|
+
source += " }\n\n";
|
|
275
|
+
|
|
215
276
|
source += " /**\n";
|
|
216
277
|
source += " * @notice Get the Diamond contract address\n";
|
|
217
278
|
source += " * @return The address of the deployed Diamond proxy\n";
|