📬
Celer Inter-chain Messaging (IM)
  • Developer
    • Celer IM Overview
      • Inter-chain App Use Cases
    • Architecture Walkthrough
      • Celer IM Design Patterns
      • End-to-End Workflow
      • Fee Mechanism
      • CELR Token Utility
    • Development Guide
      • Contract Framework
      • Contract Examples
        • Hello World
        • Hello World with Token Transfer
        • In-Order Delivery
        • Batch Transfer
        • Cross-Chain Swap
        • NFT Bridge
      • dApp Safeguard
      • Message Executor
        • Integration Guide
        • Integration Guide: Advanced
      • Query IM Tx Status
    • Contract Addresses & RPC Info
  • Audit Reports
Powered by GitBook
On this page
  • Send Message
  • Receive Message
  1. Developer
  2. Development Guide

Contract Framework

PreviousDevelopment GuideNextContract Examples

Last updated 1 year ago

We provide a , which implements the common process of Celer IM. By inheriting the app framework , the cross-chain smart contract developers only need to focus on the app-specific logic.

Send Message

To send cross-chain messages, the dApp contract needs to interact with the Celer IM on the src chain.

Send a message without an associated cross-chain token transfer

The dApp contract should use the of the inherited MessageSenderApp contract to send a cross-chain message.

function sendMessage(
    address _receiver,
    uint64 _dstChainId,
    bytes memory _message,
    uint256 _fee
) internal

The message will be typed as MsgType.MessageOnly, and will be identified in Celer SGN through its messageId, which is computed as a hash of <msgType, sender, receiver, srcChainId, srcTxHash, dstChainId, message>. The caller needs to make sure of the uniqueness of the messageId. If multiple messages with the same Id are sent, only one of them will succeed at the destination chain.

Send a message with an associated cross-chain token transfer

The dApp contract should use the of the inherited MessageSenderApp contract to send messages with associated cross-chain token transfers.

function sendMessageWithTransfer(
    address _receiver,
    address _token,
    uint256 _amount,
    uint64 _dstChainId,
    uint64 _nonce,
    uint32 _maxSlippage,
    bytes memory _message,
    MsgDataTypes.BridgeSendType _bridgeSendType,
    uint256 _fee
) internal returns (bytes32) // return transferId

The message will be typed as MsgType.MessageWithTransfer, and will be identified in Celer SGN through the returned transferId

Message Fee

Receive Message

Receive a message without an associated cross-chain token transfer

function executeMessage(
    address _sender,
    uint64 _srcChainId,
    bytes calldata _message,
    address _executor
) external payable virtual override onlyMessageBus returns (ExecutionStatus) {}

Do not forget to use the onlyMessageBus modifier, as message execution functions should only be called by the MessageBus contract.

Receive a message with an associated cross-chain token transfer

// receive and execute messages at dst chain
function executeMessageWithTransfer(
    address _sender,
    address _token,
    uint256 _amount,
    uint64 _srcChainId,
    bytes calldata _message,
    address _executor
) external payable virtual override onlyMessageBus returns (ExecutionStatus) {}

If the function above got reverted for any reason. The dApp contract can optionally implement a fallback function to decide what to do with the received tokens.

// optional fallback function at dst chain
function executeMessageWithTransferFallback(
    address _sender,
    address _token,
    uint256 _amount,
    uint64 _srcChainId,
    bytes calldata _message,
    address _executor
) external payable virtual override onlyMessageBus returns (ExecutionStatus) {}

A cross-chain token transfer could fail due to bad slippage or other reasons. In this case, the Celer SGN will refund the token to the dApp contract on the source chain, which should implement a message execution function to handle the possible refund.

// handle messages with refunded token transfer at src chain
function executeMessageWithTransferRefund(
    address _token,
    uint256 _amount,
    bytes calldata _message,
    address _executor
) external payable virtual override onlyMessageBus returns (ExecutionStatus) {}ol

The could be Liquidity, PegDeposit, PegBurn, PegV2Deposit, PegV2Burn, PegV2BurnFrom.

For both function calls above, message fees are charged in the native gas token. Here is how to .

To receive cross-chain messages, the dApp contract needs to implement (some of) the message execution functions defined in the inherited .

These functions return ExecutionStatus, which could be Success, Fail, or Retry. The which calls the dApp's message execution functions will ensure that each message will be executed exactly once if the function returns Success or Fail or is reverted. If the function returns Retry, the message can be executed again later.

The dApp contract should implement the to receive a message without associated token transfer.

The dApp contract should implement the to receive a message with an associated cross-chain token transfer.

The will guarantee that the correct amount of tokens have already been received by the dApp contract before calling the dApp's message execution functions.

dApp contract framework
MessageApp.sol
MessageBus (MessageBusSender) contract
sendMessage function
sendMessageWithTransfer function
BridgeSendType
calculate and query the fee
MessageReceiverApp
MessageBus (MessageBusReceiver) contract
executeMessage interface
executeMessageWithTransfer interfaces
MessageBus contract