The quote lifecycle
1
Parse the request
The body is parsed against the request schema. Numeric fields arrive as decimal strings and are range-checked before conversion, so malformed input is a clean
400 rather than a server error. A failure here ends the round: no solver is contacted.2
Validate the request
Two checks run before any fan-out: both
collateralToken and debtToken must be protocol-supported tokens, and every bit set in venueBitmap must correspond to a registered venue. Either failure returns 400.3
Select eligible solvers
The coordinator reads its solver registry and filters it down before making a single HTTP call. See Eligibility below.
4
Fan out in parallel
Every eligible solver is called simultaneously with the same intent, each carrying its own fresh
quoteId. The round is bounded by the slowest solver, not their sum. A solver that times out costs the round nothing beyond its own timeout.5
Validate each response
Every returned quote is checked independently: schema, terms, both signatures, registry enablement, and bond sufficiency. A quote that fails any definitive check is dropped. A dropped quote never fails the round. See Validation.
6
Select the winner
Among surviving quotes, the lowest
fixedRate wins. The response carries that quote inline plus allQuotes, every valid quote from the round. If no quote survives, the round returns 404.Eligibility
Not every registered solver sees every request. Three filters run before any HTTP call, so an ineligible solver costs the round no latency at all:
These are the reason a healthy, registered solver can see no traffic at all. See the FAQ.
Fan-out and timing
Solvers are called concurrently and independently. The default response window is 5 seconds, raisable per solver during onboarding. A solver that exceeds its window is abandoned for that round: the round does not wait, and the timeout is recorded against that endpoint. Declining is a first-class outcome, not an error. A solver that does not want to quote returns HTTP404 or a quote with bond: "0"; both are recorded as non-quotes and are treated differently from failures for health purposes.
Everything the coordinator can do in advance happens during the solver wait rather than after it. Bond-curve parameters for every enabled bond liquidity manager are fetched the moment the request arrives, unawaited and batched, so they have resolved by the time responses need checking against them. Bond validation therefore adds no latency to the round.
Validation is convenience-grade
This is the doctrine that explains most of the coordinator’s behaviour.Iris.take() re-verifies every term on-chain. The coordinator’s checks exist to drop quotes that are definitively unsubmittable before a borrower wastes gas on them, not to replicate the contract. That produces two rules:
- Reject only on a definitive invalid. A signature that recovers to the wrong address is unsubmittable, so the quote is dropped.
- Fail open when a check cannot run. If bond parameters could not be fetched, bond validation is skipped rather than failing the quote. The contract is the backstop.
take().
What a quote is
A quote is a signed, short-lived offer. It carries two signatures, both from the solver:- The
Quotesignature: an EIP-712 signature over the on-chainQuotestruct, which is whattake()verifies to bind the solver to these terms. - The Permit2 signature: an EIP-712 signature over a Permit2
PermitSingleauthorisingIristo pull exactly this quote’sbondin the debt token.take()pulls the bond from the solver, and the solver is not in the call path to approve it, so the authorisation travels with the quote.
What the coordinator is not
- Not an order book. Intents are not broadcast or persisted; a round is private to its participants.
- Not a matching engine. It returns a quote; it never settles one. Settlement is the borrower calling
take(). - Not custodial. It never holds tokens, keys, or positions.
- Not open enrolment. Solvers are onboarded through a whitelist.

