This project implements a cross-chain token bridge system for the RLC token using LayerZero's OFT (Omnichain Fungible Token) protocol. It enables seamless token transfers between multiple blockchains, initially supporting Ethereum and Arbitrum mainnets.
The system consists of three main components that work together to enable cross-chain RLC transfers:
-
RLCLiquidityUnifier (Ethereum Mainnet only): A liquidity management contract that acts as an intermediary between the original RLC token and supported bridges. It enables the locking and unlocking of RLC tokens on Ethereum, and implements the ERC-7802 interface to ensure seamless integration with various bridge contracts, while centralizing liquidity on their behalf.
-
IexecLayerZeroBridge: A LayerZero OFT bridge contract that handles cross-chain messaging and token transfers. This contract has dual deployment modes based on the chain:
- Ethereum Mainnet Mode (
APPROVAL_REQUIRED = true
): Interfaces with RLCLiquidityUnifier to lock/unlock original RLC tokens - Non-Ethereum Mode (
APPROVAL_REQUIRED = false
): Directly mints/burns RLCCrosschainToken
- Ethereum Mainnet Mode (
-
RLCCrosschainToken: An upgradeable ERC20 token that implements the ERC-7802 bridgeable token standard. This token can be minted and burned by authorized bridge contracts and is deployed on Non-Mainnet chains.
The bridge system uses a dual-mode architecture where the same IexecLayerZeroBridge
contract behaves differently based on deployment configuration:
- Configuration:
APPROVAL_REQUIRED = true
- BRIDGEABLE_TOKEN: Points to
RLCLiquidityUnifier
contract - Mechanism: Lock/unlock original RLC tokens
- Components:
- Original RLC Token (existing ERC-20)
RLCLiquidityUnifier
(ERC-7802 wrapper/adapter)IexecLayerZeroBridge
(LayerZero bridge in Ethereum mode)
- Configuration:
APPROVAL_REQUIRED = false
- BRIDGEABLE_TOKEN: Points to
RLCCrosschainToken
contract - Mechanism: Mint/burn bridgeable tokens
- Components:
RLCCrosschainToken
(ERC-7802 bridgeable token)IexecLayerZeroBridge
(LayerZero bridge in non-Ethereum mode)
- ERC-7802 Compatibility: Implement the ERC-7802 standard as a future-proof architecture for bridge compatibility
- Dual-Mode Bridge: Single bridge contract with different behaviors for Ethereum Mainnet vs. non-Mainnet chains
- Upgradeable Contracts: UUPS proxy pattern for safe upgrades across all components
- Dual-Pause Emergency System: Granular control over bridge operations with complete and send-only pause modes
- Multi-Chain Support: Designed to extend to any LayerZero-supported chain
- Original Token Preservation: Maintains the original RLC token on Ethereum through liquidity management
- Approval Optimization: Smart approval handling for UI compatibility (e.g., Stargate)
The bridge system leverages modern token standards to enable secure cross-chain transfers:
- ERC-7802 Bridgeable Token Standard: A new standard that defines interfaces for tokens that can be minted and burned by authorized bridge contracts
- LayerZero OFT V2: Omnichain Fungible Token protocol for cross-chain messaging and token transfers
- OpenZeppelin UUPS Proxy: Upgradeable proxy pattern for contract evolution while maintaining state
Currently deployed on:
- Ethereum Mainnet
- Arbitrum One
The architecture is designed to support additional networks in the future with minimal changes.
- Foundry for contract compilation and deployment
- Ethereum wallet with ETH and Arbitrum ETH for gas
- RLC tokens for bridge testing
- LCOV for coverage report generation (install via
brew install lcov
on macOS)
-
Clone the repository
git clone https://github.com/iExecBlockchainComputing/rlc-multichain.git cd rlc-multichain
-
Install dependencies
forge install
-
Create a
.env
filecp .env.template .env # and edit .env content
Note: To run scripts, you must save a wallet in the Foundry keystore. Use the following command to import a wallet with a raw private key:
cast wallet import --private-key <RAW_PRIVATE_KEY> <ACCOUNT_NAME>
Alternatively, you can use a mnemonic by specifying the --mnemonic-path
option. Remember the <ACCOUNT_NAME>
you choose, and set it in your .env
file under the ACCOUNT
field.
The core contracts of the multichain bridge system:
- RLCCrosschainToken.sol - Bridgeable ERC20 token implementing ERC-7802 standard
- RLCLiquidityUnifier.sol - Liquidity management for original RLC tokens on Ethereum (implements ERC-7802 standard as well).
- IexecLayerZeroBridge.sol - LayerZero OFT bridge for cross-chain transfers
A. To send RLC tokens from Ethereum Sepolia to Arbitrum Sepolia:
make send-tokens-to-arbitrum-sepolia
This will:
- Approve IexecLayerZeroBridge to spend your original RLC tokens
- IexecLayerZeroBridge transfers RLC tokens directly to RLCLiquidityUnifier (bypassing crosschainBurn for UI compatibility)
- RLCLiquidityUnifier receives and locks the original RLC tokens
- IexecLayerZeroBridge sends a LayerZero message to the destination chain
- Destination chain's IexecLayerZeroBridge receives the message and mints RLCCrosschainToken
B. To send RLC tokens from Arbitrum Sepolia back to Ethereum Sepolia:
make send-tokens-to-sepolia
This will:
- Burn RLCCrosschainToken tokens on Arbitrum
- Send a cross-chain message via LayerZero to Ethereum
- Release the original RLC tokens from the RLCLiquidityUnifier on Ethereum
To generate and view the coverage report, run:
make generate-coverage
-
Start a local Anvil fork of Ethereum:
make fork-ethereum
-
Start a local fork of Arbitrum:
make fork-arbitrum
-
Deploy all contracts:
make deploy-on-anvil
# deploy-on-testnets is also available.
make deploy-on-mainnets
All core contracts (RLCCrosschainToken, RLCLiquidityUnifier, and IexecLayerZeroBridge) are implemented using the UUPS pattern, allowing for seamless contract upgrades while maintaining the same proxy address.
- UUPS Proxies: Both contracts use OpenZeppelin's UUPS proxy pattern
- Upgrade Authorization: Only the contract owner can authorize upgrades
- State Preservation: Contract state is preserved across upgrades
- Initialization: New contract versions can include initialization logic for new features
Test upgrades locally before deploying to live networks:
# Test upgrade process on local forks
make upgrade-on-anvil
Execute upgrades on live networks:
make upgrade-on-mainnets
- Storage Layout Protection: Prevents storage slot conflicts between versions
- Constructor Validation: Ensures new implementations have compatible constructors
- Manual Testing: Always test upgrades thoroughly on staging environments before deploying to mainnet
The bridge operates using different mechanisms depending on the source chain:
Ethereum β Other Chains:
- User approves IexecLayerZeroBridge to spend original RLC tokens
- IexecLayerZeroBridge transfers RLC tokens directly to RLCLiquidityUnifier (bypassing crosschainBurn for UI compatibility)
- RLCLiquidityUnifier receives and locks the original RLC tokens
- IexecLayerZeroBridge sends a LayerZero message to the destination chain
- Destination chain's IexecLayerZeroBridge receives the message and mints RLCCrosschainToken
Other Chains β Ethereum:
- User initiates transfer from RLCCrosschainToken
- Source chain's IexecLayerZeroBridge burns the RLCCrosschainToken
- LayerZero delivers a message to Ethereum's IexecLayerZeroBridge
- Ethereum's RLCLiquidityUnifier releases the original RLC tokens to the recipient
Chain-to-Chain (Non-Ethereum):
- Source chain burns RLCCrosschainToken
- LayerZero message triggers minting of RLCCrosschainToken on destination chain
This design ensures the total supply across all chains remains constant while preserving the original RLC token on Ethereum.
The bridge system uses OpenZeppelin's role-based access control with the following roles:
- DEFAULT_ADMIN_ROLE: Supreme administrator with ultimate control over all contracts and role management
- UPGRADER_ROLE: Authorized to upgrade contract implementations via UUPS proxy pattern
- PAUSER_ROLE: Emergency response role that can pause/unpause bridge operations
- TOKEN_BRIDGE_ROLE: Authorized bridge contracts that can mint/burn tokens for cross-chain operations
The IexecLayerZeroBridge implements a sophisticated dual-pause emergency system designed to handle different types of security incidents while minimizing user impact.
Use Case: Critical security incidents requiring immediate complete shutdown
- Blocks: β All bridge operations (inbound and outbound transfers)
- Allows: β Admin functions, view functions
- Emergency: Maximum protection - complete bridge shutdown
Use Case: Destination chain issues, or controlled maintenance
- Blocks: β Outbound transfers only (users can't initiate send requests)
- Allows: β Inbound transfers (users can still receive tokens when the request is initiated before the pause)
- Benefit: Allows completion of already triggered transfers while preventing new ones
Contracts are automatically verified on block explorers during deployment:
# Deploys and verifies contracts on mainnet
make deploy-on-mainnets
# Upgrades and verifies contracts on mainnet
make upgrade-on-mainnets
The verification is handled by Foundry's built-in --verify
flag, which submits the source code and constructor arguments to the respective block explorers (Etherscan, Arbiscan, etc.).
LayerZero transactions require fees to cover:
- Gas on the source chain
- Gas on the destination chain (prepaid)
- LayerZero relayer fees
The scripts automatically calculate these fees and include them in the transaction.
- ERC-7802: Crosschain Token Interface - The crosschain token standard used by bridgeable tokens
- LayerZero OFT V2 Protocol
- OpenZeppelin UUPS Proxy Pattern
- OpenZeppelin Upgrade Safety
- Foundry Documentation
- Forge Coverage
- iExec Platform Documentation
- Use an enterprise RPC URL for
secrets.SEPOLIA_RPC_URL
in Github environmentci
. - Add git pre-commit hook to format code locally.
- Testing Documentation