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,228 @@
1
+ "use strict";
2
+ /**
3
+ * Core Utilities - Essential helper functions for the FHEVM Example Factory.
4
+ *
5
+ * Contains constants, types, logging, file system operations,
6
+ * naming utilities, and validation functions.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.log = exports.ERROR_MESSAGES = exports.TEST_TYPES_CONTENT = exports.CATEGORY_ORDER = exports.FHEVM_DEPENDENCIES = exports.EXCLUDE_DIRS = exports.MAX_DESCRIPTION_LENGTH = exports.TEMPLATE_DIR_NAME = exports.CATEGORY_ICON = void 0;
46
+ exports.handleError = handleError;
47
+ exports.getRootDir = getRootDir;
48
+ exports.getTemplateDir = getTemplateDir;
49
+ exports.copyDirectoryRecursive = copyDirectoryRecursive;
50
+ exports.toKebabCase = toKebabCase;
51
+ exports.contractNameToExampleName = contractNameToExampleName;
52
+ exports.contractNameToTitle = contractNameToTitle;
53
+ exports.formatCategoryName = formatCategoryName;
54
+ exports.getContractName = getContractName;
55
+ exports.validateExample = validateExample;
56
+ exports.validateCategory = validateCategory;
57
+ exports.validateDirectoryNotExists = validateDirectoryNotExists;
58
+ const fs = __importStar(require("fs"));
59
+ const path = __importStar(require("path"));
60
+ const picocolors_1 = __importDefault(require("picocolors"));
61
+ const config_1 = require("./config");
62
+ exports.CATEGORY_ICON = "📁";
63
+ /** Template directory name within the cloned repo */
64
+ exports.TEMPLATE_DIR_NAME = "fhevm-hardhat-template";
65
+ /** Maximum description length for UI display */
66
+ exports.MAX_DESCRIPTION_LENGTH = 80;
67
+ /** Directories to exclude when copying template */
68
+ exports.EXCLUDE_DIRS = [
69
+ "node_modules",
70
+ "artifacts",
71
+ "cache",
72
+ "coverage",
73
+ "types",
74
+ "dist",
75
+ ".git",
76
+ ];
77
+ /** FHEVM package versions for --add mode */
78
+ exports.FHEVM_DEPENDENCIES = {
79
+ dependencies: {
80
+ "encrypted-types": "^0.0.4",
81
+ "@fhevm/solidity": "^0.9.1",
82
+ },
83
+ devDependencies: {
84
+ "@fhevm/hardhat-plugin": "^0.3.0-1",
85
+ "@zama-fhe/relayer-sdk": "^0.3.0-5",
86
+ },
87
+ };
88
+ exports.CATEGORY_ORDER = [
89
+ "Basic - Encryption",
90
+ "Basic - Decryption",
91
+ "Basic - FHE Operations",
92
+ "Concepts",
93
+ "Gaming",
94
+ "Openzeppelin",
95
+ "Advanced",
96
+ ];
97
+ exports.TEST_TYPES_CONTENT = `import type { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
98
+
99
+ /**
100
+ * Common signers interface used across test files
101
+ */
102
+ export interface Signers {
103
+ owner: HardhatEthersSigner;
104
+ alice: HardhatEthersSigner;
105
+ }
106
+ `;
107
+ exports.ERROR_MESSAGES = {
108
+ EXAMPLE_REQUIRED: "Error: Either --example or --category is required",
109
+ BOTH_SPECIFIED: "Error: Cannot use both --example and --category",
110
+ UNKNOWN_EXAMPLE: (name) => `Error: Unknown example "${name}"`,
111
+ UNKNOWN_CATEGORY: (name) => `Error: Unknown category "${name}"`,
112
+ DIR_EXISTS: (path) => `Error: Directory already exists: ${path}`,
113
+ NOT_HARDHAT: "This directory does not contain a valid Hardhat project.",
114
+ CONFIG_NOT_FOUND: "hardhat.config.ts or hardhat.config.js not found",
115
+ CONTRACT_NAME_FAILED: "Could not extract contract name",
116
+ };
117
+ // =============================================================================
118
+ // Logging Utility
119
+ // =============================================================================
120
+ exports.log = {
121
+ success: (msg) => console.log(picocolors_1.default.green(msg)),
122
+ error: (msg) => console.error(picocolors_1.default.red(msg)),
123
+ info: (msg) => console.log(picocolors_1.default.cyan(msg)),
124
+ dim: (msg) => console.log(picocolors_1.default.dim(msg)),
125
+ message: (msg) => console.log(msg),
126
+ };
127
+ /**
128
+ * Standardized error handler for CLI - logs error and exits
129
+ */
130
+ function handleError(error, exitCode = 1) {
131
+ const message = error instanceof Error ? error.message : String(error);
132
+ exports.log.error(message);
133
+ process.exit(exitCode);
134
+ }
135
+ // =============================================================================
136
+ // File System Utilities
137
+ // =============================================================================
138
+ /** Resolves root directory of the project (from scripts/shared/) */
139
+ function getRootDir() {
140
+ return path.resolve(__dirname, "../..");
141
+ }
142
+ /** Resolves template directory path */
143
+ function getTemplateDir() {
144
+ return path.join(getRootDir(), exports.TEMPLATE_DIR_NAME);
145
+ }
146
+ /** Copies directory recursively, excluding specified directories */
147
+ function copyDirectoryRecursive(source, destination, excludeDirs = exports.EXCLUDE_DIRS) {
148
+ if (!fs.existsSync(destination)) {
149
+ fs.mkdirSync(destination, { recursive: true });
150
+ }
151
+ const items = fs.readdirSync(source);
152
+ items.forEach((item) => {
153
+ const sourcePath = path.join(source, item);
154
+ const destPath = path.join(destination, item);
155
+ const stat = fs.statSync(sourcePath);
156
+ if (stat.isDirectory()) {
157
+ if (excludeDirs.includes(item)) {
158
+ return;
159
+ }
160
+ copyDirectoryRecursive(sourcePath, destPath, excludeDirs);
161
+ }
162
+ else {
163
+ fs.copyFileSync(sourcePath, destPath);
164
+ }
165
+ });
166
+ }
167
+ // =============================================================================
168
+ // Naming Utilities
169
+ // =============================================================================
170
+ function toKebabCase(str) {
171
+ return str
172
+ .replace(/([a-z])([A-Z])/g, "$1-$2")
173
+ .replace(/([0-9])([A-Z])/g, "$1-$2")
174
+ .replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2")
175
+ .toLowerCase();
176
+ }
177
+ function contractNameToExampleName(contractName) {
178
+ return toKebabCase(contractName);
179
+ }
180
+ function contractNameToTitle(contractName) {
181
+ return contractName
182
+ .replace(/([a-z])([A-Z])/g, "$1 $2")
183
+ .replace(/([0-9])([A-Z])/g, "$1 $2")
184
+ .replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2");
185
+ }
186
+ function formatCategoryName(folderName) {
187
+ return folderName
188
+ .replace(/\bfhe\b/gi, "FHE")
189
+ .replace(/-/g, " ")
190
+ .replace(/\b\w/g, (char) => char.toUpperCase());
191
+ }
192
+ function getContractName(contractPathOrContent) {
193
+ let content;
194
+ if (contractPathOrContent.includes("contract ") ||
195
+ contractPathOrContent.includes("pragma solidity")) {
196
+ content = contractPathOrContent;
197
+ }
198
+ else {
199
+ const fullPath = contractPathOrContent.startsWith("/")
200
+ ? contractPathOrContent
201
+ : path.join(getRootDir(), contractPathOrContent);
202
+ if (!fs.existsSync(fullPath)) {
203
+ const match = contractPathOrContent.match(/([^/]+)\.sol$/);
204
+ return match ? match[1] : null;
205
+ }
206
+ content = fs.readFileSync(fullPath, "utf-8");
207
+ }
208
+ const match = content.match(/^\s*contract\s+(\w+)(?:\s+is\s+|\s*\{)/m);
209
+ return match ? match[1] : null;
210
+ }
211
+ // =============================================================================
212
+ // Validation Functions
213
+ // =============================================================================
214
+ function validateExample(name) {
215
+ if (!config_1.EXAMPLES[name]) {
216
+ throw new Error(exports.ERROR_MESSAGES.UNKNOWN_EXAMPLE(name));
217
+ }
218
+ }
219
+ function validateCategory(name) {
220
+ if (!config_1.CATEGORIES[name]) {
221
+ throw new Error(exports.ERROR_MESSAGES.UNKNOWN_CATEGORY(name));
222
+ }
223
+ }
224
+ function validateDirectoryNotExists(dirPath) {
225
+ if (fs.existsSync(dirPath)) {
226
+ throw new Error(exports.ERROR_MESSAGES.DIR_EXISTS(dirPath));
227
+ }
228
+ }
@@ -0,0 +1,26 @@
1
+ # fhevm
2
+ fhevmTemp
3
+ tmp
4
+
5
+ # directories
6
+ .coverage_artifacts
7
+ .coverage_cache
8
+ .coverage_contracts
9
+ artifacts
10
+ build
11
+ cache
12
+ coverage
13
+ dist
14
+ node_modules
15
+ types
16
+
17
+ # files
18
+ *.env
19
+ *.log
20
+ .DS_Store
21
+ .pnp.*
22
+ bun.lockb
23
+ coverage.json
24
+ package-lock.json
25
+ pnpm-lock.yaml
26
+ yarn.lock
@@ -0,0 +1,21 @@
1
+ extends:
2
+ - "eslint:recommended"
3
+ - "plugin:@typescript-eslint/eslint-recommended"
4
+ - "plugin:@typescript-eslint/recommended"
5
+ - "prettier"
6
+ parser: "@typescript-eslint/parser"
7
+ parserOptions:
8
+ project: "tsconfig.json"
9
+ plugins:
10
+ - "@typescript-eslint"
11
+ root: true
12
+ rules:
13
+ "@typescript-eslint/no-floating-promises":
14
+ - error
15
+ - ignoreIIFE: true
16
+ ignoreVoid: true
17
+ "@typescript-eslint/no-inferrable-types": "off"
18
+ "@typescript-eslint/no-unused-vars":
19
+ - error
20
+ - argsIgnorePattern: "_"
21
+ varsIgnorePattern: "_"
@@ -0,0 +1,47 @@
1
+ name: Main
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ build-and-test-windows:
13
+ runs-on: windows-latest
14
+ steps:
15
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
16
+ with:
17
+ persist-credentials: "false"
18
+ - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
19
+ with:
20
+ node-version: 22.x
21
+ - uses: foundry-rs/foundry-toolchain@82dee4ba654bd2146511f85f0d013af94670c4de # v1.4.0
22
+ with:
23
+ version: stable
24
+ - run: npm ci
25
+ - run: npm run compile
26
+ - run: npm run build:ts
27
+ - run: npm test
28
+ - run: npm run coverage
29
+ build-and-test-unix:
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
33
+ with:
34
+ persist-credentials: "false"
35
+ - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
36
+ with:
37
+ node-version: 22.x
38
+ - uses: foundry-rs/foundry-toolchain@82dee4ba654bd2146511f85f0d013af94670c4de # v1.4.0
39
+ with:
40
+ version: stable
41
+ - run: npm ci
42
+ - run: npm run prettier:check
43
+ - run: npm run lint
44
+ - run: npm run compile
45
+ - run: npm run build:ts
46
+ - run: npm test
47
+ - run: npm run coverage
@@ -0,0 +1,28 @@
1
+ name: Windows Manual Test
2
+
3
+ on:
4
+ workflow_dispatch:
5
+
6
+ permissions:
7
+ contents: read
8
+
9
+ jobs:
10
+ build-and-test:
11
+ runs-on: windows-latest
12
+ steps:
13
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
14
+ with:
15
+ persist-credentials: "false"
16
+ - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
17
+ with:
18
+ node-version: 22.x
19
+ - uses: foundry-rs/foundry-toolchain@82dee4ba654bd2146511f85f0d013af94670c4de # v1.4.0
20
+ with:
21
+ version: stable
22
+ - run: npm ci
23
+ # - run: npm run prettier:check
24
+ # - run: npm run lint
25
+ - run: npm run compile
26
+ - run: npm run build:ts
27
+ - run: npm test
28
+ - run: npm run coverage
@@ -0,0 +1,28 @@
1
+ name: Manual Test
2
+
3
+ on:
4
+ workflow_dispatch:
5
+
6
+ permissions:
7
+ contents: read
8
+
9
+ jobs:
10
+ build-and-test:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
14
+ with:
15
+ persist-credentials: "false"
16
+ - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
17
+ with:
18
+ node-version: 22.x
19
+ - uses: foundry-rs/foundry-toolchain@82dee4ba654bd2146511f85f0d013af94670c4de # v1.4.0
20
+ with:
21
+ version: stable
22
+ - run: npm ci
23
+ - run: npm run prettier:check
24
+ - run: npm run lint
25
+ - run: npm run compile
26
+ - run: npm run build:ts
27
+ - run: npm test
28
+ - run: npm run coverage
@@ -0,0 +1,25 @@
1
+ # fhevm
2
+ fhevmTemp
3
+
4
+ # directories
5
+ .coverage_artifacts
6
+ .coverage_cache
7
+ .coverage_contracts
8
+ artifacts
9
+ build
10
+ cache
11
+ coverage
12
+ dist
13
+ node_modules
14
+ types
15
+
16
+ # files
17
+ *.env
18
+ *.log
19
+ .DS_Store
20
+ .pnp.*
21
+ bun.lockb
22
+ coverage.json
23
+ package-lock.json
24
+ pnpm-lock.yaml
25
+ yarn.lock
@@ -0,0 +1,15 @@
1
+ plugins:
2
+ - "prettier-plugin-solidity"
3
+ printWidth: 120
4
+ trailingComma: "all"
5
+ endOfLine: "lf"
6
+
7
+ overrides:
8
+ - files: "*.md"
9
+ options:
10
+ proseWrap: "always"
11
+ - files: "*.sol"
12
+ options:
13
+ compiler: "0.8.24"
14
+ parser: "slang"
15
+ tabWidth: 4
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ istanbulReporter: ["html", "lcov"],
3
+ skipFiles: ["test"],
4
+ };
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "solhint:recommended",
3
+ "rules": {
4
+ "code-complexity": ["error", 8],
5
+ "compiler-version": ["error", ">=0.8.4"],
6
+ "func-visibility": ["error", { "ignoreConstructors": true }],
7
+ "max-line-length": ["error", 120],
8
+ "named-parameters-mapping": "warn",
9
+ "no-console": "off",
10
+ "not-rely-on-time": "off"
11
+ }
12
+ }
@@ -0,0 +1,3 @@
1
+ # directories
2
+ **/artifacts
3
+ **/node_modules
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["esbenp.prettier-vscode", "NomicFoundation.hardhat-solidity", "dbaeumer.vscode-eslint"]
3
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
3
+ "editor.formatOnSave": true,
4
+ "prettier.documentSelectors": ["**/*.sol"],
5
+ "typescript.tsdk": "node_modules/typescript/lib",
6
+ "[solidity]": {
7
+ "editor.defaultFormatter": "NomicFoundation.hardhat-solidity"
8
+ }
9
+ }
@@ -0,0 +1,33 @@
1
+ BSD 3-Clause Clear License
2
+
3
+ Copyright © 2025 ZAMA.
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without modification,
7
+ are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice, this
13
+ list of conditions and the following disclaimer in the documentation and/or other
14
+ materials provided with the distribution.
15
+
16
+ 3. Neither the name of ZAMA nor the names of its contributors may be used to endorse
17
+ or promote products derived from this software without specific prior written permission.
18
+
19
+ NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE*.
20
+ THIS SOFTWARE IS PROVIDED BY THE ZAMA AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
21
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23
+ ZAMA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ *In addition to the rights carried by this license, ZAMA grants to the user a non-exclusive,
31
+ free and non-commercial license on all patents filed in its name relating to the open-source
32
+ code (the "Patents") for the sole purpose of evaluation, development, research, prototyping
33
+ and experimentation.
@@ -0,0 +1,110 @@
1
+ # FHEVM Hardhat Template
2
+
3
+ A Hardhat-based template for developing Fully Homomorphic Encryption (FHE) enabled Solidity smart contracts using the
4
+ FHEVM protocol by Zama.
5
+
6
+ ## Quick Start
7
+
8
+ For detailed instructions see:
9
+ [FHEVM Hardhat Quick Start Tutorial](https://docs.zama.ai/protocol/solidity-guides/getting-started/quick-start-tutorial)
10
+
11
+ ### Prerequisites
12
+
13
+ - **Node.js**: Version 20 or higher
14
+ - **npm or yarn/pnpm**: Package manager
15
+
16
+ ### Installation
17
+
18
+ 1. **Install dependencies**
19
+
20
+ ```bash
21
+ npm install
22
+ ```
23
+
24
+ 2. **Set up environment variables**
25
+
26
+ ```bash
27
+ npx hardhat vars set MNEMONIC
28
+
29
+ # Set your Infura API key for network access
30
+ npx hardhat vars set INFURA_API_KEY
31
+
32
+ # Optional: Set Etherscan API key for contract verification
33
+ npx hardhat vars set ETHERSCAN_API_KEY
34
+ ```
35
+
36
+ 3. **Compile and test**
37
+
38
+ ```bash
39
+ npm run compile
40
+ npm run test
41
+ ```
42
+
43
+ 4. **Deploy to local network**
44
+
45
+ ```bash
46
+ # Start a local FHEVM-ready node
47
+ npx hardhat node
48
+ # Deploy to local network
49
+ npx hardhat deploy --network localhost
50
+ ```
51
+
52
+ 5. **Deploy to Sepolia Testnet**
53
+
54
+ ```bash
55
+ # Deploy to Sepolia
56
+ npx hardhat deploy --network sepolia
57
+ # Verify contract on Etherscan
58
+ npx hardhat verify --network sepolia <CONTRACT_ADDRESS>
59
+ ```
60
+
61
+ 6. **Test on Sepolia Testnet**
62
+
63
+ ```bash
64
+ # Once deployed, you can run a simple test on Sepolia.
65
+ npx hardhat test --network sepolia
66
+ ```
67
+
68
+ ## 📁 Project Structure
69
+
70
+ ```
71
+ fhevm-hardhat-template/
72
+ ├── contracts/ # Smart contract source files
73
+ │ └── FHECounter.sol # Example FHE counter contract
74
+ ├── deploy/ # Deployment scripts
75
+ ├── tasks/ # Hardhat custom tasks
76
+ ├── test/ # Test files
77
+ ├── hardhat.config.ts # Hardhat configuration
78
+ └── package.json # Dependencies and scripts
79
+ ```
80
+
81
+ ## 📜 Available Scripts
82
+
83
+ | Script | Description |
84
+ | ------------------ | ------------------------ |
85
+ | `npm run compile` | Compile all contracts |
86
+ | `npm run test` | Run all tests |
87
+ | `npm run coverage` | Generate coverage report |
88
+ | `npm run lint` | Run linting checks |
89
+ | `npm run clean` | Clean build artifacts |
90
+
91
+ ## 📚 Documentation
92
+
93
+ - [FHEVM Documentation](https://docs.zama.ai/fhevm)
94
+ - [FHEVM Hardhat Setup Guide](https://docs.zama.ai/protocol/solidity-guides/getting-started/setup)
95
+ - [FHEVM Testing Guide](https://docs.zama.ai/protocol/solidity-guides/development-guide/hardhat/write_test)
96
+ - [FHEVM Hardhat Plugin](https://docs.zama.ai/protocol/solidity-guides/development-guide/hardhat)
97
+
98
+ ## 📄 License
99
+
100
+ This project is licensed under the BSD-3-Clause-Clear License. See the [LICENSE](LICENSE) file for details.
101
+
102
+ ## 🆘 Support
103
+
104
+ - **GitHub Issues**: [Report bugs or request features](https://github.com/zama-ai/fhevm/issues)
105
+ - **Documentation**: [FHEVM Docs](https://docs.zama.ai)
106
+ - **Community**: [Zama Discord](https://discord.gg/zama)
107
+
108
+ ---
109
+
110
+ **Built with ❤️ by the Zama team**
@@ -0,0 +1,46 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.24;
3
+
4
+ import {FHE, euint32, externalEuint32} from "@fhevm/solidity/lib/FHE.sol";
5
+ import {ZamaEthereumConfig} from "@fhevm/solidity/config/ZamaConfig.sol";
6
+
7
+ /// @title A simple FHE counter contract
8
+ /// @author fhevm-hardhat-template
9
+ /// @notice A very basic example contract showing how to work with encrypted data using FHEVM.
10
+ contract FHECounter is ZamaEthereumConfig {
11
+ euint32 private _count;
12
+
13
+ /// @notice Returns the current count
14
+ /// @return The current encrypted count
15
+ function getCount() external view returns (euint32) {
16
+ return _count;
17
+ }
18
+
19
+ /// @notice Increments the counter by a specified encrypted value.
20
+ /// @param inputEuint32 the encrypted input value
21
+ /// @param inputProof the input proof
22
+ /// @dev This example omits overflow/underflow checks for simplicity and readability.
23
+ /// In a production contract, proper range checks should be implemented.
24
+ function increment(externalEuint32 inputEuint32, bytes calldata inputProof) external {
25
+ euint32 encryptedEuint32 = FHE.fromExternal(inputEuint32, inputProof);
26
+
27
+ _count = FHE.add(_count, encryptedEuint32);
28
+
29
+ FHE.allowThis(_count);
30
+ FHE.allow(_count, msg.sender);
31
+ }
32
+
33
+ /// @notice Decrements the counter by a specified encrypted value.
34
+ /// @param inputEuint32 the encrypted input value
35
+ /// @param inputProof the input proof
36
+ /// @dev This example omits overflow/underflow checks for simplicity and readability.
37
+ /// In a production contract, proper range checks should be implemented.
38
+ function decrement(externalEuint32 inputEuint32, bytes calldata inputProof) external {
39
+ euint32 encryptedEuint32 = FHE.fromExternal(inputEuint32, inputProof);
40
+
41
+ _count = FHE.sub(_count, encryptedEuint32);
42
+
43
+ FHE.allowThis(_count);
44
+ FHE.allow(_count, msg.sender);
45
+ }
46
+ }
@@ -0,0 +1,17 @@
1
+ import { DeployFunction } from "hardhat-deploy/types";
2
+ import { HardhatRuntimeEnvironment } from "hardhat/types";
3
+
4
+ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
5
+ const { deployer } = await hre.getNamedAccounts();
6
+ const { deploy } = hre.deployments;
7
+
8
+ const deployedFHECounter = await deploy("FHECounter", {
9
+ from: deployer,
10
+ log: true,
11
+ });
12
+
13
+ console.log(`FHECounter contract: `, deployedFHECounter.address);
14
+ };
15
+ export default func;
16
+ func.id = "deploy_fheCounter"; // id required to prevent reexecution
17
+ func.tags = ["FHECounter"];