99    L2TemplateAddresses,
1010    IERC20Inbox ,
1111    IERC20 ,
12+     ERC20 ,
1213    SafeERC20
1314} from  "./L1TokenBridgeRetryableSender.sol " ;
1415import  {L1GatewayRouter} from  "./gateway/L1GatewayRouter.sol " ;
@@ -216,7 +217,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
216217        // deployment mappings should not be updated in case of resend 
217218        bool  isResend =  (inboxToL1Deployment[inbox].router !=  address (0 ));
218219
219-         bool  isUsingFeeToken  =  _getFeeToken (inbox)  !=   address ( 0 );
220+         address  feeToken  =  _getFeeToken (inbox);
220221
221222        // store L2 addresses before deployments 
222223        L1DeploymentAddresses memory  l1Deployment;
@@ -233,7 +234,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
233234            l2Deployment.router =  _getProxyAddress (OrbitSalts.L2_ROUTER, chainId);
234235            l2Deployment.standardGateway =  _getProxyAddress (OrbitSalts.L2_STANDARD_GATEWAY, chainId);
235236            l2Deployment.customGateway =  _getProxyAddress (OrbitSalts.L2_CUSTOM_GATEWAY, chainId);
236-             if  (! isUsingFeeToken ) {
237+             if  (feeToken  ==   address ( 0 ) ) {
237238                l2Deployment.wethGateway =  _getProxyAddress (OrbitSalts.L2_WETH_GATEWAY, chainId);
238239                l2Deployment.weth =  _getProxyAddress (OrbitSalts.L2_WETH, chainId);
239240            }
@@ -256,7 +257,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
256257        if  (! isResend) {
257258            // l1 router deployment block 
258259            {
259-                 address  routerTemplate =  isUsingFeeToken 
260+                 address  routerTemplate =  feeToken  !=   address ( 0 ) 
260261                    ?  address (l1Templates.feeTokenBasedRouterTemplate)
261262                    :  address (l1Templates.routerTemplate);
262263                l1Deployment.router =  _deployProxyWithSalt (
@@ -266,7 +267,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
266267
267268            // l1 standard gateway deployment block 
268269            {
269-                 address  template =  isUsingFeeToken 
270+                 address  template =  feeToken  !=   address ( 0 ) 
270271                    ?  address (l1Templates.feeTokenBasedStandardGatewayTemplate)
271272                    :  address (l1Templates.standardGatewayTemplate);
272273
@@ -289,7 +290,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
289290
290291            // l1 custom gateway deployment block 
291292            {
292-                 address  template =  isUsingFeeToken 
293+                 address  template =  feeToken  !=   address ( 0 ) 
293294                    ?  address (l1Templates.feeTokenBasedCustomGatewayTemplate)
294295                    :  address (l1Templates.customGatewayTemplate);
295296
@@ -307,7 +308,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
307308            }
308309
309310            // l1 weth gateway deployment block 
310-             if  (! isUsingFeeToken ) {
311+             if  (feeToken  ==   address ( 0 ) ) {
311312                L1WethGateway wethGateway =  L1WethGateway (
312313                    payable (
313314                        _deployProxyWithSalt (
@@ -338,14 +339,37 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
338339
339340        // deploy factory and then L2 contracts through L2 factory, using 2 retryables calls 
340341        // 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 )) {
343355            // 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+             );
347361        }
348362
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+ 
349373        // alias rollup owner if it is a contract 
350374        address  l2RollupOwner =  rollupOwner.code.length  ==  0 
351375            ?  rollupOwner
@@ -354,30 +378,13 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
354378        // sweep the balance to send the retryable and refund the difference 
355379        // it is known that any eth previously in this contract can be extracted 
356380        // 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,
375384            l1Deployment,
376-             l2Deployment.standardGateway ,
385+             l2Deployment,
377386            l2RollupOwner,
378-             msg .sender ,
379-             upgradeExecutor,
380-             isUsingFeeToken
387+             upgradeExecutor
381388        );
382389
383390        // deployment mappings should not be updated in case of resend 
@@ -390,6 +397,27 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
390397        }
391398    }
392399
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+ 
393421    /** 
394422     * @notice Rollup owner can override deployment 
395423     */ 
@@ -416,16 +444,16 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
416444        return  inboxToL1Deployment[inbox].router;
417445    }
418446
419-     function _deployL2Factory  (address  inbox , uint256  gasPriceBid , bool   isUsingFeeToken ) internal  {
447+     function _deployL2Factory  (address  inbox , uint256  gasPriceBid , address   feeToken ) internal  {
420448        // encode L2 factory bytecode 
421449        bytes  memory  deploymentData = 
422450            CreationCodeHelper.getCreationCodeFor (l2TokenBridgeFactoryTemplate.code);
423451
424-         if  (isUsingFeeToken ) {
452+         if  (feeToken  !=   address ( 0 ) ) {
425453            // transfer fee tokens to inbox to pay for 1st retryable 
426-             address  feeToken =  _getFeeToken (inbox);
427454            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);
429457
430458            IERC20Inbox (inbox).createRetryableTicket (
431459                address (0 ),
@@ -435,7 +463,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
435463                msg .sender ,
436464                gasLimitForL2FactoryDeployment,
437465                gasPriceBid,
438-                 retryableFee ,
466+                 scaledRetryableFee ,
439467                deploymentData
440468            );
441469        } else  {
@@ -569,6 +597,25 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable {
569597    {
570598        return  address (new  TransparentUpgradeableProxy {salt: salt}(logic, admin, bytes ("" )));
571599    }
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+     }
572619}
573620
574621interface  IERC20Bridge  {
0 commit comments