diff --git a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/10.v5/20.accounts/01.wallet.md b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/10.v5/20.accounts/01.wallet.md index c669f63b..1eff0f23 100644 --- a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/10.v5/20.accounts/01.wallet.md +++ b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/10.v5/20.accounts/01.wallet.md @@ -199,7 +199,7 @@ the [`allowanceL1`](#getallowancel1) method. | `transaction.approveERC20?` | `boolean` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | | `transaction.approveBaseERC20?` | `boolean` | Whether or not should the base token approval be performed under the hood. Set this flag to `true` if you bridge a base token and didn't call the `approveERC20` function beforehand. | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | | `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | | `transaction.approveOverrides?` | `ethers.Overrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | @@ -359,7 +359,7 @@ Gas of approving ERC20 token is not included in estimation. | `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | | `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | | `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | @@ -1038,7 +1038,7 @@ Returns populated deposit transaction. | `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | | `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | | `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | @@ -1089,7 +1089,7 @@ Retrieves the full needed ETH fee for the deposit. Returns the L1 fee and the L2 | `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | | `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | | `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts diff --git a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/10.v5/20.accounts/03.l1signer.md b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/10.v5/20.accounts/03.l1signer.md index 350a8d22..e925cf7e 100644 --- a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/10.v5/20.accounts/03.l1signer.md +++ b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/10.v5/20.accounts/03.l1signer.md @@ -103,7 +103,7 @@ the [`allowanceL1`](#getallowancel1) method. | `transaction.approveERC20?` | `boolean` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | | `transaction.approveBaseERC20?` | `boolean` | Whether or not should the base token approval be performed under the hood. Set this flag to `true` if you bridge a base token and didn't call the `approveERC20` function beforehand. | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | | `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | | `transaction.approveOverrides?` | `ethers.Overrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | @@ -243,7 +243,7 @@ Gas of approving ERC20 token is not included in estimation. | `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | | `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | | `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | @@ -684,7 +684,7 @@ Returns populated deposit transaction. | `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | | `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | | `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | @@ -732,7 +732,7 @@ Retrieves the full needed ETH fee for the deposit. Returns the L1 fee and the L2 | `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | | `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | | `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.overrides?` | `ethers.PayableOverrides` | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts diff --git a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/20.accounts/01.wallet.md b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/20.accounts/01.wallet.md index aa377481..68f893da 100644 --- a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/20.accounts/01.wallet.md +++ b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/20.accounts/01.wallet.md @@ -196,7 +196,7 @@ use the [`allowanceL1`](/zksync-era/sdk/js/ethers/api/v6/accounts/wallet#getallo | `transaction.approveERC20?` | `boolean` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | | `transaction.approveBaseERC20?` | `boolean` | Whether or not should the base token approval be performed under the hood. Set this flag to `true` if you bridge a base token and didn't call the `approveERC20` function beforehand. | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | | `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | | `transaction.approveOverrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | @@ -356,7 +356,7 @@ Gas of approving ERC20 token is not included in estimation. | `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | | `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | | `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | @@ -1009,7 +1009,7 @@ Returns populated deposit transaction. | `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | | `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | | `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | @@ -1060,7 +1060,7 @@ Retrieves the full needed ETH fee for the deposit. Returns the L1 fee and the L2 | `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | | `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | | `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts diff --git a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/20.accounts/03.l1signer.md b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/20.accounts/03.l1signer.md index e3fd2709..c5a18d7c 100644 --- a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/20.accounts/03.l1signer.md +++ b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/20.accounts/03.l1signer.md @@ -103,7 +103,7 @@ use the [`allowanceL1`](/zksync-era/sdk/js/ethers/api/v6/accounts/l1signer#getal | `transaction.approveERC20?` | `boolean` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | | `transaction.approveBaseERC20?` | `boolean` | Whether or not should the base token approval be performed under the hood. Set this flag to `true` if you bridge a base token and didn't call the `approveERC20` function beforehand. | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | | `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | | `transaction.approveOverrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | @@ -243,7 +243,7 @@ Gas of approving ERC20 token is not included in estimation. | `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | | `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | | `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | @@ -689,7 +689,7 @@ Returns populated deposit transaction. | `transaction.operatorTip?` | `BigNumberish` | (_currently is not used_) If the ETH value passed with the transaction is not explicitly stated in the overrides,
this field will be equal to the tip the operator will receive on top of the base cost of the transaction. | | `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | | `transaction.l2GasLimit?` | `BigNumberish` | Maximum amount of L2 gas that transaction can consume during execution on L2. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | | `transaction.refundRecipient?` | `Address` | The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. | | `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | @@ -737,7 +737,7 @@ Retrieves the full needed ETH fee for the deposit. Returns the L1 fee and the L2 | `transaction.to?` | `Address` | The address that will receive the deposited tokens on L2. | | `transaction.bridgeAddress?` | `Address` | The address of the bridge contract to be used. Defaults to the default ZKsync bridge (either `L1EthBridge` or `L1Erc20Bridge`). | | `transaction.customBridgeData?` | `BytesLike` | Additional data that can be sent to a bridge. | -| `transaction.gasPerPubdataByte?` | `BigNumberish` | Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. | +| `transaction.gasPerPubdataByte?` | `BigNumberish` | The L2 gas price for each published L1 calldata byte. | | `transaction.overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | ```ts diff --git a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/00.index.md b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/00.index.md new file mode 100644 index 00000000..b089a200 --- /dev/null +++ b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/00.index.md @@ -0,0 +1,23 @@ +--- +title: Introduction +description: Bridge objects for interacting with ZKsync bridges. +tags: ["zksync", "ethereum", "zksync Era", "bridge", "integration"] +--- + +The ZKsync Era SDK provides bridge objects to interact with ZKsync bridges and transfer assets between networks. + +### Available Bridges + +The SDK includes two main bridge implementations: + +[`AbstractBridge`](./bridges/01.abstract-bridge.md): A foundational abstract class that provides core bridging functionality +and serves as a base for custom bridge implementations. It defines common deposit and withdrawal functionality shared across +different bridge types. + +[`USDCBridge`](./bridges/02.usdc-bridge.md): A specialized implementation built on top of [`AbstractBridge`](./bridges/01.abstract-bridge.md), +designed specifically for USDC token transfers via the custom [USDC bridge](https://github.com/matter-labs/usdc-bridge). + +::callout{icon="i-heroicons-light-bulb"} +Use [`AbstractBridge`](./bridges/01.abstract-bridge.md) as a foundation for custom bridges implementation or [`USDCBridge`](./bridges/02.usdc-bridge.md) +to interact with the custom [USDC bridge](https://github.com/matter-labs/usdc-bridge). +:: diff --git a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/01.abstract-bridge.md b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/01.abstract-bridge.md new file mode 100644 index 00000000..38485c41 --- /dev/null +++ b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/01.abstract-bridge.md @@ -0,0 +1,131 @@ +--- +title: AbstractBridge +description: An abstract class that provides a skeleton implementation for bridging assets. +tags: ["zksync", "bridges", "integration"] +--- + + `AbstractBridge` is an abstract class that provides a skeleton implementation for bridging assets + between Layer 1 and Layer 2. It serves as a base class that contains common functionality shared across different bridge implementations. + +This class implements the core bridging functionality such as: + +- Token deposits from L1 to L2 +- Token withdrawals from L2 to L1 +- Withdrawal finalization on L1 +- ERC20 token approval management +- Transaction validation and gas estimation + +## Abstract Methods + +Concrete bridge implementations must define the following abstract methods: + +### `getSecondBridgeDepositCalldata` + +Returns the deposit calldata for the second bridge. + +#### Inputs + +| Parameter | Type | Description | +|-----------| ---- | ----------- | +| `transaction` | [`IDepositTransaction`](./03.types.md#ideposittransaction) | Deposit transaction. | + +```ts +protected abstract getSecondBridgeDepositCalldata( + transaction: IDepositTransaction +): Promise; +``` + +### `populateWithdrawTransaction` + +Populates the withdraw transaction for the bridge. + +#### Inputs + +| Parameter | Type | Description | +|-----------| ---- | ----------- | +| `transaction` | [`IWithdrawTransaction`](./03.types.md#iwithdrawtransaction) | Withdraw transaction. | + +```ts +protected abstract populateWithdrawTransaction( + transaction: IWithdrawTransaction +): Promise; +``` + +### `finalizeL1Deposit` + +Finalizes the L1 deposit. + +#### Inputs + +| Parameter | Type | Description | +|-----------| ---- | ----------- | +| `bridgeAddress` | `Address` | The address of the bridge contract to be used. | +| `finalizeParams` | [`FinalizeL1DepositParams`](./03.types.md#finalizel1depositparams) | Finalize L1 deposit parameters. | +| `overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | + +```ts +protected abstract finalizeL1Deposit( + bridgeAddress: Address, + finalizeParams: FinalizeL1DepositParams, + overrides?: Overrides +): Promise; +``` + +### `checkIfWithdrawalIsFinalized` + +Checks if a withdrawal has been finalized on L1. + +#### Inputs + +| Parameter | Type | Description | +|-----------| ---- | ----------- | +| `bridgeAddress` | `Address` | The address of the bridge contract to be used. | +| `finalizeParams` | [`FinalizeL1DepositParams`](./03.types.md#finalizel1depositparams) | Finalize withdrawal parameters. | + +```ts +protected abstract checkIfWithdrawalIsFinalized( + bridgeAddress: Address, + finalizeParams: FinalizeL1DepositParams +): Promise; +``` + +## Validation Hooks + +The class provides optional validation hooks that can be overridden: + +### `validateDepositParams` + +Validates deposit transaction parameters. The function is expected to throw an exception if the deposit parameters are not valid. + +#### Inputs + +| Parameter | Type | Description | +|-----------| ---- | ----------- | +| `transaction` | [`IDepositTransaction`](./03.types.md#ideposittransaction) | Deposit transaction. | + +```ts +protected async validateDepositParams( + transaction: IDepositTransaction +): Promise; +``` + +### `validateWithdrawParams` + +Validates withdrawal transaction parameters. The function is expected to throw an exception if the withdrawal parameters are not valid. + +#### Inputs + +| Parameter | Type | Description | +|-----------| ---- | ----------- | +| `transaction` | [`IWithdrawTransaction`](./03.types.md#iwithdrawtransaction) | Withdraw transaction. | + +```ts +protected async validateWithdrawParams( + transaction: IWithdrawTransaction +): Promise; +``` + +## Complete Implementation Example + +For a complete implementation example, see the [`USDCBridge`](./02.usdc-bridge.md) class which extends `AbstractBridge` and +implements all required abstract methods for USDC token bridging operations. diff --git a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/02.usdc-bridge.md b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/02.usdc-bridge.md new file mode 100644 index 00000000..62cef193 --- /dev/null +++ b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/02.usdc-bridge.md @@ -0,0 +1,123 @@ +--- +title: USDCBridge +description: A class for interacting with the custom USDC bridge. +tags: ["zksync", "bridges", "integration", "usdc"] +--- + +`USDCBridge` class implements [`AbstractBridge`](./01.abstract-bridge.md) class and provides methods for depositing and +withdrawing USDC tokens using custom [USDC bridge](https://github.com/matter-labs/usdc-bridge). + +### `constructor(wallet: Wallet)` + +Creates a `USDCBridge` object. + +**Parameters:** + +| Parameter | Type | Description | +| ---------- | -------- | ------------------------- | +| `wallet` | `Wallet`| ZKsync wallet instance. | + +**Example:** + +```ts +:code-import{filePath="hardhat-sol/scripts/usdc-bridge.ts"} +``` + +### `deposit` + +Deposits USDC tokens using the custom [USDC bridge](https://github.com/matter-labs/usdc-bridge) + +#### Inputs + +| Parameter | Type | Description | +|-----------| ---- | ----------- | +| `transaction` | [`IDepositTransaction`](./03.types.md#ideposittransaction) | Deposit transaction. | + +```ts +async deposit(transaction: IDepositTransaction): Promise +``` + +#### Example + +```ts +:code-import{filePath="hardhat-sol/scripts/usdc-deposit.ts:usdc-deposit"} +``` + +### `withdraw` + +Withdraws USDC tokens using the custom [USDC bridge](https://github.com/matter-labs/usdc-bridge) from the associated account +on L2 network to the target account on L1 network. + +#### Inputs + +| Parameter | Type | Description | +|-----------| ---- | ----------- | +| `transaction` | [`IWithdrawTransaction`](./03.types.md#iwithdrawtransaction) | Withdraw transaction. | + +```ts +async withdraw(transaction: IWithdrawTransaction): Promise +``` + +#### Examples + +```ts +:code-import{filePath="hardhat-sol/scripts/usdc-withdraw.ts:usdc-withdraw"} +``` + +### `finalizeWithdrawal` + +Proves the inclusion of the L2 -> L1 withdrawal message. + +#### Inputs + +| Parameter | Type | Description | +|-----------| ---- | ----------- | +| `bridgeAddress` | `Address` | The address of the USDC bridge contract to be used. | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | +| `overrides?` | [`ethers.Overrides`](https://docs.ethers.org/v6/api/contract/#Overrides) | Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. | + +```ts +async finalizeWithdrawal( + bridgeAddress: Address, + withdrawalHash: BytesLike, + index: number = 0, + overrides?: ethers.Overrides +): Promise +``` + +#### Example + +```ts +:code-import{filePath="hardhat-sol/scripts/usdc-finalize-withdrawal.ts:setup"} + +:code-import{filePath="hardhat-sol/scripts/usdc-finalize-withdrawal.ts:finalize"} +``` + +### `isWithdrawalFinalized` + +Returns whether the withdrawal transaction has been finalized on the L1 network. + +#### Inputs + +| Parameter | Type | Description | +|-----------| ---- | ----------- | +| `bridgeAddress` | `Address` | The address of the USDC bridge contract to be used. | +| `withdrawalHash` | `BytesLike` | Hash of the L2 transaction where the withdrawal was initiated. | +| `index?` | `number` | In case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize. Defaults to 0. | + +```ts +async isWithdrawalFinalized( + bridgeAddress: Address, + withdrawalHash: BytesLike, + index: number = 0 +): Promise +``` + +#### Example + +```ts +:code-import{filePath="hardhat-sol/scripts/usdc-finalize-withdrawal.ts:setup"} + +:code-import{filePath="hardhat-sol/scripts/usdc-finalize-withdrawal.ts:status"} +``` diff --git a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/03.types.md b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/03.types.md new file mode 100644 index 00000000..69f0564b --- /dev/null +++ b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/03.types.md @@ -0,0 +1,78 @@ +--- +title: Types +description: Types used by bridge classes. +tags: ["zksync", "bridges", "integration", "types"] +--- + +### `IDepositTransaction` + +Represents a bridge deposit transaction. + +```ts +interface IDepositTransaction { + // The address of the token to deposit. + token: Address; + // The amount of the token to deposit. + amount: BigNumberish; + // The address that will receive the deposited tokens on L2. + to?: Address; + // Currently is not used. If the ETH value passed with the transaction is not explicitly stated in the overrides, this field will be equal to the tip the operator will receive on top of the base cost of the transaction. + operatorTip?: BigNumberish; + // The address of the bridge contract to be used. + bridgeAddress: Address; + // Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. + approveERC20?: boolean; + // Maximum amount of L2 gas that transaction can consume during execution on L2. + l2GasLimit?: BigNumberish; + // The L2 gas price for each published L1 calldata byte. + gasPerPubdataByte?: BigNumberish; + // The address on L2 that will receive the refund for the transaction. If the transaction fails, it will also be the address to receive l2Value. + refundRecipient?: Address; + // Ethers overrides (https://docs.ethers.org/v6/api/contract/#Overrides). Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. + overrides?: Overrides; + // Ethers overrides (https://docs.ethers.org/v6/api/contract/#Overrides). Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. + approveOverrides?: Overrides; +} +``` + +### `IWithdrawTransaction` + +Represents a bridge withdraw transaction. + +```ts +interface IWithdrawTransaction { + // The address of the token to withdraw. + token: Address; + // The amount of the token to withdraw. + amount: BigNumberish; + // The address of the recipient on L1. + to?: Address; + // The address of the bridge contract to be used. + bridgeAddress: Address; + // Paymaster parameters for the transaction. + paymasterParams?: PaymasterParams; + // Ethers overrides (https://docs.ethers.org/v6/api/contract/#Overrides). Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. + overrides?: Overrides; + // Whether or not should the token approval be performed under the hood. Set this flag to `true` if you bridge an ERC20 token and didn't call the `approveERC20` function beforehand. + approveERC20?: boolean; + // Ethers overrides (https://docs.ethers.org/v6/api/contract/#Overrides). Transaction's overrides which may be used to pass L1 `gasLimit`, `gasPrice`, `value`, etc. + approveOverrides?: Overrides; +} +``` + +### `FinalizeL1DepositParams` + +Contains parameters for finalizing the L2 -> L1 deposit transaction. Pre V26 withdrawals were special kind of transaction, +but starting from v26 any cross-chain token movement is called a deposit, regardless of direction. + +```ts +type FinalizeL1DepositParams = { + chainId: BigNumberish; + l2BatchNumber: BigNumberish; + l2MessageIndex: BigNumberish; + l2Sender: AddressLike; + l2TxNumberInBatch: BigNumberish; + message: BytesLike; + merkleProof: BytesLike[]; +} +``` diff --git a/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/_dir.yml b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/_dir.yml new file mode 100644 index 00000000..9ac638a6 --- /dev/null +++ b/content/00.zksync-era/50.sdk/10.js/01.ethers/05.api/20.v6/60.bridges/_dir.yml @@ -0,0 +1 @@ +title: Bridges diff --git a/examples/hardhat-sol/.env.example b/examples/hardhat-sol/.env.example index c65faa8c..530df336 100644 --- a/examples/hardhat-sol/.env.example +++ b/examples/hardhat-sol/.env.example @@ -1 +1,3 @@ -WALLET_PRIVATE_KEY= +# DO NOT PUT REAL PRIVATE KEYS INTO THIS FILE +# This is a local rich wallet private key for development and learning purposes only +WALLET_PRIVATE_KEY=0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110 diff --git a/examples/hardhat-sol/bun.lockb b/examples/hardhat-sol/bun.lockb index 07dc573f..38a9b3e5 100755 Binary files a/examples/hardhat-sol/bun.lockb and b/examples/hardhat-sol/bun.lockb differ diff --git a/examples/hardhat-sol/hardhat.config.ts b/examples/hardhat-sol/hardhat.config.ts index 1ed194ff..9195a3d9 100644 --- a/examples/hardhat-sol/hardhat.config.ts +++ b/examples/hardhat-sol/hardhat.config.ts @@ -1,51 +1,68 @@ import type { HardhatUserConfig } from 'hardhat/config'; + +import '@nomicfoundation/hardhat-chai-matchers'; import '@matterlabs/hardhat-zksync'; +import dotenv from 'dotenv'; +dotenv.config(); + const config: HardhatUserConfig = { - defaultNetwork: 'inMemoryNode', + defaultNetwork: 'anvilZKsync', networks: { - zkSyncSepoliaTestnet: { + ZKsyncEraSepolia: { url: 'https://sepolia.era.zksync.dev', ethNetwork: 'sepolia', zksync: true, verifyURL: 'https://explorer.sepolia.era.zksync.dev/contract_verification', + accounts: process.env.WALLET_PRIVATE_KEY ? [process.env.WALLET_PRIVATE_KEY] : [], }, - zkSyncMainnet: { + ZKsyncEraMainnet: { url: 'https://mainnet.era.zksync.io', ethNetwork: 'mainnet', zksync: true, verifyURL: 'https://zksync2-mainnet-explorer.zksync.io/contract_verification', + accounts: process.env.WALLET_PRIVATE_KEY ? [process.env.WALLET_PRIVATE_KEY] : [], + }, + SophonMainnet: { + url: 'https://rpc.sophon.xyz', + ethNetwork: 'mainnet', + verifyURL: 'https://verification-explorer.sophon.xyz/contract_verification', + zksync: true, + accounts: process.env.WALLET_PRIVATE_KEY ? [process.env.WALLET_PRIVATE_KEY] : [], + }, + SophonTestnet: { + url: 'https://rpc.testnet.sophon.xyz', + ethNetwork: 'sepolia', + verifyURL: 'https://api-explorer-verify.testnet.sophon.xyz/contract_verification', + zksync: true, + accounts: process.env.WALLET_PRIVATE_KEY ? [process.env.WALLET_PRIVATE_KEY] : [], }, - // ANCHOR: dockerizedNode dockerizedNode: { url: 'http://localhost:3050', ethNetwork: 'http://localhost:8545', zksync: true, + accounts: process.env.WALLET_PRIVATE_KEY ? [process.env.WALLET_PRIVATE_KEY] : [], }, - // ANCHOR_END: dockerizedNode - inMemoryNode: { + anvilZKsync: { url: 'http://127.0.0.1:8011', - ethNetwork: 'localhost', // in-memory node doesn't support eth node; removing this line will cause an error + ethNetwork: 'http://localhost:8545', zksync: true, + accounts: process.env.WALLET_PRIVATE_KEY ? [process.env.WALLET_PRIVATE_KEY] : [], }, hardhat: { zksync: true, }, }, - // ANCHOR: zksolc zksolc: { - version: 'latest', + version: '1.5.15', settings: { - libraries: { - 'contracts/MiniMath/MiniMath.sol': { - MiniMath: '0x111C3E89Ce80e62EE88318C2804920D4c96f92bb', - }, - }, + codegen: 'yul', + // find all available options in the official documentation + // https://docs.zksync.io/build/tooling/hardhat/hardhat-zksync-solc#configuration }, }, - // ANCHOR_END: zksolc solidity: { - version: '0.8.24', + version: '0.8.30', }, }; diff --git a/examples/hardhat-sol/package.json b/examples/hardhat-sol/package.json index 6f9fed70..6bcae63f 100644 --- a/examples/hardhat-sol/package.json +++ b/examples/hardhat-sol/package.json @@ -6,24 +6,27 @@ "license": "MIT", "repository": "https://github.com/matter-labs/zksync-hardhat-template.git", "scripts": { - "deploy:main": "hardhat deploy-zksync --script deploy-main.ts", + "mint-token": "hardhat run ./scripts/mint-token.ts", + "usdc-bridge": "hardhat run ./scripts/usdc-bridge.ts", "compile": "hardhat compile", "clean": "hardhat clean" }, "devDependencies": { - "@matterlabs/hardhat-zksync": "^1.1.0", - "@matterlabs/zksync-contracts": "^0.6.1", - "@nomicfoundation/hardhat-verify": "^2.0.9", - "@openzeppelin/contracts": "^5.3.0", - "@types/chai": "^4.3.16", - "@types/mocha": "^10.0.7", + "@matterlabs/hardhat-zksync": "^1.6.2", + "@matterlabs/zksync-contracts": "^28.0.1", + "@nomicfoundation/hardhat-chai-matchers": "^2.1.0", + "@nomicfoundation/hardhat-verify": "^2.1.1", + "@openzeppelin/contracts": "^5.4.0", + "@types/chai": "^5.2.2", + "@types/mocha": "^10.0.10", + "@types/node": "^22.17.1", "chai": "^4.5.0", - "dotenv": "^16.4.5", - "ethers": "^6.13.2", - "hardhat": "^2.22.7", - "mocha": "^10.7.0", + "dotenv": "^16.6.1", + "ethers": "^6.15.0", + "hardhat": "^2.26.2", + "mocha": "^11.7.1", "ts-node": "^10.9.2", - "typescript": "^5.5.4", - "zksync-ethers": "^6.11.0" + "typescript": "^5.9.2", + "zksync-ethers": "^6.20.1" } } diff --git a/examples/hardhat-sol/scripts/usdc-bridge.ts b/examples/hardhat-sol/scripts/usdc-bridge.ts new file mode 100644 index 00000000..207af1c9 --- /dev/null +++ b/examples/hardhat-sol/scripts/usdc-bridge.ts @@ -0,0 +1,10 @@ +import { Provider, types, Wallet, USDCBridge } from 'zksync-ethers'; +import { ethers } from 'ethers'; + +const PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY || '0x'; +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const ethProvider = ethers.getDefaultProvider('sepolia'); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); + +const usdcBridge = new USDCBridge(wallet); +console.log('USDC Bridge initialized', usdcBridge); diff --git a/examples/hardhat-sol/scripts/usdc-deposit.ts b/examples/hardhat-sol/scripts/usdc-deposit.ts new file mode 100644 index 00000000..765d67e4 --- /dev/null +++ b/examples/hardhat-sol/scripts/usdc-deposit.ts @@ -0,0 +1,35 @@ +// ANCHOR: usdc-deposit +import { Wallet, Provider, types, USDCBridge } from 'zksync-ethers'; +import { ethers } from 'ethers'; + +const PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY || '0x'; +const USDC_TOKEN_L1_ADDRESS = ''; +const USDC_BRIDGE_L1_ADDRESS = ''; +const AMOUNT = '5'; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const ethProvider = ethers.getDefaultProvider('sepolia'); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); +const usdcBridge = new USDCBridge(wallet); + +async function main() { + const depositTx = await usdcBridge.deposit({ + token: USDC_TOKEN_L1_ADDRESS, + amount: ethers.parseUnits(AMOUNT, 6), + approveERC20: true, + bridgeAddress: USDC_BRIDGE_L1_ADDRESS, + }); + + // Note that we wait not only for the L1 transaction to complete but also for it to be + // processed by ZKsync. If we want to wait only for the transaction to be processed on L1, + // we can use `await depositTx.waitL1Commit()` + await depositTx.wait(); +} +// ANCHOR_END: usdc-deposit + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/examples/hardhat-sol/scripts/usdc-finalize-withdrawal.ts b/examples/hardhat-sol/scripts/usdc-finalize-withdrawal.ts new file mode 100644 index 00000000..39c74e3c --- /dev/null +++ b/examples/hardhat-sol/scripts/usdc-finalize-withdrawal.ts @@ -0,0 +1,40 @@ +// ANCHOR: setup +import { Wallet, Provider, types, USDCBridge } from 'zksync-ethers'; +import { ethers } from 'ethers'; + +const PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY || '0x'; +const USDC_BRIDGE_L1_ADDRESS = ''; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const ethProvider = ethers.getDefaultProvider('sepolia'); +const wallet = new Wallet(PRIVATE_KEY, provider, ethProvider); +const usdcBridge = new USDCBridge(wallet); + +const WITHDRAWAL_TX_HASH = ''; +// ANCHOR_END: setup + +// ANCHOR: finalize +async function finalizeWithdrawal() { + const finalizeWithdrawalTx = await usdcBridge.finalizeWithdrawal(USDC_BRIDGE_L1_ADDRESS, WITHDRAWAL_TX_HASH); + console.log('Finalize withdrawal transaction hash:', finalizeWithdrawalTx.hash); +} +// ANCHOR_END: finalize + +// ANCHOR: status +async function checkWithdrawalStatus() { + const isFinalized = await usdcBridge.isWithdrawalFinalized(USDC_BRIDGE_L1_ADDRESS, WITHDRAWAL_TX_HASH); + console.log('Withdrawal is finalized:', isFinalized); +} +// ANCHOR_END: status + +async function main() { + await finalizeWithdrawal(); + await checkWithdrawalStatus(); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/examples/hardhat-sol/scripts/usdc-withdraw.ts b/examples/hardhat-sol/scripts/usdc-withdraw.ts new file mode 100644 index 00000000..99a8d911 --- /dev/null +++ b/examples/hardhat-sol/scripts/usdc-withdraw.ts @@ -0,0 +1,30 @@ +// ANCHOR: usdc-withdraw +import { Wallet, Provider, types, USDCBridge } from 'zksync-ethers'; +import { ethers } from 'ethers'; + +const PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY || '0x'; +const USDC_TOKEN_L2_ADDRESS = ''; +const USDC_BRIDGE_L2_ADDRESS = ''; +const AMOUNT = '5'; + +const provider = Provider.getDefaultProvider(types.Network.Sepolia); +const wallet = new Wallet(PRIVATE_KEY, provider); +const usdcBridge = new USDCBridge(wallet); + +async function main() { + const withdrawTx = await usdcBridge.withdraw({ + token: USDC_TOKEN_L2_ADDRESS, + amount: ethers.parseUnits(AMOUNT, 6), + bridgeAddress: USDC_BRIDGE_L2_ADDRESS, + approveERC20: true, + }); + console.log('Withdraw transaction hash:', withdrawTx.hash); +} +// ANCHOR_END: usdc-withdraw + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + });