You can use ZKEVM Bridge Contract to bridge assets like ETH, OKB, and ERC-20 tokens between layer 1 and layer 2. However, there are a few points to note:
precalculatedWrapperAddress
method.NetworkId
and ChainId
are not the same. NetworkId
is a property that is unique to Polygon's Agglayer whereas ChainId
is typically a transaction replay protection mechanism across EVM chains. The relevant information for Ethereum and X Layer are shown below.Network (Mainnet) | ChainId | NetworkId |
---|---|---|
Ethereum | 1 | 0 |
X Layer | 196 | 3 |
Network (Testnet) | ChainId | NetworkId |
---|---|---|
Sepolia | 11155111 | 0 |
X Layer testnet | 195 | 1 |
#support-tickets
to raise whitelising request.The mapping list for OKB and ETH is as follows:
ERC-20 Token | Testnet | Mainnet |
---|---|---|
OKB | 0x3F4B6664338F23d2397c953f2AB4Ce8031663f80 (Layer 1 Ethereum Sepolia) | 0x75231f58b43240c9718dd58b4967c5114342a86c (Layer 1 Ethereum) |
WETH | 0xBec7859BC3d0603BeC454F7194173E36BF2Aa5C8 (Layer 2 X Layer testnet) | 0x5a77f1443d16ee5761d310e38b62f77f726bc71c (Layer 2 X Layer mainnet) |
The ZKEVM bridge contract allows ETH and ERC-20 token bridging from layer 1 to layer 2 using the bridgeAsset function. Notice that ERC-20 tokens will have a different address on layer 2. You can use the precalculatedWrapperAddress function to query the new address in ZkEVMBridgeContract.sol contract
If the asset you bridged is USDC, please refer to this document.
Deposit and add a new leaf to the Merkle tree:
function bridgeAsset(
uint32 destinationNetwork,
address destinationAddress,
uint256 amount,
address token,
bool forceUpdateGlobalExitRoot,
bytes permitData
) public
Parameters
Name | Type | Description |
---|---|---|
destinationNetwork | uint32 | Network destination. 3 for X Layer |
destinationAddress | address | Address destination |
amount | uint256 | Amount of tokens |
token | address | Token address, 0 address is reserved for ETH |
forceUpdateGlobalExitRoot | bool | Indicates if the new global exit root is updated or not |
permitData | bytes | Raw data of the call permit of the token |
This returns the precalculated address of a wrapper using the token information. Note: Updating the metadata of a token is not supported. Since the metadata has relevance in the address deployed, this function will not return a valid wrapped address if the metadata provided is not the original one.
function precalculatedWrapperAddress(
uint32 originNetwork,
address originTokenAddress,
string name,
string symbol,
uint8 decimals
) external returns (address)
Parameters
Name | Type | Description |
---|---|---|
originNetwork | uint32 | Origin network |
originTokenAddress | address | Origin token address, 0 address is reserved for ETH |
name | string | Name of the token |
symbol | string | Symbol of the token |
decimals | uint8 | Decimals of the token |
You can use the claimAsset
method to retrieve assets on layer 2. Calling this method on layer 2 incurs no Gas fees, so the official bridge service will be provided to automatically invoke the claimAsset
method for you.
If the asset you withdrew is native USDC, please refer to this document.
function claimAsset(
bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProofLocalExitRoot,
bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProofRollupExitRoot,
uint256 globalIndex,
bytes32 mainnetExitRoot,
bytes32 rollupExitRoot,
uint32 originNetwork,
address originTokenAddress,
uint32 destinationNetwork,
address destinationAddress,
uint256 amount,
bytes calldata metadata
) external
Parameters
Name | Type | Description |
---|---|---|
smtProofLocalExitRoot | bytes32[32] | Smt proof to proof the leaf against the network exit root |
smtProofRollupExitRoot | bytes32[32] | Smt proof to proof the rollupLocalExitRoot against the rollups exit root |
globalIndex | uint32 | Index of the leaf |
mainnetExitRoot | bytes32 | Mainnet exit root |
rollupExitRoot | bytes32 | Rollup exit root |
originNetwork | uint32 | Origin network. 0 for assets from originating from layer 1 |
originTokenAddress | address | Origin token address, 0 address is reserved for ETH |
destinationNetwork | uint32 | Network destination. 0 for layer 1 |
destinationAddress | address | Address destination |
amount | uint256` | Amount of tokens |
metadata | bytes | Abi encoded metadata if any, empty otherwise |
ERC-20 is the technical standard for fungible tokens created using the Ethereum blockchain. A fungible token is interchangeable with another token — whereas the well-known non-fungible tokens (NFTs) are not interchangeable. You can read more information about ERC-20 here. Deploy a simple ERC-20 contract with any of the tools like Truffle, Hardhat, or Foundry. This contract is implemented based on the open-source library, which can be found at OpenZeppelin.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts@4.9.3/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor() ERC20("MyToken", "MTK") {}
}
The same bridge contract is used on both layer 1 and layer 2, so the interface definition is identical.