-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: introduce SuperchainWETH and ETHLiquidity
Introduces the SuperchainWETH and ETHLiquidity contracts. More information about these contracts can be found in the OP Stack Specs repository.
- Loading branch information
1 parent
379973e
commit bf61875
Showing
12 changed files
with
526 additions
and
15 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,52 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.15; | ||
|
||
import { WETH98 } from "src/dispute/weth/WETH98.sol"; | ||
import { Predeploys } from "src/libraries/Predeploys.sol"; | ||
import { L1Block } from "src/L2/L1Block.sol"; | ||
import { SafeSend } from "src/universal/SafeSend.sol"; | ||
import { ISemver } from "src/universal/ISemver.sol"; | ||
|
||
import "src/libraries/errors/CommonErrors.sol"; | ||
|
||
/// @title ETHLiquidity | ||
/// @notice The ETHLiquidity contract allows other contracts to access ETH liquidity without | ||
/// needing to modify the EVM to generate new ETH. | ||
contract ETHLiquidity { | ||
/// @notice Emitted when an address burns ETH liquidity. | ||
event LiquidityBurned(address indexed caller, uint256 value); | ||
|
||
/// @notice Emitted when an address mints ETH liquidity. | ||
event LiquidityMinted(address indexed caller, uint256 value); | ||
|
||
/// @notice Semantic version. | ||
/// @custom:semver 1.0.0 | ||
string public constant version = "1.0.0"; | ||
|
||
/// @notice Throws if the caller is not authorized. | ||
modifier onlyAuthorized() { | ||
// Only the SuperchainWETH contract is authorized to call this contract for now. Other | ||
// contracts may be allowed to call this contract in the future so we're using a generic | ||
// name for the modifier. | ||
if (msg.sender != Predeploys.SUPERCHAIN_WETH) revert Unauthorized(); | ||
_; | ||
} | ||
|
||
/// @notice Throws this chain is using a custom gas token. | ||
modifier notCustomGasToken() { | ||
if (L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) revert NotCustomGasToken(); | ||
_; | ||
} | ||
|
||
/// @notice Allows an address to lock ETH liquidity into this contract. | ||
function burn() external payable onlyAuthorized notCustomGasToken { | ||
emit LiquidityBurned(msg.sender, msg.value); | ||
} | ||
|
||
/// @notice Allows an address to unlock ETH liquidity from this contract. | ||
/// @param _amount The amount of liquidity to unlock. | ||
function mint(uint256 _amount) external onlyAuthorized notCustomGasToken { | ||
new SafeSend{ value: _amount }(payable(msg.sender)); | ||
emit LiquidityMinted(msg.sender, _amount); | ||
} | ||
} |
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,93 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.15; | ||
|
||
import { WETH98 } from "src/dispute/weth/WETH98.sol"; | ||
import { Predeploys } from "src/libraries/Predeploys.sol"; | ||
import { L1Block } from "src/L2/L1Block.sol"; | ||
import { IL2ToL2CrossDomainMessenger } from "src/L2/IL2ToL2CrossDomainMessenger.sol"; | ||
import { ETHLiquidity } from "src/L2/ETHLiquidity.sol"; | ||
import { ISemver } from "src/universal/ISemver.sol"; | ||
|
||
import "src/libraries/errors/CommonErrors.sol"; | ||
|
||
/// @title SuperchainWETH | ||
/// @notice SuperchainWETH is a version of WETH that can be freely transfered 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, ISemver { | ||
/// @notice Semantic version. | ||
/// @custom:semver 1.0.0 | ||
string public constant version = "1.0.0"; | ||
|
||
/// @notice Throws this chain is using a custom gas token. | ||
modifier notCustomGasToken() { | ||
if (L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) revert OnlyCustomGasToken(); | ||
_; | ||
} | ||
|
||
/// @inheritdoc WETH98 | ||
function deposit() public payable override notCustomGasToken { | ||
super.deposit(); | ||
} | ||
|
||
/// @inheritdoc WETH98 | ||
function withdraw(uint256 wad) public override notCustomGasToken { | ||
super.withdraw(wad); | ||
} | ||
|
||
/// TODO: .inheritdoc ISuperchainERC20 | ||
function sendERC20(uint256 wad, uint256 chainId) external { | ||
sendERC20To(msg.sender, wad, chainId); | ||
} | ||
|
||
/// TODO: .inheritdoc ISuperchainERC20 | ||
function sendERC20To(address dst, uint256 wad, uint256 chainId) public { | ||
// Burn from user's balance. | ||
_burn(msg.sender, wad); | ||
|
||
// Burn to ETHLiquidity contract. | ||
if (!L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) { | ||
ETHLiquidity(Predeploys.ETH_LIQUIDITY).burn{ value: wad }(); | ||
} | ||
|
||
// Send message to other chain. | ||
IL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER).sendMessage({ | ||
_destination: chainId, | ||
_target: address(this), | ||
_message: abi.encodeCall(this.finalizeSendERC20, (dst, wad)) | ||
}); | ||
} | ||
|
||
/// TODO: .inheritdoc ISuperchainERC20 | ||
function finalizeSendERC20(address dst, uint256 wad) 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(); | ||
|
||
// Mint from ETHLiquidity contract. | ||
if (!L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) { | ||
ETHLiquidity(Predeploys.ETH_LIQUIDITY).mint(wad); | ||
} | ||
|
||
// Mint to user's balance. | ||
_mint(dst, wad); | ||
} | ||
|
||
/// @notice Mints WETH to an address. | ||
/// @param guy The address to mint WETH to. | ||
/// @param wad The amount of WETH to mint. | ||
function _mint(address guy, uint256 wad) internal { | ||
balanceOf[guy] += wad; | ||
emit Transfer(address(0), guy, wad); | ||
} | ||
|
||
/// @notice Burns WETH from an address. | ||
/// @param guy The address to burn WETH from. | ||
/// @param wad The amount of WETH to burn. | ||
function _burn(address guy, uint256 wad) internal { | ||
require(balanceOf[guy] >= wad); | ||
balanceOf[guy] -= wad; | ||
emit Transfer(guy, address(0), wad); | ||
} | ||
} |
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
14 changes: 14 additions & 0 deletions
14
packages/contracts-bedrock/src/libraries/errors/CommonErrors.sol
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,14 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
/// @notice Error for an unauthorized CALLER. | ||
error Unauthorized(); | ||
|
||
/// @notice Error for when a method is called that only works when using a custom gas token. | ||
error OnlyCustomGasToken(); | ||
|
||
/// @notice Error for when a method is called that only works when NOT using a custom gas token. | ||
error NotCustomGasToken(); | ||
|
||
/// @notice Error for when a transfer via call fails. | ||
error TransferFailed(); |
14 changes: 3 additions & 11 deletions
14
packages/contracts-bedrock/src/periphery/faucet/Faucet.sol
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,11 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.15; | ||
|
||
/// @title SafeSend | ||
/// @notice Sends ETH to a recipient account without triggering any code. | ||
contract SafeSend { | ||
/// @param _recipient Account to send ETH to. | ||
constructor(address payable _recipient) payable { | ||
selfdestruct(_recipient); | ||
} | ||
} |
Oops, something went wrong.