Documentation menu

Fees

A transfer's total cost has exactly two components:

totalFee = LayerZero messaging fee + fixed protocol fee
  • LayerZero messaging fee - paid to LayerZero for verification (DVNs) and destination execution (executor gas you buy via options). This part is dynamic and depends on the route, the gas you request, and current prices.
  • Fixed protocol fee - a flat fee collected by the bridge. There is no percentage fee: the dynamic protocol fee component is 0%.

Current defaults:

ParameterValueWhere it applies
fixedProtocolFee25000000000000 wei (0.000025 ETH)Standard chains where the LayerZero endpoint is paid in native gas token
fixedFeeTokenProtocolFee100000 units (0.10 LZD at 6 decimals)EndpointV2Alt chains paid in a fee token - currently Tempo

Both values are public on the bridge (fixedProtocolFee(), fixedFeeTokenProtocolFee()) and adjustable only by the owner, with FixedProtocolFeeChanged / FixedFeeTokenProtocolFeeChanged events on every change.

Quoting

Always quote immediately before sending. The quote functions return one number - the total the bridge will require, protocol fee included:

uint256 totalFee = bridge.quoteSendOriginal(dstEid, token, amount, recipient, isFirstTransfer, options);

Use the same isFirstTransfer flag and the same options bytes for the quote and the send, otherwise the amounts will not match.

Exact-fee enforcement

The bridge requires the paid fee to exactly equal its own quote at execution time - not at least, exactly:

  • On standard chains: msg.value == LayerZero fee + fixedProtocolFee, otherwise the call reverts with Invalid fee.
  • Overpayment is rejected, not refunded - this keeps the contract free of refund logic and dust.

Because the LayerZero fee can move between your quote and your send, production integrations should re-quote and retry on an Invalid fee revert (the Omnisea web app retries up to 3 times).

Fee-token chains (Tempo)

On chains using LayerZero's EndpointV2Alt - detected at runtime via endpoint.nativeToken() != address(0) - fees are paid in an ERC-20 fee token instead of msg.value:

  1. endpointNativeToken() returns the fee token address (LZD on Tempo).
  2. The quote is denominated in the fee token's smallest units and includes fixedFeeTokenProtocolFee.
  3. The sender must approve the bridge for the quoted total and send with msg.value = 0. Any non-zero msg.value is rejected by the endpoint.

See Sending from Tempo for a complete walkthrough.

Who receives what

LayerZero's portion is forwarded to the endpoint at send time. The protocol fee accrues in the bridge (collectedProtocolFees, collectedFeeTokenProtocolFees) and is withdrawable only by the owner (withdrawProtocolFees, withdrawFeeTokenProtocolFees), with corresponding events.

Restore transfers - returning a failed transfer to its source - intentionally collect no protocol fee.

Feedback