Skip to content

Commit 91febcf

Browse files
committed
First draft of tutorial for creating custom SuperchainERC20 contracts
Note: Needs to be merged after #1376
1 parent b70d6da commit 91febcf

File tree

4 files changed

+213
-64
lines changed

4 files changed

+213
-64
lines changed

pages/stack/interop/tutorials/_meta.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"message-passing": "Interop message passing",
33
"transfer-superchainERC20": "Transferring a SuperchainERC20",
44
"deploy-superchain-erc20": "Issuing new assets with SuperchainERC20",
5-
"custom-erc20": "Creating custom SuperchainERC20 tokens",
5+
"custom-superchain-erc20": "Creating custom SuperchainERC20 tokens",
66
"bridge-crosschain-eth": "Bridging native cross-chain ETH transfers",
77
"relay-messages-cast": "Relaying interop messages using `cast`",
88
"relay-messages-viem": "Relaying interop messages using `viem`",

pages/stack/interop/tutorials/custom-erc20.mdx

-63
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
title: Creating custom SuperchainERC20 tokens
3+
lang: en-US
4+
description: Create SuperchainERC20 tokens with custom behaviors
5+
---
6+
7+
import { Callout } from 'nextra/components'
8+
import { Steps } from 'nextra/components'
9+
10+
<Callout>
11+
The SuperchainERC20 standard is ready for production use with active Mainnet deployments.
12+
Please note that the OP Stack interoperability upgrade, required for crosschain messaging, is currently still in active development.
13+
</Callout>
14+
15+
# Creating custom SuperchainERC20 tokens
16+
17+
## Overview
18+
19+
This guide explains how to modify the behavior of [`SuperchainERC20`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/SuperchainERC20.sol) contracts to create custom tokens that can then be bridged quickly and safely using the [`SuperchainTokenBridge` ](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/SuperchainTokenBridge.sol) contract (once interop is operational).
20+
For more information on how it works, [see the explainer](/stack/interop/superchain-erc20).
21+
22+
To ensure fungibility across chains, `SuperchainERC20` assets *must* have the same contract address on all chains.
23+
This requirement abstracts away the complexity of cross-chain validation.
24+
Achieving this requires deterministic deployment methods. There are [many ways to do this](https://github.com/Arachnid/deterministic-deployment-proxy).
25+
Here we will use the [SuperchainERC20 Starter Kit](/app-developers/starter-kit).
26+
27+
### What you'll do
28+
29+
* Use the [SuperchainERC20 Starter Kit](/app-developers/starter-kit) to deploy tokens with your custom code.
30+
31+
### What you'll learn
32+
33+
* How to deploy custom ERC-20 tokens on different chains at the same address so that they can be bridged with the [`SuperchainTokenBridge` ](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/SuperchainTokenBridge.sol) contract.
34+
35+
## Prerequisites
36+
37+
Before starting this tutorial, ensure your development environment meets the following requirements:
38+
39+
### Technical knowledge
40+
41+
* Understanding of smart contract development
42+
* Familiarity with blockchain concepts
43+
* Familiarity with [standard SuperchainERC20 deployments](./deploy-superchain-erc20).
44+
45+
### Development environment
46+
47+
* Unix-like operating system (Linux, macOS, or WSL for Windows)
48+
* Git for version control
49+
50+
### Required tools
51+
52+
The tutorial uses these primary tools:
53+
54+
* Foundry: For sending transactions to blockchains.
55+
56+
## Step by step explanation
57+
58+
<Steps>
59+
60+
### Prepare for deployment
61+
62+
1. Follow the setup steps in the [SuperchainERC20 Starter Kit](/app-developers/starter-kit#setup).
63+
Don't start the development environment (step 5).
64+
65+
1. Follow [the deployment preparations steps](./deploy-superchain-erc20#prepare-for-deployment) in the issuing new assets page.
66+
Don't deploy the contracts yet.
67+
68+
**Note:** Make sure to specify a previously unused value for the salt, for example your address and a timestamp.
69+
This is necessary because if the same constructor code is used with the same salt when using the deployment script, it gets the same address, which is a problem if you want a fresh deployment.
70+
71+
### Create the custom contract
72+
73+
The easiest way to do this is to copy and modify the `L2NativeSuperchainERC20.sol` contract.
74+
Use this code, for example, as `packages/contracts/src/CustomSuperchainToken.sol`.
75+
76+
```typescript file=<rootDir>/public/tutorials/CustomSuperchainToken.sol hash=4ad95b9203ce523351eba0501f8b972d
77+
```
78+
79+
<details>
80+
81+
<summary>Explanation</summary>
82+
83+
```typescript file=<rootDir>/public/tutorials/CustomSuperchainToken.sol#L36-L38 hash=4e402ea88c9cd796500425172a6de16d
84+
```
85+
86+
This function lets users get tokens for themselves.
87+
This token is for testing purposes, so it is useful for users to get their own tokens to run tests.
88+
89+
</details>
90+
91+
### Deploy the new token
92+
93+
1. Edit `packages/contracts/scripts/SuperchainERC20Deployer.s.sol`:
94+
95+
- Change line 6 to import the new token.
96+
97+
```solidity
98+
import {CustomSuperchainToken} from "../src/CustomSuperchainToken.sol";
99+
```
100+
101+
- Change lines 52-54 to get the `CustomSuperchainToken` initialization code.
102+
103+
```solidity
104+
bytes memory initCode = abi.encodePacked(
105+
type(CustomSuperchainToken).creationCode, abi.encode(ownerAddr_, name, symbol, uint8(decimals))
106+
);
107+
```
108+
109+
- Change line 62 to deploy a `CustomSuperchainToken` contract.
110+
111+
```solidity
112+
addr_ = address(new CustomSuperchainToken{salt: _implSalt()}(ownerAddr_, name, symbol, uint8(decimals)));
113+
```
114+
115+
1. Deploy the token contract.
116+
117+
```sh
118+
pnpm contracts:deploy:token
119+
```
120+
121+
<details>
122+
123+
<summary>Sanity check</summary>
124+
125+
1. Set `TOKEN_ADDRESS` to the address where the token is deployed.
126+
You can also play with the token I created, which is at address [`0xF3Ce0794cB4Ef75A902e07e5D2b75E4D71495ee8`](https://sid.testnet.routescan.io/address/0xF3Ce0794cB4Ef75A902e07e5D2b75E4D71495ee8).
127+
128+
```sh
129+
TOKEN_ADDRESS=0xF3Ce0794cB4Ef75A902e07e5D2b75E4D71495ee8
130+
```
131+
132+
1. Source the `.env` file to get the private key and the address to which it corresponds.
133+
134+
```sh
135+
. packages/contracts/.env
136+
MY_ADDRESS=`cast wallet address $DEPLOYER_PRIVATE_KEY`
137+
```
138+
139+
1. Set variables for the RPC URLs.
140+
141+
```sh
142+
RPC_DEV0=https://interop-alpha-0.optimism.io
143+
RPC_DEV1=https://interop-alpha-1.optimism.io
144+
```
145+
146+
1. Get your current balance (it should be zero).
147+
148+
```sh
149+
cast call --rpc-url $RPC_DEV0 $TOKEN_ADDRESS "balanceOf(address)" $MY_ADDRESS | cast to-dec | cast --from-wei
150+
```
151+
152+
1. Call the faucet to get a token and check the balance again.
153+
154+
```sh
155+
cast send --private-key $DEPLOYER_PRIVATE_KEY --rpc-url $RPC_DEV0 $TOKEN_ADDRESS "faucet()"
156+
cast call --rpc-url $RPC_DEV0 $TOKEN_ADDRESS "balanceOf(address)" $MY_ADDRESS | cast to-dec | cast --from-wei
157+
```
158+
159+
</details>
160+
161+
</Steps>
162+
163+
## How does this work?
164+
165+
To allow for superchain interoperability, an ERC-20 token has to implement [ERC-7802](https://specs.optimism.io/interop/token-bridging.html#ierc7802).
166+
You can either use [the `SuperchainERC20` implementation](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/SuperchainERC20.sol#L26-L46), or write your own.
167+
168+
For more details [see the explainer](../superchain-erc20).
169+
170+
## Next steps
171+
* Use the [SuperchainERC20 Starter Kit](/app-developers/starter-kit) to deploy your token across the Superchain.
172+
* Explore the [SuperchainERC20 specifications](https://specs.optimism.io/interop/token-bridging.html) for in-depth implementation details.
173+
* Review the [Superchain Interop Explainer](../explainer) for answers to common questions about interoperability.
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.25;
3+
4+
import {SuperchainERC20} from "./SuperchainERC20.sol";
5+
import {Ownable} from "@solady/auth/Ownable.sol";
6+
7+
contract CustomSuperchainToken is SuperchainERC20, Ownable {
8+
string private _name;
9+
string private _symbol;
10+
uint8 private immutable _decimals;
11+
12+
constructor(address owner_, string memory name_, string memory symbol_, uint8 decimals_) {
13+
_name = name_;
14+
_symbol = symbol_;
15+
_decimals = decimals_;
16+
17+
_initializeOwner(owner_);
18+
}
19+
20+
function name() public view virtual override returns (string memory) {
21+
return _name;
22+
}
23+
24+
function symbol() public view virtual override returns (string memory) {
25+
return _symbol;
26+
}
27+
28+
function decimals() public view override returns (uint8) {
29+
return _decimals;
30+
}
31+
32+
function mintTo(address to_, uint256 amount_) external onlyOwner {
33+
_mint(to_, amount_);
34+
}
35+
36+
function faucet() external {
37+
_mint(msg.sender, 10**_decimals);
38+
}
39+
}

0 commit comments

Comments
 (0)