> ## Documentation Index
> Fetch the complete documentation index at: https://docs.layerzero.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Message Properties

> LayerZero is purpose built for lightweight message passing across multiple blockchains. To accomplish this, the protocol provides authentic and guaranteed...

LayerZero is purpose built for lightweight message passing across multiple blockchains. To accomplish this, the protocol provides authentic and guaranteed message delivery with a configurable level of trustlessness.

## Message State

Messages are sent from the User Application (UA) at source `srcUA` to the UA at the destination `dstUA`. Once the message is received by the `dstUA`, the message is considered delivered (transitioning from `INFLIGHT` to either `SUCCESS` or `STORED`)

| Message State | Cases                                                                     |
| :------------ | :------------------------------------------------------------------------ |
| **INFLIGHT**  | After a message is sent                                                   |
| **SUCCESS**   | A1: `dstUA` success OK() <br /> A2: `dstUA` fails with uncaught exception |
| **STORED**    | B1: `dstUA` fails with uncaught error / exception                         |

```solidity wrap theme={null}
// message handling at destination chain
try ILayerZeroReceiver(_dstAddress).lzReceive{gas: _gasLimit}(_srcChainId, _srcAddress, _nonce, _payload) {
    // message state becomes SUCCESS
} catch {
    // message state becomes STORED
    emit PayloadStored(_srcChainId, _srcAddress, _dstAddress, _payload);
}
```

**Case A2: `dstUA`** is expected to store the message in their contract to be retried (LayerZero will not store any successfully delivered messages). dstUA is expected to monitor and retry STORED messages on behalf of its users.

**Case B1: `dstUA`** is expected to gracefully handle all errors/exceptions when receiving a message, and any uncaught errors/exceptions (including out-of-gas) will cause the message to transition into STORED. A STORED message will block the delivery of any future message from srcUA to all dstUA on the same destination chain and can be retried until the message becomes SUCCESS. dstUA should implement a handler to transition the stored message from STORED to SUCCESS. If a bug in dstUA contract results in an unrecoverable error/exception, LayerZero provides a last-resort interface to force resume message delivery, only by the dstUA contract.

### Message Ordering

LayerZero provides ordered delivery of messages from a given sender to a destination chain, i.e. `srcUA -> dstChain`. In other words, the message order nonce is shared by all `dstUA` on the same `dstChain`. That's why a `STORED` message blocks the message pathway from `srcUA` to all `dstUA` on the same destination chain. If it isn't necessary to preserve the sequential nonce property for a particular `dstUA` the sender must add the nonce into the payload and handle it end-to-end within the UA. UAs can implement a non-blocking pattern in their contract code.

### Extensibility

#### Message Adapter Parameters

LayerZero allows UAs to add arbitrary transaction params in the `send()` function, providing a high level of flexibility and opening up opportunities for a diverse set of 3rd party plugins This is implemented as an unreserved byte array parameter to the send() function, with UAs allowed to write any additional data necessary into that parameter. We recommend that UAs leave some degree of configurability for the extra parameters to allow for feature extensions.

One great feature of `_adapterParams` is performing an Airdrop.

### Patterns

#### Non-Reentrancy

LayerZero Endpoint has a non-reentrancy guard for both the `send()` and `receive()`, respectively. In other words, both `send()` and `receive()` can not call themselves on the same chain. UAs **should not** rely on LayerZero to perform the non-reentrancy check. However, UAs can query the endpoint to see if the endpoint **`isSendingPayload()`** or **`isReceivingPayload()`** for finer-grained reentrancy control.

#### Message Chaining

UAs can call `send()` in the `receive()` calls on the same chain. Example applications for calling `send()` in the `receive()` include (e.g. Ping Pong):

* the UA at the source chain wants a message receipt (Chain A -> Chain B -> Chain A)
* the UA at the destination reroutes the message (Chain A -> Chain B -> Chain C)

```solidity wrap theme={null}
 function lzReceive(uint16 _srcChainId, bytes memory _fromAddress, uint64, /*_nonce*/ bytes memory _payload) external override {
        ...
        // message chaining
        endpoint.send{value: messageFee}(
          ...
          );
    }
```

However, the fee for sending messages on another chain is not observable onchain. UAs would need to create some fee estimate heuristics. Optionally, user apps can store the chained message and then resend them with another transaction.

#### Multi-Send

UAs can send multiple messages in one transaction at the source chain. The endpoint non-reentrancy will not block this pattern.

```solidity wrap theme={null}
function sendFirstMessage(
        uint gasAmountForDst, uint16[] calldata chainIds, bytes[] calldata dstAddresses) external payable {
    ...
    for(uint i = 0; i < chainIds.length; i++){
        endpoint.send{value: fee}(chainIds[i], dstAddresses[i], messageString, msg.sender, address(0x0), _relayerParams);
    }
}
```
