-
A submission interface where solvers can submit their filled outputs. It should accept arbitrary payloads for validation, then call the associated output settlement contract to check whether those payloads are valid. If the oracle can prove contract calls, events, or storage on its own, submission is automatic and this requirement does not apply.
Oracle implementations can validate whether an output has been filled through the
IAttesterinterface: -
Implement the validation interface so the input chain can check whether an output was filled:
- Submission and receive interfaces do not have to be standardized, but you must document them so solvers can implement them.
- Oracle systems can either have automatic relaying or manual relaying.
- The oracle system’s trust assumptions must be explicit, so intent issuers and solvers can make informed decisions.
Implemented Validation Interfaces
There are three types of validation interfaces:- Self-serve: Validation interfaces where submitting the payload generates an off-chain proof that must be collected and submitted on the input chain.
- Automatic: Validation interfaces where submitting the payload automatically delivers the associated proof on the input chain.
- Same Chain: Using the Output Settlement to produce an oracle proof for itself, skipping a dedicated oracle system.
Speed & Price
Some oracle systems are significantly faster than other oracle systems. While speed does not impact asset delivery for users, it matters for solvers. Choosing an oracle system with fast repayments results in cheaper intents, as solvers can rotate their capital faster.
Some oracle systems are significantly faster than other oracle systems. While speed does not impact asset delivery for users, it matters for solvers. Choosing an oracle system with fast repayments results in cheaper intents, as solvers can rotate their capital faster.
OutputSettlerSimple
You can use OutputSettlerSimple, an Output Settler, as the oracle for a same-chain intent. To use it, callsetAttestation after filling the output.
setAttestation will expose the filled outputs for the Input Settlement to verify.
Same-chain intents on Solana
On Solana, nosetAttestation step exists — the fill itself creates the proof. output_settler_simple::fill (or native_fill) creates a LocalAttestation PDA when a fill succeeds, and finalise validates that account directly. No oracle program is involved, and there is no callback flow. Instead, a single-output order can use input-first settlement: the escrow pays the solver and a compact fill delivers the output in the same transaction, with no attestation at all. See Attestations for the account model.
Polymer
Polymer is an event based system that provides real time proofs at low cost. Security is based on bundled state through Polymer with block headers sourced from Sequencer preconfirmations.- Low gas cost.
- Low latency for quick settlement.
- Polymer can only prove one output at a time, so solvers have to implement batch proving themselves to stay efficient.
- Broadcast
OutputFilled, emitted when an output has been filled.
receiveMessage.
For an example integration that fetches Polymer proofs, see lintent.org/polymer or the receiveMessage call made.
Polymer on Solana
The Solana Polymer oracle is theoracle_polymer Anchor program (deployed name: polymer; IDL: polymer.json). The flow matches the EVM one — validate fills, emit a provable log, verify the proof on the input chain — with Solana mechanics:
-
Output side (a fill on Solana): after filling, the solver exports the fill with one of two instructions. Both validate each description against its
LocalAttestationand emit aProve:log line that Polymer proves on the input chain:submit(source, fill_descriptions)— permissionless and non-consuming. Its only named account is theoracle_polymerstate PDA;remaining_accountsholds one read-only attestation per payload. The attestation stays in place, so a dropped or unproven log can simply be submitted again.submit_consume(source, fill_descriptions)— also consumes each attestation, which closes it and returns its rent (if the recorded payer is an executable account, the attestation is only marked consumed and the rent is deferred). Named accounts:submitter(signer),oracle_polymer, Polymer’slocal_consumerPDA (2m1udXnYmaxjSXBBE88yZZcwrtT127DqLcwK9B3WCAus), andintents_protocol.remaining_accountsholds interleaved writable pairs[attestation_0, rent_refund_0, attestation_1, rent_refund_1, …]. For every fill payload thesubmittermust be the attestation’s recorded rent payer — the Solana account that signed the fill, not thefiller_datasolver id — otherwise it fails withUnauthorizedFillSubmitter. A consuming batch therefore cannot mix fills from different fillers. Not-filled payloads can be submitted by anyone.
submitwhose log you have already proven. -
Input side (a Solana order awaiting a remote proof): receiving always ends in
receive_attest(), which reads the validated event from the prover’s result account, maps the source chain id throughChainMapping, and registers theAttestation.
1
Fill, then submit on Solana
fill creates the LocalAttestation; oracle_polymer::submit (or submit_consume) validates it and emits the Prove: log. They can be separate transactions or combined into one if it fits; what matters is which transaction carries the Prove: log.2
Request the proof of the submit transaction
Ask Polymer’s Prove API to prove the transaction that contains the
Prove: log — the one with submit, not a fill-only transaction. Requesting a proof of a transaction without the log fails with “transaction does not contain a Polymer Prove log”.Set srcChainId to 2. This is Polymer’s own protocol id for Solana, not the canonical LI.FI chain id — see chain id namespaces.3
Deliver to receiveSolanaMessage on the input chain
Solana-sourced proofs go to the EVM oracle’s
receiveSolanaMessage, not receiveMessage. The two entry points parse different payload formats and write to different storage, so a proof delivered to the wrong one reverts. Select the entry point based on the output chain type.- Call
create_polymer_accounts(). - Call
load_proof_chunk(chunk)once per chunk. - Call
validate_event()with a compute budget of roughly 1,000,000 CU. - Call
receive_attest().
receive_load_proof(proof), then receive_attest(). In both paths, receive_attest() closes the prover’s scratch PDAs and returns their rent to the signer, who funded it.
The prover’s scratch accounts are derived from the signer alone, so two concurrent receive flows under one signer collide. The second
create_polymer_accounts fails while the accounts exist, and interleaved chunk loads write into the same proof buffer and corrupt it. Serialize receives per signer, or use distinct signers for parallel proofs.Wormhole
Wormhole is a messaging based system that allows contracts to broadcast VAAs (Verified Action Approvals). VAAs are messages signed by the Wormhole Guardian network.- Security through a decentralized guardian set.
- Supports batch proving of multiple outputs in a single VAA.
- Comparatively slow compared to alternatives.
- Broadcast
submit interface. Messages must be encoded into FillDescriptions and then submitted:
receiveMessage on the input chain to validate their intents.
There are many ways to get Wormhole VAAs like the Wormholescan api or the Wormhole SPY.
The Wormhole implementation uses a significantly more efficient validation algorithm than Wormhole’s
Implementation.sol, to save gas.Deployments
The Wormhole oracle is deployed on EVM mainnets; see the Wormhole Oracle Mainnet address table. The Solana implementation is deployed on mainnet; see the Solana program address.- On EVM,
submitpublishes the Wormhole message with consistency level15. - Fetch the signed VAA from the Wormholescan API.
- Delivery is not automatic: the solver (or any caller) must submit the VAA to
receiveMessageon the input chain.
Wormhole on Solana
The Solana Wormhole oracle implementation is theoracle_wormhole Anchor program (program name: wormhole; IDL: wormhole.json). Its mainnet deployment is listed in the deployment overview:
- Output side:
submit(source, fill_descriptions)validates and consumes the fills’LocalAttestationaccounts, then posts one Wormhole message covering all of them (finality: finalized).remaining_accountsholds interleaved writable pairs[attestation_0, rent_refund_0, …], and the batch must not be empty. The namedsubmitterand a freshpost_messageaccount sign; there is no filler-signature requirement. The VAA emitter is the oracle’s PDA. - Input side: the
receiveinstruction verifies a posted VAA, maps the emitter chain viaChainMapping, and creates oneAttestationper payload.remaining_accountsholds one writable destination attestation PDA per decoded payload, in payload order, with no rent-refund slots; the named signer funds their creation.
Hyperlane
Hyperlane is a highly customizable messaging based system that allows contracts to send and receive messages verified through a selected Interchain Security Modules (ISM).- Highly customizable security modules.
- Supports batch proving of multiple outputs in a single message.
- Strong censorship guarantees.
- Automatic or manual relaying.
dispatch function on the Hyperlane mailbox. To configure Hyperlane relaying, provide the relevant customHook and customHookMetadata when calling submit.
Chainlink CCIP
Chainlink CCIP is a messaging based system that allows contracts to send and receive messages verified through Chainlink oracles.- Security through Chainlink’s oracle network.
- Supports batch proving of multiple outputs in a single message.
- SOC2 and ISO 27001 compliant
ccipSend with an EVM2AnyMessage . To submit filled outputs to the CCIP oracle, first call the quote endpoint: getFee to estimate the messaging fee. Then call submit on the output chain, with the required fee, to send the message to the input chain. If an ERC20 token is used to pay the fee, approve the token transfer first.
Axelar
Axelar is a messaging based system that allows contracts to send and receive message verified by Axelar’s Proof of State network.- Security through Axelar’s Proof of State network.
- Supports batch proving of multiple outputs in a single message.
- Automatic relaying.
callContract function. To submit filled outputs to the Axelar oracle, first use the gasService to estimate the fees. Then call submit on the output chain, with the required fee, to send the message to the input chain.
LayerZero
LayerZero is a security customizable messaging based system that allows contracts to send and receive messages verified through a selected set of Decentralized Verifier Networks (DVNs).- Customizable security
- Popular and broad chain compatibility.
- Supports batch proving of multiple outputs in a single message.
- Expensive
send on the LayerZero endpoint. To submit filled outputs to the LayerZero oracle, first use the quote function to estimate fees, then call submit on the output chain, with the required fee, to send the message to the input chain.

