@@ -122,6 +122,65 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran
122122 emit L1CounterpartAddressSet (_l1Counterpart);
123123 }
124124
125+ /**
126+ * @notice Burns L2 tokens and initiates a transfer to L1.
127+ * The tokens will be received on L1 only after the wait period (7 days) is over,
128+ * and will require an Outbox.executeTransaction to finalize.
129+ * @dev no additional callhook data is allowed
130+ * @param _l1Token L1 Address of GRT (needed for compatibility with Arbitrum Gateway Router)
131+ * @param _to Recipient address on L1
132+ * @param _amount Amount of tokens to burn
133+ * @param _data Contains sender and additional data to send to L1
134+ * @return ID of the withdraw tx
135+ */
136+ function outboundTransfer (
137+ address _l1Token ,
138+ address _to ,
139+ uint256 _amount ,
140+ bytes calldata _data
141+ ) external returns (bytes memory ) {
142+ return outboundTransfer (_l1Token, _to, _amount, 0 , 0 , _data);
143+ }
144+
145+ /**
146+ * @notice Receives token amount from L1 and mints the equivalent tokens to the receiving address
147+ * @dev Only accepts transactions from the L1 GRT Gateway.
148+ * The function is payable for ITokenGateway compatibility, but msg.value must be zero.
149+ * Note that allowlisted senders (some protocol contracts) can include additional calldata
150+ * for a callhook to be executed on the L2 side when the tokens are received. In this case, the L2 transaction
151+ * can revert if the callhook reverts, potentially locking the tokens on the bridge if the callhook
152+ * never succeeds. This requires extra care when adding contracts to the allowlist, but is necessary to ensure that
153+ * the tickets can be retried in the case of a temporary failure, and to ensure the atomicity of callhooks
154+ * with token transfers.
155+ * @param _l1Token L1 Address of GRT
156+ * @param _from Address of the sender on L1
157+ * @param _to Recipient address on L2
158+ * @param _amount Amount of tokens transferred
159+ * @param _data Extra callhook data, only used when the sender is allowlisted
160+ */
161+ function finalizeInboundTransfer (
162+ address _l1Token ,
163+ address _from ,
164+ address _to ,
165+ uint256 _amount ,
166+ bytes calldata _data
167+ ) external payable override nonReentrant notPaused onlyL1Counterpart {
168+ require (_l1Token == l1GRT, "TOKEN_NOT_GRT " );
169+ require (msg .value == 0 , "INVALID_NONZERO_VALUE " );
170+
171+ L2GraphToken (calculateL2TokenAddress (l1GRT)).bridgeMint (_to, _amount);
172+
173+ if (_data.length > 0 ) {
174+ bytes memory callhookData;
175+ {
176+ (, callhookData) = abi.decode (_data, (bytes , bytes ));
177+ }
178+ ICallhookReceiver (_to).onTokenTransfer (_from, _amount, callhookData);
179+ }
180+
181+ emit DepositFinalized (_l1Token, _from, _to, _amount);
182+ }
183+
125184 /**
126185 * @notice Burns L2 tokens and initiates a transfer to L1.
127186 * The tokens will be available on L1 only after the wait period (7 days) is over,
@@ -151,7 +210,7 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran
151210
152211 OutboundCalldata memory outboundCalldata;
153212
154- (outboundCalldata.from, outboundCalldata.extraData) = parseOutboundData (_data);
213+ (outboundCalldata.from, outboundCalldata.extraData) = _parseOutboundData (_data);
155214 require (outboundCalldata.extraData.length == 0 , "CALL_HOOK_DATA_NOT_ALLOWED " );
156215
157216 // from needs to approve this contract to burn the amount first
@@ -176,26 +235,6 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran
176235 return abi.encode (id);
177236 }
178237
179- /**
180- * @notice Burns L2 tokens and initiates a transfer to L1.
181- * The tokens will be received on L1 only after the wait period (7 days) is over,
182- * and will require an Outbox.executeTransaction to finalize.
183- * @dev no additional callhook data is allowed
184- * @param _l1Token L1 Address of GRT (needed for compatibility with Arbitrum Gateway Router)
185- * @param _to Recipient address on L1
186- * @param _amount Amount of tokens to burn
187- * @param _data Contains sender and additional data to send to L1
188- * @return ID of the withdraw tx
189- */
190- function outboundTransfer (
191- address _l1Token ,
192- address _to ,
193- uint256 _amount ,
194- bytes calldata _data
195- ) external returns (bytes memory ) {
196- return outboundTransfer (_l1Token, _to, _amount, 0 , 0 , _data);
197- }
198-
199238 /**
200239 * @notice Calculate the L2 address of a bridged token
201240 * @dev In our case, this would only work for GRT.
@@ -209,45 +248,6 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran
209248 return address (graphToken ());
210249 }
211250
212- /**
213- * @notice Receives token amount from L1 and mints the equivalent tokens to the receiving address
214- * @dev Only accepts transactions from the L1 GRT Gateway.
215- * The function is payable for ITokenGateway compatibility, but msg.value must be zero.
216- * Note that allowlisted senders (some protocol contracts) can include additional calldata
217- * for a callhook to be executed on the L2 side when the tokens are received. In this case, the L2 transaction
218- * can revert if the callhook reverts, potentially locking the tokens on the bridge if the callhook
219- * never succeeds. This requires extra care when adding contracts to the allowlist, but is necessary to ensure that
220- * the tickets can be retried in the case of a temporary failure, and to ensure the atomicity of callhooks
221- * with token transfers.
222- * @param _l1Token L1 Address of GRT
223- * @param _from Address of the sender on L1
224- * @param _to Recipient address on L2
225- * @param _amount Amount of tokens transferred
226- * @param _data Extra callhook data, only used when the sender is allowlisted
227- */
228- function finalizeInboundTransfer (
229- address _l1Token ,
230- address _from ,
231- address _to ,
232- uint256 _amount ,
233- bytes calldata _data
234- ) external payable override nonReentrant notPaused onlyL1Counterpart {
235- require (_l1Token == l1GRT, "TOKEN_NOT_GRT " );
236- require (msg .value == 0 , "INVALID_NONZERO_VALUE " );
237-
238- L2GraphToken (calculateL2TokenAddress (l1GRT)).bridgeMint (_to, _amount);
239-
240- if (_data.length > 0 ) {
241- bytes memory callhookData;
242- {
243- (, callhookData) = abi.decode (_data, (bytes , bytes ));
244- }
245- ICallhookReceiver (_to).onTokenTransfer (_from, _amount, callhookData);
246- }
247-
248- emit DepositFinalized (_l1Token, _from, _to, _amount);
249- }
250-
251251 /**
252252 * @notice Creates calldata required to send tx to L1
253253 * @dev encodes the target function with its params which
@@ -277,14 +277,24 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran
277277 );
278278 }
279279
280+ /**
281+ * @dev Runs state validation before unpausing, reverts if
282+ * something is not set properly
283+ */
284+ function _checksBeforeUnpause () internal view override {
285+ require (l2Router != address (0 ), "ROUTER_NOT_SET " );
286+ require (l1Counterpart != address (0 ), "L1_COUNTERPART_NOT_SET " );
287+ require (l1GRT != address (0 ), "L1GRT_NOT_SET " );
288+ }
289+
280290 /**
281291 * @notice Decodes calldata required for migration of tokens
282292 * @dev extraData can be left empty
283293 * @param _data Encoded callhook data
284294 * @return Sender of the tx
285295 * @return Any other data sent to L1
286296 */
287- function parseOutboundData (bytes calldata _data ) private view returns (address , bytes memory ) {
297+ function _parseOutboundData (bytes calldata _data ) private view returns (address , bytes memory ) {
288298 address from;
289299 bytes memory extraData;
290300 if (msg .sender == l2Router) {
@@ -295,14 +305,4 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran
295305 }
296306 return (from, extraData);
297307 }
298-
299- /**
300- * @dev Runs state validation before unpausing, reverts if
301- * something is not set properly
302- */
303- function _checksBeforeUnpause () internal view override {
304- require (l2Router != address (0 ), "ROUTER_NOT_SET " );
305- require (l1Counterpart != address (0 ), "L1_COUNTERPART_NOT_SET " );
306- require (l1GRT != address (0 ), "L1GRT_NOT_SET " );
307- }
308308}
0 commit comments