create-fhevm-example 1.3.2 → 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.
- 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 +228 -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,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,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,26 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-fhevm-example",
|
|
3
|
-
"version": "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",
|
|
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",
|
|
21
24
|
"help:create": "LOCAL_DEV=1 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",
|
|
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
28
|
"prepare": "git submodule update --init --recursive || true",
|
|
26
29
|
"prepublishOnly": "npm run build",
|