| description | How to deploy and bridge an ERC-20 token from Ethereum to MegaETH using the OP Stack Standard Bridge. |
|---|
MegaETH's canonical bridge supports ERC-20 token bridging via the OP Stack Standard Bridge.
Bridging locks tokens in the L1StandardBridge on Ethereum and mints a paired OptimismMintableERC20 on MegaETH.
- Foundry installed (
forgeandcast) - A wallet funded with ETH on both L1 (for deployment and bridging gas) and L2 (for registration gas)
- An ERC-20 contract ready to deploy, or an existing L1 token address
{% tabs %} {% tab title="Mainnet" %}
| Contract | Chain | Address |
|---|---|---|
| L1StandardBridge | Ethereum (chain 1) | 0x0CA3A2FBC3D770b578223FBB6b062fa875a2eE75 |
| OptimismMintableERC20Factory | Ethereum (chain 1) | 0xF875030B9464001fC0f964E47546b0AFEEbD7C61 |
| L2StandardBridge | MegaETH Mainnet (chain 4326) | 0x4200000000000000000000000000000000000010 |
| OptimismMintableERC20Factory | MegaETH Mainnet (chain 4326) | 0x4200000000000000000000000000000000000012 |
| {% endtab %} | ||
| {% tab title="Testnet (Sepolia)" %} | ||
| Contract | Chain | Address |
| -------- | ----- | ------- |
| L1StandardBridge | Ethereum Sepolia (chain 11155111) | 0x8033d50c753b3f19748f239ac8cf915b2888cd32 |
| OptimismMintableERC20Factory | Ethereum Sepolia (chain 11155111) | 0x11f008caa3083aa8a3b6f9f06f923e98a28fa286 |
| L2StandardBridge | MegaETH Testnet (chain 6343) | 0x4200000000000000000000000000000000000010 |
| OptimismMintableERC20Factory | MegaETH Testnet (chain 6343) | 0x4200000000000000000000000000000000000012 |
| {% endtab %} | ||
| {% endtabs %} |
{% stepper %} {% step %}
Deploy your token contract on Ethereum (or Sepolia for testing). The example below uses a Foundry script; adapt it for your own token.
forge script script/Deploy.s.sol \
--rpc-url $L1_RPC \
--broadcast \
--private-key $PRIVATE_KEYSave the deployed token address — you will need it in the next step.
{% endstep %} {% step %}
Call createOptimismMintableERC20 on the OptimismMintableERC20Factory on MegaETH.
This deploys a bridgeable ERC-20 on L2 that is linked to your L1 token.
Replace "MyToken" and "MTK" with your token's name and symbol.
cast send $L2_MINTABLE_FACTORY \
"createOptimismMintableERC20(address,string,string)" \
$L1_TOKEN "MyToken" "MTK" \
--rpc-url $L2_RPC \
--private-key $PRIVATE_KEYThe factory emits an OptimismMintableERC20Created(address indexed localToken, address indexed remoteToken, address deployer) event.
Parse the localToken field from the receipt to get your L2 token address.
# Extract the L2 token address from the event logs
# topics[0] is keccak256("OptimismMintableERC20Created(address,address,address)")
# topics[1] is the L2 token address ABI-encoded as a 32-byte padded value; [26:] strips the leading zeros
cast receipt $TX_HASH --rpc-url $L2_RPC --json \
| jq -r '.logs[] | select(.topics[0] == "0x52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb") | "0x" + .topics[1][26:]'{% endstep %} {% step %}
Approve L1StandardBridge to spend the tokens you want to bridge.
Set $AMOUNT in wei (e.g. 100000000000000000000 for 100 tokens with 18 decimals).
cast send $L1_TOKEN \
"approve(address,uint256)" \
$L1_BRIDGE $AMOUNT \
--rpc-url $L1_RPC \
--private-key $PRIVATE_KEY{% endstep %} {% step %}
Call bridgeERC20 on L1StandardBridge.
Pass both the L1 and L2 token addresses, the amount in wei, a minimum gas limit for L2 execution, and empty extra data.
cast send $L1_BRIDGE \
"bridgeERC20(address,address,uint256,uint32,bytes)" \
$L1_TOKEN \
$L2_TOKEN \
$AMOUNT \
200000 \
0x \
--rpc-url $L1_RPC \
--private-key $PRIVATE_KEY200000 is sufficient for most standard ERC-20 tokens.
The bridge transaction locks tokens on L1 and relays a message to MegaETH to mint the equivalent amount on L2.
{% endstep %} {% step %}
After the L1 transaction is finalized and relayed (~1–2 minutes), check the balance on MegaETH.
cast call $L2_TOKEN \
"balanceOf(address)(uint256)" \
$(cast wallet address --private-key $PRIVATE_KEY) \
--rpc-url $L2_RPC{% hint style="info" %} The deposit takes approximately 1–2 minutes to appear on MegaETH — one L1 block for finality, plus sequencer relay time. You can track the L1 transaction on Etherscan (mainnet) or Sepolia Etherscan (testnet), and the L2 deposit on MegaETH Blockscout (mainnet) or the testnet explorer. {% endhint %}
{% endstep %} {% endstepper %}
Withdrawing tokens back to Ethereum requires initiating a withdrawal on L2 and then proving and finalizing it on L1 after the challenge period. This follows the standard OP Stack withdrawal flow — see the OP Stack withdrawal guide for details.