@cofhe/hardhat-plugin 0.4.0 → 0.5.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 +46 -0
- package/dist/index.d.mts +17 -2
- package/dist/index.d.ts +17 -2
- package/dist/index.js +92 -46
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +102 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +22 -21
- package/src/deploy.ts +47 -36
- package/src/index.ts +89 -11
- package/src/logging.ts +8 -5
- package/src/utils.ts +13 -10
package/src/index.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/* eslint-disable no-empty-pattern */
|
|
2
2
|
/* eslint-disable turbo/no-undeclared-env-vars */
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import fs from 'fs';
|
|
4
6
|
import { type PublicClient, type WalletClient } from 'viem';
|
|
5
|
-
import { extendConfig, extendEnvironment, task, types } from 'hardhat/config';
|
|
6
|
-
import { TASK_TEST, TASK_NODE } from 'hardhat/builtin-tasks/task-names';
|
|
7
|
+
import { extendConfig, extendEnvironment, task, subtask, types } from 'hardhat/config';
|
|
8
|
+
import { TASK_TEST, TASK_NODE, TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS } from 'hardhat/builtin-tasks/task-names';
|
|
7
9
|
import { HardhatEthersSigner } from '@nomicfoundation/hardhat-ethers/signers';
|
|
8
10
|
import {
|
|
9
11
|
type CofheClient,
|
|
@@ -16,13 +18,12 @@ import { HardhatSignerAdapter } from '@cofhe/sdk/adapters';
|
|
|
16
18
|
|
|
17
19
|
import { localcofheFundAccount } from './fund.js';
|
|
18
20
|
import { TASK_COFHE_MOCKS_DEPLOY, TASK_COFHE_MOCKS_SET_LOG_OPS, TASK_COFHE_USE_FAUCET } from './consts.js';
|
|
19
|
-
import { deployMocks, type DeployMocksArgs } from './deploy.js';
|
|
21
|
+
import { deployMocks, type DeployMocksArgs, type LogMocksDeploy } from './deploy.js';
|
|
20
22
|
import { mock_setLoggingEnabled, mock_withLogs } from './logging.js';
|
|
21
23
|
import { getFixedMockContract, mock_expectPlaintext } from './utils.js';
|
|
22
24
|
import { mock_getPlaintext } from './utils.js';
|
|
23
25
|
import { hardhat } from '@cofhe/sdk/chains';
|
|
24
26
|
import {
|
|
25
|
-
MockACLArtifact,
|
|
26
27
|
MockThresholdNetworkArtifact,
|
|
27
28
|
MockTaskManagerArtifact,
|
|
28
29
|
MockZkVerifierArtifact,
|
|
@@ -45,6 +46,13 @@ declare module 'hardhat/types/config' {
|
|
|
45
46
|
logMocks?: boolean;
|
|
46
47
|
/** Whether to show gas usage warnings for mock operations (default: true) */
|
|
47
48
|
gasWarning?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Controls deploy-mocks console output.
|
|
51
|
+
* - `''` — silent, no output
|
|
52
|
+
* - `'v'` — single summary line (default)
|
|
53
|
+
* - `'vv'` — full per-contract deployment logs
|
|
54
|
+
*/
|
|
55
|
+
mocksDeployVerbosity?: LogMocksDeploy;
|
|
48
56
|
};
|
|
49
57
|
}
|
|
50
58
|
|
|
@@ -54,10 +62,77 @@ declare module 'hardhat/types/config' {
|
|
|
54
62
|
logMocks: boolean;
|
|
55
63
|
/** Whether to show gas usage warnings for mock operations (default: true) */
|
|
56
64
|
gasWarning: boolean;
|
|
65
|
+
mocksDeployVerbosity: LogMocksDeploy;
|
|
57
66
|
};
|
|
58
67
|
}
|
|
59
68
|
}
|
|
60
69
|
|
|
70
|
+
const MOCK_STUBS_DIR_NAME = 'cofhe-stubs';
|
|
71
|
+
const MOCK_STUBS_FILE_NAME = 'CofheMocksImports.sol';
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Returns the absolute paths of every .sol file shipped inside the
|
|
75
|
+
* @cofhe/mock-contracts/contracts directory.
|
|
76
|
+
*/
|
|
77
|
+
function getMockContractsSolFiles(): string[] {
|
|
78
|
+
let contractsDir: string;
|
|
79
|
+
try {
|
|
80
|
+
const pkgJson = require.resolve('@cofhe/mock-contracts/package.json');
|
|
81
|
+
contractsDir = path.join(path.dirname(pkgJson), 'contracts');
|
|
82
|
+
} catch {
|
|
83
|
+
contractsDir = path.join(process.cwd(), 'node_modules', '@cofhe', 'mock-contracts', 'contracts');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!fs.existsSync(contractsDir)) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return fs
|
|
91
|
+
.readdirSync(contractsDir)
|
|
92
|
+
.filter((f) => f.endsWith('.sol'))
|
|
93
|
+
.map((f) => path.join(contractsDir, f));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Generates a stub Solidity file that imports every contract from
|
|
98
|
+
* @cofhe/mock-contracts/contracts. Writing it to the Hardhat cache directory
|
|
99
|
+
* (which is inside the project root) means:
|
|
100
|
+
* - localPathToSourceName() accepts it (no HH1007)
|
|
101
|
+
* - Hardhat resolves the npm-style "@cofhe/mock-contracts/..." imports
|
|
102
|
+
* the same way it resolves any other node_modules dependency
|
|
103
|
+
* - All mock contract artifacts end up in hre.artifacts, giving Hardhat
|
|
104
|
+
* full ABI knowledge so it can decode reverts and traces
|
|
105
|
+
*/
|
|
106
|
+
function generateMockContractsStubContent(): string {
|
|
107
|
+
const imports = getMockContractsSolFiles()
|
|
108
|
+
.map((f) => `import "@cofhe/mock-contracts/contracts/${path.basename(f)}";`)
|
|
109
|
+
.join('\n');
|
|
110
|
+
|
|
111
|
+
return [
|
|
112
|
+
'// SPDX-License-Identifier: UNLICENSED',
|
|
113
|
+
'// Auto-generated by @cofhe/hardhat-plugin — do not edit.',
|
|
114
|
+
'// Importing mock contracts here causes Hardhat to compile them and register',
|
|
115
|
+
'// their artifacts, enabling proper revert decoding during tests.',
|
|
116
|
+
'pragma solidity >=0.8.25 <0.9.0;',
|
|
117
|
+
'',
|
|
118
|
+
imports,
|
|
119
|
+
'',
|
|
120
|
+
].join('\n');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS).setAction(async (taskArgs: { sourcePath?: string }, hre, runSuper) => {
|
|
124
|
+
const existing: string[] = await runSuper(taskArgs);
|
|
125
|
+
|
|
126
|
+
// Write the stub inside the Hardhat cache dir so that it lives within the
|
|
127
|
+
// project root — a requirement of localPathToSourceName (HH1007).
|
|
128
|
+
const stubDir = path.join(hre.config.paths.cache, MOCK_STUBS_DIR_NAME);
|
|
129
|
+
const stubPath = path.join(stubDir, MOCK_STUBS_FILE_NAME);
|
|
130
|
+
fs.mkdirSync(stubDir, { recursive: true });
|
|
131
|
+
fs.writeFileSync(stubPath, generateMockContractsStubContent(), 'utf8');
|
|
132
|
+
|
|
133
|
+
return [...new Set([...existing, stubPath])];
|
|
134
|
+
});
|
|
135
|
+
|
|
61
136
|
extendConfig((config, userConfig) => {
|
|
62
137
|
// Allow users to override the localcofhe network config
|
|
63
138
|
if (userConfig.networks && userConfig.networks.localcofhe) {
|
|
@@ -110,8 +185,9 @@ extendConfig((config, userConfig) => {
|
|
|
110
185
|
|
|
111
186
|
// Add cofhe config
|
|
112
187
|
config.cofhe = {
|
|
113
|
-
logMocks: userConfig.cofhe?.logMocks ??
|
|
114
|
-
gasWarning: userConfig.cofhe?.gasWarning ??
|
|
188
|
+
logMocks: userConfig.cofhe?.logMocks ?? false,
|
|
189
|
+
gasWarning: userConfig.cofhe?.gasWarning ?? false,
|
|
190
|
+
mocksDeployVerbosity: (userConfig.cofhe?.mocksDeployVerbosity ?? 'v') as LogMocksDeploy,
|
|
115
191
|
};
|
|
116
192
|
});
|
|
117
193
|
|
|
@@ -148,12 +224,11 @@ task(TASK_COFHE_USE_FAUCET, 'Fund an account from the funder')
|
|
|
148
224
|
|
|
149
225
|
task(TASK_COFHE_MOCKS_DEPLOY, 'Deploys the mock contracts on the Hardhat network')
|
|
150
226
|
.addOptionalParam('deployTestBed', 'Whether to deploy the test bed', true, types.boolean)
|
|
151
|
-
.
|
|
152
|
-
.setAction(async ({ deployTestBed, silent }: DeployMocksArgs, hre) => {
|
|
227
|
+
.setAction(async ({ deployTestBed }: DeployMocksArgs, hre) => {
|
|
153
228
|
await deployMocks(hre, {
|
|
154
229
|
deployTestBed: deployTestBed ?? true,
|
|
155
230
|
gasWarning: hre.config.cofhe.gasWarning ?? true,
|
|
156
|
-
|
|
231
|
+
mocksDeployVerbosity: hre.config.cofhe.mocksDeployVerbosity,
|
|
157
232
|
});
|
|
158
233
|
});
|
|
159
234
|
|
|
@@ -169,6 +244,7 @@ task(TASK_TEST, 'Deploy mock contracts on hardhat').setAction(async ({}, hre, ru
|
|
|
169
244
|
await deployMocks(hre, {
|
|
170
245
|
deployTestBed: true,
|
|
171
246
|
gasWarning: hre.config.cofhe.gasWarning ?? true,
|
|
247
|
+
mocksDeployVerbosity: hre.config.cofhe.mocksDeployVerbosity,
|
|
172
248
|
});
|
|
173
249
|
}
|
|
174
250
|
return runSuper();
|
|
@@ -185,6 +261,7 @@ task(TASK_NODE, 'Deploy mock contracts on hardhat').setAction(async ({}, hre, ru
|
|
|
185
261
|
await deployMocks(hre, {
|
|
186
262
|
deployTestBed: true,
|
|
187
263
|
gasWarning: hre.config.cofhe.gasWarning ?? true,
|
|
264
|
+
mocksDeployVerbosity: hre.config.cofhe.mocksDeployVerbosity,
|
|
188
265
|
});
|
|
189
266
|
}
|
|
190
267
|
return runSuper();
|
|
@@ -438,7 +515,7 @@ extendEnvironment((hre) => {
|
|
|
438
515
|
return mock_setLoggingEnabled(hre, false);
|
|
439
516
|
},
|
|
440
517
|
deployMocks: async (options: DeployMocksArgs = {}) => {
|
|
441
|
-
return deployMocks(hre, options);
|
|
518
|
+
return deployMocks(hre, { mocksDeployVerbosity: hre.config.cofhe.mocksDeployVerbosity, ...options });
|
|
442
519
|
},
|
|
443
520
|
getPlaintext: async (ctHash: bigint | string) => {
|
|
444
521
|
const [signer] = await hre.ethers.getSigners();
|
|
@@ -453,7 +530,8 @@ extendEnvironment((hre) => {
|
|
|
453
530
|
getMockACL: async () => {
|
|
454
531
|
const taskManager = await getFixedMockContract(hre, MockTaskManagerArtifact);
|
|
455
532
|
const aclAddress = await taskManager.acl();
|
|
456
|
-
|
|
533
|
+
const aclArtifact = await hre.artifacts.readArtifact('MockACL');
|
|
534
|
+
return hre.ethers.getContractAt(aclArtifact.abi, aclAddress) as unknown as MockACL;
|
|
457
535
|
},
|
|
458
536
|
getMockThresholdNetwork: async () =>
|
|
459
537
|
getFixedMockContract(hre, MockThresholdNetworkArtifact) as unknown as Promise<MockThresholdNetwork>,
|
package/src/logging.ts
CHANGED
|
@@ -59,11 +59,14 @@ export const mock_withLogs = async (
|
|
|
59
59
|
|
|
60
60
|
await setLoggingEnabled(hre, true);
|
|
61
61
|
printLogsEnabledMessage(`"${chalk.bold(closureName)}" logs:`);
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
try {
|
|
63
|
+
await closure();
|
|
64
|
+
} finally {
|
|
65
|
+
printLogsBlockEnd();
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
// If logs were disabled, disable them again
|
|
68
|
+
if (!initiallyEnabled) {
|
|
69
|
+
await setLoggingEnabled(hre, false);
|
|
70
|
+
}
|
|
68
71
|
}
|
|
69
72
|
};
|
package/src/utils.ts
CHANGED
|
@@ -7,20 +7,22 @@ import type { HardhatRuntimeEnvironment } from 'hardhat/types';
|
|
|
7
7
|
|
|
8
8
|
// Deployment utils
|
|
9
9
|
|
|
10
|
-
/// Deploys a mock contract from a pre-built artifact from the mock-contracts package
|
|
11
|
-
///
|
|
12
|
-
///
|
|
10
|
+
/// Deploys a mock contract from a pre-built artifact from the mock-contracts package.
|
|
11
|
+
/// ABI and bytecode are sourced from Hardhat's artifact registry (populated during compilation)
|
|
12
|
+
/// so that Hardhat can decode reverts and trace calls against these contracts.
|
|
13
|
+
/// If the mock contract should be deployed to a fixed address, `hardhat_setCode` is used.
|
|
14
|
+
/// Otherwise, ethers.js deploys it to a normal address.
|
|
13
15
|
export const deployMockContractFromArtifact = async (hre: HardhatRuntimeEnvironment, artifact: MockArtifact) => {
|
|
14
|
-
|
|
16
|
+
const hardhatArtifact = await hre.artifacts.readArtifact(artifact.contractName);
|
|
17
|
+
|
|
15
18
|
if (artifact.isFixed) {
|
|
16
|
-
await hre.network.provider.send('hardhat_setCode', [artifact.fixedAddress,
|
|
17
|
-
return
|
|
19
|
+
await hre.network.provider.send('hardhat_setCode', [artifact.fixedAddress, hardhatArtifact.deployedBytecode]);
|
|
20
|
+
return hre.ethers.getContractAt(hardhatArtifact.abi, artifact.fixedAddress);
|
|
18
21
|
}
|
|
19
22
|
|
|
20
|
-
// Use ethers.js to deploy to variable address
|
|
21
23
|
const [signer] = await hre.ethers.getSigners();
|
|
22
|
-
const factory = new hre.ethers.ContractFactory(
|
|
23
|
-
const contract = await factory.deploy(
|
|
24
|
+
const factory = new hre.ethers.ContractFactory(hardhatArtifact.abi, hardhatArtifact.bytecode, signer);
|
|
25
|
+
const contract = await factory.deploy();
|
|
24
26
|
await contract.waitForDeployment();
|
|
25
27
|
return contract as Contract;
|
|
26
28
|
};
|
|
@@ -29,7 +31,8 @@ export const getFixedMockContract = async (hre: HardhatRuntimeEnvironment, artif
|
|
|
29
31
|
if (!artifact.isFixed) {
|
|
30
32
|
throw new Error('Artifact is not fixed');
|
|
31
33
|
}
|
|
32
|
-
|
|
34
|
+
const hardhatArtifact = await hre.artifacts.readArtifact(artifact.contractName);
|
|
35
|
+
return hre.ethers.getContractAt(hardhatArtifact.abi, artifact.fixedAddress);
|
|
33
36
|
};
|
|
34
37
|
|
|
35
38
|
// Testing utils
|