FHEVM Solidity 开发指南:用全同态加密构建机密智能合约的完整入门路径 📅 发布时间:2026/9/12 20:31:54 👁 浏览次数: FHEVM Solidity 开发指南用全同态加密构建机密智能合约的完整入门路径【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm导读本文是 fhevm 仓库 Solidity Guides 的完整技术导读与实战手册面向希望使用 Zama FHEVM 库在 Solidity 中编写机密智能合约的开发者。通过本文你将掌握 FHEVM 的加密类型体系ebool、euintXX、eaddress、FHE 运算符算术/位运算/比较/三元选择、ZamaEthereumConfig环境配置、加密输入与 ZKPoK 验证、ACL 权限模型以及基于 Hardhat / Foundry 的本地开发测试路径从而把普通合约改造成可以直接在密文上运算、全程不上链解密的机密合约。1. FHEVM Solidity 开发全景Zama 的 FHEVMFully Homomorphic Encryption Virtual Machine是一套将全同态加密能力接入区块链应用的全栈框架。在 Solidity 侧它表现为一个 Solidity 库FHE加上一套预构建的配置合约让智能合约可以直接在加密数据上执行运算而无需在链上解密任何中间值。Solidity Guides 系列文档按如下路径组织本文沿此骨架展开入门What is FHEVM Solidity 讲解核心概念与特性Quick Start Tutorial 提供 30 分钟从零到一的实战教程Setup Hardhat → 编写简单合约 → 改造成 FHEVM 合约 → 编写并运行测试。合约开发配置Configuration、支持的加密类型、句柄Handles、加密类型操作、加密输入、ACL 访问控制、逻辑控制、FHEVM API 参考。开发环境Hardhat 插件指南 与 Foundry 指南 覆盖两类主流工具链的搭建、测试与部署HCUHandle 计算单元 与 合约改造指南 面向进阶场景。阅读起点建议若熟悉 FHE 概念可直达 What is FHEVM Solidity若想直接动手从 Quick Start Tutorial 开始需要深挖 API 时随时查阅 FHEVM API reference。2. 核心特性一览What is FHEVM Solidity 将 FHEVM 合约库的关键能力归纳为六大部分它们是后续所有教程的共同基础。2.1 配置与初始化使用 FHEVM 的合约必须完成三件事环境设置导入并继承环境特定的配置合约如ZamaEthereumConfig从而拿到对应网络的 FHEVM 基础设施地址Relayer 配置为密码学操作配置安全的 relayer 访问面向用户解密等链下协作场景初始化检查使用FHE.isInitialized校验加密变量在使用前已被正确初始化。详见 Configuration 章节。2.2 加密数据类型FHEVM 提供了与 Solidity 原生类型对齐的加密类型布尔ebool、无符号整数euint8/euint16/euint32/euint64/euint128/euint256、地址eaddress以及用于接收链下加密输入的externalEbool/externalEaddress/externalEuintXX。所有加密值在链上统一表示为密文句柄ciphertext handle详见 加密类型详解。2.3 类型转换FHE库提供了三类转换函数FHE.asEbool将加密整数转为加密布尔、FHE.asEuintX将明文值转为加密类型、FHE.asEaddress将明文地址转为加密地址详见 Casting and trivial encryption。2.4 机密计算FHEVM 支持对加密值进行符号化执行算术FHE.add、FHE.sub、FHE.mul、FHE.min、FHE.max、FHE.neg、FHE.div、FHE.rem注意div/rem仅支持明文除数位运算FHE.and、FHE.or、FHE.xor、FHE.not、FHE.shl、FHE.shr、FHE.rotl、FHE.rotr比较FHE.eq、FHE.ne、FHE.lt、FHE.le、FHE.gt、FHE.ge高级FHE.select基于加密条件做分支选择FHE.randEuintX提供链上随机数生成。运算符的完整语义见 Operations on encrypted types条件分支逻辑见 Conditional logic in FHE随机数生成见 Generate Random Encrypted Numbers。2.5 访问控制机制FHEVM 通过链上 ACL访问控制列表强制访问权限持久访问FHE.allow、FHE.allowThis授予对密文的长期权限瞬时访问FHE.allowTransient仅对当前交易生效校验FHE.isSenderAllowed确保只有授权实体能使用密文持久公开解密FHE.makePubliclyDecryptable/FHE.isPubliclyDecryptable让某密文永久可公开解密用户解密委托合约可用FHE.delegateUserDecryption委托用户解密权EOA 则直接调用 ACL 的IACL.delegateForUserDecryption两种模式不可互换见 User decryption delegation账户拒绝名单FHE.isAccountDenied检查某账户是否被禁止操作加密值。完整机制见 ACL 章节。3. 环境配置从ZamaConfig.sol到ZamaEthereumConfig要让合约具备加密计算能力第一步是完成fhevm环境配置。Configuration 文档给出了标准化做法直接继承预构建的配置合约把精力放在业务逻辑上。3.1 配置合约解决了什么问题FHEVM 基础设施由多个合约组成ACL、FHEVMExecutor、KMSVerifier跨不同网络Ethereum 主网、Sepolia 测试网、本地 Hardhat 环境地址各不相同。手工维护这些地址极易出错因此fhevm包提供了集中封装ZamaConfig一个 Solidity 库暴露获取 FHEVM 配置结构体与各网络合约地址的函数在仓库中位于 config/ZamaConfig.sol。它将各网络基础设施地址封装进单一结构体CoprocessorConfig。ZamaEthereumConfig可继承的合约构造函数中自动调用FHE.setCoprocessor并以库提供的对应网络配置完成 FHEVM 协处理器装配源码见 config/ZamaConfig.sol 的abstract contract ZamaEthereumConfig。继承它即可让合约自动接线到目标网络的 FHEVM 合约杜绝地址管理错误。值得注意的是InputVerifier不在继承的配置范围内它在运行时通过FHEVMExecutor.getInputVerifierAddress()动态解析——这既避免了静态地址的耦合也保证了升级灵活性。3.2 最小配置示例// SPDX-License-Identifier: BSD-3-Clause-Clear pragma solidity ^0.8.24; import { ZamaEthereumConfig } from fhevm/solidity/config/ZamaConfig.sol; contract MyERC20 is ZamaEthereumConfig { constructor() { // Additional initialization logic if needed } }继承ZamaEthereumConfig后FHE库即被正确装配后续所有加密操作均可在本合约内直接调用。3.3 使用isInitialized做初始化检查FHE.isInitialized(T v) internal pure returns (bool)用于校验加密变量是否已被正确初始化防止未初始化值引发意外行为。它在 FHE.sol 中对ebool、euint8、euint16、euint32、euint64、euint128、eaddress、euint256逐一重载实现。require(FHE.isInitialized(counter), Counter not initialized!);典型应用场景在状态变量读取或参与运算前做断言把“加密值未初始化”这类逻辑错误在入口处拦截。4. 加密类型体系ebool/euintXX/eaddressSupported types 详细介绍了FHE库的加密整数类型系统。4.1 类型表与支持的运算符类型位宽支持的运算符别名含支持的运算符Ebool2and, or, xor, eq, ne, not, select, randEuint88add, sub, mul, div, rem, and, or, xor, shl, shr, rotl, rotr, eq, ne, ge, gt, le, lt, min, max, neg, not, select, rand, randBoundedEuint1616同上Euint3232同上Euint6464同上Euint128128同上Euint160160eq, ne, selectEaddress——eaddress是euint160的别名用于加密的以太坊地址Euint256256and, or, xor, shl, shr, rotl, rotr, eq, ne, neg, not, select, rand, randBounded4.2 关键语义与原生整数类似、但作用于 FHE 密文加密整数行为上贴近 Solidity 原生整数但底层数据是密文。算术运算是 unchecked 的e(u)int类型的算术运算溢出时自动回绕wrap around而不是 revert。这是有意设计——通过错误检测会泄露操作数信息从而破坏机密性。除法的明文限制div和rem只有在右操作数rhs是明文值时才受支持把加密值作为rhs会触发 panic。这一限制保证了当前框架下计算的安全与正确。扩展空间TFHE-rs库提供了更高精度的整数类型可按需加入到 fhevm 中。5. 句柄Handles密文的链上身份Handles 是理解 FHEVM 数据模型的关键文档。每一个链上加密值euint8、ebool、eaddress等都由一个32 字节的句柄引用FHE 操作输入输出句柄ACL 也按句柄粒度强制执行。5.1 四个容易混淆的概念术语是什么存在于何处明文Plaintext真实的明文值如数字42是decrypt(...)的返回值链下仅在授权解密后可得密文CiphertextFHE 产生的加密字节串协处理器存储并计算的对象可随时重随机化而不改变明文链下随协处理器保存句柄Handle指向某个特定明文, 密文对的 32 字节链上标识符Solidity 代码持有和传递的就是它链上计算Computation产生某个句柄的 FHE 操作序列如FHE.add(a, b)概念层面并非实际存储协议保证的是句柄与明文之间的关系而不保证句柄与密文、句柄与产生它的计算之间的任何对应关系。5.2 核心原则句柄是不透明的把句柄当作“名签”而不是“东西本身”。句柄字节不包含任何关于它是如何生成、背后是哪个密文的信息——你只能通过解密读出它指向的明文。不过句柄可以当作普通bytes32使用用/!比较、存储、打日志ACL 本身就是这么工作的。5.3 可以依赖与不能依赖的规则协议给出的唯一铁律是如果两个句柄相等它们指向相同的明文。其镜像命题同样成立如果两个明文不同它们的句柄必然不同。除此之外一律不可假设可以依赖不能依赖相等句柄 → 相等明文不同句柄 → 不同明文不同明文 → 不同句柄相等明文 → 相等句柄相等句柄 → 两者由同一计算产生相等句柄 → 底层是同一密文协议可能对某些“相等明文”的计算产生相等句柄对另一些产生不同句柄——跨区块、跨链、密文重随机化之后、或未来优化之下都可能变化。合约必须两种情况都能正常工作。5.4 常见误区误区一假定“相同操作 相同输入 → 相同句柄”。当前协议把上一个区块的哈希混入句柄的构建过程因此同一计算在不同区块已经会产生不同句柄反之假定不同操作必然产生不同句柄也可能在协议未来把某些计算优化为同一句柄时出错// ❌ 不要依赖 h3 h4也不要依赖 h3 ! h4 euint64 h3 FHE.add(h1, h2); euint64 h4 FHE.add(h1, h2);误区二混用来自不同来源的句柄。从其他链桥接过来的句柄或通过FHE.fromExternal(...)链下构造并带入的句柄即使编码了相同明文也不保证与链上计算产生的句柄相等。如果确实需要知道两个加密值明文是否相等请使用 FHE 运算符——FHE.eq返回一个ebool当且仅当底层值匹配时解密为trueebool isEqual FHE.eq(a, b);6. 加密类型操作算术、位运算、比较与随机数Operations on encrypted types 列出了FHE库支持的全部操作。6.1 算术运算名称函数名符号类型加FHE.add二元减FHE.sub-二元乘FHE.mul*二元除明文除数FHE.div二元余明文除数FHE.rem二元取负FHE.neg-一元最小值FHE.min二元最大值FHE.max二元div与rem目前仅支持明文除数。6.2 位运算名称函数名符号类型按位与FHE.and二元按位或FHE.or\|二元按位异或FHE.xor^二元按位非FHE.not~一元右移FHE.shr二元左移FHE.shl二元循环右移FHE.rotr二元循环左移FHE.rotl二元移位运算有一个与 Solidity 原生不同的重要语义FHE.shr/FHE.shl的第一个操作数可以是任意euintX第二个操作数接受uint8或euint8但第二个操作数永远按第一个操作数的位数取模。例如FHE.shr(euint64 x, 70)等价于FHE.shr(euint64 x, 6)因为70 % 64 6。这与 Solidity 原生移位不同——原生没有中间取模步骤任何uint64右移 70 位会直接得到 0。6.3 比较运算名称函数名类型等于FHE.eq二元不等于FHE.ne二元大于等于FHE.ge二元大于FHE.gt二元小于等于FHE.le二元小于FHE.lt二元6.4 三元选择与随机数FHE.select三元操作根据加密条件从两个加密值中选择一个select(ebool control, a, b)是 FHE 中实现条件分支的基石FHE.sol 中对所有加密类型均有重载。FHE.randEuintX()完全链上生成密码学安全的随机数详情见 Random Encrypted Numbers。6.5 最佳实践① 选择合适大小的加密类型以节省 Gas。选择能容纳数据的最小加密类型例如小数字0-255用euint8而不是euint256// ❌ 坏用大类型装小数字浪费 Gas euint64 age FHE.asEuint128(25); // age 永远不超过 255 euint64 percentage FHE.asEuint128(75); // percentage 取值 0-100 // ✅ 好使用合适大小的类型 euint8 age FHE.asEuint8(25); // age 适合 8 位 euint8 percentage FHE.asEuint8(75); // percentage 适合 8 位② 尽量使用标量操作数以节省 Gas。部分 FHE 运算符存在两个版本全密文句柄版以及某一操作数是未加密标量的版本。能用标量版本就用标量版本能节省大量 Gas// ❌ 这个写法贵得多 x FHE.add(x, FHE.asEuint(42)); // ✅ 这个写法便宜得多且加密结果完全相同 x FHE.add(x, 42);③ 警惕 FHE 算术溢出。FHE 算术运算符可能溢出实现 FHEVM 合约时必须考虑这一点。例如为加密 ERC20 写一个带加密totalSupply的 mint 函数下面的代码对溢出是脆弱的function mint(externalEuint32 encryptedAmount, bytes calldata inputProof) public { euint32 mintedAmount FHE.fromExternal(encryptedAmount, inputProof); totalSupply FHE.add(totalSupply, mintedAmount); balances[msg.sender] FHE.add(balances[msg.sender], mintedAmount); FHE.allowThis(balances[msg.sender]); FHE.allow(balances[msg.sender], msg.sender); }用FHE.select在溢出时取消铸造即可修复function mint(externalEuint32 encryptedAmount, bytes calldata inputProof) public { euint32 mintedAmount FHE.fromExternal(encryptedAmount, inputProof); euint32 tempTotalSupply FHE.add(totalSupply, mintedAmount); ebool isOverflow FHE.lt(tempTotalSupply, totalSupply); totalSupply FHE.select(isOverflow, totalSupply, tempTotalSupply); euint32 tempBalanceOf FHE.add(balances[msg.sender], mintedAmount); balances[msg.sender] FHE.select(isOverflow, balances[msg.sender], tempBalanceOf); FHE.allowThis(balances[msg.sender]); FHE.allow(balances[msg.sender], msg.sender); }注意这里只检查了totalSupply的溢出、没有单独检查balances[msg.sender]——因为totalSupply是所有用户余额之和只要totalSupply不溢出单个用户的balances[msg.sender]就不可能溢出。7. 类型转换平凡加密与加密类型互转Casting and trivial encryption 将转换操作归为两类。7.1 平凡加密Trivial encryption把明文值包装成与 FHE 运算符兼容的密文格式。虽然数据处于密文格式但在链上仍是公开可见的适合做公开值与私密值之间的混合运算euint64 value64 FHE.asEuint64(7262); // 平凡加密一个 uint64 ebool valueBool FHE.asEbool(true); // 平凡加密一个布尔值平凡加密只是让数据兼容 FHE 操作除非显式加密否则数据在链上仍是公开的。7.2 加密类型之间的转换用于把一种加密类型重解释或转换为另一种例如euint32→euint64。注意转换方向的信息保持性从小类型转大类型如euint32→euint64保留全部信息从大类型转小类型如euint64→euint32会截断并丢失信息。euint32 value32 FHE.asEuint32(value64); // 转为 euint32 ebool valueBool FHE.asEbool(value32); // 转为 ebool7.3 转换函数总表转换类型函数输入类型输出类型平凡加密FHE.asEuintXX(x)uintXeuintXFHE.asEbool(x)booleboolFHE.asEaddress(x)addresseaddress类型间转换FHE.asEuintXX(x)euintXX/ebooleuintYYFHE.asEbool(x)euintXXebool8. 加密输入密文入链与 ZKPoK 验证Encrypted Inputs 讲解了 FHEVM 的核心能力之一——让用户把加密数据安全地推送到链上同时保证机密性与完整性。8.1 什么是加密输入加密输入是用户以密文形式提交的数据值伴随零知识知识证明ZKPoK在不泄露明文的前提下验证加密数据的有效性。三个关键特征机密性数据用公共 FHE 密钥加密只有授权方才能解密或处理ZKPoK 验证每个加密输入都附带证明验证用户确实知道密文对应的明文防止重放攻击或滥用高效打包一笔交易的所有输入被打包进单一密文按用户定义顺序从而优化零知识证明的大小与生成成本。8.2 函数参数的两个组成部分接受加密输入的函数包含两类参数externalEbool/externalEaddress/externalEuintXX指加密参数在证明中的索引代表一个特定的加密输入句柄bytes包含密文与用于验证的零知识证明。function exampleFunction( externalEbool param1, externalEuint64 param2, externalEuint8 param3, bytes calldata inputProof ) public { // Function logic here }这里param1、param2、param3分别是ebool、euint64、euint8的加密输入inputProof包含验证它们真实性的 ZKPoK。8.3 使用 Hardhat 生成加密输入下面用 Alice 的地址创建加密输入并提交交易import { fhevm } from hardhat; const input fhevm.createEncryptedInput(contract.address, signers.alice.address); input.addBool(canTransfer); // 索引 0 input.add64(transferAmount); // 索引 1 input.add8(transferType); // 索引 2 const encryptedInput await input.encrypt(); const externalEboolParam1 encryptedInput.handles[0]; const externalEuint64Param2 encryptedInput.handles[1]; const externalEuint8Param3 encryptedInput.handles[2]; const inputProof encryptedInput.inputProof; tx await myContract .connect(signers.alice) exampleFunction(bytes32,bytes32,bytes32,bytes) ; await tx.wait();输入顺序开发者可以自由设计函数参数顺序TypeScript 中构造加密输入的顺序与 Solidity 函数参数顺序之间没有强制对应关系。8.4 在合约中验证加密输入合约通过FHE.fromExternal内部对应FHE.asEuintXX/FHE.asEbool/FHE.asEaddress的验证逻辑见 FHE.sol 的系列重载验证输入并转换为对应的加密类型function myExample(externalEuint64 encryptedAmount, externalEbool encryptedToggle, bytes calldata inputProof) public { // 验证并转换加密输入 euint64 amount FHE.fromExternal(encryptedAmount, inputProof); ebool toggleFlag FHE.fromExternal(encryptedToggle, inputProof); // 更新用户的加密余额 balances[msg.sender] FHE.add(balances[msg.sender], amount); // 切换用户的加密标志位 userFlags[msg.sender] FHE.not(toggleFlag); // FHE 权限与后续业务逻辑 ... } // 读取用户加密余额 function getEncryptedBalance() public view returns (euint64) { return balances[msg.sender]; } // 读取用户加密标志位 function getEncryptedFlag() public view returns (ebool) { return userFlags[msg.sender]; }ConfidentialERC20.sol中的transfer是更贴近真实场景的例子function transfer( address to, externalEuint64 encryptedAmount, bytes calldata inputProof ) public { // 验证提供的加密金额并转换为加密 uint64 euint64 amount FHE.fromExternal(encryptedAmount, inputProof); // 后续业务逻辑如转账 ... }验证工作分两步FHE.fromExternal首先确保输入是携带对应 ZKPoK 的有效密文然后将其转换为可供合约内部使用的加密类型。8.5 用FHE.toExternal再导出句柄FHE.toExternal是fromExternal的逆操作把合约已经持有的链上加密值euintXX/ebool/eaddress重新包装为匹配的外部类型externalEuintXX/externalEbool/externalEaddress。与fromExternal一样是重载函数目标类型由参数推断见 FHE.sol。这在合约间组合场景中非常有用。许多函数——包括机密代币等标准化接口——把入口参数设计为(externalEuintXX handle, bytes inputProof)因为通常调用方是提交“加密输入 零知识证明”的 EOA。而一个已经持有euintXX的合约无法在链上生成这样的证明。toExternal配合fromExternal的空证明路径正好弥合这一鸿沟// 在已经持有 euint64 amount 的合约内部 FHE.allow(amount, address(token)); // 授予被调用方访问权ACL token.transfer(to, FHE.toExternal(amount), ); // 重新包装传入空证明接收端FHE.fromExternal(encryptedAmount, )会跳过证明验证仅检查句柄已被允许给调用方然后作为普通euint64返回——这正是智能合约账户接入 FHEVM 输入 ABI 的方式。重要toExternal只改变静态类型——它不做任何验证也不授予任何访问权。空证明再导入只有在句柄已通过FHE.allow/FHE.allowThis授权给相关方时才不会以SenderNotAllowedToUseHandle回滚。务必先设置好 ACL 权限。8.6 最佳实践输入打包把所有加密输入打包进单一密文最小化零知识证明的规模与复杂度前端加密始终在客户端用 FHE 公钥加密输入保证数据机密性证明管理确保正确的零知识证明与每个加密输入对应避免验证错误。9. ACL 访问控制谁可以用你的密文ACLAccess Control List 是 FHEVM 治理加密数据访问的核心机制。9.1 为什么 ACL 至关重要FHEVM 中的加密数据完全机密如果没有恰当的访问控制即使持有密文的合约本身也无法操作它。ACL 带来的能力细粒度权限为单个账户或合约定义具体访问规则安全计算确保只有授权实体能操作或解密加密数据Gas 效率用瞬时访问transient access优化临时需求降低存储与 Gas 开销。9.2 访问类型永久授权Permanent allowanceFHE.allow(ciphertext, address)为指定地址授予对密文的长期访问存储在专用合约的持久存储中瞬时授权Transient allowanceFHE.allowTransient(ciphertext, address)仅对当前交易有效存储在 EIP-1153 瞬时存储中Gas 更省适合把密文传给外部函数等临时操作永久公开授权Permanent public allowanceFHE.makePubliclyDecryptable(ciphertext)对任意用户授予长期访问同样存储在专用合约中。语法糖FHE.allowThis(ciphertext)是FHE.allow(ciphertext, address(this))的简写授权当前合约在未来交易中复用某个密文句柄。9.3 瞬时 vs 永久授权对比授权类型目的存储类型适用场景瞬时Transient交易期间临时访问瞬时存储EIP-1153调用外部函数或跨合约传密文希望节省 Gas 时永久Permanent跨多笔交易的长期访问专用合约存储需要持续访问的合约或用户的持久密文9.4 授权与验证函数授权allow授予某地址永久访问allowThis授予当前合约操作密文的权限allowTransient为当前交易授予某地址临时访问makePubliclyDecryptable授予任意实体在链下解密该密文句柄对应明文的永久全局权限。验证isAllowed验证指定地址是否有权限isSenderAllowed针对当前交易发送者的便捷检查isPubliclyDecryptable验证是否任何实体都可以链下取回该密文的明文checkSignatures通过校验密码学签名验证明文的真实性确保回传链上的值确实来自对该密文句柄的合法公开解密操作isAccountDenied检查账户是否在拒绝名单上。被拒账户在 ACL 合约内无法执行allow*调用即不能授予或接收对加密值的新权限。9.5 用户解密委托ACL 支持把用户解密权从一个账户委托给另一个账户例如后端服务或 relayer。委托人delegator是调用 ACL 的那个账户——EOA 直接调用IACL.delegateForUserDecryption合约则用FHE.delegateUserDecryption助手此时委托人是address(this)两种模式不可互换。delegateUserDecryption为特定contractAddress授予委托人在指定到期日前代表调用合约执行用户解密的权利delegateUserDecryptionWithoutExpiration同上但没有到期日revokeUserDecryptionDelegation撤销先前授予的委托isUserDecryptable检查某句柄在特定合约上下文中能否被用户解密。EOA 侧完整流程、约束与实例见 User decryption delegationAPI 参考见 FHEVM API reference。9.6 ACL 的典型用途机密参数在合约间安全传递加密值确保只有授权实体能访问安全状态管理存储加密状态变量同时控制谁能修改或读取隐私保护计算在权限被强制的保证下对加密数据执行计算可公开验证的结果揭示公开揭示机密操作的最终结果——例如让公众验证密封投标机密拍卖的最终成交价。10. 开发环境Hardhat 与 Foundry10.1 FHEVM Hardhat 插件Hardhat 指南 说明要使用 Hardhat 编写 FHEVM 合约需要在 Hardhat 项目中安装 FHEVM Hardhat 插件fhevm/hardhat-plugin。该插件开箱即用地扩展了 Hardhat 的能力加密数据解密数据以多种 FHEVM 执行模式运行测试编写 FHEVM 启用的 Hardhat Task。后续步骤包括Setup Hardhat 初始化项目、Write FHEVM Tests in Hardhat 编写测试、Run FHEVM Tests in Hardhat 在不同 FHEVM 环境中执行测试、Write FHEVM Hardhat Task 编写自定义任务。10.2 Quick Start 教程路线Quick Start Tutorial 承诺约30 分钟完成从普通 Solidity 合约到机密合约的转换前提是具备 Solidity 与 Ethereum 基础、对 Hardhat 有一定熟悉度。四个步骤搭建开发环境编写一个简单的 Solidity 智能合约把它改造成 FHEVM 兼容的机密合约测试改造后的机密合约。每一步均有独立文档Set up Hardhat、Write a simple contract、Turn it into FHEVM、Test the FHEVM contract。10.3 Foundry 路线偏好 Foundry 的开发者可走 Foundry 指南Setup Foundry 搭建环境、Write FHEVM tests in Foundry 编写测试、Deploy contracts 部署合约并查阅 forge-fhevm API reference 了解测试断言接口。11. 进阶主题HCUHandle Computation Unit面向 FHEVM 协处理器与链上执行的成本与限额模型运行正式 FHEVM 网络前建议阅读。合约改造指南系统性地把已有 Solidity 合约迁移为 FHEVM 合约的步骤与陷阱。逻辑控制包括 条件分支、循环与分支处理、错误处理——FHE 中无法直接if (encryptedCond)需要借助FHE.select等模式。公开解密FHE.decrypt与公开解密预言机流程是“最终结果上链公开”场景的入口。合约地址各网络 FHEVM 基础设施ACL、FHEVMExecutor、KMSVerifier 等的部署地址清单。12. 参考实现与源码印证为便于深入阅读以下是本仓库中与上述机制直接对应的源码与测试位置FHE 库实现library-solidity/lib/FHE.solisInitializedL93-L142、selectL7803-L7922、fromExternal/toExternalL8497-L8776、allowTransient/makePubliclyDecryptableL9179 起等全部运算符与权限函数的重载实现。配置合约library-solidity/config/ZamaConfig.solZamaConfig库L13与ZamaEthereumConfig抽象合约L149。加密类型定义library-solidity/lib/FheType.solebool/euintXX/eaddress/externalE*等类型的用户定义类型声明。示例合约library-solidity/examples/Counter.sol、library-solidity/examples/EncryptedERC20.sol、library-solidity/examples/HeadsOrTails.sol覆盖计数器、机密代币、链上随机数等典型用法。测试用例library-solidity/test/fhevmOperations/ 下的测试文件验证了各运算符的链上行为与 ACL 权限约束。合约地址docs/solidity-guides/contract_addresses.md各网络基础设施地址。总结以 Solidity Guides 为入口FHEVM 为 Solidity 开发者提供了一条完整的机密合约开发路径用ZamaEthereumConfig一键完成环境装配用ebool/euintXX/eaddress声明加密状态用FHE.*运算符在密文上执行算术、位运算与比较用fromExternal ZKPoK 接收加密输入用 ACL 的allow/allowTransient/makePubliclyDecryptable精确控制每一句柄的访问边界最终借助 Hardhat 插件或 Foundry 模板完成测试与部署。理解“句柄是不透明的”这一核心原则并遵循“选小类型、用标量操作数、防溢出”等最佳实践即可在保证机密性的同时写出安全高效的 FHEVM 合约。【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考