# Message Bridging

## Introduction

Projects can send messages across chains by deploying their own **Message Controllers** on each chain where they want to send or receive messages, using **Lucid**. These controller contracts are deployed and managed exclusively by the project; Lucid has no control over them.

Message Controllers are **bridge-agnostic** — they use [**Adapter**](/developer-reference/adapters.md)  contracts to send and receive messages across chains via one or more bridges. As Lucid adds support for new bridges, your existing Controllers automatically gain access to new ecosystems — without requiring any contract changes (if configured that way).

Message Controller contracts also incorporate several security features, such as:

* Whitelisted message originators
* A consensus mechanism for received messages
* Timelock and veto functionality before message execution
* Pausability
* Among others

## Security model on message receipt

When a message is received by a Message Controller on the destination chain, the sender (i.e., `msg.sender`) must be verified — only a **Bridge Adapter** is allowed to call the `receiveMessage` function and register a message.

There are two ways for projects to specify which [Bridge Adapter](/developer-reference/adapters.md) contracts are allowed to call this function:

#### Specify Registry

The **Registry** is a contract deployed and maintained by Lucid on every chain. It serves two primary purposes:

* It acts as a registry of local adapters on the same chain.
* It aggregates available chains and adapters accessible from the current chain.

Message Controllers can be configured to use a Registry to validate whether a calling contract is a local bridge adapter. This is a simple option for projects that want to accept messages from any Bridge Adapter deployed by Lucid.

#### Specify local Adapters

For a more advanced setup, projects can whitelist specific Bridge Adapters they trust to deliver messages to the Controller contracts. An account with the **Admin Role** (see below) can set and update the local adapters of the Controller contract at any time.

## Roles and Permissions

Message Controllers utilize an access control system with distinct roles. This ensures that only authorized accounts can perform specific actions within the contract, enhancing overall security.

#### **Admin Role (DEFAULT\_ADMIN\_ROLE)**

This is the highest authority within the contract. Accounts with this role can grant or revoke any role — including the admin role itself. Admins have the following privileges:

* Grant or revoke the **Message Originator** role
* Pause or unpause the contract (i.e., temporarily stop sending, resending, or executing received messages)
* Update the **timelock delay** for message execution
* Update the **vetoer address**, which can cancel message execution while it's in the timelock period
* Add or remove **Message Controller contract addresses** on other chains — enabling or disabling cross-chain messaging with those chains
* Update the **local Registry address**
* Update the list of **local Adapters**

{% hint style="info" %}
For detailed instructions on how to call each function, please refer to the relevant documentation [section](/developer-reference/message-bridging/admin-functions.md).
{% endhint %}

#### **Message Originator Role (MESSAGE\_ORIGINATOR\_ROLE)**

Accounts with this role can initiate the sending of messages from the Message Controller, which are then relayed to other chains.

{% hint style="info" %}
When a Message Controller is deployed using the Lucid App, a **Pausable** role is automatically assigned to [**Hypernative**](https://www.hypernative.io/), — Lucid’s on-chain smart contract monitoring partner. Hypernative is responsible for pausing contracts in case of detected malicious activity or potential hacks.
{% endhint %}

### **Vetoer**

An account with the **Vetoer** role can block the execution of a received message during the timelock period. Only **one vetoer** can exist per Message Controller contract per chain.

### Upgradeability

Message Controller contracts are designed to be upgradeable using **OpenZeppelin’s Proxy Upgrade pattern**. This enables upgrades to the contract logic without compromising its stored state.

The initial implementation contract is created and deployed by Lucid. However, the **Proxy Admin** — set and controlled by the Project — has full authority to upgrade the contract to newer versions as they are released by Lucid in the future.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.lucidlabs.fi/developer-reference/message-bridging.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
