The fhEVM contracts were deployed on Ethererum Mainnet on Dec 30. This post will be updated to include Mainnet in the near future.
Set up a Project
Use the official template at zama-ai/fhevm-hardhat-template to create a project by clicking on โuse this templateโ button. Then pull it to local.
git clone <YOUR_REPO_URL>Then install necessary packages for development with a package manager like npm or pnpm. Iโll use pnpm in this post:
$ pnpm iThereโre caveats to make it work. First, the @fhevm/solidity package is evolves rapidly and may need to be updated to a newer version. In my case, itโs version 0.10.0. The same with @fhevm/hardhat-plugin plugin for Hardhat, which also need to be updated to pre-release version 0.3.0-4.
$ pnpm add @fhevm/solidity@0.10.0
$ pnpm add -D @fhevm/hardhat-plugin@0.3.0-4If youโre not install from the default npm registry, i.e. but from a mirror. You may found some packages are missing. I have to set the --registry https://registry.npmjs.org/ flag to install @nomicfoundation/slang version 1.3.1, which is a dependency of prettier-plugin-solidity.
Build and Test
Before going any further, you need to set up Hardhat variables for some API keys or a wallet key. Those are your MetaMask mnemonic code, INFURA endpoint API key to connect to Ethereum testnets like Sepolia.
$ pnpm hardhat vars set MNEMONIC
$ pnpm hardhat vars set INFURA_API_KEYBuild the Project
Now you can build the example contract with:
$ pnpm compile
> fhevm-hardhat-template@0.3.0-1 compile /Users/chuck/Projects/fhevm-quickstart
> cross-env TS_NODE_TRANSPILE_ONLY=true hardhat compile
Generating typings for: 3 artifacts in dir: types for target: ethers-v6
Successfully generated 26 typings!
Compiled 2 Solidity files successfully (evm target: cancun).
> fhevm-hardhat-template@0.3.0-1 postcompile /Users/chuck/Projects/fhevm-quickstart
> npm run typechain
> fhevm-hardhat-template@0.3.0-1 typechain
> cross-env TS_NODE_TRANSPILE_ONLY=true hardhat typechainRun Tests in Local
Thereโs two ways to run tests in local: with in-memory mocks or with local network mocks. The former is the default and the fastest.
$ pnpm test
> fhevm-hardhat-template@0.3.0-1 test /Users/chuck/Projects/fhevm-quickstart
> hardhat test
Counter
Counter.getCount() === 0
โ count should be zero after deployment
โ increment the counter by 1
โ decrement the counter by 1
FHECounter
โ encrypted count should be uninitialized after deployment
โ increment the counter by 1 (43ms)
โ decrement the counter by 1
FHECounterSepolia
This hardhat test suite can only run on Sepolia Testnet
- increment the counter by 1
6 passing (113ms)
1 pendingIn order to run on a local network, youโll need to start the Hardhat local network in a separate terminal.
$ pnpm hardhat node
Nothing to compile
No need to generate any newer typings.
deploying "FHECounter" (tx: 0x34e7da2e5ca6185dabe9514c39a2edcf20f6c16f4bbedd25c093d4a9dc665ebb)...: deployed at 0x32103E46a0edb5F5F3509A532308755D0F6F3149 with 605285 gas
FHECounter contract: 0x32103E46a0edb5F5F3509A532308755D0F6F3149
Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/
Accounts
========
Account #0: 0xD8C83D1C163aF2A69d77deeba0FD97FDA1C3b041 (10000 ETH)
Account #1: 0x92bE91002Eb44086CCee18cAD8e112c5c0dE6baA (10000 ETH)
Account #2: 0x47749FC0E32D821451f433b4E1Bff951eE371473 (10000 ETH)
Account #3: 0x479BE9b5Db5eBc457C6C01bC42a74c1DfBEebf0F (10000 ETH)
Account #4: 0x74EcD30B4a054800c029449110Cf9aA389753E7F (10000 ETH)
Account #5: 0x3d896DFea5Bf023111e0d3469C3BF608a57668E6 (10000 ETH)
Account #6: 0x4A98CBf4803275B31a6846000Cc5ab162E12bF5A (10000 ETH)
Account #7: 0xaE4f1D571bfcDA092D6CF60ef0554b127FC430Bb (10000 ETH)
Account #8: 0x5C3A21FE64B536B86f5e87395FF1971EBb40B502 (10000 ETH)
Account #9: 0xc3f59F5BaF08c22abFaB83e474663fE752BAedf9 (10000 ETH)
Account #10: 0xaF88a0c7D7D0850787f1F195410EE43293EF6A36 (10000 ETH)
Account #11: 0xbfED755917DceDa978432F2F26fa785200496f83 (10000 ETH)
Account #12: 0x2f939E5f0f5766bE195275a556F6939095da666F (10000 ETH)
Account #13: 0x5D5557ea284393D27082293B31e0dD49EDEb01D2 (10000 ETH)
Account #14: 0x65c11434fe5E6B3574F51682226dEe8ad07EB1CC (10000 ETH)
Account #15: 0xa446B10D9B10957e9Ba484A136f36abcc97b1fE0 (10000 ETH)
Account #16: 0x4F1C88990d05134F49a1760812556843f73DdfDC (10000 ETH)
Account #17: 0x95F9B794FBb50c4934C3158aCCa656B9fa7cd0C9 (10000 ETH)
Account #18: 0xf48e344C771e842b1C57809a59a9236E7859Be7b (10000 ETH)
Account #19: 0x2646d4Cd01D1eC281aDF1288e4610da6B5163fff (10000 ETH)And then run the tests with:
$ REPORT_GAS=true pnpm hardhat test --network localhost
Counter
Counter.getCount() === 0
โ count should be zero after deployment
โ increment the counter by 1
โ decrement the counter by 1
FHECounter
โ encrypted count should be uninitialized after deployment
โ increment the counter by 1 (54ms)
โ decrement the counter by 1 (45ms)
FHECounterSepolia
This hardhat test suite can only run on Sepolia Testnet
- increment the counter by 1
6 passing (223ms)
1 pending
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| Solidity and Network Configuration โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| Solidity: 0.8.27 ยท Optim: true ยท Runs: 800 ยท viaIR: false ยท Block: 30,000,000 gas โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| Methods โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| Contracts / Methods ยท Min ยท Max ยท Avg ยท # calls ยท usd (avg) โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| Counter ยท โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| decrement ยท - ยท - ยท 22,103 ยท 2 ยท - โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| increment ยท - ยท - ยท 43,819 ยท 4 ยท - โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| FHECounter ยท โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| decrement ยท - ยท - ยท 188,247 ยท 2 ยท - โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| increment ยท 210,595 ยท 210,607 ยท 210,601 ยท 4 ยท - โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| Deployments ยท ยท % of limit ยท โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| Counter ยท - ยท - ยท 152,763 ยท 0.5 % ยท - โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| FHECounter ยท - ยท - ยท 605,285 ยท 2 % ยท - โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท|ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| Key โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| โฏ Execution gas for this method does not include intrinsic gas overhead โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| โณ Cost was non-zero but below the precision setting for the currency display (see options) โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท
| Toolchain: hardhat โ
ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทThe REPORT_GAS environmental variable is set to also get the gas estimates for each test.
Deploy on Sepolia Testnet
If everything goes well so far, you may proceeds to deploy on Ethereum Sepolia testnet and verify the source code of the deployed contracts.
$ pnpm hardhat deploy --network sepolia
Generating typings for: 10 artifacts in dir: types for target: ethers-v6
Successfully generated 38 typings!
Compiled 7 Solidity files successfully (evm target: cancun).
deploying "FHECounter" (tx: 0x9a3970e5b63b94f0a559f5af9a0dcedd45fad4e39b1e1291a371cafc838282c9)...: deployed at 0x518C0365e6969a0Df58c3B9029de81ca1A8dfC2e with 605263 gas
FHECounter contract: 0x518C0365e6969a0Df58c3B9029de81ca1A8dfC2eThe verify doesnโt work. I find the following line in ./hardhat.config.ts need to be updated.
// This doesn't work
etherscan: {
apiKey: {
sepolia: vars.get("ETHERSCAN_API_KEY", ""),
},
},
// But this works
etherscan: {
apiKey: vars.get("ETHERSCAN_API_KEY", ""),
},pnpm hardhat verify --network sepolia 0x518C0365e6969a0Df58c3B9029de81ca1A8dfC2e
[INFO] Sourcify Verification Skipped: Sourcify verification is currently disabled. To enable it, add the following entry to your Hardhat configuration:
sourcify: {
enabled: true
}
Or set 'enabled' to false to hide this message.
For more information, visit https://v2.hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-verify#verifying-on-sourcify
Successfully submitted source code for contract
contracts/FHECounter.sol:FHECounter at 0x518C0365e6969a0Df58c3B9029de81ca1A8dfC2e
for verification on the block explorer. Waiting for verification result...
Successfully verified contract FHECounter on the block explorer.
https://sepolia.etherscan.io/address/0x518C0365e6969a0Df58c3B9029de81ca1A8dfC2e#codeNow you can check the deployed contract on BlockScout manually at https://eth-sepolia.blockscout.com/address/0x518C0365e6969a0Df58c3B9029de81ca1A8dfC2e.