Lucid
  • USING LUCID
    • Welcome to Lucid
    • Homepage
    • Explore Page
    • Organisation Summary Page
    • Sidebar Navigation
  • Organisation Creation Page
  • Creating an Organisation
    • 1. Setup Organisation Details
    • 2. Module Selection
    • 3. Module Configuration
    • 4. Safe and Protocol Upgrades Configuration
    • 5. Governor Configuration
    • 6. Veto and Multi-Bridge Configuration
    • 7. Token Configuration
    • 8. Asset Transfer Portals Configuration
    • 9. Review and Deploy Organisation
    • 10. Lucid Post-Deployment Integration
  • Editing an Organisation
  • Modules and integrations
    • Multi-Bridge
      • Multi-Bridge Asset Transfers
      • Multi-Bridge Message and Asset Transfers
      • Resend Transaction
    • Bridge Portals
    • Vested Emission Offerings (VEOs)
      • VEO Purchase Flow
      • VEO Creation Flow
      • VEO Removal Flow
      • Claiming Vested Tokens
    • Wizard | Protocol Upgrades
  • Developer Reference
    • VEOs
      • Vesting Options
      • Price Models
      • Debt Buffer
      • Deposit Interval
    • Message Bridging
      • Sending a Message
      • Message Execution
      • Admin Functions
    • Asset Bridging
      • Bridging Assets
      • Admin Functions
    • Adapters
      • Axelar Adapter
      • CCIP Adapter
      • Connext Adapter
      • Hyperlane Adapter
      • LayerZero Adapter
      • Polymer Adapter
      • Wormhole Adapter
    • Deployed Contracts
      • Multibridge Contracts
      • VEO Contracts
  • API Reference
  • RESOURCES
    • About
    • Fees
      • Lucid Pricing and Fee Structure
      • Fee Estimates for Bridges
    • Frequently Asked Questions
    • Key Terms and Explanations
    • Contact
Powered by GitBook
On this page
  • Introduction
  • Bridging Tokens
  • Using mint/burn limits - Single Bridge
  • burnAndBridge
  • resendTransfer
  • Without mint/burn limits - Multiple Bridges
  • resendTransferMulti
  • Multi-Bridge fee
  • Token Minting
  1. Developer Reference
  2. Asset Bridging

Bridging Assets

Introduction

To bridge tokens from Chain A to Chain B, an Asset Controller contract must be deployed on both chains.

To successfully bridge tokens from a controller on a source chain, ensure that:

  • The selected bridge adapter is whitelisted by an admin.

  • The adapter has sufficient mint/burn limits (unless bridging without limits).

The following sections describe how to manually bridge tokens by interacting directly with the smart contracts. This is intended for advanced users. It is recommended to use the Lucid App to bridge tokens or to construct/export transactions for execution via Safe, Snapshot’s oSnap module, or a Governor proposal.

Bridging Tokens

Using mint/burn limits - Single Bridge

To bridge tokens using a single whitelisted bridge adapter (with mint/burn limits), call the following function on the source chain:

burnAndBridge

  • Burns tokens on the source chain

  • Sends a mint message to the destination chain via the selected bridge adapter

  • msg.value must contain the bridge adapter fee

  • The token allowance must be approved prior to calling this function

function burnAndBridge( address recipient, uint256 amount, bool unwrap, uint256 destChainId, address bridgeAdapter, bytes memory bridgeOptions ) public payable;
Name
Type
Description

recipient

address

The address of the recipient. Could be the same as msg.sender.

amount

uint256

The amount of the asset to mint.

unwrap

bool

Whether to unwrap the native asset using the lockbox. Lockbox must be set in the destination chain, holding enough liquidity

destChainId

uint256

The destination chain ID.

bridgeAdapter

address

The address of the bridge adapter.

bridgeOptions

bytes

Additional params to be used by the adapter.

If the selected bridge adapter is not whitelisted, or if it does not have sufficient burn limits, the transaction will revert. Any account holding the token managed by the Asset Controller can initiate a transfer.

The following event is emitted after a transfer has been sent:

event TransferCreated(bytes32 transferId, uint256 destChainId, uint256 threshold, address sender, address recipient, uint256 amount, bool unwrap);

The transferId can be used to:

  • Resend the transfer using another adapter

  • Track delivery status on the destination chain

resendTransfer

If a bridge fails to deliver a transfer to the destination chain, anyone can call resendTransfer, specifying the transferId and a different whitelisted adapter.

  • No new tokens will be burned

  • The original bridge message is resent using the new adapter

  • The burn amount is deducted from the new adapter’s burn limit

  • The function is payable, and msg.value must contain the new adapter’s fee

function resendTransfer(bytes32 transferId, address adapter, bytes memory options) public payable;
Name
Type
Description

transferId

bytes32

The unique identifier of the message.

adapters

address

The address of the bridge adapter.

options

bytes[]

Additional abi-encoded options that are passed to the bridge adapter, specific for the bridge adapter.

Without mint/burn limits - Multiple Bridges

For transfers that exceed a single adapter’s limit, you can use multiple bridge adapters without limits by calling burnAndBridgeMulti() This function:

  • Burns tokens on the source chain

  • Sends the mint message through multiple whitelisted adapters

  • Requires the addresses of adapters that have been pre-approved for use without limits

  • msg.value must include any multi-bridge fees

  • The token allowance must be set before calling this function.

To determine:

  • The minimum number of adapters required for minting:

function minBridges() public view returns (uint256);

To determine whether a specific adapter is approved for unlimited bridging:

function multiBridgeAdapters(address adapter) public view returns (bool);

To send a transfer, call the following function:

function burnAndBridgeMulti( address recipient, uint256 amount, bool unwrap, uint256 destChainId, address[] memory adapters, uint256[] memory fees, bytes[] memory options ) public payable
Name
Type
Description

recipient

address

The address of the recipient. Could be the same as msg.sender.

amount

uint256

The amount of the asset to mint.

unwrap

bool

Whether to unwrap the native asset using the lockbox. Lockbox must be set in the destination chain, holding enough liquidity

destChainId

uint256

The destination chain ID.

adapters

address[]

The address of the bridge adapter.

fees

bytes[]

The fees to be paid to the bridge adapters.

bridgeOptions

bytes[]

Additional params to be used by the adapter.

A token allowance must be given before calling this function, which should include the multi-bridge fee, if any.

If the bridgeAdapter that was selected is not whitelisted, or the burn limits are not enough, then the transaction will revert.

resendTransferMulti

If delivery fails in a multi-bridge setup, the transfer can be resent using another whitelisted adapter by calling resendTransferMulti().

  • Works similarly to resendTransfer

  • No additional tokens are burned

  • The message is simply resent using the new adapter

function resendTransferMulti(bytes32 transferId, address[] memory adapters, uint256[] memory fees, bytes[] memory options) public payable;
Name
Type
Description

transferId

bytes32

The unique identifier of the message.

adapters

address[]

The address of the bridge adapter.

fees

uint256[]

The fees to be paid to the bridge adapters.

options

bytes[]

Additional abi-encoded options that are passed to the bridge adapter, specific for the bridge adapter.

Multi-Bridge fee

When bridging without mint/burn limits using multiple adapters, a fixed 0.3% fee is applied to the token amount being transferred.

To get a fee quote, call the following function on the FeeCollector contract (on the source chain), passing the transfer amount.

function quote(uint256 amount) public view returns (uint256 fee);

Token Minting

Once the message is delivered to the destination Asset Controller by the bridge adapters, the transfer must be executed.

Lucid will automatically execute the transfer once it becomes eligible. However, anyone can manually execute it by calling the following function and passing the transfer ID:

function execute(bytes32 messageId) public;

This function can be called by any account.

PreviousAsset BridgingNextAdmin Functions

Last updated 1 month ago