-
Notifications
You must be signed in to change notification settings - Fork 266
SuperchainERC20
bridging tutorial
#1394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
bradleycamacho
merged 19 commits into
ethereum-optimism:main
from
qbzzt:250219-xfer-superc20
Mar 7, 2025
Merged
Changes from 9 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
b5a88cf
First version of tutorial
qbzzt 15bb644
Added links to the UI, and a link from the explainer
qbzzt 8b31220
lint
qbzzt 0a1c8ec
lint and coderabbit
qbzzt 2b55029
Update superchain-erc20.mdx
qbzzt bc2fbb5
Update transfer-superchainERC20.mdx
qbzzt 8a6e9ae
Coderabbit
qbzzt 5055e3c
Merge branch 'main' into 250219-xfer-superc20
qbzzt 3cdbb8d
Put warning in a callout as per @sbvegan
qbzzt 7449a54
Merge branch 'main' into 250219-xfer-superc20
qbzzt 821a43a
Autorelay
qbzzt 07abc77
More autorelay stuff
qbzzt 2285207
Merge branch 'main' into 250219-xfer-superc20
qbzzt c2e4515
coderabbit
qbzzt 8510c01
@bradleycamacho comments
qbzzt 9e8b5ea
fix links
qbzzt 22de8b2
Merge branch 'main' into 250219-xfer-superc20
qbzzt b90cdfe
Merge branch 'main' into 250219-xfer-superc20
qbzzt e9ddbd8
Remove extra description
bradleycamacho File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
245 changes: 168 additions & 77 deletions
245
pages/stack/interop/tutorials/transfer-superchainERC20.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,118 +1,209 @@ | ||
--- | ||
title: Transferring a SuperchainERC20 | ||
title: Transferring SuperchainERC20 tokens | ||
lang: en-US | ||
description: Learn how to transfer a SuperchainERC20 between chains using L2ToL2CrossDomainMessenger. | ||
--- | ||
qbzzt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
import { Callout, Steps } from 'nextra/components' | ||
|
||
<Callout> | ||
The SuperchainERC20 standard is ready for production use with active Mainnet deployments. | ||
Please note that the OP Stack interoperability upgrade, required for crosschain messaging, is currently still in active development. | ||
The SuperchainERC20 standard is ready for production deployments. | ||
Please note that the OP Stack interoperability upgrade, required for crosschain messaging, is currently still in active development. | ||
</Callout> | ||
|
||
# Transferring a SuperchainERC20 | ||
# Transferring SuperchainERC20 tokens | ||
|
||
This guide provides an overview of transferring `SuperchainERC20` tokens between chains. | ||
This guide shows how to transfer `SuperchainERC20` tokens between chains programmatically. | ||
|
||
## Overview | ||
Note that this tutorial provides step-by-step instructions for transferring `SuperchainERC20` tokens using code. | ||
|
||
Transferring SuperchainERC20 tokens between chains involves two main phases: | ||
* For a detailed behind-the-scenes explanation, [see the explainer](../superchain-erc20#how-it-works). | ||
* For a sample UI that bridges a `SuperchainERC20` token, [see here](https://interop-alpha-app.superchain.tools/). | ||
|
||
1. **Source Chain Operations** | ||
* Mint tokens if needed | ||
* Initiate the transfer using the bridge | ||
2. **Destination Chain Operations** | ||
* Relay the transfer message | ||
* Verify the transfer completion | ||
## Overview | ||
|
||
<Callout type="warning"> | ||
Always verify your addresses and amounts before sending transactions. Cross-chain transfers cannot be reversed. | ||
Always verify your addresses and amounts before sending transactions. | ||
Cross-chain transfers cannot be reversed. | ||
</Callout> | ||
|
||
## How it works | ||
|
||
This diagram illustrates the process of a SuperchainERC20 token transfer between chains. | ||
Through the `L2ToL2CrossDomainMessenger` contract, tokens are burned on the source chain and a transfer message is emitted. | ||
This message must then be relayed to the destination chain, where an equivalent amount of tokens will be minted to the specified recipient address - ensuring secure cross-chain transfers while maintaining the total token supply across all chains. | ||
|
||
```mermaid | ||
sequenceDiagram | ||
actor User | ||
participant SourceChain | ||
participant Bridge as L2ToL2CrossDomainMessenger | ||
participant DestChain | ||
|
||
Note over User,DestChain: Step 1: Prepare Tokens | ||
User->>SourceChain: Check token balance | ||
alt | ||
User->>SourceChain: Mint or acquire tokens | ||
end | ||
|
||
Note over User,DestChain: Step 2: Initiate Transfer | ||
User->>SourceChain: Approve bridge contract | ||
User->>Bridge: Call sendERC20 | ||
Bridge->>SourceChain: Burn tokens | ||
Bridge-->>Bridge: Emit transfer message | ||
|
||
Note over User,DestChain: Step 3: Complete Transfer | ||
User->>Bridge: Get message details | ||
User->>Bridge: Relay message on destination | ||
Bridge->>DestChain: Mint tokens to recipient | ||
|
||
Note over User,DestChain: Step 4: Verify | ||
User->>DestChain: Check token balance | ||
``` | ||
### What you'll build | ||
|
||
* A TypeScript application to transfer `SuperchainERC20` tokens between chains | ||
|
||
### What you'll learn | ||
|
||
* How to send `SuperchainERC20` tokens on the blockchain and between blockchains | ||
* How to relay messages between chains | ||
|
||
## Prerequisites | ||
|
||
Before starting this tutorial, ensure your development environment meets the following requirements: | ||
|
||
### Technical knowledge | ||
|
||
* Intermediate TypeScript knowledge | ||
* Understanding of smart contract development | ||
* Familiarity with blockchain concepts | ||
bradleycamacho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Development environment | ||
|
||
* Unix-like operating system (Linux, macOS, or WSL for Windows) | ||
* Node.js version 16 or higher | ||
* Git for version control | ||
|
||
### Required tools | ||
|
||
The tutorial uses these primary tools: | ||
|
||
* Foundry: For issuing transactions | ||
* TypeScript: For implementation | ||
* Node: For running TypeScript code from the command line | ||
* Viem: For blockchain interaction | ||
bradleycamacho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Directions | ||
|
||
<Steps> | ||
### Prepare your tokens | ||
### Preparation | ||
|
||
Ensure you have tokens on the source chain using one of these methods: | ||
You need onchain `SuperchainERC20` tokens. | ||
You can [deploy your own token](./deploy-superchain-erc20), but in this tutorial we will use [`CustomSuperchainToken`](https://sid.testnet.routescan.io/address/0xF3Ce0794cB4Ef75A902e07e5D2b75E4D71495ee8), existing `SuperchainERC20` token on the [Interop devnet](../tools/devnet). | ||
|
||
* Use existing tokens you already own | ||
* Mint new tokens using the [SuperchainERC20 contract](https://github.com/ethereum-optimism/supersim/blob/main/contracts/src/L2NativeSuperchainERC20.sol) if you have minting permissions | ||
* Acquire tokens through a supported exchange or transfer | ||
1. Create environment variables for the RPC endpoints for the blockchains and the token address. | ||
|
||
### Initiate the transfer | ||
```sh | ||
RPC_DEV0=https://interop-alpha-0.optimism.io | ||
RPC_DEV1=https://interop-alpha-1.optimism.io | ||
TOKEN_ADDRESS=0xF3Ce0794cB4Ef75A902e07e5D2b75E4D71495ee8 | ||
``` | ||
|
||
To start the transfer: | ||
2. Set `PRIVATE_KEY` to the private key of an address that has [Sepolia ETH](https://cloud.google.com/application/web3/faucet/ethereum/sepolia). | ||
|
||
1. Choose the destination chain where you want to receive the tokens | ||
2. Specify the recipient address and the amount to transfer | ||
3. Call the bridge contract, which will: | ||
* Lock or burn your tokens on the source chain | ||
* Emit a message that will be used to mint tokens on the destination chain | ||
```sh | ||
export PRIVATE_KEY=0x<private key here> | ||
MY_ADDRESS=`cast wallet address $PRIVATE_KEY` | ||
``` | ||
qbzzt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Complete the transfer | ||
3. Send ETH to the two L2 blockchains. | ||
|
||
To finalize the transfer on the destination chain: | ||
```sh | ||
cast send --rpc-url https://endpoints.omniatech.io/v1/eth/sepolia/public --private-key $PRIVATE_KEY --value 0.02ether 0x7385d89d38ab79984e7c84fab9ce5e6f4815468a | ||
cast send --rpc-url https://endpoints.omniatech.io/v1/eth/sepolia/public --private-key $PRIVATE_KEY --value 0.02ether 0x55f5c4653dbcde7d1254f9c690a5d761b315500c | ||
``` | ||
|
||
1. Get the message details from the source chain event | ||
2. Use the `L2ToL2CrossDomainMessenger` contract to relay the message | ||
3. The message relay will trigger the minting of tokens on the destination chain | ||
4. Wait a few minutes until you can see the ETH [on the block explorer](https://sid.testnet.routescan.io/) for your address. | ||
|
||
<Callout type="info"> | ||
The transfer isn't complete until the message is successfully relayed on the destination chain. See the [technical reference guide](/stack/interop/tutorials/relay-messages-viem) for specific relay instructions. | ||
</Callout> | ||
<details> | ||
<summary>Sanity check</summary> | ||
qbzzt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Verify completion | ||
```sh | ||
cast balance --ether $MY_ADDRESS --rpc-url $RPC_DEV0 | ||
cast balance --ether $MY_ADDRESS --rpc-url $RPC_DEV1 | ||
``` | ||
</details> | ||
|
||
After relaying the message: | ||
5. Obtain tokens on Interop devnet 0. | ||
When using `CustomSuperchainToken`, there are two ways to do this: | ||
|
||
1. Check your token balance on the destination chain | ||
2. Confirm the transferred amount matches what you sent | ||
3. The tokens should now be available for use on the destination chain | ||
</Steps> | ||
* Use the [block explorer](https://sid.testnet.routescan.io/address/0xF3Ce0794cB4Ef75A902e07e5D2b75E4D71495ee8/contract/420120000/writeContract?chainid=420120000) and a browser wallet to run the [faucet](https://sid.testnet.routescan.io/address/0xF3Ce0794cB4Ef75A902e07e5D2b75E4D71495ee8/contract/420120000/writeContract?chainid=420120000#F6) function. | ||
|
||
* Use `cast` to call the `faucet` function. | ||
|
||
```sh | ||
cast send --rpc-url $RPC_DEV0 --private-key $PRIVATE_KEY $TOKEN_ADDRESS "faucet()" | ||
``` | ||
|
||
<details> | ||
<summary>Sanity check</summary> | ||
|
||
For detailed technical instructions including contract addresses, specific commands, and message relaying details, refer to our [technical reference guide](/stack/interop/tutorials/relay-messages-viem). | ||
Run this command to check your token balance. | ||
|
||
## Alternative methods | ||
```sh | ||
cast call --rpc-url $RPC_DEV0 $TOKEN_ADDRESS "balanceOf(address)" $MY_ADDRESS | cast --from-wei | ||
``` | ||
</details> | ||
|
||
You can also use: | ||
### Transfer tokens using TypeScript | ||
|
||
* [viem bindings/actions](/stack/interop/tutorials/relay-messages-viem) for TypeScript integration | ||
We are going to use a [Node](https://nodejs.org/en) project, to be able to use [`@eth-optimism/viem`](https://www.npmjs.com/package/@eth-optimism/viem) to send the executing message. | ||
We use [TypeScript](https://www.typescriptlang.org/) to have type safety combined with JavaScript functionality. | ||
qbzzt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
1. Initialize a new Node project. | ||
|
||
```sh | ||
mkdir xfer-erc20 | ||
cd xfer-erc20 | ||
npm init -y | ||
npm install --save-dev -y viem tsx @types/node @eth-optimism/viem | ||
mkdir src | ||
``` | ||
|
||
2. Edit `package.json` to add the `start` script. | ||
|
||
```json | ||
{ | ||
"name": "xfer-erc20", | ||
"version": "1.0.0", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1", | ||
"start": "tsx src/xfer-erc20.mts" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC", | ||
"type": "commonjs", | ||
"description": "", | ||
"devDependencies": { | ||
"@eth-optimism/viem": "^0.3.2", | ||
"@types/node": "^22.13.4", | ||
"tsx": "^4.19.3", | ||
"viem": "^2.23.3" | ||
} | ||
} | ||
``` | ||
qbzzt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
3. Create `src/xfer-erc20.mts`: | ||
|
||
```typescript file=<rootDir>/public/tutorials/xfer-erc20.mts hash=19a948eeb482046afb1a55ccc5019599 | ||
``` | ||
|
||
<details> | ||
<summary>Explanation</summary> | ||
qbzzt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```typescript file=<rootDir>/public/tutorials/xfer-erc20.mts#L79-L84 hash=85f317d0cbe2b59e303e36a3e6154c62 | ||
``` | ||
|
||
Use `@eth-optimism/viem`'s `walletActionsL2().sendSuperchainERC20` to send the `SuperchainERC20` tokens. | ||
Internally, this function calls [`SuperchainTokenBridge.sendERC20`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/SuperchainTokenBridge.sol#L52-L78) to send the tokens. | ||
|
||
```typescript file=<rootDir>/public/tutorials/xfer-erc20.mts#L88-L90 hash=cab6e961b558f4f5a7b877062b1cfa45 | ||
``` | ||
|
||
To relay a message, we need the information in the receipt. | ||
Also, we need to wait until the transaction with the relayed message is actually part of a block. | ||
|
||
```typescript file=<rootDir>/public/tutorials/xfer-erc20.mts#L92-L94 hash=1da0981adb2fbd38cccf1b0602158418 | ||
``` | ||
|
||
A single transaction can send multiple messages. | ||
But here we know we sent just one, so we look for the first one in the list. | ||
|
||
```typescript file=<rootDir>/public/tutorials/xfer-erc20.mts#L96-L99 hash=b5ad9f0c44aee84742cd20c348fdb156 | ||
``` | ||
|
||
This is how you use `@eth-optimism/viem` to create an executing message. | ||
</details> | ||
|
||
4. Run the TypeScript program, and see the change in your `CustomSuperchainToken` balances. | ||
|
||
```sh | ||
npm start | ||
``` | ||
</Steps> | ||
|
||
## Next steps | ||
|
||
* Read the [Superchain Interop Explainer](/stack/interop/explainer#faqs) or check out this [Superchain interop design video walk-thru](https://www.youtube.com/watch?v=FKc5RgjtGes). | ||
* Learn [how this works](/stack/interop/superchain-erc20). | ||
* Use [Supersim](/app-developers/tools/supersim), a local dev environment that simulates Superchain interop for testing applications against a local version of the Superchain. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.