@diamondslab/diamonds-hardhat-foundry 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/LICENSE +21 -0
- package/README.md +493 -0
- package/contracts/DiamondForgeHelpers.sol +96 -0
- package/contracts/DiamondFuzzBase.sol +128 -0
- package/package.json +78 -0
- package/src/foundry.ts +134 -0
- package/src/framework/DeploymentManager.ts +210 -0
- package/src/framework/ForgeFuzzingFramework.ts +194 -0
- package/src/framework/HelperGenerator.ts +246 -0
- package/src/index.ts +166 -0
- package/src/tasks/deploy.ts +110 -0
- package/src/tasks/generate-helpers.ts +101 -0
- package/src/tasks/init.ts +90 -0
- package/src/tasks/test.ts +108 -0
- package/src/templates/DiamondDeployment.sol.template +38 -0
- package/src/templates/ExampleFuzzTest.t.sol.template +109 -0
- package/src/templates/ExampleIntegrationTest.t.sol.template +79 -0
- package/src/templates/ExampleUnitTest.t.sol.template +59 -0
- package/src/types/config.ts +54 -0
- package/src/types/hardhat.ts +24 -0
- package/src/utils/foundry.ts +189 -0
- package/src/utils/logger.ts +66 -0
- package/src/utils/validation.ts +144 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2025-12-15
|
|
9
|
+
|
|
10
|
+
Initial public release of `@diamondslab/diamonds-hardhat-foundry`.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Initial release of `@diamondslab/diamonds-hardhat-foundry`
|
|
14
|
+
- Core framework classes for Diamond deployment and testing:
|
|
15
|
+
- `DeploymentManager` - Manages Diamond contract deployments
|
|
16
|
+
- `HelperGenerator` - Generates Solidity test helpers and scaffolding
|
|
17
|
+
- `ForgeFuzzingFramework` - Orchestrates complete test workflows
|
|
18
|
+
- Four Hardhat tasks for Diamond + Foundry workflow:
|
|
19
|
+
- `diamonds-forge:init` - Initialize test directory structure
|
|
20
|
+
- `diamonds-forge:deploy` - Deploy Diamond contracts
|
|
21
|
+
- `diamonds-forge:generate-helpers` - Generate DiamondDeployment.sol helpers
|
|
22
|
+
- `diamonds-forge:test` - Run Foundry tests with deployment orchestration
|
|
23
|
+
- Base Solidity contracts for testing:
|
|
24
|
+
- `DiamondForgeHelpers.sol` - Utility functions for Diamond testing
|
|
25
|
+
- `DiamondFuzzBase.sol` - Abstract base contract for fuzz tests
|
|
26
|
+
- Template system for generating:
|
|
27
|
+
- `DiamondDeployment.sol` - Generated deployment data helper
|
|
28
|
+
- Example unit tests (`ExampleUnitTest.t.sol`)
|
|
29
|
+
- Example integration tests (`ExampleIntegrationTest.t.sol`)
|
|
30
|
+
- Example fuzz tests (`ExampleFuzzTest.t.sol`)
|
|
31
|
+
- Configuration system via `hardhat.config.ts`:
|
|
32
|
+
- `diamondsFoundry.helpersDir` - Configure helper output directory
|
|
33
|
+
- `diamondsFoundry.generateExamples` - Toggle example generation
|
|
34
|
+
- `diamondsFoundry.exampleTests` - Select example test types
|
|
35
|
+
- `diamondsFoundry.defaultNetwork` - Set default deployment network
|
|
36
|
+
- `diamondsFoundry.reuseDeployment` - Enable deployment reuse
|
|
37
|
+
- `diamondsFoundry.forgeTestArgs` - Default Forge test arguments
|
|
38
|
+
- Comprehensive validation:
|
|
39
|
+
- Foundry installation check
|
|
40
|
+
- Peer dependency validation
|
|
41
|
+
- Configuration validation with helpful error messages
|
|
42
|
+
- Colored logging with `picocolors` for better UX
|
|
43
|
+
- Integration with `@diamondslab/diamonds` ecosystem:
|
|
44
|
+
- Uses `LocalDiamondDeployer` from workspace
|
|
45
|
+
- Reads deployment records from Diamond deployments
|
|
46
|
+
- Compatible with `@diamondslab/hardhat-diamonds` configuration
|
|
47
|
+
- Comprehensive documentation:
|
|
48
|
+
- Full README with Quick Start guide
|
|
49
|
+
- API documentation for all classes and methods
|
|
50
|
+
- Configuration reference with all options
|
|
51
|
+
- Usage examples and workflows
|
|
52
|
+
- Troubleshooting guide
|
|
53
|
+
- Integration guide for existing projects
|
|
54
|
+
|
|
55
|
+
### Testing
|
|
56
|
+
- 61 unit tests covering:
|
|
57
|
+
- Framework class functionality
|
|
58
|
+
- Configuration validation
|
|
59
|
+
- Helper generation
|
|
60
|
+
- Deployment management
|
|
61
|
+
- Error handling
|
|
62
|
+
- Integration tests:
|
|
63
|
+
- Solidity integration tests for workflow verification
|
|
64
|
+
- TypeScript integration tests for API validation
|
|
65
|
+
|
|
66
|
+
[1.0.0]: https://github.com/diamondslab/diamonds-hardhat-foundry/releases/tag/v1.0.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Nomic Foundation
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
# @diamondslab/diamonds-hardhat-foundry
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@diamondslab/diamonds-hardhat-foundry)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
Hardhat plugin that seamlessly integrates Foundry testing with [ERC-2535 Diamond](https://eips.ethereum.org/EIPS/eip-2535) proxy contracts. This plugin provides deployment helpers, test scaffolding, and automated test generation for Diamond-based smart contracts using Foundry's powerful testing framework.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- 🚀 **Automated Diamond Deployment** - Deploy Diamond contracts with a single command
|
|
11
|
+
- 📝 **Helper Generation** - Automatically generate Solidity helpers with deployment data
|
|
12
|
+
- 🧪 **Test Scaffolding** - Create unit, integration, and fuzz test templates
|
|
13
|
+
- 🔧 **Hardhat Tasks** - CLI tasks for init, deploy, generate, and test workflows
|
|
14
|
+
- 🎯 **Programmatic API** - Use framework classes directly in scripts
|
|
15
|
+
- 📚 **Base Contracts** - Reusable Solidity utilities and test base classes
|
|
16
|
+
- ⚡ **Foundry Integration** - Leverage Forge's speed and fuzzing capabilities
|
|
17
|
+
- 🔗 **Diamonds Ecosystem** - Works seamlessly with `@diamondslab/diamonds` and `@diamondslab/hardhat-diamonds`
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install --save-dev @diamondslab/diamonds-hardhat-foundry
|
|
23
|
+
# or
|
|
24
|
+
yarn add -D @diamondslab/diamonds-hardhat-foundry
|
|
25
|
+
# or
|
|
26
|
+
pnpm add -D @diamondslab/diamonds-hardhat-foundry
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Prerequisites
|
|
30
|
+
|
|
31
|
+
- **Foundry**: Install from [getfoundry.sh](https://getfoundry.sh/)
|
|
32
|
+
- **Hardhat**: `^2.26.0` or later
|
|
33
|
+
- **Peer Dependencies**:
|
|
34
|
+
- `@diamondslab/diamonds` - Core Diamond deployment library
|
|
35
|
+
- `@diamondslab/hardhat-diamonds` - Hardhat Diamond configuration helpers
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install --save-dev @diamondslab/diamonds @diamondslab/hardhat-diamonds hardhat
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
### 1. Configure Hardhat
|
|
44
|
+
|
|
45
|
+
Import the plugin in your `hardhat.config.ts`:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import "@diamondslab/diamonds-hardhat-foundry";
|
|
49
|
+
import type { HardhatUserConfig } from "hardhat/config";
|
|
50
|
+
|
|
51
|
+
const config: HardhatUserConfig = {
|
|
52
|
+
solidity: "0.8.28",
|
|
53
|
+
|
|
54
|
+
// Optional: Configure diamonds-foundry settings
|
|
55
|
+
diamondsFoundry: {
|
|
56
|
+
helpersDir: "test/foundry/helpers",
|
|
57
|
+
generateExamples: true,
|
|
58
|
+
exampleTests: ["unit", "integration", "fuzz"],
|
|
59
|
+
defaultNetwork: "hardhat",
|
|
60
|
+
reuseDeployment: false,
|
|
61
|
+
forgeTestArgs: ["-vvv"],
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default config;
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 2. Initialize Test Structure
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npx hardhat diamonds-forge:init
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This creates:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
test/foundry/
|
|
78
|
+
├── helpers/ # Generated Diamond deployment helpers
|
|
79
|
+
├── unit/ # Unit test examples
|
|
80
|
+
├── integration/ # Integration test examples
|
|
81
|
+
└── fuzz/ # Fuzz test examples
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3. Deploy Your Diamond
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx hardhat diamonds-forge:deploy --diamond-name YourDiamond --network hardhat
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 4. Generate Helpers
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npx hardhat diamonds-forge:generate-helpers --diamond-name YourDiamond
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
This generates `test/foundry/helpers/DiamondDeployment.sol` with:
|
|
97
|
+
|
|
98
|
+
- Diamond contract address
|
|
99
|
+
- All facet addresses
|
|
100
|
+
- Helper functions for test setup
|
|
101
|
+
|
|
102
|
+
### 5. Run Foundry Tests
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npx hardhat diamonds-forge:test
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Hardhat Tasks
|
|
109
|
+
|
|
110
|
+
### `diamonds-forge:init`
|
|
111
|
+
|
|
112
|
+
Initialize the Foundry test directory structure.
|
|
113
|
+
|
|
114
|
+
**Options:**
|
|
115
|
+
|
|
116
|
+
- `--helpers-dir <path>` - Custom directory for helpers (default: `test/foundry/helpers`)
|
|
117
|
+
- `--examples` - Generate example tests (default: from config)
|
|
118
|
+
- `--force` - Overwrite existing files
|
|
119
|
+
|
|
120
|
+
**Example:**
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npx hardhat diamonds-forge:init --helpers-dir test/forge/helpers --examples
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `diamonds-forge:deploy`
|
|
127
|
+
|
|
128
|
+
Deploy a Diamond contract to the specified network.
|
|
129
|
+
|
|
130
|
+
**Options:**
|
|
131
|
+
|
|
132
|
+
- `--diamond-name <name>` - Name of the Diamond to deploy (default: from config)
|
|
133
|
+
- `--network <name>` - Network to deploy to (default: `hardhat`)
|
|
134
|
+
- `--reuse` - Reuse existing deployment if found (default: from config)
|
|
135
|
+
- `--force` - Force new deployment even if one exists
|
|
136
|
+
|
|
137
|
+
**Example:**
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npx hardhat diamonds-forge:deploy --diamond-name MyDiamond --network sepolia
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### `diamonds-forge:generate-helpers`
|
|
144
|
+
|
|
145
|
+
Generate Solidity helper contract with deployment data.
|
|
146
|
+
|
|
147
|
+
**Options:**
|
|
148
|
+
|
|
149
|
+
- `--diamond-name <name>` - Name of the Diamond (default: from config)
|
|
150
|
+
- `--output-dir <path>` - Output directory for helpers (default: from config)
|
|
151
|
+
- `--network <name>` - Network to use for deployment data (default: `hardhat`)
|
|
152
|
+
|
|
153
|
+
**Example:**
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
npx hardhat diamonds-forge:generate-helpers --diamond-name MyDiamond --output-dir test/foundry/helpers
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `diamonds-forge:test`
|
|
160
|
+
|
|
161
|
+
Run Foundry tests with optional deployment and helper generation.
|
|
162
|
+
|
|
163
|
+
**Options:**
|
|
164
|
+
|
|
165
|
+
- `--diamond-name <name>` - Diamond to deploy/test (default: from config)
|
|
166
|
+
- `--network <name>` - Network for deployment (default: from config)
|
|
167
|
+
- `--skip-deployment` - Skip deployment step
|
|
168
|
+
- `--skip-helpers` - Skip helper generation step
|
|
169
|
+
- `--match-test <pattern>` - Run tests matching pattern
|
|
170
|
+
- `--match-contract <pattern>` - Run tests in matching contracts
|
|
171
|
+
- `--verbosity <level>` - Forge verbosity level (1-5)
|
|
172
|
+
- `--gas-report` - Show gas usage report
|
|
173
|
+
|
|
174
|
+
**Example:**
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# Run all tests with gas reporting
|
|
178
|
+
npx hardhat diamonds-forge:test --gas-report
|
|
179
|
+
|
|
180
|
+
# Run specific tests with high verbosity
|
|
181
|
+
npx hardhat diamonds-forge:test --match-test "testOwnership" --verbosity 4
|
|
182
|
+
|
|
183
|
+
# Skip deployment (use existing)
|
|
184
|
+
npx hardhat diamonds-forge:test --skip-deployment --match-contract "MyTest"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Programmatic API
|
|
188
|
+
|
|
189
|
+
Use the framework classes directly in your scripts:
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import hre from "hardhat";
|
|
193
|
+
import {
|
|
194
|
+
ForgeFuzzingFramework,
|
|
195
|
+
DeploymentManager,
|
|
196
|
+
HelperGenerator,
|
|
197
|
+
} from "@diamondslab/diamonds-hardhat-foundry";
|
|
198
|
+
|
|
199
|
+
// Deploy a Diamond
|
|
200
|
+
const deployer = new DeploymentManager(hre);
|
|
201
|
+
await deployer.deploy("MyDiamond", "hardhat");
|
|
202
|
+
|
|
203
|
+
// Generate helpers
|
|
204
|
+
const generator = new HelperGenerator(hre);
|
|
205
|
+
await generator.scaffoldProject();
|
|
206
|
+
await generator.generateDeploymentHelpers("MyDiamond", "hardhat");
|
|
207
|
+
|
|
208
|
+
// Run tests
|
|
209
|
+
const framework = new ForgeFuzzingFramework(hre);
|
|
210
|
+
await framework.runTests({
|
|
211
|
+
diamondName: "MyDiamond",
|
|
212
|
+
networkName: "hardhat",
|
|
213
|
+
skipDeployment: false,
|
|
214
|
+
skipHelpers: false,
|
|
215
|
+
forgeTestOptions: {
|
|
216
|
+
matchTest: "testFuzz",
|
|
217
|
+
verbosity: 3,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### DeploymentManager
|
|
223
|
+
|
|
224
|
+
Manages Diamond contract deployments.
|
|
225
|
+
|
|
226
|
+
**Methods:**
|
|
227
|
+
|
|
228
|
+
- `deploy(diamondName, networkName, force?)` - Deploy a Diamond
|
|
229
|
+
- `getDeployment(diamondName, networkName, chainId?)` - Get deployment data
|
|
230
|
+
- `ensureDeployment(diamondName, networkName, force?)` - Deploy if needed
|
|
231
|
+
- `hasDeploymentRecord(diamondName, networkName)` - Check if deployment exists
|
|
232
|
+
|
|
233
|
+
### HelperGenerator
|
|
234
|
+
|
|
235
|
+
Generates Solidity test helpers and examples.
|
|
236
|
+
|
|
237
|
+
**Methods:**
|
|
238
|
+
|
|
239
|
+
- `scaffoldProject(outputDir?, generateExamples?)` - Create test directory structure
|
|
240
|
+
- `generateDeploymentHelpers(diamondName, networkName, outputDir?)` - Generate DiamondDeployment.sol
|
|
241
|
+
- `generateExampleTests(testTypes?, outputDir?)` - Generate example test files
|
|
242
|
+
|
|
243
|
+
### ForgeFuzzingFramework
|
|
244
|
+
|
|
245
|
+
Orchestrates the complete test workflow.
|
|
246
|
+
|
|
247
|
+
**Methods:**
|
|
248
|
+
|
|
249
|
+
- `runTests(options)` - Run complete test workflow
|
|
250
|
+
- `deployOnly(diamondName?, networkName?, force?)` - Deploy only
|
|
251
|
+
- `generateHelpersOnly(diamondName?, networkName?, outputDir?)` - Generate helpers only
|
|
252
|
+
|
|
253
|
+
## Configuration
|
|
254
|
+
|
|
255
|
+
Configure the plugin in `hardhat.config.ts`:
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
export default {
|
|
259
|
+
diamondsFoundry: {
|
|
260
|
+
// Directory for generated helper contracts
|
|
261
|
+
helpersDir: "test/foundry/helpers",
|
|
262
|
+
|
|
263
|
+
// Whether to generate example tests during init
|
|
264
|
+
generateExamples: true,
|
|
265
|
+
|
|
266
|
+
// Types of example tests to generate
|
|
267
|
+
exampleTests: ["unit", "integration", "fuzz"],
|
|
268
|
+
|
|
269
|
+
// Default network for deployments
|
|
270
|
+
defaultNetwork: "hardhat",
|
|
271
|
+
|
|
272
|
+
// Reuse existing deployments instead of redeploying
|
|
273
|
+
reuseDeployment: false,
|
|
274
|
+
|
|
275
|
+
// Default arguments to pass to forge test
|
|
276
|
+
forgeTestArgs: ["-vv", "--gas-report"],
|
|
277
|
+
},
|
|
278
|
+
};
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**Configuration Options:**
|
|
282
|
+
|
|
283
|
+
| Option | Type | Default | Description |
|
|
284
|
+
| ------------------ | ---------- | --------------------------------- | ------------------------------- |
|
|
285
|
+
| `helpersDir` | `string` | `"test/foundry/helpers"` | Directory for generated helpers |
|
|
286
|
+
| `generateExamples` | `boolean` | `true` | Generate example tests on init |
|
|
287
|
+
| `exampleTests` | `array` | `["unit", "integration", "fuzz"]` | Types of examples to generate |
|
|
288
|
+
| `defaultNetwork` | `string` | `"hardhat"` | Default deployment network |
|
|
289
|
+
| `reuseDeployment` | `boolean` | `false` | Reuse existing deployments |
|
|
290
|
+
| `forgeTestArgs` | `string[]` | `[]` | Default forge test arguments |
|
|
291
|
+
|
|
292
|
+
## Base Contracts
|
|
293
|
+
|
|
294
|
+
The plugin provides base Solidity contracts for your tests:
|
|
295
|
+
|
|
296
|
+
### DiamondForgeHelpers
|
|
297
|
+
|
|
298
|
+
Utility functions for Diamond testing:
|
|
299
|
+
|
|
300
|
+
```solidity
|
|
301
|
+
import "@diamondslab/diamonds-hardhat-foundry/contracts/DiamondForgeHelpers.sol";
|
|
302
|
+
|
|
303
|
+
contract MyTest is Test {
|
|
304
|
+
using DiamondForgeHelpers for *;
|
|
305
|
+
|
|
306
|
+
function testDiamond() public {
|
|
307
|
+
address diamond = DiamondForgeHelpers.getDiamondAddress();
|
|
308
|
+
DiamondForgeHelpers.logDiamondInfo(diamond);
|
|
309
|
+
DiamondForgeHelpers.assertValidDiamond(diamond);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### DiamondFuzzBase
|
|
315
|
+
|
|
316
|
+
Base contract for fuzz tests:
|
|
317
|
+
|
|
318
|
+
```solidity
|
|
319
|
+
import "@diamondslab/diamonds-hardhat-foundry/contracts/DiamondFuzzBase.sol";
|
|
320
|
+
|
|
321
|
+
contract MyFuzzTest is DiamondFuzzBase {
|
|
322
|
+
function setUp() public override {
|
|
323
|
+
super.setUp();
|
|
324
|
+
// Your setup
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function testFuzz_Transfer(address to, uint256 amount) public {
|
|
328
|
+
assumeValidAddress(to);
|
|
329
|
+
amount = boundValue(amount, 1, 1000 ether);
|
|
330
|
+
// Test logic
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Usage Examples
|
|
336
|
+
|
|
337
|
+
### Example 1: Deploy and Test
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
# Initialize project
|
|
341
|
+
npx hardhat diamonds-forge:init
|
|
342
|
+
|
|
343
|
+
# Deploy Diamond
|
|
344
|
+
npx hardhat diamonds-forge:deploy --diamond-name MyDiamond
|
|
345
|
+
|
|
346
|
+
# Run tests
|
|
347
|
+
npx hardhat diamonds-forge:test
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Example 2: Custom Workflow
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
import hre from "hardhat";
|
|
354
|
+
import { ForgeFuzzingFramework } from "@diamondslab/diamonds-hardhat-foundry";
|
|
355
|
+
|
|
356
|
+
async function main() {
|
|
357
|
+
const framework = new ForgeFuzzingFramework(hre);
|
|
358
|
+
|
|
359
|
+
// Deploy only
|
|
360
|
+
await framework.deployOnly("MyDiamond", "sepolia");
|
|
361
|
+
|
|
362
|
+
// Generate helpers
|
|
363
|
+
await framework.generateHelpersOnly("MyDiamond", "sepolia");
|
|
364
|
+
|
|
365
|
+
// Run specific tests
|
|
366
|
+
await framework.runTests({
|
|
367
|
+
skipDeployment: true,
|
|
368
|
+
skipHelpers: true,
|
|
369
|
+
forgeTestOptions: {
|
|
370
|
+
matchContract: "MyIntegrationTest",
|
|
371
|
+
verbosity: 4,
|
|
372
|
+
},
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
main().catch(console.error);
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Example 3: CI/CD Integration
|
|
380
|
+
|
|
381
|
+
```yaml
|
|
382
|
+
# .github/workflows/test.yml
|
|
383
|
+
name: Tests
|
|
384
|
+
on: [push, pull_request]
|
|
385
|
+
|
|
386
|
+
jobs:
|
|
387
|
+
foundry-tests:
|
|
388
|
+
runs-on: ubuntu-latest
|
|
389
|
+
steps:
|
|
390
|
+
- uses: actions/checkout@v3
|
|
391
|
+
- uses: foundry-rs/foundry-toolchain@v1
|
|
392
|
+
- uses: actions/setup-node@v3
|
|
393
|
+
with:
|
|
394
|
+
node-version: "18"
|
|
395
|
+
|
|
396
|
+
- run: npm ci
|
|
397
|
+
- run: npx hardhat diamonds-forge:deploy
|
|
398
|
+
- run: npx hardhat diamonds-forge:test --gas-report
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
## Integration with Existing Diamonds Projects
|
|
402
|
+
|
|
403
|
+
This plugin is designed to work seamlessly with existing `@diamondslab/diamonds` projects:
|
|
404
|
+
|
|
405
|
+
1. **Use your existing Diamond configuration** - The plugin reads from your project's Diamond deployment configuration
|
|
406
|
+
2. **LocalDiamondDeployer integration** - Works with your project's `LocalDiamondDeployer` class
|
|
407
|
+
3. **Deployment records** - Uses the same deployment record format as `@diamondslab/diamonds`
|
|
408
|
+
4. **Hardhat configuration** - Integrates with `@diamondslab/hardhat-diamonds` settings
|
|
409
|
+
|
|
410
|
+
**Example with existing Diamond:**
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
// Your existing hardhat.config.ts
|
|
414
|
+
import "@diamondslab/hardhat-diamonds";
|
|
415
|
+
import "@diamondslab/diamonds-hardhat-foundry";
|
|
416
|
+
|
|
417
|
+
export default {
|
|
418
|
+
diamonds: {
|
|
419
|
+
diamondsPath: "./diamonds",
|
|
420
|
+
deploymentsPath: "./diamonds/ExampleDiamond/deployments",
|
|
421
|
+
},
|
|
422
|
+
diamondsFoundry: {
|
|
423
|
+
helpersDir: "test/foundry/helpers",
|
|
424
|
+
defaultNetwork: "hardhat",
|
|
425
|
+
},
|
|
426
|
+
};
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## Troubleshooting
|
|
430
|
+
|
|
431
|
+
### Foundry Not Found
|
|
432
|
+
|
|
433
|
+
**Error:** `Foundry not installed`
|
|
434
|
+
|
|
435
|
+
**Solution:** Install Foundry from [getfoundry.sh](https://getfoundry.sh/):
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
curl -L https://foundry.paradigm.xyz | bash
|
|
439
|
+
foundryup
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### LocalDiamondDeployer Not Found
|
|
443
|
+
|
|
444
|
+
**Error:** `LocalDiamondDeployer not found`
|
|
445
|
+
|
|
446
|
+
**Solution:** Ensure you have a `LocalDiamondDeployer` class in your project at `scripts/setup/LocalDiamondDeployer.ts`. This is required for Diamond deployments.
|
|
447
|
+
|
|
448
|
+
### Deployment Record Not Found
|
|
449
|
+
|
|
450
|
+
**Error:** `No deployment record found`
|
|
451
|
+
|
|
452
|
+
**Solution:** Deploy your Diamond first:
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
npx hardhat diamonds-forge:deploy --diamond-name YourDiamond
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### Generated Helpers Not Compiling
|
|
459
|
+
|
|
460
|
+
**Error:** Compilation errors in `DiamondDeployment.sol`
|
|
461
|
+
|
|
462
|
+
**Solution:** Ensure:
|
|
463
|
+
|
|
464
|
+
1. Foundry is properly installed
|
|
465
|
+
2. Your `foundry.toml` includes the correct remappings
|
|
466
|
+
3. The Diamond was successfully deployed before generating helpers
|
|
467
|
+
|
|
468
|
+
### Peer Dependency Warnings
|
|
469
|
+
|
|
470
|
+
**Warning:** `@diamondslab/diamonds not found`
|
|
471
|
+
|
|
472
|
+
**Solution:** Install required peer dependencies:
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
npm install --save-dev @diamondslab/diamonds @diamondslab/hardhat-diamonds
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## Contributing
|
|
479
|
+
|
|
480
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
481
|
+
|
|
482
|
+
## License
|
|
483
|
+
|
|
484
|
+
MIT © [DiamondsLab](https://github.com/diamondslab)
|
|
485
|
+
|
|
486
|
+
## Links
|
|
487
|
+
|
|
488
|
+
- [GitHub Repository](https://github.com/diamondslab/diamonds-hardhat-foundry)
|
|
489
|
+
- [npm Package](https://www.npmjs.com/package/@diamondslab/diamonds-hardhat-foundry)
|
|
490
|
+
- [@diamondslab/diamonds](https://github.com/diamondslab/diamonds)
|
|
491
|
+
- [@diamondslab/hardhat-diamonds](https://github.com/diamondslab/hardhat-diamonds)
|
|
492
|
+
- [ERC-2535 Diamond Standard](https://eips.ethereum.org/EIPS/eip-2535)
|
|
493
|
+
- [Foundry Book](https://book.getfoundry.sh/)
|
|
@@ -0,0 +1,96 @@
|
|
|
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
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @title DiamondForgeHelpers
|
|
9
|
+
* @notice Common test utilities for Diamond contract testing with Forge
|
|
10
|
+
* @dev Provides helper functions for accessing Diamond deployment data and logging
|
|
11
|
+
*/
|
|
12
|
+
library DiamondForgeHelpers {
|
|
13
|
+
/**
|
|
14
|
+
* @notice Get the Diamond contract address
|
|
15
|
+
* @param diamondAddress The address of the deployed Diamond
|
|
16
|
+
* @return The Diamond address
|
|
17
|
+
*/
|
|
18
|
+
function getDiamondAddress(address diamondAddress) internal pure returns (address) {
|
|
19
|
+
return diamondAddress;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @notice Get a facet address from the deployment
|
|
24
|
+
* @param facetAddress The address of the facet
|
|
25
|
+
* @return The facet address
|
|
26
|
+
*/
|
|
27
|
+
function getFacetAddress(address facetAddress) internal pure returns (address) {
|
|
28
|
+
return facetAddress;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @notice Log Diamond deployment information
|
|
33
|
+
* @param diamondAddress The Diamond contract address
|
|
34
|
+
* @param facetNames Array of facet names
|
|
35
|
+
* @param facetAddresses Array of facet addresses
|
|
36
|
+
*/
|
|
37
|
+
function logDiamondInfo(
|
|
38
|
+
address diamondAddress,
|
|
39
|
+
string[] memory facetNames,
|
|
40
|
+
address[] memory facetAddresses
|
|
41
|
+
) internal view {
|
|
42
|
+
console.log("=== Diamond Deployment Info ===");
|
|
43
|
+
console.log("Diamond Address:", diamondAddress);
|
|
44
|
+
console.log("Total Facets:", facetAddresses.length);
|
|
45
|
+
|
|
46
|
+
for (uint256 i = 0; i < facetNames.length; i++) {
|
|
47
|
+
console.log("Facet:", facetNames[i]);
|
|
48
|
+
console.log(" Address:", facetAddresses[i]);
|
|
49
|
+
}
|
|
50
|
+
console.log("================================");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @notice Log a single facet's information
|
|
55
|
+
* @param facetName Name of the facet
|
|
56
|
+
* @param facetAddress Address of the facet
|
|
57
|
+
*/
|
|
58
|
+
function logFacetInfo(string memory facetName, address facetAddress) internal view {
|
|
59
|
+
console.log("Facet:", facetName);
|
|
60
|
+
console.log("Address:", facetAddress);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @notice Assert that an address is not zero
|
|
65
|
+
* @param addr The address to check
|
|
66
|
+
* @param message Error message if assertion fails
|
|
67
|
+
*/
|
|
68
|
+
function assertNonZeroAddress(address addr, string memory message) internal pure {
|
|
69
|
+
require(addr != address(0), message);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @notice Assert that Diamond address is valid
|
|
74
|
+
* @param diamondAddress The Diamond address to validate
|
|
75
|
+
*/
|
|
76
|
+
function assertValidDiamond(address diamondAddress) internal pure {
|
|
77
|
+
require(diamondAddress != address(0), "Invalid Diamond address: zero address");
|
|
78
|
+
require(diamondAddress.code.length > 0, "Invalid Diamond address: no code deployed");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @notice Assert that a facet address is valid
|
|
83
|
+
* @param facetAddress The facet address to validate
|
|
84
|
+
* @param facetName Name of the facet for error messaging
|
|
85
|
+
*/
|
|
86
|
+
function assertValidFacet(address facetAddress, string memory facetName) internal pure {
|
|
87
|
+
require(
|
|
88
|
+
facetAddress != address(0),
|
|
89
|
+
string(abi.encodePacked("Invalid ", facetName, ": zero address"))
|
|
90
|
+
);
|
|
91
|
+
require(
|
|
92
|
+
facetAddress.code.length > 0,
|
|
93
|
+
string(abi.encodePacked("Invalid ", facetName, ": no code deployed"))
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|