-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: SuperchainWETHWrapper contract
- Loading branch information
1 parent
e50c7c3
commit dc865d8
Showing
18 changed files
with
179 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.15; | ||
|
||
import {Unauthorized} from "@contracts-bedrock/libraries/errors/CommonErrors.sol"; | ||
import {Predeploys} from "@contracts-bedrock/libraries/Predeploys.sol"; | ||
import {SafeCall} from "@contracts-bedrock//libraries/SafeCall.sol"; | ||
import {IL2ToL2CrossDomainMessenger} from "@contracts-bedrock/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; | ||
import {ISuperchainERC20Extensions} from "@contracts-bedrock/L2/interfaces/ISuperchainERC20.sol"; | ||
import {IWETH} from "@contracts-bedrock/universal/interfaces/IWETH.sol"; | ||
|
||
interface IL2ToL2CrossDomainMessengerMissing { | ||
function successfulMessages(bytes32 _msgHash) external view returns (bool); | ||
function messageNonce() external view returns (uint256); | ||
} | ||
|
||
|
||
/** | ||
* @notice Thrown when the relay of SuperchainWETH has not succeeded. | ||
* @dev This error is triggered if the SuperchainWETH relay through the L2ToL2CrossDomainMessenger | ||
* has not completed successfully successful. | ||
*/ | ||
error RelaySuperchainWETHNotSuccessful(); | ||
|
||
/** | ||
* @title SuperchainETHWrapper | ||
* @notice This contract facilitates sending ETH across chains within the Superchain by wrapping ETH into SuperchainWETH, | ||
* relaying the wrapped asset to another chain, and then unwrapping it back to ETH on the destination chain. | ||
* @dev The contract integrates with the SuperchainWETH contract for wrapping and unwrapping ETH, and uses the L2ToL2CrossDomainMessenger | ||
* for relaying the wrapped ETH between chains. | ||
*/ | ||
contract SuperchainETHWrapper { | ||
/** | ||
* @dev Emitted when ETH is received by the contract. | ||
* @param from The address that sent ETH. | ||
* @param value The amount of ETH received. | ||
*/ | ||
event LogReceived(address from, uint256 value); | ||
|
||
// Fallback function to receive ETH | ||
receive() external payable { | ||
emit LogReceived(msg.sender, msg.value); | ||
} | ||
|
||
/** | ||
* @notice Unwraps SuperchainWETH into native ETH and sends it to a specified destination address. | ||
* @dev This function is called after receiving a message from another chain. It checks the message relay status, unwraps WETH to ETH, | ||
* and calls the destination address with the unwrapped ETH and the provided calldata. | ||
* @param _relayERC20MsgHash The hash of the relayed ERC20 message. | ||
* @param _dst The destination address on the receiving chain. | ||
* @param _wad The amount of SuperchainWETH to unwrap to ETH. | ||
* @param _calldata Data to be executed on the destination address. | ||
*/ | ||
function unwrapAndCall(bytes32 _relayERC20MsgHash, address _dst, uint256 _wad, bytes memory _calldata) external { | ||
// Receive message from other chain. | ||
IL2ToL2CrossDomainMessenger messenger = IL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); | ||
if (msg.sender != address(messenger)) revert Unauthorized(); | ||
if (messenger.crossDomainMessageSender() != address(this)) revert Unauthorized(); | ||
|
||
if ( | ||
IL2ToL2CrossDomainMessengerMissing(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER).successfulMessages( | ||
_relayERC20MsgHash | ||
) == false | ||
) { | ||
revert RelaySuperchainWETHNotSuccessful(); | ||
} | ||
|
||
IWETH(Predeploys.SUPERCHAIN_WETH).withdraw(_wad); | ||
SafeCall.call(_dst, _wad, _calldata); | ||
} | ||
|
||
/** | ||
* @notice Wraps ETH into SuperchainWETH and sends it to another chain. | ||
* @dev This function wraps the sent ETH into SuperchainWETH, computes the relay message hash, and relays the message to the destination chain. | ||
* @param _dst The destination address on the receiving chain. | ||
* @param _chainId The ID of the destination chain. | ||
* @param _calldata Data to be executed on the destination address. | ||
*/ | ||
function sendETH(address _dst, uint256 _chainId, bytes memory _calldata) public payable { | ||
IWETH(Predeploys.SUPERCHAIN_WETH).deposit{value: msg.value}(); | ||
|
||
bytes32 relayERC20MessageHash = keccak256( | ||
abi.encode( | ||
_chainId, | ||
block.chainid, | ||
IL2ToL2CrossDomainMessengerMissing(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER).messageNonce(), | ||
Predeploys.SUPERCHAIN_WETH, | ||
Predeploys.SUPERCHAIN_WETH, | ||
abi.encodeCall( | ||
ISuperchainERC20Extensions(Predeploys.SUPERCHAIN_WETH).relayERC20, | ||
(address(this), address(this), msg.value) | ||
) | ||
) | ||
); | ||
ISuperchainERC20Extensions(Predeploys.SUPERCHAIN_WETH).sendERC20(address(this), msg.value, _chainId); | ||
IL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER).sendMessage({ | ||
_destination: _chainId, | ||
_target: address(this), | ||
_message: abi.encodeCall(this.unwrapAndCall, (relayERC20MessageHash, _dst, msg.value, _calldata)) | ||
}); | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
genesis/generated/l2-allocs-with-periphery/901-l2-allocs-with-periphery.json
Large diffs are not rendered by default.
Oops, something went wrong.
2 changes: 1 addition & 1 deletion
2
genesis/generated/l2-allocs-with-periphery/902-l2-allocs-with-periphery.json
Large diffs are not rendered by default.
Oops, something went wrong.
2 changes: 1 addition & 1 deletion
2
genesis/generated/l2-allocs-with-periphery/903-l2-allocs-with-periphery.json
Large diffs are not rendered by default.
Oops, something went wrong.
2 changes: 1 addition & 1 deletion
2
genesis/generated/l2-allocs-with-periphery/904-l2-allocs-with-periphery.json
Large diffs are not rendered by default.
Oops, something went wrong.
2 changes: 1 addition & 1 deletion
2
genesis/generated/l2-allocs-with-periphery/905-l2-allocs-with-periphery.json
Large diffs are not rendered by default.
Oops, something went wrong.
Oops, something went wrong.