Hardhat plugin that integrates Hardhat Ignition with ethers.js for declarative smart contract deployment
npx @tessl/cli install tessl/npm-nomicfoundation--hardhat-ignition-ethers@3.0.00
# Hardhat Ignition Ethers
1
2
Hardhat Ignition Ethers is a Hardhat plugin that integrates Hardhat Ignition with ethers.js, enabling developers to use ethers.js contract instances directly with Hardhat Ignition's declarative smart contract deployment system. The plugin extends network connections with an ignition property that includes a deploy method, allowing users to deploy Ignition modules and receive ethers contract instances for deployed contracts.
3
4
## Package Information
5
6
- **Package Name**: @nomicfoundation/hardhat-ignition-ethers
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install --save-dev @nomicfoundation/hardhat-ignition-ethers`
10
_Note: This package requires peer dependencies: hardhat, @nomicfoundation/hardhat-ethers, @nomicfoundation/hardhat-ignition, @nomicfoundation/ignition-core, and ethers_
11
12
## Core Imports
13
14
```typescript
15
import hardhatIgnitionEthers from "@nomicfoundation/hardhat-ignition-ethers";
16
```
17
18
For CommonJS:
19
20
```javascript
21
const hardhatIgnitionEthers = require("@nomicfoundation/hardhat-ignition-ethers");
22
```
23
24
Type imports for usage:
25
26
```typescript
27
import type { EthersIgnitionHelper } from "@nomicfoundation/hardhat-ignition-ethers";
28
import type {
29
ChainType,
30
DefaultChainType,
31
NetworkConnection
32
} from "hardhat/types/network";
33
import type {
34
IgnitionModule,
35
IgnitionModuleResult,
36
DeploymentParameters,
37
DeployConfig,
38
StrategyConfig
39
} from "@nomicfoundation/ignition-core";
40
import type { Contract } from "ethers";
41
```
42
43
## Basic Usage
44
45
Configure the plugin in your Hardhat configuration:
46
47
```typescript
48
import hardhatIgnitionEthers from "@nomicfoundation/hardhat-ignition-ethers";
49
50
export default {
51
plugins: [hardhatIgnitionEthers],
52
};
53
```
54
55
Deploy Ignition modules with ethers contract instances:
56
57
```typescript
58
import { network } from "hardhat";
59
import { buildModule } from "@nomicfoundation/ignition-core";
60
61
// Define an Ignition module
62
const CounterModule = buildModule("Counter", (m) => {
63
const counter = m.contract("Counter");
64
return { counter };
65
});
66
67
// Deploy and get ethers contract instance
68
const { ignition } = await network.connect();
69
const { counter } = await ignition.deploy(CounterModule);
70
71
// Use the ethers contract instance
72
await counter.inc();
73
console.log(await counter.x());
74
```
75
76
## Architecture
77
78
The plugin is built around these key components:
79
80
- **Plugin Registration**: Integrates with Hardhat's plugin system with required dependencies
81
- **Network Extension**: Adds `ignition` property to network connections via type extensions
82
- **Ethers Integration**: Converts Ignition deployment results to ethers contract instances
83
- **Deployment Management**: Handles complex deployment configuration and strategies
84
- **Mutex Protection**: Prevents concurrent deployments to avoid conflicts
85
86
## Capabilities
87
88
### Plugin Configuration
89
90
The main plugin export that integrates with Hardhat's plugin system.
91
92
```typescript { .api }
93
interface HardhatPlugin {
94
id: "hardhat-ignition-ethers";
95
dependencies: () => Promise<any>[];
96
hookHandlers: {
97
network: () => Promise<Partial<NetworkHooks>>;
98
};
99
npmPackage: "@nomicfoundation/hardhat-ignition-ethers";
100
}
101
102
declare const hardhatIgnitionEthersPlugin: HardhatPlugin;
103
export default hardhatIgnitionEthersPlugin;
104
```
105
106
### Network Connection Extension
107
108
Extends Hardhat's NetworkConnection interface to include the ignition helper and re-exports types from dependencies.
109
110
```typescript { .api }
111
// Re-export all types from dependencies for convenience
112
export type * from "@nomicfoundation/hardhat-ignition";
113
export type * from "@nomicfoundation/hardhat-ethers";
114
115
// Extend NetworkConnection interface
116
declare module "hardhat/types/network" {
117
interface NetworkConnection<
118
ChainTypeT extends ChainType | string = DefaultChainType
119
> {
120
ignition: EthersIgnitionHelper;
121
}
122
}
123
```
124
125
### Ignition Helper Interface
126
127
The core interface providing deployment functionality with ethers integration.
128
129
```typescript { .api }
130
interface EthersIgnitionHelper {
131
type: "ethers";
132
133
/**
134
* Deploys the given Ignition module and returns the results as ethers contract instances
135
* @param ignitionModule - The Ignition module to deploy
136
* @param options - Deployment configuration options
137
* @returns Promise resolving to ethers contract instances for each contract in the module
138
*/
139
deploy<
140
ModuleIdT extends string,
141
ContractNameT extends string,
142
IgnitionModuleResultsT extends IgnitionModuleResult<ContractNameT>,
143
StrategyT extends keyof StrategyConfig = "basic"
144
>(
145
ignitionModule: IgnitionModule<ModuleIdT, ContractNameT, IgnitionModuleResultsT>,
146
options?: {
147
parameters?: DeploymentParameters | string;
148
config?: Partial<DeployConfig>;
149
defaultSender?: string;
150
strategy?: StrategyT;
151
strategyConfig?: StrategyConfig[StrategyT];
152
deploymentId?: string;
153
displayUi?: boolean;
154
}
155
): Promise<IgnitionModuleResultsTToEthersContracts<ContractNameT, IgnitionModuleResultsT>>;
156
}
157
```
158
159
160
### Type Mapping
161
162
Maps Ignition module results to ethers contract instances.
163
164
```typescript { .api }
165
type IgnitionModuleResultsTToEthersContracts<
166
ContractNameT extends string,
167
IgnitionModuleResultsT extends IgnitionModuleResult<ContractNameT>
168
> = {
169
[contract in keyof IgnitionModuleResultsT]: IgnitionModuleResultsT[contract] extends
170
| NamedArtifactContractDeploymentFuture<ContractNameT>
171
| NamedArtifactContractAtFuture<ContractNameT>
172
? TypeChainEthersContractByName<ContractNameT>
173
: Contract;
174
};
175
176
/**
177
* Placeholder type for TypeChain support (currently maps to ethers Contract)
178
*/
179
type TypeChainEthersContractByName<ContractNameT> = Contract;
180
```
181
182
### Core Types
183
184
Essential types imported from dependencies for complete API definition.
185
186
```typescript { .api }
187
// These types are imported from their respective packages:
188
// - IgnitionModule, IgnitionModuleResult, DeploymentParameters, DeployConfig, StrategyConfig from @nomicfoundation/ignition-core
189
// - NamedArtifactContractDeploymentFuture, NamedArtifactContractAtFuture from @nomicfoundation/ignition-core
190
// - Contract from ethers
191
// - ChainType, DefaultChainType, NetworkConnection from hardhat/types/network
192
// - HardhatPlugin from hardhat/types/plugins
193
```
194
195
## Usage Examples
196
197
### Basic Module Deployment
198
199
```typescript
200
import { network } from "hardhat";
201
import { buildModule } from "@nomicfoundation/ignition-core";
202
203
const SimpleModule = buildModule("Simple", (m) => {
204
const token = m.contract("Token", ["My Token", "MTK"]);
205
return { token };
206
});
207
208
const { ignition } = await network.connect();
209
const { token } = await ignition.deploy(SimpleModule);
210
211
// token is now an ethers Contract instance
212
console.log(`Token deployed at: ${token.address}`);
213
const name = await token.name();
214
console.log(`Token name: ${name}`);
215
```
216
217
### Advanced Configuration
218
219
```typescript
220
import { network } from "hardhat";
221
import { buildModule } from "@nomicfoundation/ignition-core";
222
223
const { ignition } = await network.connect();
224
225
// Deploy with custom parameters and configuration
226
const result = await ignition.deploy(MyModule, {
227
parameters: {
228
initialSupply: "1000000",
229
tokenName: "Advanced Token"
230
},
231
config: {
232
gasPrice: "20000000000",
233
timeout: 300000
234
},
235
defaultSender: "0x1234567890123456789012345678901234567890",
236
strategy: "basic",
237
deploymentId: "my-custom-deployment",
238
displayUi: true
239
});
240
```
241
242
### Multiple Contract Deployment
243
244
```typescript
245
const ComplexModule = buildModule("Complex", (m) => {
246
const token = m.contract("Token", ["Test Token", "TEST"]);
247
const exchange = m.contract("Exchange", [token]);
248
const tokenAt = m.contractAt("Token", token, { id: "TokenReference" });
249
250
return { token, exchange, tokenAt };
251
});
252
253
const { token, exchange, tokenAt } = await ignition.deploy(ComplexModule);
254
255
// All returned values are ethers Contract instances
256
await token.mint(await token.owner(), "1000");
257
await exchange.setToken(token.address);
258
console.log(await tokenAt.balanceOf(await token.owner()));
259
```
260
261
## Error Handling
262
263
The plugin throws HardhatError instances for various failure scenarios:
264
265
- **Concurrent Deployment**: Only one deployment can run at a time per helper instance
266
- **Plugin Conflicts**: Only one ignition extension plugin can be active
267
- **Deployment Failures**: Failed deployments include detailed error messages
268
- **Artifact Resolution**: Missing contract artifacts are clearly reported
269
270
```typescript
271
import { HardhatError } from "@nomicfoundation/hardhat-errors";
272
273
try {
274
const result = await ignition.deploy(MyModule);
275
} catch (error) {
276
if (error instanceof HardhatError) {
277
console.log(`Deployment failed: ${error.message}`);
278
}
279
}
280
```
281
282
## Dependencies
283
284
### Peer Dependencies
285
286
These packages must be installed alongside the plugin:
287
288
- `hardhat`: ^3.0.0
289
- `@nomicfoundation/hardhat-ethers`: ^4.0.0
290
- `@nomicfoundation/hardhat-ignition`: ^3.0.2
291
- `@nomicfoundation/ignition-core`: ^3.0.2
292
- `ethers`: ^6.14.0
293
294
### Optional Peer Dependencies
295
296
- `@nomicfoundation/hardhat-verify`: ^3.0.0 (for contract verification)