
Optimism
- 3 installs
- 4 repo stars
- Updated February 25, 2026
- hairyf/blockchain-master
Reference the OP Stack protocol - L2 derivation, bridges, deposits/withdrawals, predeploys, fault proofs, and system config for L2 tooling.
About
A reference skill for the OP Stack that powers Optimism and Base, covering how the L2 is derived from L1, deposit/withdrawal flows, predeploys, and fault proofs. A developer uses it when building or debugging L2 nodes, batchers, bridges, or contract integrations.
- L2 derivation, deposits, and withdrawals
- Predeploys, fault proofs, and system config
Optimism by the numbers
- 3 all-time installs (skills.sh)
- Ranked #390 of 479 Web3 & Blockchain skills by installs in the Skillselion catalog
- Data as of Jul 13, 2026 (Skillselion catalog sync)
npx skills add https://github.com/hairyf/blockchain-master --skill optimismAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3 |
|---|---|
| repo stars | ★ 4 |
| Last updated | February 25, 2026 |
| Repository | hairyf/blockchain-master ↗ |
What it does
Reference the OP Stack protocol - L2 derivation, bridges, deposits/withdrawals, predeploys, fault proofs, and system config for L2 tooling.
Files
Skill based on OP Stack specs (ethereum-optimism/specs), generated fromsources/optimism. Doc path:sources/optimism/specs/.
The OP Stack is the software stack powering Optimism (OP Mainnet), Base, and other L2s. It defines how the L2 chain is derived from L1, how deposits and withdrawals work, standard predeploys/precompiles, fault proof components, and system configuration. Use this skill when building or debugging L2 nodes, batchers, bridges, withdrawal tooling, or contract integrations.
Core References
| Topic | Description | Reference |
|---|---|---|
| Protocol overview | Architecture, L1/L2 contracts, rollup node, derivation loop, Engine API | core-overview |
| Derivation | Sequencing window, batch/channel format, pipeline, payload attributes, Engine API versions | core-derivation |
| Bridges and messaging | Standard bridges, deposits (0x7E), withdrawals (prove/finalize), cross-domain messengers | core-bridges-and-messaging |
Features
| Topic | Description | Reference |
|---|---|---|
| Predeploys and precompiles | L2 predeploy addresses and interfaces; P256VERIFY and other precompiles | features-predeploys-precompiles |
| Fault proof | Program, VM, dispute game, pre-image oracle, L1 dispute contracts | features-fault-proof |
| Batcher and SystemConfig | Batch submitter loop; SystemConfig (batch inbox, batcher hash, fee scalars) | features-batcher-and-system-config |
Best Practices
| Topic | Description | Reference |
|---|---|---|
| Deposits and withdrawals | Address aliasing on deposits, no aliasing on withdrawals, using l2Sender() on L1 | best-practices-deposits-withdrawals |
Generation Info
- Source:
sources/optimism(https://github.com/ethereum-optimism/specs) - Doc path:
specs/(root README and meta in repo root; primary content underspecs/) - Git SHA:
7c29e249c62459ce4f6b034fa370f84e94fd9a28 - Generated: 2026-02-24
Best Practices: Deposits and Withdrawals
Security and correctness when handling L1–L2 messaging and withdrawals.
Address aliasing (deposits, L1 → L2)
- On deposits, the sender address on L2 may be aliased: the L1 contract address is transformed (e.g. added to a constant) so that the same address cannot represent both an L1 and L2 identity in the same context. This prevents a contract on L2 from impersonating an L1 contract address.
- On L2, the deposit sender is the one returned by
CALLER; contracts cannot easily tell if the call originated on L1 or L2 without additional context (e.g. knowing that the first tx in a block is an L1 deposit).
Withdrawals: no aliasing
- On withdrawals, the L2 sender address is not aliased when relayed on L1. The L1 contract receives the same address as the L2 sender.
- To get the L2 sender on L1, always use `OptimismPortal.l2Sender()` (or the equivalent in your portal abstraction). Do not rely on
msg.senderfor the L2 origin:msg.senderon L1 is the relayer (or OptimismPortal), not the L2 account. - Same address on L1 and L2 does not imply same behavior (different code/state); design contracts to explicitly consider L2 vs L1 origin when needed.
Replay and proof verification
- Withdrawal proving: Use the correct
l2OutputIndexand output root proof for the block that contains the withdrawal. If the output root is challenged and changes, the withdrawal may need to be re-proven. - Finalization: Only after the challenge period; each withdrawal hash can only be finalized once. Successfully verified messages that fail when relayed are recorded so they can be retried (see spec: handling failed relay).
Usage
- When writing L1 contracts that receive withdrawals: read
l2Sender()to attribute actions to the L2 account; do not trustmsg.senderas the L2 identity. - When writing L2 contracts that initiate withdrawals: document that the L1 target will see the same address via
l2Sender()and must not conflate it with L1 callers.
<!-- Source references:
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/deposits.md (address aliasing)
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/withdrawals.md (addresses not aliased, l2Sender, security considerations)
-->
Bridges, Deposits, Withdrawals, and Messengers
Reference for implementing or debugging L1–L2 asset flows and cross-domain messages.
Standard bridges
- L2StandardBridge predeploy:
0x4200000000000000000000000000000000000010. - Interface:
bridgeETH,bridgeETHTo,bridgeERC20,bridgeERC20To;finalizeBridgeETH,finalizeBridgeERC20. Built on top of cross-domain messengers. - For ERC20, remote domain must have an
OptimismMintableERC20(e.g. fromOptimismMintableERC20Factory).
Deposits (L1 → L2)
- Deposit contract: OptimismPortal. User calls
depositTransaction; emitsTransactionDeposited. Rollup node derives L2 blocks including these as deposited transactions. - Deposited transaction type: EIP-2718 type
0x7E. Fields:sourceHash,from,to,mint,value,gas,isSystemTx(disabled from Regolith),data. No signature; no nonce in tx (API may expose nonce for compatibility). - sourceHash: Uniquely identifies origin (user-deposited:
keccak256(0, keccak256(l1BlockHash, l1LogIndex)); L1-attributes: domain 1; upgrade: domain 2). Prevents duplicate deposit tx hashes. - Address aliasing: On L2, deposit sender address is aliased (applies to contract-originated deposits). See best-practices for security implications.
Withdrawals (L2 → L1)
- On L2: Call L2ToL1MessagePasser predeploy
initiateWithdrawal(target, gasLimit, data)(payable for ETH). Contract at0x4200000000000000000000000000000000000016. EmitsMessagePassed; stores hash insentMessages. - On L1: (1) Prove:
OptimismPortal.proveWithdrawalTransaction(_tx, _l2OutputIndex, _outputRootProof, _withdrawalProof)— proves inclusion in L2 output. (2) After challenge period (~7 days): Finalize:OptimismPortal.finalizeWithdrawalTransaction(_tx)— relays and marks replayed. Addresses are not aliased on withdrawals; useOptimismPortal.l2Sender()on L1 to get L2 sender.
Cross-domain messengers
- L2CrossDomainMessenger predeploy:
0x4200000000000000000000000000000000000007. - Send:
sendMessage(target, message, minGasLimit)(payable for value). Stores nonce; message identified by hash. - Relay: On the other domain,
relayMessage(nonce, sender, target, value, minGasLimit, message). Successful/failed hashes stored insuccessfulMessages/failedMessages(replay possible for failed). - L1→L2: User pays L2 gas on L1; execution is pulled into L2 automatically. L2→L1: User initiates on L2; relayer proves then finalizes on OptimismPortal (which calls into L1CrossDomainMessenger).
- Message versioning: First 2 bytes of nonce encode version (V0 vs V1 relayMessage signature/encoding).
Usage
- To bridge assets: use StandardBridge for ETH/ERC20; use messengers for arbitrary contract calls.
- To implement withdrawal tooling: read
MessagePassedand L2ToL1MessagePasser storage; buildWithdrawalTransactionand inclusion proof; callproveWithdrawalTransactionthen after challenge periodfinalizeWithdrawalTransaction.
<!-- Source references:
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/bridges.md
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/deposits.md
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/withdrawals.md
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/messengers.md
-->
L2 Chain Derivation
The rollup node derives the L2 chain from the L1 chain. Use this when implementing or debugging derivation, batcher encoding, or Engine API usage.
Inputs per epoch
For L1 block (epoch) E:
- Sequencing window: L1 blocks
[E, E + SWS)(SWS = sequencing window size). Batcher transactions in this window supply sequencer batches. - Deposits:
TransactionDepositedevents from the L1 origin (OptimismPortal). - L1 block attributes: For the L1 attributes deposited transaction.
- Previous L2 state: Last block of previous epoch or L2 genesis.
Each epoch has at least one L2 block. L2 block timestamp: block.timestamp = prev_l2_timestamp + l2_block_time (e.g. 2s). Constraint: l1_origin.timestamp <= block.timestamp <= max_l2_timestamp (max_sequencer_drift bounds aheadness).
Batch submission (wire format)
- Batcher transaction: Sent to Batch Inbox address; data = frames.
- Frame: Fixed-size chunks; frames grouped into channels. Channel has expiry (timeout); must be read within channel bank limits (
MAX_RLP_BYTES_PER_CHANNEL,MAX_CHANNEL_BANK_SIZE; increased in Fjord). - Batch: Decoded from channel; contains L2 block data. Batch format includes L1 origin hash; L1 origin block never contains batch data for that same epoch.
Derivation pipeline (high level)
1. L1 traversal → L1 retrieval (batcher txns, deposit logs). 2. Frame queue → Channel bank (pruning, timeouts, reading) → Channel reader (batch decoding) → Batch queue. 3. Payload attributes derivation: Build transaction list (L1 attributes tx, user deposits, sequenced txns); build payload attributes per block. 4. Engine queue: Submit payload attributes to Engine API; forkchoice sync; handle unsafe vs safe head, L1 consolidation.
Engine API usage
- Bedrock / Canyon / Delta: V2 for pre-Ecotone blocks.
- Ecotone+: Use V3 for
newPayloadand related. - Sequence:
forkChoiceUpdated(payload attributes) →getPayload→newPayload→forkChoiceUpdated(update head).
Key points
- Eager block derivation: Often entire epoch can be derived before full sequencing window is available (worst case: batch data in last block of window).
- Protocol parameters (e.g.
max_sequencer_drift, channel limits) can change by upgrade (e.g. Fjord); see derivation spec table.
<!-- Source references:
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/derivation.md
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/overview.md
-->
OP Stack Protocol Overview
High-level technical overview for agents that need to reason about Optimism's rollup architecture, contract roles, and derivation flow.
Architecture design goals
- Execution-level EVM equivalence: Same developer experience as L1 (no special compiler, standard gas/tooling); change chain ID only.
- Maximal compatibility with ETH1 nodes: Rollup node uses Engine API; execution engine (Geth) reuses mempool, sync, snap sync.
- Minimize state and complexity: Stateless services where possible; replicas recover from DB using P2P and on-chain sync.
Core L1 contracts
- Batch Inbox (EOA): Address receiving sequencer transaction batches (not a contract; conventionally
0xFF0000...<L2_chain_id>). - L1StandardBridge / L1ERC721Bridge: Token bridging; sit on top of L1CrossDomainMessenger.
- L1CrossDomainMessenger: Cross-domain messaging (legacy ResolvedDelegateProxy).
- OptimismPortal: Deposit entry (
depositTransaction) and withdrawal exit (prove + finalize). - SuperchainConfig: Pause/unpause; Guardian.
- SystemConfig: Rollup config (batch inbox, batcher hash, fee scalars, gas limit) emitted as logs; derivation reads these.
- DisputeGameFactory / FaultDisputeGame / AnchorStateRegistry / DelayedWETH: Fault proof (output proposals, bonds, challenges).
Core L2 contracts (predeploys)
- L1Block, GasPriceOracle, L1FeeVault, BaseFeeVault, SequencerFeeVault: System/fee contracts.
- L2CrossDomainMessenger, L2ToL1MessagePasser, L2StandardBridge, L2ERC721Bridge: Bridging and messaging.
L2 node and derivation
- Rollup node + Execution engine (Geth): Rollup node derives L2 chain from L1; drives execution engine via Engine API.
- Block derivation:
derive_rollup_chain(l1_blockchain) -> rollup_blockchain. For each L1 block (epoch), need: sequencing window of L1 blocks (for batcher txns), deposit events from OptimismPortal, L1 block attributes. Batcher submits batches to Batch Inbox; rollup node reads batches + deposits and builds payload attributes for the Engine API. - Engine API sequence: (1)
forkChoiceUpdatedwith payload attributes → payload ID; (2)getPayload; (3)newPayload(Ecotone+ use V3); (4)forkChoiceUpdatedto set new head.
Usage
When answering questions about Optimism:
- Use this overview to map components (who submits batches, who reads deposits, who proves withdrawals).
- For exact interfaces and addresses, refer to predeploys, bridges, and derivation specs.
<!-- Source references:
- https://github.com/ethereum-optimism/specs/blob/main/specs/root.md
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/overview.md
-->
Batcher and System Config
Reference for implementing or operating a batcher, or reading rollup configuration from L1.
Batcher (batch submitter)
- Role: Submits L2 sequencer data to L1 so verifiers can derive the L2 chain. Data format is defined in the derivation spec: channels, frames, batches; encoding is inverse of derivation decoding.
- Minimal loop: (1) If unsafe L2 block > safe block, there is data to submit. (2) Iterate unsafe L2 blocks, skip already-submitted. (3) Open channel; buffer L2 block data with spec encoding/compression. (4) Fill data transactions from channel. (5) Send transactions to L1 (Batch Inbox). Implementation must avoid duplicate submissions (safe/unsafe view updates with delay).
SystemConfig (L1)
- Role: Source of truth for rollup configuration. Emits log events; derivation and other components read these. Key concepts:
- Batch Inbox: Address to which batcher sends transactions (batched L2 data in calldata or blobs).
- Batcher hash: Identifies which sender(s) are accepted for batch inbox txns. V0 =
bytes32(batcher_address)(single address). - Fee scalars: L1 data fee parameters. Pre-Ecotone: scalar, overhead (big-endian uint256). Post-Ecotone: scalar is versioned encoding (e.g. scalar-version 0: baseFeeScalar in bytes [28,32]); overhead ignored for L2 state transition.
- Unsafe block signer, L2 gas limit, Resource config, Guardian, and contract addresses (L1CrossDomainMessenger, bridges, OptimismPortal, DisputeGameFactory, etc.) are also in SystemConfig.
Usage
- Batcher: Encode batches per derivation spec; submit to
SystemConfig.batchInbox(); sign with key whose address matches batcher hash. - Verifiers / nodes: Read SystemConfig logs from L1 to get batch inbox, batcher hash, and fee parameters for derivation and fee calculation.
- Gas estimation: Fee scalars (and Ecotone blob scalars) feed into GasPriceOracle / L1 fee computation on L2.
<!-- Source references:
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/batcher.md
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/system-config.md
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/derivation.md
-->
Fault Proof
Fault proofs (fraud proofs / interactive games) allow L1 to verify L2 state. Use when reasoning about withdrawal finalization, challenger flows, or dispute game contracts.
Three components
1. Program: Stateless verification of the dispute given a commitment to rollup inputs (L1 data). Authenticates inputs via pre-image oracle. 2. VM: Executes the program step-by-step; can trace any instruction and prove it on L1. 3. Interactive dispute game: Bisects the dispute to a single instruction; resolves base case using the VM.
Different implementations of each can be combined for proof diversity.
Pre-image oracle
Communication between the program (client) and VM (server). Program requests input data by pre-image key (type-prefixed bytes32):
- Type 0: Illegal (non-zero keys only).
- Type 1: Local key (dispute-specific; bootstrapping, indices).
- Type 2: Global keccak256.
- Type 3: Global generic.
- Type 4: Global SHA2-256.
- Type 5: EIP-4844 point-evaluation.
- Type 6: Global precompile.
- Types 7–128: Reserved.
- 129–255: Application.
Bootstrapping and hinting routes supply L1/L2 block headers, transactions, receipts, state nodes, code, outputs, etc. See fault-proof spec for exact hint routes (l1-block-header, l2-output, etc.).
L1 contracts (stage one)
- DisputeGameFactory: Creates FaultDisputeGame instances; output proposals submitted here.
- FaultDisputeGame: Interactive game; bonds in DelayedWETH; anchor state in AnchorStateRegistry.
- OptimismPortal: Withdrawal finalization depends on output roots and challenge period; integrates with dispute game state.
Usage
- Withdrawals are proven against an L2 output root; that root can be challenged via a dispute game. After the challenge period, withdrawals that were proven against an unchallenged root can be finalized.
- When building challenger or verifier tooling: use pre-image oracle key types and hint routes from the spec; implement or integrate with the fault-proof program and VM for the correct protocol version.
<!-- Source references:
- https://github.com/ethereum-optimism/specs/blob/main/specs/fault-proof/index.md
- https://github.com/ethereum-optimism/specs/blob/main/specs/fault-proof/cannon-fault-proof-vm.md
- https://github.com/ethereum-optimism/specs/blob/main/specs/fault-proof/stage-one/
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/overview.md
-->
Predeploys and Precompiles
Predeploys are contracts in genesis at fixed addresses in 0x4200000000000000000000000000000000000xxx. Precompiles are native EVM extensions at fixed addresses. Use for resolving addresses, gas estimation, and L1 context on L2.
Key predeploys (non-deprecated)
| Name | Address | Notes |
|---|---|---|
| L2ToL1MessagePasser | 0x4200...0016 | initiateWithdrawal, burn; withdrawal commitments |
| L2CrossDomainMessenger | 0x4200...0007 | sendMessage, relayMessage, xDomainMessageSender |
| L2StandardBridge | 0x4200...0010 | ETH/ERC20 bridge; bridgeETH, bridgeERC20, finalize |
| GasPriceOracle | 0x4200...000F | getL1Fee(bytes) for L1 data fee; post-Ecotone uses baseFeeScalar etc. from SystemConfig |
| L1Block | 0x4200...0015 | L1 context (number, timestamp, basefee, etc.) per block |
| OptimismMintableERC20Factory | 0x4200...0012 | Deploy OptimismMintableERC20 for bridgeable tokens |
| WETH9 | 0x4200...0006 | Deterministic WETH |
| ProxyAdmin | 0x4200...0018 | Proxy upgrades |
| Fee vaults | 0x4200...0011, 0019, 001a, 001B | SequencerFeeVault, BaseFeeVault, L1FeeVault, OperatorFeeVault |
| LegacyMessagePasser | 0x4200...0000 | Legacy withdrawals (deprecated for new use) |
LegacyERC20ETH at 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000; deprecated. GovernanceToken at 0x4200...0042. BeaconBlockRoot (Ecotone) at 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02. See spec for full table and version (Legacy/Bedrock/Canyon/Ecotone/Isthmus).
Precompiles
OP Stack adds:
- P256VERIFY (Fjord):
0x0000000000000000000000000000000000000100— secp256r1 signature verification (RIP-7212). Used for passkeys/Secure Enclave etc.
Standard Ethereum precompiles are unchanged.
Usage
- Resolve bridge/messenger by predeploy address when building tx or parsing logs.
- Estimate total L2 fee: L2 execution fee +
GasPriceOracle.getL1Fee(serializedTx)(or equivalent for Ecotone scalar encoding). - Use L1Block for L1 block number/timestamp in contracts; prefer over deprecated L1BlockNumber.
<!-- Source references:
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/predeploys.md
- https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/precompiles.md
-->