@cofhe/hardhat-plugin 0.1.0 → 0.2.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 +71 -0
- package/README.md +8 -8
- package/dist/index.d.mts +40 -30
- package/dist/index.d.ts +40 -30
- package/dist/index.js +57 -59
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +63 -53
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -7
- package/src/consts.ts +8 -0
- package/src/deploy.ts +246 -0
- package/src/fund.ts +82 -0
- package/src/index.ts +439 -0
- package/src/logging.ts +75 -0
- package/src/utils.ts +75 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
/* eslint-disable no-empty-pattern */
|
|
2
|
+
/* eslint-disable turbo/no-undeclared-env-vars */
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
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 { HardhatEthersSigner } from '@nomicfoundation/hardhat-ethers/signers';
|
|
8
|
+
import {
|
|
9
|
+
MOCKS_ZK_VERIFIER_SIGNER_ADDRESS,
|
|
10
|
+
type CofhesdkClient,
|
|
11
|
+
type CofhesdkConfig,
|
|
12
|
+
type CofhesdkInputConfig,
|
|
13
|
+
} from '@cofhe/sdk';
|
|
14
|
+
import { createCofhesdkClient, createCofhesdkConfig } from '@cofhe/sdk/node';
|
|
15
|
+
import { HardhatSignerAdapter } from '@cofhe/sdk/adapters';
|
|
16
|
+
|
|
17
|
+
import { localcofheFundAccount } from './fund.js';
|
|
18
|
+
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';
|
|
20
|
+
import { mock_setLoggingEnabled, mock_withLogs } from './logging.js';
|
|
21
|
+
import { mock_expectPlaintext } from './utils.js';
|
|
22
|
+
import { mock_getPlaintext } from './utils.js';
|
|
23
|
+
import type { Contract } from 'ethers';
|
|
24
|
+
import {
|
|
25
|
+
MockACLArtifact,
|
|
26
|
+
MockQueryDecrypterArtifact,
|
|
27
|
+
MockTaskManagerArtifact,
|
|
28
|
+
MockZkVerifierArtifact,
|
|
29
|
+
TestBedArtifact,
|
|
30
|
+
} from '@cofhe/mock-contracts';
|
|
31
|
+
import { hardhat } from '@cofhe/sdk/chains';
|
|
32
|
+
export {
|
|
33
|
+
MockACLArtifact,
|
|
34
|
+
MockQueryDecrypterArtifact,
|
|
35
|
+
MockTaskManagerArtifact,
|
|
36
|
+
MockZkVerifierArtifact,
|
|
37
|
+
TestBedArtifact,
|
|
38
|
+
} from '@cofhe/mock-contracts';
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Configuration interface for the CoFHE Hardhat plugin.
|
|
42
|
+
* Allows users to configure mock logging and gas warning settings.
|
|
43
|
+
*/
|
|
44
|
+
declare module 'hardhat/types/config' {
|
|
45
|
+
interface HardhatUserConfig {
|
|
46
|
+
cofhesdk?: {
|
|
47
|
+
/** Whether to log mock operations (default: true) */
|
|
48
|
+
logMocks?: boolean;
|
|
49
|
+
/** Whether to show gas usage warnings for mock operations (default: true) */
|
|
50
|
+
gasWarning?: boolean;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface HardhatConfig {
|
|
55
|
+
cofhesdk: {
|
|
56
|
+
/** Whether to log mock operations (default: true) */
|
|
57
|
+
logMocks: boolean;
|
|
58
|
+
/** Whether to show gas usage warnings for mock operations (default: true) */
|
|
59
|
+
gasWarning: boolean;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
extendConfig((config, userConfig) => {
|
|
65
|
+
// Allow users to override the localcofhe network config
|
|
66
|
+
if (userConfig.networks && userConfig.networks.localcofhe) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Default config
|
|
71
|
+
config.networks.localcofhe = {
|
|
72
|
+
gas: 'auto',
|
|
73
|
+
gasMultiplier: 1.2,
|
|
74
|
+
gasPrice: 'auto',
|
|
75
|
+
timeout: 10_000,
|
|
76
|
+
httpHeaders: {},
|
|
77
|
+
url: 'http://127.0.0.1:42069',
|
|
78
|
+
accounts: [
|
|
79
|
+
'0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
|
|
80
|
+
'0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d',
|
|
81
|
+
'0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a',
|
|
82
|
+
'0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6',
|
|
83
|
+
],
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Only add Sepolia config if user hasn't defined it
|
|
87
|
+
if (!userConfig.networks?.['eth-sepolia']) {
|
|
88
|
+
config.networks['eth-sepolia'] = {
|
|
89
|
+
url: process.env.SEPOLIA_RPC_URL ?? 'https://ethereum-sepolia.publicnode.com',
|
|
90
|
+
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
|
|
91
|
+
chainId: 11155111,
|
|
92
|
+
gas: 'auto',
|
|
93
|
+
gasMultiplier: 1.2,
|
|
94
|
+
gasPrice: 'auto',
|
|
95
|
+
timeout: 60_000,
|
|
96
|
+
httpHeaders: {},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Only add Arbitrum Sepolia config if user hasn't defined it
|
|
101
|
+
if (!userConfig.networks?.['arb-sepolia']) {
|
|
102
|
+
config.networks['arb-sepolia'] = {
|
|
103
|
+
url: process.env.ARBITRUM_SEPOLIA_RPC_URL ?? 'https://sepolia-rollup.arbitrum.io/rpc',
|
|
104
|
+
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
|
|
105
|
+
chainId: 421614,
|
|
106
|
+
gas: 'auto',
|
|
107
|
+
gasMultiplier: 1.2,
|
|
108
|
+
gasPrice: 'auto',
|
|
109
|
+
timeout: 60_000,
|
|
110
|
+
httpHeaders: {},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Add cofhe config
|
|
115
|
+
config.cofhesdk = {
|
|
116
|
+
logMocks: userConfig.cofhesdk?.logMocks ?? true,
|
|
117
|
+
gasWarning: userConfig.cofhesdk?.gasWarning ?? true,
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
type UseFaucetArgs = {
|
|
122
|
+
address?: string;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
task(TASK_COFHE_USE_FAUCET, 'Fund an account from the funder')
|
|
126
|
+
.addOptionalParam('address', 'Address to fund', undefined, types.string)
|
|
127
|
+
.setAction(async ({ address }: UseFaucetArgs, hre) => {
|
|
128
|
+
const { network } = hre;
|
|
129
|
+
const { name: networkName } = network;
|
|
130
|
+
|
|
131
|
+
if (networkName !== 'localcofhe') {
|
|
132
|
+
console.info(chalk.yellow(`Programmatic faucet only supported for localcofhe`));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (!address) {
|
|
137
|
+
console.info(chalk.red(`Failed to get address to fund`));
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
console.info(chalk.green(`Getting funds from faucet for ${address}`));
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
await localcofheFundAccount(hre, address);
|
|
145
|
+
} catch (e) {
|
|
146
|
+
console.info(chalk.red(`failed to get funds from localcofhe for ${address}: ${e}`));
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// DEPLOY TASKS
|
|
151
|
+
|
|
152
|
+
task(TASK_COFHE_MOCKS_DEPLOY, 'Deploys the mock contracts on the Hardhat network')
|
|
153
|
+
.addOptionalParam('deployTestBed', 'Whether to deploy the test bed', true, types.boolean)
|
|
154
|
+
.addOptionalParam('silent', 'Whether to suppress output', false, types.boolean)
|
|
155
|
+
.setAction(async ({ deployTestBed, silent }: DeployMocksArgs, hre) => {
|
|
156
|
+
await deployMocks(hre, {
|
|
157
|
+
deployTestBed: deployTestBed ?? true,
|
|
158
|
+
gasWarning: hre.config.cofhesdk.gasWarning ?? true,
|
|
159
|
+
silent: silent ?? false,
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
task(TASK_TEST, 'Deploy mock contracts on hardhat').setAction(async ({}, hre, runSuper) => {
|
|
164
|
+
await deployMocks(hre, {
|
|
165
|
+
deployTestBed: true,
|
|
166
|
+
gasWarning: hre.config.cofhesdk.gasWarning ?? true,
|
|
167
|
+
});
|
|
168
|
+
return runSuper();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
task(TASK_NODE, 'Deploy mock contracts on hardhat').setAction(async ({}, hre, runSuper) => {
|
|
172
|
+
await deployMocks(hre, {
|
|
173
|
+
deployTestBed: true,
|
|
174
|
+
gasWarning: hre.config.cofhesdk.gasWarning ?? true,
|
|
175
|
+
});
|
|
176
|
+
return runSuper();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// SET LOG OPS
|
|
180
|
+
|
|
181
|
+
task(TASK_COFHE_MOCKS_SET_LOG_OPS, 'Set logging for the Mock CoFHE contracts')
|
|
182
|
+
.addParam('enable', 'Whether to enable logging', false, types.boolean)
|
|
183
|
+
.setAction(async ({ enable }, hre) => {
|
|
184
|
+
await mock_setLoggingEnabled(hre, enable);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// MOCK UTILS
|
|
188
|
+
|
|
189
|
+
export * from './utils.js';
|
|
190
|
+
export * from './fund.js';
|
|
191
|
+
export * from './logging.js';
|
|
192
|
+
export * from './deploy.js';
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Runtime environment extensions for the CoFHE Hardhat plugin.
|
|
196
|
+
* Provides access to CoFHE initialization, environment checks, and mock utilities.
|
|
197
|
+
*/
|
|
198
|
+
declare module 'hardhat/types/runtime' {
|
|
199
|
+
export interface HardhatRuntimeEnvironment {
|
|
200
|
+
cofhesdk: {
|
|
201
|
+
/**
|
|
202
|
+
* Create a CoFHE SDK configuration for use with cofhesdk.createCofhesdkClient(...)
|
|
203
|
+
* @param {CofhesdkInputConfig} config - The CoFHE SDK input configuration
|
|
204
|
+
* @returns {CofhesdkConfig} The CoFHE SDK configuration
|
|
205
|
+
*/
|
|
206
|
+
createCofhesdkConfig: (config: CofhesdkInputConfig) => Promise<CofhesdkConfig>;
|
|
207
|
+
/**
|
|
208
|
+
* Create a CoFHE SDK client instance
|
|
209
|
+
* @param {CofhesdkConfig} config - The CoFHE SDK configuration (use createCofhesdkConfig to create with Node.js defaults)
|
|
210
|
+
* @returns {Promise<CofhesdkClient>} The CoFHE SDK client instance
|
|
211
|
+
*/
|
|
212
|
+
createCofhesdkClient: (config: CofhesdkConfig) => CofhesdkClient;
|
|
213
|
+
/**
|
|
214
|
+
* Create viem clients from a Hardhat ethers signer, to be used with `cofhesdkClient.connect(...)`
|
|
215
|
+
* @param {HardhatEthersSigner} signer - The Hardhat ethers signer to use
|
|
216
|
+
* @returns {Promise<{ publicClient: PublicClient; walletClient: WalletClient }>} The viem clients
|
|
217
|
+
*/
|
|
218
|
+
hardhatSignerAdapter: (
|
|
219
|
+
signer: HardhatEthersSigner
|
|
220
|
+
) => Promise<{ publicClient: PublicClient; walletClient: WalletClient }>;
|
|
221
|
+
/**
|
|
222
|
+
* Connect a CoFHE SDK client with a Hardhat ethers signer
|
|
223
|
+
* @param {CofhesdkClient} client - The CoFHE SDK client to connect
|
|
224
|
+
* @param {HardhatEthersSigner} signer - The Hardhat ethers signer to use
|
|
225
|
+
* @returns {Promise<void>}
|
|
226
|
+
*/
|
|
227
|
+
connectWithHardhatSigner: (client: CofhesdkClient, signer: HardhatEthersSigner) => Promise<void>;
|
|
228
|
+
/**
|
|
229
|
+
* Create and connect to a batteries included client.
|
|
230
|
+
* Also generates a self-usage a permit for the signer.
|
|
231
|
+
* If customization is needed, use createCofhesdkClient and connectWithHardhatSigner.
|
|
232
|
+
* @param {HardhatEthersSigner} signer - The Hardhat ethers signer to use (optional - defaults to first signer)
|
|
233
|
+
* @returns {Promise<CofhesdkClient>} The CoFHE SDK client instance
|
|
234
|
+
*/
|
|
235
|
+
createBatteriesIncludedCofhesdkClient: (signer?: HardhatEthersSigner) => Promise<CofhesdkClient>;
|
|
236
|
+
|
|
237
|
+
mocks: {
|
|
238
|
+
/**
|
|
239
|
+
* **[MOCKS ONLY]**
|
|
240
|
+
*
|
|
241
|
+
* Execute a block of code with cofhe mock contracts logging enabled.
|
|
242
|
+
*
|
|
243
|
+
* _(If logging only a function, we recommend passing the function name as the closureName (ex "counter.increment()"))_
|
|
244
|
+
*
|
|
245
|
+
* Example usage:
|
|
246
|
+
*
|
|
247
|
+
* ```ts
|
|
248
|
+
* await hre.cofhesdk.mocks.withLogs("counter.increment()", async () => {
|
|
249
|
+
* await counter.increment();
|
|
250
|
+
* });
|
|
251
|
+
* ```
|
|
252
|
+
*
|
|
253
|
+
* Expected output:
|
|
254
|
+
* ```
|
|
255
|
+
* ┌──────────────────┬──────────────────────────────────────────────────
|
|
256
|
+
* │ [COFHE-MOCKS] │ "counter.increment()" logs:
|
|
257
|
+
* ├──────────────────┴──────────────────────────────────────────────────
|
|
258
|
+
* ├ FHE.add | euint32(4473..3424)[0] + euint32(1157..3648)[1] => euint32(1106..1872)[1]
|
|
259
|
+
* ├ FHE.allowThis | euint32(1106..1872)[1] -> 0x663f..6602
|
|
260
|
+
* ├ FHE.allow | euint32(1106..1872)[1] -> 0x3c44..93bc
|
|
261
|
+
* └─────────────────────────────────────────────────────────────────────
|
|
262
|
+
* ```
|
|
263
|
+
* @param {string} closureName - Name of the code block to log within
|
|
264
|
+
* @param {() => Promise<void>} closure - The async function to execute
|
|
265
|
+
*/
|
|
266
|
+
withLogs: (closureName: string, closure: () => Promise<void>) => Promise<void>;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* **[MOCKS ONLY]**
|
|
270
|
+
*
|
|
271
|
+
* Enable logging from cofhe mock contracts
|
|
272
|
+
* @param {string} closureName - Optional name of the code block to enable logging for
|
|
273
|
+
*/
|
|
274
|
+
enableLogs: (closureName?: string) => Promise<void>;
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* **[MOCKS ONLY]**
|
|
278
|
+
*
|
|
279
|
+
* Disable logging from cofhe mock contracts
|
|
280
|
+
*/
|
|
281
|
+
disableLogs: () => Promise<void>;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* **[MOCKS ONLY]**
|
|
285
|
+
*
|
|
286
|
+
* Deploy the cofhe mock contracts (normally this is done automatically)
|
|
287
|
+
* @param {DeployMocksArgs} options - Deployment options
|
|
288
|
+
*/
|
|
289
|
+
deployMocks: (options: DeployMocksArgs) => Promise<void>;
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* **[MOCKS ONLY]**
|
|
293
|
+
*
|
|
294
|
+
* Get the plaintext value for a ciphertext hash
|
|
295
|
+
* @param {bigint} ctHash - The ciphertext hash to look up
|
|
296
|
+
* @returns {Promise<bigint>} The plaintext value
|
|
297
|
+
*/
|
|
298
|
+
getPlaintext: (ctHash: bigint) => Promise<bigint>;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* **[MOCKS ONLY]**
|
|
302
|
+
*
|
|
303
|
+
* Assert that a ciphertext hash represents an expected plaintext value
|
|
304
|
+
* @param {bigint} ctHash - The ciphertext hash to check
|
|
305
|
+
* @param {bigint} expectedValue - The expected plaintext value
|
|
306
|
+
*/
|
|
307
|
+
expectPlaintext: (ctHash: bigint, expectedValue: bigint) => Promise<void>;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Get the MockTaskManager contract
|
|
311
|
+
* @returns {Promise<Contract>} The MockTaskManager contract
|
|
312
|
+
*/
|
|
313
|
+
getMockTaskManager: () => Promise<Contract>;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Get the MockACL contract
|
|
317
|
+
* @returns {Promise<Contract>} The MockACL contract
|
|
318
|
+
*/
|
|
319
|
+
getMockACL: () => Promise<Contract>;
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Get the MockQueryDecrypter contract
|
|
323
|
+
* @returns {Promise<Contract>} The MockQueryDecrypter contract
|
|
324
|
+
*/
|
|
325
|
+
getMockQueryDecrypter: () => Promise<Contract>;
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Get the MockZkVerifier contract
|
|
329
|
+
* @returns {Promise<Contract>} The MockZkVerifier contract
|
|
330
|
+
*/
|
|
331
|
+
getMockZkVerifier: () => Promise<Contract>;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Get the TestBed contract
|
|
335
|
+
* @returns {Promise<Contract>} The TestBed contract
|
|
336
|
+
*/
|
|
337
|
+
getTestBed: () => Promise<Contract>;
|
|
338
|
+
};
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
extendEnvironment((hre) => {
|
|
344
|
+
hre.cofhesdk = {
|
|
345
|
+
createCofhesdkConfig: async (config: CofhesdkInputConfig) => {
|
|
346
|
+
// Create zkv wallet client
|
|
347
|
+
// This wallet interacts with the MockZkVerifier contract so that the user's connected wallet doesn't have to
|
|
348
|
+
const zkvHhSigner = await hre.ethers.getImpersonatedSigner(MOCKS_ZK_VERIFIER_SIGNER_ADDRESS);
|
|
349
|
+
const { walletClient: zkvWalletClient } = await HardhatSignerAdapter(zkvHhSigner);
|
|
350
|
+
|
|
351
|
+
// Inject zkv wallet client into config
|
|
352
|
+
const configWithZkvWalletClient = {
|
|
353
|
+
environment: 'hardhat' as const,
|
|
354
|
+
...config,
|
|
355
|
+
_internal: {
|
|
356
|
+
...config._internal,
|
|
357
|
+
zkvWalletClient,
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
return createCofhesdkConfig(configWithZkvWalletClient);
|
|
362
|
+
},
|
|
363
|
+
createCofhesdkClient: (config: CofhesdkConfig) => {
|
|
364
|
+
return createCofhesdkClient(config);
|
|
365
|
+
},
|
|
366
|
+
hardhatSignerAdapter: async (signer: HardhatEthersSigner) => {
|
|
367
|
+
return HardhatSignerAdapter(signer);
|
|
368
|
+
},
|
|
369
|
+
connectWithHardhatSigner: async (client: CofhesdkClient, signer: HardhatEthersSigner) => {
|
|
370
|
+
const { publicClient, walletClient } = await HardhatSignerAdapter(signer);
|
|
371
|
+
return client.connect(publicClient, walletClient);
|
|
372
|
+
},
|
|
373
|
+
createBatteriesIncludedCofhesdkClient: async (signer?: HardhatEthersSigner) => {
|
|
374
|
+
// Get signer if not provided
|
|
375
|
+
if (!signer) {
|
|
376
|
+
[signer] = await hre.ethers.getSigners();
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Create config
|
|
380
|
+
const config = await hre.cofhesdk.createCofhesdkConfig({
|
|
381
|
+
environment: 'hardhat',
|
|
382
|
+
supportedChains: [hardhat],
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// Create client
|
|
386
|
+
const client = hre.cofhesdk.createCofhesdkClient(config);
|
|
387
|
+
|
|
388
|
+
// Connect client
|
|
389
|
+
await hre.cofhesdk.connectWithHardhatSigner(client, signer);
|
|
390
|
+
|
|
391
|
+
// Create self-usage permit
|
|
392
|
+
await client.permits.createSelf({
|
|
393
|
+
issuer: signer.address,
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// Return client
|
|
397
|
+
return client;
|
|
398
|
+
},
|
|
399
|
+
mocks: {
|
|
400
|
+
withLogs: async (closureName: string, closure: () => Promise<void>) => {
|
|
401
|
+
return mock_withLogs(hre, closureName, closure);
|
|
402
|
+
},
|
|
403
|
+
enableLogs: async (closureName?: string) => {
|
|
404
|
+
return mock_setLoggingEnabled(hre, true, closureName);
|
|
405
|
+
},
|
|
406
|
+
disableLogs: async () => {
|
|
407
|
+
return mock_setLoggingEnabled(hre, false);
|
|
408
|
+
},
|
|
409
|
+
deployMocks: async (options: DeployMocksArgs) => {
|
|
410
|
+
return deployMocks(hre, options);
|
|
411
|
+
},
|
|
412
|
+
getPlaintext: async (ctHash: bigint) => {
|
|
413
|
+
const [signer] = await hre.ethers.getSigners();
|
|
414
|
+
return mock_getPlaintext(signer.provider, ctHash);
|
|
415
|
+
},
|
|
416
|
+
expectPlaintext: async (ctHash: bigint, expectedValue: bigint) => {
|
|
417
|
+
const [signer] = await hre.ethers.getSigners();
|
|
418
|
+
return mock_expectPlaintext(signer.provider, ctHash, expectedValue);
|
|
419
|
+
},
|
|
420
|
+
getMockTaskManager: async () => {
|
|
421
|
+
return await hre.ethers.getContractAt(MockTaskManagerArtifact.abi, MockTaskManagerArtifact.fixedAddress);
|
|
422
|
+
},
|
|
423
|
+
getMockACL: async () => {
|
|
424
|
+
const tm = await hre.ethers.getContractAt(MockTaskManagerArtifact.abi, MockTaskManagerArtifact.fixedAddress);
|
|
425
|
+
const aclAddress = await tm.acl();
|
|
426
|
+
return await hre.ethers.getContractAt(MockACLArtifact.abi, aclAddress);
|
|
427
|
+
},
|
|
428
|
+
getMockQueryDecrypter: async () => {
|
|
429
|
+
return await hre.ethers.getContractAt(MockQueryDecrypterArtifact.abi, MockQueryDecrypterArtifact.fixedAddress);
|
|
430
|
+
},
|
|
431
|
+
getMockZkVerifier: async () => {
|
|
432
|
+
return await hre.ethers.getContractAt(MockZkVerifierArtifact.abi, MockZkVerifierArtifact.fixedAddress);
|
|
433
|
+
},
|
|
434
|
+
getTestBed: async () => {
|
|
435
|
+
return await hre.ethers.getContractAt(TestBedArtifact.abi, TestBedArtifact.fixedAddress);
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
};
|
|
439
|
+
});
|
package/src/logging.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { type HardhatRuntimeEnvironment } from 'hardhat/types';
|
|
3
|
+
import { TASK_MANAGER_ADDRESS } from './consts';
|
|
4
|
+
import { MockTaskManagerArtifact } from '@cofhe/mock-contracts';
|
|
5
|
+
|
|
6
|
+
const getDeployedMockTaskManager = async (hre: HardhatRuntimeEnvironment) => {
|
|
7
|
+
// Fetch the deployed MockTaskManager
|
|
8
|
+
const taskManager = await hre.ethers.getContractAt(MockTaskManagerArtifact.abi, TASK_MANAGER_ADDRESS);
|
|
9
|
+
|
|
10
|
+
return taskManager;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const getLoggingEnabled = async (hre: HardhatRuntimeEnvironment) => {
|
|
14
|
+
const taskManager = await getDeployedMockTaskManager(hre);
|
|
15
|
+
return await taskManager.logOps();
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const setLoggingEnabled = async (hre: HardhatRuntimeEnvironment, enabled: boolean) => {
|
|
19
|
+
const taskManager = await getDeployedMockTaskManager(hre);
|
|
20
|
+
await taskManager.setLogOps(enabled);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// prettier-ignore
|
|
24
|
+
const printLogsEnabledMessage = (closureMessage: string) => {
|
|
25
|
+
console.log("┌──────────────────┬──────────────────────────────────────────────────");
|
|
26
|
+
console.log(`│ [COFHE-MOCKS] │ ${closureMessage}`);
|
|
27
|
+
console.log("├──────────────────┴──────────────────────────────────────────────────");
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// prettier-ignore
|
|
31
|
+
const printLogsBlockEnd = () => {
|
|
32
|
+
console.log("└─────────────────────────────────────────────────────────────────────");
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const mock_setLoggingEnabled = async (
|
|
36
|
+
hre: HardhatRuntimeEnvironment,
|
|
37
|
+
enabled: boolean,
|
|
38
|
+
closureName?: string
|
|
39
|
+
) => {
|
|
40
|
+
try {
|
|
41
|
+
const initiallyEnabled = await getLoggingEnabled(hre);
|
|
42
|
+
|
|
43
|
+
await setLoggingEnabled(hre, enabled);
|
|
44
|
+
|
|
45
|
+
// Only print if enabling logs
|
|
46
|
+
if (enabled) {
|
|
47
|
+
printLogsEnabledMessage(`${closureName ? `"${chalk.bold(closureName)}" logs:` : 'Logs:'}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Only print if disabling logs AND logs currently enabled
|
|
51
|
+
if (!enabled && initiallyEnabled) {
|
|
52
|
+
printLogsBlockEnd();
|
|
53
|
+
}
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.log(chalk.red('mock_setLoggingEnabled error'), error);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const mock_withLogs = async (
|
|
60
|
+
hre: HardhatRuntimeEnvironment,
|
|
61
|
+
closureName: string,
|
|
62
|
+
closure: () => Promise<void>
|
|
63
|
+
) => {
|
|
64
|
+
const initiallyEnabled = await getLoggingEnabled(hre);
|
|
65
|
+
|
|
66
|
+
await setLoggingEnabled(hre, true);
|
|
67
|
+
printLogsEnabledMessage(`"${chalk.bold(closureName)}" logs:`);
|
|
68
|
+
await closure();
|
|
69
|
+
printLogsBlockEnd();
|
|
70
|
+
|
|
71
|
+
// If logs were disabled, disable them again
|
|
72
|
+
if (!initiallyEnabled) {
|
|
73
|
+
await setLoggingEnabled(hre, false);
|
|
74
|
+
}
|
|
75
|
+
};
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { TASK_MANAGER_ADDRESS, MOCKS_ZK_VERIFIER_ADDRESS } from './consts.js';
|
|
2
|
+
import { expect } from 'chai';
|
|
3
|
+
import { ethers } from 'ethers';
|
|
4
|
+
import { type HardhatEthersProvider } from '@nomicfoundation/hardhat-ethers/internal/hardhat-ethers-provider';
|
|
5
|
+
|
|
6
|
+
const mock_checkIsTestnet = async (fnName: string, provider: HardhatEthersProvider | ethers.JsonRpcProvider) => {
|
|
7
|
+
// Testnet is checked by testing if MockZkVerifier is deployed
|
|
8
|
+
|
|
9
|
+
// Get bytecode at ZK_VERIFIER_ADDRESS
|
|
10
|
+
const bytecode = await provider.getCode(MOCKS_ZK_VERIFIER_ADDRESS);
|
|
11
|
+
|
|
12
|
+
// If bytecode is empty, we are on a testnet
|
|
13
|
+
const isTestnet = bytecode.length === 0;
|
|
14
|
+
|
|
15
|
+
// Log if we are on a testnet
|
|
16
|
+
if (isTestnet) {
|
|
17
|
+
console.log(`${fnName} - skipped on non-testnet chain`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return isTestnet;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const mock_getPlaintext = async (provider: HardhatEthersProvider | ethers.JsonRpcProvider, ctHash: bigint) => {
|
|
24
|
+
// Skip with log if called on a non-testnet chain
|
|
25
|
+
if (await mock_checkIsTestnet(mock_getPlaintext.name, provider)) return;
|
|
26
|
+
|
|
27
|
+
// Connect to MockTaskManager
|
|
28
|
+
const taskManager = new ethers.Contract(
|
|
29
|
+
TASK_MANAGER_ADDRESS,
|
|
30
|
+
['function mockStorage(uint256) view returns (uint256)'],
|
|
31
|
+
provider
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// Fetch the plaintext
|
|
35
|
+
const plaintext = await taskManager.mockStorage(ctHash);
|
|
36
|
+
|
|
37
|
+
return plaintext;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const mock_getPlaintextExists = async (
|
|
41
|
+
provider: HardhatEthersProvider | ethers.JsonRpcProvider,
|
|
42
|
+
ctHash: bigint
|
|
43
|
+
) => {
|
|
44
|
+
// Skip with log if called on a non-testnet chain
|
|
45
|
+
if (await mock_checkIsTestnet(mock_getPlaintextExists.name, provider)) return;
|
|
46
|
+
|
|
47
|
+
// Connect to MockTaskManager
|
|
48
|
+
const taskManager = new ethers.Contract(
|
|
49
|
+
TASK_MANAGER_ADDRESS,
|
|
50
|
+
['function inMockStorage(uint256) view returns (bool)'],
|
|
51
|
+
provider
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
// Fetch the plaintext exists
|
|
55
|
+
const plaintextExists = await taskManager.inMockStorage(ctHash);
|
|
56
|
+
|
|
57
|
+
return plaintextExists;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const mock_expectPlaintext = async (
|
|
61
|
+
provider: HardhatEthersProvider | ethers.JsonRpcProvider,
|
|
62
|
+
ctHash: bigint,
|
|
63
|
+
expectedValue: bigint
|
|
64
|
+
) => {
|
|
65
|
+
// Skip with log if called on a non-testnet chain
|
|
66
|
+
if (await mock_checkIsTestnet(mock_expectPlaintext.name, provider)) return;
|
|
67
|
+
|
|
68
|
+
// Expect the plaintext to exist
|
|
69
|
+
const plaintextExists = await mock_getPlaintextExists(provider, ctHash);
|
|
70
|
+
expect(plaintextExists).equal(true, 'Plaintext does not exist');
|
|
71
|
+
|
|
72
|
+
// Expect the plaintext to have the expected value
|
|
73
|
+
const plaintext = await mock_getPlaintext(provider, ctHash);
|
|
74
|
+
expect(plaintext).equal(expectedValue, 'Plaintext value is incorrect');
|
|
75
|
+
};
|