Skip to main content

Running a Solver

A solver is an HTTP endpoint. The coordinator POSTs a borrower’s intent to it; the endpoint prices the loan and returns a signed quote, or declines. There is no SDK to embed, no connection to hold open, and no state to keep between requests. Three things stand between you and your first won quote: getting registered, answering the request, and signing correctly.
A complete reference implementation is open source: iris-bots, under bots/solver. It receives intents, prices them against a fixed-rate provider, derives the required bond, signs what its funding mode needs, and quotes or declines within budget. Start from it rather than from scratch.

1. Get registered

Solvers are onboarded through a whitelist rather than open self-service enrolment. Until your endpoint is in the registry, it receives no traffic: there is no way to opt yourself in.
To start onboarding, reach out through Telegram or the team contact links in the docs header. The coordinator’s endpoint URLs and any credentials are shared directly during onboarding.
Onboarding sets up your registry entry: One entry registers one endpoint. An organisation running several, say one per chain or per region, registers several entries: all of them share its hash, each carries a distinct name (entries sharing a name merge their metric streams), and address may be reused across entries or set per endpoint. The scoping fields are opt-in narrowing: omitting them means “send me everything”. Setting them wrongly is the most common reason a live solver sees no traffic. supportedVenues is matched against the request’s venueBitmap, so a solver scoped to one venue receives nothing from borrowers who allowed only the other.
Registry changes go through the team, not a self-service surface: to update your endpoint, timeout, or scoping, use the same channel as onboarding. An applied change then normally reaches the coordinator within 5 minutes: it caches the registry and refreshes it on a 5-minute interval. A refresh that fails leaves the cached registry in place rather than failing the round, and is retried at the next interval, so a change occasionally takes more than one interval to land.

2. Answer a quote request

Your endpoint receives a POST with the borrower’s intent plus a quoteId minted for your call specifically:
Return a signed quote within your response budget. Mirror requestId exactly (a mismatch drops the quote) and mirror quoteId too, or omit it and one will be generated. solver must be the signing address registered for your endpoint; a quote claiming a different address is dropped. The permit2Nonce and permit2Signature pair is optional together: omit both to fund your bond from a standing allowance instead; see Sign the quote.
Full field bounds are in the API Reference.

Declining

Not quoting is a normal outcome, not a failure. Decline in either of two ways:
  • Return HTTP 404, or
  • Return HTTP 200 with bond: "0"
Both are recorded as non-quotes. Declining cleanly is strictly better than timing out or returning a malformed body, both of which count against your endpoint’s health.

Budget

The default response window is 5 seconds, measured from the coordinator’s request to your last byte. Exceeding it abandons your quote for that round. If your pricing genuinely needs longer, request a higher overrides.timeout during onboarding rather than running close to the limit: every millisecond you take is one the borrower waits.

3. Sign the quote

A quote always carries the solver’s Quote signature; whether it also carries a Permit2 signature depends on how you fund your bond. take() pulls the bond by trying your standing ERC-20 approval to Iris first and falling back to Permit2. Maintain a standing approval covering your bonds and you sign the quote alone, omitting permit2Nonce and permit2Signature together (half a pair is rejected). Without one, sign the per-quote Permit2 payload as well; that mode also needs your one-time ERC-20 approval to the Permit2 contract. Every signature is verified by ECDSA recovery against a reconstruction the coordinator builds from your response, so the terms you sign must be exactly the terms you return.
Signing is EOA-only today. Smart-wallet (ERC-1271) signatures are not yet verifiable and will be rejected. Signatures must be 65-byte r || s || v hex; 64-byte EIP-2098 compact signatures are rejected on purpose.
In TypeScript, signResponse from @iris-credit/iris-sdk signs what your funding mode needs in one call: the quote alone by default, or with usePermit2: true also the Permit2 payload, derived from the quote so the two can never disagree. The sections below document exactly what it signs.

The Quote signature

An EIP-712 signature over the on-chain Quote struct, which is what Iris.take() verifies to bind you to these terms. Build the typed data with getQuoteTypedData from @iris-credit/core-sdk, mixing the request’s fields with your own:

The Permit2 signature

Permit2 is Uniswap’s canonical approval contract: you approve a token to it once, and from then on allowances are granted by signature instead of by transaction. Iris uses it to stage the bond pull, because you are not in the call path at settlement to approve anything. The mode therefore has a prerequisite: a one-time ERC-20 approval to the Permit2 contract for each debt token you quote in, without which the staged pull has nothing to draw on. getSolverRequirements resolves the approvals your funding mode needs as ready-to-send transactions. For quotes carrying the pair, build the payload with getPermit2PermitTypedData from @iris-credit/core-sdk. Every field is determined by the quote you just signed plus your Permit2 nonce: Because it authorises exactly this quote’s bond and Permit2 allowance nonces are sequential, the permit is single-use by construction.
Single-use cuts both ways: quotes signed while an earlier quote in the same debt token is still live carry the same Permit2 nonce. Quote for two borrowers in the same window and, if both take within the 2-minute TTL, the first take consumes the nonce and the second reverts at Iris.take(). Rare, but structural. Either quote at most once per TTL window in each debt token, or maintain a standing ERC-20 approval to Iris for that token and omit the pair: a permitless quote has no nonce to contend.

Next

Validation

Every check your quote passes, in order, and what each failure means.

Pricing Considerations

What to weigh when deciding the rate you are willing to stand behind.

FAQ

Why am I getting no requests, and other common first-week questions.

API Reference

Field-by-field schemas and bounds.