# OpenAsset Market Documentation > Canonical, agent-readable copy of the complete OpenAsset Market documentation. This file is generated directly from the documentation source pages. It preserves their canonical order and content while removing MDX-only presentation components. # OpenAsset Market **Permissionless, non-custodial lending infrastructure for tokenized assets.** Create an isolated lending market around an asset, fund it with stablecoins, and choose how that market prices collateral, checks eligibility, represents positions, and resolves defaults. OpenAsset supplies the lending engine and the rules that keep each market separate. Market creators choose the asset, adapters, and risk parameters. > **Before you start:** OpenAsset v2 uses a pluggable adapter architecture. Version 1 is scoped to EVM chains and stablecoin lending assets. Permissionless market creation does not mean that every asset, adapter, or market is safe, verified, or suitable for every borrower. ## Choose your path OpenAsset is one protocol with several ways to use it. Start with the outcome you need, then read the protocol details behind that workflow. | If you are a... | You want to... | Start here | |---|---|---| | **Liquidity provider or market creator** | Launch an isolated market, set its terms, choose adapters, and seed liquidity. | [Create a market](/docs/guides/create-market) | | **Borrower** | Find a market, check its terms and eligibility rules, borrow stablecoins, and understand repayment and liquidation. | [Borrow against collateral](/docs/guides/borrow) | | **Adapter author or integrator** | Connect an asset, oracle, compliance rule, liquidation path, or position type to the core engine. | [Use adapters](/docs/guides/adapters) | | **RWA or tokenized-asset issuer** | Decide whether an issuer-backed market meets the oracle, compliance, settlement, and legal requirements. | [Launch an RWA market](/docs/guides/rwa-market) | | **Auditor or security reviewer** | Trace trust boundaries, validation rules, invariants, and failure paths. | [Review the security model](/docs/protocol/security) | | **Agent or documentation consumer** | Retrieve the synchronized, machine-readable source of the docs. | [Read the agent-readable docs](/docs/llms) | ## The short version OpenAsset separates a stable lending engine from the asset-specific logic that changes from market to market. The engine does not need to know whether collateral is an ERC20, NFT, tokenized equity, or another supported asset type. It calls adapters for five jobs: | Job | Adapter | |---|---| | Hold and release collateral | Asset Adapter | | Price collateral | Oracle Adapter | | Check participant eligibility | Compliance Adapter, optional | | Resolve a default | Liquidation Adapter | | Represent the loan position | Position Adapter | The Factory validates the selected combination, then deploys a new `LendingMarket`. Each market has its own liquidity, collateral, risk parameters, and adapter stack. There is no shared lending pool between markets. ## From asset to active market The market creator’s path is deliberately short: ```text Choose collateral ↓ Select adapters ↓ Set risk terms ↓ Factory validates configuration ↓ Deploy isolated LendingMarket ↓ Seed stablecoin liquidity ↓ Borrowers can originate loans ``` The Factory rejects incompatible combinations before a market goes live. For example, the selected oracle must cover the selected asset type, a permissioned asset must have a compliance adapter, and the lending asset must be on the stablecoin allowlist. See the [validation matrix](/docs/protocol/validation-matrix) for the complete rule set. ## What happens inside a loan A borrower first chooses a market by reviewing its collateral asset, LTV, APR, duration, oracle, liquidation path, position type, and adapter trust status. If the market has a Compliance Adapter, the application checks eligibility before asking for wallet approval. The borrower then escrows collateral through the Asset Adapter. The engine reads a trusted oracle, computes the maximum loan from the configured LTV, verifies the collateral balance change, creates the position, and transfers stablecoin proceeds. A loan can be repaid while active or during its grace period. If the loan defaults, the configured Liquidation Adapter resolves it. Synchronous markets settle in one transaction. Issuer-redemption markets use a reversible `LIQUIDATION_CURE` window before entering irreversible `LIQUIDATION_SETTLING`. ```text Market is active ↓ Borrower deposits collateral ↓ Oracle and eligibility checks ↓ Stablecoins transferred ↓ Repay on time? ── yes ──→ Collateral released │ no ↓ Grace period or liquidation path ↓ Synchronous or asynchronous? ├─ synchronous ─→ Liquidation settles └─ asynchronous → Cure window → Issuer settlement Debt and penalty are recovered; surplus is returned to the current position holder. ``` The fairness rule is the same across liquidation types: take the amount owed plus the configured penalty, then return the surplus to the current position holder. For a transferable position, the current holder is the economic actor for repayment, surplus, and alerts. That might not be the original borrower. ## What stays in the core The lending engine owns the parts of the system that should not vary by asset class: | Core responsibility | Why it stays in the engine | |---|---| | Loan state machine | Every market needs explicit, auditable transitions. | | Circuit breaker | Pause decisions must not be disabled by a custom oracle or adapter. | | Defensive adapter checks | The engine verifies outputs from both verified and unverified adapters. | | Reentrancy protection and CEI ordering | Every external adapter call crosses a trust boundary. | | Gradual liquidation accounting | Liquidation must reconcile what goes to the LP with what returns to the holder. | The adapter layer is open. The safety boundary around the adapter layer is not. ## Understand the adapter choices The adapter you choose determines the behavior of the market. Prefer the Verified reference adapters when they fit the asset and workflow. A Verified badge records an audit or review decision; it does not make the adapter trusted at the contract level. The engine still checks every adapter’s output. | Adapter type | It controls | Typical implementations | |---|---|---| | **Asset** | How collateral is escrowed, released, and checked for transferability. | `ERC20Adapter`, `ERC721Adapter`, `ERC1155Adapter` | | **Oracle** | The collateral price, trust status, and historical price used for circuit-breaker checks. | `UniswapV3TWAPAdapter`, `ChainlinkAdapter`, issuer or NAV oracles | | **Compliance** | Whether a participant is eligible. This adapter is optional and checked at defined protocol actions. | ERC-3643, issuer allowlist, jurisdiction geofence | | **Liquidation** | How a default is resolved and how recovered value and surplus are split. | DEX swap, NFT auction, issuer redemption | | **Position** | Who owns the loan position and whether it can transfer. | Standard, soulbound, or transferable position | Read the [adapter system](/docs/protocol/adapter-system) before creating or integrating a market. If you are selecting a third-party adapter, read its audit reference and understand its trust status first. ## Know the boundaries before you deposit or deploy OpenAsset’s design makes several boundaries explicit. They belong in the decision a reader is making, not in a footnote at the end of the docs. | Boundary | What it means in practice | |---|---| | **Stablecoin lending assets only** | Borrowers receive an allowlisted stablecoin. Non-stablecoin lending assets are out of scope for v1. | | **EVM deployments only in v1** | Each supported chain has its own Factory and Registry. There is no unified cross-chain liquidity layer. | | **No protocol underwriting** | Anyone can create a market, but the market creator sets the parameters and LPs carry the market’s economic risk. | | **Verified does not mean trusted code** | Verification is a process control. The core engine treats verified and unverified adapters as semi-trusted external code and verifies their outputs. | | **Compliance is action-specific** | Compliance adapters check eligibility at origination and, for transferable positions, on position transfer. They do not continuously monitor real-world eligibility during a loan. | | **RWA assets carry issuer risk** | An issuer can become insolvent, halt redemption, or be shut down independently of the token’s market price and OpenAsset’s contracts. This is an uninsured total-loss risk. | | **Async liquidation can become irreversible** | In an issuer-redemption market, repayment remains possible during `LIQUIDATION_CURE`. Once the market enters `LIQUIDATION_SETTLING`, the redemption has been submitted and repayment is no longer possible. | ## Read the docs in the order you need them ### If you are creating a market Start with [Create a market](/docs/guides/create-market), then read the [adapter system](/docs/protocol/adapter-system), [validation matrix](/docs/protocol/validation-matrix), and [trust model](/docs/protocol/trust-model). If the collateral is an RWA or tokenized equity, read [Launch an RWA market](/docs/guides/rwa-market) and the [RWA risk boundaries](/docs/protocol/rwa) before choosing an oracle or liquidation path. ### If you are borrowing Start with [Borrow against collateral](/docs/guides/borrow). Before depositing collateral, review the market’s LTV, APR, duration, grace period, oracle, liquidation path, position type, and adapter trust status. Then read [Loan lifecycle](/docs/protocol/loan-lifecycle) so you know what changes when a loan enters grace or liquidation. ### If you are building an adapter or integration Start with [Use adapters](/docs/guides/adapters), then read the interface definitions in the [adapter system](/docs/protocol/adapter-system), the [adapter trust model](/docs/protocol/trust-model), and the [adapter registry](/docs/protocol/adapter-registry). The core engine will verify your outputs regardless of whether OpenAsset has marked your adapter Verified. ### If you are reviewing security Start with the [security model](/docs/protocol/security), then work through the [trust model](/docs/protocol/trust-model), [validation matrix](/docs/protocol/validation-matrix), [circuit breaker](/docs/protocol/circuit-breaker), and [security checklist](/docs/reference/security-checklist). For RWA markets, include issuer insolvency and redemption failure in the review. They are operational and legal risks, not problems that contract checks can remove. ## Documentation for agents Use [`/llms.txt`](/llms.txt) when an agent needs the complete canonical documentation in plain text. The file is generated from the same MDX pages as this site, so the machine-readable version and the human-readable version stay aligned. The [`/docs/llms`](/docs/llms) page explains how to use it. ## Document status | Field | Value | |---|---| | **Status** | Canonical / source of truth | | **Architecture** | v2.0 adapter architecture | | **Scope** | EVM chains; stablecoin lending assets | | **Supersedes** | Prior monolithic `LendingMarket` designs | Where this site and older drafts disagree, this documentation is correct. Last updated August 27, 2026. [Agent-readable documentation](/docs/llms) # Protocol overview OpenAsset Market is a factory-deployed, **isolated-market** lending protocol. Each market is its own contract instance with independent liquidity, collateral asset, risk parameters, and adapter stack. ## Problem Legacy money markets approve a small set of blue-chip collaterals, fix terms via governance, and leave the long tail of on-chain value without lending utility — gaming tokens, niche NFTs, community assets, and increasingly tokenized equities and RWAs. ## Solution Separate a **stable, narrowly scoped lending engine** from a **pluggable adapter layer**: 1. **Market Factory** — permissionless deployment + validation matrix 2. **LendingMarket (engine)** — liquidity accounting, loan state machine, circuit breaker, defensive invariants 3. **Adapter Registry** — hybrid trust metadata (Verified / unverified / deprecated) 4. **Five adapter types** — Asset, Oracle, Compliance (optional), Liquidation, Position New asset classes do not require modifying or re-auditing the contracts that hold everyone’s collateral. They require a new adapter. ## Lifecycle in one page ``` LP creates market → Factory validates config + adapter compatibility → Deploys isolated LendingMarket → Wires adapters, seeds liquidity Borrower requests loan → Compliance check (if configured) → Oracle price (must be trusted) → Asset adapter escrows collateral (balance verified) → Position adapter mints position → Stablecoin proceeds transferred Repay or default → Sync liquidation (DEX / NFT auction) OR → Async path (issuer redemption: CURE → SETTLING → LIQUIDATED) → Surplus returned to position holder (gradual liquidation shape) ``` ## What the engine never does - Encode ERC20 vs NFT vs RWA branches - Trust adapter outputs without verification - Continuously poll real-world eligibility mid-loan - Underwrite which assets “deserve” markets - Share risk across markets (no shared pool contagion) ## Related - [Design philosophy](/docs/protocol/design-philosophy) - [Core contracts](/docs/protocol/core-contracts) - [Adapter system](/docs/protocol/adapter-system) - [Loan lifecycle](/docs/protocol/loan-lifecycle) **Issuer risk is not price risk.** For RWA and tokenized equity collateral, issuer insolvency or redemption halt can zero the token independent of the underlying asset’s market price. See [RWA & tokenized equity](/docs/protocol/rwa). # Design philosophy ## Core principles 1. **Permissionless market creation** — No asset-listing committee, no governance approval, no centralized underwriting. The market creator (LP) owns the parameters they configure. 2. **Isolated markets** — Each market has its own liquidity, collateral, risk parameters, and liquidation mechanism. A failure in one market cannot cascade into another. 3. **Non-custodial** — OpenAsset Market never takes discretionary control of user assets. Collateral is locked according to predefined, transparent smart contract rules. 4. **Open asset support** — Crypto, NFTs, gaming assets, tokenized equities, RWAs, and asset classes that don’t exist yet should be supportable without redesigning the core engine. 5. **Infrastructure, not underwriting** — The protocol does not decide which assets deserve financial utility. Market creators decide. ## The adapter principle Every time a new asset class needed an `if/else` branch inside a monolithic `LendingMarket`, the whole protocol’s audit surface grew. That doesn’t scale past a handful of types, and it means the contract holding collateral gets modified — and needs re-auditing — every time you want to support something new. Instead, the core engine knows exactly four verbs: | Verb | Adapter | |---|---| | Escrow / release collateral | Asset Adapter | | Price collateral | Oracle Adapter | | Check eligibility | Compliance Adapter (optional) | | Resolve default | Liquidation Adapter | | Represent the loan | Position Adapter | New asset classes, oracle sources, compliance regimes, and liquidation mechanisms are added by **writing and registering an adapter**, not by touching the engine. A bug in an adapter is contained to markets that chose it. The engine’s safety guarantees — circuit breaker, gradual liquidation shape, reentrancy protection, defensive output checks — stay stable and centrally audited. ## Non-negotiable core vs pluggable **Always in the core engine (regardless of adapters):** - Circuit breaker logic - Requirement that liquidation returns surplus to the collateral holder - Reentrancy protection and Checks-Effects-Interactions on every external call (including adapters) - Defensive verification of adapter outputs ([trust model](/docs/protocol/trust-model)) - Loan state machine **Pluggable per market (chosen by LP at creation):** - How collateral is held and released - Where price comes from - Who’s eligible to borrow or hold a position - How liquidation is executed - How the loan position is represented # Core contracts ## Market Factory Responsible for permissionless market deployment. **Responsibilities:** - Validate market configuration against the [Validation Matrix](/docs/protocol/validation-matrix) - Deploy a new isolated `LendingMarket` instance - Wire chosen adapters from the [Adapter Registry](/docs/protocol/adapter-registry) - Register market metadata - Collect creation fees ### Creation fee (immutable structure) | Parameter | Value | |---|---| | Percent fee | 1% (100 bps) of total deposit | | Minimum | 0.05 ETH (or chain native equivalent) | | Maximum | 0.5 ETH | Fee structure is immutable so LPs can compute ROI with certainty and the protocol cannot change terms after capital is committed. ### MarketConfig (conceptual) ```solidity struct MarketConfig { address lpAddress; address collateralAsset; address assetAdapter; address oracleAdapter; address complianceAdapter; // address(0) if none address liquidationAdapter; address positionAdapter; address lendingAsset; // must be in stablecoin allowlist uint256 ltvBasisPoints; uint256 aprBasisPoints; uint256 durationSeconds; uint256 gracePeriodHours; bool enableHealthFactor; uint256 healthFactorThreshold; bool enableCircuitBreaker; uint256 pauseThresholdBps; uint256 lookbackPeriodSeconds; uint256 resumeThresholdBps; uint256 cooldownSeconds; } ``` ## LendingMarket (the lending engine) Each market is its own isolated contract. It owns: - Liquidity accounting (`totalLiquidity`, `availableLiquidity`, `totalBorrowed`) - Loan state machine - Circuit breaker - Defensive adapter interaction It **never** contains asset-type logic. Every asset-specific action is delegated to the market’s configured adapters. ### Market status ```solidity enum MarketStatus { ACTIVE, PAUSED_VOLATILITY, PAUSED_STALE_ORACLE, PAUSED_MANUAL } ``` ### Loan record ```solidity struct Loan { uint256 collateralAmount; uint256 principal; uint256 startTime; uint256 expiryTime; uint256 frozenInterestAt; // set in LIQUIDATION_CURE; 0 otherwise LoanStatus status; } enum LoanStatus { ACTIVE, GRACE_PERIOD, LIQUIDATION_CURE, // reversible: holder can still repay LIQUIDATION_SETTLING, // irreversible: async redemption submitted REPAID, LIQUIDATED } ``` ### Origination sketch 1. If compliance adapter set → `isEligible(msg.sender)` 2. `assetAdapter.isTransferable(...)` 3. `oracleAdapter.getPrice()` — must be trusted and within sanity bounds 4. Compute max loan from LTV 5. Escrow collateral; **verify balance delta matches requested amount** 6. Mint position via position adapter 7. Transfer lending asset (stablecoin) to borrower See [Loan lifecycle](/docs/protocol/loan-lifecycle) for full state transitions. # Adapter system Four operational interfaces plus one presentation interface define every point where the core engine reaches outside itself. ## IAssetAdapter Handles collateral custody. **Reference implementations:** `ERC20Adapter`, `ERC721Adapter`, `ERC1155Adapter`, issuer-specific adapters for permissioned RWA tokens. ```solidity interface IAssetAdapter { function escrow(address from, uint256 amountOrId) external; function release(address to, uint256 amountOrId) external; function isTransferable(address from, address to, uint256 amountOrId) external view returns (bool); } ``` ## IOracleAdapter Handles pricing. **Reference implementations:** `UniswapV3TWAPAdapter`, `ChainlinkAdapter`, `ChainlinkEquityFeedAdapter`, `NAVOracleAdapter`, `ManualOracleAdapter`. ```solidity interface IOracleAdapter { /// isTrusted covers staleness, L2 sequencer liveness, AND session-awareness /// (e.g. equity feeds outside trading windows). function getPrice() external view returns (uint256 price, bool isTrusted, uint256 updatedAt); function getHistoricalPrice(uint256 secondsAgo) external view returns (uint256); } ``` The engine does not need to know *why* a price is untrusted — only whether to act on it. Untrusted prices feed the [circuit breaker](/docs/protocol/circuit-breaker). ## IComplianceAdapter Handles eligibility. **Optional** — markets with no compliance requirement set `complianceAdapter == address(0)` and skip checks. **Reference implementations:** `ERC3643ComplianceAdapter`, `IssuerAllowlistAdapter`, `JurisdictionGeofenceAdapter`. ```solidity interface IComplianceAdapter { function isEligible(address participant) external view returns (bool); } ``` Checked at **loan origination** and, for transferable positions, at **every position transfer**. ## ILiquidationAdapter Handles default resolution. **Reference implementations:** `DEXSwapLiquidationAdapter`, `NFTAuctionLiquidationAdapter`, `IssuerRedemptionLiquidationAdapter`. ```solidity interface ILiquidationAdapter { /// recoveredForLP — value taken to satisfy debt + penalty /// returnedToHolder — surplus returned to the position holder function liquidate(uint256 loanId, uint256 debtOwed) external returns (uint256 recoveredForLP, uint256 returnedToHolder); function isAsynchronous() external view returns (bool); /// Only meaningful when isAsynchronous() == true function cureWindowSeconds() external view returns (uint256); } ``` ### Gradual liquidation is an interface contract Gradual liquidation is **not** a separate adapter. Every `ILiquidationAdapter` must return both recovered and returned amounts. That forces surplus accounting: | Collateral type | How surplus is returned | |---|---| | Divisible ERC20 | Real tokens back to holder | | Indivisible NFT | Cash side-payment (ETH/stable) from available liquidity | | Issuer redemption | Whatever settlement yields after debt is satisfied | ## IPositionAdapter Handles how a loan is represented and who may act on it. ```solidity interface IPositionAdapter { function mint(address to, uint256 loanId) external; function ownerOf(uint256 loanId) external view returns (address); function burn(uint256 loanId) external; // repay or liquidation } ``` **Tiers:** Standard (no token), Soulbound ERC721, Transferable ERC721. Details: [Position adapters](/docs/protocol/positions). # Adapter trust model This is the single most important security design in v2.0. Treat it as non-negotiable during implementation and audit. ## Process trust vs code trust The [Adapter Registry](/docs/protocol/adapter-registry) is **hybrid**: | Status | Meaning | |---|---| | **Verified** | Passed OpenAsset Market’s internal audit; audit reference attached | | **Unverified** | Registered permissionlessly; LP’s judgment; prominent UI risk warning | | **Deprecated** | Blocked for *new* markets; existing markets keep running with warnings | Verification is a **process** control — a human reviewer vouched for the code. **It does not change how the core engine treats the adapter at the code level.** Verified and unverified adapters are called identically. The engine independently verifies outputs in both cases. Verification reduces the *probability* a bug exists. It does not eliminate the *need* for the engine to defend itself. Treating a Verified adapter as fully trusted at the contract level would turn a single missed review bug into a protocol-wide vulnerability — the failure mode the adapter architecture exists to prevent. ## Defensive invariants (every adapter call) | Adapter call | Defensive check | |---|---| | `assetAdapter.escrow()` | Verify actual balance delta matches requested amount — never assume success from a non-reverting call | | `oracleAdapter.getPrice()` | Reject `isTrusted == false`; bound price against hard sanity ceiling/floor | | `oracleAdapter.getPrice()` (repeat) | Bound magnitude of change between consecutive reads in the same tx | | `complianceAdapter.isEligible()` | Treat any revert as `false` (**fail closed**), never fail open | | `liquidationAdapter.liquidate()` | Verify `recoveredForLP + returnedToHolder` reconciles against assets received | | Every adapter call | Full CEI ordering + `nonReentrant` — each call is external to semi-trusted code | ## UI requirements - Unverified adapters must be as prominent as “Manual Oracle — use at your own risk” - Warnings at **borrower** decision points, not only LP market creation - Explicit confirmation checkbox when selecting unverified adapters at market creation # Adapter registry **Model: hybrid.** Anyone can deploy an adapter conforming to one of the five interfaces and register it. The registry does not gate what exists — it attaches and surfaces trust metadata so creators and borrowers can decide. ## AdapterInfo ```solidity enum AdapterType { ASSET, ORACLE, COMPLIANCE, LIQUIDATION, POSITION } struct AdapterInfo { address adapterAddress; AdapterType adapterType; address registeredBy; bool verified; // audit sign-off only bool deprecated; string auditReference; uint256 registeredAt; uint256 totalValueSecured; // TVL through markets using this adapter } ``` ## Lifecycle operations | Function | Who | Effect | |---|---|---| | `registerAdapter` | Anyone | Adds unverified adapter | | `markVerified` | Audit governance multisig | Sets verified + audit reference | | `markDeprecated` | Audit governance multisig | Blocks new selection; does **not** pause existing markets | ### Deprecation behavior (explicit) Deprecation does **not** retroactively pause markets already using the adapter — consistent with “market creator controls their market.” It does: 1. Block the adapter from selection in any **new** market 2. Surface a persistent warning on existing markets still wired to it 3. Directly notify affected LP(s) ## Reference adapters (ship Verified at launch) Protocol-authored defaults so most usage runs through vetted code while the registry door stays open: | Type | Adapters | |---|---| | Asset | `ERC20Adapter`, `ERC721Adapter` | | Oracle | `UniswapV3TWAPAdapter`, `ChainlinkAdapter` | | Liquidation | `DEXSwapLiquidationAdapter`, `NFTAuctionLiquidationAdapter` | | Position | `StandardPositionAdapter`, `SoulboundPositionAdapter`, `TransferablePositionAdapter` | RWA-specific adapters (`ChainlinkEquityFeedAdapter`, `ERC3643ComplianceAdapter`, `IssuerRedemptionLiquidationAdapter`) follow the same model once issuer integrations and counsel gates are met. # Market Factory validation matrix Adapter compatibility is **not** left to LP judgment or an implicit runtime checker (which would itself be untrusted code). The Factory enforces an explicit, auditable rule table. Deployment **reverts** if any rule fails. ## Rules | Rule | Rationale | |---|---| | If `positionAdapter == TransferablePosition` **and** `complianceAdapter != address(0)`, the position adapter’s transfer hook **must** call `complianceAdapter.isEligible(recipient)` | Prevents the position NFT from becoming an unregulated side-door around compliance enforced only at origination | | If `liquidationAdapter.isAsynchronous() == true`, `complianceAdapter` **must not** be `address(0)` | Async issuer-redemption assumes an eligible caller with the issuer | | `lendingAsset` **must** be on the protocol stablecoin allowlist | Enforces [lending asset scope](/docs/protocol/lending-assets) at the Factory | | Oracle adapter’s declared covered asset type **must** match asset adapter’s declared asset type | Prevents mismatched pairings (e.g. crypto TWAP on equity collateral) | | If asset adapter is flagged permissioned/compliance-gated, `complianceAdapter` **must not** be `address(0)` | Permissioned asset with no compliance layer cannot legally originate | ## Design notes - The table is deliberately **small and explicit** so it remains fully auditable in a single read - New rules are added here, not inferred by the Factory at runtime - Product UI should reject incompatible combinations **before** submitting a transaction, citing the specific rule # Circuit breaker The circuit breaker is **core engine logic, not an adapter** — deliberately. If it were pluggable, an LP could disable it by choosing (or writing) an oracle that never reports stress. The Oracle Adapter only reports price and trust; the engine alone decides what to do. ## Triggers 1. **Volatility** — price change over the lookback window exceeds `pauseThresholdBps` 2. **Untrusted / stale oracle** — `isTrusted == false` (includes equity weekend/holiday windows, L2 sequencer downtime, stale Chainlink rounds) ## Resume conditions For volatility or stale-oracle pauses: - Cooldown period has passed (`cooldownSeconds` after `pausedAt`) - Oracle is trusted again - Price change is below `resumeThresholdBps` LPs may also **manually pause** or **force-resume** their market. ## What’s allowed while paused | Action | Allowed? | |---|---| | New loan origination | **Blocked** | | Repayments | Allowed | | Liquidations | Allowed | | LP withdrawal of unlent liquidity | Allowed | ## LP configuration at market creation - Enable / disable circuit breaker - Pause threshold (bps over lookback) - Resume threshold - Lookback period - Cooldown period # Loan lifecycle & state machine ## Synchronous path (default — most markets) Applies when `ILiquidationAdapter.isAsynchronous() == false` (DEX swap, NFT auction). Liquidation resolves in one transaction. ``` ACTIVE → GRACE_PERIOD → LIQUIDATED │ │ └─ repay → REPAID └─ repay during grace → REPAID ``` ## Asynchronous path (issuer-redemption / RWA) ``` ACTIVE → GRACE_PERIOD → LIQUIDATION_CURE → LIQUIDATION_SETTLING → LIQUIDATED │ │ └─ REPAID └─ repay (still reversible) → REPAID │ └─ settlement timeout → flag for manual LP intervention ``` ### LIQUIDATION_CURE Entered when liquidation conditions are first met (grace expired or health factor breached). - Interest accrual **freezes immediately** (`frozenInterestAt = block.timestamp`) - Window length is set **per liquidation-adapter instance** (issuer-specific cancellation cutoffs) - Current position holder may repay: principal + frozen interest + liquidation penalty - Penalty is charged by default — this is a genuine default event, not a courtesy extension - LPs may configure penalty-on-cure per market; default is non-zero ### LIQUIDATION_SETTLING Entered when the cure window expires without repayment. - Adapter’s `liquidate()` submits redemption to the issuer - **Irreversible** — collateral is committed to the issuer’s settlement pipeline - Settlement confirmation (callback or keeper poll) distributes proceeds → `LIQUIDATED` - If confirmation never arrives within the outer timeout → flagged for manual LP intervention (where issuer-insolvency risk becomes operational) ## Health factor Optional per market. When enabled, loans can enter liquidation paths before expiry if health drops below the configured threshold. ## Position holder vs original borrower For markets using `TransferablePositionAdapter`, repayments, surplus, and alerts resolve to the **current** position holder — not necessarily the original borrower. Indexers must track NFT `Transfer` events. # Oracle adapters | Adapter | Asset class | Manipulation resistance | Notes | |---|---|---|---| | `UniswapV3TWAPAdapter` | Crypto-native ERC20 | Time-weighted average (10–30 min, LP-configured) | Primary where DEX liquidity is sufficient (>$50k recommended) | | `ChainlinkAdapter` | Crypto without sufficient DEX liquidity | Decentralized nodes + staleness check (e.g. revert if >1hr old) | Fallback path | | `ChainlinkEquityFeedAdapter` | Tokenized equities, ETFs, RWA with issuer Chainlink feed | Session-aware; **24/5 not 24/7**; L2 sequencer uptime check | **Do not use TWAP for this class** | | `NAVOracleAdapter` | Fund-like RWA (treasuries, private credit) | Issuer-published NAV, ideally + Proof of Reserve | Requires issuer cooperation | | `ManualOracleAdapter` | Illiquid / exotic | LP-updated, short validity window | Not recommended for production; flag at create + borrow | ## Equity / RWA pricing rules - Authoritative price is aggregated multi-venue equity market data, not thin on-chain pools - Outside the trusted trading window, `isTrusted` returns `false` → same circuit-breaker path as any untrusted oracle - On L2s, sequencer downtime can freeze feeds at stale values — must be checked before trusting a read ## Engine consumption The engine only needs: 1. `price` 2. `isTrusted` 3. Historical price for volatility lookback It does not special-case oracle implementations beyond what adapters report. # Liquidations ## Adapter comparison | Adapter | Collateral | recovered / returned shape | Sync? | |---|---|---|---| | `DEXSwapLiquidationAdapter` | Divisible ERC20 | Tokens for debt+penalty to LP; remainder tokens to holder | Yes | | `NFTAuctionLiquidationAdapter` | Indivisible ERC721/1155 | Full NFT to LP; surplus as cash side-payment | Yes | | `IssuerRedemptionLiquidationAdapter` | RWA / tokenized equity | Settlement proceeds split debt vs surplus | **No — async** | ## Fairness contract All three satisfy the same interface rule: > Take only what’s owed plus the configured penalty. Return the rest. Enforced by the two-return-value shape of `liquidate()`, not by adapter-author discretion. Product surfaces must show the breakdown (amount to LP vs amount returned) on every liquidation event. ## Async settlement timeline (RWA) Markets using issuer redemption must disclose to LP and borrower before origination: 1. Cure window length 2. Expected issuer settlement period (e.g. T+1 / T+2) 3. Outer timeout → manual intervention path See [Loan lifecycle](/docs/protocol/loan-lifecycle) and [RWA](/docs/protocol/rwa). # Position adapters A loan position’s representation determines who can repay, receive collateral back, and receive liquidation surplus — and whether that right is transferable. ## Tiers | Tier | Representation | Transferable? | Default use case | |---|---|---|---| | `StandardPositionAdapter` | Internal struct, no token | No | Simple crypto markets; lowest gas/complexity | | `SoulboundPositionAdapter` | ERC721, transfers always revert | No | **Default whenever a Compliance Adapter is attached** | | `TransferablePositionAdapter` | Full ERC721 | Yes (eligibility-gated if compliance attached) | Crypto markets wanting secondary-market / composability upside | ## Why NFT representation matters even when soulbound For a single loan, all three tiers behave identically. NFT representation (soulbound or transferable) is about **aggregation and tooling at platform scale**: - **Cross-market enumeration** — standard NFT APIs enumerate “every token this address holds” without bespoke per-market indexing forever - **Wallet-native visibility** — positions appear in standard wallets - **Standardized metadata (`tokenURI`)** — portfolio trackers, tax tools, institutional systems render state without OpenAsset Market-specific integration ## Compliance hole this closes A transferable position in a compliance-gated market would let a KYC’d borrower originate, then sell the position NFT to someone never checked. Economic control would pass while collateral stayed “compliant.” - Soulbound default for compliance markets closes this by construction - Validation Matrix still requires transfer-hook eligibility checks if Transferable + Compliance are combined ## Product defaults - Compliance attached → recommend **Soulbound** - No compliance → recommend **Transferable** (or Standard for gas-minimized markets) - Always allow LP override with plain-language tradeoff at the point of choice # RWA & tokenized equity support ## Issuer / counterparty risk Every tokenized equity or RWA token is a **claim on an issuer**, not a pure bearer asset secured only by code. If the issuer becomes insolvent, halts redemptions, or is shut down by a regulator, the token can go to zero or freeze — **independent of the underlying asset’s price**, and independent of OpenAsset Market’s liquidation mechanics. This is out of the protocol’s control by construction. No adapter or liquidation logic changes it. It must be disclosed in UI and Terms of Service as an uninsured, total-loss-possible risk category distinct from ordinary market/price risk. ## Transfer restriction models | Model | Example pattern | Integration implication | |---|---|---| | Freely transferable | Some bToken-style products | Standard `ERC20Adapter` may work unmodified | | Permissioned / identity-gated (ERC-3643 / T-REX) | Institutional issuers | Requires Compliance Adapter; market/vault must complete issuer onboarding as whitelisted holder | | Issuer-specific / evolving | Broker stock tokens | Verify current issuer docs before any market launch | ## Corporate actions & dividends | Model | Effect while collateral is escrowed | |---|---| | Auto-mirrored to token balance | Updates on-chain; oracle reflects value | | Total-return / NAV appreciation | Price feed reflects reinvestment | | Off-chain cash credit only | Credit may go to escrow holder of record (the market), **not** the borrower, unless issuer provides pass-through — confirm per issuer and disclose | ## Oracle rule (repeated because it is the common mistake) Equity/RWA markets require `ChainlinkEquityFeedAdapter` (or equivalent issuer/NAV oracle), **never** `UniswapV3TWAPAdapter`. ## Liquidation Issuer-redemption liquidation is **asynchronous**. Pair with a Compliance Adapter (Validation Matrix). Full path: [Loan lifecycle](/docs/protocol/loan-lifecycle). ## Legal gate Securities/RWA counsel review is a **hard pre-launch gate** for enabling real-user markets that use a Compliance Adapter — distinct from engineering readiness and contract audit. # Lending asset scope ## v1 rule **The lending (borrowed-out) asset is stablecoins only.** This is a Factory-enforced allowlist, not LP discretion. Borrowers receive stablecoin proceeds and may convert outside the protocol. ## Why Adapter-ization is scoped to the **collateral** side first. Expanding pluggable-asset logic to both sides of a loan simultaneously multiplies audit surface for limited near-term benefit. ## Future Non-stablecoin lending assets (ETH, BTC) are an explicit, demand-gated future item — see [Deferred / out of scope](/docs/reference/deferred). # Multi-chain architecture ## v1 scope: EVM only Supported pattern: Ethereum, Base, Arbitrum, Optimism, Polygon, and EVM-compatible RWA-specific chains. Each chain is a **separate, chain-native deployment** with its own Factory and Registry instance — not a unified cross-chain liquidity layer. ## Solana is not a port Solana / Anchor has no equivalent plug-and-play adapter pattern. A Solana market’s “adapter” is a distinct design exercise. Solana support is deferred to its own architecture document — not assumed to follow from these EVM interfaces. ## Deferred - Cross-chain unified liquidity - Cross-chain position portability - Shared cross-chain reputation / analytics # Compliance responsibility boundary This boundary must never be assumed to be handled by a mechanism that doesn’t exist. ## What Compliance Adapters do - **Point-in-time checks** at specific protocol actions: - Loan origination - Position transfer (for TransferablePosition markets) - Enforce whatever eligibility rule already exists at the **asset / issuer** level ## What they do not do - Continuous monitoring of real-world eligibility mid-loan - Poll for sanctions designations or revoked KYC after origination - Define who qualifies as an eligible investor, permitted jurisdictions, or KYC/AML standards ## Mid-loan eligibility changes If a participant’s status changes mid-loan, OpenAsset Market **does not poll for this**. Enforcement happens through the **underlying token issuer’s own freeze mechanism** (e.g. capabilities required by ERC-3643), acting on the token outside OpenAsset Market contracts. ## Product implication This boundary must appear in user-facing documentation (this site), not only internal specs, so LPs and borrowers understand ongoing enforcement limits. # Security model ## Reentrancy & CEI Every state-changing function uses `nonReentrant`. Every adapter call follows strict Checks-Effects-Interactions: validate → update internal state → call out to the adapter. ## Integer safety Solidity `^0.8.20` default overflow checks apply. `unchecked {}` only where overflow is provably impossible given realistic bounds, with inline justification comments. ## Adapter trust boundary See [Adapter trust model](/docs/protocol/trust-model) in full. Treat as equally load-bearing as reentrancy protection during audit. ## Issuer insolvency See [RWA § Issuer risk](/docs/protocol/rwa). Explicitly **not** a code-level problem — a documentation, disclosure, and legal (ToS) requirement. ## Operational security baseline - 2+ independent audits pre-mainnet - Bug bounty live - >90% test coverage target - Multisig treasury and audit-governance keys - Incident response plan documented Full checklist: [Security checklist](/docs/reference/security-checklist). # Data models ## On-chain ```solidity struct Loan { uint256 collateralAmount; uint256 principal; uint256 startTime; uint256 expiryTime; uint256 frozenInterestAt; // 0 unless LIQUIDATION_CURE or beyond LoanStatus status; } ``` ## Off-chain (PostgreSQL) ### markets ```sql CREATE TABLE markets ( id SERIAL PRIMARY KEY, contract_address VARCHAR(66) UNIQUE NOT NULL, chain_id INTEGER NOT NULL, lp_address VARCHAR(66) NOT NULL, collateral_asset VARCHAR(66) NOT NULL, lending_asset VARCHAR(66) NOT NULL, asset_adapter VARCHAR(66) NOT NULL, oracle_adapter VARCHAR(66) NOT NULL, compliance_adapter VARCHAR(66), liquidation_adapter VARCHAR(66) NOT NULL, position_adapter VARCHAR(66) NOT NULL, ltv_bps INTEGER NOT NULL, apr_bps INTEGER NOT NULL, status VARCHAR(20) DEFAULT 'ACTIVE', created_at TIMESTAMP DEFAULT NOW() ); ``` ### adapters ```sql CREATE TABLE adapters ( id SERIAL PRIMARY KEY, adapter_address VARCHAR(66) UNIQUE NOT NULL, adapter_type VARCHAR(20) NOT NULL CHECK ( adapter_type IN ('ASSET','ORACLE','COMPLIANCE','LIQUIDATION','POSITION') ), verified BOOLEAN DEFAULT FALSE, deprecated BOOLEAN DEFAULT FALSE, audit_reference TEXT, total_value_secured DECIMAL(30, 18) DEFAULT 0, registered_at TIMESTAMP DEFAULT NOW() ); ``` ### loans ```sql CREATE TABLE loans ( id SERIAL PRIMARY KEY, loan_id_onchain INTEGER NOT NULL, market_address VARCHAR(66) NOT NULL, position_holder_address VARCHAR(66) NOT NULL, status VARCHAR(30) DEFAULT 'ACTIVE' CHECK ( status IN ( 'ACTIVE','GRACE_PERIOD','LIQUIDATION_CURE', 'LIQUIDATION_SETTLING','REPAID','LIQUIDATED' ) ), health_factor DECIMAL(10, 2), created_at TIMESTAMP DEFAULT NOW() ); ``` ## Indexer note For any market using `TransferablePositionAdapter`, the backend must listen for position NFT `Transfer` events and update `position_holder_address`. Health alerts must resolve the **current** holder before sending — never assume the original borrower remains correct. # Using adapters ## For LPs - Prefer **Verified** reference adapters unless you have a specific reason not to - Read audit references before wiring third-party adapters - Unverified adapters require explicit risk acknowledgment - Deprecated adapters cannot be selected for **new** markets; existing markets keep running with banners ## For borrowers - Market detail pages list all five adapter choices with status - Unverified oracles and liquidations should be treated as elevated risk - Manual oracles are flagged at borrow time, not only at market creation ## For adapter authors 1. Implement the correct interface (`IAssetAdapter`, `IOracleAdapter`, …) 2. Register permissionlessly in the Adapter Registry 3. Optionally pursue OpenAsset Market verification (audit governance multisig) 4. Expect the engine to verify your outputs regardless of verification status — design honestly Deep dive: [Adapter system](/docs/protocol/adapter-system) · [Trust model](/docs/protocol/trust-model) · [Registry](/docs/protocol/adapter-registry) # Borrow against collateral ### Find a market Browse markets for your collateral asset. Review LTV, APR, duration, oracle type, liquidation path, and adapter trust badges. ### Eligibility pre-check If the market has a Compliance Adapter, the app checks `isEligible` **before** prompting wallet approval — so ineligible borrowers don’t spend gas on a revert. ### Deposit collateral & request - Approve and escrow collateral via the market’s Asset Adapter - Max loan is computed from oracle price × LTV - Confirm position type disclosure (standard / soulbound / transferable) ### Receive proceeds Stablecoin proceeds transfer to your wallet. Convert outside the protocol if needed. ### Manage the loan - Monitor health factor (if enabled) - Repay before expiry / grace end - Watch alerts if near liquidation On transferable-position markets, whoever holds the position NFT is the economic actor for repay, surplus, and alerts — not necessarily the original borrower. ## If you’re ineligible The UI should surface the adapter’s reason when available (e.g. jurisdiction) and suggest alternative markets you can use. # Create a market As an LP, you launch a market by selecting adapters and setting risk parameters — one deployment, no approval step. ### Collateral asset - Enter asset address / type - Select **Asset Adapter** (Verified list first; custom registration available with unverified warning) - System checks asset adapter ↔ asset type compatibility ### Oracle - Select an Oracle Adapter appropriate to the asset - UI recommends: TWAP for crypto ERC20; Chainlink Equity Feed for tokenized equities/RWA - Review Verified/unverified status and TVL secured by the adapter ### Compliance (optional) - “Does this asset require holder eligibility checks?” - If yes: select Compliance Adapter (ERC-3643, issuer allowlist, jurisdiction geofence, etc.) - Required before async liquidation or certain transferable+permissioned combinations (Validation Matrix) ### Liquidation - Choose DEX Swap, NFT Auction, or Issuer Redemption - Issuer Redemption requires Compliance Adapter and surfaces async settlement timeline ### Position representation - Standard / Soulbound / Transferable - Defaults to Soulbound when compliance is attached ### Risk parameters - LTV, APR, duration, grace period - Health factor toggle + threshold - Circuit breaker toggle + thresholds ### Lending asset & liquidity - Lending asset from **stablecoin allowlist only** - Initial liquidity + creation fee ### Deploy - Factory runs full Validation Matrix - Reverts with specific, human-readable reason on any failure - Live immediately on success Selecting an **unverified** adapter requires an explicit confirmation: you understand it has not been audited by OpenAsset Market. ## Acceptance criteria (product) - Every adapter selection shows Verified/unverified badge and TVL before confirm - Incompatible combinations rejected in UI before tx submit, citing the rule - One-transaction deploy, no approval queue # Async liquidation flow For markets using `IssuerRedemptionLiquidationAdapter`: ### Trigger Health factor breaches threshold, or grace period expires. ### LIQUIDATION_CURE - Interest freezes immediately - Holder notified with deadline and repayment amount (frozen debt + penalty) - **Repay still possible** ### Path A — cured Holder repays within the window → loan closes `REPAID`, collateral released. ### Path B — cure expires - Redemption submitted to issuer - Loan enters `LIQUIDATION_SETTLING` (irreversible) - Holder notified that repayment is no longer possible ### Settlement confirms Proceeds split `recoveredForLP` / `returnedToHolder` → loan closes `LIQUIDATED`. ### Exception — settlement timeout If confirmation doesn’t arrive within the outer timeout, the loan is flagged for **manual LP intervention**. # Launch an RWA market ### Select RWA / tokenized equity category Enter the issuer’s token address. The app loads the issuer profile: custody model, transfer restriction type, dividend handling. ### Confirm oracle System recommends `ChainlinkEquityFeedAdapter`. Do not use Uniswap TWAP for this class. ### Attach Compliance Adapter Required for this category. Choose the issuer-appropriate adapter (e.g. ERC-3643) from the Verified list when available. ### Choose Issuer Redemption liquidation Review and acknowledge the async settlement flow (cure window + expected settlement). ### Position defaults to Soulbound Proceed unless you have a validated reason to override (Validation Matrix still applies). ### Set risk parameters & stablecoin liquidity Same numeric controls as crypto markets. Lending asset from allowlist only. ### Deploy Factory validates Compliance present, async liquidation pairing, allowlisted lending asset, and related rules. ## Disclosures required - Issuer custody model (1:1 redeemable vs synthetic/offshore claim) - Dividend / corporate-action handling - Async settlement timeline - Issuer-insolvency as uninsured total-loss risk (UI + ToS) # Security checklist - [ ] Core engine independently verifies every adapter’s output ([trust model](/docs/protocol/trust-model)) — for **all** adapters, not only unverified ones - [ ] Reentrancy guards and CEI ordering on every adapter call, not only user-facing entry points - [ ] Market Factory validation matrix enforced and unit-tested for every rule, including negative tests - [ ] Circuit breaker tested under volatility **and** stale/untrusted-oracle triggers - [ ] Async liquidation state machine tested: cure repay, cure expiry, settlement confirm, settlement timeout → manual flag - [ ] TransferablePosition + Compliance Adapter transfer-hook eligibility check tested specifically - [ ] Registry `markVerified` / `markDeprecated` restricted to audit-governance multisig, not a single key - [ ] Deprecation behavior tested: blocks new selection, does not force-pause existing markets, notifies LPs - [ ] Reference adapters independently audited before marked Verified - [ ] Legal/securities counsel review before any real-user Compliance Adapter market (RWA / permissioned assets) - [ ] Terms of Service disclose issuer insolvency as uninsured total-loss risk, distinct from price risk - [ ] Baseline retained: 2+ independent audits, bug bounty, >90% coverage, multisig treasury, incident response plan # Deferred / out of scope Explicitly considered and deliberately excluded from v1: | Item | Why deferred | |---|---| | Reputation-based lending tiers | No sufficiently reliable on-chain reputation protocol to build on | | Agentic (AI-agent) borrowers | Architecture is human/wallet-first; nothing precludes later support | | Non-stablecoin lending assets (ETH/BTC) | Demand-gated; doubles adapter scope on the lend side | | Solana / non-EVM | Separate design — not a port of EVM adapter interfaces | | Cross-chain unified liquidity / position portability | Each chain deployment is independent in v1 | | Autonomous adapter-verification agent | Verification remains human-governed in v1 | # Glossary | Term | Definition | |---|---| | **oA** | Brand mark for OpenAsset Market (titles, navbar) | | **LP** | Liquidity provider / market creator | | **Isolated market** | Independent `LendingMarket` instance; no shared-pool contagion | | **Adapter** | Pluggable contract implementing one of five interfaces | | **Verified adapter** | Passed OpenAsset Market audit sign-off; still defended against at the engine layer | | **Gradual liquidation** | Interface-enforced rule: take debt+penalty, return surplus | | **LTV** | Loan-to-value ratio in basis points | | **Circuit breaker** | Core pause of new originations on volatility or untrusted oracle | | **LIQUIDATION_CURE** | Reversible async default window; interest frozen | | **LIQUIDATION_SETTLING** | Irreversible async redemption in flight | | **Soulbound position** | Non-transferable ERC721 loan representation | | **Stablecoin allowlist** | Factory-enforced set of permitted lending assets |