Skip to main content
The Omnichain Non-Fungible Token (ONFT) Standard allows non-fungible tokens (NFTs) to be transferred across multiple blockchains without asset wrapping or middlechains.
  • ONFT Contract: Uses a burn-and-mint mechanism. For a fluid NFT that can move directly between chains (e.g. Chain A and Chain B), you must deploy an ONFT contract on every chain. This creates a “mesh” of interconnected contracts.
  • ONFT Adapter: Uses a lock-and-mint mechanism. If you already have an NFT collection on one chain and want to extend it omnichain, you deploy a single ONFT Adapter on the source chain. Then, you deploy ONFT contracts on any new chains where the collection will be transferred. Note that only one ONFT Adapter is allowed in the entire mesh.
This mesh concept is central to all LayerZero implementations: it represents the network of contracts that work together to enable omnichain NFT functionality.

ONFT (Burn & Mint)

Diagram showing ONFT burn-and-mint mechanism: NFTs are burned on Network A and minted on Network B, connected by an arrow representing the crosschain transfer When using ONFT, tokens are burned on the source chain whenever an omnichain transfer is initiated. LayerZero sends a message to the destination contract instructing it to mint the same number of tokens that were burned, ensuring the overall token supply remains consistent.
Key Points
  • Default pattern for new NFT collections.
  • ONFT721 extends ERC721 (OpenZeppelin) and adds crosschain logic.
  • Unified supply across chains is maintained by burning on source, minting on destination.

ONFT Adapter (Lock & Mint)

Diagram showing ONFT Adapter lock-and-mint mechanism: existing NFTs are locked in an adapter contract on the source chain, and equivalent NFTs are minted on the destination chain When using ONFT Adapter, tokens are locked in a contract on the source chain, while the destination contract mints or unlocks the token after receiving a message from LayerZero. When bridging back, the minted token is burned on the remote side, and the original is unlocked on the source side.
Key Points
  • Suitable for existing NFT collections.
  • The adapter contract is effectively a “lockbox” for your existing ERC721 tokens.
  • No changes to your original NFT contract are required. Instead, the adapter implements the crosschain logic.

Installation

To start using the ONFT721 and ONFT721Adapter contracts, you can either create a new project via the LayerZero CLI or add the contract package to an existing project:

New project

If you’re creating a new contract, LayerZero provides create-lz-oapp, an npx package that allows developers to create any omnichain application in less than 4 minutes. Get started by running the following from your command line and choose ONFT721 when asked about a starting point. It will create both ONFT721 and ONFT721Adapter contracts for your project.

Existing project

To use ONFT in your existing project, install the @layerzerolabs/onft-evm package. This library provides both ONFT721 (burn-and-mint) and ONFT721Adapter (lock-and-mint) variants.
LayerZero contracts work with both OpenZeppelin V5 and V4 contracts. Specify your desired version in your project’s package.json:
To create an ONFT, you should decide which implementation is appropriate for your use case:
  1. Use ONFT721 when you’re creating a new NFT collection that will exist on multiple chains.
  2. Use ONFT721Adapter when you need to make an existing NFT collection crosschain compatible.

ONFT721 Implementation

Deploy an ONFT that inherits from ONFT721, which combines ERC721 with the crosschain functionality needed for omnichain transfers. The contract automatically handles token burning on the source chain and minting on the destination chain. You can pass in your chosen contract name, symbol, the LayerZero Endpoint address, and the contract’s delegate (owner or governance address). This contract becomes the “canonical” NFT on every chain.

ONFT721Adapter Implementation

Deploy an ONFT Adapter that references your existing NFT contract address. The ONFT721Adapter constructor takes an additional parameter _token, which is the address of the existing ERC721 token that you want to make crosschain compatible.

Warning

There can only be one ONFT Adapter used for a specific ERC721 token, and it should be deployed on the chain where the original ERC721 token is located. On all the other chains where you want to use the ONFT, you only need an ONFT721 contract.

Deployment Workflow

The deployment process for ONFT contracts involves several steps, which we’ll cover in detail:
  1. Deploy the ONFT or ONFT Adapter contracts to all the chains you want to connect.
  2. Configure peer relationships between contracts on different chains.
  3. Set security parameters including Decentralized Validator Networks (DVNs).
  4. Configure message execution options.

1. Deploy ONFT Contracts

First, deploy your ONFT contracts to all the chains you want to connect: For new NFT collections:
  • Deploy MyONFT721 on all chains.
For existing NFT collections:
  • Deploy MyONFT721Adapter on the chain where the original NFT exists.
  • Deploy MyONFT721 on all other chains you want to connect.

2. Configure Security Parameters

Production deployments should use multiple required DVNs from independent operators. A single-DVN configuration means a compromise of that one verifier results in unrestricted forged messages on the pathway. See the Integration Checklist for production DVN guidance.
Set the DVN configuration, including block confirmations, security thresholds, executor settings, and messaging libraries:
These configurations are stored in the EndpointV2 contract and control how messages are verified and executed. If you don’t set custom configurations, the system will use default configurations set by LayerZero Labs. We strongly recommend reviewing these settings carefully and configuring your security stack according to your needs and preferences. You can find example scripts to make these calls in Security and Executor Configuration.

3. Configure Peer Relationships

After deployment, you need to call setPeer on each contract to establish trust between ONFT contracts on different chains. Set peers by calling setPeer(dstEid, addressToBytes32(remoteONFT)) on every chain. This whitelists each destination as the trusted contract to receive your message.
The actual endpoint ids will vary per chain, see Supported Chains for endpoint id reference.

4. Configure Message Execution Options

[Optional but recommended] ONFT inherits OAppOptionsType3 from the OApp standard. This means you can define:
  1. enforcedOptions: A contract-wide default that every send must abide by (e.g. minimum gas for lzReceive, or a maximum message size).
  2. extraOptions: A call-specific set of execution settings or advanced features, such as adding a “composed” message on the remote side.
This ensures every user who calls myONFT.send(...) must pay at least 100_000 gas on the remote chain for the bridging operation. This is useful for ensuring there’s enough gas on the destination chain to execute the bridging operation and to receive the bridged tokens. enforcedOptions should only be set for msgType: SEND, to make sure there’s enough gas on the destination chain to execute the bridging operation and to receive the bridged tokens. See Message Execution Options for more details.

Using ONFT Contracts

Estimating Gas Fees

Before calling send, you’ll typically want to estimate the fee using quoteSend. Similar to OFT, you can call quoteSend(...) to get an estimate of how much msg.value you need to pass when bridging an NFT crosschain. This function takes in the same parameters as send but does not actually initiate the transfer. Instead, it queries the Endpoint for an estimated cost in nativeFee. Arguments of the estimate function:
  1. SendParam (struct): which parameters should be used for the send operation?
  1. payInLzToken (bool): which token (native or LZ token) will be used to pay for the transaction? true for LZ token and false for native token.
This lets us construct the quoteSend function:
We now have everything we need to be able to send the NFT crosschain:
  • SendParam struct with all the parameters needed to send the NFT crosschain
  • quoteSend function to estimate the fee before sending the NFT crosschain
  • refundAddress parameter to specify the address to refund if the transaction fails on the source chain (default is the sender’s address)
Let’s send some NFTs across the chains!

Sending NFTs Across Chains

To transfer an NFT to another chain, users call the send function with appropriate parameters:
You can override the _debit function with any additional logic you want to execute before the message is sent via the protocol, for example, taking custom fees.

Example Client Code

Here’s how the send function can be called, as a Hardhat task for an ONFT Adapter contract:
You can put this task in sendNFT.ts in the tasks directory and run the command below to send the NFT.This assumes that you have already deployed the adapter contract on Sepolia (testnet) and are sending the NFT to a recipient on Polygon Amoy (testnet).
When you call send:
  • ONFT will _burn in the source chain contract, _mint in the destination chain contract.
  • ONFT Adapter will transferFrom(...) tokens into itself on the source chain (locking them), then _mint or _unlock on the destination.

Receiving the NFT (_lzReceive)

A successful send call will be delivered to the destination chain, invoking the _lzReceive method during execution on that chain:
You can see each step in ONFT721Core.sol.

Advanced Features

Composed Messages

ONFT supports composed messages, allowing you to execute additional logic on the destination chain as part of the NFT transfer. When the composeMsg parameter is not empty, after the NFT is minted on the destination chain, the composed message will be executed in a separate transaction. For advanced use cases, you can leverage this feature to:
  • Trigger additional actions when an NFT arrives
  • Integrate with other protocols on the destination chain
  • Implement crosschain NFT marketplace functionality

ONFT721Enumerable

For collections that need enumeration capabilities, LayerZero provides an ONFT721Enumerable contract that extends ONFT721 with the ERC721Enumerable functionality:
This is useful for applications that need to enumerate or track all tokens within the collection.

Example: Complete End-to-End Deployment Flow

Here’s a complete example showing how to deploy and configure an ONFT system with an existing NFT collection on Ethereum and bridging to Polygon:
  1. Create a new OApp with CLI
Choose ONFT721 as the starting point.
  1. Configure OApp
  • Modify layerzero.config.ts to configure the OApp and add all the chains you want your ONFT to be available on.
  • Add private key to .env file
  • Modify hardhat.config.ts to add the networks you want to deploy to
  1. Deploy Contracts:
Adapt the contracts to your needs and deploy them using Hardhat:
You’ll be able to choose which chains you want to deploy to.
  1. Configure Peers:
Now that everything is deployed, it’s time to wire all the contracts together. The fastest way is to use the CLI:
  1. Verify Setup
Verify that everything was wired up correctly:
Verify configurations:
In the output of the config command above:
  • Custom OApp config: what you customized in your OApp
  • Default OApp config: the defaults that are applied if you don’t customize anything
  • Active OApp config: the config that is currently active (essentially, default + your applied customizations)
And you are now ready to send the NFT across all your configured chains! 🎉

Security Considerations

When deploying ONFT contracts, consider the following security aspects:
  1. Peer Configuration: Only set trusted contract addresses as peers to prevent unauthorized minting.
  2. DVN Settings: Use multiple required DVNs from independent operators in production. A single-DVN configuration means a compromise of that one verifier results in unrestricted forged messages on the pathway. See the Integration Checklist.
  3. Gas Limits: Set appropriate gas limits in enforceOptions to prevent out-of-gas errors.
  4. Ownership Controls: Implement proper access controls for administrative functions.
  5. Timeouts and Recovery: Understand how message timeouts work and prepare recovery procedures.

Next Steps

The ONFT standard provides a powerful way to create truly crosschain NFT collections. By understanding the core concepts and following the deployment guidelines outlined in this document, you can build robust omnichain NFT applications that leverage LayerZero’s secure messaging protocol. For more information, explore these related resources: You’re ready to build omnichain NFTs!