L1 Oracle Reader — 实现
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Build a trustless L1 contract that reads L2 Oracle prices via era Mailbox proof verification, enabling L1 DApps to query BabyDriver Oracle data.
Architecture: Standalone Sidecar contract (same pattern as Phase 3 FastWithdrawalPoolV2). L2 OracleHub sends prices via L2→L1 messages. Anyone can submit a Merkle proof to L1OracleReader.updatePrice(), which verifies inclusion via IMailbox.proveL2MessageInclusion() and stores the price. Reuses existing IMailbox.sol and MockMailbox.sol from Phase 3.
Tech Stack: Solidity 0.8.26, Foundry (forge), OpenZeppelin ReentrancyGuard, IMailbox (local copy of era Mailbox interface)
Existing Files You Need to Know
These files already exist and you will import/reuse them (do NOT recreate):
contracts/src/interfaces/IMailbox.sol
Minimal era Mailbox interface with L2Message struct and proveL2MessageInclusion()
contracts/test/mocks/MockMailbox.sol
Configurable mock: setDefaultResponse(bool) and setProofValid(batchNumber, index, messageHash)
contracts/src/bridge/FastWithdrawalPoolV2.sol
Reference for coding style, import paths, ReentrancyGuard usage, Mailbox interaction pattern
Build & test commands (always run from contracts/ directory):
cd /Users/judybaby/CodeBase/github/Layer2/contracts
forge build # compile
forge test # run all tests
forge test --match-contract L1OracleReaderTest -vvv # run only our tests with verboseSolidity style conventions (match FastWithdrawalPoolV2):
SPDX MIT, pragma
^0.8.26OpenZeppelin imported as
@openzeppelin/contracts/...Section separators:
// ==================== Section Name ====================/// @inheritdoc IInterfaceon all interface implementationsConstants:
UPPER_SNAKE_CASE, publicPrivate storage:
_prefixedwith underscoreImmutables:
UPPER_SNAKE_CASE, publicRequire strings: short, descriptive English
Test addresses: hex constants like
address(0x1001)Test helper functions:
_prefixedinternal
Task 1: Create IL1OracleReader Interface
Files:
Create:
contracts/src/interfaces/IL1OracleReader.sol
Step 1: Write the interface
Create contracts/src/interfaces/IL1OracleReader.sol:
Step 2: Verify it compiles
Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge build Expected: Compilation success (interface-only, no dependencies beyond Solidity)
Step 3: Commit
Task 2: Create L1OracleReader Contract Skeleton + Constructor Tests
Files:
Create:
contracts/src/oracle/L1OracleReader.solCreate:
contracts/test/L1OracleReader.t.sol
Step 1: Write the failing tests
Create contracts/test/L1OracleReader.t.sol:
Step 2: Run tests to verify they fail
Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge test --match-contract L1OracleReaderTest -vvv Expected: FAIL — L1OracleReader does not exist yet
Step 3: Write minimal L1OracleReader skeleton
Create contracts/src/oracle/L1OracleReader.sol:
Step 4: Run tests to verify they pass
Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge test --match-contract L1OracleReaderTest -vvv Expected: 4 tests PASS
Step 5: Commit
Task 3: Implement updatePrice Core Logic (TDD)
Files:
Modify:
contracts/src/oracle/L1OracleReader.sol(replaceupdatePricestub)Modify:
contracts/test/L1OracleReader.t.sol(add updatePrice tests)
Step 1: Write the failing tests
Add these tests to contracts/test/L1OracleReader.t.sol inside the L1OracleReaderTest contract, after the constructor tests:
Step 2: Run tests to verify they fail
Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge test --match-contract L1OracleReaderTest -vvv Expected: 9 new tests FAIL (updatePrice still reverts "Not implemented")
Step 3: Implement updatePrice
Replace the updatePrice function in contracts/src/oracle/L1OracleReader.sol:
Step 4: Run tests to verify they pass
Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge test --match-contract L1OracleReaderTest -vvv Expected: All 13 tests PASS
Step 5: Commit
Task 4: Multiple Pairs + Update Sequencing Tests (TDD)
Files:
Modify:
contracts/test/L1OracleReader.t.sol(add multi-pair and sequencing tests)
Step 1: Write the tests
Add these tests to contracts/test/L1OracleReader.t.sol:
Step 2: Run tests to verify they pass
Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge test --match-contract L1OracleReaderTest -vvv Expected: All 18 tests PASS (these test existing functionality, should pass immediately)
Step 3: Commit
Task 5: E2E Lifecycle Test
Files:
Modify:
contracts/test/L1OracleReader.t.sol(add E2E test)
Step 1: Write the E2E test
Add this test to contracts/test/L1OracleReader.t.sol:
Step 2: Run tests to verify they pass
Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge test --match-contract L1OracleReaderTest -vvv Expected: All 19 tests PASS
Step 3: Commit
Task 6: Full Test Suite Verification
Files: None modified — verification only
Step 1: Run the full project test suite
Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge test -vv Expected: ALL tests pass (existing 114 + new 19 = 133 total, approximately)
Check that:
All L1OracleReaderTest tests pass (19)
All FastWithdrawalPoolV2Test tests pass (31)
All Bridge.t.sol tests pass
All E2E.t.sol tests pass
No regressions
Step 2: Run forge build to confirm clean compilation
Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge build Expected: Compilation success, no errors
Step 3: Final commit if any cleanup needed
If all tests pass with no changes needed, skip this step.
Summary
1
0
feat(oracle): add IL1OracleReader interface
2
4
feat(oracle): L1OracleReader skeleton + constructor tests
3
13
feat(oracle): implement updatePrice with proof verification
4
18
test(oracle): add multi-pair and submission tests
5
19
test(oracle): add E2E lifecycle test
6
19 (verify all 133)
(verification only)
Total: 6 tasks, 19 new tests, ~5 commits
Last updated