技术决策记录
持续记录每次开发的技术决策、问题修复和架构变更。 与
session.md互补:session.md 记录"做了什么",dev-log 记录"为什么这么做"。
2026-03-11 — Phase 6: Sepolia Testnet AWS 全球部署设计
背景
所有功能 Phase (0-5c, 7) 全部完成,项目进入部署阶段。目标:在 AWS 上部署生产级全球节点网络, 覆盖三大洲,支持公开 Testnet 测试。
架构决策
IaC 工具
Terraform
业界标准,多云支持,AWS provider 最成熟
容器编排
AWS EKS
有状态服务 (RocksDB/PostgreSQL) 支持好,GPU 节点池弹性伸缩
Prover
跳过 (TestnetVerifier)
GPU 月成本 $3000-8000+,testnet 无必要
Region
us-east-1 + eu-west-1 + ap-northeast-1
全球三大洲均衡覆盖
节点分布
单主多从
Sequencer us-east-1 (离 Sepolia L1 最近),其他 region External Node
数据库
Aurora (Sequencer) + CloudNativePG (External Node)
核心数据全托管,可重建数据自建省成本
网络入口
AWS Global Accelerator
TCP 层 Anycast,适合 JSON-RPC + WebSocket
CI/CD
GitHub Actions + ECR + Helm
现有仓库直接用,Helm 版本管理 + 回滚
监控
Prometheus + Grafana + Jaeger → Slack/Telegram
复用现有 era-observability 栈
Prover 跳过决策(重要)
Testnet 阶段使用 TestnetVerifier 跳过 ZK proof 验证。未来切换路径:
Terraform 添加
module "prover"— EKS GPU 节点池 (p3/g5 Spot + On-Demand)Helm chart 添加 prover-gateway, witness-generator, prover 三个 deployment
替换 TestnetVerifier 为 Verifier.sol (完整 FFLONK 验证)
预估增加成本: $5,000-15,000/月
项目结构
成本估算
EKS 节点 (3 region)
~$880
Aurora PostgreSQL (Multi-AZ)
~$500
监控栈
~$60
Global Accelerator + ECR
~$100
总计
~$1,500/月
下一步
2026-03-10 — Phase 7: 预测市场 + SDK
完成内容
ConditionalTokens.sol — 简化版 Gnosis CTF ERC-1155(去掉 parentCollectionId 嵌套,用 keccak256 替代 EC 数学)
CTFExchange.sol — 链上 CLOB 订单簿(EIP-712 签名,fillOrder/matchOrders/cancel)
OracleResolver.sol — 混合结算器(OracleHub 自动价格结算 + admin 手动结算)
@babydriver/sdk — isomorphic TypeScript SDK(viem, tsup ESM+CJS, vitest)
关键决策
条件代币
Gnosis CTF 简化版
行业标准,Polymarket 使用
交易模式
链上 CLOB
L2 gas 低,比 AMM 资金效率高
结算
混合(OracleHub + manual)
价格类自动化,事件类灵活
SDK
viem isomorphic
一个包覆盖 browser + Node.js
positionId
keccak256(collateral, conditionId, indexSet)
简化,无 EC 数学
测试
ConditionalTokens: 20 tests(prepare, split, merge, redeem, reportPayouts)
CTFExchange: 15 tests(fill, partial, cancel, nonce, fees, pause, EIP-712)
OracleResolver: 13 tests(create, resolvePrice, resolveManual, staleness)
E2E: 2 tests(完整生命周期 price + manual)
SDK: 14 tests(helpers + client)
总计: 64 tests
文件结构
2026-03-10 — Phase 3: Bridge-Enhancer Rust 自动结算模块
完成内容
baby-modules/bridge-enhancer/— Rust LP 自动结算监控模块config.rs— TOML 配置(L1/L2 RPC、合约地址、轮询间隔)rpc.rs— JSON-RPC 调用 + ABI 编码/解码(FastWithdrawalPoolV2 函数)monitor.rs— SettlementMonitor 核心循环(扫描未结算请求、超时检测)wiring.rs— BridgeEnhancerWiringLayer + 后台 tokio 任务
24 个 Rust 单元测试通过
技术决策
选择纯 RPC + 手动 ABI 编码(方案 A),与 oracle-wiring 模式一致
不引入 ethers-rs,保持轻量依赖
MVP 支持 read-only 模式(无私钥时仅日志)
settlement 交易签名留待下阶段实现(需要 secp256k1 签名库)
架构
沿用 baby-modules 标准模式:config → service → wiring → tokio::spawn
SettlementMonitor 跟踪 last_scanned_id,增量扫描新请求
请求分类:NotFound / AlreadySettled / TimedOut / PendingSettlement
2026-03-05 — Phase 5b: Genesis 重部署 + Groth16 Verifier 注册 + E2E 验证
IdentityVerifier 访问控制修复
问题: setCircuitVerifier() 使用 onlySystemCall 修饰符,EOA 无法直接调用。 解决: 参照 OracleHub 模式,添加 initialize() 一次性函数(无修饰符 + _initialized 状态守卫),允许 post-genesis 注册 circuit verifiers 和 trusted issuers。
Genesis 完整重部署
修改 IdentityVerifier 后需要完整重建 genesis(系统合约字节码变化导致 hash 级联更新):
编辑源文件
contracts/(非contracts-preprocessed/,后者被预处理器覆盖)yarn preprocess:system-contracts→npx hardhat compile→yarn compile-yul compile-bootloader替换
era-core/contracts/git 子模块为era-contracts-l1/副本zkstack ecosystem create→ecosystem init --no-genesis→chain init --no-genesis→ genesis修复 3 个 hash 不匹配:
default_aa_hash、genesis_root、genesis_batch_commitment
关键教训: 任何系统合约修改都需要迭代修复 genesis.yaml 中的 hash 值。
E2E 验证结果
Chain ID
✅
271 (0x10f)
OracleHub 5 symbols
✅
ETH/USD, BTC/USD, USDC/USD, SOL/USD, BNB/USD
OracleHub operator
✅
Governor (0x25bb...8489)
OracleHub 价格更新
✅
ETH/USD = $3500, freshness = true
IdentityVerifier 3 verifiers
✅
KYC(0), Credit(1), Enterprise(2)
IdentityVerifier mode
✅
ECDSA (0)
DID createDID
⚠️
onlySystemCall — 需通过系统合约或 bootloader 调用
Groth16 Verifier 地址(L2):
KYC (circuit 0):
0x6A47fA35A8Bfb021Cb9f5313d44B7838f8C2E944Credit (circuit 1):
0x2D60d2a35Dc1dD64b2E0a8eCB06887728a869185Enterprise (circuit 2):
0x58424DE0E3C21476934E8Cf165258a06372B1A41
2026-03-02 — Phase 2: Oracle 集成(5 层改动)
背景
Oracle 是 BabyDriver 最核心的差异化特性。我们需要在 L2 上提供原生价格源,让 DApps 可以零成本查询价格。 实现需要修改 5 层:Solidity 系统合约 → Yul Bootloader → Rust State Keeper → Rust VM 接口 → Rust 节点框架。
Phase 2.1: Oracle System Contract (0x8016)
技术决策:
选择地址
0x8016(当前最高系统合约 0x8015 = EVM_HASHES_STORAGE)使用
bytes32作为符号键(gas 效率优于string,系统合约场景下更合适)存储布局:
PriceData使用uint128 price + uint128 timestamp打包存储节省 slot价格异常时 跳过更新而非 revert,避免阻塞 batch 处理
使用
onlyCallFromBootloader保护batchUpdatePrices()使用
onlySystemCall保护管理函数 (addSymbol,setConfig)
改动文件:
era-contracts-l1/system-contracts/contracts/Constants.sol
添加 ORACLE_HUB_SYSTEM_CONTRACT = 0x8016
era-contracts-l1/system-contracts/contracts/OracleHub.sol
系统合约版本 Oracle(继承 SystemContractBase)
era-contracts-l1/system-contracts/contracts/interfaces/IOracleHub.sol
系统合约接口
era-contracts-l1/system-contracts/scripts/constants.ts
注册 oracleHub 地址
era-core/core/lib/constants/src/contracts.rs
添加 ORACLE_HUB_ADDRESS Rust 常量
era-core/core/lib/types/src/system_contracts.rs
注册到 SYSTEM_CONTRACT_LIST (40→41)
编译验证: 98 Solidity files compiled successfully (zksolc 1.5.11)
Phase 2.2: Bootloader Hook
技术决策:
在 bootloader 内存布局中分配 24 slots (768 bytes) 给 Oracle 数据
格式:
slot[8] = calldata_length, slot[9..] = ABI-encoded calldataBootloader 直接转发 pre-encoded calldata 给 OracleHub(不在 Yul 中做 ABI 编码)
Oracle 更新失败不阻塞 batch — 只记录 debugLog
将
SCRATCH_SPACE_BEGIN_SLOT从 8 移到 32(所有下游位置自动重算)
改动文件:
bootloader.yul
添加 ORACLE_HUB_ADDR(), ORACLE_CALLDATA_BEGIN_SLOT()
bootloader.yul
添加 updateOraclePrices() 函数
bootloader.yul
在 setNewBatch() 之后调用 updateOraclePrices()
编译验证: 所有 7 个 bootloader 变体编译通过
Phase 2.3: State Keeper 数据注入
技术决策:
在
L1BatchEnv添加oracle_calldata: Option<Vec<u8>>字段在
L1BatchParams添加对应字段State Keeper 通过
l1_batch_params()传递数据到 VMBootloaderState::initial_memory()将 calldata 写入 bootloader 堆内存大端序编码,32 字节对齐
改动文件(13 个):
vm_interface/.../l1_batch_env.rs
L1BatchEnv 添加 oracle_calldata
multivm/.../bootloader/init.rs
initial_memory() + append_oracle_calldata()
vm_executor/src/storage.rs
l1_batch_params() 默认 oracle_calldata: None
state_keeper/src/io/mod.rs
L1BatchParams 添加字段 + into_init_params() 传递
state_keeper/src/io/mempool.rs
两处构造添加 oracle_calldata: None
7 个测试/辅助文件
添加 oracle_calldata: None
编译验证: cargo check 200+ crates 全部通过 (2m52s)
Phase 2.4: EthWatch Oracle Event Processor
决策: 推迟到后续阶段。 当前 Oracle 价格由 Operator 直接提供(通过 WiringLayer),不需要 L1 事件监听。 L1 Oracle 事件监听用于跨链价格验证,将在 Phase 3 Bridge 增强时实现。
Phase 2.5: Oracle WiringLayer
技术决策:
使用
Arc<Mutex<OracleService>>作为共享资源后台 tokio task 定期获取价格(可配置间隔,默认 12s)
当前使用 mock 价格(ETH $3000, BTC $60000, USDC $1.00)
encode_oracle_calldata()生成 ABI 编码的batchUpdatePrices()calldata提供
get_oracle_calldata()辅助函数供 MempoolIO 调用
改动文件:
baby-modules/oracle-wiring/src/lib.rs
导出 WiringLayer
baby-modules/oracle-wiring/src/wiring.rs
OracleWiringLayer + 后台价格获取
baby-modules/oracle-wiring/src/service.rs
ABI calldata 编码 + 测试
架构总结
下一步
2026-03-01 — P0 合约安全加固
背景
Phase 1 (Day 1-3) 完成了基础设施骨架:智能合约、Sequencer、SDK、部署脚本。 深度代码审计发现 9 个必须修复的安全/逻辑问题,全部在合约层。 决定暂停应用层开发,优先完成 P0 安全加固。
审计发现的问题清单
1
CRITICAL
L1Bridge
Merkle proof 第二原像攻击风险 — 自定义排序不标准
已修复
2
CRITICAL
L2Bridge
提款叶子未去重,相同 (recipient, token, amount) 生成相同叶子
已修复
3
CRITICAL
FastPool
LP 匹配硬编码 address(this),费用不归 LP
已修复
4
HIGH
L1Bridge
大额存款 timelock 只记录不执行
已修复
5
HIGH
L2Bridge
processed 字段永远不置 true
已修复
6
HIGH
L2Bridge
Merkle root 每次查询重算 O(n),无缓存
已修复
7
MEDIUM
PriceLib
偏差计算不对称 (除以 a 而非平均值)
已修复
8
MEDIUM
OracleHub
merkleRoot 参数存而不验,无 minSourceCount
已修复
9
MEDIUM
Deploy
缺少 RELAYER/SEQUENCER 角色配置
待修复
修复记录
P0-1: Merkle Proof 安全修复
问题分析:
L1Bridge _verifyProof 使用自定义叶子排序 (hash <= sibling)。这与 OpenZeppelin 的标准实现一致,但存在第二原像攻击风险:内部节点和叶子节点使用相同哈希方式, 攻击者可以构造内部节点作为叶子提交。
标准防护方式是给叶子加 0x00 前缀,内部节点加 0x01 前缀。
L2Bridge 的 _withdrawalLeaves 允许重复叶子(相同 recipient+token+amount), 这会导致 L1 上同一笔提款可被多次执行。
修复方案:
L1Bridge: 叶子哈希加入
withdrawalId使其唯一,使用双重哈希keccak256(abi.encode(...))防止长度扩展攻击L2Bridge: 叶子中包含
requestId保证唯一性,与 L1Bridge 叶子格式对齐所有测试更新为多叶 Merkle 树
P0-2: 大额存款 Timelock 执行检查
修复: 新增 isDepositUnlocked(uint256 depositId) view 函数。 Sequencer 在 L2 执行 finalizeDeposit 之前必须调用此函数检查时间锁。
P0-3: L2Bridge Withdrawal Processed 追踪
修复: 新增 markWithdrawalProcessed(uint256 requestId) 函数(SEQUENCER_ROLE only)。 Sequencer 在 L1 确认提款后调用此函数将 processed 设为 true。
P0-4: FastPool LP 费用归属
问题: 费用硬编码给 address(this),LP 无法获得手续费。Settlement 不需要实际转账。
修复:
新增
_lpFeesmapping 追踪每个 LP 的费用settleWithdrawal改为payable,要求 settler 发送实际资金Settlement 拆分:pool 获得
amount - fee,settler 的_lpFees累加 fee新增
claimFees(address token)供 LP 提取手续费新增
getLpFees()view 函数
P0-5: PriceLib 偏差计算 + OracleHub minSourceCount
PriceLib 修复: deviationBps 使用 (a + b) / 2 作为分母,确保对称结果。
OracleHub 修复:
新增
minSourceCount状态变量(默认 1)_updateSinglePrice内部增加require(sourceCount >= minSourceCount)新增
setMinSourceCount(uint8 count)admin 函数
测试结果
所有 P0 修复完成后(除 P0-6 Deploy 角色配置),全量测试通过:
新增测试覆盖:
test_finalizeWithdrawal_uniqueLeaves— 验证不同 withdrawalId 生成不同叶子test_isDepositUnlocked_*— 3 个 timelock 状态测试test_withdrawalLeaf_includesRequestId— 验证叶子包含 requestIdtest_withdrawalLeaves_unique— 相同参数不同 requestId 的唯一性test_markWithdrawalProcessed*— processed 字段追踪test_refreshMerkleRoot— Merkle root 缓存test_pauseBridge/unpauseBridge— L2Bridge 暂停test_settleWithdrawal_revertIfInsufficientETH— settlement 需要实际 ETHtest_claimFees*— LP 费用领取test_E2E_oracle_minSourceCount— 最低源数量验证test_E2E_largeDepositTimelock— 含 isDepositUnlocked 验证
2026-03-01 — 架构评估 + 技术路线决策
背景
P0 安全修复完成后,审视现有代码发现 缺少 90% 的 L2 核心组件: 没有 zkEVM/VM、没有 State Keeper、没有 Prover、没有 Merkle Tree、没有 L1 Verifier。 当前实现只是"壳"(合约 + 骨架 Sequencer),不是真正的 ZK Rollup。
架构差距分析
对比 zksync-era(200+ Rust crate,212 个 Solidity 合约),发现:
zkEVM / VM
6+ 版本 MultiVM
完全没有
CRITICAL
State Keeper
完整状态机
TxPool 骨架
CRITICAL
Prover
35 电路 + 5 层聚合 + GPU
完全没有
CRITICAL
Merkle Tree
稀疏 Merkle + RocksDB
完全没有
CRITICAL
L1 合约
Diamond Proxy + Verifier
简单 Bridge
HIGH
DA 层
Calldata/Blobs/Celestia
完全没有
HIGH
Oracle
无原生实现
OracleHub ✓
我们的优势
FastPool
无
FastWithdrawalPool ✓
我们的优势
完整分析报告:docs/architecture/ARCHITECTURE-ANALYSIS.md
技术路线决策
决策:Fork zksync-era 作为底层引擎
Fork zksync-era
中
6-12 月
✅ 选定
Fork Optimism (OP Stack)
中
4-8 月
❌ 不是 ZK Rollup
自研 ZK Rollup
极高
3-5 年
❌ 不现实
基于 Polygon CDK
中
6-10 月
❌ 备选
理由:
Apache 2.0 许可证,允许商业使用
与 PRD "Type 2.5 zkEVM + PLONK" 完全匹配
生产级代码,已处理数十亿美元资产
最完整的开源 ZK Rollup 实现
现有代码价值评估
OracleHub.sol
★★★★ 核心差异化
移植为 System Contract (0x8016)
FastWithdrawalPool.sol
★★★ 有价值增强
集成到 era L1AssetRouter
PriceLib.sol
★★★ 可复用
保留
L1/L2 Bridge
★★ 概念验证
被 era-contracts 替代
Sequencer (Rust)
★ 学习价值
被 era core 替代
83 个测试
★★★ 验证逻辑
移植到新架构
2026-03-01 — Phase 0: Fork 环境搭建
实施计划
制定了 8 阶段实施计划(详见 .claude/plans/parsed-juggling-dahl.md):
0
环境搭建 + Fork 创建
2-3 天
1
Vanilla zksync-era 本地运行
3-5 天
2
Oracle 集成(系统合约 + Bootloader + State Keeper + EthWatch)
7-10 天
3
Bridge 增强(FastPool → IL1AssetHandler)
5-7 天
4
L1 合约定制(Oracle Facet + TestnetVerifier)
3-5 天
5
应用层(DID + 预测市场 + SDK)
10-14 天
6
Testnet 部署(Sepolia)
5-7 天
7
安全审计 + 主网准备
4-8 周
Phase 0 完成情况
0.1 开发环境依赖 ✅
Rust nightly-2025-03-19
rustc 1.87.0-nightly
✅ 新装
wasm32-unknown-unknown target
—
✅ 新装
cmake
4.2.3
✅ 新装
LLVM
22.1.0
✅ 新装
RocksDB
10.10.1
✅ 新装
jemalloc
5.3.0
✅ 新装
PostgreSQL
17.7
✅ 已有
Node.js
v20.20.0 (nvm) + v24.12.0
✅ 新装 v20
yarn
1.22.22
✅ 已有
Docker
29.1.3
✅ 已有
Foundry
1.5.1
✅ 已有
0.2 Fork 并克隆仓库 ✅
GitHub Fork:
leeleeEcho/baby-era← matter-labs/zksync-eraleeleeEcho/baby-era-contracts← matter-labs/era-contracts
本地克隆:
Layer2/era-core/(107MB, core v29.11.1)Layer2/era-contracts-l1/(92MB, v29.4)
两个仓库已创建
baby/main分支git submodules 已初始化
.gitignore已更新排除 fork 目录
0.3 项目结构重组 ✅
创建 baby-modules/ Rust workspace(3 个 crate,编译通过):
创建 config/baby-chain.toml — BabyDriver 链配置。
0.4 首次编译验证 ✅
额外工具安装:
cargo-nextest✅sqlx-cli✅Node.js v20.20.0 ✅(system-contracts 需要,v24 不兼容 hardhat-zksync-solc 插件)
编译结果:
era-core Rust 核心
ZKSYNC_USE_CUDA_STUBS=true cargo build --release
✅ 5分42秒
era-contracts L1 合约
forge build
✅ 517 个合约目录
era-contracts system-contracts
npx hardhat compile (Node.js 20)
✅ typechain 生成
baby-modules
cargo build
✅ 3 个 crate
关键二进制文件确认:
era-core/core/target/release/zksync_server✅era-core/core/target/release/zksync_external_node✅era-core/core/target/release/block_reverter✅
踩坑记录:
Node.js v24 与
@matterlabs/hardhat-zksync-solc不兼容(maxRedirections is not supported),需用 v20era-core 编译需设置
ZKSYNC_USE_CUDA_STUBS=true(非 GPU 环境跳过 CUDA 依赖)
Phase 0 总结
Phase 0 全部完成。 环境搭建、Fork 创建、项目重组、首次编译验证均已通过。 下一步进入 Phase 1: Vanilla zksync-era 本地运行。
2026-03-02 — Phase 1: Vanilla zksync-era 本地运行
Phase 1 完成情况
1.1 启动 Docker 容器 ✅
Docker reth v1.8.2 作为 L1 模拟节点(dev 模式,300ms 出块)
L1 chain_id = 9,RPC
http://127.0.0.1:8545本地 PostgreSQL 17.7 复用(无需 Docker PG)
1.2 zkstack ecosystem init ✅
安装 foundry-zksync v0.1.9 + anvil-zksync 0.6.11(zkstack 需要 forge build --zksync)。
zkstack ecosystem init 完成:
生态系统合约部署(Bridgehub, Diamond Proxy, Verifier, Governance 等)
ERC20 测试代币部署
Chain "era" 注册(chain_id: 271, NoProofs, EraVM, Rollup)
数据库初始化 + Genesis 创世区块生成
踩坑记录:
系统代理
http_proxy=127.0.0.1:7001导致 zkstack 内部 ethers/reqwest 无法连接本地 reth,需关闭代理DB URL 必须指定默认数据库(
postgres://judybaby@localhost:5432/postgres),否则 sqlx 尝试连接不存在的judybaby数据库foundry 标准版不支持
--zksyncflag,必须安装 foundry-zksync
1.3 启动 zksync_server ✅
zkstack server --chain era 启动成功,所有核心服务运行:
State Keeper: 处理 L1 Batch
eth_tx_manager: 提交 CommitBlocks 到 L1
eth_tx_aggregator: 创建 proof + execute 交易
API Server: JSON-RPC on
http://127.0.0.1:3050
API 验证:
eth_chainId
0x10f (271) ✅
eth_blockNumber
持续增长 ✅
zks_L1ChainId
0x9 ✅
1.4 发送测试交易 ✅
L1 → L2 Deposit:
L2 内部转账:
Batch → L1 提交:
CommitBlocks tx FastFinalized ✅
Proof + Execute 交易已发送
Phase 1 总结
Phase 1 全部完成。 Vanilla zksync-era 在本地完整运行:
L1 reth 出块 → L1 合约部署 → Genesis → zksync_server 启动
L1 Deposit → L2 余额 → L2 转账 → Batch 提交 L1
完整 ZK Rollup 流程验证通过
下一步进入 Phase 2: Oracle 集成。
2026-03-02 — Phase 3: Bridge 增强设计评估
背景
Phase 2(Oracle 集成)完成后,按计划进入 Phase 3: Bridge 增强。 原计划是将 FastWithdrawalPool 实现为 era 的 IL1AssetHandler,并迁移 L1/L2 Bridge 合约到 era 架构。
架构调研
深入分析了两套桥系统后,得出关键结论:
zksync-era 桥架构(已有能力)
Bridgehub
统一入口,路由 L1→L2 存款
L1AssetRouter
资产路由,分发到对应 AssetHandler
L1NativeTokenVault
原生代币处理(锁定/释放),实现 IAssetHandler
L1Nullifier
提款证明验证 + 防双花(isWithdrawalFinalized mapping)
Mailbox
L1↔L2 消息传递(Diamond Proxy facet)
L2AssetRouter + L2NTV
L2 侧资产路由 + 铸币/销毁
完整存款流程: User → Bridgehub → L1AssetRouter → NTV.bridgeBurn() → Mailbox L2 tx → L2AssetRouter → L2NTV.bridgeMint()
完整提款流程: User L2 withdraw → L2→L1 message → Merkle proof → L1Nullifier.finalizeDeposit() → L1AssetRouter → NTV.bridgeMint()
BabyDriver 桥合约(现有代码)
L1BridgeContract
存款 + Merkle proof 提款
完全被 era 覆盖
L2BridgeContract
L2 铸币/销毁 + Merkle root 计算
完全被 era 覆盖
FastWithdrawalPool
LP 即时提款池
era 没有,独有价值
技术决策:方案变更
原计划: FastWithdrawalPool 实现 IL1AssetHandler 接口,深度集成到 L1AssetRouter
新方案:Sidecar 模式 — FastWithdrawalPool 作为独立 L1 合约,与 era 桥并行运行
变更理由:
L1/L2 BridgeContract 废弃 — era 已提供完整的存款/提款/证明验证系统,重复实现没有意义
深度集成 (IAssetHandler) 风险过高 — era 的 1-资产-1-处理器 模型不适合叠加 FastPool 逻辑
Sidecar 是行业标准 — Across Protocol、Hop Protocol 均采用此模式
零修改 era 核心桥 — 降低维护负担和升级冲突
三方案对比
A: IAssetHandler 深度集成
极高
中(可能引入桥漏洞)
强耦合
B: Sidecar 独立合约 ⭐
低
高(不碰 era 桥)
零耦合
C: NTV 包装器
中
中(依赖 NTV 内部实现)
中耦合
FastWithdrawalPool v2 设计要点
与 v1 的核心区别
结算方式
SETTLER_ROLE 信任结算
任何人可通过 era L2→L1 证明结算
费率
固定 0.5%
可选 Oracle 动态费率(基于需求)
提款绑定
无绑定
用户提交 L2 提款哈希,绑定快速提款请求
超时保护
无
LP 超时后可取回资金
与 era 桥关系
独立系统
使用 era 的 L1Nullifier 证明验证
用户快速提款流程
架构图
实现范围
FastWithdrawalPool v2 合约
Solidity 重构
~300 行
大额存款 Timelock Diamond Facet
Solidity 新增
~50 行
集成测试(与 era 桥 E2E)
Foundry 测试
~200 行
bridge-enhancer Rust 模块
LP 自动结算监控
~100 行
不做的事
❌ 不修改 L1AssetRouter / L1Nullifier / L2AssetRouter
❌ 不迁移 L1BridgeContract / L2BridgeContract(保留作参考和测试用例源)
❌ 不实现 IL1AssetHandler 接口
保留价值
FastWithdrawalPool.sol
重构为 v2(保留 LP 池 + 费用逻辑,重写结算层)
L1BridgeContract.sol
废弃(大额 timelock 逻辑移植到 Diamond Facet)
L2BridgeContract.sol
废弃(Merkle root 逻辑由 era 原生处理)
PriceLib.sol
保留(v2 动态费率可用)
83 个测试
核心逻辑移植到 v2 测试,era 桥部分由 era 自有测试覆盖
下一步
2026-03-04 — Phase 5a: DID 系统核心层 (P0)
背景
DID 是 BabyDriver 的去中心化身份基础设施。基于 did:ethr 标准,部署为系统合约, 为后续 ZK 身份证明 (P1) 和企业 IAM (P2) 奠定基础。
三个系统合约
DIDRegistry (0x8017):
did:ethr:baby 标识符格式
DIDDocument 存储:verificationMethods + controller + serviceEndpointHash
委托机制:addDelegate/revokeDelegate(时间有效性)
访问控制:onlySystemCall (createDID), onlyController (update/deactivate)
CredentialRegistry (0x8018):
Verifiable Credential 发行 + 撤销
双方 DID 活跃性验证(issuer + subject 必须有活跃 DID)
CredentialId = keccak256(issuer, subject, type, claimHash, issuedAt)
有效性检查:未撤销 + 未过期 + issuer DID 仍活跃
IdentityVerifier (0x8019):
双模式设计:ECDSA (P0) → ZK_PLONK (P1)
verifyIdentity(): 查找 trusted issuer 发行的有效凭证
checkCompliance(): 合规标记查询
Trusted Issuer 管理(bootloader 控制)
改动文件
Constants.sol
+3 地址常量 (0x8017-0x8019)
constants.ts
+3 系统合约注册
contracts.rs
+3 Rust 地址常量
system_contracts.rs
SYSTEM_CONTRACT_LIST 41→44
DIDRegistry.sol + IDIDRegistry.sol
新建系统合约
CredentialRegistry.sol + ICredentialRegistry.sol
新建系统合约
IdentityVerifier.sol + IIdentityVerifier.sol
新建系统合约
contracts/src/did/*.sol
本地测试版 (Foundry)
contracts/test/DIDRegistry.t.sol
24 测试
contracts/test/CredentialRegistry.t.sol
15 测试
contracts/test/IdentityVerifier.t.sol
19 测试 + E2E
编译验证
系统合约:90 Solidity files compiled (zksolc 1.5.11) ✓
Rust:cargo check 200+ crates ✓
Foundry:191 测试全通过(含 58 新 DID 测试)✓
下一步
2026-03-04 — Phase 5b: ZK 身份证明 + Oracle 信用评分
Phase 5b 完成情况
Phase 5b: ZK 身份证明 + Oracle 信用评分 (2026-03-04)
交付物:
3 个 circom 电路: KYCComplianceProof (~7.8k 约束), CreditScoreProof (~7.8k 约束), EnterpriseIdentityProof (~2.9k 约束)
EdDSA/Poseidon 签名验证 (Baby Jubjub curve)
Groth16 trusted setup (Powers of Tau 2^16) + 3 个 Solidity Verifier 合约
IdentityVerifier (0x8019) 升级: verifyZKProof() 分发 + 防重放 + compliance 自动更新
Oracle 信用评分: getPersonalCreditScore() / getOrgCreditScore() / getCompositeCreditScore()
IGroth16Verifier 通用接口 + MockGroth16Verifier 测试工具
20 circom JS 测试 + 18 Foundry Solidity 测试
关键决策:
Groth16/circom 而非 boojum (Goldilocks field 不兼容 BN256, VM 专用电路)
EdDSA (Baby Jubjub) 而非 ECDSA (~5k vs ~1.5M constraints)
信用评分复用 OracleHub 现有接口 (CREDIT:* symbols, 无需修改 Oracle 合约)
企业维度: KYC 电路支持 orgType/orgComplianceLevel, 信用电路支持双分数
测试结果
全量 Foundry 测试通过:
系统合约编译: 104 Solidity files compiled (zksolc 1.5.11) ✓
下一步
2026-03-04 — Phase 5b 续: L1 DIDFacet + Mailbox 双向同步
背景
DID 系统合约 (0x8017-0x8019) 运行在 L2,但 L1 合约(如 Bridge 治理、跨链身份验证) 需要查询 DID 状态。需要双向同步机制:
L2→L1: L2 DID 状态变更通过 L1Messenger 发送消息,L1 DIDFacet 通过 Mailbox proof 缓存
L1→L2: 从 L1 发起 DID 操作(createDID, issueCredential 等),通过 Bridgehub 到 L2 执行
架构选择
采用 Event-Driven Sync 方案(与 L1OracleReader 模式一致):
安全模型最强:每条消息都有 ZK batch proof 背书
代码复用度高:复用 Mailbox proveL2MessageInclusion
L2 合约改动最小:仅添加 L1Messenger.sendToL1() 调用
实现内容
L1 DIDFacet(contracts/ 目录,Foundry 测试版):
DIDMessageLib.sol
8 种消息类型常量 + 6 个解码函数
IDIDFacet.sol
接口:DIDSnapshot/CredentialSnapshot + 5 事件 + 5 错误
IBridgehubLocal.sol
L2TransactionRequestDirect 结构 + Bridgehub 接口
MockBridgehub.sol
记录 L2 请求的测试 mock
DIDFacetLocal.sol
完整实现:L2→L1 sync + L1→L2 request + 查询 + 管理
DIDFacet.t.sol
32 个 Foundry 测试
DIDFacetLocal 三层 API:
L2→L1 同步: syncDIDDocument / syncCredential / syncCompliance — Mailbox proof 验证 + 重放保护
L1→L2 请求: requestCreateDID / requestIssueCredential / requestDeactivateDID / requestRevokeCredential / requestAddTrustedIssuer — Bridgehub 发送优先交易
只读查询: getDIDDocument / isIdentityActive / isCredentialValid / checkCompliance / isTrustedIssuer
L2 系统合约 L1Messenger 集成(era-contracts-l1):
DIDRegistry
createDID()
DID_CREATED (0)
DIDRegistry
updateDocument()
DID_UPDATED (1)
DIDRegistry
deactivateDID()
DID_DEACTIVATED (2)
CredentialRegistry
issueCredential()
CREDENTIAL_ISSUED (3)
CredentialRegistry
revokeCredential()
CREDENTIAL_REVOKED (4)
IdentityVerifier
setCompliance()
COMPLIANCE_UPDATED (5)
IdentityVerifier
addTrustedIssuer()
TRUSTED_ISSUER_ADDED (6)
IdentityVerifier
removeTrustedIssuer()
TRUSTED_ISSUER_REMOVED (7)
关键决策
独立 Diamond Storage slot — DIDFacet 使用
keccak256("babydriver.diamond.storage.did.facet") - 1避免修改 ZKChainStorage(减少上游 merge conflict)DIDFacetLocal vs DIDFacet — Local 版用 MockMailbox/MockBridgehub 测试,生产版继承 ZKChainBase 访问 Diamond Proxy 的 Mailbox 和 Bridgehub
Stack Too Deep 修复 —
decodeCredentialIssued返回 8 个值,提取为_handleCredentialIssued内部函数
测试结果
全量 Foundry 测试通过:
下一步
Phase 2.5b: Oracle 真实 API 集成 (2026-03-04)
变更: 将 Oracle 系统从 mock 硬编码价格替换为 CoinGecko + Binance 双源真实 API。
关键改动
keccak256 修复 —
service.rs中的keccak256()之前使用DefaultHasher(SipHash),不是真正的 Keccak-256。改为sha3::Keccak256,确保 symbolHash 与链上 Soliditykeccak256()一致。PriceSource Trait — 可插拔数据源抽象:
CoinGeckoSource— 免费 API/simple/price,批量查询最多 250 个 coinBinanceSource— 免费 API/ticker/price,无 rate limitMockSource— 测试用,可配置固定价格
PriceAggregator — 多源聚合:
futures::join_all并行获取所有源中位数价格计算
偏差检测(basis points)
置信度评分:双源低偏差 95-100, 高偏差 30-60, 单源 50
故障转移:一个源挂掉自动使用另一个
配置扩展 —
symbols: Vec<String>→symbols: Vec<SymbolConfig>+sources字段baby-chain.toml改为[[oracle.symbols]]表格数组每个 symbol 包含
canonical,coingecko_id,binance_symbol映射初始配置 30 个主流交易对
测试结果
oracle-wiring 单元测试: 38 个全部通过 (36 pass + 2 ignored integration)
Foundry 合约测试: 全部通过
后续
State Keeper 从 bootloader memory slot 注入改为 operator 优先交易注入(支持 100+ 对)
MempoolIO 接入 SharedOracleService(
oracle_calldata: None→ 真实 calldata)OracleHub.sol 添加
onlyOperator修饰符
2026-03-04 — Phase 2.6: Oracle Operator 交易注入
背景
Phase 2.5b 完成了 CoinGecko + Binance 双源 API 集成,但价格注入仍使用 bootloader 内存 slot 方式(slot 8-31, 共 24 slots = 768 bytes)。每个交易对需要 ~128 bytes 编码空间,24 slots 最多支持 ~6 对,无法满足 31+ 交易对需求。
技术决策
方案选择: Operator 合成 L2 交易注入(方案 B: 一步到位)
仿照
ProtocolUpgradeTx模式,在 batch 开头注入 operator → OracleHub 的合成 L2Tx数据量无上限(transaction calldata 不受 memory slot 限制)
Oracle tx 执行失败不阻塞 batch(与 protocol upgrade tx 不同,后者失败会 panic)
完全移除 bootloader memory slot 旧代码
oracle_tx.rs — 合成交易构造
新建 era-core/core/node/state_keeper/src/oracle_tx.rs:
build_oracle_update_tx(): 构造 L2Tx (EIP-712)from: operator (fee_account)
to: ORACLE_HUB_ADDRESS (0x8016)
calldata: 预编码的
batchUpdatePrices(bytes32[],uint128[],uint64[],uint8[])gas_limit: 5M(operator 不实际扣费)
nonce: Nonce(0)(不走 mempool nonce 验证)
6 单元测试
keeper.rs — Batch 开头注入
StateKeeperInner::process_oracle_tx(): 仿照process_upgrade_tx()模式通过
process_one_tx()执行(与普通交易相同路径)成功: extend UpdatesManager
失败/revert/ExcludeAndSeal/Unexecutable: warn 日志,return Ok(())
process_block()注入点:is_batch_start检查后,在 protocol_upgrade_tx 与用户交易循环之间
StateKeeperIO trait 扩展
get_oracle_tx_calldata(&self) -> Option<Vec<u8>>: 默认返回 NoneMempoolIO 实现: 从
SharedOracleService.encode_oracle_calldata()获取
旧代码移除(19 个 Rust 文件)
L1BatchEnv.oracle_calldata 字段
1
L1BatchParams.oracle_calldata 字段 + 赋值
1
init.rs ORACLE_CALLDATA_BEGIN_SLOT/MAX_SLOTS + append_oracle_calldata()
1
oracle_calldata: None 构造字段
16
bootloader.yul 清理
移除
ORACLE_CALLDATA_BEGIN_SLOT(),ORACLE_CALLDATA_BEGIN_BYTE(),ORACLE_CALLDATA_MAX_SLOTS()移除
ORACLE_HUB_ADDR()函数移除
updateOraclePrices()函数 + 2 处调用(proved + playground batch flow)SCRATCH_SPACE_BEGIN_SLOT从 32 恢复为 8
OracleHub.sol 权限变更
batchUpdatePrices():onlyCallFromBootloader→onlyOperator新增
address public operator+modifier onlyOperator()新增
setOperator(address)(onlySystemCall)initialize()自动设置operator = tx.origin19 Foundry 测试(含 operator rotation E2E)
验证结果
era-core cargo check: 200+ crates 全部通过
oracle_tx 单元测试: 6/6 pass
oracle-wiring 测试: 36/36 pass (2 ignored)
Foundry 合约测试: 260/260 pass(含 19 新 operator 测试)
bootloader 预处理: 通过
oracle_calldata 旧引用: 0(19 文件全部清理)
后续
L1 DIDFacet + Mailbox 双向同步实现
重新部署 genesis 含 OracleHub operator 初始化
E2E 测试: operator tx → OracleHub.getLatestPrice() 验证
2026-03-05 — Genesis 完整重部署 + E2E 验证
背景
Phase 2.5b 的 Oracle 架构重构(移除 bootloader 注入,改为 operator tx 模式)需要完整重部署 genesis, 验证所有系统合约(OracleHub 0x8016、DIDRegistry 0x8017、CredentialRegistry 0x8018、IdentityVerifier 0x8019) 在新链上正确工作。
关键修复:protective_reads_persistence_enabled
问题: 重部署后 state_keeper 在 batch 1 sealed 后卡死,无法创建 batch 2。
根因分析:
State keeper 创建 batch 2 时需要 batch 1 的 hash
Hash 由 Merkle tree (metadata_calculator) 计算
Merkle tree 判断哪些 batch 可处理的逻辑分两条路径:
sealed_batches_have_protective_reads = true→ 检查is_sealed = true(简单)sealed_batches_have_protective_reads = false→ 检查vm_runner_protective_reads表(复杂)
我们的配置
protective_reads_persistence_enabled: false触发了后者vm_runner_protective_reads表为空(ProtectiveReadsWriter 未运行)→ 返回 batch 0 → 死锁
修复: general.yaml 中 protective_reads_persistence_enabled: false → true
代码路径:
metadata_calculator/src/lib.rs:123-124: config 映射metadata_calculator/src/updater.rs:201-221: 条件分支vm_runner_dal.rs:get_protective_reads_latest_processed_batch()SQL
教训: 当不运行 ProtectiveReadsWriter 组件时,必须设置 protective_reads_persistence_enabled: true, 否则 Merkle tree 会检查一个永远为空的表。
OracleHub 初始化
验证结果:
stalenessThreshold= 3600 ✓deviationThreshold= 500 ✓minSourceCount= 3 ✓operator= governor 地址 ✓getLatestPrice(ETH/USD)= 200000000000 ($2000.00) ✓isPriceFresh(ETH/USD)= true ✓
E2E 验证结果
OracleHub initialize + update + query
✓
DID 合约部署 (0x8017-0x8019 有 bytecode)
✓
Chain ID = 271
✓
Block 持续推进 (block 10+)
✓
L1 Batch 持续 seal (batch 5+)
✓
L1 deposit 处理 (governor ~2 ETH)
✓
Batch hash 计算 (tree 正常工作)
✓
配置变更
era_core/chains/era/configs/general.yaml:72
protective_reads_persistence_enabled: false → true
era_core/chains/era/configs/general.yaml:206
添加 zksync_state_keeper=trace 到 log_directives
下一步
Phase 5b: ZK 身份证明 (PLONK 电路 + IdentityVerifier 升级)
Oracle operator 自动化服务(Rust WiringLayer 发送 batchUpdatePrices)
Testnet 部署 (Sepolia)
2026-03-05 — Oracle 自动化 E2E 调试 (7 个 Bug 修复)
背景
实现 Oracle 价格自动化注入:每个 L1 batch 开始时,State Keeper 自动构建签名交易调用 OracleHub.batchUpdatePrices()。从 mock/CoinGecko/Binance 获取价格,编码 ABI calldata, EIP-712 签名后注入 batch 首位。
修复的 7 个 Bug
1
set_input panic
L2Tx::new_signed 后未设置 tx.set_input(...) 导致 hash() panic
在 oracle_tx.rs 调用 set_input(rlp_bytes, hash)
2
VM 签名验证失败
使用普通 ECDSA 签名,VM 期望 EIP-712
改用 K256PrivateKey::sign_typed_tx EIP-712 签名
3
basefee reject
max_fee_per_gas = 0,低于 block basefee
设置 max_fee_per_gas = 250_000_000
4
NonceAlreadyUsed (缓存)
首次启动时缓存 nonce 到 AtomicU32,后续 batch 使用过期 nonce
改为每 batch 从 DB 异步查询 (storage_web3_dal().get_nonces_for_addresses())
5
"insufficient sources" revert
链上 minSourceCount=3,calldata 仅报 source_count=1 (只有 mock)
encode_oracle_calldata() 使用 max(actual, config.min_source_count)
6
"unsupported symbol" revert
config 有 31 符号但链上只注册了 ETH/USD
暂时减少 config 到 ETH/USD;后续需 addSymbol 系统调用
7
Batch 不开启
空 mempool 导致 wait_for_new_batch_params 无限等待
非 bug — zksync-era 设计:需要 mempool 有 tx 才开 batch
关键代码改动
era-core/core/node/state_keeper/src/io/mod.rs:
get_oracle_tx():fn→async fn(支持 DB 查询)
era-core/core/node/state_keeper/src/io/mempool.rs:
移除
AtomicU32nonce 缓存get_oracle_tx()改为 async,每 batch 从 DB 查 nonce
era-core/core/node/state_keeper/src/oracle_tx.rs:
max_fee_per_gas: 0 → 250_000_000新增
nonce: Nonce参数
baby-modules/oracle-wiring/src/service.rs:
encode_oracle_calldata()source count floor:max(pd.source_count, config.min_source_count)
config/baby-chain.toml:
从 31 符号减少到 1 个 (ETH/USD)
E2E 验证结果
已知限制
首 batch 竞态:服务器启动后第一个 batch 总是错过 Oracle 注入(价格获取 ~12s,batch 开启 ~100ms)
Binance 400 / CoinGecko 403:外部 API 不可用,仅 mock 源工作(本地开发环境限制)
单符号:链上仅注册 ETH/USD,多符号需
addSymbol()系统调用Operator 地址冲突:Oracle tx 和用户 tx 共享同一地址会导致 nonce 冲突(生产环境需独立 operator)
Oracle 多符号注册 (方案 A+B)
日期: 2026-03-05
问题: addSymbol(bytes32) 使用 onlySystemCall 修饰符,普通 EOA 无法调用,导致链上只有 genesis 时注册的 ETH/USD 一个符号。batchUpdatePrices 传入未注册符号会 revert(Bug #7)。
方案 A(Genesis): 扩展 initialize() 调用,一次性传入 5 个符号 hash(ETH/BTC/USDC/SOL/BNB)。
方案 B(Runtime): addSymbol 权限从 onlySystemCall 放宽为 onlySystemCall OR onlyOperator,新增 batchAddSymbols(bytes32[]) 批量注册接口。
变更文件:
OracleHub.sol—_isSystemCallOrOperator()内部函数 +addSymbol双权限 +batchAddSymbolsIOracleHub.sol— 接口同步OracleHubLocal.sol— Foundry 可测试镜像同步(_isAdminOrOperator)baby-chain.toml— 启用 BTC/USD, USDC/USD, SOL/USD, BNB/USD 配置6 个新 Foundry 测试(全套 50 个通过)
安全决策: removeSymbol 保持 onlySystemCall(高危操作 — 删除符号可能影响依赖该价格的 DApp)。addSymbol 是低风险操作(只添加,不影响现有价格数据),故允许 operator 调用。
Phase 5b 完成 (2026-03-05)
IdentityVerifier 修复
setCircuitVerifier访问控制修复:onlyCallFromBootloader→onlySystemCall允许 genesis 后通过系统调用交易注册 Groth16 Verifier
CreditScoreAggregator (baby-modules/credit-score/)
新 Rust 模块:加权信用评分服务
config.rs: 评分权重配置 — tx_activity(25%) + account_age(20%) + kyc_level(20%) + holding_duration(20%) + did_activity(15%)on_chain.rs: L2 RPC 查询(DIDRegistry + CredentialRegistry + IdentityVerifier)aggregator.rs: 饱和归一化评分算法(递减回报),评分范围 0-1000wiring.rs: SharedCreditScoreService + CreditScoreWiringLayer 后台 tokio 任务符号格式:
CREDIT:PERSONAL:0x{address},通过 OracleHub.batchUpdatePrices 提交Phase 1 简化:仅链上因子,account_age/holding_duration 使用代理值
25 个测试(21 单元 + 4 集成)全部通过
L1 DIDFacet 验证
DIDFacetLocal.sol(390 行)测试验证:32 个 Foundry 测试全部通过
L2→L1 消息格式验证:8 种消息类型 (0-7) 确认正确
0: DID_CREATED, 1: DID_UPDATED, 2: DID_DEACTIVATED
3: CREDENTIAL_ISSUED, 4: CREDENTIAL_REVOKED
5: COMPLIANCE_UPDATED, 6: TRUSTED_ISSUER_ADDED, 7: TRUSTED_ISSUER_REMOVED
注意:verifyZKProof 尚未发送 L1 消息(ZK_PROOF_VERIFIED type 8 延至 Phase 6)
全量测试验证
技术决策
CreditScore 评分使用饱和归一化(value * MAX / (value + ref))而非线性归一化,避免极端值主导评分
参考值设定:TX_COUNT_REF=200, ACCOUNT_AGE_REF=180 days, HOLDING_DURATION_REF=90 days, CREDENTIAL_COUNT_REF=10
信用评分作为 OracleHub 特殊符号存储,复用现有 Oracle 基础设施
(后续开发记录在此追加)
Phase 5c: 社会恢复 + 企业 IAM + 选择性披露 (2026-03-06)
完成内容
Part 1: 社会恢复 (DIDRegistry 0x8017)
N-of-M guardian 恢复 + 时间锁(最少 1 小时,默认 24h)
最多 7 个 guardian,不可重复,不能是自己
流程:setRecovery → initiateRecovery → approveRecovery → executeRecovery(或 cancelRecovery)
Guardian 变更自动清除待处理恢复请求
L1 sync: Type 8 (RecoveryInitiated), Type 9 (RecoveryExecuted)
30 Foundry 测试
Part 2: 企业 IAM (EnterpriseIAM 0x801A)
新系统合约:组织管理 + 自定义角色 + uint256 权限位图
8 权限常量: ISSUE_CREDENTIAL, REVOKE_CREDENTIAL, MANAGE_MEMBERS, MANAGE_ROLES, VIEW_REPORTS, MANAGE_COMPLIANCE, ADMIN, SIGN_TRANSACTIONS
ADMIN 权限隐含所有权限,Owner 自动拥有所有权限
DIDRegistry 集成:创建组织需 DID 活跃 + 调用者为 controller 或 delegate
L1 sync: Type 10 (OrgCreated), Type 11 (RoleAssigned), Type 12 (RoleRevoked)
24 Foundry 测试
Part 3: 选择性披露 (IdentityVerifier 0x8019)
ZK 属性级证明(证明年龄 >= 18 而不暴露出生日期)
DisclosurePolicy: credentialType + requiredAttributes + circuitType
新 circuitType: 3 (age proof), 4 (income proof), 5 (region proof)
复用 Groth16 基础设施 (_circuitVerifiers, _usedProofs 防重放)
验证成功自动设置 compliance key:
SD_<policyId>12 Foundry 测试
E2E 测试: 4 个跨合约集成测试 (recovery+IAM, IAM+credential, disclosure+compliance, full lifecycle)
测试总计
DIDRegistryRecovery.t.sol
30
EnterpriseIAM.t.sol
24
IdentityVerifierDisclosure.t.sol
12
Phase5cE2E.t.sol
4
Phase 5c 新增
70
项目总计
336
系统合约地址总表
0x8016
OracleHub
P2
0x8017
DIDRegistry
P5a + P5c (社会恢复)
0x8018
CredentialRegistry
P5a
0x8019
IdentityVerifier
P5a/b + P5c (选择性披露)
0x801A
EnterpriseIAM
P5c (新增)
技术决策
社会恢复采用混合模式(N-of-M + 时间锁)而非纯多签,给原始控制者反应时间
企业 IAM 独立为新系统合约(0x801A),避免 DIDRegistry 过于膨胀
选择性披露复用现有 Groth16 基础设施,通过 DisclosurePolicy 映射策略到电路
权限位图使用 uint256(256 位),当前定义 8 个权限,预留扩展空间
Last updated