# Sending a Message

## Introduction

To send messages across chains using any of the bridges that Lucid integrates with, a project must deploy and configure a **Message Controller** contract. The **Lucid App** deploys Message Controllers using a **Create3 factory**, ensuring that the contracts have the **same address across all deployed chains**.

To send a message from **Chain A** to **Chain B**, a Message Controller must be deployed on **both chains**.

To receive messages from a controller on another chain, the target Message Controller must have either:

* A list of **local Bridge Adapter contracts**, or
* A **Registry** contract set

If neither is configured, the controller will not be able to receive messages. Additionally, the **address of the remote controller** must be registered in each deployed Message Controller. Without this, messages cannot be sent or received.

{% hint style="info" %}
✅  The Lucid App handles all of this configuration automatically.
{% endhint %}

The following sections explain how to **manually send a message** by interacting directly with the smart contracts. This is intended for **advanced users**. We recommend using the **Lucid App** to construct messages, which can then be exported for use with **Safe**, **Snapshot’s oSnap module**, or to create a **Governor proposal**.

## Sending a Message

To send a message, call the following function on the **source chain**:

### sendMessage

```solidity
function sendMessage( RelayedMessage memory relayedMsg, uint256 destChainId, address[] memory adapters, uint256[] memory fees, bytes[] memory options ) public payable
```

| Name          | Type                  | Description                                                                                                                                 |
| ------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `relayedMsg`  | RelayedMessage Struct | An instance of RelayedMessage struct to be relayed (see below)                                                                              |
| `destChainId` | uint256               | The destination chain ID.                                                                                                                   |
| `adapters`    | address\[]            | The list of adapters addresses. Adapters provided must support the destination chain id                                                     |
| `fees`        | uint256\[]            | The list of fees in the native currency (in wei) for each adapter. It must include any protocol fee. Must have the same length as adapters. |
| `options`     | bytes\[]              | Additional abi-encoded options that are passed to the bridge adapter, specific for every bridge adapter.                                    |

This function sends a message from the current controller to a controller in another chain.

* The function is **payable** — the caller must send the total amount specified in the `fees[]` array in the native token (e.g., ETH, MATIC).
* The controller forwards the message to each specified **Bridge Adapter**, passing:
  * The corresponding **fee**
  * Any additional **adapter-specific options**

The RelayedMessage contains the following fields:

```solidity
    struct RelayedMessage {
        address[] targets; ///< The list of target addresses.
        bytes[] calldatas; ///< The list of calldata to be executed.
        bytes32 messageId; ///< The unique identifier of the message, leave blank
        uint256 threshold; ///< The threshold required for the message to be executed.
    }
```

* `targets`: Smart contract addresses to call on the destination chain
* `calldatas`: The encoded function data for each target
* `threshold`: The minimum number of bridge adapters that must deliver the message before execution

{% hint style="info" %}
Multiple contract calls can be defined and will be executed sequentially.
{% endhint %}

Only accounts with the **`MESSAGE_ORIGINATOR_ROLE`** can call this function.

After sending a message, the following event is emitted:

```solidity
event MessageCreated(bytes32 indexed messageId, uint256 chainId, uint256 threshold);
```

The `messageId` can be used to:

* Track delivery status in the controller in the destination chain or via the Lucid App
* Retry delivery with another bridge adapter if needed

### Resending a Message

If a bridge fails to deliver a message — or if the threshold is not met — an account with the **`MESSAGE_RESENDER_ROLE`** can resend the message using a different adapter.

```solidity
function resendMessage( bytes32 messageId, address[] memory adapters, uint256[] memory fees, bytes[] memory options ) public payable
```

| Name        | Type       | Description                                                                                                                                 |
| ----------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `messageId` | bytes32    | The unique identifier of the message.                                                                                                       |
| `adapters`  | address\[] | The list of adapters addresses. Adapters provided must support the destination chain id.                                                    |
| `fees`      | uint256\[] | The list of fees in the native currency (in wei) for each adapter. It must include any protocol fee. Must have the same length as adapters. |
| `options`   | bytes\[]   | Additional abi-encoded options that are passed to the bridge adapter, specific for every bridge adapter.                                    |

* Takes the original `messageId` as input
* Is **payable** — the caller must send the total amount in the `fees[]` array
* The controller resends the same message to the specified Bridge Adapters

{% hint style="info" %}
The function behavior mirrors sendMessage, forwarding the message with the appropriate fees and options.
{% endhint %}
