FHEVM Hardhat Plugin v2
npm install @fhevm/hardhat-plugin

π Read white paper | π Documentation | π Community support | π FHE resources by Zama


Hardhat plugin for developing and testing FHEVM contracts.
- The FHEVM Hardhat Template
- Quickstart Tutorial
For additional documentation and resources:
- Setting up Hardhat
- FHEVM Hardhat Plugin Development Guide
- FHEVM Examples
This Hardhat plugin relies on the following peer dependencies to function correctly.
- @fhevm/mock-utils
- @fhevm/solidity
- @zama-fhe/relayer-sdk
- @nomicfoundation/hardhat-ethers
- ethers
- hardhat
If you're using npm version 7 or later, these peer dependencies will be automatically installed when you install this
plugin β no additional action is required.
If you're using a package manager that does not automatically install peer dependencies (like pnpm or npm <7) then
you'll need to add them manually to your package.
``sh`
npm install --save-dev @fhevm/hardhat-plugin
And register the plugin in your hardhat.config.js:
`ts`
// Typescript
import "@fhevm/hardhat-plugin";
To generate encrypted inputs or decrypt FHE data on Ethereum mainnet, you need a Zama API key. To configure it in the
FHEVM Hardhat Plugin, run:
`sh`
npx hardhat vars set ZAMA_FHEVM_API_KEY
To verify the Zama API key is properly set up:
`sh`
npx hardhat vars get ZAMA_FHEVM_API_KEY
In this guide, we'll walk through a simple Hello World example using FHEVM (Fully Homomorphic Encryption). The objective
is to build a Solidity smart contract that:
- Validates and stores an encrypted input value a
- Validates and stores a second encrypted input value b
- Computes the FHE sum of a and b, storing the result as aplusb
- Reads and decrypts the encrypted result aplusb
Letβs get started!
Create and navigate into a new project folder:
`sh`
mkdir hello_fhevm
cd ./hello_fhevm
Install Hardhat and the FHEVM Hardhat plugin as development dependencies:
`sh`
npm install --save-dev hardhat
npm install --save-dev ethers
npm install --save-dev @nomicfoundation/hardhat-chai-matchers
npm install --save-dev @nomicfoundation/hardhat-ethers
npm install --save-dev @nomicfoundation/hardhat-network-helpersWarning: @nomicfoundation/hardhat-chai-matchers requires v4
npm install --save-dev chai@^4.2.0Install Typescript related packages required to run Hardhat using Typescript
npm install --save-dev typescript
npm install --save-dev ts-node
npm install --save-dev @types/mocha
Install FHEVM related packaged as development dependencies:
`sh`
npm install --save-dev @fhevm/hardhat-plugin
First, create a contracts folder to hold your Solidity code:
`sh`
mkdir contracts
cd ./contracts
Then, inside the contracts directory, create a new Solidity file named APlusB.sol with the following content:
`solidity
// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity ^0.8.24;
import { FHE, euint8, externalEuint8 } from "@fhevm/solidity/lib/FHE.sol";
import { ZamaEthereumConfig } from "@fhevm/solidity/config/ZamaConfig.sol";
contract APlusB is ZamaEthereumConfig {
euint8 private _a;
euint8 private _b;
euint8 private _aplusb;
constructor() {}
function setA(externalEuint8 inputA, bytes calldata inputProof) external {
_a = FHE.fromExternal(inputA, inputProof);
FHE.allowThis(_a);
}
function setB(externalEuint8 inputB, bytes calldata inputProof) external {
_b = FHE.fromExternal(inputB, inputProof);
FHE.allowThis(_b);
}
function computeAPlusB() external {
_aplusb = FHE.add(_a, _b);
FHE.allowThis(_aplusb);
FHE.allow(_aplusb, msg.sender);
}
function aplusb() public view returns (euint8) {
return _aplusb;
}
}
`
In the project root directory hello_fhevm, create a new Typescript file named hardhat.config.ts with the following
content:
`ts
// Add the FHEVM Hardhat plugin here!
import "@fhevm/hardhat-plugin";
import "@nomicfoundation/hardhat-chai-matchers";
import "@nomicfoundation/hardhat-ethers";
import { HardhatUserConfig } from "hardhat/config";
const config: HardhatUserConfig = {
solidity: {
version: "0.8.28",
settings: {
// β οΈ FHEVM requires at least the "cancun" EVM version
evmVersion: "cancun",
},
},
};
export default config;
`
`sh`
npx hardhat compile
First, from the project root directory, create a test folder to hold your test code:
`sh`
mkdir test
cd ./test
Then, inside the test directory, create a new Solidity file named APlusB.ts with the following content:
`ts
import { FhevmType } from "@fhevm/hardhat-plugin";
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { expect } from "chai";
import { ethers } from "ethers";
import * as hre from "hardhat";
async function deployAPlusBFixture(account: HardhatEthersSigner) {
const contractFactory = await hre.ethers.getContractFactory("APlusB");
const contract = await contractFactory.connect(account).deploy();
await contract.waitForDeployment();
return contract as any as ethers.Contract;
}
describe("APlusB", function () {
let aplusbContract: ethers.Contract;
let aplusbContractAddress: string;
before(async function () {
const [alice] = await hre.ethers.getSigners();
aplusbContract = await deployAPlusBFixture(alice);
aplusbContractAddress = await aplusbContract.getAddress();
await hre.fhevm.assertCoprocessorInitialized(aplusbContract, "APlusB");
});
it("uint8: add 80 to 123 should equal 203", async function () {
const [alice] = await hre.ethers.getSigners();
// 1. Validates and Stores value 'a'
// Create the encrypted input
const inputA = hre.fhevm.createEncryptedInput(aplusbContractAddress, alice.address);
inputA.add8(80);
const encryptedInputA = await inputA.encrypt();
// Call the contract with the encrypted value a
const encryptedA = encryptedInputA.handles[0];
const proofA = encryptedInputA.inputProof;
let tx = await aplusbContract.setA(encryptedA, proofA);
await tx.wait();
// 2. Validates and Stores value 'b'
// Create the encrypted input
const inputB = hre.fhevm.createEncryptedInput(aplusbContractAddress, alice.address);
inputB.add8(123);
const encryptedInputB = await inputB.encrypt();
// Call the contract with the encrypted value b
const encryptedB = encryptedInputB.handles[0];
const proofB = encryptedInputB.inputProof;
tx = await aplusbContract.setB(encryptedB, proofB);
await tx.wait();
// 3. Computes the FHE sum of a and b, storing the result as aplusb on chain
tx = await aplusbContract.computeAPlusB();
await tx.wait();
// 4. Reads the encrypted result aplusb = a + b
const encryptedAPlusB = await aplusbContract.aplusb();
// 5. Decrypts aplusb
const clearAPlusB = await hre.fhevm.userDecryptEuint(
FhevmType.euint8,
encryptedAPlusB,
aplusbContractAddress,
alice as unknown as ethers.Signer,
);
expect(clearAPlusB).to.eq(80 + 123);
});
});
`
From the project root directory, run the test by executing the following hardhat command:
`sh``
npx hardhat test
For more FHEVM examples and detailed documentation please go here