create-fhevm-example 1.4.6 → 1.4.7

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.
@@ -127,12 +127,83 @@ async function checkConfigIntegrity() {
127
127
  };
128
128
  }
129
129
  }
130
+ async function checkSubmoduleStatus() {
131
+ const SUBMODULE_PATH = "fhevm-hardhat-template";
132
+ const SUBMODULE_URL = "https://github.com/zama-ai/fhevm-hardhat-template";
133
+ try {
134
+ // 1. Get local commit hash
135
+ const localStatus = (0, child_process_1.execSync)(`git submodule status ${SUBMODULE_PATH}`, {
136
+ stdio: "pipe",
137
+ encoding: "utf-8",
138
+ }).trim();
139
+ // git submodule status output: " 3e01a81bfca5f0857cba55a099e98863efc79bcb fhevm-hardhat-template (v0.2.0-2-g3e01a81)"
140
+ const localHash = localStatus.split(" ").filter((s) => s.length > 0)[0];
141
+ if (!localHash || localHash.length < 40) {
142
+ return {
143
+ name: "Submodule status",
144
+ status: "fail",
145
+ message: "Not initialized",
146
+ details: [
147
+ `Run ${picocolors_1.default.bold("git submodule update --init")} to initialize.`,
148
+ ],
149
+ };
150
+ }
151
+ // 2. Get remote commit hash
152
+ // We use a timeout to not hang doctor script if internet is slow/down
153
+ const remoteInfo = (0, child_process_1.execSync)(`git ls-remote ${SUBMODULE_URL} HEAD`, {
154
+ stdio: "pipe",
155
+ encoding: "utf-8",
156
+ timeout: 5000, // 5 seconds timeout
157
+ }).trim();
158
+ const remoteHash = remoteInfo.split("\t")[0];
159
+ if (!remoteHash || remoteHash.length < 40) {
160
+ return {
161
+ name: "Submodule status",
162
+ status: "warn",
163
+ message: "Connection error",
164
+ details: ["Could not fetch remote status from GitHub."],
165
+ };
166
+ }
167
+ if (localHash === remoteHash) {
168
+ return {
169
+ name: "Submodule status",
170
+ status: "success",
171
+ message: "Up to date",
172
+ };
173
+ }
174
+ else {
175
+ return {
176
+ name: "Submodule status",
177
+ status: "warn",
178
+ message: "Update available",
179
+ details: [
180
+ `Local: ${picocolors_1.default.dim(localHash.slice(0, 7))}`,
181
+ `Remote: ${picocolors_1.default.dim(remoteHash.slice(0, 7))}`,
182
+ `Run ${picocolors_1.default.bold("git submodule update --remote --merge")} to update.`,
183
+ ],
184
+ };
185
+ }
186
+ }
187
+ catch (e) {
188
+ return {
189
+ name: "Submodule status",
190
+ status: "warn",
191
+ message: "Check skipped",
192
+ details: ["Git error or no internet connection."],
193
+ };
194
+ }
195
+ }
130
196
  // =============================================================================
131
197
  // Main
132
198
  // =============================================================================
133
199
  async function main() {
134
200
  p.intro(picocolors_1.default.cyan("🩺 FHEVM Doctor"));
135
- const checks = [checkNodeVersion(), checkGit(), checkConfigIntegrity()];
201
+ const checks = [
202
+ checkNodeVersion(),
203
+ checkGit(),
204
+ checkConfigIntegrity(),
205
+ checkSubmoduleStatus(),
206
+ ];
136
207
  const results = await Promise.all(checks);
137
208
  let hasFailure = false;
138
209
  for (const result of results) {
@@ -191,7 +191,18 @@ function generateCategoriesConfig(contracts) {
191
191
  }
192
192
  categoryMap[contract.category].push(contract);
193
193
  }
194
- const categoryEntries = Object.entries(categoryMap).map(([category, items]) => {
194
+ const sortedEntries = Object.entries(categoryMap).sort(([catA], [catB]) => {
195
+ const idxA = utils_1.CATEGORY_ORDER.indexOf(catA);
196
+ const idxB = utils_1.CATEGORY_ORDER.indexOf(catB);
197
+ if (idxA !== -1 && idxB !== -1)
198
+ return idxA - idxB;
199
+ if (idxA !== -1)
200
+ return -1;
201
+ if (idxB !== -1)
202
+ return 1;
203
+ return catA.localeCompare(catB);
204
+ });
205
+ const categoryEntries = sortedEntries.map(([category, items]) => {
195
206
  const categoryKey = category
196
207
  .toLowerCase()
197
208
  .replace(/\s+/g, "")
@@ -203,7 +214,7 @@ function generateCategoriesConfig(contracts) {
203
214
  }`)
204
215
  .join(",\n");
205
216
  return ` ${categoryKey}: {
206
- name: "${category} Examples",
217
+ name: "${category}",
207
218
  contracts: [
208
219
  ${contracts}
209
220
  ],
@@ -144,30 +144,6 @@ exports.EXAMPLES = {
144
144
  docsOutput: "docs/basic/fhe-operations/fhe-if-then-else.md",
145
145
  title: "FHE If Then Else"
146
146
  },
147
- "fhe-access-control": {
148
- contract: "contracts/concepts/FHEAccessControl.sol",
149
- test: "test/concepts/FHEAccessControl.ts",
150
- description: "Master class for FHE permission patterns and access control. Explains the three permission types: allow() for permanent access, allowThis() for contract operations, and allowTransient() for temporary cross-contract calls. Includes correct and incorrect usage examples to prevent common decryption failures.",
151
- category: "Concepts",
152
- docsOutput: "docs/concepts/fhe-access-control.md",
153
- title: "FHE Access Control"
154
- },
155
- "fhe-handles": {
156
- contract: "contracts/concepts/FHEHandles.sol",
157
- test: "test/concepts/FHEHandles.ts",
158
- description: "Deep dive into FHE handles: what they are and how they work. Explains that handles are uint256 pointers to encrypted data, demonstrates three creation methods (fromExternal, asEuint, operations), and emphasizes immutability - every operation creates a NEW handle. Includes gas cost comparisons for different operations.",
159
- category: "Concepts",
160
- docsOutput: "docs/concepts/fhe-handles.md",
161
- title: "FHE Handles"
162
- },
163
- "fhe-input-proof": {
164
- contract: "contracts/concepts/FHEInputProof.sol",
165
- test: "test/concepts/FHEInputProof.ts",
166
- description: "Input proof validation and batching strategies in FHEVM. Explains why proofs are essential (prevent garbage data, wrong types, and replay attacks) and demonstrates the gas-efficient batching pattern where one proof validates multiple encrypted inputs, saving ~50k gas per additional value.",
167
- category: "Concepts",
168
- docsOutput: "docs/concepts/fhe-input-proof.md",
169
- title: "FHE Input Proof"
170
- },
171
147
  "control-flow": {
172
148
  contract: "contracts/concepts/antipatterns/ControlFlow.sol",
173
149
  test: "test/concepts/antipatterns/ControlFlow.ts",
@@ -192,6 +168,30 @@ exports.EXAMPLES = {
192
168
  docsOutput: "docs/concepts/antipatterns/permissions.md",
193
169
  title: "Permissions"
194
170
  },
171
+ "fhe-access-control": {
172
+ contract: "contracts/concepts/core/FHEAccessControl.sol",
173
+ test: "test/concepts/core/FHEAccessControl.ts",
174
+ description: "Master class for FHE permission patterns and access control. Explains the three permission types: allow() for permanent access, allowThis() for contract operations, and allowTransient() for temporary cross-contract calls. Includes correct and incorrect usage examples to prevent common decryption failures.",
175
+ category: "Concepts - Core",
176
+ docsOutput: "docs/concepts/core/fhe-access-control.md",
177
+ title: "FHE Access Control"
178
+ },
179
+ "fhe-handles": {
180
+ contract: "contracts/concepts/core/FHEHandles.sol",
181
+ test: "test/concepts/core/FHEHandles.ts",
182
+ description: "Deep dive into FHE handles: what they are and how they work. Explains that handles are uint256 pointers to encrypted data, demonstrates three creation methods (fromExternal, asEuint, operations), and emphasizes immutability - every operation creates a NEW handle. Includes gas cost comparisons for different operations.",
183
+ category: "Concepts - Core",
184
+ docsOutput: "docs/concepts/core/fhe-handles.md",
185
+ title: "FHE Handles"
186
+ },
187
+ "fhe-input-proof": {
188
+ contract: "contracts/concepts/core/FHEInputProof.sol",
189
+ test: "test/concepts/core/FHEInputProof.ts",
190
+ description: "Input proof validation and batching strategies in FHEVM. Explains why proofs are essential (prevent garbage data, wrong types, and replay attacks) and demonstrates the gas-efficient batching pattern where one proof validates multiple encrypted inputs, saving ~50k gas per additional value.",
191
+ category: "Concepts - Core",
192
+ docsOutput: "docs/concepts/core/fhe-input-proof.md",
193
+ title: "FHE Input Proof"
194
+ },
195
195
  "encrypted-lottery": {
196
196
  contract: "contracts/gaming/EncryptedLottery.sol",
197
197
  test: "test/gaming/EncryptedLottery.ts",
@@ -293,33 +293,25 @@ exports.EXAMPLES = {
293
293
  // Category Configurations
294
294
  // =============================================================================
295
295
  exports.CATEGORIES = {
296
- advanced: {
297
- name: "Advanced Examples",
296
+ basicencryption: {
297
+ name: "Basic - Encryption",
298
298
  contracts: [
299
299
  {
300
- sol: "contracts/advanced/BlindAuction.sol",
301
- test: "test/advanced/BlindAuction.ts",
302
- },
303
- {
304
- sol: "contracts/advanced/EncryptedEscrow.sol",
305
- test: "test/advanced/EncryptedEscrow.ts",
306
- },
307
- {
308
- sol: "contracts/advanced/HiddenVoting.sol",
309
- test: "test/advanced/HiddenVoting.ts",
300
+ sol: "contracts/basic/encryption/EncryptMultipleValues.sol",
301
+ test: "test/basic/encryption/EncryptMultipleValues.ts",
310
302
  },
311
303
  {
312
- sol: "contracts/advanced/PrivateKYC.sol",
313
- test: "test/advanced/PrivateKYC.ts",
304
+ sol: "contracts/basic/encryption/EncryptSingleValue.sol",
305
+ test: "test/basic/encryption/EncryptSingleValue.ts",
314
306
  },
315
307
  {
316
- sol: "contracts/advanced/PrivatePayroll.sol",
317
- test: "test/advanced/PrivatePayroll.ts",
308
+ sol: "contracts/basic/encryption/FHECounter.sol",
309
+ test: "test/basic/encryption/FHECounter.ts",
318
310
  }
319
311
  ],
320
312
  },
321
313
  basicdecryption: {
322
- name: "Basic - Decryption Examples",
314
+ name: "Basic - Decryption",
323
315
  contracts: [
324
316
  {
325
317
  sol: "contracts/basic/decryption/PublicDecryptMultipleValues.sol",
@@ -339,25 +331,8 @@ exports.CATEGORIES = {
339
331
  }
340
332
  ],
341
333
  },
342
- basicencryption: {
343
- name: "Basic - Encryption Examples",
344
- contracts: [
345
- {
346
- sol: "contracts/basic/encryption/EncryptMultipleValues.sol",
347
- test: "test/basic/encryption/EncryptMultipleValues.ts",
348
- },
349
- {
350
- sol: "contracts/basic/encryption/EncryptSingleValue.sol",
351
- test: "test/basic/encryption/EncryptSingleValue.ts",
352
- },
353
- {
354
- sol: "contracts/basic/encryption/FHECounter.sol",
355
- test: "test/basic/encryption/FHECounter.ts",
356
- }
357
- ],
358
- },
359
334
  basicfheoperations: {
360
- name: "Basic - FHE Operations Examples",
335
+ name: "Basic - FHE Operations",
361
336
  contracts: [
362
337
  {
363
338
  sol: "contracts/basic/fhe-operations/FHEAdd.sol",
@@ -377,25 +352,25 @@ exports.CATEGORIES = {
377
352
  }
378
353
  ],
379
354
  },
380
- concepts: {
381
- name: "Concepts Examples",
355
+ conceptscore: {
356
+ name: "Concepts - Core",
382
357
  contracts: [
383
358
  {
384
- sol: "contracts/concepts/FHEAccessControl.sol",
385
- test: "test/concepts/FHEAccessControl.ts",
359
+ sol: "contracts/concepts/core/FHEAccessControl.sol",
360
+ test: "test/concepts/core/FHEAccessControl.ts",
386
361
  },
387
362
  {
388
- sol: "contracts/concepts/FHEHandles.sol",
389
- test: "test/concepts/FHEHandles.ts",
363
+ sol: "contracts/concepts/core/FHEHandles.sol",
364
+ test: "test/concepts/core/FHEHandles.ts",
390
365
  },
391
366
  {
392
- sol: "contracts/concepts/FHEInputProof.sol",
393
- test: "test/concepts/FHEInputProof.ts",
367
+ sol: "contracts/concepts/core/FHEInputProof.sol",
368
+ test: "test/concepts/core/FHEInputProof.ts",
394
369
  }
395
370
  ],
396
371
  },
397
372
  conceptsantipatterns: {
398
- name: "Concepts - Antipatterns Examples",
373
+ name: "Concepts - Antipatterns",
399
374
  contracts: [
400
375
  {
401
376
  sol: "contracts/concepts/antipatterns/ControlFlow.sol",
@@ -412,7 +387,7 @@ exports.CATEGORIES = {
412
387
  ],
413
388
  },
414
389
  gaming: {
415
- name: "Gaming Examples",
390
+ name: "Gaming",
416
391
  contracts: [
417
392
  {
418
393
  sol: "contracts/gaming/EncryptedLottery.sol",
@@ -428,8 +403,33 @@ exports.CATEGORIES = {
428
403
  }
429
404
  ],
430
405
  },
406
+ advanced: {
407
+ name: "Advanced",
408
+ contracts: [
409
+ {
410
+ sol: "contracts/advanced/BlindAuction.sol",
411
+ test: "test/advanced/BlindAuction.ts",
412
+ },
413
+ {
414
+ sol: "contracts/advanced/EncryptedEscrow.sol",
415
+ test: "test/advanced/EncryptedEscrow.ts",
416
+ },
417
+ {
418
+ sol: "contracts/advanced/HiddenVoting.sol",
419
+ test: "test/advanced/HiddenVoting.ts",
420
+ },
421
+ {
422
+ sol: "contracts/advanced/PrivateKYC.sol",
423
+ test: "test/advanced/PrivateKYC.ts",
424
+ },
425
+ {
426
+ sol: "contracts/advanced/PrivatePayroll.sol",
427
+ test: "test/advanced/PrivatePayroll.ts",
428
+ }
429
+ ],
430
+ },
431
431
  openzeppelin: {
432
- name: "Openzeppelin Examples",
432
+ name: "Openzeppelin",
433
433
  contracts: [
434
434
  {
435
435
  sol: "contracts/openzeppelin/ERC7984.sol",
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../scripts/shared/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEhD,eAAO,MAAM,aAAa,iBAAO,CAAC;AAElC,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,2BAA2B,CAAC;AAE1D,gDAAgD;AAChD,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,mDAAmD;AACnD,eAAO,MAAM,YAAY,UAQxB,CAAC;AAEF,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,2QAyB7B,CAAC;AAEF,4CAA4C;AAC5C,eAAO,MAAM,kBAAkB;;;;;;;;;CAS9B,CAAC;AAEF,eAAO,MAAM,cAAc,UAQ1B,CAAC;AAEF,eAAO,MAAM,kBAAkB,yPAS9B,CAAC;AAEF,eAAO,MAAM,cAAc;;;4BAGD,MAAM;6BACL,MAAM;uBACZ,MAAM;;;;CAI1B,CAAC;AAMF,eAAO,MAAM,GAAG;mBACC,MAAM;iBACR,MAAM;gBACP,MAAM;eACP,MAAM;mBACF,MAAM;CACtB,CAAC;AAEF;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,SAAI,GAAG,KAAK,CAI/D;AAMD,sDAAsD;AACtD,wBAAgB,UAAU,IAAI,MAAM,CAUnC;AAED,uCAAuC;AACvC,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,oEAAoE;AACpE,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,WAAW,GAAE,MAAM,EAAiB,GACnC,IAAI,CAoBN;AAMD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM/C;AAED,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAKhE;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED,wBAAgB,eAAe,CAAC,qBAAqB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqB5E;AAMD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIlD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAInD;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAIhE"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../scripts/shared/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEhD,eAAO,MAAM,aAAa,iBAAO,CAAC;AAElC,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,2BAA2B,CAAC;AAE1D,gDAAgD;AAChD,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,mDAAmD;AACnD,eAAO,MAAM,YAAY,UAQxB,CAAC;AAEF,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,2QAyB7B,CAAC;AAEF,4CAA4C;AAC5C,eAAO,MAAM,kBAAkB;;;;;;;;;CAS9B,CAAC;AAEF,eAAO,MAAM,cAAc,UAS1B,CAAC;AAEF,eAAO,MAAM,kBAAkB,yPAS9B,CAAC;AAEF,eAAO,MAAM,cAAc;;;4BAGD,MAAM;6BACL,MAAM;uBACZ,MAAM;;;;CAI1B,CAAC;AAMF,eAAO,MAAM,GAAG;mBACC,MAAM;iBACR,MAAM;gBACP,MAAM;eACP,MAAM;mBACF,MAAM;CACtB,CAAC;AAEF;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,SAAI,GAAG,KAAK,CAI/D;AAMD,sDAAsD;AACtD,wBAAgB,UAAU,IAAI,MAAM,CAUnC;AAED,uCAAuC;AACvC,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,oEAAoE;AACpE,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,WAAW,GAAE,MAAM,EAAiB,GACnC,IAAI,CAoBN;AAMD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM/C;AAED,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAKhE;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED,wBAAgB,eAAe,CAAC,qBAAqB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqB5E;AAMD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIlD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAInD;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAIhE"}
@@ -116,10 +116,11 @@ exports.CATEGORY_ORDER = [
116
116
  "Basic - Encryption",
117
117
  "Basic - Decryption",
118
118
  "Basic - FHE Operations",
119
- "Concepts",
119
+ "Concepts - Core",
120
+ "Concepts - Antipatterns",
120
121
  "Gaming",
121
- "Openzeppelin",
122
122
  "Advanced",
123
+ "Openzeppelin",
123
124
  ];
124
125
  exports.TEST_TYPES_CONTENT = `import type { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
125
126
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-fhevm-example",
3
- "version": "1.4.6",
3
+ "version": "1.4.7",
4
4
  "description": "Create FHEVM example projects with a single command - A comprehensive toolkit for building privacy-preserving smart contracts",
5
5
  "bin": {
6
6
  "create-fhevm-example": "./dist/scripts/index.js"
@@ -1,112 +0,0 @@
1
- import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
2
- import { expect } from "chai";
3
- import { ethers } from "hardhat";
4
- import * as hre from "hardhat";
5
-
6
- import { FHEAntiPatterns, FHEAntiPatterns__factory } from "../types";
7
- import type { Signers } from "./types";
8
-
9
- async function deployFixture() {
10
- const factory = (await ethers.getContractFactory(
11
- "FHEAntiPatterns"
12
- )) as FHEAntiPatterns__factory;
13
- const contract = (await factory.deploy()) as FHEAntiPatterns;
14
- const contractAddress = await contract.getAddress();
15
- return { contract, contractAddress };
16
- }
17
-
18
- /**
19
- * @notice Tests for FHE anti-patterns
20
- * Demonstrates correct patterns for common FHE mistakes
21
- */
22
- describe("FHEAntiPatterns", function () {
23
- let contract: FHEAntiPatterns;
24
- let contractAddress: string;
25
- let signers: Signers;
26
-
27
- before(async function () {
28
- if (!hre.fhevm.isMock) {
29
- console.warn(`This hardhat test suite cannot run on Sepolia Testnet`);
30
- this.skip();
31
- }
32
- const ethSigners: HardhatEthersSigner[] = await ethers.getSigners();
33
- signers = { owner: ethSigners[0], alice: ethSigners[1] };
34
- });
35
-
36
- beforeEach(async function () {
37
- const deployment = await deployFixture();
38
- contractAddress = deployment.contractAddress;
39
- contract = deployment.contract;
40
- });
41
-
42
- describe("Initialization", function () {
43
- it("should initialize with encrypted balance and threshold", async function () {
44
- const fhevm = hre.fhevm;
45
- const balance = 100;
46
- const threshold = 50;
47
-
48
- const input = await fhevm
49
- .createEncryptedInput(contractAddress, signers.alice.address)
50
- .add32(balance)
51
- .add32(threshold)
52
- .encrypt();
53
-
54
- await contract
55
- .connect(signers.alice)
56
- .initialize(input.handles[0], input.handles[1], input.inputProof);
57
-
58
- // Contract should now have encrypted values
59
- // We can't directly verify values without decryption, but tx should succeed
60
- });
61
- });
62
-
63
- describe("Correct Conditional Pattern", function () {
64
- it("should handle conditional logic with FHE.select", async function () {
65
- const fhevm = hre.fhevm;
66
-
67
- // Initialize with balance=100, threshold=50
68
- const input = await fhevm
69
- .createEncryptedInput(contractAddress, signers.alice.address)
70
- .add32(100) // balance
71
- .add32(50) // threshold
72
- .encrypt();
73
-
74
- await contract
75
- .connect(signers.alice)
76
- .initialize(input.handles[0], input.handles[1], input.inputProof);
77
-
78
- // Execute correct conditional - should not revert
79
- await expect(contract.connect(signers.alice).correctConditional()).to.not
80
- .be.reverted;
81
- });
82
- });
83
-
84
- describe("Correct Computation Pattern", function () {
85
- it("should compute with proper permission grants", async function () {
86
- const fhevm = hre.fhevm;
87
-
88
- const input = await fhevm
89
- .createEncryptedInput(contractAddress, signers.alice.address)
90
- .add32(50) // balance
91
- .add32(25) // threshold
92
- .encrypt();
93
-
94
- await contract
95
- .connect(signers.alice)
96
- .initialize(input.handles[0], input.handles[1], input.inputProof);
97
-
98
- // correctCompute grants proper permissions
99
- await expect(contract.connect(signers.alice).correctCompute()).to.not.be
100
- .reverted;
101
- });
102
- });
103
-
104
- describe("Rules Reference", function () {
105
- it("should return the key rules summary", async function () {
106
- const rules = await contract.getRules();
107
- expect(rules).to.include("FHE.select");
108
- expect(rules).to.include("FHE.allowThis");
109
- expect(rules).to.include("require/revert");
110
- });
111
- });
112
- });