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.
L1 processing
-
An L1 entity, either a smart contract or an externally owned account (EOA), sends a deposit transaction to
L1CrossDomainMessenger, usingsendMessage. 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.
-
The L1 cross domain messenger calls its own
_sendMessagefunction. It uses these parameters:_to, the destination address, is the messenger on the other side. In the case of deposits, this is always0x4200000000000000000000000000000000000007._gasLimit, the gas limit. This value is calculated using thebaseGasfunction._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 torelayMessage.
-
_sendMessagecalls the portal’sdepositTransactionfunction. Note that other contracts can also calldepositTransactiondirectly. However, doing so bypasses certain safeguards, so in most cases it’s a bad idea. -
The
depositTransactionfunction runs a few sanity checks, and then emits aTransactionDepositedevent.
L2 processing
-
The
op-nodecomponent looks forTransactionDepositedevents on L1. If it sees any such events, it parses them. -
Next,
op-nodeconverts thoseTransactionDepositedevents into deposit transactions. -
In most cases, user deposit transactions call the
relayMessagefunction ofL2CrossDomainMessenger. -
relayMessageruns 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.