多符号 — 实现

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Allow the Operator to dynamically register new price symbols on OracleHub, and expand genesis initialization to include 5 symbols (ETH/USD, BTC/USD, USDC/USD, SOL/USD, BNB/USD).

Architecture: Two-pronged approach. (A) Expand genesis initialize() call to register all 5 symbols at deployment. (B) Relax addSymbol from onlySystemCall to onlySystemCall OR onlyOperator, and add batchAddSymbols for bulk registration. Tests use OracleHubLocal (Foundry-testable mirror that replaces onlySystemCall with onlyAdmin).

Tech Stack: Solidity ^0.8.20/^0.8.26, Foundry (forge test), TOML config


Task 1: Add batchAddSymbols to IOracleHub interface

Files:

  • Modify: era-contracts-l1/system-contracts/contracts/interfaces/IOracleHub.sol:39-44

Step 1: Add the new function signature to the interface

Open era-contracts-l1/system-contracts/contracts/interfaces/IOracleHub.sol. In the // --- Admin section (line 39), add batchAddSymbols after addSymbol:

    // --- Admin (system call or operator) ---
    function addSymbol(bytes32 symbolHash) external;
    function batchAddSymbols(bytes32[] calldata symbolHashes) external;
    // --- Admin (system call only) ---
    function removeSymbol(bytes32 symbolHash) external;
    function setConfig(uint256 stalenessThreshold, uint256 deviationThreshold, uint8 minSourceCount) external;
    function setOperator(address _operator) external;
    function operator() external view returns (address);

The key change: addSymbol and batchAddSymbols are grouped under "system call or operator", while removeSymbol/setConfig/setOperator stay under "system call only".

Step 2: Verify file compiles

Run: cd /Users/judybaby/CodeBase/github/Layer2/era-contracts-l1/system-contracts && npx hardhat compile 2>&1 | tail -5 Expected: Compilation error (OracleHub.sol doesn't implement batchAddSymbols yet — that's OK, we'll fix in Task 2)

Step 3: Commit


Task 2: Implement _isSystemCallOrOperator + modify addSymbol + add batchAddSymbols in OracleHub.sol

Files:

  • Modify: era-contracts-l1/system-contracts/contracts/OracleHub.sol:131-139

This is the main system contract at 0x8016. It uses the real SystemContractHelper for onlySystemCall.

Step 1: Add the _isSystemCallOrOperator internal function

Add this function in the // ==================== Internal ==================== section (before _updatePrice, around line 193):

You need to add the SystemContractHelper import. Check if it's already imported via SystemContractBase. Open era-contracts-l1/system-contracts/contracts/abstract/SystemContractBase.sol — it imports SystemContractHelper from ../libraries/SystemContractHelper.sol. Since OracleHub inherits SystemContractBase, SystemContractHelper is already accessible. But we need to import it directly since we're calling it in our own function:

Add at the top of OracleHub.sol (after line 3):

Step 2: Modify addSymbol to use dual-permission check

Replace the current addSymbol (lines 133-139):

Step 3: Add batchAddSymbols function

Add this right after addSymbol:

Step 4: Update the section comment

Change line 131 from:

to:

And add a new section comment before removeSymbol:

Step 5: Verify compilation

Run: cd /Users/judybaby/CodeBase/github/Layer2/era-contracts-l1/system-contracts && npx hardhat compile 2>&1 | tail -5 Expected: Compiled successfully

If SystemContractHelper import causes issues (already available via inheritance), remove the explicit import and use the inherited one.

Step 6: Commit


Task 3: Sync contracts-preprocessed copies

Files:

  • Modify: era-contracts-l1/system-contracts/contracts-preprocessed/OracleHub.sol

  • Modify: era-contracts-l1/system-contracts/contracts-preprocessed/interfaces/IOracleHub.sol

The contracts-preprocessed/ directory must mirror contracts/ exactly for system contract compilation.

Step 1: Copy both files

Step 2: Verify the preprocessed copies match

Expected: No output (files identical)

Step 3: Commit


Task 4: Update OracleHubLocal.sol (Foundry-testable mirror)

Files:

  • Modify: contracts/src/oracle/OracleHubLocal.sol:134-155

OracleHubLocal replaces onlySystemCall with onlyAdmin for local Foundry testing. We need to mirror the permission change: addSymbol now allows both admin AND operator.

Step 1: Add _isAdminOrOperator internal function

Add before _updatePrice (around line 192):

Step 2: Modify addSymbol to use dual-permission check

Replace lines 136-141:

Step 3: Add batchAddSymbols function

Add right after addSymbol:

Step 4: Keep removeSymbol as onlyAdmin only — no change needed

Step 5: Verify it compiles

Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge build 2>&1 | tail -5 Expected: Compiled successfully

Step 6: Commit


Task 5: Write 6 new Foundry tests

Files:

  • Modify: contracts/test/OracleHub.t.sol (append to OracleHubOperatorTest contract)

All 6 new tests go inside the existing OracleHubOperatorTest contract (which uses OracleHubLocal and already has operatorAddr, adminAddr, stranger addresses set up).

Step 1: Write the 6 tests

Append these tests at the end of OracleHubOperatorTest (before the closing }):

Step 2: Run tests to verify they fail

Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge test --match-contract OracleHubOperatorTest --match-test "test_addSymbol_by_operator|test_addSymbol_by_admin|test_addSymbol_by_random_reverts|test_batchAddSymbols_by_operator|test_batchAddSymbols_empty_reverts|test_removeSymbol_by_operator_reverts" -vv 2>&1 | tail -20

Expected: If Task 4 was completed, tests should PASS. If not yet, they will fail with "function not found" since OracleHubLocal doesn't have the new functions yet.

Step 3: Run ALL tests (regression)

Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge test --match-contract OracleHub -vv 2>&1 | tail -30

Expected: All existing tests + 6 new tests pass. No regressions.

Step 4: Commit


Task 6: Update baby-chain.toml — uncomment 4 symbols

Files:

  • Modify: config/baby-chain.toml:25-44

Step 1: Uncomment the 4 symbol configurations

Replace lines 25-44 with the uncommented versions:

Also update the NOTE comment (lines 17-19) to reflect new state:

Step 2: Verify TOML is valid

Run: python3 -c "import tomllib; tomllib.load(open('config/baby-chain.toml', 'rb')); print('OK')" Expected: OK

Step 3: Verify oracle-wiring Rust code still compiles (no Rust changes needed, just verify config parsing)

Run: cd /Users/judybaby/CodeBase/github/Layer2/baby-modules/oracle-wiring && cargo check 2>&1 | tail -5 Expected: Finished (no errors)

Step 4: Commit


Task 7: Final regression + dev-log update

Files:

  • Modify: docs/dev-log.md (append entry)

Step 1: Run full Foundry test suite

Run: cd /Users/judybaby/CodeBase/github/Layer2/contracts && forge test -vv 2>&1 | tail -30 Expected: All tests pass (existing + 6 new)

Step 2: Run oracle-wiring tests

Run: cd /Users/judybaby/CodeBase/github/Layer2/baby-modules/oracle-wiring && cargo test 2>&1 | tail -15 Expected: All tests pass

Step 3: Update dev-log

Append to docs/dev-log.md:

Step 4: Commit

Last updated