Skip to main content
continuation.settle registers an escrow with LI.FI’s settlement service for a destination flow (config.continuationFlow) that runs after the source flow. Once the escrow holds the minimum funding, LI.FI’s settlement service runs the destination flow from it, and the settlement contract checks the minimum received before it forwards the outcome to destination. It is the op behind every cross-chain flow. It also runs a destination flow later on the source flow’s own chain; see Same-chain continuations.

Ports

output is a future output: its tokens exist only after the destination flow runs, outside the user’s transaction. Leave it unbound. The compile response reports it as a terminal output under outputs['<settle id>.output']. providesMinimum means the port carries the minimum received: the least amount of the outcome token the settlement contract lets through. The settle node accepts no guards; the minimum comes from the destination flow or from outcomes[0].minAmount.

Config

The live schema above shows the shape. The table below adds the rules the compiler enforces on top of it.

Expiry

The settlement service may shorten the expiry you author. The stored value comes back as settlements[<settle id>].escrow.expiresAtMs. Trust that value, not the one you sent.

Minimum received

The compiler proves the destination flow at the escrow’s minimum funding (escrow.floor), the least balance that starts a run. The minimum received for the outcome is:
  • proven is the enforced minimum the destination flow leaves in its proxy, in the outcome token: a guard’s floor, an op’s own minimum such as a swap’s minimum output, or the whole minimum funding for an unused funding input.
  • d is the rounding allowance of the final transfer: 2 wei for a rebasing token such as an Aave aToken, otherwise 0.
  • minAmount is the value you author; '0' counts as omitted.
With neither a proven minimum nor a minAmount, the compile fails and the error names config.outcomes[0].minAmount. A minAmount above what the destination flow can deliver compiles, and then every run reverts until the escrow is refunded. Derive it from the destination flow’s own quote, not from an earlier compile’s output.

Funding rules

The settle node’s bind.input decides how the escrow gets its funds; see Funding the escrow for the model. In every mode, the funding must carry an enforced minimum (amount.minimum): funding with no minimum, or a minimum of 0, fails with validation_error on the settle node’s input port before any escrow is registered. Fund the settle from a declared input deposited with a fixed amount, from a quoted output that provides a minimum (such as lifi.swap’s amountOut), or add a slippage guard on the producing port. A directDeposit with allowNonExact cannot fund a settle directly.
  • Bridge or order funding (bind.input is a future output of the source op, and that op has no destination; funding omitted): the source op pays the escrow directly, and the escrow lives on the source op’s destination chain. The source op is a lifi.bridge or a lifiIntents.order, bound by its amountOut. The minimum funding is the source op’s quoted minimum less a 25 bps margin, or exactly N for an exact-output lifiIntents.order (exactAmountOut: N). The compile then quotes the source op again with the escrow as receiver; if that quote no longer fits the minimum funding, the compile fails with delivery_error.
  • External (funding: 'external'): the escrow lives on the flow’s own chain. bind.input must be a declared input supplied as a plain amount. An upstream output or a directDeposit input is rejected. The response adds a fundEscrow action. When the settle is the only node, the source program is empty: the response has no top-level transactionRequest, and actions holds only the fundEscrow.
  • Inline (bind.input is a declared input or an upstream output on the flow’s chain; funding omitted or 'inline'): the user’s transaction ends with a transfer of the realised amount into an escrow on the same chain, which can differ from escrow.amount when a swap funds it.

Destination flow rules

The destination flow is an ordinary Flow that runs on the escrow’s chain, from a proxy that LI.FI’s executor controls. That chain is the source op’s destination chain for bridge or order funding, and the flow’s own chain for external and inline funding. The guide explains each rule. In short:
  • Declare exactly one input: a resource input in the funding token on the escrow’s chain. The settlement service binds the escrow’s balance to it.
  • Leave every outcome in the destination flow’s proxy. Where a node needs a receiver, bind destFlow.context.executionAddress.
  • Never reference context.sender (inside a destination flow it is LI.FI’s executor), never set an epilogue, and never nest a settle node.
  • A destination flow with no nodes is valid: the escrow then delivers its funding token unchanged.
  • The committed destination flow is limited to 64 KiB.
After a run, the settlement contract checks the minimum received and forwards the outcome to destination; leftover funds go to refund.

Which ops a destination flow can run

When it runs a standard destination flow, LI.FI’s settlement service quotes it again. So every op in a standard destination flow must declare how the settlement verifies it, and an op without that declaration is rejected: The operands of a balance or allowance invariant must be literal addresses and amounts. An amount bound to the destination flow’s funding input is also accepted when the settle node is funded from a declared input with a known amount. Anything else fails with runtime_materialised_address. The set of allowed ops grows release by release. The compile error is the authoritative answer: a rejected op fails with validation_error on the settle node and a forbidden_operation message that names the op and the node.

Exact destination flows

With exact: true, the compiler compiles the destination flow once, as LI.FI’s executor will run it, and the escrow is bound to those bytes. Use an exact destination flow when “done” means one specific call ran, such as an invoice payment, rather than a balance arriving.
  • Funding must be an ERC-20. Native funding fails with validation_error; wrap it first.
  • No verification declaration is needed, so core.call, core.transfer and other ops that the table above rejects are allowed: a node may pay a third party.
  • No node may quote or prepare off chain: lifi.swap, paraswap.buy, core.peek and prepared ops fail at that node. Ops whose output lands later (lifi.bridge, lifiIntents.order) are rejected too. The source flow may still quote.
  • Name no funding amount in the destination flow. When it runs, the executor’s proxy pulls the funding token it received, at most escrow.cap (How much a run spends), and checks on chain that it pulled at least escrow.floor (less a rounding allowance for rebasing tokens; exactly escrow.floor for USDC).
  • Each outcome needs a positive minimum. To return a surplus, fund the escrow above what the destination flow spends.
  • outcomes: [] is allowed. The destination flow must then run on the funding chain, and the response has no outputs['<settle id>.output'].
  • A payment to a third party counts as lost value for the price-impact check: a destination flow that takes 1,050 USDC in, pays 1,000 and returns 50 fails price_impact_exceeded at 9,524 bps. Pass maxPriceImpactBps: 0 in the run to turn the check off. It is then off for the whole flow, so a swap in the source flow is bounded only by its own slippage; compare its price with an independent source.
The response adds settlements[<settle id>].binding. The compile already checks it; you can also check it yourself before anyone funds the escrow.

How much a run spends

A run starts once the balance reaches escrow.floor, and it spends min(balance, escrow.cap), where escrow.cap is amount + floor(amount / 10): the expected funding plus 10%.
Do not send more than the expected funding amount. After a run, a balance above escrow.cap is not used and is not refunded automatically: it stays in the escrow under escrow.owner’s control, and LI.FI provides no tool to withdraw it. If the destination flow never runs, the refund sends the escrow’s whole balance to refund.

Example

Bridge 1,000 USDC from Arbitrum into an escrow on Base, and deposit it into Aave there once it lands. The full runnable version, with the submit and tracking loops, is the Bridge and deposit recipe.
The flow wire format shows the settle node as JSON.

Errors

A settle node that breaks an authoring rule fails with a 400 validation_error, not with continuation_error. path is the settle node unless the table says otherwise, port is set when the problem is a binding, and fix names the edit. The <reason> in continuation verification derivation failed (<reason>): … tells you what to change: