---
# System prepended metadata

title: OP

---

# OP

# Current OP

It seems current OP is a very centralized system, where sequencer, proposer, fraudverifier, bond manager all have a single address, likely controlled by optimism team. If this is the case, I found it hard for the system to really go wrong.

## Q1: enqueue() and appendSequencerBatch() in CanonicalTransactionChain.sol do not check the order of transactions, how is it being ensured?

## Q2: for deposit transactions, L2bridge received the cross domain message with ```require(undoL1ToL2Alias(msg.sender) == l1CrossDomainMessager)```.
My question is how is this msg sent from this sender? L1CrossDomainMessager is not predeployed, therefore the sender should have a random address on L2
https://github.com/ethereum-optimism/optimism/blob/1975480fc04d532ebf5cf8ff263a8f3b626f5aff/packages/contracts/contracts/L2/messaging/L2CrossDomainMessenger.sol#L102
 
## Q3: role of replayMessage
how does replayMessage work? It can be called by anyone and the same existing transaction may be processed more than once. Is it a concern?
https://github.com/ethereum-optimism/optimism/blob/e4ef92a63c3aceeda2a2306429b04df4a25c97c8/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol#L250

## Q4: time window requirement is not honored immediately after deleteElement 
After deleteElementsAfterInclusive is call, *_lastSequencerTimestamp* in extraData is assigend to 0 
https://github.com/ethereum-optimism/optimism/blob/b1d5fd2c5653a664eae7cca7125127ec483c0443/packages/contracts/contracts/L1/rollup/StateCommitmentChain.sol#L285
which gives a window for non sequencer to submit new batches regardless of the actual timestamp.
https://github.com/ethereum-optimism/optimism/blob/b1d5fd2c5653a664eae7cca7125127ec483c0443/packages/contracts/contracts/L1/rollup/StateCommitmentChain.sol#L241

## Q5: this version of deleteElementsAfterInclusive reuses most recent context, which would result in using wrong extraData for later appends. This function is not being used currently, but may not deserve its existence in the first place

https://github.com/ethereum-optimism/optimism/blob/b1d5fd2c5653a664eae7cca7125127ec483c0443/packages/contracts/contracts/L1/rollup/ChainStorageContainer.sol#L119

For example, when used for StateCommintmentChain, when new data are pushed
https://github.com/ethereum-optimism/optimism/blob/b1d5fd2c5653a664eae7cca7125127ec483c0443/packages/contracts/contracts/L1/rollup/ChainStorageContainer.sol#L95
ChainStorageContainer will take existing context.extraData, which would have wrong total # of elements. 

This would require wrong _shouldStartAtElement for new appendStateBatch() call
https://github.com/ethereum-optimism/optimism/blob/b1d5fd2c5653a664eae7cca7125127ec483c0443/packages/contracts/contracts/L1/rollup/StateCommitmentChain.sol#L90

Recommendation:
disallow the use of this version of deleteElementsAfterInclusive 

## Q6: Use of magic number:
https://github.com/ethereum-optimism/optimism/blob/46bfb3c31fad2497fe87879e67116766005bad6a/packages/contracts/contracts/L1/rollup/CanonicalTransactionChain.sol#L392
use BATCH_CONTEXT_START_POS instead

## Q7: I may get this wrong entirely, but it seems if a _gasLimit is passed, it will pass all tests, thus an user may spam enqueue()?
https://github.com/ethereum-optimism/optimism/blob/91ba02e1c5c34f7f74fef5e75111fc2453f56acc/packages/contracts/contracts/L1/rollup/CanonicalTransactionChain.sol#L239

## Q8: Arbitrum has the ambition of deploying multiple rollups. If OP has that ambition at some point, does it make sense to add chainID to transactionHash creation, so to prevent replay on different chains?
https://github.com/ethereum-optimism/optimism/blob/91ba02e1c5c34f7f74fef5e75111fc2453f56acc/packages/contracts/contracts/L1/rollup/CanonicalTransactionChain.sol#L265

## Q9: No unpause()?
https://github.com/ethereum-optimism/optimism/blob/e4ef92a63c3aceeda2a2306429b04df4a25c97c8/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol#L99

## Q10: why the extra redicrection from _getBatchContext(i) to nextContext  to curContext and not direct `curContext = _getBatchContext(i);`?
https://github.com/ethereum-optimism/optimism/blob/91ba02e1c5c34f7f74fef5e75111fc2453f56acc/packages/contracts/contracts/L1/rollup/CanonicalTransactionChain.sol#L322

## Q11: is emit _data necessary when it is in calldata already?
https://github.com/ethereum-optimism/optimism/blob/91ba02e1c5c34f7f74fef5e75111fc2453f56acc/packages/contracts/contracts/L1/rollup/CanonicalTransactionChain.sol#L275
https://github.com/ethereum-optimism/optimism/blob/5ee2af9ac1e678d37435475ca3f3f4da6f27f302/packages/contracts/contracts/L1/messaging/L1StandardBridge.sol#L222


## Q12: why use public, not external when no internal calls to these functions?
https://github.com/ethereum-optimism/optimism/blob/91ba02e1c5c34f7f74fef5e75111fc2453f56acc/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol#L141
https://github.com/ethereum-optimism/optimism/blob/91ba02e1c5c34f7f74fef5e75111fc2453f56acc/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol#L171
https://github.com/ethereum-optimism/optimism/blob/91ba02e1c5c34f7f74fef5e75111fc2453f56acc/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol#L238

## Q13: going through the call chain, I didn't find it necessary to ```require(_target != resolve("CanonicalTransactionChain")```. As it has passed all the proofs, it is not really possible to have it false
https://github.com/ethereum-optimism/optimism/blob/37066088bfb8d6b0323e299056f7150ab7cefc47/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol#L197

## Q14: if a transaction from 7 days ago was proven fraud, what happens to the follow-up transactions? Do they need to be resubmitted by the sequencer? in one block or multiple blocks? Would they start with new fraud-proof time window? Will there be potential DDOS? I don't have a good understanding of the events following a fraud proof in general.

## Q15: is the proof encoded by the l2geth node or in some other way? which specific code that does that?
https://github.com/ethereum-optimism/optimism/blob/46bfb3c31fad2497fe87879e67116766005bad6a/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol#L170

# Bedrock

## Q1: rollup node is expected to derive deposit transaction from opaquedata, but wouldn't encodePacked be ambiguous? 
https://github.com/ethereum-optimism/optimism/blob/f772f66cfcb59e57d43bdd0419baf5a5ee96228e/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol#L264

## Q2: sendMessage lacks access control, is the expectation to be checked by off-chain nodes?
https://github.com/ethereum-optimism/optimism/blob/f772f66cfcb59e57d43bdd0419baf5a5ee96228e/packages/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol#L180

## Q3: depositTransaction can be called through L1SB then L1CDM, however it can be called directly as well. When to use which?
https://github.com/ethereum-optimism/optimism/blob/f772f66cfcb59e57d43bdd0419baf5a5ee96228e/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol#L242

## initiateWithdrawal call be called through L2SB then L2CDM, however it can be called directly as well. When to use which?
https://github.com/ethereum-optimism/optimism/blob/f772f66cfcb59e57d43bdd0419baf5a5ee96228e/packages/contracts-bedrock/contracts/L2/L2ToL1MessagePasser.sol#L98

## Q4: who is calling finalizeWithdrawalTransaction?
https://github.com/ethereum-optimism/optimism/blob/f772f66cfcb59e57d43bdd0419baf5a5ee96228e/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol#L125

## Q5: how is GasPriceOracle.sol used?

## Q6: how is isBlockFinalized used in
https://github.com/ethereum-optimism/optimism/blob/f772f66cfcb59e57d43bdd0419baf5a5ee96228e/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol#L217

# Random notes below, please ignore

# Cannon

## _bytes.length - _start may overflow, however, it is checked in slice()
https://github.com/ethereum-optimism/cannon/blob/dfac3fb2e09bb974e77e6563a64d898d049a2a90/contracts/lib/Lib_BytesUtils.sol#L174



## to check
https://github.com/nomad-xyz/docs/blob/1ff0c55dba2a842c811468c57793ff9a6542ef0f/docs/public/Nomad-Audit.pdf





---


---


---


|     | Current OP          | Bedrock          | Nitro               |
| ----------------- |:----------------------- |:----------------------- |:----------------------- |
| L2 Block Size | One tx per block | Multiple txs per block | One tx per L2 block. Rollup protocol produces a chain of Rollup Blocks (RBlocks), which encapsulates a sequence of L2 blocks |
| L2 Block Time | Variable | Fixed 2 secs per block | Variable |
| Architecture base layer | |  Execution engine (EE) is a vanilla Geth node with minor modifications to support Optimism. It maintains L2 state. Batch Submitter submits transaction batches to a BatchInbox address. Output Submitter submits L2 output commitments to the L2OutputOracle. All written in Go. | Geth, as a library with neccessary hooks, emulate the execution of EVM contracts and maintain data strucutre. State Transition Function is compiled into a modified version of WASM, called WAVM, and used for proving, which assures machine-independentness. WAVM allows a mix of Rust, C, Go for different modules |
| Architecture middle layer | | Rollup Node is a standalone, stateless binary. It receives L2 transactions from users, syncs and verifies rollup data on L1, applies rollup-specific block production rules to synthesize blocks from L1, appends blocks to the L2 chain using the Engine API, handles L1 reorgs. The fault proof Cannon is half Geth, half MIPS | Custom software called ArbOS with L2 functions, such as decompressing, parsing data batches, accounting for L1 gas costs and collecting fees, cross-chain bridge functionalities. State Transition Function uses the same code as base layer, but compiled for native execution in Nitro node, which assures fast execution |
| Architecture top layer | | EE uses Geth's built-in peer-to-peer network and transaction pool to propagate transactions. The same network can also be used to propagate submitted blocks and support snap-sync. | Node software, mostly drawn from Geth, handles connection and RPC requires to opearte as an Ethereum compatible blockchain node  |
| P2P Data Availability | | The rollup node has an optional peer-to-peer (P2P) network service to improve the latency between the view of sequencers and the rest of the network by bypassing the L1 in the happy case, without relying on a single centralized endpoint | A variant of Nitro, called AnyTrust, relies on an external data availabitlity committe to store and provie data on demand  |
| L1 to L2 message inclusion delay |  | a few blocks for confirmation, but may derive L2 from L1 as much as 10 mins ago to ensure liveness | 10 mins to avoid potential L1 reorg |
| L1 to L2 sequencer censorship resistence | user may enqueue tx directly to CanonicalStateChain | lower-level call for deposits via L1 Portal contract | User can add txs via a L1 Delayed Inbox, which will be included after 10 mins delay to avoid L1 reorg. After 24 hrs, an user can force-include it to Inbox contract  |
| L1 to L2 message retry mechanism |  | L1 tx that lands in L2 cross-domain message will have its hash recorded, thus retryable. It is implemented in Solidity | ArbOS creates retryable tickets for failed txs. It also esrows callvalue for ETH transactions. After one week, unredeemed tickets are deleted and callvalue refunded |
| L1 to L2 fungible token bridge |  |  | The tx, that deposites n tokens to an L1 contract known as Token Gateway, creates a retryale transaction that mints n tokens of an L2-counterpart contract. |
| L2 to L1 message | | | Initiated via L2 ArbSys precomiple. |
| L2 to L1 fungible token bridge |  |  | A withdrawal of m tokens is initiated via an L2 tx which burns m tokens on L2 and creates a L2 to L1 message, which upon confirmation, release the tokens from L1 Token Gateway |
| L2 fungible token address |  |  | By default, tokens are bridged via a deterministically generated CREATE2 address. An L1 token contract can register itself for other custom gateway |
| L2 to L1 state representation | | | Once a RBlock is confirmed, the root hash of all L2 to L1 messages' Merkle tree is updated in an Outbox contract on L1. User can call the Outbox contract with Merkle proof of inclusion of the message to redeem it |
| non-fungible token bridge |  | A separate bridge for ERC721 is implemented in the periphery package. Other assets will require new bridge implementation | Built by independent services |
| L1 fee algorithm | | backward-looking basefee * a small multiplier | an adaptive algorithm that cause the Sequencer's long term reimbursement to close to its long term costs. A small per data unit reward is added. Fees are apportioned among txs based on estimation of data compression |
| L2 fee algorithm | flat fee + surge pricing | reuse EIP-1559 | bespoke gas metering system due to 1 tx per block. Base adjustment is determined at one-second interval using a expenential function based on backlog |
| Fault proof | currently not operational | compiles to the MIPS instruction set architecture. state root, potentially over many batches at once | d-way disection over three phrase, first disecting over blocks with on RBlock, then disecting over WAVM instructions, at last, call a one-step proof verification contract on Ethereum, passing it a single instruction witness |
| L1 Preimage oracle | N/A | Batches hash are not stored in a contract (leading to some gas savings). Instead, we walk back the L1 chain using the L1 block headers, then walk down the transaction Merkle root to find the batches in the calldata | State hashs are stored in a special L1 account in special memory layout to map keys to storage slots using Merkle Patricia state trie data structure. The nodes of the tree are stored in a database, indexed by Merkle hash of the node, outside of STF's storage |
| L2 Preimage oracle | N/A | On-chain, preimages can be presupplied in advance. Off-chain, read L2 states directly | same as bedrock |
| Large preimages on L1 due to large logs | N/A | Plan to use zk-proof to prove the value of some bytes within the preimage  | Store a hash of the message |
| State Storage |  | Stored in ordinary EVM contracts | State hashs are stored in a special L1 account in special memory layout to map keys to storage slots using Merkle Patricia state trie data structure. The nodes of the tree are stored in a database, indexed by Merkle hash of the node, outside of STF's storage |
| State roots posting | N/A | Not posted frequently, encompassing the validation of many blocks/batches | Posted with each set of batches (RBlock) posted to L1 |
| Batches & state roots | N/A | Seperately posting batch more often than state roots. State roots are posted frequently, encompassing the validation of many blocks/batches  | RBlocks are posted to L1,  containing both batches and state roots |
| Invalid txs | N/A | Throw out "garbage" txs based on the same code as fraud proof  | allowed |
| Precomiples | N/A | so far, pre-deploys only, which are actual EVM contracts at special addresses since genesis block | for L2-to-L1 message passing |
| Tx Ordering | | | Sequencer order txs based on first-come, first served policy |
| Tx Publishing | | | Two ways: a) real-feed that anyone can subscribe to, b) post compressed tx sequence as Ethereum calldata to Inbox contract |
