Write FHEVM tests in Hardhat
In this section, you'll find everything you need to set up a new Hardhat project and start developing FHEVM smart contracts from scratch using the FHEVM Hardhat Plugin
Enabling the FHEVM Hardhat Plugin in your Hardhat project
Like any Hardhat plugin, the FHEVM Hardhat Plugin must be enabled by adding the following import
statement to your hardhat.config.ts
file:
import "@fhevm/hardhat-plugin";
Without this import, the Hardhat FHEVM API will not be available in your Hardhat runtime environment (HRE).
Accessing the Hardhat FHEVM API
The plugin extends the standard Hardhat Runtime Environment (or hre
in short) with the new fhevm
Hardhat module.
You can access it in either of the following ways:
import { fhevm } from "hardhat";
or
import * as hre from "hardhat";
// Then access: hre.fhevm
Encrypting Values Using the Hardhat FHEVM API
Suppose the FHEVM smart contract you want to test has a function called foo
that takes an encrypted uint32
value as input. The Solidity function foo
should be declared as follows:
function foo(externalEunit32 value, bytes calldata memory inputProof);
Where:
externalEunit32 value
: is abytes32
representing the encrypteduint32
bytes calldata memory inputProof
: is abytes
array representing the zero-knowledge proof of knowledge that validates the encryption
To compute these arguments in TypeScript, you need:
The address of the target smart contract
The signer’s address (i.e., the account sending the transaction)
Create a new encryted input
// use the `fhevm` API module from the Hardhat Runtime Environment
const input = fhevm.createEncryptedInput(contractAddress, signers.alice.address);
Add the value you want to encrypt.
input.add32(12345);
Perform local encryption.
const encryptedInputs = await input.encrypt();
Call the Solidity function
const externalUint32Value = encryptedInputs.handles[0];
const inputProof = encryptedInputs.proof;
const tx = await input.foo(externalUint32Value, inputProof);
await tx.wait();
Encryption examples
Decrypting values using the Hardhat FHEVM API
Suppose user Alice wants to decrypt a euint32
value that is stored in a smart contract exposing the following Solidity view
function:
function getEncryptedUint32Value() public view returns (euint32) { returns _encryptedUint32Value; }
For simplicity, we assume that both Alice’s account and the target smart contract already have the necessary FHE permissions to decrypt this value. For a detailed explanation of how FHE permissions work, see the initializeUint32()
function in DecryptSingleValue.sol.
Retrieve the encrypted value (a bytes32
handle) from the smart contract:
const encryptedUint32Value = await contract.getEncryptedUint32Value();
Perform the decryption using the FHEVM API:
const clearUint32Value = await fhevm.userDecryptEuint(
FhevmType.euint32, // Encrypted type (must match the Solidity type)
encryptedUint32Value, // bytes32 handle Alice wants to decrypt
contractAddress, // Target contract address
signers.alice, // Alice’s wallet
);
If either the target smart contract or the user does NOT have FHE permissions, then the decryption call will fail!
Supported Decryption Types
Use the appropriate function for each encrypted data type:
euintXXX
fhevm.userDecryptEuint(...)
ebool
fhevm.userDecryptEbool(...)
eaddress
fhevm.userDecryptEaddress(...)
Decryption examples
Last updated