Blockchain Privacy Technologies

fhEVM Quickstart

Chuck Chen
 · 
Categories: [Privacy]

fhEVM is now live on Ethereum Mainnet

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 i

Thereโ€™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-4

If 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_KEY

Build 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 typechain

Run 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 pending

In 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:  0x518C0365e6969a0Df58c3B9029de81ca1A8dfC2e

The 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#code

Now you can check the deployed contract on BlockScout manually at https://eth-sepolia.blockscout.com/address/0x518C0365e6969a0Df58c3B9029de81ca1A8dfC2e.