Skip to main content
Learn the OP Stack — stop 8 of 13. You’ve followed a transaction that starts and ends on L2. This page adds the first cross-layer direction: how a transaction triggered on L1 becomes an L2 transaction. When you’re done, continue to Withdrawal flow.
This page explains the deposit flow process for L2 deposit transactions, triggered by transactions or events on L1. In Optimism terminology, “deposit transaction” refers to any L2 transaction that is triggered by a transaction or event on L1. The process is somewhat similar to the way most networking stacks work. Information is encapsulated in lower layer packets on the sending side and then retrieved and used by those layers on the receiving side while going up the stack to the receiving application. Deposit Flow Diagram.

L1 processing

  1. An L1 entity, either a smart contract or an externally owned account (EOA), sends a deposit transaction to L1CrossDomainMessenger, using sendMessage. This function accepts three parameters:
    • _target, target address on L2.
    • _message, the L2 transaction’s calldata, formatted as per the ABI of the target account.
    • _minGasLimit, the minimum gas limit allowed for the transaction on L2. Note that this is a minimum and the actual amount provided on L2 may be higher (but never lower) than the specified gas limit. The actual amount provided on L2 is often higher because the portal contract on L2 performs some processing before submitting the call to _target.
  2. The L1 cross domain messenger calls its own _sendMessage function. It uses these parameters:
    • _to, the destination address, is the messenger on the other side. In the case of deposits, this is always 0x4200000000000000000000000000000000000007.
    • _gasLimit, the gas limit. This value is calculated using the baseGas function.
    • _value, the ETH that is sent with the message. This amount is taken from the transaction value.
    • _data, the calldata for the call on L2 that is needed to relay the message. This is an ABI encoded call to relayMessage.
  3. _sendMessage calls the portal’s depositTransaction function. Note that other contracts can also call depositTransaction directly. However, doing so bypasses certain safeguards, so in most cases it’s a bad idea.
  4. The depositTransaction function runs a few sanity checks, and then emits a TransactionDeposited event.

L2 processing

  1. The op-node component looks for TransactionDeposited events on L1. If it sees any such events, it parses them.
  2. Next, op-node converts those TransactionDeposited events into deposit transactions.
  3. In most cases, user deposit transactions call the relayMessage function of L2CrossDomainMessenger.
  4. relayMessage runs a few sanity checks and then, if everything is good, calls the real target contract with the relayed calldata.

Denial of service (DoS) prevention

As with all other L1 transactions, the L1 costs of a deposit are borne by the transaction’s originator. However, the L2 processing of the transaction is performed by the Optimism nodes. If there were no cost attached, an attacker could submit a transaction that had high execution costs on L2, and that way perform a denial of service attack. To avoid this DoS vector, depositTransaction, and the functions that call it, require a gas limit parameter. This gas limit is encoded into the TransactionDeposited event, and used as the gas limit for the user deposit transaction on L2. This L2 gas is paid for by burning L1 gas here.

Replaying failed deposits

Deposit transactions can fail on L2 — usually because not enough gas was provided, or the L2 state did not allow the transaction to succeed. When that happens the message is not lost: L2CrossDomainMessenger records it as a failed message, and you can replay it later, optionally with more gas. To walk through triggering a failed deposit and replaying it end to end, follow the tutorial Replaying a failed deposit.