Skip to main content
This guide covers the steps necessary to bridge the BLAST token from Blast (L2) to Ethereum (L1). The guide is geared towards exchanges and other custodians that need to bridge BLAST from contracts on L2, such as multisigs or custody contracts. The steps on Blast are calls made by the contract that holds your BLAST; each lists the contract, function, arguments, and ETH value, so you can execute them with whatever your contract or custody platform supports. The steps on Ethereum can be sent from any account; see Building the Prove and Finalize Transactions for TypeScript code examples.

How It Works

BLAST is native to Blast. It moves to Ethereum through the standard OP Stack bridge using a lock-and-mint model:
  • On Blast, your BLAST is locked in the L2StandardBridge.
  • On Ethereum, the same amount of L1 BLAST (0x71b9e0FD392713A14FCaB92D9aF7A21F47E3b1Fa) is minted to your recipient when the withdrawal is finalized.
L1 BLAST is an OptimismMintableERC20. Its remoteToken() is L2 BLAST, and its bridge() is the L1StandardBridge, the only address that can mint it.

Before You Start

Your L2 Contract Must Be Able to Call the Bridge

The withdrawal is initiated by the contract that holds the BLAST on the L2. It must be able to make the following contract calls: approve on the BLAST token, then bridgeERC20To on the L2StandardBridge. A contract that can only transfer tokens to an address can’t start a withdrawal itself; move the BLAST to a contract or account that can.

Verify Your L1 Recipient

Before you start, verify that the intended recipient address meets the following conditions:
  • It exists on Ethereum. There is contract code at the address, or it’s an EOA you control. If nothing is deployed there yet, the BLAST still arrives, but whoever later deploys a contract at that address controls it. A not-yet-deployed multisig must later be deployed with exactly the same configuration to reach the same address.
  • It’s the contract you expect. Its source is verified and it’s the contract type you intended. For a multisig, it has the owners and threshold you expect.
  • It can transfer the BLAST out. It must be able to send ERC20 tokens it holds to another address. A contract that can receive tokens but not send them leaves the BLAST stuck permanently.

Anyone Can Prove and Finalize

proveWithdrawalTransaction and finalizeWithdrawalTransaction on Ethereum don’t check who sends them. Any EOA with ETH for gas can submit them; your L2 contract and its signers don’t need to do anything on Ethereum.

Test With a Small Amount First

Be sure to run the whole flow end-to-end with a small amount before moving large balances.

Withdraw Your BLAST

1

Approve the bridge (Blast)

The bridge pulls the BLAST into escrow, so it must be approved first.
2

Initiate the withdrawal (Blast)

Failure to use the official L1 BLAST address (0x71b9e0FD392713A14FCaB92D9aF7A21F47E3b1Fa) as _remoteToken will permanently lock your BLAST. The L2 bridge accepts any address, but the withdrawal will then fail on Ethereum, and the BLAST can’t be recovered from the L2 bridge.
Record these values. The later steps and status checks use them:
  • the L2 transaction hash
  • its L2 block number
  • the withdrawalHash: the last field of the MessagePassed event emitted by the L2ToL1MessagePasser (0x4200000000000000000000000000000000000016) in this transaction
3

Prove the withdrawal (Ethereum)

Wait until the L2 output containing your transaction has been posted to Ethereum, up to ~1 hour (see Ready to Prove?). Then call proveWithdrawalTransaction on the OptimismPortal (0x0Ec68c5B10F21EFFb74f2A5C61DFe6b08C0Db6Cb):
The proof arguments are built from your L2 transaction hash. See Building the Prove and Finalize Transactions for code that does this.
4

Wait for the challenge period

Wait 1 day after proving.
5

Finalize the withdrawal (Ethereum)

Call finalizeWithdrawalTransaction on the OptimismPortal, with hintId set to 0:
This signature differs from other OP Stack chains: Blast’s portal takes an extra hintId argument before the withdrawal. For BLAST, hintId is always 0.
Set the finalize transaction’s gas limit explicitly. The portal reverts with SafeCall: Not enough gas if the limit is too low. A withdrawal initiated with _minGasLimit 200000 needs about 670,000 gas, so use 800,000.
See Building the Prove and Finalize Transactions for code that builds and sends this call.The L1StandardBridge mints L1 BLAST to your recipient in the same transaction. Confirm it arrived (see Delivered?).

Building the Prove and Finalize Transactions

The examples below use TypeScript and viem 2.57.3. Each builds the transaction from the L2 transaction hash of your initiate step and sends it.

Setup

Prove

Run this once the withdrawal is ready to prove.

Finalize

Run this once the challenge period is over, 1 day after proving. Then confirm delivery.

Checking Withdrawal Status

Every stage can be checked with read-only calls on Ethereum, from your own tooling or the Read as Proxy tab on Etherscan, using the L2 block number and withdrawalHash you recorded when you initiated.

Ready to Prove?

Proven?

A timestamp of 0 means the withdrawal hasn’t been proven. requestId is always 0 for BLAST.

Challenge Period Over?

timestamp is the proven timestamp from the previous check. The challenge period is currently 86400 seconds (1 day).

Finalized?

This means the finalize transaction has run. It doesn’t by itself mean the BLAST was minted: check Delivered?.

Delivered?

Finalizing hands the withdrawal to the L1CrossDomainMessenger (0x5D4472f31Bd9385709ec61305AFc749F0fA8e9d0), which calls the L1StandardBridge to mint. If that call fails (for example, because of a wrong _remoteToken), the withdrawal is still marked as finalized, but the messenger records the message as failed and nothing is minted. Confirm delivery in any of these ways:
  • L1BLAST.balanceOf(_to) increased by your amount.
  • The finalize transaction emitted ERC20BridgeFinalized from the L1StandardBridge.
  • L1CrossDomainMessenger.successfulMessages(keccak256(data)) is true, where data is the data field of your withdrawal’s MessagePassed event.

Contract Addresses

Blast (Chain ID 81457)

Ethereum (Chain ID 1)