Executor options & gas
Every quoteSend*, send*, quoteRestore, and restoreFailedMessage call takes an options byte string that tells the LayerZero executor how much destination gas to buy. Omnisea uses standard type-3 options with a single executor lzReceive option.
Encoding
0x0003 uint16 options type (3)
01 uint8 worker id (1 = executor)
0021 uint16 option length (33 = 1 + 16 + 16)
01 uint8 option type (1 = lzReceive)
<gas> uint128 destination execution gas
<value> uint128 destination msg.value (0 for token transfers)Reference implementations:
import { concatHex, numberToHex, type Hex } from "viem";
export function lzReceiveOptions(gas: bigint, value = 0n): Hex {
return concatHex([
"0x000301002101",
numberToHex(gas, { size: 16 }),
numberToHex(value, { size: 16 }),
]);
}import { OptionsBuilder } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol";
bytes memory options = OptionsBuilder.newOptions().addExecutorLzReceiveOption(400000, 0);Gas floors
The bridge validates the lzReceive gas inside your options at send/restore time and reverts with InsufficientLayerZeroGas(provided, required) if it is below the floor for the transfer type:
| Situation | Floor | Bridge getter |
|---|---|---|
| Transfer to a chain where the representation exists (or to the home chain) | 400,000 | minTransferGas() |
| Restore to the source chain | 400,000 | minTransferGas() |
First transfer - representation must be deployed (isFirstTransfer = true) | 500,000 | minCreationGas() |
These floors are validation minimums, not recommendations for every route.
Route guidance
| Destination | Recommended lzReceive gas |
|---|---|
| Base, Arbitrum, Polygon, BNB Chain, Optimism | 400,000 transfer / 500,000 creation |
| Tempo | 1,500,000 for both, until route-specific measurements lower it |
Unused executor gas is not refunded to you, so don't massively overshoot - but undershooting causes a destination execution failure that must be retried or restored. When in doubt, round up.
Hook gas
If your transfer carries a hook, the hook's gasLimit executes within the same lzReceive budget. Buy transfer floor + hook gasLimit (or creation floor + hook gasLimit for first transfers); the bridge enforces this combined minimum at send time.
Matching quote and send
The options bytes are part of the priced message. Use byte-identical options in quoteSend* and send* - changing gas between quote and send changes the LayerZero fee and trips the exact-fee check.