> ## Documentation Index
> Fetch the complete documentation index at: https://docs.layerzero.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Support OFTs and OApps on Tempo

> How to adapt OFT and OApp deployments for Tempo: fee payment with LZD, OFTAlt contracts, and the TempoOFTWrapper flow.

## Does my existing OFT/OApp work on Tempo?

Yes. Source-chain contracts remain unchanged, **but** the Tempo side requires Alt contract variants and pays fees in LZD instead of `msg.value`. The message format, pathway configuration, and security model are the same.

<Warning>
  Source-chain contracts may need updated `enforcedOptions` to account for Tempo's higher gas costs. See [what changes on Tempo](#what-changes-on-tempo) below.
</Warning>

## What changes on Tempo

See the [overview](/v2/developers/tempo/overview) for how each standard LayerZero component maps to its Tempo equivalent. The key changes relevant to OFT/OApp integrations:

* **OFT/OApp contracts** are replaced by their Alt variants: [OFTAlt, OFTAdapterAlt](/v2/developers/tempo/reference/oft-vs-oftalt#choosing-the-right-contract), [OFTBurnSelfMintAlt](/v2/developers/tempo/reference/tip-20-token-standard#integration-with-oftalt), or [OAppAlt](/v2/developers/evm/evm-variants/evm-compatible-variants) depending on your use case
* **Fees** are paid in [LZD](/v2/developers/tempo/reference/lz-endpoint-dollar) instead of `msg.value` (this is because Tempo has no native gas token). You must wrap a stablecoin into LZD and approve the OFT before calling `send{value: 0}()`
* **Native drop** is not supported (`addExecutorNativeDropOption` reverts)
* **Gas costs are higher** on Tempo for certain operations (state creation, new accounts). Set custom `enforcedOptions` with higher gas limits for `lzReceive` when Tempo is the destination. See [TIP-1010](https://docs.tempo.xyz/protocol/tips/tip-1010) for the full gas schedule

## Sending from other chains to Tempo

When sending **to** Tempo from another chain, the normal fee model applies on the source chain:

* Pay fees in the source chain's native token (ETH, MATIC, etc.) as usual
* No LZD is needed on the source chain
* The receiver on Tempo does not pay anything to receive the message

No changes are required to your existing OFT/OApp contracts on the source chain.

## Sending from Tempo to other chains

When sending **from** Tempo, you pay the LayerZero fee in LZD. There are two approaches:

### Direct flow (1 view call + 5 transactions)

```solidity wrap theme={null}
// 1. Quote the fee (view call)
MessagingFee memory fee = oft.quoteSend(sendParam, false);

// 2. Approve the asset token to the OFT (bridge amount)
IERC20(usdce).approve(address(oft), sendParam.amountLD);

// 3. Approve the fee token to LZD (fee amount)
IERC20(usdce).approve(address(lzd), fee.nativeFee);

// 4. Wrap stablecoin into LZD (token must be whitelisted by LZD)
lzd.wrap(usdce, msg.sender, fee.nativeFee);

// 5. Approve LZD to the OFT (fee amount)
IERC20(lzd).approve(address(oft), fee.nativeFee);

// 6. Send with msg.value = 0
oft.send{value: 0}(sendParam, fee, refundAddress);
```

### Wrapper flow (1 view call + 2 transactions)

The TempoOFTWrapper simplifies this by handling wrapping, approvals, and sending in a single transaction:

```solidity wrap theme={null}
// 1. Quote the fee
MessagingFee memory fee = oft.quoteSend(sendParam, false);

// 2. Approve the fee token to the wrapper (bridge amount + messaging fee)
IERC20(usdce).approve(address(wrapper), sendParam.amountLD + fee.nativeFee);

// 3. Call sendOFT: wrapper handles wrap, approve, and send atomically
wrapper.sendOFT(
    address(oft),       // OFT contract
    usdce,              // fee token (whitelisted stablecoin)
    sendParam,          // standard send parameters
    fee.nativeFee       // max acceptable fee (reverts if re-quote exceeds this)
);
```

The wrapper:

1. Pulls tokens from the caller:
   * **Same token** (e.g., USDC.e for both bridging and fees): pulls `amountLD + nativeFee` in a single transfer
   * **Different tokens** (e.g., bridging EURC.e, fees in USDC.e): pulls `amountLD` and `nativeFee` separately, requiring two approvals
2. Wraps the fee portion into LZD
3. Approves LZD to the OFT
4. Calls `oft.send()` with the correct fee
5. Reverts the entire transaction if the re-quoted fee exceeds `maxNativeFee`

<Tip>
  You can preflight with an `eth_call` to `sendOFT` to obtain
  `oftReceipt.amountSentLD` before sending the live transaction, and avoid dust.
</Tip>

<Warning>
  If the bridged token differs from the fee token (e.g., bridging EURC.e but paying fees in USDC.e), you will need to approve the asset token and fee token to the wrapper separately before calling `sendOFT`.
</Warning>

### With LZMulticall (frontend pattern)

The Stargate frontend uses LZMulticall to bundle wrapping, approvals, and sending into a single transaction. On Tempo, it bundles the LZD wrap and approval steps alongside the OFT send.

| Contract         | Address                                      |
| ---------------- | -------------------------------------------- |
| LZMulticall      | `0x4683ce822272cd66cea73f5f1f9f5cbcaef4f066` |
| TransferDelegate | `0x3c18440268a78d651a3847653692fc82c31731c9` |
| TempoOFTWrapper  | `0xbb95daf376cd63f258d7c37a4efe57c10055e8e0` |
| LZEndpointDollar | `0x0ceb237e109ee22374a567c6b09f373c73fa4cbb` |

## Common pitfalls

* **LZD is not available on DEXes.** LZD is an ERC-20, not a TIP-20 token, so it cannot be traded on the Tempo DEX. Always use `LZD.wrap()` to obtain fee tokens.
* **Wrapper becomes `msg.sender`.** When using the TempoOFTWrapper, the wrapper is the sender for the OFT call. Do not use it for compose messages where the composer refunds the original sender. The refund goes to the wrapper, not the user, and the funds will be permanently lost.
* **Fee token must be a whitelisted stablecoin, not LZD.** The `feeToken` passed to the wrapper must be a 6-decimal stablecoin whitelisted by LZD (pathUSD, USDC.e, or USDT0). Passing LZD itself reverts.

See the [LZD reference failure modes table](/v2/developers/tempo/reference/lz-endpoint-dollar#failure-modes) for a complete list of revert reasons.
