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

# The lens

> Rondo Lens — atomic book reads and fill preflight checks in a separate read-only contract.

The Rondo Lens is a separate, read-only contract deployed alongside the
swapper. It holds **no arithmetic of its own**: every price it reports comes from the swapper's own
`previewFill`, so a quote here cannot drift from the fill it predicts.

<Note>
  The swapper sits near the EIP-170 bytecode limit. Keeping convenience reads in the Lens leaves the
  settlement contract smaller. Lens functions hold no state and never receive approvals or writes.
</Note>

Address and its binding to the proxy: [Deployments](/reference/deployments).

## `openOrders` — the whole read, in one call

```solidity theme={"system"}
openOrders(uint256 offset, uint256 limit)
  returns (uint256[] ids, Order[] orders, uint256 nextOffset)
```

This is the function most integrations want, and the reason is correctness rather than convenience.

Paging ids and order data as two separate calls is a race: the open set removes by swapping its last
element into the freed slot, so an order closed between the two reads slides backwards and the reader
ends up pairing **one order's id with another order's data**. In a trading UI that means the ticket
can describe an order the button would not fill. Reading both inside one call puts them in the same
block by construction.

`nextOffset` stops advancing once the sweep reaches the end of the set, so a caller loops until it
does not move.

```ts theme={"system"}
const [ids, orders, nextOffset] = await client.readContract({
  address: LENS, abi: lensAbi, functionName: "openOrders",
  args: [offset, 200n], blockNumber,   // still pin the block across pages
});
```

<Warning>
  One call is atomic; a **sequence** of them is not. Pin `blockNumber` across pages anyway — otherwise
  page 2 can come from a later block than page 1 and the set can have moved between them.
</Warning>

## `quoteFill` — guard-aware preflight

```solidity theme={"system"}
quoteFill(uint256 orderId, uint256 sellAmountOut, address taker)
  returns (uint256 amountIn, uint256 fee, uint256 netOut, FillProblem problem)
```

The swapper's own `previewFill` prices only — by design it will happily quote a cancelled or expired
order. `quoteFill` adds the state, access, size, oracle, balance and allowance checks that a read-only
helper can evaluate, then *returns* the first problem instead of reverting. An interface can render
that reason rather than decode a revert.

| `FillProblem`                                      |                                                           |
| -------------------------------------------------- | --------------------------------------------------------- |
| `None`                                             | It would settle right now                                 |
| `NotOpen` · `Expired`                              | Already closed, or past its deadline                      |
| `Paused`                                           | Trading is halted                                         |
| `NotWhitelisted`                                   | Only while `takerWhitelistEnabled` is on                  |
| `ZeroAmount` · `ExceedsRemaining` · `BelowMinFill` | Size problems                                             |
| `StaleOracle`                                      | Pegged only — fixed orders keep filling through an outage |
| `BelowMakerFloor`                                  | The order has paused itself under its maker's floor       |
| `InsufficientBalance` · `InsufficientAllowance`    | The taker is not ready to pay                             |

The problems are checked in the order `fillOrder` checks them, so the first one reported is the
first one a real call would hit. Pricing is delegated to `previewFill` and never recomputed here;
its maker-floor revert is caught rather than duplicated, because reproducing that comparison would
be a second copy of the rule, free to drift from the one that actually gates the fill.

<Warning>
  `quoteFill` is still **not an `eth_call` simulation of the final transaction**. It has no
  `maxAmountIn` argument, so it cannot report `SlippageExceeded`, and it does not execute either token
  transfer. A transfer failure can therefore stop a fill that the lens reports as `None`. Use it to
  explain known guards, not as an unconditional settlement promise.
</Warning>

## `config` — the settings in one call

```solidity theme={"system"}
config() returns (
  uint16 feeBps, uint16 bandBps, uint64 maxOracleAge, uint64 maxOrderDuration, address feed
)
```

Five getters that would otherwise be five round trips.

## `totalEscrowed` — the solvency check

```solidity theme={"system"}
totalEscrowed(address token) returns (uint256 total)
```

The left-hand side of the invariant in [Topology](/protocol/topology#the-solvency-invariant): what
the contract still owes makers for `token`, across every open order. Compare it against
`token.balanceOf(swapper) − accruedFees(token)` to audit solvency from outside.

It walks the whole open set, so it is for `eth_call` and ops dashboards — never for on-chain use.

## When not to use the lens

Reach for the swapper directly when you are **sending a transaction**. The lens is a read path; the
fill itself takes its arguments from `previewFill` on the swapper, which is the contract that will
execute them. For a responsive client, quote locally for display, confirm against `previewFill`
before building a transaction, and use the lens to read the book and explain why a fill would fail.
