Operator TX — 设计

概述

将 Oracle 价格注入方式从 bootloader 内存 slot(24 slots = 768 bytes, 最多 ~6 对)改为 operator 合成交易注入(无上限),完成 Oracle E2E 闭环。

核心变更:

  1. State Keeper 在每个 batch 开始时注入一笔 operator → OracleHub 的合成 L2 交易

  2. MempoolIO 接入 SharedOracleService,获取真实价格编码

  3. 完全移除 bootloader memory slot 方式(slot 8-31, updateOraclePrices())

  4. 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 check 200+ 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