> For the complete documentation index, see [llms.txt](https://docs.t-rex.network/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.t-rex.network/reference/token-suite/messaging.md).

# Messaging

The token is the only author and the only recipient of an asset's cross-chain messages on the reference chain. This page lists the three pieces behind that: `TREXMessaging`, which the token inherits, the `TrustedGatewayRegistry` of the network, and the library `MessageTypesLib` that defines the wire format. The concept is in [Messaging: ERC-7786 gateways, routes and peers](/cross-chain-the-distributed-register/messaging-erc-7786-gateways-routes-and-peers.md).

### At a glance

|                 |                                                                                                                                                                          |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Source**      | `contracts/interop/TREXMessaging.sol`, `contracts/interop/TrustedGatewayRegistry.sol`, `contracts/libraries/MessageTypesLib.sol`, `contracts/libraries/WalletKeyLib.sol` |
| **Interfaces**  | `ITREXMessaging`, `ITrustedGatewayRegistry`, `ISettlementHandler`, OpenZeppelin's `IERC7786GatewaySource` and `IERC7786Recipient`                                        |
| **Deployed as** | `TREXMessaging` is part of each `Token`. The `TrustedGatewayRegistry` is one contract per network, not upgradeable                                                       |
| **Roles**       | `IDENTITY_MANAGER` of the asset for routes and peers. The platform role `INTEROP_MANAGER` for the list of trusted gateways                                               |

### Routes and peers, on the token

| Function                                       | Access             | Reverts with                                                                                                                                                                                                                                         |
| ---------------------------------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setRoute(chainType, chainReference, gateway)` | `IDENTITY_MANAGER` | `GatewayNotTrusted` unless the gateway is trusted or zero, `InvalidChainReference` for an empty reference or, on an EVM chain, one with a leading zero byte. A zero gateway closes the chain. Emits `ChainRegistered` the first time, and `RouteSet` |
| `setPeer(chainKey, peer)`                      | `IDENTITY_MANAGER` | `ChainNotRegistered`, `InvalidPeer` for an address with no account part or with trailing bytes, `PeerChainMismatch`. Emits `PeerSet`                                                                                                                 |
| `routeFor(chainKey)`                           | Anyone, read       | The gateway of a chain, or zero                                                                                                                                                                                                                      |
| `peerFor(chainKey)`                            | Anyone, read       | The peer as an ERC-7930 address. On an EVM chain with no registered peer, the token's own address on that chain                                                                                                                                      |
| `chainOf(chainKey)`                            | Anyone, read       | The `chainType` and `chainReference` behind a key                                                                                                                                                                                                    |
| `isChainOpen(chainKey)`                        | Anyone, read       | True when the chain has a route, the route is trusted at that moment, and a peer is known                                                                                                                                                            |
| `pinnedRouteFor(validationId, chainKey)`       | Anyone, read       | The gateway a validation went out through toward a chain                                                                                                                                                                                             |
| `messageReceived(gateway, receiveId)`          | Anyone, read       | Whether a gateway already delivered a `receiveId`                                                                                                                                                                                                    |
| `trustedGatewayRegistry()`                     | Anyone, read       | The registry the token reads                                                                                                                                                                                                                         |

Guide: [33 Open an asset on a satellite](/guides/cross-chain/33.-open-an-asset-on-a-satellite.md).

### Sending

Every outbound message goes through one call: `sendMessage(recipient, payload, attributes)` on the gateway of the chain, with the peer as recipient, an empty list of attributes and no value.

| Function of the token                                        | Access               | Message                                                                                                                                                    |
| ------------------------------------------------------------ | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `dispatchComplianceValidation(chainKey, validationId, body)` | The bound compliance | `COMPLIANCE_VALIDATION`. Records the gateway used (`ValidationRoutePinned`). Reverts with `SenderNotCompliance`, `ChainNotOpen`, `ValidationAlreadyRouted` |
| `dispatchMintInstruction(chainKey, body)`                    | `AGENT`              | `MINT_INSTRUCTION`. Reverts with `ChainNotOpen`                                                                                                            |
| `dispatchRecallInstruction(chainKey, body)`                  | `AGENT`              | `RECALL_INSTRUCTION`. Reverts with `ChainNotOpen`                                                                                                          |

Each emits `ProtocolMessageSent` with the `sendId` the gateway returned.

### Receiving

A gateway delivers with `receiveMessage(receiveId, sender, payload)`. The token checks, in this order:

| # | Check                                                                                                                                            | Reverts with                                                                                            |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
| 1 | The caller is trusted in the `TrustedGatewayRegistry` at that moment                                                                             | `ERC7786RecipientUnauthorizedGateway`                                                                   |
| 2 | `sender` parses as an ERC-7930 version 1 address and names a chain                                                                               | `InteroperableAddressParsingError`, `InteroperableAddressEmptyReferenceAndAddress`                      |
| 3 | `sender` is, byte for byte, the peer of that chain                                                                                               | `SenderNotPeer`                                                                                         |
| 4 | The payload decodes to a defined type, with version 1                                                                                            | `UnsupportedMessageVersion`                                                                             |
| 5 | This gateway has not delivered this `receiveId`                                                                                                  | `MessageAlreadyReceived`                                                                                |
| 6 | Settlement: the caller is the gateway the validation went out through, or the route of the chain when the token never sent that validation there | `GatewayNotPinned`, `GatewayNotRouted`                                                                  |
| 7 | Settlement: the token is not paused, and the compliance accepts the report                                                                       | `EnforcedPause`, and the errors of [Transfer validation](/reference/token-suite/transfer-validation.md) |
| 8 | Burn proof: the caller is the route of the chain, and the proof names an address to credit                                                       | `GatewayNotRouted`, `ZeroAddress`                                                                       |
| 9 | Any other type                                                                                                                                   | `MessageTypeNotInbound`                                                                                 |

On success the token emits `ProtocolMessageReceived`. When the compliance reports a replayed or unknown settlement, the token applies nothing and pauses itself. What a gateway must guarantee is in [Build an ERC-7786 gateway adapter](/build/build-an-erc-7786-gateway-adapter.md).

### `TrustedGatewayRegistry`

| Function                              | Access            | Behavior                                                                                                                                               |
| ------------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `setTrustedGateway(gateway, trusted)` | `INTEROP_MANAGER` | Adds a gateway to the list of the network, or removes it. Reverts with `ZeroAddress`. Emits `TrustedGatewaySet(address indexed gateway, bool trusted)` |
| `isTrusted(gateway)`                  | Anyone, read      | Tokens call it on every send and every delivery                                                                                                        |

Removing a gateway severs every route through it at once, for every asset, validations in flight included.

### `MessageTypesLib`

| Element                                                                                                              | Definition                                                                                                                                                     |
| -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Message`                                                                                                            | The enum of message types: `COMPLIANCE_VALIDATION` 0, `MINT_INSTRUCTION` 1, `RECALL_INSTRUCTION` 2, `SETTLEMENT_NOTIFICATION` 3, `BURN_PROOF` 4                |
| `VERSION`                                                                                                            | 1                                                                                                                                                              |
| `encode(messageType, body)`, `decode(payload)`                                                                       | The envelope: `abi.encode(messageType, VERSION, body)`. `decode` reverts with `UnsupportedMessageVersion`                                                      |
| `ComplianceValidation`                                                                                               | `(uint256 validationId, bytes from, bytes to, bytes spender, uint256 amountMin, uint256 amountMax, address token, uint64 expiry, uint64 reconciliationWindow)` |
| `SettlementNotification`                                                                                             | `(uint256 validationId, bytes from, bytes to, uint256 amount)`                                                                                                 |
| `BurnProof`                                                                                                          | `(bytes burnedWallet, uint256 amount, address nativeWallet)`                                                                                                   |
| `encodeValidation`, `decodeValidation`, `encodeSettlement`, `decodeSettlement`, `encodeBurnProof`, `decodeBurnProof` | The three encoders return the full payload, envelope included. The three decoders take a body and return the struct                                            |
| `hashValidation(validation)`                                                                                         | The ERC-712 struct hash of a validation, stored by the compliance                                                                                              |
| `chainKey(chainType, chainReference)`                                                                                | The `keccak256` of the ERC-7930 address of the chain, with an empty account                                                                                    |

The format is described field by field in [Implement T-REX Lite on a new chain](/build/implement-t-rex-lite-on-a-new-chain.md).

### `WalletKeyLib`

| Function                                 | Returns                                                                                                                                                              |
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parse(envelope)`                        | The parts of an ERC-7930 address. Reverts with `NonCanonicalInteroperableAddress` for trailing bytes or, on an EVM chain, a chain reference with a leading zero byte |
| `canonicalKey(envelope)`                 | The `keccak256` of a canonical address                                                                                                                               |
| `satelliteKey(envelope)`                 | The same, for a wallet that must be on another chain: reverts with `NotASatelliteWallet` for a wallet of the reference chain                                         |
| `walletId(envelope)`, `walletId(wallet)` | The `bytes32` key the ledger uses: an address of the reference chain padded on the left, the `keccak256` for a satellite wallet                                      |
| `isReferenceChain(envelope)`             | Whether the address is on the reference chain, and the address when it is                                                                                            |

### Events

| Event                                                                                                                 | Emitted when                                        |
| --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| `ChainRegistered(bytes32 indexed chainKey, bytes2 chainType, bytes chainReference)`                                   | First route for a chain                             |
| `RouteSet(bytes32 indexed chainKey, address indexed gateway)`, `PeerSet(bytes32 indexed chainKey, bytes peer)`        | The gateway, the peer, of a chain                   |
| `TrustedGatewayRegistrySet(address trustedGatewayRegistry)`                                                           | Once, at deployment of the token                    |
| `ValidationRoutePinned(uint256 indexed validationId, bytes32 indexed chainKey, address gateway)`                      | First dispatch of a validation to a chain           |
| `ProtocolMessageSent(MessageTypesLib.Message indexed messageType, bytes32 indexed chainKey, bytes32 sendId)`          | A message leaves                                    |
| `ProtocolMessageReceived(MessageTypesLib.Message indexed messageType, bytes32 indexed chainKey, bytes32 receiveId)`   | A message was processed                             |
| `BurnProofReceived(bytes32 indexed originChainKey, bytes burnedWallet, address indexed nativeWallet, uint256 amount)` | A burn proof arrives                                |
| `TrustedGatewaySet(address indexed gateway, bool trusted)`                                                            | On the registry: a gateway is trusted, or no longer |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.t-rex.network/reference/token-suite/messaging.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
