-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathL1WETHGateway.sol
153 lines (129 loc) · 4.9 KB
/
L1WETHGateway.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
import {IWETH} from "../../interfaces/IWETH.sol";
import {IL2ERC20Gateway} from "../../L2/gateways/IL2ERC20Gateway.sol";
import {IL1ScrollMessenger} from "../IL1ScrollMessenger.sol";
import {IL1ERC20Gateway} from "./IL1ERC20Gateway.sol";
import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
import {L1ERC20Gateway} from "./L1ERC20Gateway.sol";
/// @title L1WETHGateway
/// @notice The `L1WETHGateway` contract is used to deposit `WETH` token on layer 1 and
/// finalize withdraw `WETH` from layer 2.
/// @dev The deposited WETH tokens are not held in the gateway. It will first be unwrapped
/// as Ether and then the Ether will be sent to the `L1ScrollMessenger` contract.
/// On finalizing withdraw, the Ether will be transferred from `L1ScrollMessenger`, then
/// wrapped as WETH and finally transfer to recipient.
contract L1WETHGateway is L1ERC20Gateway {
/*************
* Constants *
*************/
/// @notice The address of L2 WETH address.
address public immutable l2WETH;
/// @notice The address of L1 WETH address.
// solhint-disable-next-line var-name-mixedcase
address public immutable WETH;
/***************
* Constructor *
***************/
/// @notice Constructor for `L1WETHGateway` implementation contract.
///
/// @param _WETH The address of WETH in L1.
/// @param _l2WETH The address of WETH in L2.
/// @param _counterpart The address of `L2WETHGateway` contract in L2.
/// @param _router The address of `L1GatewayRouter` contract in L1.
/// @param _messenger The address of `L1ScrollMessenger` contract in L1.
constructor(
address _WETH,
address _l2WETH,
address _counterpart,
address _router,
address _messenger
) ScrollGatewayBase(_counterpart, _router, _messenger) {
if (_WETH == address(0) || _l2WETH == address(0) || _router == address(0)) {
revert ErrorZeroAddress();
}
_disableInitializers();
WETH = _WETH;
l2WETH = _l2WETH;
}
/// @notice Initialize the storage of L1WETHGateway.
///
/// @dev The parameters `_counterpart`, `_router` and `_messenger` are no longer used.
///
/// @param _counterpart The address of L2ETHGateway in L2.
/// @param _router The address of L1GatewayRouter in L1.
/// @param _messenger The address of L1ScrollMessenger in L1.
function initialize(
address _counterpart,
address _router,
address _messenger
) external initializer {
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
}
receive() external payable {
require(_msgSender() == WETH, "only WETH");
}
/*************************
* Public View Functions *
*************************/
/// @inheritdoc IL1ERC20Gateway
function getL2ERC20Address(address) public view override returns (address) {
return l2WETH;
}
/**********************
* Internal Functions *
**********************/
/// @inheritdoc L1ERC20Gateway
function _beforeFinalizeWithdrawERC20(
address _l1Token,
address _l2Token,
address,
address,
uint256 _amount,
bytes calldata
) internal virtual override {
require(_l1Token == WETH, "l1 token not WETH");
require(_l2Token == l2WETH, "l2 token not WETH");
require(_amount == msg.value, "msg.value mismatch");
IWETH(_l1Token).deposit{value: _amount}();
}
/// @inheritdoc L1ERC20Gateway
function _beforeDropMessage(
address _token,
address,
uint256 _amount
) internal virtual override {
require(_token == WETH, "token not WETH");
require(_amount == msg.value, "msg.value mismatch");
IWETH(_token).deposit{value: _amount}();
}
/// @inheritdoc L1ERC20Gateway
function _deposit(
address _token,
address _to,
uint256 _amount,
bytes memory _data,
uint256 _gasLimit
) internal virtual override nonReentrant {
require(_amount > 0, "deposit zero amount");
require(_token == WETH, "only WETH is allowed");
// 1. Transfer token into this contract.
address _from;
(_from, _amount, _data) = _transferERC20In(_token, _amount, _data);
IWETH(_token).withdraw(_amount);
// 2. Generate message passed to L2WETHGateway.
bytes memory _message = abi.encodeCall(
IL2ERC20Gateway.finalizeDepositERC20,
(_token, l2WETH, _from, _to, _amount, _data)
);
// 3. Send message to L1ScrollMessenger.
IL1ScrollMessenger(messenger).sendMessage{value: _amount + msg.value}(
counterpart,
_amount,
_message,
_gasLimit,
_from
);
emit DepositERC20(_token, l2WETH, _from, _to, _amount, _data);
}
}