Skip to content

Commit

Permalink
feat: add crosschain erc20 interface (#80)
Browse files Browse the repository at this point in the history
* feat: add crosschain erc20 interface

* fix: refactor interfaces
  • Loading branch information
agusduha authored Oct 3, 2024
1 parent ae019b8 commit a5aca61
Show file tree
Hide file tree
Showing 14 changed files with 122 additions and 136 deletions.
10 changes: 5 additions & 5 deletions packages/contracts-bedrock/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@
"sourceCodeHash": "0xfea53344596d735eff3be945ed1300dc75a6f8b7b2c02c0043af5b0036f5f239"
},
"src/L2/OptimismSuperchainERC20.sol": {
"initCodeHash": "0xc6452d9aef6d76bdc789f3cddac6862658a481c619e6a2e7a74f6d61147f927b",
"sourceCodeHash": "0x4463e49c98ceb3327bd768579341d1e0863c8c3925d4b533fbc0f7951306261f"
"initCodeHash": "0x964c826693c6633dc5eff6d4b059a30043775af46b06e42367aff91b904498da",
"sourceCodeHash": "0xf5cb8307067f2ef7aa540b9e0a4828cde76f783c7fb95c7d3f84c6d723f9d316"
},
"src/L2/OptimismSuperchainERC20Beacon.sol": {
"initCodeHash": "0x99ce8095b23c124850d866cbc144fee6cee05dbc6bb5d83acadfe00b90cf42c7",
Expand All @@ -133,11 +133,11 @@
},
"src/L2/SuperchainERC20.sol": {
"initCodeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
"sourceCodeHash": "0x9bc2e208774eb923894dbe391a5038a6189d7d36c202f4bf3e2c4dd332b0adf0"
"sourceCodeHash": "0x4debbf83ad569eae88fb1e70db5f45fb85eed609fd464bd180611756116e04ae"
},
"src/L2/SuperchainERC20Bridge.sol": {
"initCodeHash": "0xea7eb314f96cd2520a58012ff7cc376c82c5a95612187ff6bb96ace4f095ebc4",
"sourceCodeHash": "0x83188d878ce0b2890a7f7f41d09a8807f94a126e0ea274f0dac8b93f77217d3b"
"initCodeHash": "0xf85225ea25a87ba670b6ce0172a4814fda712d1c8a174fd4e8ce72b1cebcc2a0",
"sourceCodeHash": "0x66b56c0ac0d49b6da84da01a318f43418ef486e5fb40ae0af487568fde8566fb"
},
"src/L2/SuperchainWETH.sol": {
"initCodeHash": "0x5db03c5c4cd6ea9e4b3e74e28f50d04fd3e130af5109b34fa208808fa9ba7742",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"type": "uint256"
}
],
"name": "__superchainBurn",
"name": "__crosschainBurn",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
Expand All @@ -48,7 +48,7 @@
"type": "uint256"
}
],
"name": "__superchainMint",
"name": "__crosschainMint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
Expand Down Expand Up @@ -427,7 +427,7 @@
{
"indexed": true,
"internalType": "address",
"name": "account",
"name": "from",
"type": "address"
},
{
Expand All @@ -443,14 +443,20 @@
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": false,
"internalType": "uint64",
"name": "version",
"type": "uint64"
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "Initialized",
"name": "CrosschainBurnt",
"type": "event"
},
{
Expand All @@ -459,7 +465,7 @@
{
"indexed": true,
"internalType": "address",
"name": "account",
"name": "to",
"type": "address"
},
{
Expand All @@ -469,26 +475,20 @@
"type": "uint256"
}
],
"name": "Mint",
"name": "CrosschainMinted",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
"internalType": "uint64",
"name": "version",
"type": "uint64"
}
],
"name": "SuperchainBurnt",
"name": "Initialized",
"type": "event"
},
{
Expand All @@ -497,7 +497,7 @@
{
"indexed": true,
"internalType": "address",
"name": "account",
"name": "to",
"type": "address"
},
{
Expand All @@ -507,7 +507,7 @@
"type": "uint256"
}
],
"name": "SuperchainMinted",
"name": "Mint",
"type": "event"
},
{
Expand Down
7 changes: 3 additions & 4 deletions packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import { IOptimismSuperchainERC20Extension } from "src/L2/interfaces/IOptimismSuperchainERC20.sol";
import { IOptimismSuperchainERC20 } from "src/L2/interfaces/IOptimismSuperchainERC20.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
import { ERC165 } from "@openzeppelin/contracts-v5/utils/introspection/ERC165.sol";
import { SuperchainERC20 } from "src/L2/SuperchainERC20.sol";
Expand All @@ -15,7 +15,7 @@ import { Initializable } from "@openzeppelin/contracts-v5/proxy/utils/Initializa
/// OptimismSuperchainERC20 token, turning it fungible and interoperable across the superchain. Likewise, it
/// also enables the inverse conversion path.
/// Moreover, it builds on top of the L2ToL2CrossDomainMessenger for both replay protection and domain binding.
contract OptimismSuperchainERC20 is SuperchainERC20, Initializable, ERC165, IOptimismSuperchainERC20Extension {
contract OptimismSuperchainERC20 is SuperchainERC20, Initializable, ERC165, IOptimismSuperchainERC20 {
/// @notice Storage slot that the OptimismSuperchainERC20Metadata struct is stored at.
/// keccak256(abi.encode(uint256(keccak256("optimismSuperchainERC20.metadata")) - 1)) & ~bytes32(uint256(0xff));
bytes32 internal constant OPTIMISM_SUPERCHAIN_ERC20_METADATA_SLOT =
Expand Down Expand Up @@ -130,7 +130,6 @@ contract OptimismSuperchainERC20 is SuperchainERC20, Initializable, ERC165, IOpt
/// @param _interfaceId Interface ID to check.
/// @return Whether or not the interface is supported by this contract.
function supportsInterface(bytes4 _interfaceId) public view virtual override returns (bool) {
return
_interfaceId == type(IOptimismSuperchainERC20Extension).interfaceId || super.supportsInterface(_interfaceId);
return _interfaceId == type(IOptimismSuperchainERC20).interfaceId || super.supportsInterface(_interfaceId);
}
}
12 changes: 6 additions & 6 deletions packages/contracts-bedrock/src/L2/SuperchainERC20.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import { ISuperchainERC20Extension } from "src/L2/interfaces/ISuperchainERC20.sol";
import { ISuperchainERC20 } from "src/L2/interfaces/ISuperchainERC20.sol";
import { ISemver } from "src/universal/interfaces/ISemver.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
import { ERC20 } from "@solady/tokens/ERC20.sol";
Expand All @@ -10,7 +10,7 @@ import { ERC20 } from "@solady/tokens/ERC20.sol";
/// @notice SuperchainERC20 is a standard extension of the base ERC20 token contract that unifies ERC20 token
/// bridging to make it fungible across the Superchain. This construction allows the SuperchainERC20Bridge to
/// burn and mint tokens.
abstract contract SuperchainERC20 is ERC20, ISuperchainERC20Extension, ISemver {
abstract contract SuperchainERC20 is ERC20, ISuperchainERC20, ISemver {
/// @notice A modifier that only allows the SuperchainERC20Bridge to call
modifier onlySuperchainERC20Bridge() {
if (msg.sender != Predeploys.SUPERCHAIN_ERC20_BRIDGE) revert OnlySuperchainERC20Bridge();
Expand All @@ -26,18 +26,18 @@ abstract contract SuperchainERC20 is ERC20, ISuperchainERC20Extension, ISemver {
/// @notice Allows the SuperchainERC20Bridge to mint tokens.
/// @param _to Address to mint tokens to.
/// @param _amount Amount of tokens to mint.
function __superchainMint(address _to, uint256 _amount) external virtual onlySuperchainERC20Bridge {
function __crosschainMint(address _to, uint256 _amount) external virtual onlySuperchainERC20Bridge {
_mint(_to, _amount);

emit SuperchainMinted(_to, _amount);
emit CrosschainMinted(_to, _amount);
}

/// @notice Allows the SuperchainERC20Bridge to burn tokens.
/// @param _from Address to burn tokens from.
/// @param _amount Amount of tokens to burn.
function __superchainBurn(address _from, uint256 _amount) external virtual onlySuperchainERC20Bridge {
function __crosschainBurn(address _from, uint256 _amount) external virtual onlySuperchainERC20Bridge {
_burn(_from, _amount);

emit SuperchainBurnt(_from, _amount);
emit CrosschainBurnt(_from, _amount);
}
}
4 changes: 2 additions & 2 deletions packages/contracts-bedrock/src/L2/SuperchainERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ contract SuperchainERC20Bridge is ISuperchainERC20Bridge {
function sendERC20(address _token, address _to, uint256 _amount, uint256 _chainId) external {
if (_to == address(0)) revert ZeroAddress();

ISuperchainERC20(_token).__superchainBurn(msg.sender, _amount);
ISuperchainERC20(_token).__crosschainBurn(msg.sender, _amount);

bytes memory message = abi.encodeCall(this.relayERC20, (_token, msg.sender, _to, _amount));
IL2ToL2CrossDomainMessenger(MESSENGER).sendMessage(_chainId, address(this), message);
Expand All @@ -53,7 +53,7 @@ contract SuperchainERC20Bridge is ISuperchainERC20Bridge {

uint256 source = IL2ToL2CrossDomainMessenger(MESSENGER).crossDomainMessageSource();

ISuperchainERC20(_token).__superchainMint(_to, _amount);
ISuperchainERC20(_token).__crosschainMint(_to, _amount);

emit RelayERC20(_token, _from, _to, _amount, source);
}
Expand Down
26 changes: 26 additions & 0 deletions packages/contracts-bedrock/src/L2/interfaces/ICrosschainERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @title ICrosschainERC20
/// @notice Defines the interface for crosschain ERC20 transfers.
interface ICrosschainERC20 {
/// @notice Emitted when a crosschain transfer mints tokens.
/// @param to Address of the account tokens are being minted for.
/// @param amount Amount of tokens minted.
event CrosschainMinted(address indexed to, uint256 amount);

/// @notice Emitted when a crosschain transfer burns tokens.
/// @param from Address of the account tokens are being burned from.
/// @param amount Amount of tokens burned.
event CrosschainBurnt(address indexed from, uint256 amount);

/// @notice Mint tokens through a crosschain transfer.
/// @param _to Address to mint tokens to.
/// @param _amount Amount of tokens to mint.
function __crosschainMint(address _to, uint256 _amount) external;

/// @notice Burn tokens through a crosschain transfer.
/// @param _from Address to burn tokens from.
/// @param _amount Amount of tokens to burn.
function __crosschainBurn(address _from, uint256 _amount) external;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,26 @@
pragma solidity ^0.8.0;

// Interfaces
import { ISuperchainERC20, ISuperchainERC20Extension } from "src/L2/interfaces/ISuperchainERC20.sol";
import { IERC20Solady } from "src/vendor/interfaces/IERC20Solady.sol";
import { ISuperchainERC20 } from "src/L2/interfaces/ISuperchainERC20.sol";

/// @title IOptimismSuperchainERC20Errors
/// @notice Interface containing the errors added in the OptimismSuperchainERC20 implementation.
interface IOptimismSuperchainERC20Errors {
/// @title IOptimismSuperchainERC20
/// @notice This interface is available on the OptimismSuperchainERC20 contract.
interface IOptimismSuperchainERC20 is ISuperchainERC20 {
/// @notice Thrown when attempting to perform an operation and the account is the zero address.
error ZeroAddress();

/// @notice Thrown when attempting to mint or burn tokens and the function caller is not the L2StandardBridge
error OnlyL2StandardBridge();
}

/// @title IOptimismSuperchainERC20Extension
/// @notice This interface is available on the OptimismSuperchainERC20 contract.
interface IOptimismSuperchainERC20Extension is ISuperchainERC20Extension, IOptimismSuperchainERC20Errors {
/// @notice Emitted whenever tokens are minted for an account.
/// @param account Address of the account tokens are being minted for.
/// @param to Address of the account tokens are being minted for.
/// @param amount Amount of tokens minted.
event Mint(address indexed account, uint256 amount);
event Mint(address indexed to, uint256 amount);

/// @notice Emitted whenever tokens are burned from an account.
/// @param account Address of the account tokens are being burned from.
/// @param from Address of the account tokens are being burned from.
/// @param amount Amount of tokens burned.
event Burn(address indexed account, uint256 amount);
event Burn(address indexed from, uint256 amount);

/// @notice Allows the L2StandardBridge and SuperchainERC20Bridge to mint tokens.
/// @param _to Address to mint tokens to.
Expand All @@ -41,7 +36,3 @@ interface IOptimismSuperchainERC20Extension is ISuperchainERC20Extension, IOptim
/// @notice Returns the address of the corresponding version of this token on the remote chain.
function remoteToken() external view returns (address);
}

/// @title IOptimismSuperchainERC20
/// @notice Combines Solady's ERC20 interface with the IOptimismSuperchainERC20Extension interface.
interface IOptimismSuperchainERC20 is IERC20Solady, IOptimismSuperchainERC20Extension { }
38 changes: 4 additions & 34 deletions packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,11 @@
pragma solidity ^0.8.0;

// Interfaces
import { IERC20Solady } from "src/vendor/interfaces/IERC20Solady.sol";
import { ICrosschainERC20 } from "src/L2/interfaces/ICrosschainERC20.sol";

/// @title ISuperchainERC20Errors
/// @notice Interface containing the errors added in the SuperchainERC20 implementation.
interface ISuperchainERC20Errors {
/// @title ISuperchainERC20
/// @notice This interface is available on the SuperchainERC20 contract.
interface ISuperchainERC20 is ICrosschainERC20 {
/// @notice Thrown when attempting to mint or burn tokens and the function caller is not the SuperchainERC20Bridge.
error OnlySuperchainERC20Bridge();
}

/// @title ISuperchainERC20Extension
/// @notice This interface is available on the SuperchainERC20 contract.
interface ISuperchainERC20Extension is ISuperchainERC20Errors {
/// @notice Emitted whenever tokens are minted for by the SuperchainERC20Bridge.
/// @param account Address of the account tokens are being minted for.
/// @param amount Amount of tokens minted.
event SuperchainMinted(address indexed account, uint256 amount);

/// @notice Emitted whenever tokens are burned by the SuperchainERC20Bridge.
/// @param account Address of the account tokens are being burned from.
/// @param amount Amount of tokens burned.
event SuperchainBurnt(address indexed account, uint256 amount);

/// @notice Allows the SuperchainERC20Bridge to mint tokens.
/// @param _to Address to mint tokens to.
/// @param _amount Amount of tokens to mint.
function __superchainMint(address _to, uint256 _amount) external;

/// @notice Allows the SuperchainERC20Bridge to burn tokens.
/// @param _from Address to burn tokens from.
/// @param _amount Amount of tokens to burn.
function __superchainBurn(address _from, uint256 _amount) external;
}

/// @title ISuperchainERC20
/// @notice Combines Solady's ERC20 interface with the SuperchainERC20Extension interface.
interface ISuperchainERC20 is IERC20Solady, ISuperchainERC20Extension {
function __constructor__() external;
}
Loading

0 comments on commit a5aca61

Please sign in to comment.