9
9
L2TemplateAddresses,
10
10
IERC20Inbox ,
11
11
IERC20 ,
12
+ ERC20 ,
12
13
SafeERC20
13
14
} from "./L1TokenBridgeRetryableSender.sol " ;
14
15
import {L1GatewayRouter} from "./gateway/L1GatewayRouter.sol " ;
@@ -216,7 +217,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
216
217
// deployment mappings should not be updated in case of resend
217
218
bool isResend = (inboxToL1Deployment[inbox].router != address (0 ));
218
219
219
- bool isUsingFeeToken = _getFeeToken (inbox) != address ( 0 );
220
+ address feeToken = _getFeeToken (inbox);
220
221
221
222
// store L2 addresses before deployments
222
223
L1DeploymentAddresses memory l1Deployment;
@@ -233,7 +234,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
233
234
l2Deployment.router = _getProxyAddress (OrbitSalts.L2_ROUTER, chainId);
234
235
l2Deployment.standardGateway = _getProxyAddress (OrbitSalts.L2_STANDARD_GATEWAY, chainId);
235
236
l2Deployment.customGateway = _getProxyAddress (OrbitSalts.L2_CUSTOM_GATEWAY, chainId);
236
- if (! isUsingFeeToken ) {
237
+ if (feeToken == address ( 0 ) ) {
237
238
l2Deployment.wethGateway = _getProxyAddress (OrbitSalts.L2_WETH_GATEWAY, chainId);
238
239
l2Deployment.weth = _getProxyAddress (OrbitSalts.L2_WETH, chainId);
239
240
}
@@ -256,7 +257,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
256
257
if (! isResend) {
257
258
// l1 router deployment block
258
259
{
259
- address routerTemplate = isUsingFeeToken
260
+ address routerTemplate = feeToken != address ( 0 )
260
261
? address (l1Templates.feeTokenBasedRouterTemplate)
261
262
: address (l1Templates.routerTemplate);
262
263
l1Deployment.router = _deployProxyWithSalt (
@@ -266,7 +267,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
266
267
267
268
// l1 standard gateway deployment block
268
269
{
269
- address template = isUsingFeeToken
270
+ address template = feeToken != address ( 0 )
270
271
? address (l1Templates.feeTokenBasedStandardGatewayTemplate)
271
272
: address (l1Templates.standardGatewayTemplate);
272
273
@@ -289,7 +290,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
289
290
290
291
// l1 custom gateway deployment block
291
292
{
292
- address template = isUsingFeeToken
293
+ address template = feeToken != address ( 0 )
293
294
? address (l1Templates.feeTokenBasedCustomGatewayTemplate)
294
295
: address (l1Templates.customGatewayTemplate);
295
296
@@ -307,7 +308,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
307
308
}
308
309
309
310
// l1 weth gateway deployment block
310
- if (! isUsingFeeToken ) {
311
+ if (feeToken == address ( 0 ) ) {
311
312
L1WethGateway wethGateway = L1WethGateway (
312
313
payable (
313
314
_deployProxyWithSalt (
@@ -338,14 +339,37 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
338
339
339
340
// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls
340
341
// we do not care if it is a resend or not, if the L2 deployment already exists it will simply fail on L2
341
- _deployL2Factory (inbox, gasPriceBid, isUsingFeeToken);
342
- if (isUsingFeeToken) {
342
+ _deployL2Factory (inbox, gasPriceBid, feeToken);
343
+
344
+ RetryableParams memory retryableParams = RetryableParams (
345
+ inbox,
346
+ canonicalL2FactoryAddress,
347
+ msg .sender ,
348
+ msg .sender ,
349
+ maxGasForContracts,
350
+ gasPriceBid,
351
+ 0
352
+ );
353
+
354
+ if (feeToken != address (0 )) {
343
355
// transfer fee tokens to inbox to pay for 2nd retryable
344
- address feeToken = _getFeeToken (inbox);
345
- uint256 fee = maxGasForContracts * gasPriceBid;
346
- IERC20 (feeToken).safeTransferFrom (msg .sender , inbox, fee);
356
+ retryableParams.feeTokenTotalFeeAmount =
357
+ _getScaledAmount (feeToken, maxGasForContracts * gasPriceBid);
358
+ IERC20 (feeToken).safeTransferFrom (
359
+ msg .sender , inbox, retryableParams.feeTokenTotalFeeAmount
360
+ );
347
361
}
348
362
363
+ L2TemplateAddresses memory l2TemplateAddress = L2TemplateAddresses (
364
+ l2RouterTemplate,
365
+ l2StandardGatewayTemplate,
366
+ l2CustomGatewayTemplate,
367
+ feeToken != address (0 ) ? address (0 ) : l2WethGatewayTemplate,
368
+ feeToken != address (0 ) ? address (0 ) : l2WethTemplate,
369
+ address (l1Templates.upgradeExecutor),
370
+ l2MulticallTemplate
371
+ );
372
+
349
373
// alias rollup owner if it is a contract
350
374
address l2RollupOwner = rollupOwner.code.length == 0
351
375
? rollupOwner
@@ -354,30 +378,13 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
354
378
// sweep the balance to send the retryable and refund the difference
355
379
// it is known that any eth previously in this contract can be extracted
356
380
// tho it is not expected that this contract will have any eth
357
- retryableSender.sendRetryable {value: isUsingFeeToken ? 0 : address (this ).balance}(
358
- RetryableParams (
359
- inbox,
360
- canonicalL2FactoryAddress,
361
- msg .sender ,
362
- msg .sender ,
363
- maxGasForContracts,
364
- gasPriceBid
365
- ),
366
- L2TemplateAddresses (
367
- l2RouterTemplate,
368
- l2StandardGatewayTemplate,
369
- l2CustomGatewayTemplate,
370
- isUsingFeeToken ? address (0 ) : l2WethGatewayTemplate,
371
- isUsingFeeToken ? address (0 ) : l2WethTemplate,
372
- address (l1Templates.upgradeExecutor),
373
- l2MulticallTemplate
374
- ),
381
+ _sendRetryableToCreateContracts (
382
+ retryableParams,
383
+ l2TemplateAddress,
375
384
l1Deployment,
376
- l2Deployment.standardGateway ,
385
+ l2Deployment,
377
386
l2RollupOwner,
378
- msg .sender ,
379
- upgradeExecutor,
380
- isUsingFeeToken
387
+ upgradeExecutor
381
388
);
382
389
383
390
// deployment mappings should not be updated in case of resend
@@ -390,6 +397,27 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
390
397
}
391
398
}
392
399
400
+ function _sendRetryableToCreateContracts (
401
+ RetryableParams memory retryableParams ,
402
+ L2TemplateAddresses memory l2TemplateAddress ,
403
+ L1DeploymentAddresses memory l1Deployment ,
404
+ L2DeploymentAddresses memory l2Deployment ,
405
+ address l2RollupOwner ,
406
+ address upgradeExecutor
407
+ ) internal {
408
+ retryableSender.sendRetryable {
409
+ value: retryableParams.feeTokenTotalFeeAmount > 0 ? 0 : address (this ).balance
410
+ }(
411
+ retryableParams,
412
+ l2TemplateAddress,
413
+ l1Deployment,
414
+ l2Deployment.standardGateway,
415
+ l2RollupOwner,
416
+ msg .sender ,
417
+ upgradeExecutor
418
+ );
419
+ }
420
+
393
421
/**
394
422
* @notice Rollup owner can override deployment
395
423
*/
@@ -416,16 +444,16 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
416
444
return inboxToL1Deployment[inbox].router;
417
445
}
418
446
419
- function _deployL2Factory (address inbox , uint256 gasPriceBid , bool isUsingFeeToken ) internal {
447
+ function _deployL2Factory (address inbox , uint256 gasPriceBid , address feeToken ) internal {
420
448
// encode L2 factory bytecode
421
449
bytes memory deploymentData =
422
450
CreationCodeHelper.getCreationCodeFor (l2TokenBridgeFactoryTemplate.code);
423
451
424
- if (isUsingFeeToken ) {
452
+ if (feeToken != address ( 0 ) ) {
425
453
// transfer fee tokens to inbox to pay for 1st retryable
426
- address feeToken = _getFeeToken (inbox);
427
454
uint256 retryableFee = gasLimitForL2FactoryDeployment * gasPriceBid;
428
- IERC20 (feeToken).safeTransferFrom (msg .sender , inbox, retryableFee);
455
+ uint256 scaledRetryableFee = _getScaledAmount (feeToken, retryableFee);
456
+ IERC20 (feeToken).safeTransferFrom (msg .sender , inbox, scaledRetryableFee);
429
457
430
458
IERC20Inbox (inbox).createRetryableTicket (
431
459
address (0 ),
@@ -435,7 +463,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
435
463
msg .sender ,
436
464
gasLimitForL2FactoryDeployment,
437
465
gasPriceBid,
438
- retryableFee ,
466
+ scaledRetryableFee ,
439
467
deploymentData
440
468
);
441
469
} else {
@@ -569,6 +597,25 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
569
597
{
570
598
return address (new TransparentUpgradeableProxy {salt: salt}(logic, admin, bytes ("" )));
571
599
}
600
+
601
+ /**
602
+ * @notice Scale amount to the fee token's decimals. Ie. amount of 1e18 will be scaled to 1e6 if fee token has 6 decimals like USDC.
603
+ */
604
+ function _getScaledAmount (address feeToken , uint256 amount ) internal view returns (uint256 ) {
605
+ uint8 decimals = ERC20 (feeToken).decimals ();
606
+ if (decimals == 18 ) {
607
+ return amount;
608
+ }
609
+ if (decimals < 18 ) {
610
+ uint256 scaledAmount = amount / (10 ** (18 - decimals));
611
+ // round up if necessary
612
+ if (scaledAmount * (10 ** (18 - decimals)) < amount) {
613
+ scaledAmount++ ;
614
+ }
615
+ return scaledAmount;
616
+ }
617
+ return amount * (10 ** (decimals - 18 ));
618
+ }
572
619
}
573
620
574
621
interface IERC20Bridge {
0 commit comments