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

# Filling an order

> fillOrder, the ladder of guards it walks, and why the taker names the output rather than the payment.

```solidity theme={"system"}
fillOrder(uint256 orderId, uint256 sellAmountOut, uint256 maxAmountIn)
```

<Info>
  **The most important fact on this page.** `sellAmountOut` — the gross amount released from escrow —
  is an **argument**, not a result. What the taker receives is therefore fixed the moment they sign.
  Only the *payment* can move, only for pegged orders, and only up to `maxAmountIn`.
</Info>

## What each side is exposed to

|          | Taker                          | Maker                      |
| -------- | ------------------------------ | -------------------------- |
| receives | **fixed** — it is the argument | bounded below by `minRate` |
| pays     | bounded above by `maxAmountIn` | —                          |

Neither party can be moved past a bound they set themselves. A price swing between signing and
mining can only make the fill revert, never settle badly.

## The order of operations is the safety model

<Steps>
  <Step title="Role — only if the desk has switched it on">
    ```solidity theme={"system"}
    if (takerWhitelistEnabled && !hasRole(TAKER_ROLE, msg.sender)) {
      revert TakerNotWhitelisted(msg.sender);
    }
    ```

    Checked inline rather than by a modifier, because *whether the role is required* is itself
    state. On the live deployment `takerWhitelistEnabled` is **false**, so filling is open to
    anyone — read it on-chain rather than trusting this page.
  </Step>

  <Step title="State and time">
    `status == Open` · `block.timestamp ≤ expiry` · `sellAmountOut ≠ 0` · `sellAmountOut ≤ sellRemaining`
  </Step>

  <Step title="Minimum size — partial fills only">
    ```solidity theme={"system"}
    if (newRemaining != 0) {
      if (sellRemaining >= minOrderAmount) {
        sellAmountOut ≥ minOrderAmount   // otherwise BelowMinFill
      }
    }
    ```

    The threshold applies to what this fill releases, not what it leaves behind. It is skipped when
    the fill clears the order and waived once the order's current remainder is already below the
    threshold. Raising the minimum later therefore does not freeze a small existing remainder.
  </Step>

  <Step title="Quote — the only oracle read on this path">
    Fixed: the stored ratio, no oracle at all. Pegged: the five-minute Orakl reference (strict),
    then the maker's floor check.
  </Step>

  <Step title="The taker's ceiling">
    `amountIn ≤ maxAmountIn`, else `SlippageExceeded`.
  </Step>

  <Step title="Effects — before any transfer">
    `sellRemaining` is decremented; the order is closed and de-indexed if it reaches zero;
    `accruedFees[sellToken] += fee`.
  </Step>

  <Step title="Interactions">
    ```
    buyToken  : taker ──amountIn────────▶ maker
    sellToken : this  ──(out − fee)─────▶ taker
    ```
  </Step>
</Steps>

## Partial fills and the minimum

The rule prevents a normal-sized order from being chipped away through sub-minimum fills. It does
**not** require the remainder after a valid fill to stay above the minimum; the remainder can
always be taken later, including in smaller pieces once it is itself below the threshold.

A UI should make the two simplest valid corrections explicit:

* **take it all** — fill the whole remainder
* **take the minimum** — release `minOrderAmount` of the offered token and show the exact payment

Any larger partial fill is valid too. Rondo asks the user for the payment amount, derives the gross
output, and presents both correction presets using contract-valid integers.

## The taker receives `sellAmountOut − fee`

The argument is the **gross** released from escrow; the desk's cut comes out of it. Anything
integrating directly must gross up, or it will ask for less than it wants.

## Reverts a taker will actually meet

| Error                           | Meaning                                                                                  |
| ------------------------------- | ---------------------------------------------------------------------------------------- |
| `SlippageExceeded`              | The price moved past their ceiling                                                       |
| `BelowMakerFloor`               | It moved past the *maker's* floor; the order paused itself                               |
| `StaleOracle`                   | Pegged only — fixed orders keep filling through an outage                                |
| `OracleTwapUnavailable`         | Pegged only — the five-minute average lacks enough usable observations                   |
| `OrderExpired` · `OrderNotOpen` | Somebody got there first, or the clock ran out                                           |
| `BelowMinFill`                  | A size problem, not a price problem                                                      |
| `TakerNotWhitelisted`           | Only reachable while `takerWhitelistEnabled` is on — it is off on the deployed instances |
