github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/src/L1/L1StandardBridge.sol (about) 1 // SPDX-License-Identifier: MIT 2 pragma solidity 0.8.15; 3 4 import { Predeploys } from "src/libraries/Predeploys.sol"; 5 import { StandardBridge } from "src/universal/StandardBridge.sol"; 6 import { ISemver } from "src/universal/ISemver.sol"; 7 import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; 8 import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; 9 import { Constants } from "src/libraries/Constants.sol"; 10 11 /// @custom:proxied 12 /// @title L1StandardBridge 13 /// @notice The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and 14 /// L2. In the case that an ERC20 token is native to L1, it will be escrowed within this 15 /// contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was 16 /// stored within this contract. After Bedrock, ETH is instead stored inside the 17 /// OptimismPortal contract. 18 /// NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples 19 /// of some token types that may not be properly supported by this contract include, but are 20 /// not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists. 21 contract L1StandardBridge is StandardBridge, ISemver { 22 /// @custom:legacy 23 /// @notice Emitted whenever a deposit of ETH from L1 into L2 is initiated. 24 /// @param from Address of the depositor. 25 /// @param to Address of the recipient on L2. 26 /// @param amount Amount of ETH deposited. 27 /// @param extraData Extra data attached to the deposit. 28 event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes extraData); 29 30 /// @custom:legacy 31 /// @notice Emitted whenever a withdrawal of ETH from L2 to L1 is finalized. 32 /// @param from Address of the withdrawer. 33 /// @param to Address of the recipient on L1. 34 /// @param amount Amount of ETH withdrawn. 35 /// @param extraData Extra data attached to the withdrawal. 36 event ETHWithdrawalFinalized(address indexed from, address indexed to, uint256 amount, bytes extraData); 37 38 /// @custom:legacy 39 /// @notice Emitted whenever an ERC20 deposit is initiated. 40 /// @param l1Token Address of the token on L1. 41 /// @param l2Token Address of the corresponding token on L2. 42 /// @param from Address of the depositor. 43 /// @param to Address of the recipient on L2. 44 /// @param amount Amount of the ERC20 deposited. 45 /// @param extraData Extra data attached to the deposit. 46 event ERC20DepositInitiated( 47 address indexed l1Token, 48 address indexed l2Token, 49 address indexed from, 50 address to, 51 uint256 amount, 52 bytes extraData 53 ); 54 55 /// @custom:legacy 56 /// @notice Emitted whenever an ERC20 withdrawal is finalized. 57 /// @param l1Token Address of the token on L1. 58 /// @param l2Token Address of the corresponding token on L2. 59 /// @param from Address of the withdrawer. 60 /// @param to Address of the recipient on L1. 61 /// @param amount Amount of the ERC20 withdrawn. 62 /// @param extraData Extra data attached to the withdrawal. 63 event ERC20WithdrawalFinalized( 64 address indexed l1Token, 65 address indexed l2Token, 66 address indexed from, 67 address to, 68 uint256 amount, 69 bytes extraData 70 ); 71 72 /// @notice Semantic version. 73 /// @custom:semver 2.1.0 74 string public constant version = "2.1.0"; 75 76 /// @notice Address of the SuperchainConfig contract. 77 SuperchainConfig public superchainConfig; 78 79 /// @notice Constructs the L1StandardBridge contract. 80 constructor() StandardBridge() { 81 initialize({ _messenger: CrossDomainMessenger(address(0)), _superchainConfig: SuperchainConfig(address(0)) }); 82 } 83 84 /// @notice Initializer. 85 /// @param _messenger Contract for the CrossDomainMessenger on this network. 86 /// @param _superchainConfig Contract for the SuperchainConfig on this network. 87 function initialize(CrossDomainMessenger _messenger, SuperchainConfig _superchainConfig) public initializer { 88 superchainConfig = _superchainConfig; 89 __StandardBridge_init({ 90 _messenger: _messenger, 91 _otherBridge: StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)) 92 }); 93 } 94 95 /// @inheritdoc StandardBridge 96 function paused() public view override returns (bool) { 97 return superchainConfig.paused(); 98 } 99 100 /// @notice Allows EOAs to bridge ETH by sending directly to the bridge. 101 receive() external payable override onlyEOA { 102 _initiateETHDeposit(msg.sender, msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes("")); 103 } 104 105 /// @custom:legacy 106 /// @notice Deposits some amount of ETH into the sender's account on L2. 107 /// @param _minGasLimit Minimum gas limit for the deposit message on L2. 108 /// @param _extraData Optional data to forward to L2. 109 /// Data supplied here will not be used to execute any code on L2 and is 110 /// only emitted as extra data for the convenience of off-chain tooling. 111 function depositETH(uint32 _minGasLimit, bytes calldata _extraData) external payable onlyEOA { 112 _initiateETHDeposit(msg.sender, msg.sender, _minGasLimit, _extraData); 113 } 114 115 /// @custom:legacy 116 /// @notice Deposits some amount of ETH into a target account on L2. 117 /// Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will 118 /// be locked in the L2StandardBridge. ETH may be recoverable if the call can be 119 /// successfully replayed by increasing the amount of gas supplied to the call. If the 120 /// call will fail for any amount of gas, then the ETH will be locked permanently. 121 /// @param _to Address of the recipient on L2. 122 /// @param _minGasLimit Minimum gas limit for the deposit message on L2. 123 /// @param _extraData Optional data to forward to L2. 124 /// Data supplied here will not be used to execute any code on L2 and is 125 /// only emitted as extra data for the convenience of off-chain tooling. 126 function depositETHTo(address _to, uint32 _minGasLimit, bytes calldata _extraData) external payable { 127 _initiateETHDeposit(msg.sender, _to, _minGasLimit, _extraData); 128 } 129 130 /// @custom:legacy 131 /// @notice Deposits some amount of ERC20 tokens into the sender's account on L2. 132 /// @param _l1Token Address of the L1 token being deposited. 133 /// @param _l2Token Address of the corresponding token on L2. 134 /// @param _amount Amount of the ERC20 to deposit. 135 /// @param _minGasLimit Minimum gas limit for the deposit message on L2. 136 /// @param _extraData Optional data to forward to L2. 137 /// Data supplied here will not be used to execute any code on L2 and is 138 /// only emitted as extra data for the convenience of off-chain tooling. 139 function depositERC20( 140 address _l1Token, 141 address _l2Token, 142 uint256 _amount, 143 uint32 _minGasLimit, 144 bytes calldata _extraData 145 ) 146 external 147 virtual 148 onlyEOA 149 { 150 _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, msg.sender, _amount, _minGasLimit, _extraData); 151 } 152 153 /// @custom:legacy 154 /// @notice Deposits some amount of ERC20 tokens into a target account on L2. 155 /// @param _l1Token Address of the L1 token being deposited. 156 /// @param _l2Token Address of the corresponding token on L2. 157 /// @param _to Address of the recipient on L2. 158 /// @param _amount Amount of the ERC20 to deposit. 159 /// @param _minGasLimit Minimum gas limit for the deposit message on L2. 160 /// @param _extraData Optional data to forward to L2. 161 /// Data supplied here will not be used to execute any code on L2 and is 162 /// only emitted as extra data for the convenience of off-chain tooling. 163 function depositERC20To( 164 address _l1Token, 165 address _l2Token, 166 address _to, 167 uint256 _amount, 168 uint32 _minGasLimit, 169 bytes calldata _extraData 170 ) 171 external 172 virtual 173 { 174 _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, _to, _amount, _minGasLimit, _extraData); 175 } 176 177 /// @custom:legacy 178 /// @notice Finalizes a withdrawal of ETH from L2. 179 /// @param _from Address of the withdrawer on L2. 180 /// @param _to Address of the recipient on L1. 181 /// @param _amount Amount of ETH to withdraw. 182 /// @param _extraData Optional data forwarded from L2. 183 function finalizeETHWithdrawal( 184 address _from, 185 address _to, 186 uint256 _amount, 187 bytes calldata _extraData 188 ) 189 external 190 payable 191 { 192 finalizeBridgeETH(_from, _to, _amount, _extraData); 193 } 194 195 /// @custom:legacy 196 /// @notice Finalizes a withdrawal of ERC20 tokens from L2. 197 /// @param _l1Token Address of the token on L1. 198 /// @param _l2Token Address of the corresponding token on L2. 199 /// @param _from Address of the withdrawer on L2. 200 /// @param _to Address of the recipient on L1. 201 /// @param _amount Amount of the ERC20 to withdraw. 202 /// @param _extraData Optional data forwarded from L2. 203 function finalizeERC20Withdrawal( 204 address _l1Token, 205 address _l2Token, 206 address _from, 207 address _to, 208 uint256 _amount, 209 bytes calldata _extraData 210 ) 211 external 212 { 213 finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData); 214 } 215 216 /// @custom:legacy 217 /// @notice Retrieves the access of the corresponding L2 bridge contract. 218 /// @return Address of the corresponding L2 bridge contract. 219 function l2TokenBridge() external view returns (address) { 220 return address(otherBridge); 221 } 222 223 /// @notice Internal function for initiating an ETH deposit. 224 /// @param _from Address of the sender on L1. 225 /// @param _to Address of the recipient on L2. 226 /// @param _minGasLimit Minimum gas limit for the deposit message on L2. 227 /// @param _extraData Optional data to forward to L2. 228 function _initiateETHDeposit(address _from, address _to, uint32 _minGasLimit, bytes memory _extraData) internal { 229 _initiateBridgeETH(_from, _to, msg.value, _minGasLimit, _extraData); 230 } 231 232 /// @notice Internal function for initiating an ERC20 deposit. 233 /// @param _l1Token Address of the L1 token being deposited. 234 /// @param _l2Token Address of the corresponding token on L2. 235 /// @param _from Address of the sender on L1. 236 /// @param _to Address of the recipient on L2. 237 /// @param _amount Amount of the ERC20 to deposit. 238 /// @param _minGasLimit Minimum gas limit for the deposit message on L2. 239 /// @param _extraData Optional data to forward to L2. 240 function _initiateERC20Deposit( 241 address _l1Token, 242 address _l2Token, 243 address _from, 244 address _to, 245 uint256 _amount, 246 uint32 _minGasLimit, 247 bytes memory _extraData 248 ) 249 internal 250 { 251 _initiateBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _minGasLimit, _extraData); 252 } 253 254 /// @inheritdoc StandardBridge 255 /// @notice Emits the legacy ETHDepositInitiated event followed by the ETHBridgeInitiated event. 256 /// This is necessary for backwards compatibility with the legacy bridge. 257 function _emitETHBridgeInitiated( 258 address _from, 259 address _to, 260 uint256 _amount, 261 bytes memory _extraData 262 ) 263 internal 264 override 265 { 266 emit ETHDepositInitiated(_from, _to, _amount, _extraData); 267 super._emitETHBridgeInitiated(_from, _to, _amount, _extraData); 268 } 269 270 /// @inheritdoc StandardBridge 271 /// @notice Emits the legacy ERC20DepositInitiated event followed by the ERC20BridgeInitiated 272 /// event. This is necessary for backwards compatibility with the legacy bridge. 273 function _emitETHBridgeFinalized( 274 address _from, 275 address _to, 276 uint256 _amount, 277 bytes memory _extraData 278 ) 279 internal 280 override 281 { 282 emit ETHWithdrawalFinalized(_from, _to, _amount, _extraData); 283 super._emitETHBridgeFinalized(_from, _to, _amount, _extraData); 284 } 285 286 /// @inheritdoc StandardBridge 287 /// @notice Emits the legacy ERC20WithdrawalFinalized event followed by the ERC20BridgeFinalized 288 /// event. This is necessary for backwards compatibility with the legacy bridge. 289 function _emitERC20BridgeInitiated( 290 address _localToken, 291 address _remoteToken, 292 address _from, 293 address _to, 294 uint256 _amount, 295 bytes memory _extraData 296 ) 297 internal 298 override 299 { 300 emit ERC20DepositInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData); 301 super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData); 302 } 303 304 /// @inheritdoc StandardBridge 305 /// @notice Emits the legacy ERC20WithdrawalFinalized event followed by the ERC20BridgeFinalized 306 /// event. This is necessary for backwards compatibility with the legacy bridge. 307 function _emitERC20BridgeFinalized( 308 address _localToken, 309 address _remoteToken, 310 address _from, 311 address _to, 312 uint256 _amount, 313 bytes memory _extraData 314 ) 315 internal 316 override 317 { 318 emit ERC20WithdrawalFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData); 319 super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData); 320 } 321 }