| Message Pattern | Description |
|---|---|
| Composed OFT | a composed call made after the OFT delivers the token transfer |
| OFT Alt | a variant of the OFT standard that supports EndpointV2Alt for paying in an alternative ERC20 token |
Composed OFT
A composed message refers to an OApp that invokes the LayerZero Endpoint methodsendCompose to deliver a composed call to another contract on the destination chain via lzCompose.
Because OFT inherits the base OApp implementation, you can also send composed messages within your OFT receive logic.
Composing an OFT
The OFT Standard comes pre-packaged with methods for delivering composed calls to the destination OFT contract for handling.-
Source OFT: The Source OFT specifies in the
sendcall a composed message inbytesfor deliveringto. You can think of this the same as how_lzSendsends arbitrary bytes to a destination, which the destination contract uses in the_lzReceivebusiness logic. -
Destination OFT(s): When the send call is received by the destination OFT, the internal
_lzReceivefunction inOFTCore.solhandles the delivery of tokens along with the composed call. -
Composed Receiver(s): the contract interface implementing business logic to handle receiving a composed message via
lzCompose.
Sending Token
When sending a token from source to destination, the caller has the option to specify an additionalcomposeMsg in bytes.
Composed Message Execution Options
You will need to pass both anlzReceiveOption and lzComposeOption as either your enforced or extra options for this call to succeed.
You can decide both the _gas and msg.value that should be used for the composed call(s), depending on the type and quantity of messages you intend to send.
Your configured Executor will use the _options provided in the original _lzSend call to determine the gas limit and amount of msg.value to include per message _index:
21000 wei, but other chains may have lower or higher opcode costs, or entirely different gas mechanisms.
You can read more about generating _options and the role of _index in Message Execution Options.
Sending Compose
By default, the destination OFT’s_lzReceive method will check if the message is composed, and then deliver those arbitrary bytes to the specified toAddress:
sendCompose comments, the base OFT implementation only allows for 1 composed message per lzReceive call.
To add additional composed calls, you will need to override the _lzReceive method and add custom composed logic.
Receiving Compose
The receiving address of the crosschain token transfer will need to implement custom business logic to handle the composed message, for example, consider this mock contract that swaps an inbound OFT for an ERC20:OFTComposeMsgCodec to extract the composeMsg and _amountLD from the overall message, before decoding it.
Further Reading
- Review the
OFT.solimplementation and unit tests for handling composed messages.
OFT Alt
When deploying OApps, you might encounter scenarios where the native gas token cannot be used to pay the LayerZero Endpoint to send a message. These Endpoints have been deployed using theEndpointV2Alt.sol contract, so that they can use an alternative ERC20 token on the same chain to pay for crosschain messages. Because these Endpoints do not use the native gas token, some changes must be made to your OApp contracts (including OFT).
For example, the OFTAlt.sol demonstrates this implementation fully, which you can reference when modifying your other OApp-based contracts:
Contract Changes
At a high level, only a few changes to your OApp are needed to interact with theEndpointV2Alt.sol contract:
Pass OpenZeppelin Ownable
Using SafeERC20
Error Handling
LzAltTokenUnavailable which is used to handle cases where the native ERC20 token for fee payment is not set in the EndpointV2Alt contract.
Override _payNative
_payNative function to handle paying using an ERC20 token. This function checks if the ERC20 token address is set (nativeErc20), reverts if not, and performs a safeTransferFrom to transfer the fee from the sender to the endpoint.
This ensures that the contract can handle fees in the specified ERC20 token by the EndpointV2Alt.
Override _lzSend
_payNative, you should also override _lzSend to handle the ERC20 token fee.
Because
_lzSend now uses an ERC20 token as payment, you must now approve the OFT as a spender of your ERC20 token.