Appearance
S1C12: Give Me The Block!
1. 问题
需要提供正确的 RLP 编码的区块头来调用 mintFlag。合约验证区块头的时间戳、难度等字段。
2. 原因
合约实现了轻客户端式的区块验证:它接受一个 RLP 编码的区块头,解码后检查区块号是否在允许范围内(当前区块号 - 256 到当前区块号 - 2),以及其他字段的合法性。
3. 方案
- 等待当前交易被打包(获取
block.number) - 等待至少 2 个区块
- 使用
eth_getBlockByNumber获取历史区块的完整头信息 - RLP 编码该区块头
- 在 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 上可能为 0baseFeePerGas在 EIP-1559 后是必填字段(OP 支持 1559)- 区块必须在
[block.number - 256, block.number - 2]范围内
7. 技术要点
| 要点 | 说明 |
|---|---|
| RLP 编码 | Ethereum 的标准序列化格式,用于区块头、交易等 |
| OP 区块结构 | Optimism 的区块格式与以太坊有差异(Bedrock 升级后) |
| 时间窗口约束 | 合约检查区块在 256 个区块内(约 512 秒),防止使用过旧的区块 |
blockhash 可用性 | EVM 只保存最近 256 个区块的哈希 |