docs/solidity-guides/migration.md
FHEVM v0.9 introduces major architectural changes, including:
ZamaEthereumConfig replacing SepoliaConfigThis guide explains what changed and how to migrate your project smoothly.
Before diving into migration steps, it’s important to understand the main breaking change: public decryption is no longer handled by a Zama Oracle, but by your dApp’s off-chain logic.
In FHEVM v0.8, the decryption process relies on a trusted Oracle to relay the decryption request and proof between the dApp and the Zama Key Management System (KMS). This approach abstracts the complexity but introduces an external dependency.
Decryption Steps:
| Step | Component | Action |
|---|---|---|
| 1. | dApp (Solidity) | Calls FHE.requestDecryption() to signal a need for clear data. |
| 2. | Oracle | Listens for the on-chain decryption request event. |
| 3. | Oracle (Off-chain) | Performs the publicDecryption with the Zama KMS, retrieving the clear values and the decryption proof. |
| 4. | Oracle | Calls the user-specified dApp callback Solidity function with the clear values and the associated proof. |
| 5. | dApp (Solidity Callback) | Calls FHE.verifySignatures() to verify the authenticity of the clear values using the provided proof. |
Key takeaway for v0.8: The Oracle is the trusted intermediary responsible for performing the off-chain decryption and submitting the result back to the dApp contract.
The FHEVM v0.9 architecture shifts to a self-relaying model, empowering the dApp client (the user) to execute the off-chain decryption and re-submission. This decentralizes the process and removes the dependency on a general-purpose Oracle.
Example Scenario: Checking a Player's Encrypted Score
Consider a Game contract where Alice's final score is stored encrypted on-chain. Alice needs to prove her clear score to claim a reward.
| Step | Component | Action |
|---|---|---|
| 1. | Game Contract (Solidity) | An on-chain function is called to make Alice's encrypted score publicly decryptable. |
| 2. | Alice (Client/Off-chain) | Alice fetches the publicly decryptable encrypted score from the Game contract. |
| 3. | Alice (Client/Off-chain) | Alice or any third-party service uses the @zama-fhe/relayer-sdk to call the off-chain publicDecrypt function. This returns the clear score value and a proof of decryption. |
| 4. | Alice (Client/On-chain) | Alice calls a function on the Game contract with the decrypted clear score and the proof. |
| 5. | Game Contract (Solidity) | The contract calls FHE.verifySignatures() to verify the score's validity using the provided proof. |
| 6. | Game Contract (Solidity) | If the score is valid, the contract executes the game logic (e.g., distributing Alice's prize). |
Key takeaway for FHEVM v0.9: Decryption is a user-driven, off-chain process. The dApp client is responsible for off-chain decryption, fetching the proof, and relaying the result back on-chain for verification.
Why this matters: If your dApp previously relied on the Oracle, you must rewrite your decryption flow. The migration steps below guide you through this change.
Here is a brief, ordered list of the steps required to successfully migrate your project to FHEVM v0.9:
SepoliaConfig with the unified ZamaEthereumConfig.@zama-fhe/relayer-sdk and FHE.verifySignatures().Follow these steps for a smooth transition to FHEVM v0.9:
Ensure your project uses the latest versions of the FHEVM development tools.
| Dependency | Minimum Required Version | Notes |
|---|---|---|
@fhevm/solidity | v0.9.1 | Contains the updated FHE library contracts. |
@zama-fhe/relayer-sdk | v0.3.0-5 | Crucial for v0.9: Enables the new self-relaying decryption model. |
@fhevm/hardhat-plugin | v0.3.0-1 | Latest tooling support for development and deployment. |
The Solidity contracts now use a unified configuration contract defined in @fhevm/solidity/config/ZamaConfig.sol.
SepoliaConfig contract is now removed.ZamaEthereumConfig contract. This change simplifies future cross-chain compatibility.The new ZamaEthereumConfig abstract contract now dynamically resolves the FHEVM host addresses according to the block.chainid.
Replace:
import { SepoliaConfig } from "@fhevm/solidity/config/ZamaConfig.sol";
With:
import { ZamaEthereumConfig } from "@fhevm/solidity/config/ZamaConfig.sol";
You can read more about Configuration on the dedicated page.
The Zama public decryption Oracle is discontinued. The following functions are no more available in the FHE Solidity library:
FHE.loadRequestedHandlesFHE.requestDecryptionWithoutSavingHandlesFHE.requestDecryptionDue to fundamental changes in the FHEVM implementation and underlying infrastructure:
The most significant change is the discontinuation of the Zama Oracle. This requires substantial adjustments to how your dApp handles decryption on-chain.
| Aspect | FHEVM v0.8 (Old Logic) | FHEVM v0.9 (New Logic) |
|---|---|---|
| Decryption Handler | Zama Oracle actively listens for requests and submits the result. | dApp Client/User performs the off-chain decryption (self-relaying). |
| Solidity Function | Used FHE.requestDecryption(). | You will now create custom functions that accept the decrypted value and the proof. |
| Client-Side Tool | N/A | Use @zama-fhe/relayer-sdk to perform the publicDecrypt and obtain the proof. |
Action: Thoroughly review your Solidity code, dApp logic, and backend services. Any code relying on the external Oracle must be rewritten to implement the self-relaying workflow using the
@zama-fhe/relayer-sdk.
The following code examples illustrate the new public decryption logic introduced in v0.9. This new workflow uses the combination of:
FHE.makePubliclyDecryptablepublicDecrypt using the @zama-fhe/relayer-sdk or the FHEVM Hardhat PluginFHE.checkSignaturesFHE.makePubliclyDecryptable, and its cleartext value is subsequently verified on-chain using FHE.checkSignatures after being fetched off-chain via publicDecrypt.FHE.checkSignatures function ensures the authenticity of multiple cleartext values derived from multiple encrypted on-chain cypher texts.