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.
Custom SuperchainERC20 tokens
Overview
This guide explains how to upgrade an ERC20 to a SuperchainERC20
(opens in a new tab) that can then teleport across the Superchain interop cluster quickly and safely using the SuperchainTokenBridge
(opens in a new tab) contract. For more information on how it works, see the explainer.
To ensure fungibility across chains, SuperchainERC20
assets must have the same contract address on all chains. This requirement abstracts away the complexity of cross-chain validation. Achieving this requires deterministic deployment methods. There are many ways to do this (opens in a new tab).
Here we will use the SuperchainERC20 Starter Kit.
About this tutorial
What you'll learn
- How to deploy custom ERC20 tokens across multiple chains at the same address so that they can be bridged with the
SuperchainTokenBridge
(opens in a new tab) contract.
Prerequisite technical knowledge
- Understanding of smart contract development
- Familiarity with blockchain concepts
- Familiarity with standard SuperchainERC20 deployments.
Development environment
- Unix-like operating system (Linux, macOS, or WSL for Windows)
- Git for version control
What you'll do
- Use the SuperchainERC20 starter kit to deploy tokens with your custom code.
Step by step
General setup
Follow the setup steps in the SuperchainERC20 starter kit, steps 1-4.
-
Install Foundry (opens in a new tab).
-
Run these commands:
git clone https://github.com/ethereum-optimism/superchainerc20-starter.git cd superchainerc20-starter pnpm install pnpm init:env
-
Edit
packages/contracts/configs/deploy-config.toml
's[token]
section.Parameter Meaning Example owner_address Owner of the token Your address1 name Token name Quick Transfer Token symbol Token symbol QTT decimals Number of decimal places 18 (1) This should be an address you control (for which you know the private key), which has some ETH on the blockchains in question. In the case of Supersim, the default has 10k ETH and you can use it. For the devnets, see here to send ETH.
-
If you change
owner_address
, you need to also set the private key. Editpackages/contracts/.env
to setDEPLOYER_PRIVATE_KEY
to the private key of an account that has ETH on both devnet blockchains.DEPLOYER_PRIVATE_KEY= <<<private key goes here>>>
Blockchain-specific setup
The SuperchainERC20 Starter Kit is already set up for Supersim. All you need to do is start it.
./supersim --interop.autorelay
Create the custom contract
The easiest way to do this is to copy and modify the L2NativeSuperchainERC20.sol
contract.
Use this code, for example, as packages/contracts/src/CustomSuperchainToken.sol
.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
import {SuperchainERC20} from "./SuperchainERC20.sol";
import {Ownable} from "@solady/auth/Ownable.sol";
contract CustomSuperchainToken is SuperchainERC20, Ownable {
string private _name;
string private _symbol;
uint8 private immutable _decimals;
constructor(address owner_, string memory name_, string memory symbol_, uint8 decimals_) {
_name = name_;
_symbol = symbol_;
_decimals = decimals_;
_initializeOwner(owner_);
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view override returns (uint8) {
return _decimals;
}
function mintTo(address to_, uint256 amount_) external onlyOwner {
_mint(to_, amount_);
}
function faucet() external {
_mint(msg.sender, 10**_decimals);
}
}
Explanation
function faucet() external {
_mint(msg.sender, 10**_decimals);
}
This function lets users get tokens for themselves. This token is for testing purposes, so it is useful for users to get their own tokens to run tests.
Deploy the new token
-
Edit
packages/contracts/scripts/SuperchainERC20Deployer.s.sol
:-
Change line 6 to import the new token.
import {CustomSuperchainToken} from "../src/CustomSuperchainToken.sol";
-
Update lines 52-54 to get the
CustomSuperchainToken
initialization code.bytes memory initCode = abi.encodePacked( type(CustomSuperchainToken).creationCode, abi.encode(ownerAddr_, name, symbol, uint8(decimals)) );
-
Modify line 62 to deploy a
CustomSuperchainToken
contract.addr_ = address(new CustomSuperchainToken{salt: _implSalt()}(ownerAddr_, name, symbol, uint8(decimals)));
-
-
Deploy the token contract.
pnpm contracts:deploy:token
Verify the installation
-
Set
TOKEN_ADDRESS
to the address where the token is deployed. You can also play with a previously created token, which is at address0xF3Ce0794cB4Ef75A902e07e5D2b75E4D71495ee8
(opens in a new tab) on the devnets.TOKEN_ADDRESS=<<< Your token address >>>
-
Source the
.env
file to get the private key and the address to which it corresponds.. packages/contracts/.env USER_ADDRESS=`cast wallet address $DEPLOYER_PRIVATE_KEY`
-
Set variables for the RPC URLs.
Set these parameters for Supersim.
URL_CHAIN_A=http://127.0.0.1:9545 URL_CHAIN_B=http://127.0.0.1:9546
-
Get your current balance (it should be zero).
cast call --rpc-url $URL_CHAIN_A $TOKEN_ADDRESS "balanceOf(address)" $USER_ADDRESS | cast --from-wei
-
Call the faucet to get a token and check the balance again.
cast send --private-key $DEPLOYER_PRIVATE_KEY --rpc-url $URL_CHAIN_A $TOKEN_ADDRESS "faucet()" cast call --rpc-url $URL_CHAIN_A $TOKEN_ADDRESS "balanceOf(address)" $USER_ADDRESS | cast --from-wei
-
Repeat the same steps on Chain B.
cast call --rpc-url $URL_CHAIN_B $TOKEN_ADDRESS "balanceOf(address)" $USER_ADDRESS | cast --from-wei cast send --private-key $DEPLOYER_PRIVATE_KEY --rpc-url $URL_CHAIN_B $TOKEN_ADDRESS "faucet()" cast call --rpc-url $URL_CHAIN_B $TOKEN_ADDRESS "balanceOf(address)" $USER_ADDRESS | cast --from-wei
For more details see the explainer.
Next steps
- Use the SuperchainERC20 Starter Kit to deploy your token across the Superchain.
- If you'd like a guided walkthrough, check out our tutorial video (opens in a new tab) instead.
- Review the Superchain Interop Explainer for answers to common questions about interoperability.