# Order Contract Reference



`LimitOrderProtocol` settles maker-signed orders. Signing reserves no tokens:
the maker must hold `makerAsset` and approve it to `LimitOrderProtocol` when
a fill executes. Spectra's rate getter computes the payment for PT/YT orders
at the signed APY.

See [encoding](/docs/integration-reference/evm-limit-orders/encoding) for
signature types, extension bytes and trait bits, and
[settlement](/docs/integration-reference/evm-limit-orders/quotes-and-execution)
for batch fills and tokenisation.

## Order [#order]

The ABI-equivalent tuple expands the upstream `Address` and `MakerTraits`
types to `uint256`:

```solidity
struct Order {
    uint256 salt;
    uint256 maker;
    uint256 receiver;
    uint256 makerAsset;
    uint256 takerAsset;
    uint256 makingAmount;
    uint256 takingAmount;
    uint256 makerTraits;
}
```

| Field          | ABI type  | Unit                    | Meaning                                                                             |
| -------------- | --------- | ----------------------- | ----------------------------------------------------------------------------------- |
| `salt`         | `uint256` | Integer                 | Distinguishes orders and binds the extension hash.                                  |
| `maker`        | `uint256` | Address in low 160 bits | Account authorizing the order and providing `makerAsset`.                           |
| `receiver`     | `uint256` | Address in low 160 bits | Recipient of `takerAsset`; zero selects the maker. Fee orders select the fee taker. |
| `makerAsset`   | `uint256` | Address in low 160 bits | Token sent by the maker.                                                            |
| `takerAsset`   | `uint256` | Address in low 160 bits | Token paid by the taker.                                                            |
| `makingAmount` | `uint256` | `makerAsset` base units | Full maker quantity; fixed for a rate order.                                        |
| `takingAmount` | `uint256` | `takerAsset` base units | Full payment for a fixed-price order; creation-time baseline for a rate order.      |
| `makerTraits`  | `uint256` | Packed word             | Signed fill permissions, expiry, epoch and extension flags.                         |

Without amount getters, settlement uses the signed token ratio. Spectra
rate getters recompute the counter-amount at execution.

### Hashing [#hashing]

**Role:** identify the order in the execution chain's settlement domain.

```solidity
function hashOrder(Order calldata order) external view returns (bytes32);
function DOMAIN_SEPARATOR() external view returns (bytes32);
```

**Inputs:** the eight signed fields for `hashOrder`; none for `DOMAIN_SEPARATOR`.
&#x2A;*Outputs:** EIP-712 order digest and domain separator, respectively.
&#x2A;*Events:** none. &#x2A;*Failures:** no order-validation errors; these views do
not check authorization, funding or fill conditions. Use the settlement's
[signature domain](/docs/integration-reference/evm-limit-orders/encoding#signature-domain).

## Rate orders [#rate-orders]

A rate order fixes the maker's outgoing quantity and an effective annually
compounded APY. The quote token is the registered PT's underlying, IBT, or
the vault share wrapped by its `Spectra4626Wrapper` IBT. The asset pair
determines the direction; the order has no `orderType` field.

For a wrapper market, **vault share** means the original vault token deposited
into `Spectra4626Wrapper`. The token issued by the wrapper is the **IBT** used
by the PT market. The wrapper's `vaultShare()` returns the original token's
address; `wrap` converts that token into IBT and `unwrap` converts IBT back.
Vault-share quotes are supported only when the market's IBT exposes this
wrapper interface. See the [wrapper reference](/docs/technical-reference/contract-functions/spectra4626wrapper#wrap)
for conversion inputs and outputs.

| Direction | `makerAsset` | `takerAsset` | Fixed `makingAmount` |
| --------- | ------------ | ------------ | -------------------- |
| Buy PT    | Quote        | PT           | Quote budget         |
| Sell PT   | PT           | Quote        | PT quantity          |
| Buy YT    | Quote        | YT           | Quote budget         |
| Sell YT   | YT           | Quote        | YT quantity          |

The [rate payload](/docs/integration-reference/evm-limit-orders/encoding#rate-payload)
names the PT, derivative kind, quote kind and APY. APY uses WAD precision:
`50000000000000000` means 5%. PT accepts zero APY; YT requires positive APY.

<Callout type="warn">
  **ERC-4626 compliance required.**

  Spectra assumes its interest-bearing tokens (IBTs) conform to the
  [ERC-4626 standard](https://eips.ethereum.org/EIPS/eip-4626). Deviations from
  its exchange-rate, conversion and preview behavior can cause incorrect
  pricing, accounting discrepancies or failed protocol operations.
</Callout>

## Pricing views [#pricing-views]

**Role:** obtain fee-free pricing from `SpectraPtYtRateAmountGetter`.

`SPECTRA_REGISTRY()` takes no arguments and returns the `address` of the
Spectra registry used to check whether the quoted PT is registered. The
address is set by the getter's constructor.

```solidity
function previewOrder(Order calldata order, bytes calldata extension)
    external view returns (RateOrderPreview memory preview);
function quoteTakingAmount(RateQuoteParams calldata params)
    external view returns (uint256 fullTaking, uint256 discountFactorWad);
function quoteDiscountFactor(address pt, uint256 impliedApyWad)
    external view returns (uint256 discountFactorWad, uint256 maturity);
```

**Inputs:** `previewOrder` reads the order's maker quantity, asset pair and
extension payload. `quoteDiscountFactor` takes the PT and WAD APY.
`RateQuoteParams` has these fields in ABI order:

| Field            | Type      | Meaning                                                       |
| ---------------- | --------- | ------------------------------------------------------------- |
| `pt`             | `address` | Registered PT, including for YT quotes.                       |
| `derivativeKind` | `uint8`   | `0` PT, `1` YT.                                               |
| `quoteKind`      | `uint8`   | `0` underlying, `1` IBT, `2` vault share.                     |
| `isSell`         | `bool`    | `true` fixes derivative quantity; `false` fixes quote budget. |
| `amount`         | `uint256` | Nonzero outgoing quantity in that token's base units.         |
| `impliedApyWad`  | `uint256` | Effective annual APY, WAD.                                    |

**Outputs:** `fullTaking` is the full counter-amount in the other token's
base units. `discountFactorWad` is the WAD discount factor; `maturity` is
Unix seconds. `RateOrderPreview` returns these fields in ABI order:

| Fields                               | Types                           | Meaning                                            |
| ------------------------------------ | ------------------------------- | -------------------------------------------------- |
| `derivativeKind`, `quoteKind`        | `uint8`, `uint8`                | Rate payload enums.                                |
| `pt`, `yt`, `quoteToken`             | `address`, `address`, `address` | Resolved market tokens.                            |
| `maturity`                           | `uint256`                       | Unix seconds.                                      |
| `impliedApyWad`, `discountFactorWad` | `uint256`, `uint256`            | Signed APY and current discount factor, WAD.       |
| `makingAmount`, `takingAmount`       | `uint256`, `uint256`            | Full amounts in their respective token base units. |

With `t = (maturity - block.timestamp) / 365 days` and `D = (1 + APY)^t`,
PT value is `claim / D`; YT value is `claim × (D - 1) / D`. Time in years
is floored to WAD precision. Claims use `convertToUnderlying`,
`previewRedeemForIBT`, or the wrapper's `previewUnwrap` of that IBT claim.
Taking amounts round up; inverse making amounts round down. Partial
quotes scale the current full-order price.

**Events:** none. &#x2A;*Failures:**

| Error                             | Condition                                                    |
| --------------------------------- | ------------------------------------------------------------ |
| `InvalidRateData()`               | Invalid payload, unsupported enums or zero PT.               |
| `ZeroMakingAmount()`              | Maker quantity is zero.                                      |
| `InvalidApy(uint256)`             | APY exceeds `10e18` (1,000%), or YT APY is zero.             |
| `UnregisteredPT(address)`         | PT is absent from the registry.                              |
| `InconsistentYT(address,address)` | YT has a wrong PT identity or different decimals.            |
| `InvalidOrderAssets()`            | Pair does not match the selected derivative and quote.       |
| `IbtNotAWrapper(address)`         | Vault-share quote has no readable, nonzero `vaultShare()`.   |
| `OrderMatured(uint256)`           | Current timestamp is at or after maturity.                   |
| `MaturityTooFar(uint256)`         | More than `10 × 365 days` remain.                            |
| `ZeroRatePrice()`                 | Pricing rounds to zero or the buy-price denominator is zero. |

`quoteDiscountFactor` validates a PT/underlying market; it does not validate
YT or an order asset pair. External views and arithmetic can also revert.
A successful preview does not verify signature, expiry, funding,
cancellation or outer extension wiring. Fee orders add fee pricing.

## Fee orders [#fee-orders]

`SpectraRateFeeTaker` computes the fee-adjusted payment and splits it after
settlement. A fee order names it as receiver, both amount getters and
post-interaction target, enables post-interaction and forbids maker native
unwrap. See the exact [public fee extension](/docs/integration-reference/evm-limit-orders/encoding#public-fee-extension).

The fee is a relative APY shift. With `WAD = 1e18`, the fee APY is
`floor(apyWad × (WAD ± fee) / WAD)`: `+` for buy-PT/sell-YT, `−` for
sell-PT/buy-YT. A 2% relative fee shifts 10% APY to 10.2% or 9.8%.
The maker receives the fee-free amount, or one base unit more from
rounding; the remainder goes in `takerAsset` to the registry's fee collector.

### Read contract addresses [#read-contract-addresses]

These read-only functions on `SpectraRateFeeTaker` take no arguments and
each return one `address`. Their values are set by the constructor:

| Function                 | Address returned and its role                                |
| ------------------------ | ------------------------------------------------------------ |
| `LIMIT_ORDER_PROTOCOL()` | The settlement allowed to call the fee-payment callback.     |
| `RATE_GETTER()`          | The pricing contract used to calculate the fee-free payment. |
| `SPECTRA_REGISTRY()`     | The registry from which the fee collector is read.           |
| `FEE_ADMIN()`            | The account allowed to change the fee through `setFee`.      |

### Fee administration [#fee-administration]

**Role:** read or update the live relative APY shift.

```solidity
function fee() external view returns (uint256);
function setFee(uint256 newFee) external;
```

**Inputs:** only immutable `FEE_ADMIN` may call `setFee`; `newFee` is WAD
and must be at most `0.2e18`. &#x2A;*Outputs:** `fee()` returns the current shift;
`setFee` returns no value. &#x2A;*Events:** `setFee` emits
`FeeUpdated(uint256 oldFee, uint256 newFee)`.
&#x2A;*Failures:** `OnlyFeeAdmin()` or `FeeTooHigh(uint256)`.

Fee pricing rejects invalid wiring with `NotFeeOrder()` and a zero fee-ratio
denominator with `FeeRateOutOfDomain()`. Only the configured settlement may
invoke the payment-split callback; other callers get `OnlyLimitOrderProtocol()`.
Pricing and transfer failures also revert the fill.

## Fills [#fills]

**Role:** verify maker authorization and settle a full or partial order.
The immediate caller is the taker. `TakerTraits` encodes as `uint256` below.

```solidity
function fillOrder(
    Order calldata order, bytes32 r, bytes32 vs, uint256 amount,
    uint256 takerTraits
) external payable returns (uint256 makingAmount, uint256 takingAmount, bytes32 orderHash);
function fillOrderArgs(
    Order calldata order, bytes32 r, bytes32 vs, uint256 amount,
    uint256 takerTraits, bytes calldata args
) external payable returns (uint256 makingAmount, uint256 takingAmount, bytes32 orderHash);
function fillContractOrder(
    Order calldata order, bytes calldata signature, uint256 amount,
    uint256 takerTraits
) external returns (uint256 makingAmount, uint256 takingAmount, bytes32 orderHash);
function fillContractOrderArgs(
    Order calldata order, bytes calldata signature, uint256 amount,
    uint256 takerTraits, bytes calldata args
) external returns (uint256 makingAmount, uint256 takingAmount, bytes32 orderHash);
```

**Inputs:**

| Input         | Meaning                                                                                                                                                       |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `order`       | Signed tuple. Maker balance and allowance must cover the fill.                                                                                                |
| `r`, `vs`     | Compact EIP-2098 signature for an EOA maker.                                                                                                                  |
| `signature`   | ERC-1271 bytes for a contract maker; empty bytes work only if that maker accepts them.                                                                        |
| `amount`      | Requested maker quantity in maker-amount mode; requested payment otherwise.                                                                                   |
| `takerTraits` | Amount mode, price threshold and argument lengths; see [taker traits](/docs/integration-reference/evm-limit-orders/encoding#taker-traits-and-fill-arguments). |
| `args`        | Packed target, signed extension and taker interaction. Rate orders use an `Args` method to supply their extension.                                            |

Authorization is checked on the first fill. Later partial fills use the
stored remainder and still enforce current execution conditions. Fills
clamp to the remaining maker quantity; the threshold preserves the
caller's maximum-payment or minimum-maker-quantity rate.

**Outputs:** actual `makingAmount` and `takingAmount` in their respective
token base units, plus `orderHash`. &#x2A;*Events:**

```solidity
event OrderFilled(bytes32 orderHash, uint256 remainingAmount);
```

`remainingAmount` is the maker quantity left after the fill.

**Failures:** `BadSignature()`, `InvalidatedOrder()`, `OrderExpired()`,
`PrivateOrder()`, `WrongSeriesNonce()`, `TakingAmountTooHigh()`,
`MakingAmountTooLow()`, `PartialFillNotAllowed()` or `SwapWithZeroAmount()`.
Invalid extension binding, paused settlement, pricing, callbacks and token
transfers can also revert the whole fill.

Source: [settlement entry points and fill checks](https://github.com/1inch/limit-order-protocol/blob/4.3.2/contracts/OrderMixin.sol#L129-L440).

## Remaining amount [#remaining-amount]

**Role:** inspect orders that allow both partial and multiple fills. This
profile stores remaining maker quantity by maker and order hash.

```solidity
function remainingInvalidatorForOrder(address maker, bytes32 orderHash)
    external view returns (uint256 remaining);
function rawRemainingInvalidatorForOrder(address maker, bytes32 orderHash)
    external view returns (uint256 remainingRaw);
```

**Inputs:** maker and settlement order digest. &#x2A;*Outputs:** `remaining` is
in `makerAsset` base units. Raw zero means untouched; otherwise
`~remainingRaw` is the remaining quantity. Full fill and single cancellation
both encode zero remaining; distinguish them with events. &#x2A;*Events:** none.
&#x2A;*Failures:** the decoded view reverts with `RemainingInvalidatedOrder()`
for an untouched order; the raw view returns zero. Neither view checks
other fill conditions.

Source: [remaining invalidator](https://github.com/1inch/limit-order-protocol/blob/4.3.2/contracts/libraries/RemainingInvalidatorLib.sol).

## Cancellation [#cancellation]

**Role:** invalidate one order, a batch, or an epoch of the maker's orders.
The maker calls the original settlement. Cancellation has no fill pause gate.
`MakerTraits` encodes as `uint256` below.

```solidity
function cancelOrder(uint256 makerTraits, bytes32 orderHash) public;
function cancelOrders(uint256[] calldata makerTraits, bytes32[] calldata orderHashes) external;
function increaseEpoch(uint96 series) external;
function advanceEpoch(uint96 series, uint256 amount) public;
function epoch(address maker, uint96 series) public view returns (uint256);
```

**Inputs:**

| Function        | Inputs and effect                                                                                          |
| --------------- | ---------------------------------------------------------------------------------------------------------- |
| `cancelOrder`   | Original traits and digest. For the partial/multiple-fill profile, writes zero remaining for `msg.sender`. |
| `cancelOrders`  | Equal-length traits and digest arrays; cancels each pair.                                                  |
| `increaseEpoch` | Maker's series; adds one to its current epoch.                                                             |
| `advanceEpoch`  | Maker's series and an increment from `1..255`.                                                             |
| `epoch`         | Maker and series to read.                                                                                  |

**Outputs:** `epoch` returns the current `uint256` epoch; mutations return
no value. &#x2A;*Events:**

```solidity
event OrderCancelled(bytes32 orderHash);
event BitInvalidatorUpdated(address indexed maker, uint256 slotIndex, uint256 slotValue);
event EpochIncreased(address indexed maker, uint256 series, uint256 newEpoch);
```

Single and batch cancellation emit `OrderCancelled` for the partial/multiple-fill
profile. Other profiles invalidate a nonce bit and emit `BitInvalidatorUpdated`;
orders sharing that bit are affected together. Epoch advances emit
`EpochIncreased`; subsequent fills require equality with the signed epoch.
The epoch check requires the partial/multiple-fill profile.

**Failures:** `MismatchArraysLengths()` for unequal batch arrays;
`AdvanceEpochFailed()` for an increment outside `1..255`.

Series `0` groups that maker's epoch-checked orders across markets on this
settlement. Advancing it leaves other series and orders without epoch
checks unaffected. Delisting or revoking allowance does not record
cancellation. A fill can execute before a pending cancellation is included.

Source: [cancellation](https://github.com/1inch/limit-order-protocol/blob/4.3.2/contracts/OrderMixin.sol#L80-L108),
[series epochs](https://github.com/1inch/limit-order-protocol/blob/4.3.2/contracts/helpers/SeriesEpochManager.sol#L23-L47).

## Authorization helpers [#authorization-helpers]

These two contracts expose a read-only function with no arguments and one
`address` return. The address is set by the respective constructor:

| Contract and function                                 | Address returned and its role                                              |
| ----------------------------------------------------- | -------------------------------------------------------------------------- |
| `SpectraLimitOrderSigner.LOP()`                       | The settlement whose order hash is used when a Safe authorizes an order.   |
| `SpectraAuthorizedTakersGuard.LIMIT_ORDER_PROTOCOL()` | The only settlement allowed to invoke the guard's authorized-caller check. |
