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

# Resource Model

> Resource lifecycle, port behaviors, linear consumption, and the asResource graduation.

> [Flow Structure](/composer/composer-api/concepts/flow-anatomy) showed *where* resources and handles appear in the wire format. This page covers *how they behave*: consumption rules, port behaviors, and the `asResource` graduation.

A Flow's runtime objects come in two flavours: **resources** (tokens that flow through the program and have a balance) and **handles** (typed scalar values like `uint256`, `address`, `bool`). Op calls connect to them through **ports**, which the manifest declares with a type and a mode. The compiler enforces the rules on this page at build time, so most "I expected this to type-check" surprises trace back here.

## Resources

A resource represents a balance the execution proxy holds: either an ERC-20 (`{ kind: "erc20", token, chainId }`) or the native asset (`{ kind: "native", chainId }`).

Resources are created in three ways:

* **Declared as inputs.** A `ResourceInput` declares a resource the flow consumes. The runtime materialiser (e.g. `directDeposit`, `balanceOf`) makes the actual amount available before execution. See [Build a Flow → Wire runtime values](/composer/composer-api/guides/build-a-flow#wire-runtime-values).
* **Produced by an op.** Most LI.FI ops (`lifi.swap`, `lifi.zap`) produce a resource on their `amountOut` port. The receiving op binds that handle to its own input port.
* **Graduated by `core.asResource`.** Sometimes you need to treat the *output of an external contract call* as a tracked resource, for example the receipt token an ERC-4626 vault returns from `deposit()`. `core.asResource` takes a typed handle plus a resource declaration and graduates it into a first-class resource. See the [Op Catalog](/composer/composer-api/ops) for the manifest signature.

### Linear consumption

Resources are **linear** by default: exactly one downstream call may consume a given resource. If two ops both bind to the same resource handle as a consuming input, the compiler rejects the flow with a `linearity_error`. This guarantees the proxy never tries to spend the same balance twice.

A copy-mode binding lets an op read a resource without consuming it: `core.approve` references a resource to approve a spender while leaving the balance available for a later consuming binding. A copy-mode read can coexist with one consuming binding for the same resource. The op manifest's port metadata determines which binding consumes and which only reads. You don't have to track this manually; the SDK's typed handles model the rule.

### Terminal resources

A resource that is **never consumed** by any op is a **terminal resource**. This happens either because it was produced by a terminal op (e.g. the receipt token from a vault deposit) or because a `core.split` output was deliberately left dangling. Terminal resources stay on the proxy at the end of execution and are subject to the flow's `sweepTo` policy. See [Terminal Resources](/composer/composer-api/concepts/sweeping-and-amounts) for the full sweep semantics.

## Handles

A handle is a typed scalar produced by the SDK builder: an input handle for a flow input, an output handle for an op's output port, or a context handle (`builder.context.sender`, `builder.context.executionAddress`). The SDK serialises handles into wire-format `$ref` strings; see [References](/composer/composer-api/concepts/ref-grammar) for the conversion rules and the `raw.ref` escape hatch.

Unlike resources, handles are **non-linear**: the same handle may be referenced by many downstream ops. Reading a handle does not "consume" it. A `uint256` representing a deadline or a slippage tolerance can be wired into every op that needs it.

## Ports

Ops declare typed input and output **ports** in the manifest. Each port has three properties the validator checks at build time:

* **Type.** The value the port carries: a resource (token balance) or a handle (typed scalar).
* **Mode.** For resource ports, whether the binding consumes the resource or only reads it. The default is consuming; copy-mode ports (e.g. `core.approve`'s) read the resource without consuming it.
* **Availability.** Whether the port is an input (the op consumes or reads from it) or an output (the op produces a value other ops can bind).

Bindings whose handle doesn't match a port's type or mode are rejected at compile time.

### Port discrimination

Use the typed handle returned by the builder (`swap.amountOut`) whenever possible; port type and mode are implicit and the validator infers them. Reach for `raw.ref<T>(path)` only for paths the typed API can't reach (see [References](/composer/composer-api/concepts/ref-grammar#raw-refs-escape-hatch)). When you do, the type guards in the manifest decide whether the path is a handle or a resource port; if you pick the wrong type parameter, the validator rejects the flow.

### `providesMinimum`

Some output ports already encode a minimum-out invariant. `lifi.swap.amountOut` is the canonical example: the aggregator bakes in `minOut` from the swap's `slippage` config, so the port declares `providesMinimum: true` in the manifest. The validator rejects redundant minimum-out guards on those ports. See [Guards](/composer/composer-api/concepts/simulation-and-guards#where-guards-can-attach-providesminimum-ports) for the full attachment rules.

> Bindings between ports are written as **refs**. The next page, [References](/composer/composer-api/concepts/ref-grammar), covers the grammar.

## See also

* [Flow Structure](/composer/composer-api/concepts/flow-anatomy) — wire-format shape of inputs and node bindings.
* [References](/composer/composer-api/concepts/ref-grammar) — how SDK handles convert to refs.
* [Terminal Resources](/composer/composer-api/concepts/sweeping-and-amounts) — terminal-resource handling at end of flow.
* [Op Catalog](/composer/composer-api/ops) — `core.asResource` and every other op registered in the manifest.
