OmniseaONFTs
The ERC-721 bridge and representation factory. Immutable, permissionless, deployed at 0x5c0cFc7B0758e5bedE5E9E3A8BA226591f09dC5b on every chain.
contract OmniseaONFTs is Ownable, ReentrancyGuardThe contract mirrors OmniseaOFTs - fees, options validation, immutable peer setup and first-set activation timing, hooks, owner functions, and failed-message recovery are identical. This page documents what differs for NFTs.
Send functions
The value argument is a tokenId, not an amount. Each function keeps the same three overloads (plain / isFirstTransfer / isFirstTransfer + Hook).
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, // optional overload
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, // optional overload
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 representationRepresentationDeployed, RepresentationMinted, BridgeMessageSent/Received, hook events, recovery events, and configuration events match the OFT bridge with tokenId taking the place of amount.
Metadata
First transfers deploy an ONFT representation initialized with the original collection's name, symbol, contractURI, default royalty, and owner. Each minted token stores the tokenURI carried in its transfer, so bridged NFTs render correctly in wallets and marketplaces - including ERC-2981 royalty queries.