Operator TX — 设计
概述
将 Oracle 价格注入方式从 bootloader 内存 slot(24 slots = 768 bytes, 最多 ~6 对)改为 operator 合成交易注入(无上限),完成 Oracle E2E 闭环。
核心变更:
State Keeper 在每个 batch 开始时注入一笔 operator → OracleHub 的合成 L2 交易
MempoolIO 接入 SharedOracleService,获取真实价格编码
完全移除 bootloader memory slot 方式(slot 8-31, updateOraclePrices())
OracleHub.sol 权限从
onlyCallFromBootloader改为onlyOperator
架构
当前流程(移除)
OracleService → encode_calldata → L1BatchParams.oracle_calldata
→ bootloader memory slots 8-31
→ bootloader updateOraclePrices()
→ OracleHub.batchUpdatePrices() [onlyCallFromBootloader]新流程
注入点
Oracle 交易构造
交易参数
类型
L2Tx (EIP-712)
发送者
l1_batch_env.fee_account (operator 地址)
目标
ORACLE_HUB_ADDRESS (0x8016)
Calldata
batchUpdatePrices(bytes32[], uint128[], uint64[], uint8[])
Gas limit
5_000_000 (足够大,operator 不实际扣费)
Value
0
Nonce
由 State Keeper 管理(不走 mempool nonce)
新增文件
era-core/core/node/state_keeper/src/oracle_tx.rs:
错误处理
Oracle tx 执行失败不阻塞 batch(只记 warn 日志,继续处理用户交易)
Oracle tx 不计入 batch gas 消耗限制
Oracle tx 不需要签名验证(operator 直接构造)
无价格数据时跳过注入(OracleService 返回 None)
MempoolIO 接入
新增字段
StateKeeperIO trait 扩展
MempoolIO 实现:
初始化
OracleWiringLayer 构建 SharedOracleService 后,通过依赖注入传递给 MempoolIO 构造函数。 MempoolIO 当前的构造在 MempoolIOBuilder 中,添加 oracle_service 参数。
旧代码移除
Rust (era-core) 移除
vm_interface/.../l1_batch_env.rs
oracle_calldata: Option<Vec<u8>> 字段
multivm/.../bootloader/init.rs
ORACLE_CALLDATA_BEGIN_SLOT, ORACLE_CALLDATA_MAX_SLOTS, append_oracle_calldata()
state_keeper/src/io/mod.rs
L1BatchParams.oracle_calldata 字段 + into_init_params() 中的赋值
state_keeper/src/io/mempool.rs
两处 oracle_calldata: None
vm_executor/src/storage.rs
oracle_calldata: None
~7 个测试/辅助文件
oracle_calldata: None 构造字段
Solidity (era-contracts-l1) 移除
bootloader.yul
updateOraclePrices() 函数
bootloader.yul
两处 updateOraclePrices() 调用(main + playground batch flow)
bootloader.yul
ORACLE_CALLDATA_BEGIN_SLOT(), ORACLE_CALLDATA_MAX_SLOTS(), ORACLE_CALLDATA_BEGIN_BYTE()
bootloader.yul
SCRATCH_SPACE_BEGIN_SLOT 从 32 恢复为 8
OracleHub.sol 权限变更
测试策略
新增测试 (~8)
1
Oracle tx 构造: 正确 calldata + target + sender
oracle_tx.rs
2
Oracle tx 构造: 空价格返回 None
oracle_tx.rs
3
get_oracle_tx_calldata: 有数据时返回 Some
oracle_tx.rs
4
OracleHub.batchUpdatePrices: operator 调用成功
OracleHub.t.sol
5
OracleHub.batchUpdatePrices: 非 operator revert
OracleHub.t.sol
6
OracleHub.setOperator: admin 函数
OracleHub.t.sol
7
Bootloader 编译通过
编译验证
8
era-core 编译通过 + 现有测试回归
cargo check + forge test
回归验证
era-core:
cargo check200+ crates 全部通过Foundry: 241+ 合约测试全部通过
Bootloader: 7 个变体编译通过
System contracts: 编译通过
文件清单
新建文件
era-core/core/node/state_keeper/src/oracle_tx.rs
Oracle 交易构造 + 单元测试
修改文件 (~20)
era-core (Rust):
state_keeper/src/keeper.rs
process_block() 注入 Oracle tx
state_keeper/src/io/mod.rs
trait 新增 get_oracle_tx_calldata(), 移除 oracle_calldata 字段
state_keeper/src/io/mempool.rs
接入 SharedOracleService, 实现新方法
state_keeper/src/lib.rs
添加 mod oracle_tx
vm_interface/.../l1_batch_env.rs
移除 oracle_calldata
multivm/.../bootloader/init.rs
移除 Oracle memory slot
vm_executor/src/storage.rs
移除 oracle_calldata
~7 个测试/辅助文件
移除 oracle_calldata 构造
era-contracts-l1 (Solidity):
bootloader.yul
移除 Oracle 相关代码 + 恢复 SCRATCH_SPACE
OracleHub.sol
onlyOperator + setOperator
IOracleHub.sol
更新接口
baby-modules (Rust):
oracle-wiring/src/wiring.rs
导出 SharedOracleService 构造函数供 MempoolIO 使用
测试:
contracts/test/OracleHub.t.sol
新增 operator 权限测试
交付计划
Task 1
oracle_tx.rs 交易构造 + 单元测试
25 min
Task 2
MempoolIO 接入 SharedOracleService
20 min
Task 3
keeper.rs Oracle tx 注入
30 min
Task 4
移除 Rust 旧代码 (L1BatchEnv, init.rs, 等)
30 min
Task 5
移除 bootloader.yul Oracle 代码 + 编译
20 min
Task 6
OracleHub.sol onlyOperator + Foundry 测试
20 min
Task 7
全量回归 + dev-log
15 min
Last updated