@@ -18,6 +18,7 @@ const {
1818 ParentEthDepositTransactionReceipt,
1919} = require ( '@arbitrum/sdk' ) ;
2020const { getBaseFee } = require ( '@arbitrum/sdk/dist/lib/utils/lib' ) ;
21+ const { ERC20__factory } = require ( '@arbitrum/sdk/dist/lib/abi/factories/ERC20__factory' ) ;
2122require ( 'dotenv' ) . config ( ) ;
2223requireEnvVariables ( [ 'PRIVATE_KEY' , 'CHAIN_RPC' , 'PARENT_CHAIN_RPC' , 'TransferTo' ] ) ;
2324
@@ -50,15 +51,24 @@ const main = async () => {
5051 const ethBridger = new EthBridger ( childChainNetwork ) ;
5152 const inboxAddress = ethBridger . childNetwork . ethBridge . inbox ;
5253
54+ /**
55+ * We find out whether the child chain we are using is a custom gas token chain
56+ * We need to perform an additional approve call to transfer
57+ * the native tokens to pay for the gas of the retryable tickets.
58+ */
59+ const isCustomGasTokenChain =
60+ childChainNetwork . nativeToken && childChainNetwork . nativeToken !== ethers . constants . AddressZero ;
61+
5362 /**
5463 * We deploy EthDeposit contract to the parent chain first and send eth to
5564 * the child chain via this contract.
5665 * Funds will deposit to the contract's alias address first.
5766 */
58- const DepositContract = await (
59- await hre . ethers . getContractFactory ( 'EthDeposit' )
60- ) . connect ( parentChainWallet ) ;
61- console . log ( 'Deploying EthDeposit contract...' ) ;
67+ const depositContractName = isCustomGasTokenChain ? 'CustomGasTokenDeposit' : 'EthDeposit' ;
68+ const DepositContract = ( await hre . ethers . getContractFactory ( depositContractName ) ) . connect (
69+ parentChainWallet ,
70+ ) ;
71+ console . log ( `Deploying ${ depositContractName } contract...` ) ;
6272 const depositContract = await DepositContract . deploy ( inboxAddress ) ;
6373 await depositContract . deployed ( ) ;
6474 console . log ( `deployed to ${ depositContract . address } ` ) ;
@@ -71,18 +81,41 @@ const main = async () => {
7181
7282 console . log ( `Sending deposit transaction...` ) ;
7383
74- const ethDepositTx = await depositContract . depositToChildChain ( {
75- value : ethers . utils . parseEther ( '0.01' ) ,
76- } ) ;
77- const ethDepositRec = await ethDepositTx . wait ( ) ;
84+ let depositTx ;
85+ let nativeTokenDecimals = 18 ; // We default to 18 decimals for ETH and most of ERC-20 tokens
86+ if ( isCustomGasTokenChain ) {
87+ // Approve the gas token to be sent to the contract
88+ console . log ( 'Giving allowance to the contract to transfer the chain native token' ) ;
89+ const nativeToken = new ethers . Contract (
90+ childChainNetwork . nativeToken ,
91+ ERC20__factory . abi ,
92+ parentChainWallet ,
93+ ) ;
94+ nativeTokenDecimals = await nativeToken . decimals ( ) ;
95+ const approvalTransaction = await nativeToken . approve (
96+ depositContract . address ,
97+ ethers . utils . parseUnits ( '1' , nativeTokenDecimals ) ,
98+ ) ;
99+ const approvalTransactionReceipt = await approvalTransaction . wait ( ) ;
100+ console . log ( `Approval transaction receipt is: ${ approvalTransactionReceipt . transactionHash } ` ) ;
101+
102+ depositTx = await depositContract . depositToChildChain (
103+ ethers . utils . parseUnits ( '0.01' , nativeTokenDecimals ) ,
104+ ) ;
105+ } else {
106+ depositTx = await depositContract . depositToChildChain ( {
107+ value : ethers . utils . parseEther ( '0.01' ) , // Here we know we are using ETH, so we can use parseEther
108+ } ) ;
109+ }
110+ const depositReceipt = await depositTx . wait ( ) ;
78111
79- console . log ( `Deposit txn confirmed on the parent chain! 🙌 ${ ethDepositRec . transactionHash } ` ) ;
112+ console . log ( `Deposit txn confirmed on the parent chain! 🙌 ${ depositReceipt . transactionHash } ` ) ;
80113
81114 console . log (
82115 'Waiting for the execution of the deposit in the child chain. This may take up to 10-15 minutes ⏰' ,
83116 ) ;
84117
85- const parentChainDepositTxReceipt = new ParentEthDepositTransactionReceipt ( ethDepositRec ) ;
118+ const parentChainDepositTxReceipt = new ParentEthDepositTransactionReceipt ( depositReceipt ) ;
86119 const childChainDepositResult = await parentChainDepositTxReceipt . waitForChildTransactionReceipt (
87120 childChainProvider ,
88121 ) ;
@@ -103,7 +136,7 @@ const main = async () => {
103136 ) ;
104137 } else {
105138 throw new Error (
106- `Deposit to the child chain failed, EthDepositStatus is ${
139+ `Deposit to the child chain failed, DepositStatus is ${
107140 EthDepositStatus [ childChainDepositResult . message . status ]
108141 } `,
109142 ) ;
@@ -147,7 +180,7 @@ const main = async () => {
147180 {
148181 from : contractAliasAddress ,
149182 to : transferTo ,
150- l2CallValue : ethers . utils . parseEther ( '0.01' ) , // because we deposited 0.01 ether, so we also transfer 0.01 ether out here.
183+ l2CallValue : ethers . utils . parseUnits ( '0.01' , nativeTokenDecimals ) , // because we deposited 0.01 ether, so we also transfer 0.01 ether out here.
151184 excessFeeRefundAddress : depositContract . address ,
152185 callValueRefundAddress : depositContract . address ,
153186 data : [ ] ,
@@ -175,7 +208,9 @@ const main = async () => {
175208 * we need to subtract it here so the transaction in the parent chain doesn't pay l2callvalue
176209 * and instead uses the alias balance on the child chain directly.
177210 */
178- const depositAmount = parentToChildMessageGasParams . deposit . sub ( ethers . utils . parseEther ( '0.01' ) ) ;
211+ const depositAmount = parentToChildMessageGasParams . deposit . sub (
212+ ethers . utils . parseUnits ( '0.01' , nativeTokenDecimals ) ,
213+ ) ;
179214
180215 console . log (
181216 `Transfer funds txn needs ${ ethers . utils . formatEther (
@@ -186,16 +221,31 @@ const main = async () => {
186221 /**
187222 * Call the contract's method to transfer the funds from the alias to the address you set
188223 */
189- const setTransferTx = await depositContract . moveFundsFromChildChainAliasToAnotherAddress (
190- transferTo ,
191- ethers . utils . parseEther ( '0.01' ) , // because we deposited 0.01 ether, so we also transfer 0.01 ether out here.
192- parentToChildMessageGasParams . maxSubmissionCost ,
193- parentToChildMessageGasParams . gasLimit ,
194- gasPriceBid ,
195- {
196- value : depositAmount ,
197- } ,
198- ) ;
224+ let setTransferTx ;
225+ if ( isCustomGasTokenChain ) {
226+ // We don't need to give allowance to the contract now since we already gave plenty in the
227+ // previous step
228+
229+ setTransferTx = await depositContract . moveFundsFromChildChainAliasToAnotherAddress (
230+ transferTo ,
231+ ethers . utils . parseUnits ( '0.01' , nativeTokenDecimals ) , // because we deposited 0.01 ether, so we also transfer 0.01 ether out here.
232+ parentToChildMessageGasParams . maxSubmissionCost ,
233+ parentToChildMessageGasParams . gasLimit ,
234+ gasPriceBid ,
235+ depositAmount ,
236+ ) ;
237+ } else {
238+ setTransferTx = await depositContract . moveFundsFromChildChainAliasToAnotherAddress (
239+ transferTo ,
240+ ethers . utils . parseEther ( '0.01' ) , // because we deposited 0.01 ether, so we also transfer 0.01 ether out here.
241+ parentToChildMessageGasParams . maxSubmissionCost ,
242+ parentToChildMessageGasParams . gasLimit ,
243+ gasPriceBid ,
244+ {
245+ value : depositAmount ,
246+ } ,
247+ ) ;
248+ }
199249 const setTransferRec = await setTransferTx . wait ( ) ;
200250
201251 console . log (
0 commit comments