11// SPDX-License-Identifier: GPL-3.0-only
22pragma solidity ^ 0.8.0 ;
3-
4- import "./SpokePool.sol " ;
5- import "./interfaces/WETH9.sol " ;
6-
7- import "@eth-optimism/contracts/libraries/bridge/CrossDomainEnabled.sol " ;
83import "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol " ;
9- import "@eth-optimism/contracts/L2/messaging/IL2ERC20Bridge.sol " ;
4+
5+ import "./Ovm_SpokePool.sol " ;
106
117/**
12- * @notice OVM specific SpokePool. Uses OVM cross-domain-enabled logic to implement admin only access to functions .
8+ * @notice Optimism Spoke pool .
139 */
14- contract Optimism_SpokePool is CrossDomainEnabled , SpokePool {
15- // "l1Gas" parameter used in call to bridge tokens from this contract back to L1 via IL2ERC20Bridge. Currently
16- // unused by bridge but included for future compatibility.
17- uint32 public l1Gas = 5_000_000 ;
18-
19- // ETH is an ERC20 on OVM.
20- address public immutable l2Eth = address (Lib_PredeployAddresses.OVM_ETH);
21-
22- // Stores alternative token bridges to use for L2 tokens that don't go over the standard bridge. This is needed
23- // to support non-standard ERC20 tokens on Optimism, such as DIA and SNX which both use custom bridges.
24- mapping (address => address ) public tokenBridges;
25-
26- event OptimismTokensBridged (address indexed l2Token , address target , uint256 numberOfTokensBridged , uint256 l1Gas );
27- event SetL1Gas (uint32 indexed newL1Gas );
28- event SetL2TokenBridge (address indexed l2Token , address indexed tokenBridge );
29-
10+ contract Optimism_SpokePool is Ovm_SpokePool {
3011 /**
31- * @notice Construct the OVM SpokePool.
12+ * @notice Construct the OVM Optimism SpokePool.
3213 * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.
3314 * @param _hubPool Hub pool address to set. Can be changed by admin.
3415 * @param timerAddress Timer address to set.
@@ -38,120 +19,12 @@ contract Optimism_SpokePool is CrossDomainEnabled, SpokePool {
3819 address _hubPool ,
3920 address timerAddress
4021 )
41- CrossDomainEnabled (Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER)
42- SpokePool (_crossDomainAdmin, _hubPool, 0x4200000000000000000000000000000000000006 , timerAddress)
22+ Ovm_SpokePool (
23+ _crossDomainAdmin,
24+ _hubPool,
25+ Lib_PredeployAddresses.OVM_ETH,
26+ 0x4200000000000000000000000000000000000006 ,
27+ timerAddress
28+ )
4329 {}
44-
45- /*******************************************
46- * OPTIMISM-SPECIFIC ADMIN FUNCTIONS *
47- *******************************************/
48-
49- /**
50- * @notice Change L1 gas limit. Callable only by admin.
51- * @param newl1Gas New L1 gas limit to set.
52- */
53- function setL1GasLimit (uint32 newl1Gas ) public onlyAdmin nonReentrant {
54- l1Gas = newl1Gas;
55- emit SetL1Gas (newl1Gas);
56- }
57-
58- /**
59- * @notice Set bridge contract for L2 token used to withdraw back to L1.
60- * @dev If this mapping isn't set for an L2 token, then the standard bridge will be used to bridge this token.
61- * @param tokenBridge Address of token bridge
62- */
63- function setTokenBridge (address l2Token , address tokenBridge ) public onlyAdmin nonReentrant {
64- tokenBridges[l2Token] = tokenBridge;
65- emit SetL2TokenBridge (l2Token, tokenBridge);
66- }
67-
68- /**************************************
69- * DATA WORKER FUNCTIONS *
70- **************************************/
71-
72- /**
73- * @notice Wraps any ETH into WETH before executing base function. This is necessary because SpokePool receives
74- * ETH over the canonical token bridge instead of WETH.
75- * @inheritdoc SpokePool
76- */
77- function executeSlowRelayLeaf (
78- address depositor ,
79- address recipient ,
80- address destinationToken ,
81- uint256 totalRelayAmount ,
82- uint256 originChainId ,
83- uint64 realizedLpFeePct ,
84- uint64 relayerFeePct ,
85- uint32 depositId ,
86- uint32 rootBundleId ,
87- bytes32 [] memory proof
88- ) public override (SpokePool) nonReentrant {
89- if (destinationToken == address (wrappedNativeToken)) _depositEthToWeth ();
90-
91- _executeSlowRelayLeaf (
92- depositor,
93- recipient,
94- destinationToken,
95- totalRelayAmount,
96- originChainId,
97- chainId (),
98- realizedLpFeePct,
99- relayerFeePct,
100- depositId,
101- rootBundleId,
102- proof
103- );
104- }
105-
106- /**
107- * @notice Wraps any ETH into WETH before executing base function. This is necessary because SpokePool receives
108- * ETH over the canonical token bridge instead of WETH.
109- * @inheritdoc SpokePool
110- */
111- function executeRelayerRefundLeaf (
112- uint32 rootBundleId ,
113- SpokePoolInterface.RelayerRefundLeaf memory relayerRefundLeaf ,
114- bytes32 [] memory proof
115- ) public override (SpokePool) nonReentrant {
116- if (relayerRefundLeaf.l2TokenAddress == address (wrappedNativeToken)) _depositEthToWeth ();
117-
118- _executeRelayerRefundLeaf (rootBundleId, relayerRefundLeaf, proof);
119- }
120-
121- /**************************************
122- * INTERNAL FUNCTIONS *
123- **************************************/
124-
125- // Wrap any ETH owned by this contract so we can send expected L2 token to recipient. This is necessary because
126- // this SpokePool will receive ETH from the canonical token bridge instead of WETH. Its not sufficient to execute
127- // this logic inside a fallback method that executes when this contract receives ETH because ETH is an ERC20
128- // on the OVM.
129- function _depositEthToWeth () internal {
130- if (address (this ).balance > 0 ) wrappedNativeToken.deposit { value: address (this ).balance }();
131- }
132-
133- function _bridgeTokensToHubPool (RelayerRefundLeaf memory relayerRefundLeaf ) internal override {
134- // If the token being bridged is WETH then we need to first unwrap it to ETH and then send ETH over the
135- // canonical bridge. On Optimism, this is address 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000.
136- if (relayerRefundLeaf.l2TokenAddress == address (wrappedNativeToken)) {
137- WETH9 (relayerRefundLeaf.l2TokenAddress).withdraw (relayerRefundLeaf.amountToReturn); // Unwrap into ETH.
138- relayerRefundLeaf.l2TokenAddress = l2Eth; // Set the l2TokenAddress to ETH.
139- }
140- IL2ERC20Bridge (
141- tokenBridges[relayerRefundLeaf.l2TokenAddress] == address (0 )
142- ? Lib_PredeployAddresses.L2_STANDARD_BRIDGE
143- : tokenBridges[relayerRefundLeaf.l2TokenAddress]
144- ).withdrawTo (
145- relayerRefundLeaf.l2TokenAddress, // _l2Token. Address of the L2 token to bridge over.
146- hubPool, // _to. Withdraw, over the bridge, to the l1 pool contract.
147- relayerRefundLeaf.amountToReturn, // _amount.
148- l1Gas, // _l1Gas. Unused, but included for potential forward compatibility considerations
149- "" // _data. We don't need to send any data for the bridging action.
150- );
151-
152- emit OptimismTokensBridged (relayerRefundLeaf.l2TokenAddress, hubPool, relayerRefundLeaf.amountToReturn, l1Gas);
153- }
154-
155- // Apply OVM-specific transformation to cross domain admin address on L1.
156- function _requireAdminSender () internal override onlyFromCrossDomainAccount (crossDomainAdmin) {}
15730}
0 commit comments