Integration ReferenceEVM Limit Orders

Order Contract Reference

Order fields, rate pricing, fill entry points, remaining amounts and maker cancellation.

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 for signature types, extension bytes and trait bits, and settlement for batch fills and tokenisation.

Order

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

struct Order {
    uint256 salt;
    uint256 maker;
    uint256 receiver;
    uint256 makerAsset;
    uint256 takerAsset;
    uint256 makingAmount;
    uint256 takingAmount;
    uint256 makerTraits;
}
FieldABI typeUnitMeaning
saltuint256IntegerDistinguishes orders and binds the extension hash.
makeruint256Address in low 160 bitsAccount authorizing the order and providing makerAsset.
receiveruint256Address in low 160 bitsRecipient of takerAsset; zero selects the maker. Fee orders select the fee taker.
makerAssetuint256Address in low 160 bitsToken sent by the maker.
takerAssetuint256Address in low 160 bitsToken paid by the taker.
makingAmountuint256makerAsset base unitsFull maker quantity; fixed for a rate order.
takingAmountuint256takerAsset base unitsFull payment for a fixed-price order; creation-time baseline for a rate order.
makerTraitsuint256Packed wordSigned 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

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

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. Outputs: EIP-712 order digest and domain separator, respectively. Events: none. Failures: no order-validation errors; these views do not check authorization, funding or fill conditions. Use the settlement's signature domain.

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 for conversion inputs and outputs.

DirectionmakerAssettakerAssetFixed makingAmount
Buy PTQuotePTQuote budget
Sell PTPTQuotePT quantity
Buy YTQuoteYTQuote budget
Sell YTYTQuoteYT quantity

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

ERC-4626 compliance required.

Spectra assumes its interest-bearing tokens (IBTs) conform to the ERC-4626 standard. Deviations from its exchange-rate, conversion and preview behavior can cause incorrect pricing, accounting discrepancies or failed protocol operations.

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.

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:

FieldTypeMeaning
ptaddressRegistered PT, including for YT quotes.
derivativeKinduint80 PT, 1 YT.
quoteKinduint80 underlying, 1 IBT, 2 vault share.
isSellbooltrue fixes derivative quantity; false fixes quote budget.
amountuint256Nonzero outgoing quantity in that token's base units.
impliedApyWaduint256Effective 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:

FieldsTypesMeaning
derivativeKind, quoteKinduint8, uint8Rate payload enums.
pt, yt, quoteTokenaddress, address, addressResolved market tokens.
maturityuint256Unix seconds.
impliedApyWad, discountFactorWaduint256, uint256Signed APY and current discount factor, WAD.
makingAmount, takingAmountuint256, uint256Full 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. Failures:

ErrorCondition
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

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.

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

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

FunctionAddress 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

Role: read or update the live relative APY shift.

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. Outputs: fee() returns the current shift; setFee returns no value. Events: setFee emits FeeUpdated(uint256 oldFee, uint256 newFee). 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

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

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:

InputMeaning
orderSigned tuple. Maker balance and allowance must cover the fill.
r, vsCompact EIP-2098 signature for an EOA maker.
signatureERC-1271 bytes for a contract maker; empty bytes work only if that maker accepts them.
amountRequested maker quantity in maker-amount mode; requested payment otherwise.
takerTraitsAmount mode, price threshold and argument lengths; see taker traits.
argsPacked 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. Events:

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.

Remaining amount

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

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. 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. Events: none. 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.

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.

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:

FunctionInputs and effect
cancelOrderOriginal traits and digest. For the partial/multiple-fill profile, writes zero remaining for msg.sender.
cancelOrdersEqual-length traits and digest arrays; cancels each pair.
increaseEpochMaker's series; adds one to its current epoch.
advanceEpochMaker's series and an increment from 1..255.
epochMaker and series to read.

Outputs: epoch returns the current uint256 epoch; mutations return no value. Events:

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, series epochs.

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

On this page