Skip to content

immutable/zkevm-bridge-contracts

Repository files navigation

Immutable Token Bridge

The Immutable token bridge facilitates the transfer of assets between two chains, namely Ethereum (the Root chain) and the Immutable chain (the Child chain). At present, the bridge only supports the transfer of standard ERC20 tokens originating from Ethereum, as well as native assets (ETH and IMX). Other types of assets (such as ERC721) and assets originating from the Child chain are not currently supported.

Contents

Features

Core Features

The bridge provides two key functions, deposits and withdrawals.

Deposit Assets (Root Chain → Child Chain)

When a user wishes to transfer assets from Ethereum to Immutable, they initiate a deposit. This deposit moves an asset from the Root chain to the Child chain. It does so by first transferring the user's asset to the bridge (Root chain), then minting and transferring corresponding representation tokens of that asset to the user, on the Child chain. The following types of asset deposits flows are supported:

  1. Native ETH on Ethereum → Wrapped ETH on Immutable zkEVM (ERC20 token)
  2. Wrapped ETH on Ethereum → Wrapped ETH on Immutable zkEVM (ERC20 token)
  3. ERC20 IMX on Ethereum → Native IMX on Immutable zkEVM. IMX is represented on Immutable zkEVM as the native gas token, see here
  4. Standard ERC20 tokens → Wrapped equivalents on Immutable zkEVM (ERC20 token)

Withdraw Assets (Child Chain → Root Chain)

When a user wants to transfer bridged assets from Immutable back to Ethereum, they start a withdrawal. This process moves an asset from the Child chain to the Root chain. It includes burning the user's bridged tokens on the child chain and unlocking the corresponding asset on the Root chain. Only assets that were bridged using the deposit flow described above can be withdrawn. Therefore, the available withdrawal flows are as follows:

  1. Native IMX on Immutable zkEVM → for ERC20 IMX on Ethereum.
  2. Wrapped ETH on Immutable zkEVM → Native ETH on Ethereum
  3. Wrapped IMX on Immutable zkEVM → for ERC20 IMX on Ethereum
  4. Wrapped ERC20 on Immutable zkEVM → Original ERC20 on Ethereum

Not supported: The following capabilities are not currently supported by the Immutable bridge:

  • Bridging of tokens that were originally deployed on the Child chain (i.e. ones that do not originate from the Root chain).
  • Bridging of non-standard ERC20 tokens
  • Bridging of ERC721 or other tokens standards

Security Features

The bridge employs a number of security features to mitigate the likelihood and impact of potential exploits. These are discussed further in subsections below.

IMX Deposit Limit

The total amount of IMX that can be deposited (i.e. sent from the Root chain to the Child chain), is capped at a configurable threshold. In addition to mitigating the potential impact of an exploit, this limit serves to reduce the likelihood of scenarios where the bridge might not have sufficient native IMX to process the deposits on the child chain.

Withdrawal Delays

To mitigate the impact of potential exploits, withdrawal transactions (token transfers from the Child chain to the Root chain) may be automatically delayed under certain conditions. By default, this delay is one day. The delay is implemented as a withdrawal queue, which is an array of withdrawal transactions for each user. Once the required delay has passed, a user can finalize a queued withdrawal. The conditions that trigger a withdrawal delay are as follows:

  • Specific flow rates can be set for individual tokens. These rates regulate the amount that can be withdrawn over a period of time. If a token's withdrawal rate exceeds its specific threshold, all subsequent withdrawals from the bridge are queued.
  • Any withdrawal that exceeds a token-specific amount is queued. This only affects the individual withdrawal in question and does not impact other withdrawals by the same user or others.
  • If no thresholds are defined for a given token, all withdrawals relating to that token are queued.

For further details, see the withdrawal delay mechanism section.

Emergency Pause

In the event of an emergency, the bridge can be paused to mitigate the potential impact of an incident. This suspends all user-accessible capabilities, including token mapping, deposits, and withdrawals, until the bridge is resumed. However, this doesn't restrict privileged functions accessible by accounts with certain roles. It allows administrators to perform necessary operations that can address the incident (e.g., bridge parameter changes, upgrades). The specific functions that are halted by the emergency pause mechanism for each contract are listed below:

  • Root Chain
    • RootERC20Bridge: mapToken(), deposit(), depositTo(), depositETH(), depositToETH(), onMessageReceive()
    • RootERC20BridgeFlowRate contract: finaliseQueuedWithdrawal(), finaliseQueuedWithdrawalsAggregated(), as well as all functions from RootERC20Bridge.
  • Child Chain:
    • ChildERC20Bridge: withdraw(), withdrawTo(), withdrawIMX(), withdrawIMXTo(), withdrawWIMX(), withdrawWIMXTo(),onMessageReceive()

Role-Based-Access-Control

The bridge employs fine-grained Role-Based-Access-Controls (RBAC), for privileged operations that control various parameters of the bridge. These include:

  • DEFAULT_ADMIN_ROLE: Can manage granting and revoking of roles to accounts.
  • VARIABLE_MANAGER_ROLE: Can update the cumulative IMX deposit limit.
  • RATE_MANAGER_ROLE: Can enable or disable the withdrawal queue, and configure parameter for each token related to the withdrawal queue.
  • BRIDGE_MANAGER_ROLE: Can update the bridge used by the adaptor.
  • ADAPTOR_MANAGER_ROLE: Can update the bridge adaptor.
  • TARGET_MANAGER_ROLE: Can update targeted bridge used by the adaptor (e.g. target is child chain on root adaptors).
  • GAS_SERVICE_MANAGER_ROLE: Role identifier for those who can update the gas service used by the adaptor.
  • PAUSER_ROLE: Role identifier for those who can pause functionanlity.
  • UNPAUSER_ROLE: Role identifier for those who can unpause functionality

Build and Test

Install Dependencies

$ yarn install
$ forge install

Build

$ forge build

Testing

To run unit, integration and fuzz tests execute the following command:

$ forge test --no-match-path "test/{fork,invariant}/**"

Fork Tests

The fork tests run a suite of tests against one or more deployments of the bridge. To run these tests copy .env.example file to a .env file and set the MAINNET_RPC_URL and TESTNET_RPC_URL environment variables. Set or update any other environment variables as required. Then run the following command to run the fork tests.

$ forge test --match-path "test/fork/**"

Contract Deployment

Local Deployment

To set up the contracts on two separate local networks, we need to start running the local networks, then deploy and initialize the contracts.

  1. Set up the two local networks and axelar network
yarn local:start
  1. Run the deployment of contracts
yarn local:setup
  1. Get contract addresses from ./scripts/localdev/.child.bridge.contracts.json and ./scripts/localdev/.root.bridge.contracts.json.

  2. (Optional) Run end-to-end tests

yarn local:test

Remote Deployment

When deploying these contracts on remote networks (i.e. testnet or mainnet), refer to the documentation in deployment or bootstrap.

Deployed Contract Addresses

Addresses for the core bridge contracts are listed below. For a full list of deployed contracts see deployments/ directory. ABIs for contracts can be obtained from the blockchain explorer links for each contract provided below.

Root Chain

Core Contracts

Mainnet (Ethereum) Testnet (Sepolia)
Bridge Proxy 0xBa5E35E26Ae59c7aea6F029B68c6460De2d13eB6 0x0D3C59c779Fd552C27b23F723E80246c840100F5
Bridge Implementation 0x177EaFe0f1F3359375B1728dae0530a75C83E154 0xac88a57943b5BBa1ecd931F8494cAd0B7F717590
Adaptor Proxy 0x4f49B53928A71E553bB1B0F66a5BcB54Fd4E8932 0x6328Ac88ba8D466a0F551FC7C42C61d1aC7f92ab
Adaptor Implementation 0xE2E91C1Ae2873720C3b975a8034e887A35323345 0xe9ec55e1fC90AB69B2Fb4C029d24a4622B94042e

Token Addresses

Mainnet (Ethereum) Testnet (Sepolia)
Wrapped ETH 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 0x7b79995e5f793a07bc00c21412e50ecae098e7f9
IMX 0xf57e7e7c23978c3caec3c3548e3d615c346e79ff 0xe2629e08f4125d14e446660028bd98ee60ee69f2
USDC 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 0x40b87d235A5B010a20A241F15797C9debf1ecd01

Child Chain

Core Contracts

Mainnet Testnet
Bridge Proxy 0xBa5E35E26Ae59c7aea6F029B68c6460De2d13eB6 0x0D3C59c779Fd552C27b23F723E80246c840100F5
Bridge Implementation 0xb4c3597e6b090A2f6117780cEd103FB16B071A84 0xA554Cf58b9524d43F1dee2fE1b0C928f18A93FE9
Adaptor Proxy 0x4f49B53928A71E553bB1B0F66a5BcB54Fd4E8932 0x6328Ac88ba8D466a0F551FC7C42C61d1aC7f92ab
Adaptor Implementation 0x1d49c44dc4BbDE68D8D51a9C5732f3a24e48EFA6 0xac88a57943b5BBa1ecd931F8494cAd0B7F717590

Token Addresses

Mainnet Testnet
Wrapped ETH 0x52a6c53869ce09a731cd772f245b97a4401d3348 0xe9E96d1aad82562b7588F03f49aD34186f996478
Wrapped IMX 0x3a0c2ba54d6cbd3121f01b96dfd20e99d1696c9d 0x1CcCa691501174B4A623CeDA58cC8f1a76dc3439
USDC 0x6de8aCC0D406837030CE4dd28e7c08C5a96a30d2 0x3B2d8A1931736Fc321C24864BceEe981B11c3c57
USDT 0x68bcc7F1190AF20e7b572BCfb431c3Ac10A936Ab TBA
Wrapped BTC 0x235F9A2Dc29E51cE7D103bcC5Dfb4F5c9c3371De TBA
Gods Unchained (GODS) 0xE0e0981D19eF2E0a57Cc48CA60D9454eD2D53fEB TBA
Guild of Guardians (GOG) 0xb00ed913aAFf8280C17BfF33CcE82fE6D79e85e8 TBA

Flow Rate Parameters

The flow rate parameters configured for assets can be queried from the L1 bridge contract using a block explorer (mainnet, testnet). The flowRateBuckets() function provides the bucket capacity and refill rate, while the largeTransferThreshold() function provides the withdrawal size threshold configured for a token. The L1 address of the token to query parameters for needs to be provided as input to both functions. If flow rate parameters have not been configured for a token, these functions will return zero values.

Manual Bridging Guide

The process to manually bridge funds from Ethereum to Immutable zkEVM by directly interacting with the bridge contracts is documented here. However, the recommended method for bridging to and from the Immutable zkEVM is to use the Immutable Toolkit user interface.

Audits

The Immutable token bridge has been audited by Trail of Bits. The audit report can be found here.