Skip to content
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

fix: stop inheriting superchain interfaces #85

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ EXCLUDE_CONTRACTS=(
"IOptimismSuperchainERC20"

# Doesn't start with "I"
"MintableAndBurnable"
"KontrolCheatsBase"

# Currently inherit from interface, needs to be fixed.
"IWETH"
"IDelayedWETH"
"ISuperchainWETH"
"IL2ToL2CrossDomainMessenger"
"ICrossL2Inbox"
"ISystemConfigInterop"
Expand Down
12 changes: 6 additions & 6 deletions packages/contracts-bedrock/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,28 +116,28 @@
"sourceCodeHash": "0xfea53344596d735eff3be945ed1300dc75a6f8b7b2c02c0043af5b0036f5f239"
},
"src/L2/OptimismSuperchainERC20.sol": {
"initCodeHash": "0x964c826693c6633dc5eff6d4b059a30043775af46b06e42367aff91b904498da",
"sourceCodeHash": "0xf5cb8307067f2ef7aa540b9e0a4828cde76f783c7fb95c7d3f84c6d723f9d316"
"initCodeHash": "0x28372d06b45a3235a2c5273e3d6e41fe9572dd58ad8a20161b917d0e45a9718e",
"sourceCodeHash": "0x5a40eabbdc33bd96ff0a7bc2be6699a7b6233610bf67f3da899f0efb367bb486"
},
"src/L2/OptimismSuperchainERC20Beacon.sol": {
"initCodeHash": "0x99ce8095b23c124850d866cbc144fee6cee05dbc6bb5d83acadfe00b90cf42c7",
"sourceCodeHash": "0x5e58b7c867fafa49fe39d68d83875425e9cf94f05f2835bdcdaa08fc8bc6b68e"
},
"src/L2/OptimismSuperchainERC20Factory.sol": {
"initCodeHash": "0x43ec413140b05bfb83ec453b0d4f82b33a2d560bf8c76405d08de17565b87053",
"sourceCodeHash": "0x04a88ee6c4cf68becf8727b53cbc56ab6cfbaac9dbeb61083f63613dbf823a76"
"sourceCodeHash": "0xf50cb5566da50883cc320b90e5ca117dcbb3f6d0dc2afa01db4f400d882319dc"
},
"src/L2/SequencerFeeVault.sol": {
"initCodeHash": "0x2e6551705e493bacba8cffe22e564d5c401ae5bb02577a5424e0d32784e13e74",
"sourceCodeHash": "0xd56922cb04597dea469c65e5a49d4b3c50c171e603601e6f41da9517cae0b11a"
},
"src/L2/SuperchainERC20.sol": {
"initCodeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
"sourceCodeHash": "0x4debbf83ad569eae88fb1e70db5f45fb85eed609fd464bd180611756116e04ae"
"sourceCodeHash": "0x4d251314bae2904986d3df791e916fc619bc65d09ccd80bc2032cfdd12b8c0a3"
},
"src/L2/SuperchainERC20Bridge.sol": {
"initCodeHash": "0xf85225ea25a87ba670b6ce0172a4814fda712d1c8a174fd4e8ce72b1cebcc2a0",
"sourceCodeHash": "0x4fabf65703f4a02bdd7e2b6f2425448f2c54162ae12bbbbaed1fbb8ec569a873"
"initCodeHash": "0xfeba60d8e17a0c62cc56c7319da323e154ccc6c379e7b72c48c9d0ce1e5b9474",
"sourceCodeHash": "0xf576ba9150a9ec0f1b624b821453eec9a79a8baadb735e3b7b7a7cae7f8e9f91"
},
"src/L2/SuperchainWETH.sol": {
"initCodeHash": "0x5db03c5c4cd6ea9e4b3e74e28f50d04fd3e130af5109b34fa208808fa9ba7742",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@
"inputs": [
{
"internalType": "address",
"name": "superchainToken",
"name": "_localToken",
"type": "address"
}
],
"name": "deployments",
"outputs": [
{
"internalType": "address",
"name": "remoteToken",
"name": "remoteToken_",
"type": "address"
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@
}
],
"name": "sendERC20",
"outputs": [],
"outputs": [
{
"internalType": "bytes32",
"name": "msgHash_",
"type": "bytes32"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
Expand Down
20 changes: 18 additions & 2 deletions packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,23 @@ 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, IOptimismSuperchainERC20 {
contract OptimismSuperchainERC20 is SuperchainERC20, Initializable, ERC165 {
/// @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();

/// @notice Emitted whenever tokens are minted for an account.
/// @param to Address of the account tokens are being minted for.
/// @param amount Amount of tokens minted.
event Mint(address indexed to, uint256 amount);

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

/// @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 @@ -102,7 +118,7 @@ contract OptimismSuperchainERC20 is SuperchainERC20, Initializable, ERC165, IOpt
}

/// @notice Returns the address of the corresponding version of this token on the remote chain.
function remoteToken() public view override returns (address) {
function remoteToken() public view returns (address) {
return _getStorage().remoteToken;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import { IOptimismSuperchainERC20Factory } from "src/L2/interfaces/IOptimismSuperchainERC20Factory.sol";
import { ISemver } from "src/universal/interfaces/ISemver.sol";
import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
Expand All @@ -13,11 +12,7 @@ import { CREATE3 } from "@rari-capital/solmate/src/utils/CREATE3.sol";
/// @title OptimismSuperchainERC20Factory
/// @notice OptimismSuperchainERC20Factory is a factory contract that deploys OptimismSuperchainERC20 Beacon Proxies
/// using CREATE3.
contract OptimismSuperchainERC20Factory is IOptimismSuperchainERC20Factory, ISemver {
/// @notice Mapping of the deployed OptimismSuperchainERC20 to the remote token address.
/// This is used to keep track of the token deployments.
mapping(address superchainToken => address remoteToken) public deployments;

contract OptimismSuperchainERC20Factory is ISemver {
/// @notice Emitted when an OptimismSuperchainERC20 is deployed.
/// @param superchainToken Address of the OptimismSuperchainERC20 deployment.
/// @param remoteToken Address of the corresponding token on the remote chain.
Expand All @@ -30,6 +25,10 @@ contract OptimismSuperchainERC20Factory is IOptimismSuperchainERC20Factory, ISem
/// @custom:semver 1.0.0-beta.3
string public constant version = "1.0.0-beta.3";

/// @notice Mapping of the deployed OptimismSuperchainERC20 to the remote token address.
/// This is used to keep track of the token deployments.
mapping(address _localToken => address remoteToken_) public deployments;
0xDiscotech marked this conversation as resolved.
Show resolved Hide resolved

/// @notice Deploys a OptimismSuperchainERC20 Beacon Proxy using CREATE3.
/// @param _remoteToken Address of the remote token.
/// @param _name Name of the OptimismSuperchainERC20.
Expand Down
9 changes: 6 additions & 3 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 { ISuperchainERC20 } from "src/L2/interfaces/ISuperchainERC20.sol";
import { ICrosschainERC20 } from "src/L2/interfaces/ICrosschainERC20.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,10 @@ 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, ISuperchainERC20, ISemver {
abstract contract SuperchainERC20 is ERC20, ICrosschainERC20, ISemver {
/// @notice Thrown when attempting to mint or burn tokens and the function caller is not the SuperchainERC20Bridge.
error OnlySuperchainERC20Bridge();

/// @notice A modifier that only allows the SuperchainERC20Bridge to call
modifier onlySuperchainERC20Bridge() {
if (msg.sender != Predeploys.SUPERCHAIN_ERC20_BRIDGE) revert OnlySuperchainERC20Bridge();
Expand All @@ -19,7 +22,7 @@ abstract contract SuperchainERC20 is ERC20, ISuperchainERC20, ISemver {

/// @notice Semantic version.
/// @custom:semver 1.0.0-beta.1
function version() external pure virtual returns (string memory) {
function version() external view virtual returns (string memory) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not pure?

Copy link
Member Author

@agusduha agusduha Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ABI diff makes the script fail

return "1.0.0-beta.1";
}

Expand Down
59 changes: 53 additions & 6 deletions packages/contracts-bedrock/src/L2/SuperchainERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ pragma solidity 0.8.25;
import { Predeploys } from "src/libraries/Predeploys.sol";

// Interfaces
import { ISuperchainERC20Bridge } from "src/L2/interfaces/ISuperchainERC20Bridge.sol";
import { ISuperchainERC20 } from "src/L2/interfaces/ISuperchainERC20.sol";
import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol";

Expand All @@ -15,27 +14,75 @@ import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomai
/// @notice The SuperchainERC20Bridge allows for the bridging of ERC20 tokens to make them fungible across the
/// Superchain. It builds on top of the L2ToL2CrossDomainMessenger for both replay protection and domain
/// binding.
contract SuperchainERC20Bridge is ISuperchainERC20Bridge {
contract SuperchainERC20Bridge {
/// @notice Thrown when attempting to perform an operation and the account is the zero address.
error ZeroAddress();

/// @notice Thrown when attempting to relay a message and the function caller (msg.sender) is not
/// L2ToL2CrossDomainMessenger.
error CallerNotL2ToL2CrossDomainMessenger();

/// @notice Thrown when attempting to relay a message and the cross domain message sender is not the
/// SuperchainERC20Bridge.
error InvalidCrossDomainSender();

/// @notice Emitted when tokens are sent from one chain to another.
/// @param token Address of the token sent.
/// @param from Address of the sender.
/// @param to Address of the recipient.
/// @param amount Number of tokens sent.
/// @param destination Chain ID of the destination chain.
event SendERC20(
address indexed token, address indexed from, address indexed to, uint256 amount, uint256 destination
);

/// @notice Emitted whenever tokens are successfully relayed on this chain.
/// @param token Address of the token relayed.
/// @param from Address of the msg.sender of sendERC20 on the source chain.
/// @param to Address of the recipient.
/// @param amount Amount of tokens relayed.
/// @param source Chain ID of the source chain.
event RelayERC20(address indexed token, address indexed from, address indexed to, uint256 amount, uint256 source);

/// @notice Address of the L2ToL2CrossDomainMessenger Predeploy.
address internal constant MESSENGER = Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER;

/// @notice Semantic version.
/// @custom:semver 1.0.0-beta.1
string public constant version = "1.0.0-beta.1";

/// @inheritdoc ISuperchainERC20Bridge
function sendERC20(address _token, address _to, uint256 _amount, uint256 _chainId) external {
/// @notice Sends tokens to a target address on another chain.
/// @dev Tokens are burned on the source chain.
/// @param _token Token to send.
/// @param _to Address to send tokens to.
/// @param _amount Amount of tokens to send.
/// @param _chainId Chain ID of the destination chain.
/// @return msgHash_ Hash of the message sent.
function sendERC20(
address _token,
address _to,
uint256 _amount,
uint256 _chainId
)
external
returns (bytes32 msgHash_)
{
if (_to == address(0)) revert ZeroAddress();

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);
msgHash_ = IL2ToL2CrossDomainMessenger(MESSENGER).sendMessage(_chainId, address(this), message);

emit SendERC20(_token, msg.sender, _to, _amount, _chainId);
}

/// @inheritdoc ISuperchainERC20Bridge
/// @notice Relays tokens received from another chain.
/// @dev Tokens are minted on the destination chain.
/// @param _token Token to relay.
/// @param _from Address of the msg.sender of sendERC20 on the source chain.
/// @param _to Address to relay tokens to.
/// @param _amount Amount of tokens to relay.
function relayERC20(address _token, address _from, address _to, uint256 _amount) external {
if (msg.sender != MESSENGER) revert CallerNotL2ToL2CrossDomainMessenger();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,18 @@ import { ISuperchainERC20 } from "src/L2/interfaces/ISuperchainERC20.sol";
/// @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();

/// @notice Emitted whenever tokens are minted for an account.
/// @param to Address of the account tokens are being minted for.
/// @param amount Amount of tokens minted.
event Mint(address indexed to, uint256 amount);

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

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

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

/// @notice Returns the address of the corresponding version of this token on the remote chain.
function remoteToken() external view returns (address);

function __constructor__() external;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@
pragma solidity ^0.8.0;

import { IOptimismERC20Factory } from "./IOptimismERC20Factory.sol";
import { ISemver } from "src/universal/interfaces/ISemver.sol";

/// @title IOptimismSuperchainERC20Factory
/// @notice Interface for OptimismSuperchainERC20Factory.
interface IOptimismSuperchainERC20Factory is IOptimismERC20Factory {
/// @notice Deploys a OptimismSuperchainERC20 Beacon Proxy using CREATE3.
/// @param _remoteToken Address of the remote token.
/// @param _name Name of the OptimismSuperchainERC20.
/// @param _symbol Symbol of the OptimismSuperchainERC20.
/// @param _decimals Decimals of the OptimismSuperchainERC20.
/// @return _superchainERC20 Address of the OptimismSuperchainERC20 deployment.
interface IOptimismSuperchainERC20Factory is IOptimismERC20Factory, ISemver {
event OptimismSuperchainERC20Created(
address indexed superchainToken, address indexed remoteToken, address deployer
);

function deploy(
address _remoteToken,
string memory _name,
string memory _symbol,
uint8 _decimals
)
external
returns (address _superchainERC20);
returns (address superchainERC20_);

function __constructor__() external;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ pragma solidity ^0.8.0;

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

/// @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.
interface ISuperchainERC20 is ICrosschainERC20, IERC20Solady, ISemver {
error OnlySuperchainERC20Bridge();

function __constructor__() external;
}
Loading