Skip to main content
Every state-changing flow on the client.iris.core(chainId) entity returns the same shape: getRequirements() resolves the on-chain prerequisites, and buildTx(signatures?) synchronously encodes the final Transaction object (to, value, data, plus a typed action discriminator). Building is deterministic (no simulation, no gas estimation, no sending): the SDK produces calldata and your application decides when and how to submit it. Each flow validates locally what the contract would reject (deadlines, bounds, roles, bitmap membership) as typed errors, so bad input fails at build time rather than as a revert.

How flows are routed

Flows that move tokens in run through Bundler3’s general adapter: Iris pulls funding atomically with the call, so the transfer and the Iris call must share one transaction. The bundle is also what lets a permit, a Permit2 approval or an Iris authorization signature ride along instead of costing a standalone transaction. Flows that only move tokens out call Iris directly: nothing is pulled from the caller, so there is nothing to make atomic and no approval to fold in. Pulls priced at execution are funded with an upper bound. Iris prices repay, close, escape and refinance when the transaction lands, not when the position was fetched. A repay costs the principal plus the full term’s fixed interest, so its price is flat until maturity (repaying early does not reduce it, see Maturity & Overdue) and only grows per second, at the fixed plus overdue rate, once past it. The venue debt escape and refinance fund does accrue per second from the start. These bundles fund the position projected two hours forward and sweep the residual back to the receiver. repay and close fund one unit beyond that projection (REPAY_ROUNDING_HEADROOM): the flat fixed total is settled as two separately rounded-down parts, the interest accrued to the settlement timestamp and the residual from there to maturity, so projecting forward re-rounds the split rather than bounding it, and the amount owed at the mined block can sit one unit above the projection. The sweep returns that unit too. close is sized on its repay leg alone: the repay clears the venue debt, so its escape leg funds nothing. The projection doubles as the transaction’s validity window: rebuild after two hours rather than sending a stale one.

Requirements

getRequirements() returns what must be satisfied before the transaction can land:
  • ERC-20 approval: approve the general adapter (or, on the Permit2 path, the Permit2 contract) to pull tokens. Returned as a standard approve transaction to send first.
  • Permit / Permit2 signature: off-chain approvals passed into buildTx instead of costing a transaction. Enabled by irisViemExtension({ supportSignature: true }); pass useSimplePermit: true to getRequirements to prefer an ERC-2612 permit for the tokens core-sdk records a verified permit domain for (SIMPLE_PERMIT_TOKENS). Any other token falls through to Permit2 without being probed, because signing a guessed domain reverts at execution.
  • Iris authorization: bundled flows that operate on a user’s loan need that user to authorize the general adapter on Iris (take, close and escape the borrower’s, refinance the solver’s). Returned as a setAuthorization transaction (or, with supportSignature, as a signable requirement folded into the bundle) and omitted when already in place.
The isRequirementApproval and isRequirementIrisAuthorization guards narrow the transaction requirements further when the two must be handled differently. buildTx consumes at most one permit and one authorization signature: passing several of a kind, or a kind the flow does not consume, throws instead of silently dropping a signed requirement. Every signable requirement carries the exact EIP-712 payload its sign() will sign as requirement.action.typedData, so the permit, Permit2 allowance or Iris authorization can be inspected or shown to the user before they sign it. The payload is fixed when the requirement is resolved and frozen against mutation: what is displayed is what gets signed.
Builder = signer. userAddress must be the account that signs and sends the transaction. The entity enforces the contract’s pinned roles at build time (take, close, escape and withdrawCollateral require the borrower, withdrawBond and refinance the solver), and every requirement’s sign(client, userAddress) rejects a client whose account is not userAddress. A permit or Iris authorization signs a payload that names its owner, so those requirements also reject a userAddress other than the account they were resolved for.

Take

Opens a loan from a solver-signed quote delivered through the RFQ: the response carries the quote, its signature and, for solvers funding bonds per-quote, the solverPermit2 payload. The flow also takes a fresh view of the venue the quote opens on; a Quote carries every field getVenueData needs, so it satisfies the params directly. Validation is local-only: the RFQ already validated the quote, and the contract re-verifies everything at execution. What is checked here, beyond the quote’s shape, is its health on venueData: the debt must fit the venue’s max borrow for the quote’s collateral, measured 0.5% below the venue LLTV so the loan does not open one accrual away from venue liquidation, and capped by what the venue can lend. A view of a different venue than the quote opens throws VenueMismatchError, a missing venue price IrisCoreErrors.UnknownVenuePrice, and an oversized debt UnhealthyDebtError.
The same nativeAmount parameter funds the debt token on repay / close / escape / refinance and the deposit on supplyCollateral / supplyBond, always requiring the funded asset to be the chain’s wNative.

Repay

Closes the loan in full: there are no partial repays on Iris. Permissionless: anyone can fund it, and the sweep returns the residual to userAddress. getRequirements sizes the approval on the funded amount, so it sits above the repayAmount read from the position: the projection plus the one-unit rounding headroom.
Repay resolves the loan but leaves the collateral with the position. Exit it afterwards with escape, or do both in one bundle with close.

Close

Resolves the loan and recovers its collateral in one bundle: Iris.repay leaves the collateral on the venue, so the bundle repays first (clearing the bond requirement Iris.escape checks) and then exits the venue position to userAddress. The exit runs on escape rather than withdrawCollateral, so it takes the venue balance as it stands at execution instead of an amount a rebase can invalidate. Funding is sized like repay: the loan projected two hours forward plus the one-unit rounding headroom, residual swept back to userAddress. The escape leg needs no funding of its own, because the repay clears the venue debt in full. Unlike the permissionless repay, userAddress must be the loan’s borrower: GeneralAdapter1 pins them as the bundle initiator, and the escape leg runs on their Iris authorization of the adapter, so getRequirements resolves that authorization alongside the debt-token approval.
The collateral and the swept residual both go to userAddress. A different receiver goes through the raw irisClose action instead. A loan that is already resolved throws LoanResolvedError: use escape on its own.

Supply collateral

Adds collateral to the loan’s position. Permissionless: anyone can fund it.

Withdraw collateral

A direct Iris call: no bundler, no approval. The amount is validated locally against the ceilings Iris re-checks onchain, measured with a 0.5% buffer below the venue LLTV so a withdrawal sized to the fetched state still clears once it lands, and additionally against the venue’s own ceiling, which Iris’s does not imply.
The flow pins userAddress to the loan’s borrower and withdraws to it. A manager the borrower authorized on Iris, or a different receiver, goes through the raw irisWithdrawCollateral action instead.

Supply bond

Adds bond to the solver’s backing. Permissionless: anyone can fund it.

Withdraw bond

A direct Iris call: no bundler, no approval. The amount is validated locally against the withdrawable bond Iris re-checks onchain, measured with a 0.5% buffer below the loan’s bond LLTV so a withdrawal sized to the fetched state still clears once it lands.
The flow pins userAddress to the loan’s solver and withdraws to it. A manager the solver authorized on Iris, or a different receiver, goes through the raw irisWithdrawBond action instead.

Claim

Settlement credits the solver’s net and surplus (and the fee recipient’s fees) to claimable balances. claim draws one down; amount defaults to the whole balance.

Escape

Exits the venue position of a resolved loan (bondRequirement === 0n): the bundle funds any remaining venue debt (projected two hours forward, residual swept back), settles it, and withdraws the venue collateral, yield included, to userAddress. After a repay or liquidation the venue usually carries no debt, in which case the funding requirement comes back empty. For a loan that is still open, close does both legs in one transaction.

Refinance

Moves the loan’s position to another venue enabled in the loan’s venueBitmap, up until the loan becomes liquidatable. The migration is replayed locally to reject what the contract would reject; the bundle then funds the current venue’s debt (projected two hours forward), re-enters the new venue, and returns the borrow proceeds plus the swept residual to userAddress, leaving it whole.
Whether the new venue’s data payload is enabled on Iris is not read here: the contract rejects a disabled payload at execution. Check upfront with fetchIsDataEnabled from @iris-credit/core-sdk.
A loan past maturity + overduePeriod is liquidatable, and refinancing it throws IrisCoreErrors.LiquidatableLoan. The gate is evaluated at the same two-hour projected timestamp as the funding, so a refinance is refused for up to two hours before the loan is liquidatable onchain. A solver moving a loan close to its overdue deadline should build the bundle with that window in mind.

Next

Solver Signing

The maker-flow counterpart: sign quotes and manage bond allowances.

Entities & Reads

What the flows’ pre-fetched inputs are made of.