hardhat-deploy 2.0.0-next.45 → 2.0.0-next.47
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/README.md +2 -623
- package/dist/esm/helpers.d.ts +15 -8
- package/dist/esm/helpers.d.ts.map +1 -1
- package/dist/esm/helpers.js +83 -66
- package/dist/esm/helpers.js.map +1 -1
- package/dist/esm/tasks/deploy.d.ts.map +1 -1
- package/dist/esm/tasks/deploy.js +6 -5
- package/dist/esm/tasks/deploy.js.map +1 -1
- package/package.json +10 -10
- package/src/helpers.ts +99 -74
- package/src/tasks/deploy.ts +8 -5
package/README.md
CHANGED
|
@@ -17,627 +17,6 @@ But you can provide your own module for advanced use case.
|
|
|
17
17
|
|
|
18
18
|
There are already a few like `@rocketh/proxy` to deploy proxy declaratively like in hardhat-deploy v1 or `@rocketh/diamond` to deploy diamond declaratively.
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## Documentation:
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
It also adds a mechanism to associate names to addresses, so test and deployment scripts can be reconfigured by simply changing the address a name points to, allowing different configurations per network. This also results in much clearer tests and deployment scripts (no more accounts[0] in your code).
|
|
25
|
-
|
|
26
|
-
This plugin contains a lot more features too, all geared toward a better developer experience :
|
|
27
|
-
|
|
28
|
-
- chain configuration export (via @rocketh/export)
|
|
29
|
-
(listing deployed contracts' addresses and their abis (useful for web apps))
|
|
30
|
-
- library linking at the time of deployment.
|
|
31
|
-
- deterministic deployment across networks.
|
|
32
|
-
- support for specific deploy script per network (L1 vs L2 for example)
|
|
33
|
-
- deployment dependency system (allowing you to only deploy what is needed).
|
|
34
|
-
- deployment retrying (by saving pending tx): so you can feel confident when making a deployment that you can always recover.
|
|
35
|
-
- deployments as test fixture via hardhat helpers
|
|
36
|
-
- contains helpers to read and execute transaction on deployed contract referring to them by name.
|
|
37
|
-
- save metadata of deployed contract so they can always be fully verified, via sourcify or etherscan.
|
|
38
|
-
- ability to submit contract source to etherscan and sourcify for verification at any time. (Because hardhat-deploy will save all the necessary info, it can be executed at any time.)
|
|
39
|
-
- support hardhat's fork feature so deployment can be accessed even when run through fork.
|
|
40
|
-
- declarative proxy deployment with ability to upgrade them transparently, only if code changes.
|
|
41
|
-
- this include support for [openzeppelin](https://openzeppelin.com) transparent proxies
|
|
42
|
-
- diamond deployment with facets, allowing you to focus on what the new version will be. It will generate the diamondCut necessary to reach the new state.
|
|
43
|
-
- support HRC (Hot Contract Replacement) via special proxy mechanism and file watch setup
|
|
44
|
-
|
|
45
|
-
## hardhat-deploy in a nutshell
|
|
46
|
-
|
|
47
|
-
Before going into the details, here is a very simple summary of the basic feature of **hardhat-deploy**.
|
|
48
|
-
|
|
49
|
-
**hardhat-deploy** allows you to write [`deploy scripts`](#deploy-scripts) in the `deploy` folder. Each of these files that look as follows will be executed in turn when you execute the following task: `hardhat --network <networkName> deploy`
|
|
50
|
-
|
|
51
|
-
```js
|
|
52
|
-
// we import what we need from the #rocketh alias, see below for setup
|
|
53
|
-
import { deployScript, artifacts } from "#rocketh";
|
|
54
|
-
|
|
55
|
-
export default deployScript(
|
|
56
|
-
// this allow us to define our deploy function which takes as first argument an environment object
|
|
57
|
-
// This contaisn the function provided by the modules imported in 'rocketh.ts'
|
|
58
|
-
// along with other built-in functions and the named accounts
|
|
59
|
-
async ({ deployViaProxy, namedAccounts }) => {
|
|
60
|
-
const { deployer, admin } = namedAccounts;
|
|
61
|
-
|
|
62
|
-
const prefix = "proxy:";
|
|
63
|
-
await deployViaProxy(
|
|
64
|
-
"GreetingsRegistry",
|
|
65
|
-
{
|
|
66
|
-
account: deployer,
|
|
67
|
-
artifact: artifacts.GreetingsRegistry,
|
|
68
|
-
args: [prefix],
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
owner: admin,
|
|
72
|
-
linkedData: {
|
|
73
|
-
prefix,
|
|
74
|
-
admin,
|
|
75
|
-
},
|
|
76
|
-
}
|
|
77
|
-
);
|
|
78
|
-
},
|
|
79
|
-
// execute takes as a second argument an options object where you can specify tags and dependencies
|
|
80
|
-
{ tags: ["GreetingsRegistry", "GreetingsRegistry_deploy"] }
|
|
81
|
-
);
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Furthermore you can also ensure these scripts are executed in test too by calling `await loadAndExecuteDeployments({provider: provider,});` in your tests.
|
|
85
|
-
|
|
86
|
-
Amd you can call these in hardhat test fixture to benefit from caching optimization.
|
|
87
|
-
|
|
88
|
-
This is a huge benefit for testing since you are not required to replicate the deployment procedure in your tests. The tag feature (as seen in the script above) and [dependencies](#deploy-scripts-tags-and-dependencies) will also make your life easier when writing complex deployment procedures.
|
|
89
|
-
|
|
90
|
-
You can even group deploy scripts in different sub-folders and ensure they are executed in their logical order.
|
|
91
|
-
|
|
92
|
-
## Installation
|
|
93
|
-
|
|
94
|
-
Here is the basic for getting started
|
|
95
|
-
|
|
96
|
-
Note: hardhat-deploy is alpha, see @next to get alpha version, if you do not specify @nextyou'll get v1
|
|
97
|
-
|
|
98
|
-
::: code-group
|
|
99
|
-
|
|
100
|
-
```bash [npm]
|
|
101
|
-
npm install -D hardhat-deploy@next rocketh @rocketh/deploy @rocketh/read-execute
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
```bash [pnpm]
|
|
105
|
-
pnpm add -D hardhat-deploy@next rocketh @rocketh/deploy @rocketh/read-execute
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
:::
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
Then you need to add it to the plugins list of hardhat in hardhat.config.ts:
|
|
112
|
-
|
|
113
|
-
```ts
|
|
114
|
-
import HardhatDeploy from 'hardhat-deploy';
|
|
115
|
-
...
|
|
116
|
-
const config: HardhatUserConfig = {
|
|
117
|
-
plugins: [..., HardhatDeploy],
|
|
118
|
-
...
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
We also recommend you add these to provide more features
|
|
123
|
-
|
|
124
|
-
::: code-group
|
|
125
|
-
|
|
126
|
-
```bash [npm]
|
|
127
|
-
npm install -D @rocketh/proxy @rocketh/diamond @rocketh/export @rocketh/verifier @rocketh/doc
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
```bash [pnpm]
|
|
131
|
-
pnpm add -D @rocketh/proxy @rocketh/diamond @rocketh/export @rocketh/verifier @rocketh/doc
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
:::
|
|
135
|
-
|
|
136
|
-
Note that extensions like `@rocketh/proxy` need to be passed into the rocketh setup function so they can be used.
|
|
137
|
-
|
|
138
|
-
The best way to do that is actually use the `rocketh.ts/js` config file itself to do that in one place.
|
|
139
|
-
We also recommend you setup an alias for it so you can import with `import .. from "#rocketh"` it from anywhere:
|
|
140
|
-
You can set it up by settings imports in `package.json`
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
```json
|
|
144
|
-
{
|
|
145
|
-
...
|
|
146
|
-
"imports": {
|
|
147
|
-
"#rocketh": "./rocketh.js",
|
|
148
|
-
},
|
|
149
|
-
}
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
Alternatively if you use typescript, you can instead use `tsconfig.json`
|
|
153
|
-
|
|
154
|
-
```json
|
|
155
|
-
{
|
|
156
|
-
"compilerOptions": {
|
|
157
|
-
...
|
|
158
|
-
"paths": {
|
|
159
|
-
"#rocketh": ["./rocketh.ts"]
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
Example of `rocketh.ts` file:
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
// ------------------------------------------------------------------------------------------------
|
|
169
|
-
// Typed Config
|
|
170
|
-
// ------------------------------------------------------------------------------------------------
|
|
171
|
-
import { UserConfig } from "rocketh";
|
|
172
|
-
export const config = {
|
|
173
|
-
accounts: {
|
|
174
|
-
deployer: {
|
|
175
|
-
default: 0,
|
|
176
|
-
},
|
|
177
|
-
},
|
|
178
|
-
} as const satisfies UserConfig;
|
|
179
|
-
|
|
180
|
-
// ------------------------------------------------------------------------------------------------
|
|
181
|
-
// Imports and Re-exports
|
|
182
|
-
// ------------------------------------------------------------------------------------------------
|
|
183
|
-
// We regroup all what is needed for the deploy scripts
|
|
184
|
-
// so that they just need to import this file
|
|
185
|
-
// we add here the extension we need, so that they are available in the deploy scripts
|
|
186
|
-
// extensions are simply function that accept as their first argument the Environment
|
|
187
|
-
// by passing them to the setup function (see below) you get to access them through the environment object with type-safety
|
|
188
|
-
import * as deployExtensions from '@rocketh/deploy'; // this one provide a deploy function
|
|
189
|
-
import * as readExecuteFunctions from '@rocketh/read-execute'; // this one provide read,execute functions
|
|
190
|
-
const extensions = {...deployExtensions, ...readExecuteExtensions};
|
|
191
|
-
// ------------------------------------------------------------------------------------------------
|
|
192
|
-
// we re-export the artifacts, so they are easily available from the alias
|
|
193
|
-
import * as artifacts from './generated/artifacts.js';
|
|
194
|
-
export {artifacts};
|
|
195
|
-
// ------------------------------------------------------------------------------------------------
|
|
196
|
-
// we create the rocketh function we need by passing the extensions
|
|
197
|
-
import {setup} from 'rocketh';
|
|
198
|
-
const {deployScript, loadAndExecuteDeployments} = setup<typeof extensions, typeof config.accounts, typeof config.data>(
|
|
199
|
-
extensions,
|
|
200
|
-
);
|
|
201
|
-
// ------------------------------------------------------------------------------------------------
|
|
202
|
-
// we do the same for hardhat-deploy
|
|
203
|
-
import {setupHardhatDeploy} from 'hardhat-deploy/helpers';
|
|
204
|
-
const {loadEnvironmentFromHardhat} = setupHardhatDeploy(extensions);
|
|
205
|
-
// ------------------------------------------------------------------------------------------------
|
|
206
|
-
// finally we export them
|
|
207
|
-
export {loadAndExecuteDeployments, deployScript, loadEnvironmentFromHardhat};
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
You can them create a deploy script in the `deploy` folder like so:
|
|
211
|
-
|
|
212
|
-
```typescript
|
|
213
|
-
// we import what we need from the #rocketh alias, see ../rocketh.ts
|
|
214
|
-
import { deployScript, artifacts } from "#rocketh";
|
|
215
|
-
|
|
216
|
-
export default deployScript(
|
|
217
|
-
async ({ deploy, namedAccounts }) => {
|
|
218
|
-
const { deployer } = namedAccounts;
|
|
219
|
-
|
|
220
|
-
await deploy("GreetingsRegistry", {
|
|
221
|
-
account: deployer,
|
|
222
|
-
artifact: artifacts.GreetingsRegistry,
|
|
223
|
-
args: [""],
|
|
224
|
-
});
|
|
225
|
-
},
|
|
226
|
-
// finally you can pass tags and dependencies
|
|
227
|
-
{ tags: ["GreetingsRegistry", "GreetingsRegistry_deploy"] }
|
|
228
|
-
);
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
See a template that uses **hardhat-deploy** here: https://github.com/wighawag/template-ethereum-contracts
|
|
232
|
-
|
|
233
|
-
## Migrating from hardhat-deploy v1
|
|
234
|
-
|
|
235
|
-
in v1 you would create a deploy file like this:
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
// deploy/00_deploy_my_contract.js
|
|
239
|
-
// export a function that get passed the Hardhat runtime environment
|
|
240
|
-
module.exports = async ({ getNamedAccounts, deployments }) => {
|
|
241
|
-
const { deploy } = deployments;
|
|
242
|
-
const { deployer } = await getNamedAccounts();
|
|
243
|
-
await deploy("MyContract", {
|
|
244
|
-
from: deployer,
|
|
245
|
-
args: ["Hello"],
|
|
246
|
-
log: true,
|
|
247
|
-
});
|
|
248
|
-
};
|
|
249
|
-
// add tags and dependencies
|
|
250
|
-
module.exports.tags = ["MyContract"];
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
and you would have configuraiton in hardhat.config.ts
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
namedAccounts: {
|
|
257
|
-
deployer: 0,
|
|
258
|
-
...
|
|
259
|
-
},
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
in v2 you will do this instead:
|
|
263
|
-
|
|
264
|
-
```typescript
|
|
265
|
-
/// we import what we need from the #rocketh alias, see ../rocketh.ts
|
|
266
|
-
import { deployScript, artifacts } from "#rocketh";
|
|
267
|
-
|
|
268
|
-
export default deployScript(
|
|
269
|
-
async ({ deploy, namedAccounts }) => {
|
|
270
|
-
const { deployer } = namedAccounts;
|
|
271
|
-
|
|
272
|
-
await deploy("MyContract", {
|
|
273
|
-
account: deployer,
|
|
274
|
-
artifact: artifacts.MyContract,
|
|
275
|
-
args: ["Hello"],
|
|
276
|
-
});
|
|
277
|
-
},
|
|
278
|
-
// finally you can pass tags and dependencies
|
|
279
|
-
{ tags: ["MyContract"] }
|
|
280
|
-
);
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
and you would have a `rocketh.ts/js` file as described in the [Setup](#setup)
|
|
284
|
-
|
|
285
|
-
### Migrating existing deployment to hardhat-deploy
|
|
286
|
-
|
|
287
|
-
> Only needed for an existing project that already deployed contracts and has the deployment information available **(at minimum, address, abi, bytecode and metadata)**
|
|
288
|
-
>
|
|
289
|
-
> If you come from hardhat-deploy v1, there is nothing you should need to do as hardhat-deploy v2 will read your deployment files as usual.
|
|
290
|
-
|
|
291
|
-
You might want to switch your current deployment process to use **hardhat-deploy**. In that case you probably have some deployments saved elsewhere.
|
|
292
|
-
|
|
293
|
-
In order to port them to **hardhat-deploy**, you'll need to create one `.json` file per contract in the `deployments/<network>` folder (configurable via [paths config](#extra-paths-config)).
|
|
294
|
-
|
|
295
|
-
The network folder is simply the hardhat network name (as configured in hardhat.config.js).
|
|
296
|
-
Such folder need to have a file named `.chain` containing both the chainId as decimal and the genesisHash.
|
|
297
|
-
If coming from hardhat-deploy v1, it will also accept a `.chainId` file containing only the chainId but will convert it
|
|
298
|
-
|
|
299
|
-
For example for a network named "sepolia" (for the corresponding network) the file `deployments/rinkeby/.chain` would be
|
|
300
|
-
|
|
301
|
-
```
|
|
302
|
-
{"chainId":"11155111","genesisHash":"0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9"}
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
Each contract file must follow this type (as defined in [types.ts](types.ts)) :
|
|
306
|
-
|
|
307
|
-
```typescript
|
|
308
|
-
export type Deployment<TAbi extends Abi> = {
|
|
309
|
-
readonly address: EIP1193Account;
|
|
310
|
-
readonly abi: Narrow<TAbi>;
|
|
311
|
-
readonly transaction?: {
|
|
312
|
-
readonly hash: EIP1193DATA;
|
|
313
|
-
readonly origin?: EIP1193Account;
|
|
314
|
-
readonly nonce?: EIP1193DATA;
|
|
315
|
-
};
|
|
316
|
-
readonly receipt?: {
|
|
317
|
-
confirmations: number;
|
|
318
|
-
blockHash: EIP1193DATA;
|
|
319
|
-
blockNumber: EIP1193QUANTITY;
|
|
320
|
-
transactionIndex: EIP1193QUANTITY;
|
|
321
|
-
};
|
|
322
|
-
readonly bytecode: EIP1193DATA;
|
|
323
|
-
readonly argsData: EIP1193DATA;
|
|
324
|
-
readonly metadata: string;
|
|
325
|
-
readonly numDeployments?: number;
|
|
326
|
-
readonly libraries?: Libraries;
|
|
327
|
-
readonly linkedData?: any; // TODO
|
|
328
|
-
readonly deployedBytecode?: EIP1193DATA;
|
|
329
|
-
readonly linkReferences?: any; // TODO
|
|
330
|
-
readonly deployedLinkReferences?: any; // TODO
|
|
331
|
-
readonly contractName?: string;
|
|
332
|
-
readonly sourceName?: string; // relative path
|
|
333
|
-
readonly devdoc?: DevDoc;
|
|
334
|
-
readonly evm?: {
|
|
335
|
-
readonly gasEstimates?: GasEstimates | null;
|
|
336
|
-
} & any;
|
|
337
|
-
readonly storageLayout?: StorageLayout;
|
|
338
|
-
readonly userdoc?: UserDoc;
|
|
339
|
-
} & Record<string, unknown>;
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
As you can see, not all fields are mandatory. But having the other fields allow more feature. For example, metadata and args allow you to benefit from contract code verification.
|
|
343
|
-
|
|
344
|
-
Here is an example:
|
|
345
|
-
|
|
346
|
-
Let's say you have:
|
|
347
|
-
|
|
348
|
-
- 2 Contract named Greeter and Registry deployed on rinkeby
|
|
349
|
-
- 1 contract named Greeter on mainnet
|
|
350
|
-
- 2 Contract named Greeter and Registry deployed on a network named rinkeby2
|
|
351
|
-
|
|
352
|
-
You would get the following folder structure:
|
|
353
|
-
|
|
354
|
-
```
|
|
355
|
-
deployments/
|
|
356
|
-
mainnet/
|
|
357
|
-
.chain
|
|
358
|
-
Greeter.json
|
|
359
|
-
rinkeby/
|
|
360
|
-
.chain
|
|
361
|
-
Greeter.json
|
|
362
|
-
Registry.json
|
|
363
|
-
rinkeby2/
|
|
364
|
-
.chain
|
|
365
|
-
Greeter.json
|
|
366
|
-
Registry.json
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
The reason why **hardhat-deploy** save chainId and genesisHash in the `.chain` file is both for
|
|
370
|
-
|
|
371
|
-
- safety: so that if you were to change the network name to point to a different chain, it would not attempt to read the wrong folder and assume that a contract has been deployed while it has not.
|
|
372
|
-
- ability to know the chainId without requiring to be connected to a node (and so not dependent on hardhat.config.js settings). Useful for `export` task.
|
|
373
|
-
|
|
374
|
-
## Hardhat Tasks Available/Updated
|
|
375
|
-
|
|
376
|
-
hardhat deploy currently add one task to hardhat. But since hardhat-deploy is now just a tiny wrapper arround rocketh, you can use rocketh commands too
|
|
377
|
-
|
|
378
|
-
### 1. hardhat deploy
|
|
379
|
-
|
|
380
|
-
This plugin adds the _deploy_ task to Hardhat.
|
|
381
|
-
|
|
382
|
-
This task will execute the scripts in the `deploy` folder and save the contract deployments to disk. These deployments are supposed to be saved for example in a git repository. This way they can be accessed later. But you are free to save them elsewhere and get them back via your mechanism of choice.
|
|
383
|
-
|
|
384
|
-
With the deployment saved, it allows you to deploy a contract only if changes were made.
|
|
385
|
-
|
|
386
|
-
Deploy scripts (also called Deploy functions) can also perform arbitrary logic.
|
|
387
|
-
|
|
388
|
-
For further details on how to use it and write deploy script, see [section](#deploy-scripts) below.
|
|
389
|
-
|
|
390
|
-
### 2. rocketh-verify
|
|
391
|
-
|
|
392
|
-
This command is provided by the optional package `@rocketh/verify`
|
|
393
|
-
|
|
394
|
-
This command will submit the contract source and other info of all deployed contracts to allow services like etherscan, blockscout or sourcify to verify and record the sources.
|
|
395
|
-
|
|
396
|
-
To execute that command, you need to specify the network to run against :
|
|
397
|
-
|
|
398
|
-
```bash
|
|
399
|
-
pnpm rocketh-verify -n <network-name> <etherscan|sourcify|blockscout>
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
For etherscan verification, you just need the ETHERSCAN_API_KEY en variable to be set.
|
|
403
|
-
you can use a .env or .env.local file for that as rocketh will load them automatically.
|
|
404
|
-
|
|
405
|
-
### 3. rocketh-export
|
|
406
|
-
|
|
407
|
-
This command is provided by the optional package `@rocketh/export`
|
|
408
|
-
|
|
409
|
-
This command will export the contract deployed (saved in `deployments` folder) to a file with a simple format containing only contract addresses and abi, useful for web apps.
|
|
410
|
-
|
|
411
|
-
One of the following options need to be set for this task to have any effects :
|
|
412
|
-
|
|
413
|
-
```bash
|
|
414
|
-
rocketh-export -n <network-name> --ts <path-to-contracts.ts>
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
## Environment object and extension
|
|
418
|
-
|
|
419
|
-
Each deploy function is given a environment object as first argument.
|
|
420
|
-
|
|
421
|
-
it contains at least the following fields :
|
|
422
|
-
|
|
423
|
-
```typescript
|
|
424
|
-
export interface Environment<
|
|
425
|
-
NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
|
|
426
|
-
Deployments extends UnknownDeployments = UnknownDeployments
|
|
427
|
-
> {
|
|
428
|
-
network: {
|
|
429
|
-
chain: Chain;
|
|
430
|
-
name: string;
|
|
431
|
-
tags: { [tag: string]: boolean };
|
|
432
|
-
provider: TransactionHashTracker;
|
|
433
|
-
};
|
|
434
|
-
namedAccounts: ResolvedNamedAccounts<NamedAccounts>;
|
|
435
|
-
namedSigners: ResolvedNamedSigners<ResolvedNamedAccounts<NamedAccounts>>;
|
|
436
|
-
unnamedAccounts: EIP1193Account[];
|
|
437
|
-
addressSigners: { [name: `0x${string}`]: Signer };
|
|
438
|
-
save<TAbi extends Abi = Abi>(
|
|
439
|
-
name: string,
|
|
440
|
-
deployment: Deployment<TAbi>,
|
|
441
|
-
options?: { doNotCountAsNewDeployment?: boolean }
|
|
442
|
-
): Promise<Deployment<TAbi>>;
|
|
443
|
-
savePendingDeployment<TAbi extends Abi = Abi>(
|
|
444
|
-
pendingDeployment: PendingDeployment<TAbi>
|
|
445
|
-
): Promise<Deployment<TAbi>>;
|
|
446
|
-
savePendingExecution(
|
|
447
|
-
pendingExecution: PendingExecution
|
|
448
|
-
): Promise<EIP1193TransactionReceipt>;
|
|
449
|
-
get<TAbi extends Abi>(name: string): Deployment<TAbi>;
|
|
450
|
-
getOrNull<TAbi extends Abi>(name: string): Deployment<TAbi> | null;
|
|
451
|
-
fromAddressToNamedABI<TAbi extends Abi>(
|
|
452
|
-
address: Address
|
|
453
|
-
): { mergedABI: TAbi; names: string[] };
|
|
454
|
-
fromAddressToNamedABIOrNull<TAbi extends Abi>(
|
|
455
|
-
address: Address
|
|
456
|
-
): { mergedABI: TAbi; names: string[] } | null;
|
|
457
|
-
showMessage(message: string): void;
|
|
458
|
-
showProgress(message?: string): ProgressIndicator;
|
|
459
|
-
hasMigrationBeenDone(id: string): boolean;
|
|
460
|
-
}
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
And it is expanded by each module you import like `@rocketh/deploy` which adds a deploy function
|
|
464
|
-
|
|
465
|
-
## Configuration
|
|
466
|
-
|
|
467
|
-
Configuration of network or other hardhat specific config is done via hardhat.config.ts
|
|
468
|
-
|
|
469
|
-
Else rocketh.ts/js is where you can configure hardhat-deploy/rocketh specific configs.
|
|
470
|
-
|
|
471
|
-
### **1. namedAccounts (ability to name addresses)**
|
|
472
|
-
|
|
473
|
-
The rocketh.js file need to export a config object
|
|
474
|
-
|
|
475
|
-
For example
|
|
476
|
-
|
|
477
|
-
```js
|
|
478
|
-
import {UserConfig} from 'rocketh';
|
|
479
|
-
export const config = {
|
|
480
|
-
accounts: {
|
|
481
|
-
deployer: {
|
|
482
|
-
default: 0,
|
|
483
|
-
sepolia: 1
|
|
484
|
-
},
|
|
485
|
-
admin: {
|
|
486
|
-
default: 1,
|
|
487
|
-
},
|
|
488
|
-
},
|
|
489
|
-
} as const satisfies UserConfig;
|
|
490
|
-
|
|
491
|
-
import * as artifacts from './generated/artifacts.js';
|
|
492
|
-
export {artifacts};
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
This config file import modules too so that deploy script can simply import rocketh.js to have access to artifacts and specifc environment functions
|
|
496
|
-
|
|
497
|
-
The named account feature allow you to define accounts by name and have them configurable by network
|
|
498
|
-
|
|
499
|
-
In the above file, the deployer is set to be the first account on all network, except for sepolia where it is the second
|
|
500
|
-
|
|
501
|
-
### **4. deterministicDeployment (ability to specify a deployment factory)**
|
|
502
|
-
|
|
503
|
-
---
|
|
504
|
-
|
|
505
|
-
The config also allow you to set an optional `deterministicDeployment` field.
|
|
506
|
-
|
|
507
|
-
`deterministicDeployment` allows you to associate information that are used on each network for deterministic deployment. The information for each deterministic deployment consist out of a `factory`, a `deployer`, the required `funding` and a `signedTx` to deploy the factory. The default deterministic deployment used is the [Deterministic Deployment Proxy](https://github.com/Arachnid/deterministic-deployment-proxy). The factory expects a 32 bytes `salt` concatenated with the deployment data (see [EIP-1014](https://eips.ethereum.org/EIPS/eip-1014) for more information on these parameters).
|
|
508
|
-
|
|
509
|
-
Using the `deterministicDeployment` it is possible to define a different setup for the deterministic deployment. One use case for this is the deterministic deployment on networks that required replay protection (such as Celo or Avalanche). The [Deterministic Deployment Proxy](https://github.com/Arachnid/deterministic-deployment-proxy) can only be deployed on networks that don't enforce replay protection, therefore on other networks an alternative library has to be used. An example for this would be the [Safe Singleton Factory](https://github.com/gnosis/safe-singleton-factory) that is an adjusted version of the [Deterministic Deployment Proxy](https://github.com/Arachnid/deterministic-deployment-proxy) that contains signed transactions that include replay protection.
|
|
510
|
-
|
|
511
|
-
```js
|
|
512
|
-
import {UserConfig} from 'rocketh';
|
|
513
|
-
export const config = {
|
|
514
|
-
accounts: {
|
|
515
|
-
deployer: {
|
|
516
|
-
default: 0,
|
|
517
|
-
sepolia: 1
|
|
518
|
-
},
|
|
519
|
-
admin: {
|
|
520
|
-
default: 1,
|
|
521
|
-
},
|
|
522
|
-
},
|
|
523
|
-
networks: {
|
|
524
|
-
sepolia: {
|
|
525
|
-
factory: '0x4e59b44847b379578588920ca78fbf26c0b4956c',
|
|
526
|
-
deployer: '0x3fab184622dc19b6109349b94811493bf2a45362',
|
|
527
|
-
funding: '10000000000000000',
|
|
528
|
-
signedTx:
|
|
529
|
-
'0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222',
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
} as const satisfies UserConfig;
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
## How to Deploy Contracts
|
|
536
|
-
|
|
537
|
-
---
|
|
538
|
-
|
|
539
|
-
### The `deploy` Task
|
|
540
|
-
|
|
541
|
-
`hardhat --network <networkName> deploy`
|
|
542
|
-
|
|
543
|
-
This is a new task that the `hardhat-deploy` adds. As the name suggests it deploys contracts.
|
|
544
|
-
To be exact it will look for files in the folder `deploy`
|
|
545
|
-
|
|
546
|
-
It will scan for files in alphabetical order and execute them in turn.
|
|
547
|
-
|
|
548
|
-
- it will `import` each of these files and execute the exported function
|
|
549
|
-
|
|
550
|
-
To specify the network, you can use the builtin hardhat argument `--network <network name>`
|
|
551
|
-
|
|
552
|
-
> :warning: Note that running `hardhat deploy` without specifying a network will use the default network. If the default network is hardhat (the default's default) then nothing will happen as a result as everything happens in memory, but this can be used to ensure the deployment is without issues.
|
|
553
|
-
|
|
554
|
-
---
|
|
555
|
-
|
|
556
|
-
### Deploy Scripts
|
|
557
|
-
|
|
558
|
-
The deploy scripts need to call the execute function exported by `rocketh`
|
|
559
|
-
|
|
560
|
-
The execute expect as first argument a function
|
|
561
|
-
|
|
562
|
-
For example this script will deploy the `GreetingsRegistry` contract
|
|
563
|
-
|
|
564
|
-
```typescript
|
|
565
|
-
import { deployScript, artifacts } from "#rocketh";
|
|
566
|
-
export default deployScript(
|
|
567
|
-
async ({ deploy, namedAccounts }) => {
|
|
568
|
-
const { deployer } = namedAccounts;
|
|
569
|
-
|
|
570
|
-
await deploy("GreetingsRegistry", {
|
|
571
|
-
account: deployer,
|
|
572
|
-
artifact: artifacts.GreetingsRegistry,
|
|
573
|
-
args: [""],
|
|
574
|
-
});
|
|
575
|
-
},
|
|
576
|
-
|
|
577
|
-
{ tags: ["GreetingsRegistry", "GreetingsRegistry_deploy"] }
|
|
578
|
-
);
|
|
579
|
-
```
|
|
580
|
-
|
|
581
|
-
The tags is a list of string that when the _deploy_ task is executed with, the script will be executed (unless it skips). In other word if the deploy task is executed with a tag that does not belong to that script, that script will not be executed unless it is a dependency of a script that does get executed.
|
|
582
|
-
|
|
583
|
-
The dependencies is a list of tag that will be executed if that script is executed. So if the script is executed, every script whose tag match any of the dependencies will be executed first.
|
|
584
|
-
|
|
585
|
-
Finally the function can return true if it wishes to never be executed again. This can be useful to emulate migration scripts that are meant to be executed only once. Once such script return true (async), the `id` field is used to track execution and if that field is not present when the script return true, it will fails.
|
|
586
|
-
|
|
587
|
-
In other words, if you want a particular deploy script to run only once, it needs to both return true (async) and have an `id` set.
|
|
588
|
-
|
|
589
|
-
In any case, as a general advice every deploy function should be idempotent. This is so they can always recover from failure or pending transaction. This is what underpin most of hardhat-deploy philosophy.
|
|
590
|
-
|
|
591
|
-
This is why the `deploy` function provided by `@rocketh/deploy` will by default only deploy if the contract code has changed, making it easier to write idempotent script.
|
|
592
|
-
|
|
593
|
-
### Environment and function provided by rocketh modules
|
|
594
|
-
|
|
595
|
-
By default rocketh environment only provide function to read and write deployments. It has no `deploy` function on its own.
|
|
596
|
-
|
|
597
|
-
These are provided by external modules but few are already available like `@rocketh/deploy`, `@rocketh/proxy` and `@rocketh/diamond` each with its own specific use case.
|
|
598
|
-
|
|
599
|
-
#### `@rocketh/deploy`
|
|
600
|
-
|
|
601
|
-
#### `@rocketh/proxy`
|
|
602
|
-
|
|
603
|
-
#### `@rocketh/diamond`
|
|
604
|
-
|
|
605
|
-
## Handling contract using libraries
|
|
606
|
-
|
|
607
|
-
In the deploy function, one of the `DeployOptions` field is the `libraries` field. It allows you to associate external contract as libraries at the time of deployment.
|
|
608
|
-
|
|
609
|
-
First, you have deploy the library using the `deploy` function, then when we deploy a contract that needs the linked library, we can pass the deployed library name and address in as an argument to the `libraries` object.
|
|
610
|
-
|
|
611
|
-
First step: deploy the library:
|
|
612
|
-
|
|
613
|
-
```js
|
|
614
|
-
const exampleLibrary = await deploy("ExampleLibary", {
|
|
615
|
-
artifact: artifacts.ExampleLibary,
|
|
616
|
-
from: <deployer>
|
|
617
|
-
});
|
|
618
|
-
|
|
619
|
-
```
|
|
620
|
-
|
|
621
|
-
ExampleLibrary is now deployed to whatever network was chosen (`hardhat deploy --network <networkName>`)
|
|
622
|
-
|
|
623
|
-
For example, if we are deploying on Sepolia, this library will get deployed on sepolia, and the `exampleLibrary` variable will be a deployment object that contains the abi as well as the deployed address for the contract.
|
|
624
|
-
|
|
625
|
-
Now that the library is deployed, we can link it in our next deployed contract.
|
|
626
|
-
|
|
627
|
-
```js
|
|
628
|
-
const example = await deploy(
|
|
629
|
-
"Example",
|
|
630
|
-
{
|
|
631
|
-
account: deployer,
|
|
632
|
-
artifact: artifacts.Example,
|
|
633
|
-
args: ["example string argument for the 'Example' contract constructor"],
|
|
634
|
-
},
|
|
635
|
-
{
|
|
636
|
-
libraries: {
|
|
637
|
-
ExampleLibrary: exampleLibrary.address,
|
|
638
|
-
},
|
|
639
|
-
}
|
|
640
|
-
);
|
|
641
|
-
```
|
|
642
|
-
|
|
643
|
-
This `libraries` object takes the name of the library, and its deployed address on the network. Multiple libraries can be passed into the `libraries` object.
|
|
22
|
+
Please find the [documentation here](https://rocketh.dev/hardhat-deploy)
|
package/dist/esm/helpers.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NetworkUserConfig, SensitiveString } from 'hardhat/types/config';
|
|
2
2
|
import { HardhatRuntimeEnvironment } from 'hardhat/types/hre';
|
|
3
3
|
import { NetworkConnection } from 'hardhat/types/network';
|
|
4
4
|
import { Environment, UnresolvedUnknownNamedAccounts, UnresolvedNetworkSpecificData } from 'rocketh';
|
|
@@ -6,22 +6,29 @@ export declare function setupHardhatDeploy<Extensions extends Record<string, (en
|
|
|
6
6
|
loadEnvironmentFromHardhat: (required: {
|
|
7
7
|
hre: HardhatRuntimeEnvironment;
|
|
8
8
|
connection?: NetworkConnection;
|
|
9
|
-
}, options?: {
|
|
10
|
-
useChainIdOfForkedNetwork?: boolean;
|
|
11
9
|
}) => Promise<import("rocketh").EnhancedEnvironment<UnresolvedUnknownNamedAccounts, UnresolvedNetworkSpecificData, import("rocketh").UnknownDeployments, Extensions, Record<string, unknown>>>;
|
|
12
10
|
};
|
|
11
|
+
export declare function generateForkConfig(params: {
|
|
12
|
+
hre: HardhatRuntimeEnvironment;
|
|
13
|
+
connection?: NetworkConnection;
|
|
14
|
+
}): Promise<{
|
|
15
|
+
provider: any;
|
|
16
|
+
environment: string | {
|
|
17
|
+
fork: string;
|
|
18
|
+
};
|
|
19
|
+
connection: NetworkConnection;
|
|
20
|
+
isFork: boolean;
|
|
21
|
+
}>;
|
|
13
22
|
export declare function loadEnvironmentFromHardhat<NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts, Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData>(params: {
|
|
14
23
|
hre: HardhatRuntimeEnvironment;
|
|
15
24
|
connection?: NetworkConnection;
|
|
16
|
-
}, options?: {
|
|
17
|
-
useChainIdOfForkedNetwork?: boolean;
|
|
18
25
|
}): Promise<Environment<NamedAccounts, Data>>;
|
|
19
26
|
export declare function getRPC(networkName: string): string | SensitiveString | undefined;
|
|
20
|
-
export declare function getMnemonic(networkName?: string): string | SensitiveString;
|
|
21
|
-
export declare function getAccounts(networkName?: string): {
|
|
27
|
+
export declare function getMnemonic(networkName?: string, failsOnNoMnemonicSet?: boolean): string | SensitiveString;
|
|
28
|
+
export declare function getAccounts(networkName?: string, failsOnNoMnemonicSet?: boolean): {
|
|
22
29
|
mnemonic: string | SensitiveString;
|
|
23
30
|
};
|
|
24
31
|
export declare function addNetworksFromEnv(networks?: Record<string, NetworkUserConfig>): Record<string, NetworkUserConfig>;
|
|
25
|
-
export declare function
|
|
32
|
+
export declare function addNetworksFromKnownList(networks?: Record<string, NetworkUserConfig>): Record<string, NetworkUserConfig>;
|
|
26
33
|
export declare function addForkConfiguration(networks: Record<string, NetworkUserConfig>): Record<string, NetworkUserConfig>;
|
|
27
34
|
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"AACA,OAAO,EAIN,iBAAiB,EACjB,eAAe,EACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAC,yBAAyB,EAAC,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAC,iBAAiB,EAAC,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACN,WAAW,EACX,8BAA8B,EAC9B,6BAA6B,EAI7B,MAAM,SAAS,CAAC;AAEjB,wBAAgB,kBAAkB,CACjC,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,EAAE,EAChF,aAAa,SAAS,8BAA8B,GAAG,8BAA8B,EACrF,IAAI,SAAS,6BAA6B,GAAG,6BAA6B,EACzE,UAAU,EAAE,UAAU;2CAEZ;QAAC,GAAG,EAAE,yBAAyB,CAAC;QAAC,UAAU,CAAC,EAAE,iBAAiB,CAAA;KAAC;EAY3E;AAED,wBAAsB,kBAAkB,CACvC,MAAM,EAAE;IAAC,GAAG,EAAE,yBAAyB,CAAC;IAAC,UAAU,CAAC,EAAE,iBAAiB,CAAA;CAAC,GAItE,OAAO,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC;IAAC,UAAU,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAC,CAAC,CAsEhH;AAED,wBAAsB,0BAA0B,CAC/C,aAAa,SAAS,8BAA8B,GAAG,8BAA8B,EACrF,IAAI,SAAS,6BAA6B,GAAG,6BAA6B,EAE1E,MAAM,EAAE;IAAC,GAAG,EAAE,yBAAyB,CAAC;IAAC,UAAU,CAAC,EAAE,iBAAiB,CAAA;CAAC,GAKtE,OAAO,CAAC,WAAW,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CAW3C;AAiBD,wBAAgB,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,eAAe,GAAG,SAAS,CAuBhF;AAED,wBAAgB,WAAW,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,eAAe,CAmB1G;AAED,wBAAgB,WAAW,CAC1B,WAAW,CAAC,EAAE,MAAM,EACpB,oBAAoB,CAAC,EAAE,OAAO,GAC5B;IAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAAA;CAAC,CAEtC;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAuBlH;AAGD,wBAAgB,wBAAwB,CACvC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAC1C,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAsBnC;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAoDnH"}
|
package/dist/esm/helpers.js
CHANGED
|
@@ -1,53 +1,60 @@
|
|
|
1
1
|
import { configVariable } from 'hardhat/config';
|
|
2
|
-
import { loadEnvironment, enhanceEnvIfNeeded, } from 'rocketh';
|
|
2
|
+
import { loadEnvironment, enhanceEnvIfNeeded, chainByCanonicalName, } from 'rocketh';
|
|
3
3
|
export function setupHardhatDeploy(extensions) {
|
|
4
|
-
async function loadEnvironmentFromHardhatWithExtensions(required
|
|
5
|
-
|
|
4
|
+
async function loadEnvironmentFromHardhatWithExtensions(required
|
|
5
|
+
// options?: {
|
|
6
|
+
// useChainIdOfForkedNetwork?: boolean;
|
|
7
|
+
// }
|
|
8
|
+
) {
|
|
9
|
+
const env = await loadEnvironmentFromHardhat(required);
|
|
6
10
|
return enhanceEnvIfNeeded(env, extensions);
|
|
7
11
|
}
|
|
8
12
|
return {
|
|
9
13
|
loadEnvironmentFromHardhat: loadEnvironmentFromHardhatWithExtensions,
|
|
10
14
|
};
|
|
11
15
|
}
|
|
12
|
-
export async function
|
|
13
|
-
|
|
16
|
+
export async function generateForkConfig(params
|
|
17
|
+
// options?: {
|
|
18
|
+
// useChainIdOfForkedNetwork?: boolean;
|
|
19
|
+
// }
|
|
20
|
+
) {
|
|
21
|
+
const fork = process.env.HARDHAT_FORK;
|
|
22
|
+
const connection = params.connection || fork
|
|
23
|
+
? await params.hre.network.connect({ network: 'fork' })
|
|
24
|
+
: await params.hre.network.connect();
|
|
14
25
|
let provider = connection.provider;
|
|
15
|
-
let
|
|
26
|
+
let environment = connection.networkName;
|
|
16
27
|
let forkChainId;
|
|
17
|
-
const fork = process.env.HARDHAT_FORK;
|
|
18
28
|
if (fork) {
|
|
19
|
-
if (options?.useChainIdOfForkedNetwork) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
network = {
|
|
29
|
+
// if (options?.useChainIdOfForkedNetwork) {
|
|
30
|
+
// const forkNetworkConfig = params.hre.config.networks[fork];
|
|
31
|
+
// if (forkNetworkConfig.type === 'edr-simulated') {
|
|
32
|
+
// forkChainId = forkNetworkConfig.chainId;
|
|
33
|
+
// } else if (forkNetworkConfig.chainId) {
|
|
34
|
+
// forkChainId = forkNetworkConfig.chainId;
|
|
35
|
+
// } else {
|
|
36
|
+
// if ('url' in forkNetworkConfig) {
|
|
37
|
+
// const url = await forkNetworkConfig.url.getUrl();
|
|
38
|
+
// const response = await fetch(url, {
|
|
39
|
+
// method: 'POST',
|
|
40
|
+
// headers: {
|
|
41
|
+
// 'Content-Type': 'application/json',
|
|
42
|
+
// },
|
|
43
|
+
// body: JSON.stringify({
|
|
44
|
+
// jsonrpc: '2.0',
|
|
45
|
+
// id: 1,
|
|
46
|
+
// method: 'eth_chainId',
|
|
47
|
+
// params: [],
|
|
48
|
+
// }),
|
|
49
|
+
// });
|
|
50
|
+
// const json = (await response.json()) as {result: string};
|
|
51
|
+
// forkChainId = Number(json.result);
|
|
52
|
+
// } else {
|
|
53
|
+
// throw new Error(`cannot fetch chainId`);
|
|
54
|
+
// }
|
|
55
|
+
// }
|
|
56
|
+
// }
|
|
57
|
+
environment = {
|
|
51
58
|
fork,
|
|
52
59
|
};
|
|
53
60
|
}
|
|
@@ -71,13 +78,23 @@ export async function loadEnvironmentFromHardhat(params, options) {
|
|
|
71
78
|
},
|
|
72
79
|
});
|
|
73
80
|
}
|
|
81
|
+
return { provider, environment, connection, isFork: !!fork };
|
|
82
|
+
}
|
|
83
|
+
export async function loadEnvironmentFromHardhat(params
|
|
84
|
+
// TODO ?
|
|
85
|
+
// options?: {
|
|
86
|
+
// useChainIdOfForkedNetwork?: boolean;
|
|
87
|
+
// }
|
|
88
|
+
) {
|
|
89
|
+
const { connection, environment, provider, isFork } = await generateForkConfig(params);
|
|
74
90
|
// console.log(`loading environments...`);
|
|
75
91
|
return loadEnvironment({
|
|
76
92
|
provider,
|
|
77
|
-
|
|
93
|
+
environment,
|
|
78
94
|
extra: {
|
|
79
95
|
connection,
|
|
80
96
|
},
|
|
97
|
+
saveDeployments: isFork ? false : undefined,
|
|
81
98
|
});
|
|
82
99
|
}
|
|
83
100
|
function getVariable(prefix, name) {
|
|
@@ -116,7 +133,7 @@ export function getRPC(networkName) {
|
|
|
116
133
|
}
|
|
117
134
|
return uri;
|
|
118
135
|
}
|
|
119
|
-
export function getMnemonic(networkName) {
|
|
136
|
+
export function getMnemonic(networkName, failsOnNoMnemonicSet) {
|
|
120
137
|
if (networkName) {
|
|
121
138
|
const mnemonic = getVariable('MNEMONIC_', networkName);
|
|
122
139
|
if (mnemonic && mnemonic !== '') {
|
|
@@ -125,12 +142,15 @@ export function getMnemonic(networkName) {
|
|
|
125
142
|
}
|
|
126
143
|
const mnemonic = process.env.MNEMONIC;
|
|
127
144
|
if (!mnemonic || mnemonic === '') {
|
|
145
|
+
if (failsOnNoMnemonicSet) {
|
|
146
|
+
throw new Error(`no mnemonic set for ${networkName} (via env variable 'MNEMONIC_${networkName}') or globally (via 'MNEMONIC_')`);
|
|
147
|
+
}
|
|
128
148
|
return 'test test test test test test test test test test test junk';
|
|
129
149
|
}
|
|
130
150
|
return mnemonic;
|
|
131
151
|
}
|
|
132
|
-
export function getAccounts(networkName) {
|
|
133
|
-
return { mnemonic: getMnemonic(networkName) };
|
|
152
|
+
export function getAccounts(networkName, failsOnNoMnemonicSet) {
|
|
153
|
+
return { mnemonic: getMnemonic(networkName, failsOnNoMnemonicSet) };
|
|
134
154
|
}
|
|
135
155
|
export function addNetworksFromEnv(networks) {
|
|
136
156
|
const newNetworks = networks ? { ...networks } : {};
|
|
@@ -158,29 +178,28 @@ export function addNetworksFromEnv(networks) {
|
|
|
158
178
|
}
|
|
159
179
|
return newNetworks;
|
|
160
180
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
else {
|
|
170
|
-
const url = getRPC(networkName);
|
|
181
|
+
const listOfNetworkNamesWithTestAccountAllowed = ['hardhat', 'localhost', 'memory', 'test'];
|
|
182
|
+
export function addNetworksFromKnownList(networks) {
|
|
183
|
+
const newNetworks = networks ? { ...networks } : {};
|
|
184
|
+
const canonicalNames = Object.keys(chainByCanonicalName);
|
|
185
|
+
for (const canonicalName of canonicalNames) {
|
|
186
|
+
const chain = chainByCanonicalName[canonicalName];
|
|
187
|
+
const url = getRPC(canonicalName) || chain.rpcUrls.default.http[0];
|
|
188
|
+
if (!newNetworks[canonicalName]) {
|
|
171
189
|
if (url) {
|
|
172
|
-
newNetworks[
|
|
173
|
-
|
|
190
|
+
newNetworks[canonicalName] = {
|
|
191
|
+
type: 'http',
|
|
174
192
|
url,
|
|
175
|
-
accounts: getAccounts(
|
|
193
|
+
accounts: getAccounts(canonicalName, !listOfNetworkNamesWithTestAccountAllowed.includes(canonicalName)),
|
|
176
194
|
};
|
|
177
195
|
}
|
|
178
196
|
else {
|
|
179
|
-
|
|
180
|
-
console.error(`no url for network ${networkName}`);
|
|
181
|
-
}
|
|
197
|
+
console.error(`no url for chain ${canonicalName}`);
|
|
182
198
|
}
|
|
183
199
|
}
|
|
200
|
+
else {
|
|
201
|
+
// console.error(`duplicated chain ${canonicalName}`);
|
|
202
|
+
}
|
|
184
203
|
}
|
|
185
204
|
return newNetworks;
|
|
186
205
|
}
|
|
@@ -211,15 +230,13 @@ export function addForkConfiguration(networks) {
|
|
|
211
230
|
}
|
|
212
231
|
}
|
|
213
232
|
}
|
|
214
|
-
const
|
|
215
|
-
? networks.hardhat
|
|
216
|
-
: { type: 'edr-simulated', chainType: 'l1' };
|
|
233
|
+
const existingForkConfiguration = networks.fork && networks.fork.type === 'edr-simulated' ? networks.fork : { type: 'edr-simulated', chainType: 'l1' };
|
|
217
234
|
const newNetworks = {
|
|
218
|
-
...
|
|
219
|
-
|
|
220
|
-
...
|
|
235
|
+
...networks,
|
|
236
|
+
fork: {
|
|
237
|
+
...existingForkConfiguration,
|
|
221
238
|
...{
|
|
222
|
-
accounts: hardhatAccounts ||
|
|
239
|
+
accounts: hardhatAccounts || existingForkConfiguration?.accounts,
|
|
223
240
|
forking: forkURL
|
|
224
241
|
? {
|
|
225
242
|
url: forkURL,
|
package/dist/esm/helpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,gBAAgB,CAAC;AAU9C,OAAO,EAIN,eAAe,EACf,kBAAkB,
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/tasks/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,qBAAqB,EAAC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/tasks/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,qBAAqB,EAAC,MAAM,qBAAqB,CAAC;AAI1D,UAAU,kBAAkB;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,QAAA,MAAM,oBAAoB,EAAE,qBAAqB,CAAC,kBAAkB,CA0BnE,CAAC;AACF,eAAe,oBAAoB,CAAC"}
|
package/dist/esm/tasks/deploy.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { loadAndExecuteDeployments } from 'rocketh';
|
|
2
|
+
import { generateForkConfig } from '../helpers.js';
|
|
2
3
|
const runScriptWithHardhat = async (args, hre) => {
|
|
3
4
|
let saveDeployments = true;
|
|
4
5
|
let skipPrompts = args.skipPrompts ? true : false;
|
|
5
|
-
const connection = await hre
|
|
6
|
+
const { connection, environment, isFork, provider } = await generateForkConfig({ hre });
|
|
6
7
|
const isMemoryNetwork = connection.networkConfig.type == 'edr-simulated';
|
|
7
8
|
if (isMemoryNetwork) {
|
|
8
9
|
skipPrompts = true;
|
|
@@ -14,11 +15,11 @@ const runScriptWithHardhat = async (args, hre) => {
|
|
|
14
15
|
const tags = args.tags && args.tags != '' ? args.tags : undefined;
|
|
15
16
|
await loadAndExecuteDeployments({
|
|
16
17
|
logLevel: 1,
|
|
17
|
-
provider
|
|
18
|
-
|
|
19
|
-
saveDeployments,
|
|
18
|
+
provider,
|
|
19
|
+
environment: environment,
|
|
20
|
+
saveDeployments: isFork ? false : saveDeployments,
|
|
20
21
|
askBeforeProceeding: skipPrompts ? false : true,
|
|
21
|
-
tags,
|
|
22
|
+
tags: tags?.split(','),
|
|
22
23
|
// reportGasUse: args.skipGasReport ? false : true,
|
|
23
24
|
extra: { connection },
|
|
24
25
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../../src/tasks/deploy.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,yBAAyB,EAAC,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../../src/tasks/deploy.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,yBAAyB,EAAC,MAAM,SAAS,CAAC;AAClD,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAQjD,MAAM,oBAAoB,GAA8C,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;IAC3F,IAAI,eAAe,GAAG,IAAI,CAAC;IAC3B,IAAI,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IAElD,MAAM,EAAC,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAC,GAAG,MAAM,kBAAkB,CAAC,EAAC,GAAG,EAAC,CAAC,CAAC;IAEpF,MAAM,eAAe,GAAG,UAAU,CAAC,aAAa,CAAC,IAAI,IAAI,eAAe,CAAC;IACzE,IAAI,eAAe,EAAE,CAAC;QACrB,WAAW,GAAG,IAAI,CAAC;QACnB,eAAe,GAAG,KAAK,CAAC;IACzB,CAAC;IACD,IAAI,IAAI,CAAC,eAAe,IAAI,EAAE,EAAE,CAAC;QAChC,eAAe,GAAG,IAAI,CAAC,eAAe,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IACjE,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAElE,MAAM,yBAAyB,CAAC;QAC/B,QAAQ,EAAE,CAAC;QACX,QAAQ;QACR,WAAW,EAAE,WAAW;QACxB,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe;QACjD,mBAAmB,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;QAC/C,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;QACtB,mDAAmD;QACnD,KAAK,EAAE,EAAC,UAAU,EAAC;KACnB,CAAC,CAAC;AACJ,CAAC,CAAC;AACF,eAAe,oBAAoB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hardhat-deploy",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.47",
|
|
4
4
|
"description": "deployment plugin for hardhat",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -28,25 +28,25 @@
|
|
|
28
28
|
"src"
|
|
29
29
|
],
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@changesets/cli": "^2.29.
|
|
32
|
-
"@types/node": "^24.
|
|
31
|
+
"@changesets/cli": "^2.29.7",
|
|
32
|
+
"@types/node": "^24.5.2",
|
|
33
33
|
"as-soon": "^0.0.11",
|
|
34
|
-
"hardhat": "3.0.
|
|
34
|
+
"hardhat": "3.0.6",
|
|
35
35
|
"rimraf": "^6.0.1",
|
|
36
|
-
"rocketh": "
|
|
36
|
+
"rocketh": "0.15.0",
|
|
37
37
|
"set-defaults": "^0.0.5",
|
|
38
38
|
"typescript": "^5.9.2"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"hardhat": "^3.0.
|
|
42
|
-
"rocketh": "^0.
|
|
41
|
+
"hardhat": "^3.0.6",
|
|
42
|
+
"rocketh": "^0.15.0"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@nomicfoundation/hardhat-zod-utils": "3.0.
|
|
45
|
+
"@nomicfoundation/hardhat-zod-utils": "3.0.1",
|
|
46
46
|
"@types/debug": "^4.1.12",
|
|
47
|
-
"debug": "^4.4.
|
|
47
|
+
"debug": "^4.4.3",
|
|
48
48
|
"slash": "^5.1.0",
|
|
49
|
-
"zod": "^4.1.
|
|
49
|
+
"zod": "^4.1.9"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "tsc --project tsconfig.json",
|
package/src/helpers.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
UnresolvedNetworkSpecificData,
|
|
15
15
|
loadEnvironment,
|
|
16
16
|
enhanceEnvIfNeeded,
|
|
17
|
+
chainByCanonicalName,
|
|
17
18
|
} from 'rocketh';
|
|
18
19
|
|
|
19
20
|
export function setupHardhatDeploy<
|
|
@@ -22,12 +23,12 @@ export function setupHardhatDeploy<
|
|
|
22
23
|
Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData
|
|
23
24
|
>(extensions: Extensions) {
|
|
24
25
|
async function loadEnvironmentFromHardhatWithExtensions(
|
|
25
|
-
required: {hre: HardhatRuntimeEnvironment; connection?: NetworkConnection}
|
|
26
|
-
options?: {
|
|
27
|
-
|
|
28
|
-
}
|
|
26
|
+
required: {hre: HardhatRuntimeEnvironment; connection?: NetworkConnection}
|
|
27
|
+
// options?: {
|
|
28
|
+
// useChainIdOfForkedNetwork?: boolean;
|
|
29
|
+
// }
|
|
29
30
|
) {
|
|
30
|
-
const env = await loadEnvironmentFromHardhat<NamedAccounts, Data>(required
|
|
31
|
+
const env = await loadEnvironmentFromHardhat<NamedAccounts, Data>(required);
|
|
31
32
|
return enhanceEnvIfNeeded(env, extensions);
|
|
32
33
|
}
|
|
33
34
|
|
|
@@ -36,52 +37,55 @@ export function setupHardhatDeploy<
|
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
export async function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
export async function generateForkConfig(
|
|
41
|
+
params: {hre: HardhatRuntimeEnvironment; connection?: NetworkConnection}
|
|
42
|
+
// options?: {
|
|
43
|
+
// useChainIdOfForkedNetwork?: boolean;
|
|
44
|
+
// }
|
|
45
|
+
): Promise<{provider: any; environment: string | {fork: string}; connection: NetworkConnection; isFork: boolean}> {
|
|
46
|
+
const fork = process.env.HARDHAT_FORK as string | undefined;
|
|
47
|
+
|
|
48
|
+
const connection =
|
|
49
|
+
params.connection || fork
|
|
50
|
+
? await params.hre.network.connect({network: 'fork'})
|
|
51
|
+
: await params.hre.network.connect();
|
|
52
|
+
|
|
49
53
|
let provider: any = connection.provider;
|
|
50
|
-
let
|
|
54
|
+
let environment: string | {fork: string} = connection.networkName;
|
|
51
55
|
let forkChainId: number | undefined;
|
|
52
|
-
|
|
56
|
+
|
|
53
57
|
if (fork) {
|
|
54
|
-
if (options?.useChainIdOfForkedNetwork) {
|
|
55
|
-
|
|
58
|
+
// if (options?.useChainIdOfForkedNetwork) {
|
|
59
|
+
// const forkNetworkConfig = params.hre.config.networks[fork];
|
|
56
60
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
61
|
+
// if (forkNetworkConfig.type === 'edr-simulated') {
|
|
62
|
+
// forkChainId = forkNetworkConfig.chainId;
|
|
63
|
+
// } else if (forkNetworkConfig.chainId) {
|
|
64
|
+
// forkChainId = forkNetworkConfig.chainId;
|
|
65
|
+
// } else {
|
|
66
|
+
// if ('url' in forkNetworkConfig) {
|
|
67
|
+
// const url = await forkNetworkConfig.url.getUrl();
|
|
68
|
+
// const response = await fetch(url, {
|
|
69
|
+
// method: 'POST',
|
|
70
|
+
// headers: {
|
|
71
|
+
// 'Content-Type': 'application/json',
|
|
72
|
+
// },
|
|
73
|
+
// body: JSON.stringify({
|
|
74
|
+
// jsonrpc: '2.0',
|
|
75
|
+
// id: 1,
|
|
76
|
+
// method: 'eth_chainId',
|
|
77
|
+
// params: [],
|
|
78
|
+
// }),
|
|
79
|
+
// });
|
|
80
|
+
// const json = (await response.json()) as {result: string};
|
|
81
|
+
// forkChainId = Number(json.result);
|
|
82
|
+
// } else {
|
|
83
|
+
// throw new Error(`cannot fetch chainId`);
|
|
84
|
+
// }
|
|
85
|
+
// }
|
|
86
|
+
// }
|
|
83
87
|
|
|
84
|
-
|
|
88
|
+
environment = {
|
|
85
89
|
fork,
|
|
86
90
|
};
|
|
87
91
|
}
|
|
@@ -107,13 +111,28 @@ export async function loadEnvironmentFromHardhat<
|
|
|
107
111
|
});
|
|
108
112
|
}
|
|
109
113
|
|
|
114
|
+
return {provider, environment, connection, isFork: !!fork};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function loadEnvironmentFromHardhat<
|
|
118
|
+
NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
|
|
119
|
+
Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData
|
|
120
|
+
>(
|
|
121
|
+
params: {hre: HardhatRuntimeEnvironment; connection?: NetworkConnection}
|
|
122
|
+
// TODO ?
|
|
123
|
+
// options?: {
|
|
124
|
+
// useChainIdOfForkedNetwork?: boolean;
|
|
125
|
+
// }
|
|
126
|
+
): Promise<Environment<NamedAccounts, Data>> {
|
|
127
|
+
const {connection, environment, provider, isFork} = await generateForkConfig(params);
|
|
110
128
|
// console.log(`loading environments...`);
|
|
111
129
|
return loadEnvironment<NamedAccounts, Data>({
|
|
112
130
|
provider,
|
|
113
|
-
|
|
131
|
+
environment,
|
|
114
132
|
extra: {
|
|
115
133
|
connection,
|
|
116
134
|
},
|
|
135
|
+
saveDeployments: isFork ? false : undefined,
|
|
117
136
|
});
|
|
118
137
|
}
|
|
119
138
|
|
|
@@ -157,7 +176,7 @@ export function getRPC(networkName: string): string | SensitiveString | undefine
|
|
|
157
176
|
return uri;
|
|
158
177
|
}
|
|
159
178
|
|
|
160
|
-
export function getMnemonic(networkName?: string): string | SensitiveString {
|
|
179
|
+
export function getMnemonic(networkName?: string, failsOnNoMnemonicSet?: boolean): string | SensitiveString {
|
|
161
180
|
if (networkName) {
|
|
162
181
|
const mnemonic = getVariable('MNEMONIC_', networkName);
|
|
163
182
|
|
|
@@ -168,13 +187,21 @@ export function getMnemonic(networkName?: string): string | SensitiveString {
|
|
|
168
187
|
|
|
169
188
|
const mnemonic = process.env.MNEMONIC;
|
|
170
189
|
if (!mnemonic || mnemonic === '') {
|
|
190
|
+
if (failsOnNoMnemonicSet) {
|
|
191
|
+
throw new Error(
|
|
192
|
+
`no mnemonic set for ${networkName} (via env variable 'MNEMONIC_${networkName}') or globally (via 'MNEMONIC_')`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
171
195
|
return 'test test test test test test test test test test test junk';
|
|
172
196
|
}
|
|
173
197
|
return mnemonic;
|
|
174
198
|
}
|
|
175
199
|
|
|
176
|
-
export function getAccounts(
|
|
177
|
-
|
|
200
|
+
export function getAccounts(
|
|
201
|
+
networkName?: string,
|
|
202
|
+
failsOnNoMnemonicSet?: boolean
|
|
203
|
+
): {mnemonic: string | SensitiveString} {
|
|
204
|
+
return {mnemonic: getMnemonic(networkName, failsOnNoMnemonicSet)};
|
|
178
205
|
}
|
|
179
206
|
|
|
180
207
|
export function addNetworksFromEnv(networks?: Record<string, NetworkUserConfig>): Record<string, NetworkUserConfig> {
|
|
@@ -202,28 +229,28 @@ export function addNetworksFromEnv(networks?: Record<string, NetworkUserConfig>)
|
|
|
202
229
|
return newNetworks;
|
|
203
230
|
}
|
|
204
231
|
|
|
205
|
-
|
|
206
|
-
|
|
232
|
+
const listOfNetworkNamesWithTestAccountAllowed = ['hardhat', 'localhost', 'memory', 'test'];
|
|
233
|
+
export function addNetworksFromKnownList(
|
|
234
|
+
networks?: Record<string, NetworkUserConfig>
|
|
207
235
|
): Record<string, NetworkUserConfig> {
|
|
208
|
-
const newNetworks: Record<string, NetworkUserConfig> = {};
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
const url = getRPC(networkName);
|
|
236
|
+
const newNetworks: Record<string, NetworkUserConfig> = networks ? {...networks} : {};
|
|
237
|
+
const canonicalNames = Object.keys(chainByCanonicalName);
|
|
238
|
+
|
|
239
|
+
for (const canonicalName of canonicalNames) {
|
|
240
|
+
const chain = chainByCanonicalName[canonicalName];
|
|
241
|
+
const url = getRPC(canonicalName) || chain.rpcUrls.default.http[0];
|
|
242
|
+
if (!newNetworks[canonicalName]) {
|
|
216
243
|
if (url) {
|
|
217
|
-
newNetworks[
|
|
218
|
-
|
|
244
|
+
newNetworks[canonicalName] = {
|
|
245
|
+
type: 'http',
|
|
219
246
|
url,
|
|
220
|
-
accounts: getAccounts(
|
|
247
|
+
accounts: getAccounts(canonicalName, !listOfNetworkNamesWithTestAccountAllowed.includes(canonicalName)),
|
|
221
248
|
};
|
|
222
249
|
} else {
|
|
223
|
-
|
|
224
|
-
console.error(`no url for network ${networkName}`);
|
|
225
|
-
}
|
|
250
|
+
console.error(`no url for chain ${canonicalName}`);
|
|
226
251
|
}
|
|
252
|
+
} else {
|
|
253
|
+
// console.error(`duplicated chain ${canonicalName}`);
|
|
227
254
|
}
|
|
228
255
|
}
|
|
229
256
|
return newNetworks;
|
|
@@ -262,17 +289,15 @@ export function addForkConfiguration(networks: Record<string, NetworkUserConfig>
|
|
|
262
289
|
}
|
|
263
290
|
}
|
|
264
291
|
|
|
265
|
-
const
|
|
266
|
-
networks.
|
|
267
|
-
? networks.hardhat
|
|
268
|
-
: {type: 'edr-simulated', chainType: 'l1'};
|
|
292
|
+
const existingForkConfiguration: EdrNetworkUserConfig =
|
|
293
|
+
networks.fork && networks.fork.type === 'edr-simulated' ? networks.fork : {type: 'edr-simulated', chainType: 'l1'};
|
|
269
294
|
|
|
270
295
|
const newNetworks: Record<string, NetworkUserConfig> = {
|
|
271
|
-
...
|
|
272
|
-
|
|
273
|
-
...
|
|
296
|
+
...networks,
|
|
297
|
+
fork: {
|
|
298
|
+
...existingForkConfiguration,
|
|
274
299
|
...{
|
|
275
|
-
accounts: hardhatAccounts ||
|
|
300
|
+
accounts: hardhatAccounts || existingForkConfiguration?.accounts,
|
|
276
301
|
forking: forkURL
|
|
277
302
|
? {
|
|
278
303
|
url: forkURL,
|
package/src/tasks/deploy.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {NewTaskActionFunction} from 'hardhat/types/tasks';
|
|
2
2
|
import {loadAndExecuteDeployments} from 'rocketh';
|
|
3
|
+
import {generateForkConfig} from '../helpers.js';
|
|
3
4
|
|
|
4
5
|
interface RunActionArguments {
|
|
5
6
|
saveDeployments: string;
|
|
@@ -10,7 +11,9 @@ interface RunActionArguments {
|
|
|
10
11
|
const runScriptWithHardhat: NewTaskActionFunction<RunActionArguments> = async (args, hre) => {
|
|
11
12
|
let saveDeployments = true;
|
|
12
13
|
let skipPrompts = args.skipPrompts ? true : false;
|
|
13
|
-
|
|
14
|
+
|
|
15
|
+
const {connection, environment, isFork, provider} = await generateForkConfig({hre});
|
|
16
|
+
|
|
14
17
|
const isMemoryNetwork = connection.networkConfig.type == 'edr-simulated';
|
|
15
18
|
if (isMemoryNetwork) {
|
|
16
19
|
skipPrompts = true;
|
|
@@ -23,11 +26,11 @@ const runScriptWithHardhat: NewTaskActionFunction<RunActionArguments> = async (a
|
|
|
23
26
|
|
|
24
27
|
await loadAndExecuteDeployments({
|
|
25
28
|
logLevel: 1,
|
|
26
|
-
provider
|
|
27
|
-
|
|
28
|
-
saveDeployments,
|
|
29
|
+
provider,
|
|
30
|
+
environment: environment,
|
|
31
|
+
saveDeployments: isFork ? false : saveDeployments,
|
|
29
32
|
askBeforeProceeding: skipPrompts ? false : true,
|
|
30
|
-
tags,
|
|
33
|
+
tags: tags?.split(','),
|
|
31
34
|
// reportGasUse: args.skipGasReport ? false : true,
|
|
32
35
|
extra: {connection},
|
|
33
36
|
});
|