From 816257428ebb4d03bcf2fe92c7669fd88b21d48e Mon Sep 17 00:00:00 2001 From: agusduha Date: Fri, 4 Oct 2024 15:28:53 -0300 Subject: [PATCH 1/3] fix: stop inheriting superchain interfaces --- .../scripts/checks/check-interfaces.sh | 2 +- packages/contracts-bedrock/semver-lock.json | 12 +++--- .../abi/OptimismSuperchainERC20Factory.json | 4 +- .../snapshots/abi/SuperchainERC20Bridge.json | 8 +++- .../src/L2/OptimismSuperchainERC20.sol | 14 +++---- .../src/L2/OptimismSuperchainERC20Factory.sol | 14 ++----- .../src/L2/SuperchainERC20.sol | 11 +++--- .../src/L2/SuperchainERC20Bridge.sol | 39 ++++++++++++++----- .../interfaces/IOptimismSuperchainERC20.sol | 2 + .../IOptimismSuperchainERC20Factory.sol | 17 ++++++-- .../src/L2/interfaces/ISuperchainERC20.sol | 6 ++- .../L2/interfaces/ISuperchainERC20Bridge.sol | 20 +++++++--- .../test/L2/SuperchainERC20Bridge.t.sol | 20 ++++++++-- 13 files changed, 113 insertions(+), 56 deletions(-) diff --git a/packages/contracts-bedrock/scripts/checks/check-interfaces.sh b/packages/contracts-bedrock/scripts/checks/check-interfaces.sh index 174c26969058..c7d8476cc758 100755 --- a/packages/contracts-bedrock/scripts/checks/check-interfaces.sh +++ b/packages/contracts-bedrock/scripts/checks/check-interfaces.sh @@ -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" diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index f27a45372557..fe1374844623 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -116,8 +116,8 @@ "sourceCodeHash": "0xfea53344596d735eff3be945ed1300dc75a6f8b7b2c02c0043af5b0036f5f239" }, "src/L2/OptimismSuperchainERC20.sol": { - "initCodeHash": "0x964c826693c6633dc5eff6d4b059a30043775af46b06e42367aff91b904498da", - "sourceCodeHash": "0xf5cb8307067f2ef7aa540b9e0a4828cde76f783c7fb95c7d3f84c6d723f9d316" + "initCodeHash": "0x28372d06b45a3235a2c5273e3d6e41fe9572dd58ad8a20161b917d0e45a9718e", + "sourceCodeHash": "0xe56a4521dc38833ebd58febe2c1ce05b1425623aa29536937ca629c906740fcd" }, "src/L2/OptimismSuperchainERC20Beacon.sol": { "initCodeHash": "0x99ce8095b23c124850d866cbc144fee6cee05dbc6bb5d83acadfe00b90cf42c7", @@ -125,7 +125,7 @@ }, "src/L2/OptimismSuperchainERC20Factory.sol": { "initCodeHash": "0x43ec413140b05bfb83ec453b0d4f82b33a2d560bf8c76405d08de17565b87053", - "sourceCodeHash": "0x04a88ee6c4cf68becf8727b53cbc56ab6cfbaac9dbeb61083f63613dbf823a76" + "sourceCodeHash": "0x394c647d2d6a73b68297b20d10ba8ddd9f59ca4d916052cc709e83a640a55422" }, "src/L2/SequencerFeeVault.sol": { "initCodeHash": "0x2e6551705e493bacba8cffe22e564d5c401ae5bb02577a5424e0d32784e13e74", @@ -133,11 +133,11 @@ }, "src/L2/SuperchainERC20.sol": { "initCodeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "sourceCodeHash": "0x4debbf83ad569eae88fb1e70db5f45fb85eed609fd464bd180611756116e04ae" + "sourceCodeHash": "0xa1999c8fa4fe59b22e32f2aa81d986ae5b7467b41250338870942548a33aa091" }, "src/L2/SuperchainERC20Bridge.sol": { - "initCodeHash": "0xf85225ea25a87ba670b6ce0172a4814fda712d1c8a174fd4e8ce72b1cebcc2a0", - "sourceCodeHash": "0x4fabf65703f4a02bdd7e2b6f2425448f2c54162ae12bbbbaed1fbb8ec569a873" + "initCodeHash": "0xfeba60d8e17a0c62cc56c7319da323e154ccc6c379e7b72c48c9d0ce1e5b9474", + "sourceCodeHash": "0x81d161ed426fa7b766a98b8d82e0d579fbf8717196bcd487bf269b98d780142e" }, "src/L2/SuperchainWETH.sol": { "initCodeHash": "0x5db03c5c4cd6ea9e4b3e74e28f50d04fd3e130af5109b34fa208808fa9ba7742", diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20Factory.json b/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20Factory.json index eb1315194e44..f6020300b036 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20Factory.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20Factory.json @@ -37,7 +37,7 @@ "inputs": [ { "internalType": "address", - "name": "superchainToken", + "name": "_localToken", "type": "address" } ], @@ -45,7 +45,7 @@ "outputs": [ { "internalType": "address", - "name": "remoteToken", + "name": "remoteToken_", "type": "address" } ], diff --git a/packages/contracts-bedrock/snapshots/abi/SuperchainERC20Bridge.json b/packages/contracts-bedrock/snapshots/abi/SuperchainERC20Bridge.json index ed7ff2ba5129..1eec16f60e3d 100644 --- a/packages/contracts-bedrock/snapshots/abi/SuperchainERC20Bridge.json +++ b/packages/contracts-bedrock/snapshots/abi/SuperchainERC20Bridge.json @@ -51,7 +51,13 @@ } ], "name": "sendERC20", - "outputs": [], + "outputs": [ + { + "internalType": "bytes32", + "name": "msgHash_", + "type": "bytes32" + } + ], "stateMutability": "nonpayable", "type": "function" }, diff --git a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol index 017b5060d90f..dd86d107b1af 100644 --- a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol @@ -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, IOptimismSuperchainERC20 { +contract OptimismSuperchainERC20 is SuperchainERC20, Initializable, ERC165 { /// @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 = @@ -44,7 +44,7 @@ contract OptimismSuperchainERC20 is SuperchainERC20, Initializable, ERC165, IOpt /// @notice A modifier that only allows the L2StandardBridge to call modifier onlyL2StandardBridge() { if (msg.sender != Predeploys.L2_STANDARD_BRIDGE) { - revert OnlyL2StandardBridge(); + revert IOptimismSuperchainERC20.OnlyL2StandardBridge(); } _; } @@ -83,26 +83,26 @@ contract OptimismSuperchainERC20 is SuperchainERC20, Initializable, ERC165, IOpt /// @param _to Address to mint tokens to. /// @param _amount Amount of tokens to mint. function mint(address _to, uint256 _amount) external virtual onlyL2StandardBridge { - if (_to == address(0)) revert ZeroAddress(); + if (_to == address(0)) revert IOptimismSuperchainERC20.ZeroAddress(); _mint(_to, _amount); - emit Mint(_to, _amount); + emit IOptimismSuperchainERC20.Mint(_to, _amount); } /// @notice Allows the L2StandardBridge to burn tokens. /// @param _from Address to burn tokens from. /// @param _amount Amount of tokens to burn. function burn(address _from, uint256 _amount) external virtual onlyL2StandardBridge { - if (_from == address(0)) revert ZeroAddress(); + if (_from == address(0)) revert IOptimismSuperchainERC20.ZeroAddress(); _burn(_from, _amount); - emit Burn(_from, _amount); + emit IOptimismSuperchainERC20.Burn(_from, _amount); } /// @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; } diff --git a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol index e7ad7ed389b5..04421da5e5ff 100644 --- a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol +++ b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol @@ -13,18 +13,10 @@ 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 { +contract OptimismSuperchainERC20Factory is 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; - - /// @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. - /// @param deployer Address of the account that deployed the token. - event OptimismSuperchainERC20Created( - address indexed superchainToken, address indexed remoteToken, address deployer - ); + mapping(address _localToken => address remoteToken_) public deployments; /// @notice Semantic version. /// @custom:semver 1.0.0-beta.3 @@ -57,6 +49,6 @@ contract OptimismSuperchainERC20Factory is IOptimismSuperchainERC20Factory, ISem deployments[superchainERC20_] = _remoteToken; - emit OptimismSuperchainERC20Created(superchainERC20_, _remoteToken, msg.sender); + emit IOptimismSuperchainERC20Factory.OptimismSuperchainERC20Created(superchainERC20_, _remoteToken, msg.sender); } } diff --git a/packages/contracts-bedrock/src/L2/SuperchainERC20.sol b/packages/contracts-bedrock/src/L2/SuperchainERC20.sol index c2ef27ebc273..357fbf3dd64e 100644 --- a/packages/contracts-bedrock/src/L2/SuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/SuperchainERC20.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.25; +import { ICrosschainERC20 } from "src/L2/interfaces/ICrosschainERC20.sol"; import { ISuperchainERC20 } from "src/L2/interfaces/ISuperchainERC20.sol"; import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; @@ -10,16 +11,16 @@ 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, ISemver { /// @notice A modifier that only allows the SuperchainERC20Bridge to call modifier onlySuperchainERC20Bridge() { - if (msg.sender != Predeploys.SUPERCHAIN_ERC20_BRIDGE) revert OnlySuperchainERC20Bridge(); + if (msg.sender != Predeploys.SUPERCHAIN_ERC20_BRIDGE) revert ISuperchainERC20.OnlySuperchainERC20Bridge(); _; } /// @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) { return "1.0.0-beta.1"; } @@ -29,7 +30,7 @@ abstract contract SuperchainERC20 is ERC20, ISuperchainERC20, ISemver { function __crosschainMint(address _to, uint256 _amount) external virtual onlySuperchainERC20Bridge { _mint(_to, _amount); - emit CrosschainMinted(_to, _amount); + emit ICrosschainERC20.CrosschainMinted(_to, _amount); } /// @notice Allows the SuperchainERC20Bridge to burn tokens. @@ -38,6 +39,6 @@ abstract contract SuperchainERC20 is ERC20, ISuperchainERC20, ISemver { function __crosschainBurn(address _from, uint256 _amount) external virtual onlySuperchainERC20Bridge { _burn(_from, _amount); - emit CrosschainBurnt(_from, _amount); + emit ICrosschainERC20.CrosschainBurnt(_from, _amount); } } diff --git a/packages/contracts-bedrock/src/L2/SuperchainERC20Bridge.sol b/packages/contracts-bedrock/src/L2/SuperchainERC20Bridge.sol index b6674864502a..299087a801a1 100644 --- a/packages/contracts-bedrock/src/L2/SuperchainERC20Bridge.sol +++ b/packages/contracts-bedrock/src/L2/SuperchainERC20Bridge.sol @@ -15,7 +15,7 @@ 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 Address of the L2ToL2CrossDomainMessenger Predeploy. address internal constant MESSENGER = Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER; @@ -23,30 +23,49 @@ contract SuperchainERC20Bridge is ISuperchainERC20Bridge { /// @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 { - if (_to == address(0)) revert ZeroAddress(); + /// @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 ISuperchainERC20Bridge.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); + emit ISuperchainERC20Bridge.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(); + if (msg.sender != MESSENGER) revert ISuperchainERC20Bridge.CallerNotL2ToL2CrossDomainMessenger(); if (IL2ToL2CrossDomainMessenger(MESSENGER).crossDomainMessageSender() != address(this)) { - revert InvalidCrossDomainSender(); + revert ISuperchainERC20Bridge.InvalidCrossDomainSender(); } uint256 source = IL2ToL2CrossDomainMessenger(MESSENGER).crossDomainMessageSource(); ISuperchainERC20(_token).__crosschainMint(_to, _amount); - emit RelayERC20(_token, _from, _to, _amount, source); + emit ISuperchainERC20Bridge.RelayERC20(_token, _from, _to, _amount, source); } } diff --git a/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol b/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol index e8d87d91e4b4..cfe822e84f96 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol @@ -35,4 +35,6 @@ interface IOptimismSuperchainERC20 is ISuperchainERC20 { /// @notice Returns the address of the corresponding version of this token on the remote chain. function remoteToken() external view returns (address); + + function __constructor__() external; } diff --git a/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20Factory.sol b/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20Factory.sol index aa23405fa527..f7d8872bd29e 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20Factory.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20Factory.sol @@ -2,16 +2,25 @@ 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 { +interface IOptimismSuperchainERC20Factory is IOptimismERC20Factory, 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. + /// @param deployer Address of the account that deployed the token. + event OptimismSuperchainERC20Created( + address indexed superchainToken, address indexed remoteToken, address deployer + ); + /// @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. + /// @return superchainERC20_ Address of the OptimismSuperchainERC20 deployment. function deploy( address _remoteToken, string memory _name, @@ -19,5 +28,7 @@ interface IOptimismSuperchainERC20Factory is IOptimismERC20Factory { uint8 _decimals ) external - returns (address _superchainERC20); + returns (address superchainERC20_); + + function __constructor__() external; } diff --git a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol index cc96520355f9..0b9e998c8037 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol @@ -3,10 +3,14 @@ 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 { +interface ISuperchainERC20 is ICrosschainERC20, IERC20Solady, ISemver { /// @notice Thrown when attempting to mint or burn tokens and the function caller is not the SuperchainERC20Bridge. error OnlySuperchainERC20Bridge(); + + function __constructor__() external; } diff --git a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20Bridge.sol b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20Bridge.sol index b570b835a56f..2ea9ccdb6fdc 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20Bridge.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20Bridge.sol @@ -37,11 +37,19 @@ interface ISuperchainERC20Bridge is ISemver { /// @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. - function sendERC20(address _token, address _to, uint256 _amount, uint256 _chainId) external; + /// @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_); /// @notice Relays tokens received from another chain. /// @dev Tokens are minted on the destination chain. @@ -50,4 +58,6 @@ interface ISuperchainERC20Bridge is ISemver { /// @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; + + function __constructor__() external; } diff --git a/packages/contracts-bedrock/test/L2/SuperchainERC20Bridge.t.sol b/packages/contracts-bedrock/test/L2/SuperchainERC20Bridge.t.sol index b6ccc681068f..dd77b80316b9 100644 --- a/packages/contracts-bedrock/test/L2/SuperchainERC20Bridge.t.sol +++ b/packages/contracts-bedrock/test/L2/SuperchainERC20Bridge.t.sol @@ -62,9 +62,18 @@ contract SuperchainERC20BridgeTest is Bridge_Initializer { /// @notice Tests the `sendERC20` function burns the sender tokens, sends the message, and emits the `SendERC20` /// event. - function testFuzz_sendERC20_succeeds(address _sender, address _to, uint256 _amount, uint256 _chainId) external { - // Ensure `_sender` is not the zero address + function testFuzz_sendERC20_succeeds( + address _sender, + address _to, + uint256 _amount, + uint256 _chainId, + bytes32 _msgHash + ) + external + { + // Ensure `_sender` and `_to` is not the zero address vm.assume(_sender != ZERO_ADDRESS); + vm.assume(_to != ZERO_ADDRESS); // Mint some tokens to the sender so then they can be sent vm.prank(Predeploys.SUPERCHAIN_ERC20_BRIDGE); @@ -90,12 +99,15 @@ contract SuperchainERC20BridgeTest is Bridge_Initializer { abi.encodeWithSelector( IL2ToL2CrossDomainMessenger.sendMessage.selector, _chainId, address(superchainERC20Bridge), _message ), - abi.encode("") + abi.encode(_msgHash) ); // Call the `sendERC20` function vm.prank(_sender); - superchainERC20Bridge.sendERC20(address(superchainERC20), _to, _amount, _chainId); + bytes32 _returnedMsgHash = superchainERC20Bridge.sendERC20(address(superchainERC20), _to, _amount, _chainId); + + // Check the message hash was generated correctly + assertEq(_msgHash, _returnedMsgHash); // Check the total supply and balance of `_sender` after the send were updated correctly assertEq(IERC20(address(superchainERC20)).totalSupply(), _totalSupplyBefore - _amount); From b9df3a0a9281fba806fad1a0ebc2a11a7c4262dd Mon Sep 17 00:00:00 2001 From: agusduha Date: Fri, 4 Oct 2024 16:39:17 -0300 Subject: [PATCH 2/3] fix: move events and erros into the implementation --- packages/contracts-bedrock/semver-lock.json | 8 ++-- .../src/L2/OptimismSuperchainERC20.sol | 26 +++++++++--- .../src/L2/OptimismSuperchainERC20Factory.sol | 17 +++++--- .../src/L2/SuperchainERC20.sol | 6 ++- .../src/L2/SuperchainERC20Bridge.sol | 40 ++++++++++++++++--- .../interfaces/IOptimismSuperchainERC20.sol | 16 -------- .../IOptimismSuperchainERC20Factory.sol | 10 ----- .../src/L2/interfaces/ISuperchainERC20.sol | 1 - .../L2/interfaces/ISuperchainERC20Bridge.sol | 32 --------------- 9 files changed, 75 insertions(+), 81 deletions(-) diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index fe1374844623..dec8e09fc92d 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -117,7 +117,7 @@ }, "src/L2/OptimismSuperchainERC20.sol": { "initCodeHash": "0x28372d06b45a3235a2c5273e3d6e41fe9572dd58ad8a20161b917d0e45a9718e", - "sourceCodeHash": "0xe56a4521dc38833ebd58febe2c1ce05b1425623aa29536937ca629c906740fcd" + "sourceCodeHash": "0x5a40eabbdc33bd96ff0a7bc2be6699a7b6233610bf67f3da899f0efb367bb486" }, "src/L2/OptimismSuperchainERC20Beacon.sol": { "initCodeHash": "0x99ce8095b23c124850d866cbc144fee6cee05dbc6bb5d83acadfe00b90cf42c7", @@ -125,7 +125,7 @@ }, "src/L2/OptimismSuperchainERC20Factory.sol": { "initCodeHash": "0x43ec413140b05bfb83ec453b0d4f82b33a2d560bf8c76405d08de17565b87053", - "sourceCodeHash": "0x394c647d2d6a73b68297b20d10ba8ddd9f59ca4d916052cc709e83a640a55422" + "sourceCodeHash": "0xf50cb5566da50883cc320b90e5ca117dcbb3f6d0dc2afa01db4f400d882319dc" }, "src/L2/SequencerFeeVault.sol": { "initCodeHash": "0x2e6551705e493bacba8cffe22e564d5c401ae5bb02577a5424e0d32784e13e74", @@ -133,11 +133,11 @@ }, "src/L2/SuperchainERC20.sol": { "initCodeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "sourceCodeHash": "0xa1999c8fa4fe59b22e32f2aa81d986ae5b7467b41250338870942548a33aa091" + "sourceCodeHash": "0x7b7f564d35ad85059dbfb6b0b2b012d0e323bc5dbe1edee5f76f9dece4e1fe2e" }, "src/L2/SuperchainERC20Bridge.sol": { "initCodeHash": "0xfeba60d8e17a0c62cc56c7319da323e154ccc6c379e7b72c48c9d0ce1e5b9474", - "sourceCodeHash": "0x81d161ed426fa7b766a98b8d82e0d579fbf8717196bcd487bf269b98d780142e" + "sourceCodeHash": "0xf576ba9150a9ec0f1b624b821453eec9a79a8baadb735e3b7b7a7cae7f8e9f91" }, "src/L2/SuperchainWETH.sol": { "initCodeHash": "0x5db03c5c4cd6ea9e4b3e74e28f50d04fd3e130af5109b34fa208808fa9ba7742", diff --git a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol index dd86d107b1af..f34e6b0f525a 100644 --- a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol @@ -16,6 +16,22 @@ import { Initializable } from "@openzeppelin/contracts-v5/proxy/utils/Initializa /// 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 { + /// @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 = @@ -44,7 +60,7 @@ contract OptimismSuperchainERC20 is SuperchainERC20, Initializable, ERC165 { /// @notice A modifier that only allows the L2StandardBridge to call modifier onlyL2StandardBridge() { if (msg.sender != Predeploys.L2_STANDARD_BRIDGE) { - revert IOptimismSuperchainERC20.OnlyL2StandardBridge(); + revert OnlyL2StandardBridge(); } _; } @@ -83,22 +99,22 @@ contract OptimismSuperchainERC20 is SuperchainERC20, Initializable, ERC165 { /// @param _to Address to mint tokens to. /// @param _amount Amount of tokens to mint. function mint(address _to, uint256 _amount) external virtual onlyL2StandardBridge { - if (_to == address(0)) revert IOptimismSuperchainERC20.ZeroAddress(); + if (_to == address(0)) revert ZeroAddress(); _mint(_to, _amount); - emit IOptimismSuperchainERC20.Mint(_to, _amount); + emit Mint(_to, _amount); } /// @notice Allows the L2StandardBridge to burn tokens. /// @param _from Address to burn tokens from. /// @param _amount Amount of tokens to burn. function burn(address _from, uint256 _amount) external virtual onlyL2StandardBridge { - if (_from == address(0)) revert IOptimismSuperchainERC20.ZeroAddress(); + if (_from == address(0)) revert ZeroAddress(); _burn(_from, _amount); - emit IOptimismSuperchainERC20.Burn(_from, _amount); + emit Burn(_from, _amount); } /// @notice Returns the address of the corresponding version of this token on the remote chain. diff --git a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol index 04421da5e5ff..cdd900ce33f7 100644 --- a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol +++ b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol @@ -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"; @@ -14,14 +13,22 @@ import { CREATE3 } from "@rari-capital/solmate/src/utils/CREATE3.sol"; /// @notice OptimismSuperchainERC20Factory is a factory contract that deploys OptimismSuperchainERC20 Beacon Proxies /// using CREATE3. contract OptimismSuperchainERC20Factory is ISemver { - /// @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; + /// @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. + /// @param deployer Address of the account that deployed the token. + event OptimismSuperchainERC20Created( + address indexed superchainToken, address indexed remoteToken, address deployer + ); /// @notice Semantic version. /// @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; + /// @notice Deploys a OptimismSuperchainERC20 Beacon Proxy using CREATE3. /// @param _remoteToken Address of the remote token. /// @param _name Name of the OptimismSuperchainERC20. @@ -49,6 +56,6 @@ contract OptimismSuperchainERC20Factory is ISemver { deployments[superchainERC20_] = _remoteToken; - emit IOptimismSuperchainERC20Factory.OptimismSuperchainERC20Created(superchainERC20_, _remoteToken, msg.sender); + emit OptimismSuperchainERC20Created(superchainERC20_, _remoteToken, msg.sender); } } diff --git a/packages/contracts-bedrock/src/L2/SuperchainERC20.sol b/packages/contracts-bedrock/src/L2/SuperchainERC20.sol index 357fbf3dd64e..b4689e3a6380 100644 --- a/packages/contracts-bedrock/src/L2/SuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/SuperchainERC20.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.25; import { ICrosschainERC20 } from "src/L2/interfaces/ICrosschainERC20.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"; @@ -12,9 +11,12 @@ import { ERC20 } from "@solady/tokens/ERC20.sol"; /// bridging to make it fungible across the Superchain. This construction allows the SuperchainERC20Bridge to /// burn and mint tokens. abstract contract SuperchainERC20 is ERC20, 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 ISuperchainERC20.OnlySuperchainERC20Bridge(); + if (msg.sender != Predeploys.SUPERCHAIN_ERC20_BRIDGE) revert OnlySuperchainERC20Bridge(); _; } diff --git a/packages/contracts-bedrock/src/L2/SuperchainERC20Bridge.sol b/packages/contracts-bedrock/src/L2/SuperchainERC20Bridge.sol index 299087a801a1..dc6cd86b04bd 100644 --- a/packages/contracts-bedrock/src/L2/SuperchainERC20Bridge.sol +++ b/packages/contracts-bedrock/src/L2/SuperchainERC20Bridge.sol @@ -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"; @@ -16,6 +15,35 @@ import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomai /// Superchain. It builds on top of the L2ToL2CrossDomainMessenger for both replay protection and domain /// binding. 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; @@ -39,14 +67,14 @@ contract SuperchainERC20Bridge { external returns (bytes32 msgHash_) { - if (_to == address(0)) revert ISuperchainERC20Bridge.ZeroAddress(); + if (_to == address(0)) revert ZeroAddress(); ISuperchainERC20(_token).__crosschainBurn(msg.sender, _amount); bytes memory message = abi.encodeCall(this.relayERC20, (_token, msg.sender, _to, _amount)); msgHash_ = IL2ToL2CrossDomainMessenger(MESSENGER).sendMessage(_chainId, address(this), message); - emit ISuperchainERC20Bridge.SendERC20(_token, msg.sender, _to, _amount, _chainId); + emit SendERC20(_token, msg.sender, _to, _amount, _chainId); } /// @notice Relays tokens received from another chain. @@ -56,16 +84,16 @@ contract SuperchainERC20Bridge { /// @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 ISuperchainERC20Bridge.CallerNotL2ToL2CrossDomainMessenger(); + if (msg.sender != MESSENGER) revert CallerNotL2ToL2CrossDomainMessenger(); if (IL2ToL2CrossDomainMessenger(MESSENGER).crossDomainMessageSender() != address(this)) { - revert ISuperchainERC20Bridge.InvalidCrossDomainSender(); + revert InvalidCrossDomainSender(); } uint256 source = IL2ToL2CrossDomainMessenger(MESSENGER).crossDomainMessageSource(); ISuperchainERC20(_token).__crosschainMint(_to, _amount); - emit ISuperchainERC20Bridge.RelayERC20(_token, _from, _to, _amount, source); + emit RelayERC20(_token, _from, _to, _amount, source); } } diff --git a/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol b/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol index cfe822e84f96..f59ffa069a52 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol @@ -7,33 +7,17 @@ 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; diff --git a/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20Factory.sol b/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20Factory.sol index f7d8872bd29e..d501bc51b28d 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20Factory.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20Factory.sol @@ -7,20 +7,10 @@ import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title IOptimismSuperchainERC20Factory /// @notice Interface for OptimismSuperchainERC20Factory. interface IOptimismSuperchainERC20Factory is IOptimismERC20Factory, 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. - /// @param deployer Address of the account that deployed the token. event OptimismSuperchainERC20Created( address indexed superchainToken, address indexed remoteToken, address deployer ); - /// @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. function deploy( address _remoteToken, string memory _name, diff --git a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol index 0b9e998c8037..c10b32eaa5af 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol @@ -9,7 +9,6 @@ import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title ISuperchainERC20 /// @notice This interface is available on the SuperchainERC20 contract. interface ISuperchainERC20 is ICrosschainERC20, IERC20Solady, ISemver { - /// @notice Thrown when attempting to mint or burn tokens and the function caller is not the SuperchainERC20Bridge. error OnlySuperchainERC20Bridge(); function __constructor__() external; diff --git a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20Bridge.sol b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20Bridge.sol index 2ea9ccdb6fdc..e4c7cc127598 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20Bridge.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20Bridge.sol @@ -6,42 +6,16 @@ import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title ISuperchainERC20Bridge /// @notice Interface for the SuperchainERC20Bridge contract. interface ISuperchainERC20Bridge is ISemver { - /// @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 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, @@ -51,12 +25,6 @@ interface ISuperchainERC20Bridge is ISemver { external returns (bytes32 msgHash_); - /// @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; function __constructor__() external; From c85ac1b33c80314b34b44b0425341a23b5da3520 Mon Sep 17 00:00:00 2001 From: agusduha Date: Fri, 4 Oct 2024 16:47:06 -0300 Subject: [PATCH 3/3] fix: make superchainERC20 inherits from crosschainERC20 --- packages/contracts-bedrock/semver-lock.json | 2 +- packages/contracts-bedrock/src/L2/SuperchainERC20.sol | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index dec8e09fc92d..a9031d13d060 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -133,7 +133,7 @@ }, "src/L2/SuperchainERC20.sol": { "initCodeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "sourceCodeHash": "0x7b7f564d35ad85059dbfb6b0b2b012d0e323bc5dbe1edee5f76f9dece4e1fe2e" + "sourceCodeHash": "0x4d251314bae2904986d3df791e916fc619bc65d09ccd80bc2032cfdd12b8c0a3" }, "src/L2/SuperchainERC20Bridge.sol": { "initCodeHash": "0xfeba60d8e17a0c62cc56c7319da323e154ccc6c379e7b72c48c9d0ce1e5b9474", diff --git a/packages/contracts-bedrock/src/L2/SuperchainERC20.sol b/packages/contracts-bedrock/src/L2/SuperchainERC20.sol index b4689e3a6380..e2fb81bdc084 100644 --- a/packages/contracts-bedrock/src/L2/SuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/SuperchainERC20.sol @@ -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, 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(); @@ -32,7 +32,7 @@ abstract contract SuperchainERC20 is ERC20, ISemver { function __crosschainMint(address _to, uint256 _amount) external virtual onlySuperchainERC20Bridge { _mint(_to, _amount); - emit ICrosschainERC20.CrosschainMinted(_to, _amount); + emit CrosschainMinted(_to, _amount); } /// @notice Allows the SuperchainERC20Bridge to burn tokens. @@ -41,6 +41,6 @@ abstract contract SuperchainERC20 is ERC20, ISemver { function __crosschainBurn(address _from, uint256 _amount) external virtual onlySuperchainERC20Bridge { _burn(_from, _amount); - emit ICrosschainERC20.CrosschainBurnt(_from, _amount); + emit CrosschainBurnt(_from, _amount); } }