@cofhe/hardhat-3-plugin 0.7.1 → 0.8.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 CHANGED
@@ -1,5 +1,26 @@
1
1
  # @cofhe/hardhat-3-plugin
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6f7a4c5: Resolve the Task Manager through the `CoFHEAddressBook` (`@fhenixprotocol/cofhe-contracts@1.0.0`). **Breaking:** `TASK_MANAGER_ADDRESS` is removed from `@cofhe/sdk`. Use `getTaskManagerAddress(publicClient)`, which reads `getTm(TASK_MANAGER_ID)` from the book at `COFHE_ADDRESS_BOOK_ADDRESS` (both exported) and caches the result per chain. If the chain has no book, or the id is unset, it throws `TASK_MANAGER_UNRESOLVED`. `verifyDecryptResult`, the ACL/ACP lookups and `useCofheEnabled` / `useCofheReadDecryptionResults` now resolve the Task Manager this way. `@cofhe/react` adds `useCofheTaskManagerAddress()`.
8
+
9
+ Mocks: a new `MockCoFHEAddressBook` is deployed at FHE.sol's `COFHE_ADDRESS_BOOK`, and `MockTaskManager` moves to `MOCKS_TASK_MANAGER_ADDRESS` (`0x…5000`) and is registered in the book. `MockACL` now stores its Task Manager (`setTaskManager` / `getTaskManagerAddress`) instead of reading a constant, so its `TASK_MANAGER_ADDRESS_()` getter is gone. All three plugins deploy and wire the book. Hardhat 2 exposes `hre.cofhe.mocks.getMockCoFHEAddressBook()`, Hardhat 3 exposes `conn.cofhe.mocks.MockCoFHEAddressBook`, and Foundry exposes `CofheTest.mockAddressBook`. Contracts must be built against `@fhenixprotocol/cofhe-contracts@1.0.0` or later (the hardhat plugin's peer range is now `>=1.0.0`). Each FHE op now makes one extra `getTm` call on the book, as it does on real networks, so expect slightly higher gas numbers.
10
+
11
+ ### Patch Changes
12
+
13
+ - ccb7b68: Realistic gas reporting for mocks. Under Foundry, mock-only work is now excluded from gas metering by default (opt out with `mockTaskManager.setMockGasExcluded(false)`), so expect `forge snapshot` numbers to drop. Under Hardhat, mock transactions emit `MockGasConsumed` events (extra receipt logs), and the plugins add `getAdjustedGasUsed(receipt)` / `getAdjustedGasBreakdown(receipt)` plus an opt-in `cofhe.gasSummary` report.
14
+ - Updated dependencies [17ff23e]
15
+ - Updated dependencies [0fe40c3]
16
+ - Updated dependencies [6f7a4c5]
17
+ - Updated dependencies [552d118]
18
+ - Updated dependencies [22eebcc]
19
+ - Updated dependencies [ccb7b68]
20
+ - Updated dependencies [42fccae]
21
+ - @cofhe/sdk@0.8.0
22
+ - @cofhe/mock-contracts@0.8.0
23
+
3
24
  ## 0.7.1
4
25
 
5
26
  ### Patch Changes
package/README.md CHANGED
@@ -36,18 +36,20 @@ export default defineConfig({
36
36
 
37
37
  // Optional cofhe config (all values shown are their defaults)
38
38
  cofhe: {
39
- gasWarning: true, // warn when mock ops report higher gas than real FHE
40
- logMocks: true, // enable mock contract event logging
39
+ gasWarning: false, // warn when mock ops report higher gas than real FHE
40
+ gasSummary: false, // print a per-method adjusted-gas summary after `hardhat test`
41
+ logMocks: false, // enable mock contract event logging
41
42
  },
42
43
  });
43
44
  ```
44
45
 
45
46
  ### Config options
46
47
 
47
- | Option | Type | Default | Description |
48
- | ------------ | --------- | ------- | ---------------------------------------------------------------------------------------- |
49
- | `gasWarning` | `boolean` | `true` | Print a warning after mock deployment reminding that mock gas costs differ from live FHE |
50
- | `logMocks` | `boolean` | `true` | Enable event-based logging inside mock contracts |
48
+ | Option | Type | Default | Description |
49
+ | ------------ | --------- | ------- | ------------------------------------------------------------------------------------------------- |
50
+ | `gasWarning` | `boolean` | `false` | Print a warning after mock deployment reminding that mock gas costs differ from live FHE |
51
+ | `gasSummary` | `boolean` | `false` | Print a per-method gas summary after `hardhat test`, with mock-only overhead excluded (see below) |
52
+ | `logMocks` | `boolean` | `false` | Enable event-based logging inside mock contracts |
51
53
 
52
54
  ---
53
55
 
@@ -127,6 +129,40 @@ const client = await cofhe.createClientWithBatteries(walletClient);
127
129
 
128
130
  ---
129
131
 
132
+ ### `cofhe.getAdjustedGasUsed(receipt)` / `cofhe.getAdjustedGasBreakdown(receipt)`
133
+
134
+ Mock transactions consume more gas than they would on a real CoFHE network, because the off-chain FHE work is replicated on-chain. The mock task manager measures that overhead and emits a `MockGasConsumed(uint256)` event per block of mock-only work, letting the plugin report corrected numbers:
135
+
136
+ ```typescript
137
+ const hash = await myContract.write.doFheThings();
138
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
139
+
140
+ // Gas usage excluding mock overhead — an estimate of real-network cost.
141
+ const adjusted = cofhe.getAdjustedGasUsed(receipt);
142
+
143
+ // Or the full breakdown:
144
+ const { gasUsed, mockGas, adjustedGasUsed, mockGasEvents } = cofhe.getAdjustedGasBreakdown(receipt);
145
+ ```
146
+
147
+ Both are pure functions of the receipt (no RPC calls). On a real network the receipt carries no mock events, so `adjustedGasUsed` equals `gasUsed` — the same code works everywhere.
148
+
149
+ With `cofhe: { gasSummary: true }` in the config, a per-method table (raw vs adjusted gas) is printed after `hardhat test`:
150
+
151
+ ```
152
+ [COFHE-MOCKS] Gas summary — adjusted ≈ cost excluding mock-only overhead
153
+ ┌──────────────────┬──────────────────────────┬───────┬─────────────────┬────────────────────┬───────────────┐
154
+ │ Contract │ Method │ Calls │ Avg gas (mocks) │ Avg gas (adjusted) │ Mock overhead │
155
+ ├──────────────────┼──────────────────────────┼───────┼─────────────────┼────────────────────┼───────────────┤
156
+ │ MyFHEContract │ doFheThings() │ 9 │ 146,199 │ 109,595 │ 25% │
157
+ └──────────────────┴──────────────────────────┴───────┴─────────────────┴────────────────────┴───────────────┘
158
+ ```
159
+
160
+ Note: `eth_estimateGas` is not adjusted — the mock work really does execute, so transactions still need the raw gas limit. Use a testnet for estimate-sensitive flows.
161
+
162
+ The summary table is collected per test worker at process exit and reconstructed from chain history: transactions rolled back by snapshots won't appear, and it is best-effort after forced exits (`process.exit`, Ctrl+C) — use `getAdjustedGasUsed(receipt)` inside tests for exact per-transaction numbers.
163
+
164
+ ---
165
+
130
166
  ### `cofhe.mocks`
131
167
 
132
168
  #### Contract descriptors
@@ -205,7 +241,8 @@ The plugin deploys these core contracts automatically on every `network.connect(
205
241
 
206
242
  | Contract | Address | Description |
207
243
  | ---------------------- | -------------------------------------------- | ------------------------------------------------------- |
208
- | `MockTaskManager` | `0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9` | Coordinates FHE operations and ACL |
244
+ | `MockCoFHEAddressBook` | `0xC0F4e00E531a2B086492Ae3DCC1515038307196b` | Resolves the TaskManager for FHE.sol (`getTm(1)`) |
245
+ | `MockTaskManager` | `0x0000000000000000000000000000000000005000` | Coordinates FHE operations and ACL |
209
246
  | `MockACL` | dynamic | Access Control List — address resolved from TaskManager |
210
247
  | `MockZkVerifier` | `0x0000000000000000000000000000000000005001` | Verifies ZK proofs for encrypted inputs |
211
248
  | `MockThresholdNetwork` | `0x0000000000000000000000000000000000005002` | Simulates the threshold decryption network |
@@ -0,0 +1,217 @@
1
+ // src/gas.ts
2
+ import chalk from "chalk";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import { parseAbiItem, toEventSelector, toFunctionSelector, toFunctionSignature } from "viem";
6
+ import { MOCKS_TASK_MANAGER_ADDRESS } from "@cofhe/sdk";
7
+ var MOCK_GAS_CONSUMED_EVENT = parseAbiItem("event MockGasConsumed(uint256 gas)");
8
+ var MOCK_GAS_CONSUMED_TOPIC = toEventSelector(MOCK_GAS_CONSUMED_EVENT);
9
+ var mock_getAdjustedGasBreakdown = (receipt) => {
10
+ let mockGas = 0n;
11
+ let mockGasEvents = 0;
12
+ for (const log of receipt.logs ?? []) {
13
+ if (log.address.toLowerCase() === MOCKS_TASK_MANAGER_ADDRESS.toLowerCase() && log.topics[0]?.toLowerCase() === MOCK_GAS_CONSUMED_TOPIC) {
14
+ mockGas += BigInt(log.data);
15
+ mockGasEvents += 1;
16
+ }
17
+ }
18
+ const gasUsed = BigInt(receipt.gasUsed);
19
+ return { gasUsed, mockGas, adjustedGasUsed: mockGas > gasUsed ? 0n : gasUsed - mockGas, mockGasEvents };
20
+ };
21
+ var mock_getAdjustedGasUsed = (receipt) => mock_getAdjustedGasBreakdown(receipt).adjustedGasUsed;
22
+ var SUMMARY_DIR_NAME = "cofhe-gas-summary";
23
+ var registeredConnections = [];
24
+ var summaryDir;
25
+ var exitHookInstalled = false;
26
+ var exitHookRan = false;
27
+ var shortAddress = (address) => `${address.slice(0, 6)}..${address.slice(-4)}`;
28
+ var buildSelectorNameMap = async (artifacts) => {
29
+ const selectorNames = /* @__PURE__ */ new Map();
30
+ for (const fqn of await artifacts.getAllFullyQualifiedNames()) {
31
+ try {
32
+ const artifact = await artifacts.readArtifact(fqn);
33
+ for (const item of artifact.abi) {
34
+ if (item.type !== "function") continue;
35
+ const selector = toFunctionSelector(item);
36
+ if (!selectorNames.has(selector)) selectorNames.set(selector, toFunctionSignature(item));
37
+ }
38
+ } catch {
39
+ }
40
+ }
41
+ return selectorNames;
42
+ };
43
+ var buildAddressNameMap = async (publicClient, artifacts, addresses) => {
44
+ const codeToName = /* @__PURE__ */ new Map();
45
+ for (const fqn of await artifacts.getAllFullyQualifiedNames()) {
46
+ try {
47
+ const artifact = await artifacts.readArtifact(fqn);
48
+ if (artifact.deployedBytecode && artifact.deployedBytecode !== "0x") {
49
+ codeToName.set(artifact.deployedBytecode.toLowerCase(), artifact.contractName);
50
+ }
51
+ } catch {
52
+ }
53
+ }
54
+ const addressNames = /* @__PURE__ */ new Map();
55
+ for (const address of addresses) {
56
+ try {
57
+ const code = await publicClient.getCode({ address }) ?? "0x";
58
+ addressNames.set(address, codeToName.get(code.toLowerCase()) ?? shortAddress(address));
59
+ } catch {
60
+ addressNames.set(address, shortAddress(address));
61
+ }
62
+ }
63
+ return addressNames;
64
+ };
65
+ var collectMockGasRows = async (publicClient, artifacts, fromBlock = 0n) => {
66
+ let logs;
67
+ try {
68
+ logs = await publicClient.getLogs({
69
+ address: MOCKS_TASK_MANAGER_ADDRESS,
70
+ event: MOCK_GAS_CONSUMED_EVENT,
71
+ fromBlock,
72
+ toBlock: "latest"
73
+ });
74
+ } catch {
75
+ return [];
76
+ }
77
+ if (logs.length === 0) return [];
78
+ const mockGasPerTx = /* @__PURE__ */ new Map();
79
+ for (const log of logs) {
80
+ if (log.transactionHash === null) continue;
81
+ mockGasPerTx.set(log.transactionHash, (mockGasPerTx.get(log.transactionHash) ?? 0n) + (log.args.gas ?? 0n));
82
+ }
83
+ const aggregates = /* @__PURE__ */ new Map();
84
+ for (const [txHash, mockGas] of mockGasPerTx) {
85
+ try {
86
+ const receipt = await publicClient.getTransactionReceipt({ hash: txHash });
87
+ const tx = await publicClient.getTransaction({ hash: txHash });
88
+ const target = tx.to ?? receipt.contractAddress;
89
+ if (!target) continue;
90
+ const selector = tx.to ? (tx.input ?? "0x").slice(0, 10) : "(deployment)";
91
+ const key = `${target}:${selector}`;
92
+ const aggregate = aggregates.get(key) ?? { to: target, selector, calls: 0, totalGasUsed: 0n, totalMockGas: 0n };
93
+ aggregate.calls += 1;
94
+ aggregate.totalGasUsed += receipt.gasUsed;
95
+ aggregate.totalMockGas += mockGas;
96
+ aggregates.set(key, aggregate);
97
+ } catch {
98
+ }
99
+ }
100
+ if (aggregates.size === 0) return [];
101
+ const selectorNames = await buildSelectorNameMap(artifacts);
102
+ const addressNames = await buildAddressNameMap(publicClient, artifacts, [
103
+ ...new Set([...aggregates.values()].map((a) => a.to))
104
+ ]);
105
+ return [...aggregates.values()].map((a) => ({
106
+ contract: addressNames.get(a.to) ?? shortAddress(a.to),
107
+ method: selectorNames.get(a.selector) ?? a.selector,
108
+ calls: a.calls,
109
+ totalGasUsed: a.totalGasUsed.toString(),
110
+ totalMockGas: a.totalMockGas.toString()
111
+ }));
112
+ };
113
+ var registerGasSummaryConnection = (publicClient, artifacts, cacheDir, fromBlock) => {
114
+ registeredConnections.push({ publicClient, artifacts, fromBlock });
115
+ summaryDir = path.join(cacheDir, SUMMARY_DIR_NAME);
116
+ if (exitHookInstalled) return;
117
+ exitHookInstalled = true;
118
+ process.on("beforeExit", () => {
119
+ if (exitHookRan) return;
120
+ exitHookRan = true;
121
+ void (async () => {
122
+ const rows = [];
123
+ for (const { publicClient: client, artifacts: arts, fromBlock: fromBlock2 } of registeredConnections) {
124
+ try {
125
+ rows.push(...await collectMockGasRows(client, arts, fromBlock2));
126
+ } catch {
127
+ }
128
+ }
129
+ if (rows.length === 0 || summaryDir === void 0) return;
130
+ try {
131
+ fs.mkdirSync(summaryDir, { recursive: true });
132
+ const file = path.join(summaryDir, `rows-${process.pid}-${Date.now()}.json`);
133
+ fs.writeFileSync(file, JSON.stringify(rows), "utf8");
134
+ } catch {
135
+ }
136
+ })();
137
+ });
138
+ };
139
+ var cleanGasSummaryDir = (cacheDir) => {
140
+ try {
141
+ fs.rmSync(path.join(cacheDir, SUMMARY_DIR_NAME), { recursive: true, force: true });
142
+ } catch {
143
+ }
144
+ };
145
+ var printMockGasSummaryFromDir = (cacheDir) => {
146
+ const dir = path.join(cacheDir, SUMMARY_DIR_NAME);
147
+ let files;
148
+ try {
149
+ files = fs.readdirSync(dir).filter((f) => f.endsWith(".json"));
150
+ } catch {
151
+ return;
152
+ }
153
+ const merged = /* @__PURE__ */ new Map();
154
+ for (const file of files) {
155
+ try {
156
+ const rows2 = JSON.parse(fs.readFileSync(path.join(dir, file), "utf8"));
157
+ for (const r of rows2) {
158
+ const key = `${r.contract}:${r.method}`;
159
+ const row = merged.get(key) ?? { contract: r.contract, method: r.method, calls: 0, gasUsed: 0n, mockGas: 0n };
160
+ row.calls += r.calls;
161
+ row.gasUsed += BigInt(r.totalGasUsed);
162
+ row.mockGas += BigInt(r.totalMockGas);
163
+ merged.set(key, row);
164
+ }
165
+ } catch {
166
+ }
167
+ }
168
+ cleanGasSummaryDir(cacheDir);
169
+ if (merged.size === 0) return;
170
+ const rows = [...merged.values()].map((r) => {
171
+ const avgGasUsed = r.gasUsed / BigInt(r.calls);
172
+ const avgMockGas = r.mockGas / BigInt(r.calls);
173
+ return {
174
+ contract: r.contract,
175
+ method: r.method,
176
+ calls: r.calls,
177
+ avgGasUsed,
178
+ avgAdjusted: avgMockGas > avgGasUsed ? 0n : avgGasUsed - avgMockGas,
179
+ overheadPct: avgGasUsed === 0n ? 0 : Math.min(100, Number(avgMockGas * 100n / avgGasUsed))
180
+ };
181
+ }).sort((a, b) => a.contract.localeCompare(b.contract) || a.method.localeCompare(b.method));
182
+ const headers = ["Contract", "Method", "Calls", "Avg gas (mocks)", "Avg gas (adjusted)", "Mock overhead"];
183
+ const cells = rows.map((r) => [
184
+ r.contract,
185
+ r.method,
186
+ String(r.calls),
187
+ r.avgGasUsed.toLocaleString(),
188
+ r.avgAdjusted.toLocaleString(),
189
+ `${r.overheadPct}%`
190
+ ]);
191
+ const widths = headers.map((h, i) => Math.max(h.length, ...cells.map((row) => row[i].length)));
192
+ const line = (row) => `\u2502 ${row.map((cell, i) => cell.padEnd(widths[i])).join(" \u2502 ")} \u2502`;
193
+ const divider = (l, m, r) => `${l}${widths.map((w) => "\u2500".repeat(w + 2)).join(m)}${r}`;
194
+ console.log("");
195
+ console.log(chalk.bold("[COFHE-MOCKS] Gas summary") + chalk.dim(" \u2014 adjusted \u2248 cost excluding mock-only overhead"));
196
+ console.log(divider("\u250C", "\u252C", "\u2510"));
197
+ console.log(line(headers));
198
+ console.log(divider("\u251C", "\u253C", "\u2524"));
199
+ for (const row of cells) console.log(line(row));
200
+ console.log(divider("\u2514", "\u2534", "\u2518"));
201
+ console.log(
202
+ chalk.dim(
203
+ "Raw numbers include on-chain replication of off-chain CoFHE work; adjusted numbers estimate real-network cost. estimateGas remains unadjusted."
204
+ )
205
+ );
206
+ };
207
+
208
+ export {
209
+ MOCK_GAS_CONSUMED_EVENT,
210
+ MOCK_GAS_CONSUMED_TOPIC,
211
+ mock_getAdjustedGasBreakdown,
212
+ mock_getAdjustedGasUsed,
213
+ collectMockGasRows,
214
+ registerGasSummaryConnection,
215
+ cleanGasSummaryDir,
216
+ printMockGasSummaryFromDir
217
+ };
@@ -2,9 +2,16 @@
2
2
  import { createTestClient, custom } from "viem";
3
3
  import chalk from "chalk";
4
4
  import { privateKeyToAccount } from "viem/accounts";
5
- import { MockACLArtifact, MockTaskManagerArtifact, MockThresholdNetworkArtifact } from "@cofhe/mock-contracts";
6
5
  import {
7
- TASK_MANAGER_ADDRESS,
6
+ MockACLArtifact,
7
+ MockCoFHEAddressBookArtifact,
8
+ MockTaskManagerArtifact,
9
+ MockThresholdNetworkArtifact
10
+ } from "@cofhe/mock-contracts";
11
+ import {
12
+ COFHE_ADDRESS_BOOK_ADDRESS,
13
+ TASK_MANAGER_ID,
14
+ MOCKS_TASK_MANAGER_ADDRESS,
8
15
  MOCKS_ZK_VERIFIER_ADDRESS,
9
16
  MOCKS_ZK_VERIFIER_SIGNER_ADDRESS,
10
17
  MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY,
@@ -28,11 +35,13 @@ async function deployMocks(ctx, options = {}) {
28
35
  return {};
29
36
  }
30
37
  log("vv", chalk.bold("cofhe-hardhat-3-plugin :: deploy mocks"), 0);
31
- await deployFixed(ctx.publicClient, "MockTaskManager", TASK_MANAGER_ADDRESS, ctx.artifacts);
32
- logDeployment("MockTaskManager", TASK_MANAGER_ADDRESS);
38
+ await deployFixed(ctx.publicClient, "MockCoFHEAddressBook", COFHE_ADDRESS_BOOK_ADDRESS, ctx.artifacts);
39
+ logDeployment("MockCoFHEAddressBook", COFHE_ADDRESS_BOOK_ADDRESS);
40
+ await deployFixed(ctx.publicClient, "MockTaskManager", MOCKS_TASK_MANAGER_ADDRESS, ctx.artifacts);
41
+ logDeployment("MockTaskManager", MOCKS_TASK_MANAGER_ADDRESS);
33
42
  const [account] = await ctx.walletClient.getAddresses();
34
43
  await ctx.walletClient.writeContract({
35
- address: TASK_MANAGER_ADDRESS,
44
+ address: MOCKS_TASK_MANAGER_ADDRESS,
36
45
  abi: MockTaskManagerArtifact.abi,
37
46
  functionName: "initialize",
38
47
  args: [account],
@@ -40,7 +49,16 @@ async function deployMocks(ctx, options = {}) {
40
49
  chain: null
41
50
  });
42
51
  await ctx.walletClient.writeContract({
43
- address: TASK_MANAGER_ADDRESS,
52
+ address: COFHE_ADDRESS_BOOK_ADDRESS,
53
+ abi: MockCoFHEAddressBookArtifact.abi,
54
+ functionName: "setTm",
55
+ args: [TASK_MANAGER_ID, MOCKS_TASK_MANAGER_ADDRESS],
56
+ account,
57
+ chain: null
58
+ });
59
+ log("vv", "TaskManager registered in CoFHEAddressBook", 2);
60
+ await ctx.walletClient.writeContract({
61
+ address: MOCKS_TASK_MANAGER_ADDRESS,
44
62
  abi: MockTaskManagerArtifact.abi,
45
63
  functionName: "setSecurityZones",
46
64
  args: [0, 1],
@@ -50,7 +68,7 @@ async function deployMocks(ctx, options = {}) {
50
68
  const aclAddress = await deployVariable(ctx, "MockACL", []);
51
69
  logDeployment("MockACL", aclAddress);
52
70
  await ctx.walletClient.writeContract({
53
- address: TASK_MANAGER_ADDRESS,
71
+ address: MOCKS_TASK_MANAGER_ADDRESS,
54
72
  abi: MockTaskManagerArtifact.abi,
55
73
  functionName: "setACLContract",
56
74
  args: [aclAddress],
@@ -58,6 +76,15 @@ async function deployMocks(ctx, options = {}) {
58
76
  chain: null
59
77
  });
60
78
  log("vv", "ACL address set in TaskManager", 2);
79
+ await ctx.walletClient.writeContract({
80
+ address: aclAddress,
81
+ abi: MockACLArtifact.abi,
82
+ functionName: "setTaskManager",
83
+ args: [MOCKS_TASK_MANAGER_ADDRESS],
84
+ account,
85
+ chain: null
86
+ });
87
+ log("vv", "TaskManager address set in ACL", 2);
61
88
  const acpRevokerAddress = await deployVariable(ctx, "ACPTimestampRevoker", []);
62
89
  logDeployment("ACPTimestampRevoker", acpRevokerAddress);
63
90
  await ctx.walletClient.writeContract({
@@ -82,7 +109,7 @@ async function deployMocks(ctx, options = {}) {
82
109
  log("vv", "Share registry set in ACL", 2);
83
110
  const verifierSigner = privateKeyToAccount(MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY);
84
111
  await ctx.walletClient.writeContract({
85
- address: TASK_MANAGER_ADDRESS,
112
+ address: MOCKS_TASK_MANAGER_ADDRESS,
86
113
  abi: MockTaskManagerArtifact.abi,
87
114
  functionName: "setVerifierSigner",
88
115
  args: [verifierSigner.address],
@@ -92,7 +119,7 @@ async function deployMocks(ctx, options = {}) {
92
119
  log("vv", "Verifier signer set", 2);
93
120
  const decryptSigner = privateKeyToAccount(MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY);
94
121
  await ctx.walletClient.writeContract({
95
- address: TASK_MANAGER_ADDRESS,
122
+ address: MOCKS_TASK_MANAGER_ADDRESS,
96
123
  abi: MockTaskManagerArtifact.abi,
97
124
  functionName: "setDecryptResultSigner",
98
125
  args: [decryptSigner.address],
@@ -120,7 +147,7 @@ async function deployMocks(ctx, options = {}) {
120
147
  address: MockThresholdNetworkArtifact.fixedAddress,
121
148
  abi: MockThresholdNetworkArtifact.abi,
122
149
  functionName: "initialize",
123
- args: [TASK_MANAGER_ADDRESS, aclAddress],
150
+ args: [MOCKS_TASK_MANAGER_ADDRESS, aclAddress],
124
151
  account,
125
152
  chain: null
126
153
  });
@@ -128,13 +155,14 @@ async function deployMocks(ctx, options = {}) {
128
155
  if (gasWarning) {
129
156
  logEmpty("v");
130
157
  logWarning(
131
- "When using mocks, FHE operations report a higher gas price due to on-chain mocking logic. Deploy your contracts on a testnet to check true gas costs.\n(Disable this warning by setting 'cofhe.gasWarning: false' in your Hardhat config)",
158
+ "When using mocks, FHE operations consume extra gas replicating off-chain CoFHE work on-chain. Use conn.cofhe.getAdjustedGasUsed(receipt) or set 'cofhe.gasSummary: true' to see gas numbers with that overhead excluded.\n(Disable this warning by setting 'cofhe.gasWarning: false' in your Hardhat config)",
132
159
  0
133
160
  );
134
161
  }
135
162
  logEmpty("v");
136
163
  return {
137
- MockTaskManager: TASK_MANAGER_ADDRESS,
164
+ MockCoFHEAddressBook: COFHE_ADDRESS_BOOK_ADDRESS,
165
+ MockTaskManager: MOCKS_TASK_MANAGER_ADDRESS,
138
166
  MockACL: aclAddress,
139
167
  ACPTimestampRevoker: acpRevokerAddress,
140
168
  ACPShareRegistry: acpShareRegistryAddress,
@@ -186,7 +214,7 @@ var logDeployment = (contractName, address) => {
186
214
  };
187
215
 
188
216
  // src/utils.ts
189
- import { TASK_MANAGER_ADDRESS as TASK_MANAGER_ADDRESS2, MOCKS_ZK_VERIFIER_ADDRESS as MOCKS_ZK_VERIFIER_ADDRESS2 } from "@cofhe/sdk";
217
+ import { MOCKS_TASK_MANAGER_ADDRESS as MOCKS_TASK_MANAGER_ADDRESS2, MOCKS_ZK_VERIFIER_ADDRESS as MOCKS_ZK_VERIFIER_ADDRESS2 } from "@cofhe/sdk";
190
218
  import path from "path";
191
219
  import fs from "fs";
192
220
  import { createRequire } from "module";
@@ -216,7 +244,7 @@ async function mock_getPlaintext(publicClient, ctHash) {
216
244
  return void 0;
217
245
  }
218
246
  return publicClient.readContract({
219
- address: TASK_MANAGER_ADDRESS2,
247
+ address: MOCKS_TASK_MANAGER_ADDRESS2,
220
248
  abi: [
221
249
  {
222
250
  name: "mockStorage",
@@ -236,7 +264,7 @@ async function mock_expectPlaintext(publicClient, ctHash, expectedValue) {
236
264
  return;
237
265
  }
238
266
  const exists = await publicClient.readContract({
239
- address: TASK_MANAGER_ADDRESS2,
267
+ address: MOCKS_TASK_MANAGER_ADDRESS2,
240
268
  abi: [
241
269
  {
242
270
  name: "inMockStorage",
@@ -1,10 +1,10 @@
1
1
  // src/logging.ts
2
2
  import chalk from "chalk";
3
3
  import { MockTaskManagerArtifact } from "@cofhe/mock-contracts";
4
- import { TASK_MANAGER_ADDRESS } from "@cofhe/sdk";
4
+ import { MOCKS_TASK_MANAGER_ADDRESS } from "@cofhe/sdk";
5
5
  async function getLoggingEnabled(publicClient) {
6
6
  return publicClient.readContract({
7
- address: TASK_MANAGER_ADDRESS,
7
+ address: MOCKS_TASK_MANAGER_ADDRESS,
8
8
  abi: MockTaskManagerArtifact.abi,
9
9
  functionName: "logOps",
10
10
  args: []
@@ -13,7 +13,7 @@ async function getLoggingEnabled(publicClient) {
13
13
  async function setLoggingEnabled(publicClient, walletClient, enabled) {
14
14
  const [account] = await walletClient.getAddresses();
15
15
  const hash = await walletClient.writeContract({
16
- address: TASK_MANAGER_ADDRESS,
16
+ address: MOCKS_TASK_MANAGER_ADDRESS,
17
17
  abi: MockTaskManagerArtifact.abi,
18
18
  functionName: "setLogOps",
19
19
  args: [enabled],
@@ -46,6 +46,7 @@ function resolvePluginConfig(userConfig, resolvedConfig) {
46
46
  resolvedConfig.cofhe = {
47
47
  logMocks: userConfig.cofhe?.logMocks ?? false,
48
48
  gasWarning: userConfig.cofhe?.gasWarning ?? false,
49
+ gasSummary: userConfig.cofhe?.gasSummary ?? false,
49
50
  mocksDeployVerbosity: userConfig.cofhe?.mocksDeployVerbosity ?? "v"
50
51
  };
51
52
  }
@@ -3,17 +3,23 @@ import {
3
3
  getMockContractsNpmPaths,
4
4
  mock_expectPlaintext,
5
5
  mock_getPlaintext
6
- } from "./chunk-E7DR6EGV.js";
6
+ } from "./chunk-FDCRLC5K.js";
7
7
  import {
8
8
  mock_setLoggingEnabled,
9
9
  mock_withLogs
10
- } from "./chunk-IVRNGFNF.js";
10
+ } from "./chunk-NYXXHYHW.js";
11
+ import {
12
+ mock_getAdjustedGasBreakdown,
13
+ mock_getAdjustedGasUsed,
14
+ registerGasSummaryConnection
15
+ } from "./chunk-6G2MCXNM.js";
11
16
 
12
17
  // src/hooks/hre.ts
13
18
  import { FileBuildResultType } from "hardhat/types/solidity";
14
19
  import { createPublicClient, createWalletClient, custom } from "viem";
15
20
  import { privateKeyToAccount } from "viem/accounts";
16
21
  import {
22
+ MockCoFHEAddressBookArtifact,
17
23
  MockTaskManagerArtifact,
18
24
  MockACLArtifact,
19
25
  MockZkVerifierArtifact,
@@ -44,6 +50,8 @@ function createCofheConnection(publicClient, walletClient, transport, artifacts,
44
50
  createClient(config) {
45
51
  return createCofheClient(config);
46
52
  },
53
+ getAdjustedGasUsed: mock_getAdjustedGasUsed,
54
+ getAdjustedGasBreakdown: mock_getAdjustedGasBreakdown,
47
55
  async createClientWithBatteries(signerWalletClient) {
48
56
  let signerClient;
49
57
  let address;
@@ -85,6 +93,10 @@ function createCofheConnection(publicClient, walletClient, transport, artifacts,
85
93
  async expectPlaintext(ctHash, expectedValue) {
86
94
  await mock_expectPlaintext(publicClient, ctHash, expectedValue);
87
95
  },
96
+ MockCoFHEAddressBook: {
97
+ address: deployedMockContracts.MockCoFHEAddressBook,
98
+ abi: MockCoFHEAddressBookArtifact.abi
99
+ },
88
100
  MockTaskManager: { address: deployedMockContracts.MockTaskManager, abi: MockTaskManagerArtifact.abi },
89
101
  MockACL: { address: deployedMockContracts.MockACL, abi: MockACLArtifact.abi },
90
102
  MockZkVerifier: { address: deployedMockContracts.MockZkVerifier, abi: MockZkVerifierArtifact.abi },
@@ -136,6 +148,10 @@ var hreHooks = {
136
148
  mocksDeployVerbosity: hre.config.cofhe.mocksDeployVerbosity
137
149
  }
138
150
  );
151
+ if (hre.config.cofhe.gasSummary && deployedMockContracts.MockTaskManager !== void 0) {
152
+ const fromBlock = await publicClient.getBlockNumber();
153
+ registerGasSummaryConnection(publicClient, hre.artifacts, hre.config.paths.cache, fromBlock);
154
+ }
139
155
  conn.cofhe = createCofheConnection(
140
156
  publicClient,
141
157
  walletClient,