Genesis 部署 — 实现
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: 用全部 44 个系统合约(含 OracleHub 0x8016 + DID 0x8017-0x8019)重新部署 genesis,验证 Oracle operator tx 注入和 DID 系统合约功能的端到端流程。
Architecture: 清理旧环境 → 修改 OracleHub.initialize() 权限 → 编译系统合约 + bootloader → zkstack ecosystem init 部署 L1 + genesis → 启动节点 + Oracle 后台 → post-genesis 合约初始化 → E2E 验证全部功能。
Tech Stack: Rust (nightly-2025-03-19), Solidity (0.8.20), Docker (reth + postgres), zkstack CLI, Foundry (foundry-zksync), cast
Task 1: OracleHub.initialize() 修饰符修改 + 编译验证
目标: 将 initialize() 从 onlyCallFromBootloader 改为 onlySystemCall,使 genesis 后可通过交易调用初始化。
Files:
Modify:
era-contracts-l1/system-contracts/contracts/OracleHub.sol:66
Step 1: 修改 initialize() 修饰符
将 OracleHub.sol 第 66 行的 onlyCallFromBootloader 改为 onlySystemCall:
// 修改前 (line 66):
) external onlyCallFromBootloader {
// 修改后:
) external onlySystemCall {同时更新注释(第 60 行):
// 修改前 (line 60):
/// @dev Uses onlyCallFromBootloader since genesis deploys run as bootloader.
// 修改后:
/// @dev Uses onlySystemCall to allow post-genesis initialization via system call.Step 2: 编译系统合约验证
Expected: 编译成功,无 error。
Step 3: 运行 Foundry 测试回归
Expected: 所有 OracleHub 测试通过(19 tests in OracleHubLocal 不受影响,因为 OracleHubLocal 使用独立的 admin 访问控制)。
Step 4: Commit
Task 2: 环境清理 (Docker + PostgreSQL)
目标: 停止旧容器、清理旧数据库,为全新 genesis 做准备。
Step 1: 停止所有 Docker 容器
确认容器已停止:
Expected: 无 reth/postgres 相关容器运行。
Step 2: 清理 PostgreSQL 数据库
查看当前数据库列表:
删除旧数据库并重建:
Expected: DROP DATABASE 成功(或 "does not exist")。
Step 3: 清理 era-core 生成的配置文件
Step 4: 重新启动 Docker 容器
验证容器运行:
Expected: reth (port 8545) 和 postgres (port 5432) 运行中。
Step 5: 验证 L1 reth 节点
Expected: 0x9 (chain_id = 9)
Step 6: 验证 PostgreSQL 连接
Expected: 返回 1。
Task 3: 编译系统合约 + Bootloader
目标: 编译包含 OracleHub (onlySystemCall) + DID 合约的完整系统合约集和 bootloader。
前提: Task 1 已修改 OracleHub.sol,Task 2 环境已就绪。
Step 1: 确认 Node.js 版本
Expected: v20.x.x(v24 会导致 hardhat-zksync-solc 错误)
Step 2: 预处理 + 编译系统合约
Expected: 编译 44 个系统合约成功(包括 OracleHub 0x8016, DIDRegistry 0x8017, CredentialRegistry 0x8018, IdentityVerifier 0x8019)。
Step 3: 预处理 + 编译 Bootloader
Expected: 7 个 bootloader 变体编译成功。新的 bootloader 不含 Oracle memory slot 代码(已在 Phase 2.5b 移除),SCRATCH_SPACE_BEGIN_SLOT = 8。
Step 4: 编译 L1 合约
Expected: L1 合约编译成功。
Step 5: 验证 bootloader hash 已更新
bootloader hash 会在编译后自动更新到 artifacts。zkstack ecosystem init 会读取这些 artifacts 生成 genesis config。
Expected: 存在 proved_batch.yul.zbin 等 artifact 文件。
Task 4: zkstack ecosystem init (L1 合约 + Genesis)
目标: 使用 zkstack 部署 L1 合约到本地 reth,生成包含 44 个系统合约的 genesis block。
前提: Task 2(环境就绪)+ Task 3(合约已编译)。
⚠️ 重要:关闭系统代理再执行!
Step 1: 运行 zkstack ecosystem init
按照交互提示选择:
部署 L1 合约到
http://127.0.0.1:8545(本地 reth)Chain name:
eraChain ID:
271Prover mode:
NoProofsVM type:
EraVML1 batch commit data generator mode:
Rollup数据库 URL:
postgres://judybaby@localhost:5432/postgres(⚠️ 必须指定/postgres)
Expected:
生态系统合约部署(Bridgehub, Diamond Proxy, Verifier, Governance)
ERC20 测试代币部署
Chain "era" 注册 (chain_id: 271)
Genesis block 生成(包含 44 个系统合约)
数据库初始化
Step 2: 验证 genesis 配置生成
Expected: 新的 GENESIS_ROOT、GENESIS_BATCH_COMMITMENT 等值已更新。
Step 3: 验证数据库已初始化
Expected: 存在新创建的 zksync 数据库。
故障排除:
如果出现代理错误:确保
http_proxy已 unset如果出现数据库错误:确保 DB URL 以
/postgres结尾如果出现 forge build 错误:确保使用 foundry-zksync 而非标准 foundry
Task 5: 启动 zksync_server + 验证 API
目标: 启动节点,验证 API 正常工作,确认 genesis 包含正确的系统合约。
Step 1: 启动 zksync_server
等待日志显示 State Keeper 和 API Server 启动完成:
State Keeper: processing L1 batch...API Server: JSON-RPC on http://127.0.0.1:3050
Step 2: 验证链 ID
Expected: 0x10f (271)
Step 3: 验证 L1 chain ID
Expected: 0x9 (9)
Step 4: 验证区块持续增长
Expected: 区块号持续增长。
Step 5: 验证 OracleHub 系统合约已部署
Expected: 返回非空 bytecode(0x... 大量数据)。
Step 6: 验证 DID 系统合约已部署
Expected: 三个地址均返回非空 bytecode。
Task 6: 合约初始化 (OracleHub + setOperator)
目标: 通过 cast 交易调用 OracleHub.initialize() 和 setOperator(),完成 post-genesis 初始化。
前提: Task 5(节点运行中)。
Step 1: 确认 fee_account (operator) 地址
查看配置中的 fee_account 地址:
Expected: 0xde03a0B5963f75f1C8485B355fF6D30f3093BDE7 或当前配置的地址。
同时需要确认 operator 的私钥(zkstack 生成的 rich wallet):
Step 2: 准备 symbol hashes
Step 3: 调用 OracleHub.initialize()
⚠️ 需要使用 isSystem: true 标志发送系统调用交易。由于 cast send 不直接支持 isSystem flag,使用 zkSync 的 EIP-712 交易格式:
Expected: 交易成功 (status: 1)。
⚠️ 如果 cast --zksync 不支持 isSystem flag:
可能需要编写简短的 Node.js/TypeScript 脚本使用 zksync-ethers SDK 发送系统调用
或者在 OracleHub.sol 中将
initialize()改为无权限修饰符(只保留require(stalenessThreshold == 0)防重入)
Step 4: 验证初始化成功
Expected:
stalenessThreshold= 60operator= fee_account 地址
Step 5: 调用 setOperator() (如需更新 operator)
Expected: 交易成功 (status: 1)。
Step 6: 验证 symbol 支持
Expected: true
Task 7: E2E 验证 (Oracle + DID + Bridge)
目标: 端到端验证 Oracle 价格注入、DID 系统、L1→L2 Bridge 所有功能。
前提: Task 6(合约初始化完成)、节点+Oracle后台运行中。
Step 1: 启动 Oracle 后台服务
如果 Oracle 后台未自动启动(取决于 zkstack 配置),手动启动:
⚠️ 注意: Oracle 服务是通过 OracleWiringLayer 集成到 zksync_server 的。如果 zksync_server 没有加载 Oracle 配置,可能需要单独的 Oracle 服务进程,或确认 MempoolIO 已连接 SharedOracleService。
Step 2: 验证 Oracle 价格查询
等待 Oracle 后台至少运行一个 fetch 周期(12 秒)后:
Expected: 返回非零价格和时间戳(price > 0, timestamp > 0)。
如果返回 0/0,说明 Oracle operator tx 尚未注入价格。检查:
zksync_server 日志中是否有
Oracle tx injected日志SharedOracleService 是否有价格数据
Step 3: 验证 DID 创建
Expected: 交易成功 (status: 1)。
Step 4: 验证 DID 查询
Expected: 返回非空 DID 文档数据(包含 publicKeys 和 authMethod)。
Step 5: L1→L2 Deposit
Expected: L1 交易成功。
Step 6: 验证 L2 余额增加
等待约 10 秒让 deposit 被处理:
Expected: 余额 > 0(如果 wallet 之前没有余额)。
Step 7: 验证 Batch 提交到 L1
检查 zksync_server 日志中是否有 CommitBlocks 交易。
Step 8: 综合验证清单
1
链 ID
cast rpc eth_chainId --rpc-url localhost:3050
0x10f (271)
2
OracleHub 已部署
cast code 0x...8016 --rpc-url localhost:3050
非空
3
OracleHub 已初始化
cast call 0x...8016 "stalenessThreshold()"
60
4
Oracle 价格
cast call 0x...8016 "getLatestPrice(bytes32)" $ETH_HASH
非零
5
DID 创建
cast send 0x...8017 "createDID(...)"
status=1
6
DID 查询
cast call 0x...8017 "getDocument(address)"
非空
7
L1→L2 Deposit
cast send bridgehub ... --value 1ether
status=1
8
L2 余额
cast balance $ADDR --rpc-url localhost:3050
> 0
9
DIDRegistry 已部署
cast code 0x...8017
非空
10
CredentialRegistry 已部署
cast code 0x...8018
非空
11
IdentityVerifier 已部署
cast code 0x...8019
非空
Task 8: dev-log 更新
目标: 记录 genesis 重部署的完整过程、结果和踩坑记录。
Files:
Modify:
docs/dev-log.md
Step 1: 在 dev-log 末尾追加 Genesis 重部署条目
在 docs/dev-log.md 末尾添加:
Step 2: Commit
Last updated