fhEVM js-sdk 测试地址簿解析:从助记词到确定性合约地址的推导全流程
【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm
本文档以 fhEVM 仓库 sdk/js-sdk/test/ADDRESSES.md 为骨架,系统讲解 js-sdk 测试基础设施中测试账户与合约地址是如何从固定助记词确定性推导出来的。它直接服务于本地 anvil/localstack 测试环境、SDK 测试套件与浏览器端 e2e 测试,读者读完后可以掌握:一条助记词如何派生出多个部署者账户(index 派生)、这些账户如何按 nonce 通过 CREATE 语义推导出 ACL、FHEVMExecutor、KMSVerifier 等宿主合约地址,以及如何用cast命令行与仓库源码互相验证这些地址。
一、这份文档是什么:测试环境的确定性地址账本
ADDRESSES.md不是一份营销文档,而是 js-sdk 测试设施中单点维护的地址清单(single source of truth)。它记录了:
- 测试助记词
FHEVM_REPO_MNEMONIC(同时是 test/infra/config.ts 中的DEFAULT_DEPLOYER_MNEMONIC); - 由该助记词在不同 BIP-39 index 下派生的部署者私钥与账户地址(index=5 与 index=9);
- 由这些部署者账户按固定 nonce 通过 CREATE 推导出的宿主合约地址,并标注了合约类型、版本(v0.11.0 / v0.12.0 / v0.13.0)与适用链(localstack / chainId=31337)。
整个 js-sdk 测试矩阵(test/ 目录下的 vitest 单测、test/infra/ 的 anvil 编排、test/chains/ 的链配置)都依赖这套地址的确定性:同一助记词 + 同一索引 + 同一 nonce,在任何机器、任何时候都得到同一地址,从而保证 CI 与本地环境的可复现性。
二、助记词与账户派生:一条助记词,两个部署者
ADDRESSES.md首先给出核心助记词:
FHEVM_REPO_MNEMONIC="adapt mosquito move limb mobile illegal tree voyage juice mosquito burger raise father hope layer"该助记词在仓库中的正式定义位于 sdk/js-sdk/test/infra/config.ts:
export const DEFAULT_DEPLOYER_MNEMONIC = 'adapt mosquito move limb mobile illegal tree voyage juice mosquito burger raise father hope layer'; export const DEFAULT_DEPLOYER_INDEX = 5;由此派生两个部署者账户:
| 账户 | 派生方式 | 私钥 | 地址 |
|---|---|---|---|
| 主部署者 | FHEVM_REPO_MNEMONIC, index=5, path=default | 0x7697c90f7863e6057fbe25674464e14b57f2c670b1a8ee0f60fb87eb9b615c4d | 0x8B8f5091f8b9817EF69cFC1E8B2f721BafF60DF4 |
| 辅助部署者 | FHEVM_REPO_MNEMONIC, index=9, path=default | 0x2d24c36c57e6bfbf90c43173481cc00edcbd1a3922de5e5fdb9aba5fc4e0fafd | 0xc45994e4098271c3140117ebD5c74C70dd56D9cd |
文档给出的私钥派生命令(依赖 Foundry 的cast,需先cast wallet import或用cast wallet private-key直接由助记词推导):
# index=9 的私钥 cast wallet private-key "adapt mosquito move limb mobile illegal tree voyage juice mosquito burger raise father hope layer" 9 # index=5 的私钥 cast wallet private-key "adapt mosquito move limb mobile illegal tree voyage juice mosquito burger raise father hope layer" 5两个部署者对应两套测试部署场景:
- index=9:用于 localstack 链(
localstack:v0.11.0)的宿主合约部署,对应 test/chains/localstack.ts 等链配置; - index=5:用于
@fhevm/solidity/config中 chainId=31337 的 cleartext 部署(Foundry 测试网),对应 test/infra/config.ts 中 v12 slot(chainId 31337)。
从源码结构看,v12 槽位使用独立部署者助记词
FIRST_ANVIL_MNEMONIC(见 test/infra/config.ts),以保证 legacy 与 current 两套协议栈地址不冲突——因为 SDK 会按合约地址缓存协议版本,两个链共享地址会互相碰撞。
三、核心机制:合约地址 = f(部署者, nonce) 的 CREATE 推导
地址簿后半部分的所有合约地址,都遵循以太坊 CREATE 语义:由部署者地址与部署 nonce 共同决定,与链无关、与部署时间无关。仓库 test/infra/anvil/fhevmAddresses.ts 是这一机制的源码实现:
import { getContractAddress } from 'viem'; import { mnemonicToAccount } from 'viem/accounts'; import { DEFAULT_DEPLOYER_INDEX } from '../config.js'; // CREATE nonce of each host contract, fixed by the deploy's creation order. const HOST_NONCE = { acl: 1, fhevmExecutor: 3, kmsVerifier: 4, inputVerifier: 5, hcuLimit: 6, protocolConfig: 7, kmsGeneration: 8, pauserSet: 9, } as const; export function deriveFhevmHostAddresses(mnemonic: string, index: number = DEFAULT_DEPLOYER_INDEX): FhevmHostAddresses { const from = mnemonicToAccount(mnemonic, { addressIndex: index }).address; const at = (nonce: number): string => getContractAddress({ from, nonce: BigInt(nonce) }); return { acl: at(HOST_NONCE.acl), inputVerifier: at(HOST_NONCE.inputVerifier), kmsVerifier: at(HOST_NONCE.kmsVerifier), protocolConfig: at(HOST_NONCE.protocolConfig), }; }这段代码同时印证了两个要点:
- 部署顺序即 nonce 顺序:部署脚本按"ACL → FHEVMExecutor → KMSVerifier → InputVerifier → HCULimit → ProtocolConfig → KMSGeneration → PauserSet"的固定顺序逐个
CREATE,因此每个合约占用固定 nonce,地址可预先离线计算; - 文件头注释给出验证锚点:
deriveFhevmHostAddresses(DEFAULT_DEPLOYER_MNEMONIC, 5).acl === 0x50157CFfD6bBFA2DECe204a89ec419c23ef5755D,与地址簿第 8 项完全一致,证明该地址清单与代码推导逻辑互为校验。
需要区分两个概念:账户地址(由助记词经 BIP-39/BIP-32 派生,即"钱包地址")与合约地址(由部署者地址 + nonce 经 CREATE 推导)。地址簿中 index=5/9 两项是账户地址,其余都是合约地址。
四、地址与合约映射速查表
4.1 localstack:v0.11.0 部署组(部署者 = index=9)
| 序号 | 合约 | 部署 nonce | 地址 |
|---|---|---|---|
| — | 部署者账户(index=9) | — | 0xc45994e4098271c3140117ebD5c74C70dd56D9cd |
| 1 | ACL | 1 | 0x05fD9B5EFE0a996095f42Ed7e77c390810CF660c |
| 2 | FHEVMExecutor | 3 | 0xcCAe95fF1d11656358E782570dF0418F59fA40e1 |
| 3 | KMSVerifier | 4 | 0xa1880e99d86F081E8D3868A8C4732C8f65dfdB11 |
| 4 | InputVerifier | 5 | 0x857Ca72A957920Fa0FB138602995839866Bd4005 |
| 5 | HCULimit | 6 | 0xAb30999D17FAAB8c95B2eCD500cFeFc8f658f15d |
| 6 | PauserSet | 7 | 0x52054F36036811ca418be59e41Fc6DD1b9e4F4c8 |
对应验证命令(cast wallet address用私钥反查账户地址,cast compute-address用"部署者 + nonce"正向计算合约地址):
# address of FHEVM_REPO_MNEMONIC, index=9 path=default cast wallet private-key "adapt mosquito move limb mobile illegal tree voyage juice mosquito burger raise father hope layer" 9 cast wallet address --private-key 0x2d24c36c57e6bfbf90c43173481cc00edcbd1a3922de5e5fdb9aba5fc4e0fafd cast compute-address 0xc45994e4098271c3140117ebD5c74C70dd56D9cd --nonce 1 # ACL cast compute-address 0xc45994e4098271c3140117ebD5c74C70dd56D9cd --nonce 3 # FHEVMExecutor cast compute-address 0xc45994e4098271c3140117ebD5c74C70dd56D9cd --nonce 4 # KMSVerifier cast compute-address 0xc45994e4098271c3140117ebD5c74C70dd56D9cd --nonce 5 # InputVerifier cast compute-address 0xc45994e4098271c3140117ebD5c74C70dd56D9cd --nonce 6 # HCULimit cast compute-address 0xc45994e4098271c3140117ebD5c74C70dd56D9cd --nonce 7 # PauserSet4.2 @fhevm/solidity/config chainId=31337 部署组(部署者 = index=5)
| 序号 | 合约 | 部署 nonce | 适用版本 | 地址 |
|---|---|---|---|---|
| — | 部署者账户(index=5) | — | — | 0x8B8f5091f8b9817EF69cFC1E8B2f721BafF60DF4 |
| 1 | PauserSet | 0 | v0.11.0, v0.12.0 | 0x34e3eD8472e409dbF8FDf933cA996DC75e4Be126 |
| 2 | ACL | 1 | 所有版本 | 0x50157CFfD6bBFA2DECe204a89ec419c23ef5755D |
| 3 | FHEVMExecutor | 3 | 所有版本 | 0xe3a9105a3a932253A70F126eb1E3b589C643dD24 |
| 4 | KMSVerifier | 4 | 所有版本 | 0x901F8942346f7AB3a01F6D7613119Bca447Bb030 |
| 5 | InputVerifier | 5 | 所有版本 | 0x36772142b74871f255CbD7A3e89B401d3e45825f |
| 6 | HCULimit | 6 | 所有版本 | 0x233ff88A48c172d29F675403e6A8e302b0F032D9 |
| 7 | ProtocolConfig | 7 | v0.13.0 | 0x44aA028fd264C76BF4A8f8B4d8A5272f6AE25CAc |
| 8 | KMSGeneration | 8 | v0.13.0 | 0x216be43148dB537BeddBC268163deb1a802b5553 |
| 9 | PauserSet | 9 | v0.13.0 | 0xded0D2a71268DC12622BdD1b55d68a1CB5662327 |
对应验证命令:
# address of FHEVM_REPO_MNEMONIC, index=5 path=default cast wallet private-key "adapt mosquito move limb mobile illegal tree voyage juice mosquito burger raise father hope layer" 5 cast wallet address --private-key 0x7697c90f7863e6057fbe25674464e14b57f2c670b1a8ee0f60fb87eb9b615c4d # nonce=0 → 0x34e3eD8472e409dbF8FDf933cA996DC75e4Be126 (PauserSet, 旧版本) cast compute-address 0x8B8f5091f8b9817EF69cFC1E8B2f721BafF60DF4 --nonce 0 # nonce=1 → ACL(所有版本) cast compute-address 0x8B8f5091f8b9817EF69cFC1E8B2f721BafF60DF4 --nonce 1 # nonce=3 → FHEVMExecutor(所有版本) cast compute-address 0x8B8f5091f8b9817EF69cFC1E8B2f721BafF60DF4 --nonce 3 # nonce=4 → KMSVerifier(所有版本) cast compute-address 0x8B8f5091f8b9817EF69cFC1E8B2f721BafF60DF4 --nonce 4 # nonce=5 → InputVerifier(所有版本) cast compute-address 0x8B8f5091f8b9817EF69cFC1E8B2f721BafF60DF4 --nonce 5 # nonce=6 → HCULimit(所有版本) cast compute-address 0x8B8f5091f8b9817EF69cFC1E8B2f721BafF60DF4 --nonce 6 # nonce=7 → ProtocolConfig(v0.13.0) cast compute-address 0x8B8f5091f8b9817EF69cFC1E8B2f721BafF60DF4 --nonce 7 # nonce=8 → KMSGeneration(v0.13.0) cast compute-address 0x8B8f5091f8b9817EF69cFC1E8B2f721BafF60DF4 --nonce 8 # nonce=9 → PauserSet(v0.13.0) cast compute-address 0x8B8f5091f8b9817EF69cFC1E8B2f721BafF60DF4 --nonce 9注:
HOST_NONCE中 ACL 固定为 nonce=1,而旧版(v0.11.0/v0.12.0)在 nonce=0 处多部署了一个早期 PauserSet,v0.13.0 起 PauserSet 移到 nonce=9(即HOST_NONCE.pauserSet),这正是地址簿两组数据存在差异的原因。
五、地址簿与测试设施的联动关系
地址簿中的地址并不是孤立存在的,它们被 js-sdk 测试设施多处引用:
- 链配置消费合约地址:test/chains/localstack.ts 等
defineFhevmChain配置中,acl、inputVerifier、kmsVerifier、protocolConfig字段填写的正是地址簿中的地址(例如 ACL0x05fD9B5E...、InputVerifier0x857Ca72A...、KMSVerifier0xa1880e99...)。SDK 运行时通过这些地址解析并缓存协议版本; - slot 编排消费部署者:test/infra/config.ts 中每个 slot 定义了独立的 chainId、端口与 TFHE 密钥版本,其中 v12 slot 使用 chainId 31337、端口 8544、TFHE 1.5.4,v13 slot 使用 chainId 31338、端口 8546、TFHE 1.6.2——这与地址簿 chainId=31337 的分组一致;
- anvil 启动即地址推导:test/infra/anvil/spawn-anvils.ts 通过
startAnvils(anvilSpecs())拉起测试链,而 fhevmAddresses.ts 的作用正是在部署前离线算出各槽位地址,让 gateway 无需解析部署产物即可按槽位提供地址; - RPC/测试合约参数:test/chains/chain-defaults.json 记录了各链(localstack、sepolia、mainnet、polygon 等)的 RPC 地址与测试合约
fheTestAddress,与地址簿一起构成完整的测试拓扑。
六、安全边界与使用提醒
这份地址簿属于测试设施专用,使用时必须注意:
- 助记词与私钥均硬编码在仓库中,仅供本地 anvil / 测试网 / 模拟环境使用,任何情况下都不得用于持有真实资产的主网账户;
- 地址的确定性依赖"部署顺序 = nonce 顺序",一旦部署脚本调整了合约创建顺序,整套地址簿即失效,必须同步更新 ADDRESSES.md 与 fhevmAddresses.ts 中的
HOST_NONCE; - 若需在本地复现,需安装 Foundry(提供
cast命令)与 Node 环境,并通过cast compute-address/cast wallet或viem的getContractAddress双向校验。
总结
sdk/js-sdk/test/ADDRESSES.md以极简的清单形式,浓缩了 fhEVM js-sdk 测试设施中"助记词 → 账户 → 合约地址"的完整确定性推导链路:一条FHEVM_REPO_MNEMONIC助记词在 index=5 与 index=9 处派生出两个部署者,再由固定 nonce 经 CREATE 语义推导出 ACL、FHEVMExecutor、KMSVerifier、InputVerifier、HCULimit、ProtocolConfig、KMSGeneration、PauserSet 等宿主合约地址。理解这套机制,是排查本地测试环境地址不一致、部署顺序变更导致地址漂移、以及参与 js-sdk 测试矩阵开发的基本功。
【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考