Skip to main content
Version: Endpoint V2 Docs

Omnichain Fungible Token (OFT) Technical Reference

LayerZero's Omnichain Fungible Token (OFT) standard enables a single fungible token to exist across many chains while preserving one global supply. The standard abstracts away differences in contract languages, so the high-level behavior is identical no matter which VM you deploy on.

Deployment

An OFT contract must be deployed on every network where a token currently exists or will exist. Since OFT contracts inherit all of the core properties of a LayerZero OApp, connecting OFT deployments requires setting a directional channel configuration between the source chain and the destination blockchain.

Channel Configuration

Every OFT deployment must have a directional channel configuration for messaging to be successful. This means the deployer must:

  • Connect the messaging channel at the Endpoint level (establishing the underlying pathway for cross-chain messages).
  • Pair the OFT deployments at the OApp level using setPeer(...), so each contract knows its trusted counterpart on the destination chain.

For an overview of what a messaging channel is, see Message Channel Security. For a more thorough explanation of channel configuration and peer relationships, see the OApp Reference.

Core Transfer Flow

When an OFT transfer is initiated, the token balance on the source chain is debited. This either burns or locks the tokens inside the OFT contract, similar to an escrow account. A message is then sent via LayerZero to the destination chain where the paired OFT credits the recipient by minting or unlocking the same amount. This mechanism guarantees a unified supply across all chains.

  1. Debit on the source chain
    The sender calls the OFT's send(...) function, burning or locking an amount of tokens.

  2. Message dispatch via LayerZero
    The source OFT packages the transfer details into a LayerZero message and routes it through the protocol's messaging layer. LayerZero's messaging rails handle cross-chain routing, verification of the encoded message, and delivery of the message to the destination chain's receiver OFT contract.

  3. Credit on the destination chain
    The paired OFT receives the message and credits the recipient by minting new tokens or unlocking previously-held tokens. The total supply across all chains remains constant, since burned or locked tokens on the source chain are matched 1:1 with minted or unlocked tokens on the destination.

  4. (Optional) Trigger a composing call
    A composing contract uses the tokens received in a new transaction, delivered automatically by the LayerZero Executor, to trigger some state change (e.g., swap, stake, vote). For more details on how to implement composable OFT transfers, see Omnichain Composability.

Core Concepts

This section explains the fundamental design principles that make OFT a flexible, developer-friendly standard for fungible tokens.

1. Transferring Value Across Different VMs

When transferring tokens across different virtual machines, OFT needs to handle varying decimal precision between chains. This is managed through a few key concepts:

  • Local Decimals
    Each chain's recommended token standard (e.g., ERC-20 on EVM, SPL Token on Solana, Fungible Assets on Aptos) may use a different default number of decimal places to represent tokens on-chain. If an EVM token uses 18 decimals and a Solana token uses 6, transferring 1.000000000000000000 on Chain A without adjustment would not equate to 1.000000 on Chain B. Put differently, localDecimals represent a token contract's decimal precision on a specific blockchain.

  • Shared Decimals
    To ensure consistent value representation, every OFT declares a sharedDecimals parameter. Before sending a token cross-chain, the OFT logic converts the "local" amount into a normalized "shared" unit. Upon arrival, the destination OFT reconverts that shared unit back into the local representation of its own decimal precision.

  • Dust Removal
    Before converting the local unit amount (amountLD) into the shared unit amount (amountSD), OFT implementations first "floor" the local amount to the nearest multiple of the conversion rate so that no remainder ("dust") is included in the cross-chain transfer.

    The normalization process works as follows:

    1. Compute the conversion rate:

      decimalConversionRate  =  10(localDecimalssharedDecimals)\Large {decimalConversionRate} \;=\; 10^{\,(\text{localDecimals} - \text{sharedDecimals})}
    2. Remove dust by flooring to that multiple (e.g., integer division on the EVM):

      flooredAmountLD  =  amountLDdecimalConversionRate×decimalConversionRate\Large{flooredAmountLD} \;=\; \Bigl\lfloor \tfrac{\text{amountLD}}{\text{decimalConversionRate}} \Bigr\rfloor \times \text{decimalConversionRate}
    3. Compute and return the dust remainder to the sender:

      dust  =  amountLD    flooredAmountLD\Large{dust} \;=\; \text{amountLD} \;-\; \text{flooredAmountLD}

      That dust is refunded to the sender's balance before proceeding with debiting the sender's account, and the flooredAmountLD is now used as the amountLD.

    4. Convert the amount in local decimals (amountLD) to shared units on the source chain:

      amountSD=amountLDdecimalConversionRate\Large amountSD = \frac{amountLD}{decimalConversionRate}
    5. Transmit the amount in shared decimals (amountSD) as part of the LayerZero message.

    6. On the destination chain, reconstruct the local amount (amountLD):

      amountLD=amountSDdecimalConversionRate\Large amountLD = {amountSD}*{decimalConversionRate}
  • Why This Matters

    • Consistent Economic Value: "1 OFT" means the same thing on any chain, regardless of differing decimal precision.
    • DeFi Compatibility: Prevents rounding errors and ensures seamless integration with on-chain tooling (e.g., AMMs, lending protocols) that expect familiar decimal behavior.
    • No Precision Loss: By using a common sharedDecimals, you avoid truncation or expansion mistakes when moving large or small amounts across networks.
caution

If you override the vanilla sharedDecimals amount or have an existing token supply exceeding 18,446,744,073,709.551615 tokens, extra caution should be applied to ensure amountSD and amountLD do not overflow. Vanilla OFTs can disregard this admonition.

  1. Shared‐Unit Overflow (amountSD)
    OFT encodes amountSD as a 64-bit unsigned integer (uint64). The largest representable shared‐unit value is 2^64 − 1. Therefore, the maximum token supply (in whole‐token terms) is:

    264110sharedDecimals\Large \frac{2^{64} - 1}{10^{\,\text{sharedDecimals}}}

    In vanilla OFT implementations, sharedDecimals = 6, yielding a max supply of

    2641106  =  18,446,744,073,709.551615 tokens\Large \frac{2^{64} - 1}{10^6} \;=\; 18{,}446{,}744{,}073{,}709.551615 \text{ tokens}

    If you choose a smaller sharedDecimals, the divisor shrinks and you may exceed the uint64 limit when converting a large amountLD into amountSD.

  2. Local‐Unit Overflow (amountLD)
    On some chains (e.g., Solana's SPL Token or Aptos's Fungible Asset), the native token amount is also stored as a 64-bit unsigned integer (uint64). In those environments, the maximum local amount is 2^64 − 1. But because amountLD must be a multiple of

    decimalConversionRate  =  10(localDecimalssharedDecimals)\Large \text{decimalConversionRate} \;=\; 10^{(\text{localDecimals} - \text{sharedDecimals})}

    If amountSD × decimalConversionRate would exceed 2^64 − 1, the reconstructed amountLD cannot fit in the native uint64 type.

To avoid both overflow risks:

  • Pick sharedDecimals so that your target maximum supply divided by 10^{sharedDecimals} is ≤ 2^64 − 1.
  • Verify each chain's local type (e.g., uint64 on Solana/Aptos or uint256 on most EVM chains) can accommodate the resulting amountLD (i.e., amountSD × decimalConversionRate must not exceed the local limit).

2. Adapter vs. Direct Patterns: Contract Structure & Bridge Logic

What Is "Direct" vs. "Adapter"?

  • Direct Pattern

    • The token contract itself contains all bridge logic (send/receive) along with standard token functions (mint, burn, transfer).
    • When a user initiates a cross-chain transfer, the token contract on the source chain invokes internal "debit" logic to burn tokens, packages the message, and sends it through LayerZero. On the destination chain, the same contract (deployed there) receives the message and invokes internal "credit" logic to mint new tokens.
  • Adapter Pattern

    • The token contract is separate from the bridge logic. Instead of embedding send/receive in the token, an adapter contract handles all cross-chain operations.
    • The adapter holds (locks) user tokens (or has burn and mint roles, e.g., "Mint and Burn Adapter") and communicates with a paired OFT contract on the destination chain, which mints/unlocks or transfers the equivalent amount to the recipient.
    • From the developer's perspective, the only requirement is that the adapter exists as a standalone contract; the original token contract remains unaware of LayerZero or cross-chain flows.

Key Distinctions

  • Separate vs. Combined

    • Direct: Token + bridge = single deployable.
    • Adapter: Token = unmodified existing contract; Bridge logic = standalone adapter contract.
  • Mint And Burn Adapter Example

    • Even though it uses mint/burn semantics, it is still an "Adapter" because the adapter contract, not the token contract itself, contains all LayerZero business logic.
    • The adapter delegates calls to mint or burn on a "wrapper" token or calls an interface on the underlying token, separating concerns without requiring the original token code to change.
  • User/Integrator Perspective

    • No Difference in UX: Users call a standard send function (or "transfer" wrapper) without caring whether the token is Direct or Adapter.
    • Meshability: Any two OFT-enabled contracts (Direct or Adapter) on different chains can interoperate. This means liquidity can span adapters and direct tokens seamlessly, making the system truly omnichain.

Implications for Asset Issuers

  • Direct Pattern Suits New Tokens

    • When launching a brand-new token, embedding OFT logic directly can save on contract count and gas.
    • Simplifies deployment paths since your token and cross-chain logic are co-located.
  • Adapter Pattern Suits Existing Tokens

    • If you already have an active ERC-20 (or SPL, or Move) token with liquidity and integrations, deploying an adapter contract lets you plug into OFT without migrating your token.
    • The adapter can implement mint and burn, lock and unlock, or any hybrid, as long as it abides by the OFT interface.
  • Access Control & Governance

    • Direct Token: You manage roles (Admin, Delegate) within a single contract.
    • Adapter + Token: You may need to coordinate roles and permissions across two deployables.

3. Extensibility & Composability

OFT's design prioritizes flexibility and extensibility, allowing developers to customize token behavior and build complex cross-chain applications. The standard provides hooks for custom logic and supports composable transfers that can trigger additional actions on the destination chain.

Hooks Around Debit/Credit

  • Beyond Value Transfer

    • Many applications require extra functionality during or after cross-chain value transfer for example:

      • Protocol Fees: Automatically deduct a small fee on each cross-chain transfer and route it to a treasury.
      • Rate Limiting: Applying a limit on the number of tokens that can be sent in a given time-interval.
      • Access Control: Enforce time-based or role-based restrictions, such as requiring KYC verification for large transfers.
  • Overrideable Functions

    • OFT's core _debit and _credit methods are declared virtual (or their equivalent in non-EVM languages), allowing developers to override them in custom subclasses/modules.
    • Inject additional checks or side effects (e.g., take fees off transfers, check for rate limits, or validate off-chain context) without rewriting the entire message flow.

Composability with LayerZero Messaging

  • Cross-Chain Value Transfer + Call
    • You can bundle arbitrary data with your OFT transfer. For example, trigger a staking action on the destination chain if a recipient stakes a minimum amount, or execute a cross-chain governance vote.
    • The OFT contract simply forwards any extra bytes as a composeMsg through LayerZero's endpoint. On the destination, your custom lzCompose(...) hook can decode and act on that arbitrary data and token transfer.

Security & Roles

OFTs inherit LayerZero's admin/delegate role model:

  • Owner

    • Sets required gas limit requests for execution.
    • Can peer new OApp contracts or remove peers in emergencies.
  • Delegate

    • Configures connected chain's and messaging channel properties (e.g., Message Libraries, DVNs, and executors).
    • Can pause or unpause cross-chain functionality in emergencies.

Best Practice: Use a multisig to manage both Owner and Delegate privileges.

Further Reading

  • EVM OFT Quickstart A step-by-step guide to deploying Direct or Adapter OFT contracts on Ethereum-compatible networks.

  • Solana OFT Quickstart Detailed instructions and example code for setting up an OFT program with SPL Token / Token 2022 integration.

  • Aptos Move OFT Quickstart In-depth documentation on Move module structure, sharedDecimals math, and composability best practices.