On this page

Omnilink reads

Omnilink makes an approved source-chain view result available on another chain without making the transport specific to prices, NAV, vault rates, or any other result ABI.

It is a read-result relay, not an oracle. The source contract determines the value, Omnilink transports the returned bytes, and the destination integration decides how to decode and use them.

The normal flow

Source chain                                      Destination chain

approved target.staticcall(calldata)
              |
              v
       Omnilink.sendRead()  -- LayerZero V2 -->  Omnilink stores raw ABI bytes
              ^                                      |
              |                                      v
     permissionless relayer                 application reads by readId
  1. The source Omnilink owner registers one exact (target, callData) path with configureRead.
  2. Anyone can preview that path, quote its delivery, and call sendRead.
  3. Omnilink executes the source call with staticcall, applies the configured gas and result-size limits, and optionally calls a read-specific validator.
  4. The destination verifies the LayerZero peer and source-chain mapping, then stores the complete returned bytes with source metadata.
  5. Consumers decode the expected ABI and enforce their own freshness and risk policy.

A read cannot mutate the source target. Unregistered calldata, oversized results, empty results, failed calls, and disabled read paths revert before a message is sent.

Deterministic identity

Every result is stored under an identity that includes the complete calldata hash:

readId = keccak256(
    abi.encode(
        PAYLOAD_VERSION,
        sourceChainId,
        target,
        keccak256(callData)
    )
);

This means price(assetA) and price(assetB) cannot collide even though they use the same target and selector. For typed adapters, readPrice(asset), readNav(asset), and readVault(vault) each produce an asset-specific path.

The stored result also records the source sender, target, selector, calldata hash, target code hash, sequence, source timestamp, source block number, LayerZero GUID, and delivery time.

Typed data adapters

Omnilink can relay a canonical contract directly, such as a Chainlink proxy's latestRoundData(). Typed source adapters are useful when an integration needs several values from the same source block or a stable result schema.

The included adapters cover:

AdapterReadAggregate result
OmnilinkChainlinkPriceAdapterreadPrice(asset)Price answer, quote ID, feed identity, decimals, round metadata, freshness policy, and immutable config hash
OmnilinkChainlinkNavAdapterreadNav(asset)Single-value NAV, currency ID, per-share/total semantics, feed metadata, freshness policy, and immutable config hash
OmnilinkERC4626AdapterreadVault(vault)One-share conversion, underlying identity, share/asset decimals, totalAssets, totalSupply, and immutable config hash

Adapters are read-only Omnilink targets. They do not call sendRead themselves. This preserves the external relayer as readSender, including for optional OMNI rewards.

Read Omnilink data adapters for their schemas and registration rules.

Optional OMNI rewards

A destination-chain requester can lock a custom OMNI reward for an exact read path. This is separate from the normal transport flow and sends no request message to the source chain.

Chain A requestRead(sourceChainId, target, callData, reward)
    -> locks OMNI locally
    -> emits ReadRequested

Chain B relayer independently calls the normal sendRead()
    -> knows nothing about the request

Matching result reaches Chain A
    -> stores the read normally
    -> credits the locked OMNI to result.readSender

The requester can cancel an unanswered lock after one hour. A result arriving after cancellation is still stored but receives no reward. Relayers should therefore re-check that a reward remains locked and account for the cancellation race before spending source-chain gas.

Fees

Each sendRead to one destination pays:

totalFee = LayerZero messaging fee + fixedProtocolFee

The quote already includes both components. Excess native payment is refunded. requestRead sends no LayerZero message and charges no Omnilink protocol fee; its OMNI amount is a refundable or claimable reward, not a fee.

Read Fees for the accounting differences between Omnilink reads and bridge transfers.

Trust and freshness

Omnilink proves which approved source call returned the bytes. It does not prove that the underlying value is economically correct or manipulation-resistant.

Consumers should verify:

  • The expected source chain, target, calldata, schema version, and adapter configHash.
  • Source observation freshness through requireFresh(readId, maxAge).
  • Feed-specific timestamps embedded in Chainlink snapshots.
  • Expected decimals, units, and price or NAV semantics.
  • Application-specific deviation, bounds, and market-hours rules.
  • Vault-specific risks around convertToAssets, donations, losses, and accounting implementations.

Out-of-order messages cannot rewind a stored result because every read path has a monotonically increasing source sequence. A stale sequence is consumed and logged but cannot earn a newly locked reward. This protects ordering; it does not replace consumer freshness checks.

Experimental Beta is Live-Learn more about the Pilot