Stargatebridge v2 uses Taxi to combine token transfers with destination contract calls
Stargatebridge v2 enables destination contract calls through Taxi transfers that carry instructions to a compatible composer contract. That contract receives the bridged asset and handles a separate callback through LayerZero. Bus mode does not support composed messages. Token delivery and execution of the requested contract action have separate outcomes, so a completed transfer does not establish a successful destination swap.
In this guide
Composition suits an integration that needs the received funds to enter application logic. The receiving contract, message format and execution options determine that behavior. A transport mode alone cannot supply a swap implementation or its failure policy.
Key takeaway: A composer can forward the bridged token after a failed swap if its callback implements and successfully completes that fallback.
A destination swap uses a composer contract
A destination swap uses a composer contract to receive the bridge payout and interact with an external swap contract. The application supplies the swap logic through its
lzCompose
handler. The bridge transports assets and queues the callback; the composer defines the downstream operation. Support for composition therefore requires an actual receiving implementation, alongside an available transfer route.
In SendParam, the to field identifies that composer on the destination network. An application can encode a different final recipient inside composeMsg, provided its receiver understands that format. This separates the bridge payout address from the address that ultimately receives the application's output.
The payload joins application instructions with transfer context
A composed message combines application instructions with transfer context, including the source endpoint identifier, message nonce and received amount. On receipt, the v2 contract uses
OFTComposeMsgCodec
to build the message that the composer reads. The application bytes sit inside that structured payload. Decoding the entire payload directly as custom swap arguments would ignore its transfer context. The sender and receiver must agree on the custom byte format. With application binary interface (ABI) encoding, that agreement includes argument types and order. A changed format needs a matching decoder.
Bus leaves out the composed-message callback
The v2 Bus receiving path does not support composed messages.
Its payout handling has no compose payload to queue for the recipient. The Taxi path can supply that payload when the transfer includes a nonempty
composeMsg
.
oftCmd
selects the transfer mode: an empty value selects Taxi, while a nonempty value selects Bus.
Adding application bytes to a Bus request does not create Taxi's callback behavior. An integration that requires a composed destination action must use Taxi. That requirement concerns executable application instructions, independently of the destination asset.
Does token delivery prove that the destination action succeeded?
Token delivery does not prove that a destination action succeeded, because the composer executes its callback separately from the bridge payout.
During successful Taxi reception, the v2 contract pays the configured receiver and asks the LayerZero Endpoint to queue the composed message. A later
lzCompose
execution invokes the receiver's application logic. The send receipt on the source network records an earlier state. It cannot demonstrate that the downstream swap completed or that the final recipient obtained its requested asset.
If the bridge's payout attempt returns failure, v2 caches the unreceived transfer instead of queuing its composed message. Its
retryReceiveToken
path retries that payout and queues composition after a successful retry.
If the application callback reverts, it leaves the earlier token delivery intact. Tokens can remain in the composer with the queued message still available for another execution attempt.
Execution options fund the compose call
A composed transfer needs execution gas for token delivery and for the separate application callback. LayerZero's
OptionsBuilder
can encode a compose gas allowance in
SendParam.extraOptions
. Its
addExecutorLzComposeOption
method takes the compose index, gas limit and native value for that callback. The v2 receiver queues its message at index 0, so the callback option needs the matching index.
Taxi combines caller-supplied options with the enforced options for its destination pathway. Those settings affect the execution budget that the messaging quote covers. Prepare the receiver, payload and options before requesting that quote.
quoteOFT
describes the token-side amount, while
quoteSend
quotes messaging for the supplied transfer configuration. A gas-on-destination top-up and a compose execution allowance fund different uses.
The receiver must authenticate the Endpoint and bridge
The composer needs to check both the caller of
lzCompose
and the bridge contract identified by its
_from
argument. In this integration,
msg.sender
should match the destination LayerZero Endpoint. The
_from
value should match the intended destination bridge contract. The Endpoint permits applications to queue compose messages under their own sender addresses. An Endpoint call therefore does not, by itself, establish the trusted destination bridge. Executor-supplied
_extraData
also remains untrusted input. The receiver needs its own validation before using that data to influence an application action.
A swap fallback changes the asset that the recipient receives
A hypothetical composer that catches a destination swap failure can finish by forwarding the bridged token, provided that its fallback transfer succeeds. The selected route, ERC-20 token choices, recipient, minimum swap output and deadline are illustrative settings for this integration.
Under the success branch, the external swap sends its output to that recipient. Now take the branch where the swap call reverts, the fallback token transfer succeeds and the handler returns normally. The recipient receives the bridged token, although the callback completes without producing the requested swap asset.
Only the external swap's caught failure reaches this fallback. A decoding error before that call, or a reverting fallback transfer, can still abort the callback. A composer that lets the swap error propagate instead reverts its callback and retains the previously delivered token.
Pool redemption can carry the same destination instructions
The v2 pool method
redeemSend
supports composed Taxi transfers that draw on the caller's liquidity-provider tokens, commonly called LP tokens. It burns the relevant pool tokens and sends the underlying value across the selected path. That entry point requires Taxi mode.
The account needs enough matching LP tokens. The selected path also needs sufficient credit for the resulting transfer. Applicable fees and the minimum receive amount still constrain that transfer. The caller also funds the applicable messaging fee. The source account spends its pool position, while the destination contract receives the underlying asset for its configured action.
Stargatebridge: questions and answers
Can send replace sendToken in a composed Taxi integration?
send can submit a composed Taxi transfer because the v2 implementation delegates to sendToken. Both paths use SendParam for the receiver, compose payload and execution options. The wrapper returns the messaging and token receipts; sendToken also returns a ticket field. That return-value difference does not provide a different destination composition mechanism.
Who does composeFrom identify when a router submits the transfer?
composeFrom identifies the immediate caller that submitted the source transfer to the bridge. When a router makes that call, the encoded address identifies the router. It does not automatically identify the wallet that invoked the router. An application that needs an end-user identity must define how it carries and authenticates that identity within its own message design.
What unit does amountLD use inside a composed message?
amountLD records the transfer amount in the destination token's local decimal units. It is an integer token quantity, not a price, a messaging fee or the composer's entire balance. The destination bridge derives it from the transfer's shared-decimal amount before encoding the compose payload. A receiver must interpret that quantity using the destination token's decimals.
Is an OFT compose decoder enough to establish transport compatibility?
Using OFTComposeMsgCodec does not establish compatibility with the default Omnichain Fungible Token (OFT) transfer-message encoding. The v2 bridge exposes OFT interfaces, while its oftVersion function reports encoding version 0. The contract identifies that version as incompatible with the default OFT message format. Composer payload compatibility and bridge transport compatibility therefore require separate consideration.
How does minAmountLD differ from a destination swap minimum?
minAmountLD sets the minimum bridge receive value, expressed in the sending contract's local token units. A destination swap minimum instead belongs to the payload that the composer passes to its swap contract. That minimum uses the units expected by the destination swap. The bridge minimum does not enforce the swap's final output amount.
Can the same queued compose message execute twice?
The LayerZero Endpoint prevents a successfully completed compose message from executing again under the same sender, receiver, message identifier and compose index. A reverting execution also rolls back the completion marker, leaving the message available for retry. A callback that handles a swap failure and returns normally counts as completed for this queue. This protection applies to that queue entry; separate application requests can still duplicate an intended action.
Is a payable lzCompose handler enough for a native-coin payout?
A native-coin composer also needs a payable receive or fallback function that accepts the bridge's separate payout. A payable lzCompose handler does not handle that empty-calldata value transfer. The native-pool contract applies a configurable gas limit to its initial payout attempt, so the receiver's payout handler must fit that limit. Compose execution gas funds a different call.