Skip to content

Convert erc20 to serc20 tutorial #1403

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
merged 13 commits into from
Feb 21, 2025
4 changes: 4 additions & 0 deletions pages/stack/interop/tutorials.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,8 @@ Documentation covering Interop related tutorials.

<Card title="Deploying crosschain event composability (contests)" href="/stack/interop/tutorials/event-contests" icon={<img src="/img/icons/shapes.svg" />} />

<Card title="Deploying crosschain event composability (contests)" href="/stack/interop/tutorials/event-contests" icon={<img src="/img/icons/shapes.svg" />} />

<Card title="Creating custom SuperchainERC20 tokens" href="/stack/interop/tutorials/custom-superchain-erc20" icon={<img src="/img/icons/shapes.svg" />} />

</Cards>
142 changes: 127 additions & 15 deletions pages/stack/interop/tutorials/custom-superchain-erc20.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@ import { Steps } from 'nextra/components'

## Overview

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).
For more information on how it works, [see the explainer](/stack/interop/superchain-erc20).
This guide explains how to upgrade an ERC20 to a [`SuperchainERC20`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/SuperchainERC20.sol) that can then teleport across the Superchain interop cluster quickly and safely using the [`SuperchainTokenBridge`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/SuperchainTokenBridge.sol) contract. For more information on how it works, [see the explainer](/stack/interop/superchain-erc20).

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](https://github.com/Arachnid/deterministic-deployment-proxy).
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](https://github.com/Arachnid/deterministic-deployment-proxy).
Here we will use the [SuperchainERC20 Starter Kit](/app-developers/starter-kit).

### What you'll do
Expand All @@ -30,7 +27,127 @@ Here we will use the [SuperchainERC20 Starter Kit](/app-developers/starter-kit).

### What you'll learn

* 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.
* How to deploy custom ERC20 tokens across multiple 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.

### How does this work?

To benefit from Superchain Interoperability, an ERC-20 token has to implement ERC-7802. You can either use the SuperchainERC20 implementation, or write your own.

At a high level you will:

<Steps>

### Create a basic ERC20 contract

The following code implements a basic ERC20 contract:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract MyERC20 is ERC20, Ownable {
constructor(address owner, string memory name, string memory symbol) ERC20(name, symbol) Ownable(owner) {}

function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}

```

### Add the new SuperchainERC20 interface

The first step is simply to implement `IERC7802` and `IERC165`. Note that we've renamed the contract at this point:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
import {IERC7802} from "@openzeppelin/contracts/token/ERC20/IERC7802.sol";

contract MySuperchainERC20 is ERC20, Ownable, IERC7802 {
error NotSuperchainERC20Bridge();

constructor(address owner, string memory name, string memory symbol) ERC20(name, symbol) Ownable(owner) {}

function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}


function supportsInterface(bytes4 _interfaceId) public view virtual returns (bool) {
return _interfaceId == type(IERC7802).interfaceId ||
_interfaceId == type(ERC20).interfaceId
|| _interfaceId == type(ERC165).interfaceId;
}
}

```

### Implement burn and mint functions

There are two functions we need to implement: `CrosschainMint` and `CrosschainBurn`. These two functions allow two chains to bridge a token by burning them on one chain and mint them on another. Read more about these functions in our [SuperchainERC20 docs](/stack/interop/superchain-erc20).

Here's what our contract looks like once we've implemented the functions:


```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
import {IERC7802} from "@openzeppelin/contracts/token/ERC20/IERC7802.sol";

contract MySuperchainERC20 is ERC20, Ownable, IERC7802 {
error NotSuperchainERC20Bridge();

constructor(address owner, string memory name, string memory symbol) ERC20(name, symbol) Ownable(owner) {}

function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}

/// @notice Allows the SuperchainTokenBridge to mint tokens.
/// @param _to Address to mint tokens to.
/// @param _amount Amount of tokens to mint.
function crosschainMint(address _to, uint256 _amount) external {
if (msg.sender != 0x4200000000000000000000000000000000000028) revert NotSuperchainERC20Bridge();

_mint(_to, _amount);

emit CrosschainMint(_to, _amount, msg.sender);
}

/// @notice Allows the SuperchainTokenBridge to burn tokens.
/// @param _from Address to burn tokens from.
/// @param _amount Amount of tokens to burn.
function crosschainBurn(address _from, uint256 _amount) external {
if (msg.sender != 0x4200000000000000000000000000000000000028) revert NotSuperchainERC20Bridge();

_burn(_from, _amount);

emit CrosschainBurn(_from, _amount, msg.sender);
}

function supportsInterface(bytes4 _interfaceId) public view virtual returns (bool) {
return _interfaceId == type(IERC7802).interfaceId ||
_interfaceId == type(ERC20).interfaceId
|| _interfaceId == type(ERC165).interfaceId;
}
}
```

</Steps>

For more details [see the explainer](/stack/interop/superchain-erc20).

## Prerequisites

Expand Down Expand Up @@ -154,15 +271,10 @@ The tutorial uses these primary tools:
</details>
</Steps>

## How does this work?

To allow for superchain interoperability, an ERC-20 token has to implement [ERC-7802](https://specs.optimism.io/interop/token-bridging.html#ierc7802).
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.

For more details [see the explainer](../superchain-erc20).
For more details [see the explainer](/stack/interop/superchain-erc20).

## Next steps

* Use the [SuperchainERC20 Starter Kit](/app-developers/starter-kit) to deploy your token across the Superchain.
* Explore the [SuperchainERC20 specifications](https://specs.optimism.io/interop/token-bridging.html) for in-depth implementation details.
* Review the [Superchain Interop Explainer](../explainer) for answers to common questions about interoperability.
* If you'd like a guided walkthrough, check out our [tutorial video](https://x.com/i/status/1866095114374045969) instead.
* Review the [Superchain Interop Explainer](/stack/interop/explainer) for answers to common questions about interoperability.

4 changes: 2 additions & 2 deletions pages/stack/interop/tutorials/deploy-superchain-erc20.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ The tutorial uses these primary tools:

### Prepare for deployment

The Starter Kit already deploys a `SuperchainERC20` token to [Supersim](../tools/supersim).
Here we will deploy it to the [Interop devnet](../tools/devnet).
The Starter Kit already deploys a `SuperchainERC20` token to [Supersim](/stack/interop/tools/supersim).
Here we will deploy it to the [Interop devnet](/stack/interop/tools/devnet).

1. Edit `packages/contracts/foundry.toml` to add the RPC endpoints for the devnet (add the bottom two rows).

Expand Down