create-fhevm-example 1.3.1 → 1.4.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.
Files changed (122) hide show
  1. package/contracts/advanced/BlindAuction.sol +255 -0
  2. package/contracts/advanced/EncryptedEscrow.sol +315 -0
  3. package/contracts/advanced/HiddenVoting.sol +231 -0
  4. package/contracts/advanced/PrivateKYC.sol +309 -0
  5. package/contracts/advanced/PrivatePayroll.sol +285 -0
  6. package/contracts/basic/decryption/PublicDecryptMultipleValues.sol +160 -0
  7. package/contracts/basic/decryption/PublicDecryptSingleValue.sol +142 -0
  8. package/contracts/basic/decryption/UserDecryptMultipleValues.sol +61 -0
  9. package/contracts/basic/decryption/UserDecryptSingleValue.sol +59 -0
  10. package/contracts/basic/encryption/EncryptMultipleValues.sol +72 -0
  11. package/contracts/basic/encryption/EncryptSingleValue.sol +44 -0
  12. package/contracts/basic/encryption/FHECounter.sol +54 -0
  13. package/contracts/basic/fhe-operations/FHEAdd.sol +51 -0
  14. package/contracts/basic/fhe-operations/FHEArithmetic.sol +99 -0
  15. package/contracts/basic/fhe-operations/FHEComparison.sol +116 -0
  16. package/contracts/basic/fhe-operations/FHEIfThenElse.sol +53 -0
  17. package/contracts/concepts/FHEAccessControl.sol +94 -0
  18. package/contracts/concepts/FHEAntiPatterns.sol +329 -0
  19. package/contracts/concepts/FHEHandles.sol +128 -0
  20. package/contracts/concepts/FHEInputProof.sol +104 -0
  21. package/contracts/gaming/EncryptedLottery.sol +298 -0
  22. package/contracts/gaming/EncryptedPoker.sol +337 -0
  23. package/contracts/gaming/RockPaperScissors.sol +213 -0
  24. package/contracts/openzeppelin/ERC7984.sol +85 -0
  25. package/contracts/openzeppelin/ERC7984ERC20Wrapper.sol +43 -0
  26. package/contracts/openzeppelin/SwapERC7984ToERC20.sol +110 -0
  27. package/contracts/openzeppelin/SwapERC7984ToERC7984.sol +48 -0
  28. package/contracts/openzeppelin/VestingWallet.sol +147 -0
  29. package/contracts/openzeppelin/mocks/ERC20Mock.sol +31 -0
  30. package/dist/scripts/commands/add-mode.d.ts.map +1 -0
  31. package/dist/scripts/{add-mode.js → commands/add-mode.js} +27 -61
  32. package/dist/scripts/commands/doctor.d.ts.map +1 -0
  33. package/dist/scripts/{doctor.js → commands/doctor.js} +2 -2
  34. package/dist/scripts/commands/generate-config.d.ts.map +1 -0
  35. package/dist/scripts/{generate-config.js → commands/generate-config.js} +3 -10
  36. package/dist/scripts/commands/generate-docs.d.ts.map +1 -0
  37. package/dist/scripts/{generate-docs.js → commands/generate-docs.js} +4 -3
  38. package/dist/scripts/commands/maintenance.d.ts.map +1 -0
  39. package/dist/scripts/{maintenance.js → commands/maintenance.js} +11 -10
  40. package/dist/scripts/index.js +63 -59
  41. package/dist/scripts/{builders.d.ts → shared/builders.d.ts} +2 -2
  42. package/dist/scripts/shared/builders.d.ts.map +1 -0
  43. package/dist/scripts/{builders.js → shared/builders.js} +49 -30
  44. package/dist/scripts/{config.d.ts → shared/config.d.ts} +0 -2
  45. package/dist/scripts/shared/config.d.ts.map +1 -0
  46. package/dist/scripts/{config.js → shared/config.js} +48 -59
  47. package/dist/scripts/shared/generators.d.ts +42 -0
  48. package/dist/scripts/shared/generators.d.ts.map +1 -0
  49. package/dist/scripts/{utils.js → shared/generators.js} +34 -271
  50. package/dist/scripts/shared/ui.d.ts.map +1 -0
  51. package/dist/scripts/{ui.js → shared/ui.js} +3 -2
  52. package/dist/scripts/{utils.d.ts → shared/utils.d.ts} +4 -27
  53. package/dist/scripts/shared/utils.d.ts.map +1 -0
  54. package/dist/scripts/shared/utils.js +228 -0
  55. package/fhevm-hardhat-template/.eslintignore +26 -0
  56. package/fhevm-hardhat-template/.eslintrc.yml +21 -0
  57. package/fhevm-hardhat-template/.github/workflows/main.yml +47 -0
  58. package/fhevm-hardhat-template/.github/workflows/manual-windows.yml +28 -0
  59. package/fhevm-hardhat-template/.github/workflows/manual.yml +28 -0
  60. package/fhevm-hardhat-template/.prettierignore +25 -0
  61. package/fhevm-hardhat-template/.prettierrc.yml +15 -0
  62. package/fhevm-hardhat-template/.solcover.js +4 -0
  63. package/fhevm-hardhat-template/.solhint.json +12 -0
  64. package/fhevm-hardhat-template/.solhintignore +3 -0
  65. package/fhevm-hardhat-template/.vscode/extensions.json +3 -0
  66. package/fhevm-hardhat-template/.vscode/settings.json +9 -0
  67. package/fhevm-hardhat-template/LICENSE +33 -0
  68. package/fhevm-hardhat-template/README.md +110 -0
  69. package/fhevm-hardhat-template/contracts/FHECounter.sol +46 -0
  70. package/fhevm-hardhat-template/deploy/deploy.ts +17 -0
  71. package/fhevm-hardhat-template/hardhat.config.ts +90 -0
  72. package/fhevm-hardhat-template/package-lock.json +10405 -0
  73. package/fhevm-hardhat-template/package.json +104 -0
  74. package/fhevm-hardhat-template/tasks/FHECounter.ts +184 -0
  75. package/fhevm-hardhat-template/tasks/accounts.ts +9 -0
  76. package/fhevm-hardhat-template/test/FHECounter.ts +104 -0
  77. package/fhevm-hardhat-template/test/FHECounterSepolia.ts +104 -0
  78. package/fhevm-hardhat-template/tsconfig.json +23 -0
  79. package/package.json +13 -10
  80. package/test/advanced/BlindAuction.ts +246 -0
  81. package/test/advanced/EncryptedEscrow.ts +295 -0
  82. package/test/advanced/HiddenVoting.ts +268 -0
  83. package/test/advanced/PrivateKYC.ts +382 -0
  84. package/test/advanced/PrivatePayroll.ts +253 -0
  85. package/test/basic/decryption/PublicDecryptMultipleValues.ts +254 -0
  86. package/test/basic/decryption/PublicDecryptSingleValue.ts +264 -0
  87. package/test/basic/decryption/UserDecryptMultipleValues.ts +107 -0
  88. package/test/basic/decryption/UserDecryptSingleValue.ts +97 -0
  89. package/test/basic/encryption/EncryptMultipleValues.ts +110 -0
  90. package/test/basic/encryption/EncryptSingleValue.ts +124 -0
  91. package/test/basic/encryption/FHECounter.ts +112 -0
  92. package/test/basic/fhe-operations/FHEAdd.ts +97 -0
  93. package/test/basic/fhe-operations/FHEArithmetic.ts +161 -0
  94. package/test/basic/fhe-operations/FHEComparison.ts +167 -0
  95. package/test/basic/fhe-operations/FHEIfThenElse.ts +97 -0
  96. package/test/concepts/FHEAccessControl.ts +154 -0
  97. package/test/concepts/FHEAntiPatterns.ts +111 -0
  98. package/test/concepts/FHEHandles.ts +156 -0
  99. package/test/concepts/FHEInputProof.ts +151 -0
  100. package/test/gaming/EncryptedLottery.ts +214 -0
  101. package/test/gaming/EncryptedPoker.ts +349 -0
  102. package/test/gaming/RockPaperScissors.ts +205 -0
  103. package/test/openzeppelin/ERC7984.ts +142 -0
  104. package/test/openzeppelin/ERC7984ERC20Wrapper.ts +71 -0
  105. package/test/openzeppelin/SwapERC7984ToERC20.ts +76 -0
  106. package/test/openzeppelin/SwapERC7984ToERC7984.ts +113 -0
  107. package/test/openzeppelin/VestingWallet.ts +89 -0
  108. package/dist/scripts/add-mode.d.ts.map +0 -1
  109. package/dist/scripts/builders.d.ts.map +0 -1
  110. package/dist/scripts/config.d.ts.map +0 -1
  111. package/dist/scripts/doctor.d.ts.map +0 -1
  112. package/dist/scripts/generate-config.d.ts.map +0 -1
  113. package/dist/scripts/generate-docs.d.ts.map +0 -1
  114. package/dist/scripts/maintenance.d.ts.map +0 -1
  115. package/dist/scripts/ui.d.ts.map +0 -1
  116. package/dist/scripts/utils.d.ts.map +0 -1
  117. /package/dist/scripts/{add-mode.d.ts → commands/add-mode.d.ts} +0 -0
  118. /package/dist/scripts/{doctor.d.ts → commands/doctor.d.ts} +0 -0
  119. /package/dist/scripts/{generate-config.d.ts → commands/generate-config.d.ts} +0 -0
  120. /package/dist/scripts/{generate-docs.d.ts → commands/generate-docs.d.ts} +0 -0
  121. /package/dist/scripts/{maintenance.d.ts → commands/maintenance.d.ts} +0 -0
  122. /package/dist/scripts/{ui.d.ts → shared/ui.d.ts} +0 -0
@@ -0,0 +1,104 @@
1
+ {
2
+ "name": "fhevm-hardhat-template",
3
+ "description": "Hardhat-based template for developing FHEVM Solidity smart contracts",
4
+ "version": "0.3.0-3",
5
+ "engines": {
6
+ "node": ">=20",
7
+ "npm": ">=7.0.0"
8
+ },
9
+ "license": "BSD-3-Clause-Clear",
10
+ "homepage": "https://github.com/zama-ai/fhevm-hardhat-template/README.md",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/zama-ai/fhevm-hardhat-template.git"
14
+ },
15
+ "keywords": [
16
+ "fhevm",
17
+ "zama",
18
+ "eth",
19
+ "ethereum",
20
+ "dapps",
21
+ "wallet",
22
+ "web3",
23
+ "typescript",
24
+ "hardhat"
25
+ ],
26
+ "dependencies": {
27
+ "encrypted-types": "^0.0.4",
28
+ "@fhevm/solidity": "^0.9.1"
29
+ },
30
+ "devDependencies": {
31
+ "@fhevm/hardhat-plugin": "^0.3.0-3",
32
+ "@nomicfoundation/hardhat-chai-matchers": "^2.1.0",
33
+ "@nomicfoundation/hardhat-ethers": "^3.1.0",
34
+ "@nomicfoundation/hardhat-network-helpers": "^1.1.0",
35
+ "@nomicfoundation/hardhat-verify": "^2.1.0",
36
+ "@typechain/ethers-v6": "^0.5.1",
37
+ "@typechain/hardhat": "^9.1.0",
38
+ "@types/chai": "^4.3.20",
39
+ "@types/mocha": "^10.0.10",
40
+ "@types/node": "^20.19.8",
41
+ "@typescript-eslint/eslint-plugin": "^8.37.0",
42
+ "@typescript-eslint/parser": "^8.37.0",
43
+ "@zama-fhe/relayer-sdk": "^0.3.0-6",
44
+ "chai": "^4.5.0",
45
+ "chai-as-promised": "^8.0.1",
46
+ "cross-env": "^7.0.3",
47
+ "eslint": "^8.57.1",
48
+ "eslint-config-prettier": "^9.1.0",
49
+ "ethers": "^6.15.0",
50
+ "hardhat": "^2.26.0",
51
+ "hardhat-deploy": "^0.11.45",
52
+ "hardhat-gas-reporter": "^2.3.0",
53
+ "mocha": "^11.7.1",
54
+ "prettier": "^3.6.2",
55
+ "prettier-plugin-solidity": "^2.1.0",
56
+ "rimraf": "^6.0.1",
57
+ "solhint": "^6.0.0",
58
+ "solidity-coverage": "^0.8.16",
59
+ "ts-generator": "^0.1.1",
60
+ "ts-node": "^10.9.2",
61
+ "typechain": "^8.3.2",
62
+ "typescript": "^5.8.3"
63
+ },
64
+ "files": [
65
+ "contracts"
66
+ ],
67
+ "scripts": {
68
+ "clean": "rimraf ./fhevmTemp ./artifacts ./cache ./coverage ./types ./coverage.json ./dist && npm run typechain",
69
+ "compile": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat compile",
70
+ "coverage": "cross-env SOLIDITY_COVERAGE=true hardhat coverage --solcoverjs ./.solcover.js --temp artifacts --testfiles \"test/**/*.ts\" && npm run typechain",
71
+ "lint": "npm run lint:sol && npm run lint:ts && npm run prettier:check",
72
+ "lint:sol": "solhint --max-warnings 0 \"contracts/**/*.sol\"",
73
+ "lint:ts": "eslint --ignore-path ./.eslintignore --ext .js,.ts .",
74
+ "postcompile": "npm run typechain",
75
+ "prettier:check": "prettier --check \"**/*.{js,json,md,sol,ts,yml}\"",
76
+ "prettier:write": "prettier --write \"**/*.{js,json,md,sol,ts,yml}\"",
77
+ "test": "hardhat test",
78
+ "test:sepolia": "hardhat test --network sepolia",
79
+ "build:ts": "tsc --project tsconfig.json",
80
+ "typechain": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat typechain",
81
+ "chain": "hardhat node --network hardhat --no-deploy",
82
+ "deploy:localhost": "hardhat deploy --network localhost",
83
+ "deploy:sepolia": "hardhat deploy --network sepolia",
84
+ "verify:sepolia": "hardhat verify --network sepolia"
85
+ },
86
+ "overrides": {
87
+ "ws@>=7.0.0 <7.5.10": ">=7.5.10",
88
+ "axios@>=1.3.2 <=1.7.3": ">=1.7.4",
89
+ "elliptic@>=4.0.0 <=6.5.6": ">=6.5.7",
90
+ "elliptic@>=2.0.0 <=6.5.6": ">=6.5.7",
91
+ "elliptic@>=5.2.1 <=6.5.6": ">=6.5.7",
92
+ "micromatch@<4.0.8": ">=4.0.8",
93
+ "elliptic@<6.6.0": ">=6.6.0",
94
+ "elliptic@<6.5.6": ">=6.5.6",
95
+ "undici@>=6.0.0 <6.21.1": ">=6.21.1 <7.0.0",
96
+ "undici@>=4.5.0 <5.28.5": ">=5.28.5 <6.0.0",
97
+ "elliptic@<=6.6.0": ">=6.6.1",
98
+ "tar-fs@>=2.0.0 <2.1.2": ">=2.1.2",
99
+ "axios@>=1.0.0 <1.8.2": ">=1.8.2",
100
+ "axios@<0.29.1": ">=0.29.1",
101
+ "cookie@<0.7.0": ">=0.7.0",
102
+ "minimatch": "^3.1.2"
103
+ }
104
+ }
@@ -0,0 +1,184 @@
1
+ import { FhevmType } from "@fhevm/hardhat-plugin";
2
+ import { task } from "hardhat/config";
3
+ import type { TaskArguments } from "hardhat/types";
4
+
5
+ /**
6
+ * Tutorial: Deploy and Interact Locally (--network localhost)
7
+ * ===========================================================
8
+ *
9
+ * 1. From a separate terminal window:
10
+ *
11
+ * npx hardhat node
12
+ *
13
+ * 2. Deploy the FHECounter contract
14
+ *
15
+ * npx hardhat --network localhost deploy
16
+ *
17
+ * 3. Interact with the FHECounter contract
18
+ *
19
+ * npx hardhat --network localhost task:decrypt-count
20
+ * npx hardhat --network localhost task:increment --value 2
21
+ * npx hardhat --network localhost task:decrement --value 1
22
+ * npx hardhat --network localhost task:decrypt-count
23
+ *
24
+ *
25
+ * Tutorial: Deploy and Interact on Sepolia (--network sepolia)
26
+ * ===========================================================
27
+ *
28
+ * 1. Deploy the FHECounter contract
29
+ *
30
+ * npx hardhat --network sepolia deploy
31
+ *
32
+ * 2. Interact with the FHECounter contract
33
+ *
34
+ * npx hardhat --network sepolia task:decrypt-count
35
+ * npx hardhat --network sepolia task:increment --value 2
36
+ * npx hardhat --network sepolia task:decrement --value 1
37
+ * npx hardhat --network sepolia task:decrypt-count
38
+ *
39
+ */
40
+
41
+ /**
42
+ * Example:
43
+ * - npx hardhat --network localhost task:address
44
+ * - npx hardhat --network sepolia task:address
45
+ */
46
+ task("task:address", "Prints the FHECounter address").setAction(async function (_taskArguments: TaskArguments, hre) {
47
+ const { deployments } = hre;
48
+
49
+ const fheCounter = await deployments.get("FHECounter");
50
+
51
+ console.log("FHECounter address is " + fheCounter.address);
52
+ });
53
+
54
+ /**
55
+ * Example:
56
+ * - npx hardhat --network localhost task:decrypt-count
57
+ * - npx hardhat --network sepolia task:decrypt-count
58
+ */
59
+ task("task:decrypt-count", "Calls the getCount() function of Counter Contract")
60
+ .addOptionalParam("address", "Optionally specify the Counter contract address")
61
+ .setAction(async function (taskArguments: TaskArguments, hre) {
62
+ const { ethers, deployments, fhevm } = hre;
63
+
64
+ await fhevm.initializeCLIApi();
65
+
66
+ const FHECounterDeployement = taskArguments.address
67
+ ? { address: taskArguments.address }
68
+ : await deployments.get("FHECounter");
69
+ console.log(`FHECounter: ${FHECounterDeployement.address}`);
70
+
71
+ const signers = await ethers.getSigners();
72
+
73
+ const fheCounterContract = await ethers.getContractAt("FHECounter", FHECounterDeployement.address);
74
+
75
+ const encryptedCount = await fheCounterContract.getCount();
76
+ if (encryptedCount === ethers.ZeroHash) {
77
+ console.log(`encrypted count: ${encryptedCount}`);
78
+ console.log("clear count : 0");
79
+ return;
80
+ }
81
+
82
+ const clearCount = await fhevm.userDecryptEuint(
83
+ FhevmType.euint32,
84
+ encryptedCount,
85
+ FHECounterDeployement.address,
86
+ signers[0],
87
+ );
88
+ console.log(`Encrypted count: ${encryptedCount}`);
89
+ console.log(`Clear count : ${clearCount}`);
90
+ });
91
+
92
+ /**
93
+ * Example:
94
+ * - npx hardhat --network localhost task:increment --value 1
95
+ * - npx hardhat --network sepolia task:increment --value 1
96
+ */
97
+ task("task:increment", "Calls the increment() function of FHECounter Contract")
98
+ .addOptionalParam("address", "Optionally specify the FHECounter contract address")
99
+ .addParam("value", "The increment value")
100
+ .setAction(async function (taskArguments: TaskArguments, hre) {
101
+ const { ethers, deployments, fhevm } = hre;
102
+
103
+ const value = parseInt(taskArguments.value);
104
+ if (!Number.isInteger(value)) {
105
+ throw new Error(`Argument --value is not an integer`);
106
+ }
107
+
108
+ await fhevm.initializeCLIApi();
109
+
110
+ const FHECounterDeployement = taskArguments.address
111
+ ? { address: taskArguments.address }
112
+ : await deployments.get("FHECounter");
113
+ console.log(`FHECounter: ${FHECounterDeployement.address}`);
114
+
115
+ const signers = await ethers.getSigners();
116
+
117
+ const fheCounterContract = await ethers.getContractAt("FHECounter", FHECounterDeployement.address);
118
+
119
+ // Encrypt the value passed as argument
120
+ const encryptedValue = await fhevm
121
+ .createEncryptedInput(FHECounterDeployement.address, signers[0].address)
122
+ .add32(value)
123
+ .encrypt();
124
+
125
+ const tx = await fheCounterContract
126
+ .connect(signers[0])
127
+ .increment(encryptedValue.handles[0], encryptedValue.inputProof);
128
+ console.log(`Wait for tx:${tx.hash}...`);
129
+
130
+ const receipt = await tx.wait();
131
+ console.log(`tx:${tx.hash} status=${receipt?.status}`);
132
+
133
+ const newEncryptedCount = await fheCounterContract.getCount();
134
+ console.log("Encrypted count after increment:", newEncryptedCount);
135
+
136
+ console.log(`FHECounter increment(${value}) succeeded!`);
137
+ });
138
+
139
+ /**
140
+ * Example:
141
+ * - npx hardhat --network localhost task:decrement --value 1
142
+ * - npx hardhat --network sepolia task:decrement --value 1
143
+ */
144
+ task("task:decrement", "Calls the decrement() function of FHECounter Contract")
145
+ .addOptionalParam("address", "Optionally specify the FHECounter contract address")
146
+ .addParam("value", "The decrement value")
147
+ .setAction(async function (taskArguments: TaskArguments, hre) {
148
+ const { ethers, deployments, fhevm } = hre;
149
+
150
+ const value = parseInt(taskArguments.value);
151
+ if (!Number.isInteger(value)) {
152
+ throw new Error(`Argument --value is not an integer`);
153
+ }
154
+
155
+ await fhevm.initializeCLIApi();
156
+
157
+ const FHECounterDeployement = taskArguments.address
158
+ ? { address: taskArguments.address }
159
+ : await deployments.get("FHECounter");
160
+ console.log(`FHECounter: ${FHECounterDeployement.address}`);
161
+
162
+ const signers = await ethers.getSigners();
163
+
164
+ const fheCounterContract = await ethers.getContractAt("FHECounter", FHECounterDeployement.address);
165
+
166
+ // Encrypt the value passed as argument
167
+ const encryptedValue = await fhevm
168
+ .createEncryptedInput(FHECounterDeployement.address, signers[0].address)
169
+ .add32(value)
170
+ .encrypt();
171
+
172
+ const tx = await fheCounterContract
173
+ .connect(signers[0])
174
+ .decrement(encryptedValue.handles[0], encryptedValue.inputProof);
175
+ console.log(`Wait for tx:${tx.hash}...`);
176
+
177
+ const receipt = await tx.wait();
178
+ console.log(`tx:${tx.hash} status=${receipt?.status}`);
179
+
180
+ const newEncryptedCount = await fheCounterContract.getCount();
181
+ console.log("Encrypted count after decrement:", newEncryptedCount);
182
+
183
+ console.log(`FHECounter decrement(${value}) succeeded!`);
184
+ });
@@ -0,0 +1,9 @@
1
+ import { task } from "hardhat/config";
2
+
3
+ task("accounts", "Prints the list of accounts", async (_taskArgs, hre) => {
4
+ const accounts = await hre.ethers.getSigners();
5
+
6
+ for (const account of accounts) {
7
+ console.log(`${account.address}`);
8
+ }
9
+ });
@@ -0,0 +1,104 @@
1
+ import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
2
+ import { ethers, fhevm } from "hardhat";
3
+ import { FHECounter, FHECounter__factory } from "../types";
4
+ import { expect } from "chai";
5
+ import { FhevmType } from "@fhevm/hardhat-plugin";
6
+
7
+ type Signers = {
8
+ deployer: HardhatEthersSigner;
9
+ alice: HardhatEthersSigner;
10
+ bob: HardhatEthersSigner;
11
+ };
12
+
13
+ async function deployFixture() {
14
+ const factory = (await ethers.getContractFactory("FHECounter")) as FHECounter__factory;
15
+ const fheCounterContract = (await factory.deploy()) as FHECounter;
16
+ const fheCounterContractAddress = await fheCounterContract.getAddress();
17
+
18
+ return { fheCounterContract, fheCounterContractAddress };
19
+ }
20
+
21
+ describe("FHECounter", function () {
22
+ let signers: Signers;
23
+ let fheCounterContract: FHECounter;
24
+ let fheCounterContractAddress: string;
25
+
26
+ before(async function () {
27
+ const ethSigners: HardhatEthersSigner[] = await ethers.getSigners();
28
+ signers = { deployer: ethSigners[0], alice: ethSigners[1], bob: ethSigners[2] };
29
+ });
30
+
31
+ beforeEach(async function () {
32
+ // Check whether the tests are running against an FHEVM mock environment
33
+ if (!fhevm.isMock) {
34
+ console.warn(`This hardhat test suite cannot run on Sepolia Testnet`);
35
+ this.skip();
36
+ }
37
+
38
+ ({ fheCounterContract, fheCounterContractAddress } = await deployFixture());
39
+ });
40
+
41
+ it("encrypted count should be uninitialized after deployment", async function () {
42
+ const encryptedCount = await fheCounterContract.getCount();
43
+ // Expect initial count to be bytes32(0) after deployment,
44
+ // (meaning the encrypted count value is uninitialized)
45
+ expect(encryptedCount).to.eq(ethers.ZeroHash);
46
+ });
47
+
48
+ it("increment the counter by 1", async function () {
49
+ const encryptedCountBeforeInc = await fheCounterContract.getCount();
50
+ expect(encryptedCountBeforeInc).to.eq(ethers.ZeroHash);
51
+ const clearCountBeforeInc = 0;
52
+
53
+ // Encrypt constant 1 as a euint32
54
+ const clearOne = 1;
55
+ const encryptedOne = await fhevm
56
+ .createEncryptedInput(fheCounterContractAddress, signers.alice.address)
57
+ .add32(clearOne)
58
+ .encrypt();
59
+
60
+ const tx = await fheCounterContract
61
+ .connect(signers.alice)
62
+ .increment(encryptedOne.handles[0], encryptedOne.inputProof);
63
+ await tx.wait();
64
+
65
+ const encryptedCountAfterInc = await fheCounterContract.getCount();
66
+ const clearCountAfterInc = await fhevm.userDecryptEuint(
67
+ FhevmType.euint32,
68
+ encryptedCountAfterInc,
69
+ fheCounterContractAddress,
70
+ signers.alice,
71
+ );
72
+
73
+ expect(clearCountAfterInc).to.eq(clearCountBeforeInc + clearOne);
74
+ });
75
+
76
+ it("decrement the counter by 1", async function () {
77
+ // Encrypt constant 1 as a euint32
78
+ const clearOne = 1;
79
+ const encryptedOne = await fhevm
80
+ .createEncryptedInput(fheCounterContractAddress, signers.alice.address)
81
+ .add32(clearOne)
82
+ .encrypt();
83
+
84
+ // First increment by 1, count becomes 1
85
+ let tx = await fheCounterContract
86
+ .connect(signers.alice)
87
+ .increment(encryptedOne.handles[0], encryptedOne.inputProof);
88
+ await tx.wait();
89
+
90
+ // Then decrement by 1, count goes back to 0
91
+ tx = await fheCounterContract.connect(signers.alice).decrement(encryptedOne.handles[0], encryptedOne.inputProof);
92
+ await tx.wait();
93
+
94
+ const encryptedCountAfterDec = await fheCounterContract.getCount();
95
+ const clearCountAfterInc = await fhevm.userDecryptEuint(
96
+ FhevmType.euint32,
97
+ encryptedCountAfterDec,
98
+ fheCounterContractAddress,
99
+ signers.alice,
100
+ );
101
+
102
+ expect(clearCountAfterInc).to.eq(0);
103
+ });
104
+ });
@@ -0,0 +1,104 @@
1
+ import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
2
+ import { ethers, fhevm, deployments } from "hardhat";
3
+ import { FHECounter } from "../types";
4
+ import { expect } from "chai";
5
+ import { FhevmType } from "@fhevm/hardhat-plugin";
6
+
7
+ type Signers = {
8
+ alice: HardhatEthersSigner;
9
+ };
10
+
11
+ describe("FHECounterSepolia", function () {
12
+ let signers: Signers;
13
+ let fheCounterContract: FHECounter;
14
+ let fheCounterContractAddress: string;
15
+ let step: number;
16
+ let steps: number;
17
+
18
+ function progress(message: string) {
19
+ console.log(`${++step}/${steps} ${message}`);
20
+ }
21
+
22
+ before(async function () {
23
+ if (fhevm.isMock) {
24
+ console.warn(`This hardhat test suite can only run on Sepolia Testnet`);
25
+ this.skip();
26
+ }
27
+
28
+ try {
29
+ const FHECounterDeployement = await deployments.get("FHECounter");
30
+ fheCounterContractAddress = FHECounterDeployement.address;
31
+ fheCounterContract = await ethers.getContractAt("FHECounter", FHECounterDeployement.address);
32
+ } catch (e) {
33
+ (e as Error).message += ". Call 'npx hardhat deploy --network sepolia'";
34
+ throw e;
35
+ }
36
+
37
+ const ethSigners: HardhatEthersSigner[] = await ethers.getSigners();
38
+ signers = { alice: ethSigners[0] };
39
+ });
40
+
41
+ beforeEach(async () => {
42
+ step = 0;
43
+ steps = 0;
44
+ });
45
+
46
+ it("increment the counter by 1", async function () {
47
+ steps = 10;
48
+
49
+ this.timeout(4 * 40000);
50
+
51
+ progress("Encrypting '0'...");
52
+ const encryptedZero = await fhevm
53
+ .createEncryptedInput(fheCounterContractAddress, signers.alice.address)
54
+ .add32(0)
55
+ .encrypt();
56
+
57
+ progress(
58
+ `Call increment(0) FHECounter=${fheCounterContractAddress} handle=${ethers.hexlify(encryptedZero.handles[0])} signer=${signers.alice.address}...`,
59
+ );
60
+ let tx = await fheCounterContract
61
+ .connect(signers.alice)
62
+ .increment(encryptedZero.handles[0], encryptedZero.inputProof);
63
+ await tx.wait();
64
+
65
+ progress(`Call FHECounter.getCount()...`);
66
+ const encryptedCountBeforeInc = await fheCounterContract.getCount();
67
+ expect(encryptedCountBeforeInc).to.not.eq(ethers.ZeroHash);
68
+
69
+ progress(`Decrypting FHECounter.getCount()=${encryptedCountBeforeInc}...`);
70
+ const clearCountBeforeInc = await fhevm.userDecryptEuint(
71
+ FhevmType.euint32,
72
+ encryptedCountBeforeInc,
73
+ fheCounterContractAddress,
74
+ signers.alice,
75
+ );
76
+ progress(`Clear FHECounter.getCount()=${clearCountBeforeInc}`);
77
+
78
+ progress(`Encrypting '1'...`);
79
+ const encryptedOne = await fhevm
80
+ .createEncryptedInput(fheCounterContractAddress, signers.alice.address)
81
+ .add32(1)
82
+ .encrypt();
83
+
84
+ progress(
85
+ `Call increment(1) FHECounter=${fheCounterContractAddress} handle=${ethers.hexlify(encryptedOne.handles[0])} signer=${signers.alice.address}...`,
86
+ );
87
+ tx = await fheCounterContract.connect(signers.alice).increment(encryptedOne.handles[0], encryptedOne.inputProof);
88
+ await tx.wait();
89
+
90
+ progress(`Call FHECounter.getCount()...`);
91
+ const encryptedCountAfterInc = await fheCounterContract.getCount();
92
+
93
+ progress(`Decrypting FHECounter.getCount()=${encryptedCountAfterInc}...`);
94
+ const clearCountAfterInc = await fhevm.userDecryptEuint(
95
+ FhevmType.euint32,
96
+ encryptedCountAfterInc,
97
+ fheCounterContractAddress,
98
+ signers.alice,
99
+ );
100
+ progress(`Clear FHECounter.getCount()=${clearCountAfterInc}`);
101
+
102
+ expect(clearCountAfterInc - clearCountBeforeInc).to.eq(1);
103
+ });
104
+ });
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "declaration": true,
4
+ "declarationMap": true,
5
+ "outDir": "dist",
6
+ "emitDecoratorMetadata": true,
7
+ "esModuleInterop": true,
8
+ "experimentalDecorators": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "lib": ["es2022"], // get error cause (ErrorOptions)
11
+ "module": "commonjs",
12
+ "moduleResolution": "node",
13
+ "noImplicitAny": true,
14
+ "removeComments": true,
15
+ "resolveJsonModule": true,
16
+ "sourceMap": true,
17
+ "strict": true,
18
+ "target": "es2022" // get error cause (ErrorOptions)
19
+ },
20
+ "exclude": ["node_modules"],
21
+ "files": ["./hardhat.config.ts"],
22
+ "include": ["src/**/*", "tasks/**/*", "test/**/*", "deploy/**/*", "types/"]
23
+ }
package/package.json CHANGED
@@ -1,28 +1,31 @@
1
1
  {
2
2
  "name": "create-fhevm-example",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
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"
7
7
  },
8
8
  "main": "./dist/scripts/index.js",
9
9
  "files": [
10
- "dist"
10
+ "dist",
11
+ "contracts",
12
+ "test",
13
+ "fhevm-hardhat-template"
11
14
  ],
12
15
  "scripts": {
13
16
  "build": "tsc",
14
17
  "create": "LOCAL_DEV=1 npx ts-node scripts/index.ts",
15
18
  "create:example": "npx ts-node scripts/index.ts --example",
16
19
  "create:category": "npx ts-node scripts/index.ts --category",
17
- "create:docs": "npx ts-node scripts/generate-docs.ts",
18
- "test:all": "npx ts-node scripts/maintenance.ts test-all",
19
- "generate:config": "npx ts-node scripts/generate-config.ts",
20
- "doctor": "npx ts-node scripts/doctor.ts",
21
- "help:create": "npx ts-node scripts/index.ts --help",
22
- "help:docs": "npx ts-node scripts/generate-docs.ts --help",
23
- "help:test": "npx ts-node scripts/maintenance.ts test-all --help",
20
+ "create:docs": "npx ts-node scripts/commands/generate-docs.ts",
21
+ "test:all": "npx ts-node scripts/commands/maintenance.ts test-all",
22
+ "generate:config": "npx ts-node scripts/commands/generate-config.ts",
23
+ "doctor": "npx ts-node scripts/commands/doctor.ts",
24
+ "help:create": "LOCAL_DEV=1 npx ts-node scripts/index.ts --help",
25
+ "help:docs": "npx ts-node scripts/commands/generate-docs.ts --help",
26
+ "help:test": "npx ts-node scripts/commands/maintenance.ts test-all --help",
24
27
 
25
- "postinstall": "git submodule update --init --recursive",
28
+ "prepare": "git submodule update --init --recursive || true",
26
29
  "prepublishOnly": "npm run build",
27
30
  "prepack": "mv README.md GITHUB_README.md && cp NPM_README.md README.md",
28
31
  "postpack": "mv GITHUB_README.md README.md"