Skip to content
On this page

S1C12: Give Me The Block!

1. 问题

需要提供正确的 RLP 编码的区块头来调用 mintFlag。合约验证区块头的时间戳、难度等字段。

2. 原因

合约实现了轻客户端式的区块验证:它接受一个 RLP 编码的区块头,解码后检查区块号是否在允许范围内(当前区块号 - 256 到当前区块号 - 2),以及其他字段的合法性。

3. 方案

  1. 等待当前交易被打包(获取 block.number
  2. 等待至少 2 个区块
  3. 使用 eth_getBlockByNumber 获取历史区块的完整头信息
  4. RLP 编码该区块头
  5. 在 256 区块窗口内提交
javascript
// 获取区块头并 RLP 编码
const block = await provider.getBlock(blockNumber);
const rlpEncoded = ethers.utils.RLP.encode([
    block.parentHash,
    block.sha3Uncles,
    block.miner,
    block.stateRoot,
    block.transactionsRoot,
    block.receiptsRoot,
    block.logsBloom,
    block.difficulty,
    block.number,
    block.gasLimit,
    block.gasUsed,
    block.timestamp,
    block.extraData,
    block.mixHash,
    block.nonce,
]);

4. 遇到的陷阱

RLP 编码格式: OP Mainnet 的区块头字段编码与以太坊主网相同但有细微差异。cast block 输出的格式需要转换为 RLP 友好的数值格式。

5. 陷阱的原因

RLP 对每个字段有严格的编码要求,数值类型必须去除前导零。OP 使用 Bedrock 升级后的区块格式,某些字段(如 difficulty)可能与标准以太坊不同。

6. 如何解决

使用 cast rlp 或 JavaScript ethers.utils.RLP.encode 正确编码。注意:

  • difficulty 在 OP 上可能为 0
  • baseFeePerGas 在 EIP-1559 后是必填字段(OP 支持 1559)
  • 区块必须在 [block.number - 256, block.number - 2] 范围内

7. 技术要点

要点说明
RLP 编码Ethereum 的标准序列化格式,用于区块头、交易等
OP 区块结构Optimism 的区块格式与以太坊有差异(Bedrock 升级后)
时间窗口约束合约检查区块在 256 个区块内(约 512 秒),防止使用过旧的区块
blockhash 可用性EVM 只保存最近 256 个区块的哈希

Built with AiAda