On this page

OmniseaONFTs (Coming soon)

NFT routes are coming soon. The current production deployment supports OFT transfers for ERC-20 assets only.

This page documents the planned ERC-721 bridge surface so integrators can see the intended shape ahead of launch. Do not use old ONFT beta addresses for live transfers. Verified ONFT deployment addresses will be published in Deployments once NFT routes are active.

contract OmniseaONFTs is OmniseaUpgradeableCore

The planned contract will mirror the live Omnisea route model where appropriate - fees, options validation, peer setup and first-set activation timing, hooks, owner functions, and failed-message recovery. This page documents expected NFT-specific differences and should not be treated as live deployment documentation.

Send functions

The value argument is a tokenId, not an amount. Each function uses the full hook-aware signature; use an empty hook for a plain transfer.

sendOriginal

Locks an original NFT (requires approve or setApprovalForAll to the bridge) and sends it to dstEid:

function sendOriginal(
    uint32 dstEid,
    address originalCollection,
    uint256 tokenId,
    address recipient,
    bool isFirstTransfer,
    Hook calldata hook,
    bytes calldata options
) external payable returns (MessagingReceipt memory receipt);

sendONFT

Burns a representation NFT and sends it back home or onward. Reverts with RepresentationMustUseSendONFT if you call sendOriginal with a representation, and NotRepresentation if you call sendONFT with anything else:

function sendONFT(
    uint32 dstEid,
    address representation,
    uint256 tokenId,
    address recipient,
    bool isFirstTransfer,
    Hook calldata hook,
    bytes calldata options
) external payable returns (MessagingReceipt memory receipt);

quoteSendOriginal / quoteSendONFT

View counterparts returning the exact total fee, like the OFT quotes.

What the message carries

The NFT payload propagates collection metadata, the token's URI, and ERC-2981 royalty configuration with every transfer:

struct TokenPayload {
    MessageKind messageKind;   // Transfer | Restore
    uint32  originalChainId;
    address originalToken;
    uint256 tokenId;
    address sender;
    address recipient;
    string  tokenName;
    string  tokenSymbol;
    string  tokenURI;          // per-token, stored on the representation at mint
    string  contractURI;
    address royaltyReceiver;   // ERC-2981 default royalty, propagated from the original
    uint96  royaltyBps;
    address contractOwner;     // original collection's owner() - becomes the representation's owner
    Hook    hook;
}

See Representations for what the issuer-owned representation can do with this metadata.

Identity & discovery

function collectionKey(uint32 originalChainId, address originalToken) public pure returns (bytes32);
function representationFor(uint32 originalChainId, address originalToken) external view returns (address);
function predictRepresentation(uint32 originalChainId, address originalToken) external view returns (address);

/// Reverse lookup for local representations.
mapping(address representation => OriginalCollection original) public onftToOriginal;

/// Forward lookup by collection key.
mapping(bytes32 originalCollectionKey => address representation) public originalToONFT;

/// Per-token lock registry for originals held by the bridge.
mapping(address originalToken => mapping(uint256 tokenId => bool locked)) public locked;

Safe-transfer guard

The bridge implements onERC721Received defensively: it only accepts the exact token it is actively locking inside a sendOriginal call. Any other NFT pushed at the bridge via safeTransferFrom reverts with UnexpectedERC721Received - tokens cannot be stranded in the bridge by accident.

NFT-specific events & errors

event OriginalLocked(address indexed originalToken, uint256 indexed tokenId, address indexed owner);
event OriginalUnlocked(address indexed originalToken, uint256 indexed tokenId, address indexed recipient);
event RepresentationBurned(address indexed representation, uint32 indexed originalChainId, address indexed originalToken, address owner, uint256 tokenId);

error NotLocked();                      // unlock for a token the bridge does not hold
error TokenAlreadyLocked();             // double-lock attempt
error UnexpectedERC721Received();       // unsolicited safeTransferFrom into the bridge
error RepresentationMustUseSendONFT();  // sendOriginal called with a representation

RepresentationDeployed, RepresentationMinted, BridgeMessageSent/Received, hook events, recovery events, and configuration events match the OFT bridge with tokenId taking the place of amount.

Metadata

Once NFT routes are live, first transfers will deploy an ONFT representation initialized with the original collection's name, symbol, contractURI, default royalty, and owner. Each minted token will store the tokenURI carried in its transfer, so bridged NFTs can render correctly in wallets and marketplaces - including ERC-2981 royalty queries.

Experimental Beta is Live-Learn more about the Pilot