Developer documentation
Omniassets for developers.
Move existing ERC-20 tokens across supported EVM chains through one contract interface. No token-team deployment is required.
What Omnisea does
An ERC-20 can enter the network without a custom bridge deployment. Omnisea locks the original token, creates a deterministic ERC-20 representation when needed, and burns or unlocks supply as the asset moves between chains.
Transfer
Lock an original ERC-20 or burn its Omniasset, then deliver it on another chain.
Quote
Calculate the exact native fee for the same arguments you will send onchain.
Track
Follow a transfer from its source transaction to destination delivery by message GUID.
Understand
Review the backing, messaging, failure handling, and trust boundaries.
Choose your path
Start with the client action you need, then use the contract references for exact arguments, events, errors, and LayerZero options.
Build a transfer flow
Connect React wallet state to discovery, approval, quote, and send actions.
Quote a transfer
Prepare live route arguments and show the current native fee before confirmation.
Track delivery
Read the source GUID and follow delivery or failure on the destination.
Handle client errors
Turn wallet, contract, fee, gas, and network failures into useful UI states.
Find deployments
Copy the current contract addresses and LayerZero endpoint IDs.
Learn how it works
See how originals, Omniassets, vault backing, and delivery fit together.
Programmatic start
This viem example sends an original ERC-20 from BNB Chain to Base. It checks whether Base needs the Omniasset deployed, builds the corresponding receive-gas option, approves the token, and sends with an exact quote.
import { erc20Abi, zeroAddress } from "viem";
const omnisea = "0x0E108CbbD4d783Fea6c07E96be9e2aA5A842D6b4";
const token = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c";
const sourceEid = 30102; // BNB Chain
const dstEid = 30184; // Base
const recipient = account.address;
const representation = await destinationClient.readContract({
address: omnisea,
abi: omniseaAbi,
functionName: "representationFor",
args: [sourceEid, token],
});
const isFirstTransfer = representation === zeroAddress;
const minimumGas = await sourceClient.readContract({
address: omnisea,
abi: omniseaAbi,
functionName: isFirstTransfer ? "minCreationGas" : "minTransferGas",
});
const receiveGas = minimumGas + minimumGas / 5n;
const u128 = (value: bigint) => value.toString(16).padStart(32, "0");
const options = `0x000301002101${u128(receiveGas)}${u128(0n)}` as const;
const compose = { composer: zeroAddress, gasLimit: 0n, message: "0x" } as const;
const approval = await walletClient.writeContract({
account,
address: token,
abi: erc20Abi,
functionName: "approve",
args: [omnisea, amount],
});
await sourceClient.waitForTransactionReceipt({ hash: approval });
const args = [dstEid, token, amount, recipient, isFirstTransfer, compose, options] as const;
const fee = await sourceClient.readContract({
address: omnisea,
abi: omniseaAbi,
functionName: "quoteSendOriginal",
args,
});
await walletClient.writeContract({
account,
address: omnisea,
abi: omniseaAbi,
functionName: "sendOriginal",
args,
value: fee,
});Documentation directory
Contract methods, client integrations, deployment addresses, and the concepts behind Omniassets.