create-fhevm-example 1.3.2 → 1.4.1
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/contracts/advanced/BlindAuction.sol +255 -0
- package/contracts/advanced/EncryptedEscrow.sol +315 -0
- package/contracts/advanced/HiddenVoting.sol +231 -0
- package/contracts/advanced/PrivateKYC.sol +309 -0
- package/contracts/advanced/PrivatePayroll.sol +285 -0
- package/contracts/basic/decryption/PublicDecryptMultipleValues.sol +160 -0
- package/contracts/basic/decryption/PublicDecryptSingleValue.sol +142 -0
- package/contracts/basic/decryption/UserDecryptMultipleValues.sol +61 -0
- package/contracts/basic/decryption/UserDecryptSingleValue.sol +59 -0
- package/contracts/basic/encryption/EncryptMultipleValues.sol +72 -0
- package/contracts/basic/encryption/EncryptSingleValue.sol +44 -0
- package/contracts/basic/encryption/FHECounter.sol +54 -0
- package/contracts/basic/fhe-operations/FHEAdd.sol +51 -0
- package/contracts/basic/fhe-operations/FHEArithmetic.sol +99 -0
- package/contracts/basic/fhe-operations/FHEComparison.sol +116 -0
- package/contracts/basic/fhe-operations/FHEIfThenElse.sol +53 -0
- package/contracts/concepts/FHEAccessControl.sol +94 -0
- package/contracts/concepts/FHEAntiPatterns.sol +329 -0
- package/contracts/concepts/FHEHandles.sol +128 -0
- package/contracts/concepts/FHEInputProof.sol +104 -0
- package/contracts/gaming/EncryptedLottery.sol +298 -0
- package/contracts/gaming/EncryptedPoker.sol +337 -0
- package/contracts/gaming/RockPaperScissors.sol +213 -0
- package/contracts/openzeppelin/ERC7984.sol +85 -0
- package/contracts/openzeppelin/ERC7984ERC20Wrapper.sol +43 -0
- package/contracts/openzeppelin/SwapERC7984ToERC20.sol +110 -0
- package/contracts/openzeppelin/SwapERC7984ToERC7984.sol +48 -0
- package/contracts/openzeppelin/VestingWallet.sol +147 -0
- package/contracts/openzeppelin/mocks/ERC20Mock.sol +31 -0
- package/dist/scripts/commands/add-mode.d.ts.map +1 -0
- package/dist/scripts/{add-mode.js → commands/add-mode.js} +27 -61
- package/dist/scripts/commands/doctor.d.ts.map +1 -0
- package/dist/scripts/{doctor.js → commands/doctor.js} +2 -2
- package/dist/scripts/commands/generate-config.d.ts.map +1 -0
- package/dist/scripts/{generate-config.js → commands/generate-config.js} +3 -10
- package/dist/scripts/commands/generate-docs.d.ts.map +1 -0
- package/dist/scripts/{generate-docs.js → commands/generate-docs.js} +4 -3
- package/dist/scripts/commands/maintenance.d.ts.map +1 -0
- package/dist/scripts/{maintenance.js → commands/maintenance.js} +11 -10
- package/dist/scripts/index.js +14 -33
- package/dist/scripts/{builders.d.ts → shared/builders.d.ts} +2 -2
- package/dist/scripts/shared/builders.d.ts.map +1 -0
- package/dist/scripts/{builders.js → shared/builders.js} +49 -30
- package/dist/scripts/{config.d.ts → shared/config.d.ts} +0 -2
- package/dist/scripts/shared/config.d.ts.map +1 -0
- package/dist/scripts/{config.js → shared/config.js} +48 -59
- package/dist/scripts/shared/generators.d.ts +42 -0
- package/dist/scripts/shared/generators.d.ts.map +1 -0
- package/dist/scripts/{utils.js → shared/generators.js} +34 -271
- package/dist/scripts/shared/ui.d.ts.map +1 -0
- package/dist/scripts/{ui.js → shared/ui.js} +3 -2
- package/dist/scripts/{utils.d.ts → shared/utils.d.ts} +4 -27
- package/dist/scripts/shared/utils.d.ts.map +1 -0
- package/dist/scripts/shared/utils.js +236 -0
- package/fhevm-hardhat-template/.eslintignore +26 -0
- package/fhevm-hardhat-template/.eslintrc.yml +21 -0
- package/fhevm-hardhat-template/.github/workflows/main.yml +47 -0
- package/fhevm-hardhat-template/.github/workflows/manual-windows.yml +28 -0
- package/fhevm-hardhat-template/.github/workflows/manual.yml +28 -0
- package/fhevm-hardhat-template/.prettierignore +25 -0
- package/fhevm-hardhat-template/.prettierrc.yml +15 -0
- package/fhevm-hardhat-template/.solcover.js +4 -0
- package/fhevm-hardhat-template/.solhint.json +12 -0
- package/fhevm-hardhat-template/.solhintignore +3 -0
- package/fhevm-hardhat-template/.vscode/extensions.json +3 -0
- package/fhevm-hardhat-template/.vscode/settings.json +9 -0
- package/fhevm-hardhat-template/LICENSE +33 -0
- package/fhevm-hardhat-template/README.md +110 -0
- package/fhevm-hardhat-template/contracts/FHECounter.sol +46 -0
- package/fhevm-hardhat-template/deploy/deploy.ts +17 -0
- package/fhevm-hardhat-template/hardhat.config.ts +90 -0
- package/fhevm-hardhat-template/package-lock.json +10405 -0
- package/fhevm-hardhat-template/package.json +104 -0
- package/fhevm-hardhat-template/tasks/FHECounter.ts +184 -0
- package/fhevm-hardhat-template/tasks/accounts.ts +9 -0
- package/fhevm-hardhat-template/test/FHECounter.ts +104 -0
- package/fhevm-hardhat-template/test/FHECounterSepolia.ts +104 -0
- package/fhevm-hardhat-template/tsconfig.json +23 -0
- package/package.json +11 -8
- package/test/advanced/BlindAuction.ts +246 -0
- package/test/advanced/EncryptedEscrow.ts +295 -0
- package/test/advanced/HiddenVoting.ts +268 -0
- package/test/advanced/PrivateKYC.ts +382 -0
- package/test/advanced/PrivatePayroll.ts +253 -0
- package/test/basic/decryption/PublicDecryptMultipleValues.ts +254 -0
- package/test/basic/decryption/PublicDecryptSingleValue.ts +264 -0
- package/test/basic/decryption/UserDecryptMultipleValues.ts +107 -0
- package/test/basic/decryption/UserDecryptSingleValue.ts +97 -0
- package/test/basic/encryption/EncryptMultipleValues.ts +110 -0
- package/test/basic/encryption/EncryptSingleValue.ts +124 -0
- package/test/basic/encryption/FHECounter.ts +112 -0
- package/test/basic/fhe-operations/FHEAdd.ts +97 -0
- package/test/basic/fhe-operations/FHEArithmetic.ts +161 -0
- package/test/basic/fhe-operations/FHEComparison.ts +167 -0
- package/test/basic/fhe-operations/FHEIfThenElse.ts +97 -0
- package/test/concepts/FHEAccessControl.ts +154 -0
- package/test/concepts/FHEAntiPatterns.ts +111 -0
- package/test/concepts/FHEHandles.ts +156 -0
- package/test/concepts/FHEInputProof.ts +151 -0
- package/test/gaming/EncryptedLottery.ts +214 -0
- package/test/gaming/EncryptedPoker.ts +349 -0
- package/test/gaming/RockPaperScissors.ts +205 -0
- package/test/openzeppelin/ERC7984.ts +142 -0
- package/test/openzeppelin/ERC7984ERC20Wrapper.ts +71 -0
- package/test/openzeppelin/SwapERC7984ToERC20.ts +76 -0
- package/test/openzeppelin/SwapERC7984ToERC7984.ts +113 -0
- package/test/openzeppelin/VestingWallet.ts +89 -0
- package/dist/scripts/add-mode.d.ts.map +0 -1
- package/dist/scripts/builders.d.ts.map +0 -1
- package/dist/scripts/config.d.ts.map +0 -1
- package/dist/scripts/doctor.d.ts.map +0 -1
- package/dist/scripts/generate-config.d.ts.map +0 -1
- package/dist/scripts/generate-docs.d.ts.map +0 -1
- package/dist/scripts/help.d.ts +0 -9
- package/dist/scripts/help.d.ts.map +0 -1
- package/dist/scripts/help.js +0 -73
- package/dist/scripts/maintenance.d.ts.map +0 -1
- package/dist/scripts/ui.d.ts.map +0 -1
- package/dist/scripts/utils.d.ts.map +0 -1
- /package/dist/scripts/{add-mode.d.ts → commands/add-mode.d.ts} +0 -0
- /package/dist/scripts/{doctor.d.ts → commands/doctor.d.ts} +0 -0
- /package/dist/scripts/{generate-config.d.ts → commands/generate-config.d.ts} +0 -0
- /package/dist/scripts/{generate-docs.d.ts → commands/generate-docs.d.ts} +0 -0
- /package/dist/scripts/{maintenance.d.ts → commands/maintenance.d.ts} +0 -0
- /package/dist/scripts/{ui.d.ts → shared/ui.d.ts} +0 -0
|
@@ -0,0 +1,236 @@
|
|
|
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 by finding package.json */
|
|
139
|
+
function getRootDir() {
|
|
140
|
+
let dir = __dirname;
|
|
141
|
+
while (dir !== path.dirname(dir)) {
|
|
142
|
+
if (fs.existsSync(path.join(dir, "package.json"))) {
|
|
143
|
+
return dir;
|
|
144
|
+
}
|
|
145
|
+
dir = path.dirname(dir);
|
|
146
|
+
}
|
|
147
|
+
// Fallback
|
|
148
|
+
return path.resolve(__dirname, "../..");
|
|
149
|
+
}
|
|
150
|
+
/** Resolves template directory path */
|
|
151
|
+
function getTemplateDir() {
|
|
152
|
+
return path.join(getRootDir(), exports.TEMPLATE_DIR_NAME);
|
|
153
|
+
}
|
|
154
|
+
/** Copies directory recursively, excluding specified directories */
|
|
155
|
+
function copyDirectoryRecursive(source, destination, excludeDirs = exports.EXCLUDE_DIRS) {
|
|
156
|
+
if (!fs.existsSync(destination)) {
|
|
157
|
+
fs.mkdirSync(destination, { recursive: true });
|
|
158
|
+
}
|
|
159
|
+
const items = fs.readdirSync(source);
|
|
160
|
+
items.forEach((item) => {
|
|
161
|
+
const sourcePath = path.join(source, item);
|
|
162
|
+
const destPath = path.join(destination, item);
|
|
163
|
+
const stat = fs.statSync(sourcePath);
|
|
164
|
+
if (stat.isDirectory()) {
|
|
165
|
+
if (excludeDirs.includes(item)) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
copyDirectoryRecursive(sourcePath, destPath, excludeDirs);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
fs.copyFileSync(sourcePath, destPath);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
// =============================================================================
|
|
176
|
+
// Naming Utilities
|
|
177
|
+
// =============================================================================
|
|
178
|
+
function toKebabCase(str) {
|
|
179
|
+
return str
|
|
180
|
+
.replace(/([a-z])([A-Z])/g, "$1-$2")
|
|
181
|
+
.replace(/([0-9])([A-Z])/g, "$1-$2")
|
|
182
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2")
|
|
183
|
+
.toLowerCase();
|
|
184
|
+
}
|
|
185
|
+
function contractNameToExampleName(contractName) {
|
|
186
|
+
return toKebabCase(contractName);
|
|
187
|
+
}
|
|
188
|
+
function contractNameToTitle(contractName) {
|
|
189
|
+
return contractName
|
|
190
|
+
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
191
|
+
.replace(/([0-9])([A-Z])/g, "$1 $2")
|
|
192
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2");
|
|
193
|
+
}
|
|
194
|
+
function formatCategoryName(folderName) {
|
|
195
|
+
return folderName
|
|
196
|
+
.replace(/\bfhe\b/gi, "FHE")
|
|
197
|
+
.replace(/-/g, " ")
|
|
198
|
+
.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
199
|
+
}
|
|
200
|
+
function getContractName(contractPathOrContent) {
|
|
201
|
+
let content;
|
|
202
|
+
if (contractPathOrContent.includes("contract ") ||
|
|
203
|
+
contractPathOrContent.includes("pragma solidity")) {
|
|
204
|
+
content = contractPathOrContent;
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
const fullPath = contractPathOrContent.startsWith("/")
|
|
208
|
+
? contractPathOrContent
|
|
209
|
+
: path.join(getRootDir(), contractPathOrContent);
|
|
210
|
+
if (!fs.existsSync(fullPath)) {
|
|
211
|
+
const match = contractPathOrContent.match(/([^/]+)\.sol$/);
|
|
212
|
+
return match ? match[1] : null;
|
|
213
|
+
}
|
|
214
|
+
content = fs.readFileSync(fullPath, "utf-8");
|
|
215
|
+
}
|
|
216
|
+
const match = content.match(/^\s*contract\s+(\w+)(?:\s+is\s+|\s*\{)/m);
|
|
217
|
+
return match ? match[1] : null;
|
|
218
|
+
}
|
|
219
|
+
// =============================================================================
|
|
220
|
+
// Validation Functions
|
|
221
|
+
// =============================================================================
|
|
222
|
+
function validateExample(name) {
|
|
223
|
+
if (!config_1.EXAMPLES[name]) {
|
|
224
|
+
throw new Error(exports.ERROR_MESSAGES.UNKNOWN_EXAMPLE(name));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function validateCategory(name) {
|
|
228
|
+
if (!config_1.CATEGORIES[name]) {
|
|
229
|
+
throw new Error(exports.ERROR_MESSAGES.UNKNOWN_CATEGORY(name));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function validateDirectoryNotExists(dirPath) {
|
|
233
|
+
if (fs.existsSync(dirPath)) {
|
|
234
|
+
throw new Error(exports.ERROR_MESSAGES.DIR_EXISTS(dirPath));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -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,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,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"];
|