Composability
Stargate is a fully composable liquidity transport protocol meaning it supports additional compose logic on destination chain. You can use this feature to perform calls to external smart contracts.
Composable methods
The following methods are composable:
IStargate.sendToken()IStargate.send()IStargatePool.redeemSend()
Architecture
Send
To take advantage of compose feature you need to modify SendParam struct passed to IStargate.sendToken().
First, you need to change:
bytes calldata composeMsgMake sure it is non-zero bytes. You would usually use this field with ABI encode and decode to pass your application-specific input that contracts along the way understand.
You also need to pass additional gas for the compose call. You need to set this value to the amount of gas your lzCompose function in the compose receiver consumes.
For "taxi" you can use typical LayerZero's OptionsBuilder. Make sure to pass it as SendParam.extraOptions:
bytes memory extraOptions = _composeMsg.length > 0
? OptionsBuilder.newOptions().addExecutorLzComposeOption(0, 200_000, 0) // compose gas limit
: bytes("");Receive
Stargate will attempt to call LayerZero's Endpoint.sendCompose() on the destination chain when it distributes tokens to receiver.
Here's how the Stargate internal call looks like:
where composeMsg is:
and receiver is an address that was supposed to receive tokens on the destination chain.
Stargate is using standard OFTComposeMsgCodec for encoding a composed message. This means that when you receive this message in the composer it will be encoded using the aforementioned codec.
To access your custom application specific message (the one you passed as SendParams.composeMsg) you have to call:
Implementing "composer receiver"
To receive a composed message from Stargate and perform additional logic the receiver address has to be a smart contract implementing ILayerZeroComposer. LayerZero's Endpoint defaults to calling the lzCompose() function on the receiver contract address.
Here's how an example receiver can look like:
This very simple example above will emit ComposeAcknowledged each time a composed call is received and increment the acknowledgedCount by 1. A more advanced contract example is detailed below.
External contract interaction example
Below you can find a Solidity example of doing a swap through external smart contract with a composed message, using the taxi method.
This example illustrates the process of swapping Token A on the source chain for Token B on the destination chain. Following this, it demonstrates how to swap Token B for Token C on the destination chain by leveraging an external smart contract through a composed call.
Send
Preparing arguments:
Sending transaction:
Receive
On the receive side we will use dummy IMockAMM interface to demonstrate how the external call to the swap function can look like:
As shown above, lzCompose() will attempt to swap token B received from Stargate into token C and transfer it to the receiver address. If the swap fails in the try/catch clause it will send the original token B to the receiver address instead.
Last updated
