> For the complete documentation index, see [llms.txt](https://docs.syndromics.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.syndromics.xyz/protocol/offers-and-matching.md).

# Offers and matching

Syndromics separates price discovery from settlement. Price discovery happens off-chain through signed messages that cost nothing to create or cancel. Settlement happens on-chain in one transaction that verifies every message it consumes.

This is the pattern used by Blend, NFTfi and Seaport-style exchanges. It gives lenders the flexibility of a limit-order book without the gas cost of posting and cancelling on-chain orders.

## The offer struct

Offers are EIP-712 typed data with the domain `Syndromics`, version `1`, chain ID `4663`.

```solidity
struct Offer {
    address maker;           // signer, lender or borrower
    uint8   side;            // 0 = lend, 1 = borrow
    address collateralToken; // specific token, or tier sentinel for standing offers
    address loanToken;       // USDG
    uint256 principalMin;    // smallest fill accepted
    uint256 principalMax;    // largest fill accepted; remaining capacity on partial fills
    uint16  aprBps;          // fixed APR in basis points
    uint16  maxLtvBps;       // lender's own ceiling; must be at or under the tier max
    uint32  termSeconds;     // loan term the maker accepts
    uint40  expiry;          // offer is invalid after this timestamp
    uint256 nonce;           // per-maker bitmap slot for cancellation
    bytes32 salt;            // uniqueness
    bytes32 requestId;       // zero for standing offers, request hash for targeted offers
    uint8   flags;           // selfLiquidate, noClosedMarketLiquidation, parkIdle
}
```

### Targeted and standing offers

* A **targeted offer** sets `requestId` to the hash of a specific borrow request. It fills only that request.
* A **standing offer** leaves `requestId` empty and sets `collateralToken` to either a specific token or a tier sentinel. It behaves like a limit order: any request that meets its terms can consume it, up to `principalMax`.

Standing offers are what keep the book live. A professional lender can post one standing offer per Tier A token and be matched against many borrowers over time without signing anything new.

### Flags

| Flag                        | Effect                                                                                                                                                           |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `selfLiquidate`             | On liquidation the lender receives collateral in kind at the oracle price instead of USDG proceeds. Suits lenders who actually want the stock.                   |
| `noClosedMarketLiquidation` | The lender waives liquidation while the underlying market is closed, accepting the gap risk in exchange for not selling into a weekend book.                     |
| `parkIdle`                  | Unmatched principal is deposited into the whitelisted Morpho USDG vault and withdrawn just in time at settlement. See [Idle capital](/protocol/idle-capital.md). |

## Signatures

* **ECDSA** for externally owned accounts.
* **EIP-1271** for smart accounts. This is mandatory rather than optional: Robinhood Chain ships ERC-4337 entry points and EIP-7702, so a large share of wallets will be contracts.

## Cancellation and partial fills

* Each maker has a **nonce bitmap**. Cancelling an offer flips its bit; cancelling a whole range flips a word. Cancellation is a cheap on-chain call and takes effect immediately.
* **Partial fills** are tracked per offer hash. A standing offer with `principalMax` of 50,000 USDG that fills 10,000 today keeps 40,000 of capacity until it expires or is cancelled.
* Offers include an `expiry`, so stale offers die on their own without a transaction.

## The relayer

The order book of unsettled offers lives off-chain in a relayer: a stateless REST and WebSocket service that

* stores signed offers and borrow requests,
* validates them against on-chain state (balances, allowances, eligibility, nonces, expiry),
* serves filtered views (by token, tier, term, APR, LTV),
* proposes matching sets for a given request.

The relayer has no privileged role. Anyone can run one, and every relayer sees the same offers because the offers are just signed messages. The indexer mirrors the book so it survives any single relayer going down. See [Off-chain services](/architecture/off-chain-services.md).

## Matching

Matching is deterministic and runs off-chain. For a borrow request, the relayer selects offers that:

1. have the right `side`, `loanToken` and `termSeconds`,
2. cover the request's `collateralToken` (directly or through its tier),
3. have `aprBps` at or under the borrower's maximum,
4. have `maxLtvBps` at or above the request's LTV,
5. are unexpired, uncancelled and have remaining capacity,

sorted by APR ascending, taking capacity until the principal is covered. The borrower sees the proposed syndicate, its blended APR and the per-slice terms before submitting anything.

## Settlement verification

`settle(request, offers[], signatures[])` performs the following, and reverts on any failure:

1. Recompute the request hash and check the fill deadline.
2. For every offer: recover the signer (ECDSA or EIP-1271), check the nonce bit is unset, check expiry, check remaining capacity, check term and token compatibility.
3. Query the eligibility registry for the borrower and every lender.
4. Query the oracle router for the collateral price, session status and staleness; apply the closed-market haircut if needed.
5. Check the resulting LTV against the tier maximum and against every lender's `maxLtvBps`.
6. Check the per-token exposure cap.
7. Transfer collateral from the borrower into escrow.
8. For each lender, pull principal (directly, or from the idle-capital vault if `parkIdle` is set) and transfer it to the borrower.
9. Mint one position NFT per slice recording principal, APR, start time and loan ID.
10. Deduct the origination fee.
11. Emit `LoanSettled` with the full slice list.

Batch signature verification is the most compute-heavy part of the call. A Stylus (Rust) implementation of the verifier is on the roadmap to cut that cost further. See [Smart contracts](/architecture/smart-contracts.md).

## Worked example

A borrower posts: 250 NVDA Stock Tokens, 20,000 USDG, maximum 9.00% APR, 30 days. With NVDA at 176.40, collateral is worth 44,100 USDG and the request LTV is 45.4%, under the Tier A maximum of 55%.

The relayer finds three standing offers:

| Lender        | Capacity    | APR   | Max LTV |
| ------------- | ----------- | ----- | ------- |
| 0x71c3...9e4a | 5,000 USDG  | 8.50% | 50%     |
| 0xb02f...17d3 | 10,000 USDG | 8.90% | 55%     |
| 0x4e88...c0b1 | 5,000 USDG  | 9.00% | 50%     |

The blended APR is 8.825%. The borrower submits one `settle` call and receives 20,000 USDG less the 0.25% origination fee. Three position NFTs are minted. Health factor at origination is `44,100 × 0.70 / 20,000 = 1.54`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.syndromics.xyz/protocol/offers-and-matching.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
