> ## Documentation Index
> Fetch the complete documentation index at: https://docs.li.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# continuation.settle

> Fund an escrow, on the destination chain of a bridge or on the flow's own chain, and run a destination flow from it later, with the minimum received checked on chain.

`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](https://docs.li.fi/composer/composer-api/concepts/cross-chain-flows.md). It also runs a destination flow later on the source flow's own chain; see [Same-chain continuations](https://docs.li.fi/composer/composer-api/concepts/cross-chain-flows.md#same-chain-continuations).

## Ports

| Port | Direction | Kind | Meaning |
| - | - | - | - |
| `input` | in | resource, linear, any token | The funding: a `lifi.bridge` or `lifiIntents.order` output, a declared flow input, or an upstream op's output. Its token and chain decide the escrow's token and chain. |
| `output` | out | resource, linear, `availability: future`, `providesMinimum` | The outcome. It reaches `outcomes[0].destination` after the destination flow runs, not during the user's transaction. |

`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.

| Field | Type | Required | Default | Rules |
| - | - | - | - | - |
| `outcomes` | `{ token, destination, chainId, minAmount? }[]` | yes | — | At most one entry. Add another settle node for each further delivery. `[]` is allowed only with `exact: true`. |
| `outcomes[].token` | address | yes | — | The token the **destination flow produces** and leaves in its proxy, for example the aToken a zap mints. It is the funding token only when the destination flow delivers its funding unchanged. For a native outcome on Tempo or Arc, name the native ERC-20 (pathUSD on Tempo, USDC on Arc), not the zero address. |
| `outcomes[].destination` | address | yes | — | Receives the outcome on the destination chain. The zero address is rejected. |
| `outcomes[].chainId` | number | yes | — | Must equal the escrow's chain. A destination flow cannot bridge: deliver the funds into an escrow on the outcome's chain instead. |
| `outcomes[].minAmount` | decimal string, base units | no | the minimum the destination flow proves | Set it only when the destination flow produces the token without an enforced minimum. `'0'` counts as omitted. See [Minimum received](#minimum-received). |
| `continuationFlow` | `Flow` | yes in practice | — | The destination flow. The schema marks it optional, but a settle without one fails with `validation_error`. |
| `validity.expiresAtMs` | integer, epoch milliseconds | yes | — | Must be in the future. For bridge or order funding, at least `max(3 × the delivery's quoted ETA, 30 minutes)` away. See [Expiry](#expiry). |
| `provider` | string | no | `'intent-factory'` | The settlement service. `'intent-factory'` is the only value; omit the field. |
| `funding` | `'inline' \| 'external'` | no | `'inline'` | Set `'external'` to fund the escrow with a separate transfer. Omit it for bridge or order funding: any value there is rejected. |
| `refund` | address | no | the signer | Receives the escrow's balance when it is refunded (after expiry, or after a run that fails for good), plus the destination flow's leftovers after a run. Must be an address you control **on the destination chain**. With `funding: 'external'`, the default refunds the signer, not the payer. |
| `exact` | boolean | no | `false` | Binds the escrow to the destination flow's compiled calldata. Requires ERC-20 funding. See [Exact destination flows](#exact-destination-flows). |

### 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:

```text theme={"system"}
minimum received = max(proven - d, minAmount + d), clamped at 0
```

* `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](https://docs.li.fi/composer/composer-api/concepts/cross-chain-flows.md#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](https://docs.li.fi/composer/composer-api/ops.md#future-outputs) 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`](https://docs.li.fi/composer/composer-api/ops/lifi-bridge) or a [`lifiIntents.order`](https://docs.li.fi/composer/composer-api/ops/lifi-intents-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](https://docs.li.fi/composer/composer-api/guides/build-a-cross-chain-flow.md#1-write-the-destination-flow) 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:

| Ops | In a standard destination flow |
| - | - |
| `core.add` and the other arithmetic ops, `core.assert*` | Allowed |
| `core.split`, `core.splitAt`, `core.partition`, `core.merge`, `core.asResource` | Allowed |
| `core.balanceOf` | Allowed when it reads the destination flow's proxy. With an `owner`, it is rejected. |
| `lifi.swap`, `lifi.zap`, `paraswap.buy`, `fly.swap` | Allowed when every output stays in the destination flow's proxy. A `lifi.zap` with any other `recipient` is rejected. |
| `uniswapV2.addLiquidity`, `uniswapV2.removeLiquidity` | Allowed |
| `invariant.balance*`, `invariant.allowance*` | Allowed. Each adds a predicate that the settlement contract checks. |
| The numeric invariants (`invariant.numeric`, `invariant.numericInRange`, `invariant.gte` and the other comparisons) | Rejected: they read a register, not chain state |
| `core.transfer`, `core.approve`, `core.call`, `core.staticCall`, `core.rawCall` | Rejected: they move assets out of the proxy or call arbitrary contracts, which no balance check can verify. Use an [exact destination flow](#exact-destination-flows). |
| `lifi.bridge`, `lifiIntents.order` | Rejected: their output lands after the run |
| Every other op, for example `aave.*`, `morphoBlue.*`, `uniswapV3.*`, `core.peek` | Rejected: no settlement verification yet |

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](#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`](https://docs.li.fi/composer/composer-api/reference/flow-wire-format#settlements). The compile already checks it; you can also [check it yourself](https://docs.li.fi/composer/composer-api/guides/build-a-cross-chain-flow.md#optional-verify-the-binding-before-funding) 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%.

> [!WARNING]
>
> 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](https://docs.li.fi/composer/composer-api/recipes/bridge-and-deposit.md) recipe.

```ts theme={"system"}
import { createComposeSdk, guards, materialisers, resources } from '@lifi/composer-sdk';

const ARBITRUM = 42161;
const BASE = 8453;
const ARB_USDC = '0xaf88d065e77c8cC2239327C5EDb3A432268e5831';
const BASE_USDC = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
const A_BAS_USDC = '0x4e65fE4DbA92790696d040ac24Aa414708F5c0AB'; // Aave V3 aUSDC on Base
const owner = '0xYourSignerAddress';

const sdk = createComposeSdk({
  baseUrl: 'https://composer.li.quest',
  apiKey: process.env.LIFI_API_KEY!,
});

// The destination flow: runs later on Base, from the escrow.
const destFlow = sdk.flow(BASE, {
  name: 'deposit-on-base',
  inputs: { funding: resources.erc20(BASE_USDC, BASE) },
});
destFlow.lifi.zap('deposit', {
  bind: { amountIn: destFlow.inputs.funding },
  config: { resourceOut: resources.erc20(A_BAS_USDC, BASE) },
  guards: [guards.slippage({ port: 'amountOut', bps: 50 })], // proves the minimum received
});

// The source flow: runs now, on Arbitrum.
const source = sdk.flow(ARBITRUM, {
  name: 'bridge-and-deposit',
  inputs: { amountIn: resources.erc20(ARB_USDC, ARBITRUM) },
});
const bridge = source.lifi.bridge('bridge', {
  bind: { amountIn: source.inputs.amountIn },
  config: { resourceOut: resources.erc20(BASE_USDC, BASE) }, // no destination: delivers into the escrow
});
source.continuation.settle('settle', {
  bind: { input: bridge.amountOut },
  config: {
    outcomes: [{ token: A_BAS_USDC, destination: owner, chainId: BASE }],
    continuationFlow: destFlow.build(),
    validity: { expiresAtMs: Date.now() + 60 * 60 * 1000 },
    refund: owner, // must be an address you control on Base
  },
});

const result = await source.compile({
  signer: owner,
  inputs: { amountIn: materialisers.directDeposit({ amount: '1000000000' }) }, // 1,000 USDC
  sweepTo: source.context.sender, // returns the bridge's unspentIn, if any, on Arbitrum
});
console.log(result.settlements?.settle?.escrow, result.outputs['settle.output']?.amount);
```

The [flow wire format](https://docs.li.fi/composer/composer-api/reference/flow-wire-format.md#continuationsettle-node) 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.

| Error | Cause | Fix |
| - | - | - |
| `validation_error` | `validity.expiresAtMs` is not in the future. | Set a future time. |
| `validation_error` | More than one entry in `outcomes`. | Add one settle node per outcome. |
| `validation_error` | `outcomes: []` without `exact: true`. | Add an outcome, or make the destination flow exact. |
| `validation_error` | The funding chain or the outcome chain is not [served](https://docs.li.fi/composer/composer-api/concepts/cross-chain-flows.md#availability) (`port: input` for the funding chain). | Use a served chain for both. |
| `validation_error` | `outcomes[].chainId` differs from the escrow's chain. | Deliver the funds into an escrow on the outcome's chain. |
| `validation_error` | `funding` is set on a settle funded by `lifi.bridge` or `lifiIntents.order`. | Omit `funding`. |
| `validation_error` | `funding: 'external'` on an upstream output or a `directDeposit` input. | Bind a declared input and supply a plain amount. |
| `validation_error` | A `lifi.bridge` or `lifiIntents.order` without `destination` whose output funds no settle node (`path` is that op). | Set its `destination`, or bind its output to a settle node. |
| `validation_error` | No `continuationFlow`. | Pass `destFlow.build()`. |
| `validation_error` | The funding has no enforced minimum (`port: input`). | See [Funding rules](#funding-rules). |
| `validation_error` | No proven minimum and no `minAmount` for an outcome. | Set `config.outcomes[0].minAmount`, or leave a guarded outcome in `context.executionAddress`. |
| `validation_error` | `exact: true` with native-coin funding (`port: input`). | Wrap the native coin first. |
| `validation_error` | A node of an exact destination flow quotes or prepares off chain, or its route expires (`path` is that node). | Replace the node; see [Exact destination flows](#exact-destination-flows). |
| `validation_error` | A settle funded by a zero-outcome settle's `output` (`port: input`). | Fund it from another output. |
| `validation_error`: `continuation verification derivation failed (<reason>)` | The compiler cannot derive a verifiable settlement from the destination flow. | See the reasons below. |
| The destination flow's own kind, message `continuation leg of '<id>' failed at the funding floor` | A node of the destination flow fails when compiled at the minimum funding. | Read the rest of the message: for example, a zap with no route, or a guard that cannot hold at the minimum. |
| `delivery_error` (422), `details.reason: 'floor_drift'` | The bridge's or order's second quote, to the escrow, fell below the minimum funding registered from the first. `path` is that op. | Compile again. |
| `delivery_error` (422), `details.reason: 'eta_exceeds_expiry'` | The escrow expires before the delivery's ETA allows. | Set a later `validity.expiresAtMs`. |
| `delivery_error` (422), `details.reason: 'quote_failed'` | The second quote failed. `details.cause` names its kind, such as `no_route_error`. A top-level `shortfall` (`required`, `available`) means the order needs more input than the source flow guarantees. | Compile again, or fund the source flow with more. |
| `price_impact_exceeded` (422) | An exact destination flow pays a third party, which reads as lost value. | Pass `maxPriceImpactBps: 0`, with the care described in [Exact destination flows](#exact-destination-flows). |
| `provider_error` (422) | The named `provider` is not registered, or an exact destination flow's binding check failed (missing binding, wrong wrap, hash mismatch, different executor). | Do not fund anything; compile again. |
| `resolution_error` (503) | LI.FI's settlement service was unreachable while registering the escrow. | Retry the same flow. |

The `<reason>` in `continuation verification derivation failed (<reason>): …` tells you what to change:

| Reason | Meaning |
| - | - |
| `forbidden_operation` | A node runs an op that declares no settlement verification, or delivers an output outside the destination flow's proxy. Remove or replace the node, bind the output to `context.executionAddress`, or use an [exact destination flow](#exact-destination-flows). See [Which ops a destination flow can run](#which-ops-a-destination-flow-can-run). |
| `leg_binds_sender` | The destination flow references `context.sender`, which there is LI.FI's executor. Bind `context.executionAddress` instead. |
| `leg_names_epilogue` | The destination flow sets its own `epilogue`. Remove it; the compiler writes its forwards. |
| `non_enumerable_token_graph` | The destination flow does not declare exactly one resource input. |
| `runtime_materialised_address` | An asserting node reads an operand only known at runtime. Bind a literal, or the destination flow's funding input. |
| `invalid_thunk` | The destination flow disagrees with its settle node (chain, funding asset), or a node's config does not match its ports. A zero-outcome exact destination flow on another chain also fails here. |
| `program_too_large` | The committed program exceeds the settlement service's size limit. Use fewer nodes or invariants. |

## Related

* [Cross-chain flows](https://docs.li.fi/composer/composer-api/concepts/cross-chain-flows.md): the model, guarantees and served chains.
* [Build a cross-chain flow](https://docs.li.fi/composer/composer-api/guides/build-a-cross-chain-flow.md): step by step.
* [Escrow status](https://docs.li.fi/composer/composer-api/reference/escrow-status.md): track the escrow and its refund.
* [Flow wire format: `settlements`](https://docs.li.fi/composer/composer-api/reference/flow-wire-format#settlements): every response field a settle node adds.
* Recipes: [Bridge and deposit](https://docs.li.fi/composer/composer-api/recipes/bridge-and-deposit.md) and [Pay cross-chain](https://docs.li.fi/composer/composer-api/recipes/pay-cross-chain.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.