Integration ReferenceEVM Limit Orders

Batch Settlement

Batch fill inputs, outputs, tokenisation callbacks and router execution constraints.

SpectraLimitOrderBatchFiller fills several orders in one call using per-token budgets supplied by its caller. It calls the 1inch settlement once per order. Direct fills send maker assets to the caller; tokenised fills first send them to SpectraLimitOrderTokeniser to mint or redeem the market's PT/YT pair.

The order reference defines the signed order, pricing and cancellation interfaces. The order-book HTTP reference defines order publication, listing and quote formats.

Protect the taker's final output. Settlement enforces the maker's quote, not the taker's final proceeds after conversions on the maker's underlying or vault-share leg, tokenisation or later AMM swaps. Always include ASSERT_MIN_BALANCE in the final receive token, after all swaps and output conversions and before transferring the output. Per-fill thresholds and minMakingFilled do not replace this final check.

Batch filler

The batch filler is the settlement's immediate taker, including when called through the router. It pulls each budget once, executes the fills in order, then refunds remaining budget-token balances to its caller.

Read contract addresses

These read-only functions take no arguments and each return one address, set by the batch filler's constructor:

FunctionAddress returned and its role
LIMIT_ORDER_PROTOCOL()The settlement called for each order in fillMany.
TOKENISER()The conversion contract used for tokenised fills and allowed to draw from the batch's budgets.

Data structures

Order refers to the signed-order ABI tuple. The layouts below expand TakerTraits to its ABI type, uint256, and IERC20 to address.

struct Fill {
    Order order;
    bytes signature;
    bool contractMaker;
    uint256 amount;
    uint256 takerTraits;
    bytes extension;
    bytes interaction;
    uint256 gasLimit;
}

struct Budget {
    address token;
    uint256 amount;
}
Fill fieldMeaning and constraint
orderSigned Order. Maker allowed-sender bits must be zero.
signatureWith contractMaker = false, exactly 64 bytes containing compact r || vs. Otherwise, the ERC-1271 signature bytes.
contractMakerSelects fillContractOrderArgs when true; otherwise selects fillOrderArgs.
amountMaker-token base units in maker-amount mode; taker-token base units otherwise, as selected by takerTraits.
takerTraitsAmount mode, threshold and other taker flags. Target and Permit2 bits must be clear; length fields are overwritten.
extensionThe order's extension bytes.
interactionEmpty, another taker interaction, or the packed tokeniser payload described below. Other interaction addresses receive no budget-token approvals.
gasLimitGas units forwarded to this fill's settlement call, including signature checks, hooks, transfers and tokeniser execution.
Budget fieldMeaning and constraint
tokenToken approved by the caller to the batch filler. Entries must be strictly ascending by token address, without duplicates.
amountAmount pulled from the caller, in that token's base units. May be zero for a token produced during tokenisation.

fillMany

Executes the batch and returns aggregate fill results and the caller's net contribution for each budget.

function fillMany(
    Fill[] calldata fills,
    Budget[] calldata budgets,
    uint256 minMakingFilled,
    bool skipReverts
) external returns (uint256 totalMaking, uint256 filled, uint256[] memory spent);
InputMeaning and unit
fillsNonempty array of fills, processed in input order.
budgetsToken/amount pairs. Every order's taker asset must have an entry, including a zero-amount entry when tokenisation produces it.
minMakingFilledMinimum sum of successful making amounts, each in its own maker token's base units.
skipRevertsWhether to skip failed settlement calls. Does not bypass batch validation or the minimum-making check.
ReturnMeaning and unit
totalMakingSum of actual successful making amounts, each in its own maker token's base units.
filledNumber of successful fills.
spentPer-budget caller contribution after refunds, in input budget order and that token's base units: max(budget.amount - refundedBalance, 0).

totalMaking and minMakingFilled can combine different token units. They are not common-denomination values or a minimum final output. Use a separate output constraint after any conversions.

Execution constraints

Choose each gasLimit from a simulation with a margin. The transaction also needs gas for encoding, budget transfers, approvals, looping, refunds and EIP-150 forwarding overhead. Merely summing the caps is not sufficient. A settlement that exhausts its cap follows skipReverts; insufficient remaining gas to forward that cap reverts the entire batch with InsufficientGas(index), even when skipping failures is enabled.

Private OTC orders: use direct settlement.

Do not authorize the BatchFiller as a taker for private OTC orders or use it to fill them. Fill private OTC orders directly through LimitOrderProtocol.

All budget ordering and fill-shape checks complete before tokens are pulled or approved. The caller must approve each funded budget token to the filler. The filler approves budget tokens to the settlement and, for tokenised batches, the tokeniser; those approvals are reset before returning.

The filler replaces the extension/interaction length fields in takerTraits and adds its own target: the caller for direct fills, or the tokeniser for tokenised fills. Other traits, including amount mode and threshold, pass through. A tokenised fill's recipient must equal the caller of fillMany.

skipReverts = true skips only failed settlement calls. Validation, token pulls and approvals, the final minMakingFilled check and refunds remain mandatory. With skipReverts = false, a failed settlement call reverts as FillFailed(index, reason).

Events

event FillSkipped(address indexed caller, uint256 index, bytes reason);
event BatchFilled(address indexed caller, uint256 filled, uint256 totalMaking);

FillSkipped.index identifies the input fill. Its reason contains at most four bytes of settlement revert data: the error selector without arguments, or fewer bytes if less data was returned. FillFailed retains the full reason when skipReverts is false. BatchFilled follows the minimum-making check and refunds. Individual settlement events identify each order's fill outcome.

Failures

ErrorCause
EmptyBatch()fills is empty.
DuplicateBudget(address token)Adjacent budget entries use the same token.
UnsortedBudgets(address previousToken, address token)A budget token sorts below its predecessor.
TakerAssetNotBudgeted(uint256 index, address takerAsset)An order's taker asset has no budget entry.
UnsupportedTakerTraits(uint256 index)A supplied target or Permit2 bit is set.
InvalidSignatureLength(uint256 index)An EOA-maker signature is not 64 bytes.
SenderRestrictedOrder(uint256 index)Maker allowed-sender bits are nonzero.
InvalidTokenisation(uint256 index)A configured-tokeniser interaction is not 148 bytes or names a recipient other than the caller.
InsufficientGas(uint256 index)Not enough gas remains to forward the fill's exact cap. Reverts the whole batch.
FillFailed(uint256 index, bytes reason)A settlement call failed and skipReverts is false.
InsufficientMakingFilled(uint256 filled, uint256 minimum)The raw making-amount sum is below minMakingFilled; filled here is that sum, not the successful-fill count.

Token transfer, approval and reentrancy-guard failures can also revert the batch. ZeroAddress() applies to zero settlement/tokeniser addresses at construction.

Tokeniser callback

SpectraLimitOrderTokeniser converts within one registered market during a settlement fill. It receives the maker asset, mints IBT into PT/YT or redeems PT/YT into IBT, supplies the maker payment and sends the proceeds to the specified recipient.

Read contract addresses

These read-only functions take no arguments and each return one address, set by the tokeniser's constructor:

FunctionAddress returned and its role
LIMIT_ORDER_PROTOCOL()The only settlement allowed to invoke takerInteraction.
REGISTRY()The registry used to check that the conversion's PT belongs to a registered market.

Interaction arguments

A tokenised fill's interaction is the packed 20-byte configured tokeniser address followed by abi.encode(Args), with no function selector:

struct Args {
    address pt;
    address recipient;
    uint256 input;
    uint256 minOut;
}
FieldMeaning and unit
ptPT registered in the tokeniser's registry; identifies the market.
recipientReceives the complementary derivative, conversion surplus and leftovers. In a batch, must be the actual caller of fillMany.
inputConversion input pulled from the settlement's taker: IBT base units for minting, or complementary PT/YT base units for redemption.
minOutMinimum complementary derivative shares when minting; minimum IBT left after reserving the maker payment when redeeming. In the respective token's base units.

Args occupies 128 bytes; the complete interaction occupies 148 bytes. The taker's conversion input and proceeds use canonical IBT, PT or YT. Underlying/vault-share conversions occur on the maker's quote leg. The tokeniser supplies the exact settlement takingAmount, including any applicable fee; the fee taker then splits fee-order payment between the maker and collector. The taker bears conversion shortfalls and rounding.

takerInteraction

The settlement invokes this callback after transferring the maker asset and before collecting the taker asset. Only the configured settlement may call it. Order uses the same signed-order ABI tuple as Fill.order.

function takerInteraction(
    Order calldata order,
    bytes calldata extension,
    bytes32 orderHash,
    address taker,
    uint256 makingAmount,
    uint256 takingAmount,
    uint256 remainingMakingAmount,
    bytes calldata extraData
) external;
InputUse in the tokeniser
orderIts maker/taker assets select the mint or redeem path for the registered market.
takerSource of Args.input and recipient of the exact maker-payment token amount for settlement to collect. In a batch, the batch filler.
takingAmountExact settlement payment, in taker-token base units. Includes the fee for fee orders; the maker receives the fee-free share.
extraDataThe 128-byte ABI-encoded Args, excluding the 20-byte interaction address.
extension, orderHash, makingAmount, remainingMakingAmountSupplied by settlement; unused by this tokeniser.

For underlying-quoted redemptions, the tokeniser calls IBT.withdraw(takingAmount, taker, address(this)) first, measures the IBT balance decrease, then checks the remaining redeemed IBT against minOut. A failed check rolls back the withdrawal and the complete fill. A withdrawal that cannot execute propagates the IBT's own revert.

The callback returns no value and defines no dedicated fill event. It resets conversion approvals and sends remaining market-token balances to recipient; these sweeps can include underlying or vault-share residue.

Failures

ErrorCause
OnlySettlement()Caller is not the configured settlement.
UnregisteredPT(address pt)Args.pt is not registered.
UnsupportedPair(address makerAsset, address takerAsset)The order does not exchange the market's PT/YT against a supported quote token.
InsufficientOutput(uint256 output, uint256 required)Conversion cannot cover the maker payment. Units are the converted PT/YT, IBT or unwrapped vault share, according to the path.
ProceedsBelowMinimum(uint256 proceeds, uint256 minOut)Complementary shares or net IBT proceeds fall below Args.minOut.

Malformed ABI data, external conversions, token transfers and the reentrancy guard can also revert. ZeroAddress() applies to zero settlement/registry addresses at construction. A callback revert fails its settlement call and therefore follows the batch's skipReverts setting.

Router commands

The router keeps fill outputs and budget refunds for later commands. It resolves budget amounts, approves the filler, calls fillMany, then resets those allowances. Conversions into an order's payment token precede the fill; conversions into the desired output token follow it.

FILL_1INCH_LIMIT_ORDERS (0x27)

The command invokes fillOneInchOrders with this ABI-encoded input:

abi.encode(Fill[] fills, Budget[] budgets,
           uint256 minMakingFilled, bool skipReverts)

Inputs and (totalMaking, filled, spent) returns follow fillMany, with two router-specific constraints:

InputRouter behavior
Budget.amountCONTRACT_BALANCE (1 << 255) resolves to the router's entire current balance of that token. Other values remain amounts in token base units. The batch filler itself does not interpret this sentinel.
Tokeniser Args.recipientMust be the actual router address, the caller seen by the filler. Router address sentinels are not resolved inside tokeniser arguments.

Only the active execution's sender or the router may invoke fillOneInchOrders; other calls revert with OnlyDuringExecution(). It emits no additional fill event. The batch and settlement provide the fill events and failures.

ASSERT_MIN_BALANCE (0x0f)

Place the final output check after output conversions and before output transfers. The command takes:

abi.encode(address token, address owner, uint256 minValue)
InputMeaning and unit
tokenERC-20 token whose balance is checked.
ownerAccount checked; ADDRESS_THIS (address(0xe0)) selects the router.
minValueMinimum balance in token base units.

The command returns no value. It reads balanceOf(owner) and reverts as MinimumBalanceNotReached(token, owner, actualBalance, requiredMinimum) when the balance is below minValue.

This is an absolute balance, not the increase generated by the execution. Existing residue can contribute to the minimum. Budget limits, per-fill thresholds and minMakingFilled do not replace this output constraint; whole-balance conversions and transfers also include existing residue.

TRANSFER (0x02)

Return the final output and all remaining route assets to the recipient. Rounding, conversions and skipped fills can leave dust in PT, YT, IBT, underlying or vault-share tokens. Batch refunds return to the router when it is the batch caller; they do not automatically reach the end user.

abi.encode(address token, address recipient, uint256 value)
InputMeaning and unit
tokenERC-20 token to transfer.
recipientOutput or refund recipient; router address sentinels are resolved.
valueAmount in token base units. CONTRACT_BALANCE (1 << 255) transfers the router's entire current balance of this token.

After the final output assertion, use TRANSFER for the output and for each other token the route may leave behind. The command returns no value and emits no router-specific event. An invalid recipient or token-transfer failure reverts the transaction. Zero resolved amounts are skipped.

fills / swaps / output conversions
→ ASSERT_MIN_BALANCE(finalToken, ADDRESS_THIS, minOut)
→ TRANSFER(finalToken, recipient, CONTRACT_BALANCE)
→ TRANSFER(each remaining route token, recipient, CONTRACT_BALANCE)

On this page