diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index 06bd7fd793b55..1cc71c0e4dc79 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -136,8 +136,8 @@ "sourceCodeHash": "0xb11ce94fd6165d8ca86eebafc7235e0875380d1a5d4e8b267ff0c6477083b21c" }, "src/L2/SuperchainWETH.sol": { - "initCodeHash": "0xe87f7012ac3050250d6cc6ca371ec09ec888b991603e531e3a97485c751d586b", - "sourceCodeHash": "0x720f4a6f4157558214c9943c49dc28702b7695b91ab1413a4f1c0ca216a97877" + "initCodeHash": "0xf30071df59d85e0e8a552845031aca8d6f0261762e1b4ea1b28ff30379eaa20e", + "sourceCodeHash": "0xdafbb056dbc6198ade27a0ee051e9cd1c8f03084beb50821dc93c82d710ef2b4" }, "src/L2/WETH.sol": { "initCodeHash": "0xfb253765520690623f177941c2cd9eba23e4c6d15063bccdd5e98081329d8956", diff --git a/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json b/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json index 08364ff80514a..b0b86ea7c8ceb 100644 --- a/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json +++ b/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json @@ -422,10 +422,5 @@ "inputs": [], "name": "NotCustomGasToken", "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/src/L2/SuperchainWETH.sol b/packages/contracts-bedrock/src/L2/SuperchainWETH.sol index 77262192a65ac..de6a51d7407cd 100644 --- a/packages/contracts-bedrock/src/L2/SuperchainWETH.sol +++ b/packages/contracts-bedrock/src/L2/SuperchainWETH.sol @@ -5,24 +5,23 @@ pragma solidity 0.8.15; import { WETH98 } from "src/universal/WETH98.sol"; // Libraries -import { Unauthorized, NotCustomGasToken } from "src/libraries/errors/CommonErrors.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; // Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; -import { ISuperchainERC20Extensions } from "src/L2/interfaces/ISuperchainERC20.sol"; import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; import { IETHLiquidity } from "src/L2/interfaces/IETHLiquidity.sol"; +import { ISuperchainWETH } from "src/L2/interfaces/ISuperchainWETH.sol"; /// @title SuperchainWETH /// @notice SuperchainWETH is a version of WETH that can be freely transfrered between chains /// within the superchain. SuperchainWETH can be converted into native ETH on chains that /// do not use a custom gas token. -contract SuperchainWETH is WETH98, ISuperchainERC20Extensions, ISemver { +contract SuperchainWETH is WETH98, ISuperchainWETH, ISemver { /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.6 - string public constant version = "1.0.0-beta.6"; + /// @custom:semver 1.0.0-beta.7 + string public constant version = "1.0.0-beta.7"; /// @inheritdoc WETH98 function deposit() public payable override { @@ -36,7 +35,7 @@ contract SuperchainWETH is WETH98, ISuperchainERC20Extensions, ISemver { super.withdraw(wad); } - /// @inheritdoc ISuperchainERC20Extensions + /// @inheritdoc ISuperchainWETH function sendERC20(address dst, uint256 wad, uint256 chainId) public { // Burn from user's balance. _burn(msg.sender, wad); @@ -57,7 +56,7 @@ contract SuperchainWETH is WETH98, ISuperchainERC20Extensions, ISemver { emit SendERC20(msg.sender, dst, wad, chainId); } - /// @inheritdoc ISuperchainERC20Extensions + /// @inheritdoc ISuperchainWETH function relayERC20(address from, address dst, uint256 wad) external { // Receive message from other chain. IL2ToL2CrossDomainMessenger messenger = IL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); diff --git a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol deleted file mode 100644 index 724f18ff8e048..0000000000000 --- a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @title ISuperchainERC20Errors -/// @notice Interface containing the errors added in the SuperchainERC20 implementation. -interface ISuperchainERC20Errors { - /// @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 `address(this)` - error InvalidCrossDomainSender(); - - /// @notice Thrown when attempting to perform an operation and the account is the zero address. - error ZeroAddress(); -} - -/// @title ISuperchainERC20Extensions -/// @notice Interface for the extensions to the ERC20 standard that are used by SuperchainERC20. -/// Exists in case developers are already importing the ERC20 interface separately and -/// importing the full SuperchainERC20 interface would cause conflicting imports. -interface ISuperchainERC20Extensions is ISuperchainERC20Errors { - /// @notice Emitted when tokens are sent from one chain to another. - /// @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 from, address indexed to, uint256 amount, uint256 destination); - - /// @notice Emitted whenever tokens are successfully relayed on this chain. - /// @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 from, address indexed to, uint256 amount, uint256 source); - - /// @notice Sends tokens to some target address on another chain. - /// @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 _to, uint256 _amount, uint256 _chainId) external; - - /// @notice Relays tokens received from another chain. - /// @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 _from, address _to, uint256 _amount) external; -} diff --git a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol index 7c755e11e8693..bccab456f5fd2 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol @@ -1,33 +1,44 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import { IWETH } from "src/universal/interfaces/IWETH.sol"; + interface ISuperchainWETH { + /// @notice Thrown when attempting a deposit or withdrawal and the chain uses a custom gas token. error NotCustomGasToken(); - error Unauthorized(); - event Approval(address indexed src, address indexed guy, uint256 wad); - event Deposit(address indexed dst, uint256 wad); + /// @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 `address(this)` + error InvalidCrossDomainSender(); + + /// @notice Emitted whenever tokens are successfully relayed on this chain. + /// @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 from, address indexed to, uint256 amount, uint256 source); + + /// @notice Emitted when tokens are sent from one chain to another. + /// @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 from, address indexed to, uint256 amount, uint256 destination); - event Transfer(address indexed src, address indexed dst, uint256 wad); - event Withdrawal(address indexed src, uint256 wad); - - fallback() external payable; - - receive() external payable; - - function allowance(address, address) external view returns (uint256); - function approve(address guy, uint256 wad) external returns (bool); - function balanceOf(address) external view returns (uint256); - function decimals() external view returns (uint8); - function deposit() external payable; - function name() external view returns (string memory); - function relayERC20(address from, address dst, uint256 wad) external; - function sendERC20(address dst, uint256 wad, uint256 chainId) external; - function symbol() external view returns (string memory); - function totalSupply() external view returns (uint256); - function transfer(address dst, uint256 wad) external returns (bool); - function transferFrom(address src, address dst, uint256 wad) external returns (bool); - function version() external view returns (string memory); - function withdraw(uint256 wad) external; + + /// @notice Sends tokens to some target address on another chain. + /// @param _dst Address to send tokens to. + /// @param _wad Amount of tokens to send. + /// @param _chainId Chain ID of the destination chain. + function sendERC20(address _dst, uint256 _wad, uint256 _chainId) external; + + /// @notice Relays tokens received from another chain. + /// @param _from Address of the msg.sender of sendERC20 on the source chain. + /// @param _dst Address to relay tokens to. + /// @param _wad Amount of tokens to relay. + function relayERC20(address _from, address _dst, uint256 _wad) external; } + +interface ISuperchainWETHERC20 is IWETH, ISuperchainWETH { } diff --git a/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol b/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol index cd68ef14eff05..c9c523201c6ae 100644 --- a/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol +++ b/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol @@ -11,7 +11,7 @@ import { NotCustomGasToken } from "src/libraries/errors/CommonErrors.sol"; // Interfaces import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; import { IETHLiquidity } from "src/L2/interfaces/IETHLiquidity.sol"; -import { ISuperchainERC20Errors } from "src/L2/interfaces/ISuperchainERC20.sol"; +import { ISuperchainWETH } from "src/L2/interfaces/ISuperchainWETH.sol"; /// @title SuperchainWETH_Test /// @notice Contract for testing the SuperchainWETH contract. @@ -321,7 +321,7 @@ contract SuperchainWETH_Test is CommonTest { // Nothing to arrange. // Act - vm.expectRevert(ISuperchainERC20Errors.CallerNotL2ToL2CrossDomainMessenger.selector); + vm.expectRevert(ISuperchainWETH.CallerNotL2ToL2CrossDomainMessenger.selector); vm.prank(alice); superchainWeth.relayERC20(_sender, bob, _amount); @@ -346,7 +346,7 @@ contract SuperchainWETH_Test is CommonTest { ); // Act - vm.expectRevert(ISuperchainERC20Errors.InvalidCrossDomainSender.selector); + vm.expectRevert(ISuperchainWETH.InvalidCrossDomainSender.selector); vm.prank(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); superchainWeth.relayERC20(_sender, bob, _amount); diff --git a/packages/contracts-bedrock/test/invariants/SuperchainWETH.t.sol b/packages/contracts-bedrock/test/invariants/SuperchainWETH.t.sol index 1e761b7ea1621..e9b8a3be828a7 100644 --- a/packages/contracts-bedrock/test/invariants/SuperchainWETH.t.sol +++ b/packages/contracts-bedrock/test/invariants/SuperchainWETH.t.sol @@ -10,7 +10,7 @@ import { CommonTest } from "test/setup/CommonTest.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; // Interfaces -import { ISuperchainWETH } from "src/L2/interfaces/ISuperchainWETH.sol"; +import { ISuperchainWETHERC20 } from "src/L2/interfaces/ISuperchainWETH.sol"; import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; /// @title SuperchainWETH_User @@ -29,7 +29,7 @@ contract SuperchainWETH_User is StdUtils { Vm internal vm; /// @notice The SuperchainWETH contract. - ISuperchainWETH internal weth; + ISuperchainWETHERC20 internal weth; /// @notice Mapping of sent messages. mapping(bytes32 => bool) internal sent; @@ -40,7 +40,7 @@ contract SuperchainWETH_User is StdUtils { /// @param _vm The Vm contract. /// @param _weth The SuperchainWETH contract. /// @param _balance The initial balance of the contract. - constructor(Vm _vm, ISuperchainWETH _weth, uint256 _balance) { + constructor(Vm _vm, ISuperchainWETHERC20 _weth, uint256 _balance) { vm = _vm; weth = _weth; vm.deal(address(this), _balance); diff --git a/packages/contracts-bedrock/test/setup/Setup.sol b/packages/contracts-bedrock/test/setup/Setup.sol index 14fe952d001a4..2af8b6d04e40c 100644 --- a/packages/contracts-bedrock/test/setup/Setup.sol +++ b/packages/contracts-bedrock/test/setup/Setup.sol @@ -44,7 +44,7 @@ import { ISequencerFeeVault } from "src/L2/interfaces/ISequencerFeeVault.sol"; import { IL1FeeVault } from "src/L2/interfaces/IL1FeeVault.sol"; import { IGasPriceOracle } from "src/L2/interfaces/IGasPriceOracle.sol"; import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; -import { ISuperchainWETH } from "src/L2/interfaces/ISuperchainWETH.sol"; +import { ISuperchainWETHERC20 } from "src/L2/interfaces/ISuperchainWETH.sol"; import { IETHLiquidity } from "src/L2/interfaces/IETHLiquidity.sol"; import { IWETH } from "src/universal/interfaces/IWETH.sol"; import { IGovernanceToken } from "src/governance/interfaces/IGovernanceToken.sol"; @@ -105,7 +105,7 @@ contract Setup { IGovernanceToken governanceToken = IGovernanceToken(Predeploys.GOVERNANCE_TOKEN); ILegacyMessagePasser legacyMessagePasser = ILegacyMessagePasser(Predeploys.LEGACY_MESSAGE_PASSER); IWETH weth = IWETH(payable(Predeploys.WETH)); - ISuperchainWETH superchainWeth = ISuperchainWETH(payable(Predeploys.SUPERCHAIN_WETH)); + ISuperchainWETHERC20 superchainWeth = ISuperchainWETHERC20(payable(Predeploys.SUPERCHAIN_WETH)); IETHLiquidity ethLiquidity = IETHLiquidity(Predeploys.ETH_LIQUIDITY); ISuperchainERC20Bridge superchainERC20Bridge = ISuperchainERC20Bridge(Predeploys.SUPERCHAIN_ERC20_BRIDGE); IOptimismSuperchainERC20Factory l2OptimismSuperchainERC20Factory =