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

feat: SuperchainWETH redesign #101

Merged
merged 31 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ae024a5
feat: add superchain erc20 bridge (#61)
agusduha Sep 25, 2024
2a22161
refactor: optimism superchain erc20 redesign (#62)
0xDiscotech Sep 26, 2024
6aaf905
test: add superchain erc20 bridge tests (#65)
agusduha Sep 27, 2024
11fda67
chore: update missing bridge on natspec (#69)
0xDiscotech Sep 27, 2024
7a69a7e
fix: remove superchain erc20 base (#70)
agusduha Sep 27, 2024
07c9c77
refactor: update isuperchainweth (#71)
0xDiscotech Sep 27, 2024
d9bdad1
feat: rename mint/burn and add SuperchainERC20 (#74)
agusduha Oct 1, 2024
2e507b2
fix: refactor zero check (#76)
agusduha Oct 2, 2024
7fcaf6c
Merge branch 'develop' into fix/redesign-merge-conflicts
agusduha Oct 2, 2024
619f23c
fix: pre pr
agusduha Oct 2, 2024
1981789
Merge pull request #77 from defi-wonderland/fix/redesign-merge-conflicts
agusduha Oct 2, 2024
ae019b8
fix: semver natspec check failure (#79)
agusduha Oct 3, 2024
a5aca61
feat: add crosschain erc20 interface (#80)
agusduha Oct 3, 2024
83757ea
fix: superchain bridge natspec (#83)
agusduha Oct 4, 2024
904a0ce
fix: superchain weth natspec (#84)
agusduha Oct 4, 2024
3ebb1d1
fix: stop inheriting superchain interfaces (#85)
agusduha Oct 4, 2024
1b4317e
fix: superchain bridge rename (#86)
agusduha Oct 7, 2024
10038c3
fix: fee vault compiler error (#87)
agusduha Oct 7, 2024
9f49b43
Merge branch 'develop' into fix/crosschain-merge-conflicts
agusduha Oct 8, 2024
ab1e074
fix: remove unused imports
agusduha Oct 8, 2024
a79bf4e
Merge pull request #88 from defi-wonderland/fix/crosschain-merge-conf…
agusduha Oct 8, 2024
af9694e
fix: refactor common errors (#90)
agusduha Oct 9, 2024
6c46f9b
fix: reuse unauthorized error (#92)
agusduha Oct 10, 2024
736adf3
Merge branch 'develop' into fix/superchain-erc20-factory-merge-conflicts
agusduha Oct 11, 2024
061b1ff
fix: superchain erc20 factory conflicts
agusduha Oct 11, 2024
97fb300
Merge pull request #93 from defi-wonderland/fix/superchain-erc20-fact…
agusduha Oct 11, 2024
71389b6
fix: rename crosschain functions (#94)
agusduha Oct 11, 2024
5dca40d
feat: superweth redesign
agusduha Oct 14, 2024
2eb051c
fix: pr fixes
agusduha Oct 15, 2024
29dd7b8
Merge branch 'develop' into feat/superweth-redesign
agusduha Oct 17, 2024
1be3791
fix: fixes post merge
agusduha Oct 17, 2024
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
4 changes: 2 additions & 2 deletions packages/contracts-bedrock/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@
"sourceCodeHash": "0xaf2458e48dcadcafa8940cde7368549eae2280eef91247600d864ddac20f5d82"
},
"src/L2/SuperchainWETH.sol": {
"initCodeHash": "0x50f6ea9bfe650fcf792e98e44b1bf66c036fd0e6d4b753da680253d7d8609816",
"sourceCodeHash": "0x82d03262decf52d5954d40bca8703f96a0f3ba7accf6c1d75292856c2f34cf8f"
"initCodeHash": "0x76a6baa0823ca75f32a94ba49592f07129e762f9459be305b95b12475d8a5fce",
"sourceCodeHash": "0xbb6196751e8d1f0c7281bd824f0cb024dda726d65701def59cc3cb6d2bcbe6b3"
},
"src/L2/WETH.sol": {
"initCodeHash": "0xfb253765520690623f177941c2cd9eba23e4c6d15063bccdd5e98081329d8956",
Expand Down
129 changes: 45 additions & 84 deletions packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,42 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_from",
"type": "address"
},
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "crosschainBurn",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "crosschainMint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
Expand Down Expand Up @@ -107,52 +143,6 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "dst",
"type": "address"
},
{
"internalType": "uint256",
"name": "wad",
"type": "uint256"
}
],
"name": "relayERC20",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "dst",
"type": "address"
},
{
"internalType": "uint256",
"name": "wad",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "chainId",
"type": "uint256"
}
],
"name": "sendERC20",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
Expand Down Expand Up @@ -289,28 +279,22 @@
{
"indexed": true,
"internalType": "address",
"name": "dst",
"name": "from",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "wad",
"name": "amount",
"type": "uint256"
}
],
"name": "Deposit",
"name": "CrosschainBurnt",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
Expand All @@ -322,15 +306,9 @@
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "source",
"type": "uint256"
}
],
"name": "RelayERC20",
"name": "CrosschainMinted",
"type": "event"
},
{
Expand All @@ -339,29 +317,17 @@
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"name": "dst",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "destination",
"name": "wad",
"type": "uint256"
}
],
"name": "SendERC20",
"name": "Deposit",
"type": "event"
},
{
Expand Down Expand Up @@ -410,17 +376,12 @@
},
{
"inputs": [],
"name": "CallerNotL2ToL2CrossDomainMessenger",
"type": "error"
},
{
"inputs": [],
"name": "InvalidCrossDomainSender",
"name": "NotCustomGasToken",
"type": "error"
},
{
"inputs": [],
"name": "NotCustomGasToken",
"name": "Unauthorized",
"type": "error"
}
]
95 changes: 43 additions & 52 deletions packages/contracts-bedrock/src/L2/SuperchainWETH.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,27 @@ 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 { IL1Block } from "src/L2/interfaces/IL1Block.sol";
import { IETHLiquidity } from "src/L2/interfaces/IETHLiquidity.sol";
import { ISuperchainWETH } from "src/L2/interfaces/ISuperchainWETH.sol";
import { ICrosschainERC20 } from "src/L2/interfaces/ICrosschainERC20.sol";
import { Unauthorized, NotCustomGasToken } from "src/libraries/errors/CommonErrors.sol";

/// @custom:proxied true
/// @custom:predeploy 0x4200000000000000000000000000000000000024
/// @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, ISuperchainWETH, ISemver {
contract SuperchainWETH is WETH98, ICrosschainERC20, ISemver {
/// @notice A modifier that only allows the SuperchainTokenBridge to call
modifier onlySuperchainTokenBridge() {
if (msg.sender != Predeploys.SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();
_;
}

/// @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 {
Expand All @@ -37,63 +43,48 @@ contract SuperchainWETH is WETH98, ISuperchainWETH, ISemver {
super.withdraw(wad);
}

/// @inheritdoc ISuperchainWETH
function sendERC20(address dst, uint256 wad, uint256 chainId) public {
// Burn from user's balance.
_burn(msg.sender, wad);

// Burn to ETHLiquidity contract.
if (!IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) {
IETHLiquidity(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.relayERC20, (msg.sender, 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);
}

// Emit event.
emit SendERC20(msg.sender, dst, wad, chainId);
/// @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);
}

/// @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);
if (msg.sender != address(messenger)) revert CallerNotL2ToL2CrossDomainMessenger();
if (messenger.crossDomainMessageSender() != address(this)) revert InvalidCrossDomainSender();
/// @notice Allows the SuperchainTokenBridge to mint tokens.
/// @param _to Address to mint tokens to.
/// @param _amount Amount of tokens to mint.
function crosschainMint(address _to, uint256 _amount) external onlySuperchainTokenBridge {
_mint(_to, _amount);

// Mint from ETHLiquidity contract.
if (!IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) {
IETHLiquidity(Predeploys.ETH_LIQUIDITY).mint(wad);
IETHLiquidity(Predeploys.ETH_LIQUIDITY).mint(_amount);
}

// Get source chain ID.
uint256 source = messenger.crossDomainMessageSource();

// Mint to user's balance.
_mint(dst, wad);

// Emit event.
emit RelayERC20(from, dst, wad, source);
emit CrosschainMinted(_to, _amount);
}

/// @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 Allows the SuperchainTokenBridge to burn tokens.
/// @param _from Address to burn tokens from.
/// @param _amount Amount of tokens to burn.
function crosschainBurn(address _from, uint256 _amount) external onlySuperchainTokenBridge {
_burn(_from, _amount);

/// @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);
// Burn to ETHLiquidity contract.
if (!IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) {
IETHLiquidity(Predeploys.ETH_LIQUIDITY).burn{ value: _amount }();
}

emit CrosschainBurnt(_from, _amount);
}
}
41 changes: 5 additions & 36 deletions packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,12 @@
pragma solidity ^0.8.0;

import { IWETH } from "src/universal/interfaces/IWETH.sol";
import { ICrosschainERC20 } from "src/L2/interfaces/ICrosschainERC20.sol";
import { ISemver } from "src/universal/interfaces/ISemver.sol";

interface ISuperchainWETH {
/// @notice Thrown when attempting a deposit or withdrawal and the chain uses a custom gas token.
interface ISuperchainWETH is IWETH, ICrosschainERC20, ISemver {
error Unauthorized();
error NotCustomGasToken();

/// @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);

/// @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;
function __constructor__() external;
}

interface ISuperchainWETHERC20 is IWETH, ISuperchainWETH { }
Loading