Architecture Overview
Market Manager admin
Protocol-level administrative role controlled via a multisig. Deploys new market contracts through the Market Manager and reads the list of deployed markets. Operates only at the "which markets exist" layer — it does not touch pools or user obligations directly. Admin transfer follows a 2-step process (propose_new_admin → accept_proposed_admin).
Market admin
Administrative actor for a specific (owned) market. Manages pools with time-locked queue_in_pool_set → apply_pool_set, and manages market config with time-locked queue_in_market_update → apply_market_update. Controls market status with update_market_status (7 statuses including *ByAdmin variants) and per-pool status with update_pool_status (bitfield flags). Configures fee beneficiaries with set_take_rate_fees_beneficiaries and set_operation_fees_beneficiaries, updates the swap provider with update_swap_provider, and can transfer the admin role via propose_new_admin → accept_proposed_admin. All changes are persisted in the market's pool structure.
User
Standard protocol participant (lender, borrower, or reader). Each user position is identified by an ObligationKey { user: Address, seed: Option<BytesN<32>> }, allowing a single address to maintain multiple isolated positions. Users supply assets with deposit, borrow with borrow, repay with repay, exit with withdraw, and manage collateral with add_collateral and remove_collateral. Advanced strategies are composed via submit_requests_batch (e.g., flash borrow + swap + deposit + borrow in one atomic transaction). The market updates the user's obligation and relevant asset pool on every action, applying current pool config and state.
Market Manager
Registry and factory smart contract for markets. Deploys new markets (constructor invoked via manager), stores and returns the list of deployed markets, and serves as the protocol-level entry point for market creation. Receives calls from the Market Manager admin and exposes deployed market addresses to other actors.
Market
Main functional smart contract of the protocol, where lending and borrowing occur.
There are two types of markets. Owned markets have config that can be modified by the admin via the time-locked update queue — changes are queued first and applied after the required period. Ungoverned markets have permanently immutable config; admins can only configure fee beneficiaries.
The market maintains per-asset pools created via time-locked queue_in_pool_set → apply_pool_set, stores and updates all user obligations (identified by ObligationKey) on calls like deposit, borrow, repay, withdraw, add_collateral, and remove_collateral, and executes composable batch operations via submit_requests_batch. It provides service functions (liquidate, issue_cover_bad_debt, claim_cover_bad_debt_results) and fee distribution via distribute_pool_fees and distribute_all_pools_fees. Markets support 7 statuses (Active, BorrowFrozen, BorrowFrozenByAdmin, DepositFrozen, DepositFrozenByAdmin, Frozen, FrozenByAdmin), and individual pools carry per-pool status flags (4-bit bitfield) for fine-grained operation control.
The market receives calls from users and the market admin, is created by the Market Manager, calls an external DEX (swap provider) for swaps in batch operations, queries the external oracle for prices, and accepts liquidation calls from external liquidators.
Asset pool
Per-asset liquidity pool inside a market (e.g., XLM, USDC). Each pool holds supply and borrow balances for its asset, acts as the target for user deposits and borrows, and can participate in collateral relationships between assets. Per-pool status flags control which operations are enabled. Balances and utilization are tracked in pool state, user obligations record into specific asset pools, and the pool structure consumes their data for interest and fee calculations.
Insurance fund
A per-market safety buffer implemented as a smart contract, funded primarily by protocol fees (take rate and configured portions of operation fees), with optional inflows from high-utilization exit fees and donations. Covers residual bad debt after liquidations via the two-phase flow issue_cover_bad_debt → claim_cover_bad_debt_results. Can freeze the market via fund_update_market_status, but cannot override *ByAdmin states. When an insolvent obligation remains under-collateralized after liquidations, the market issues cover requests to the fund. The fund can proactively freeze market operations in emergencies.
INFO
Learn more in Insurance Fund
Pool structure (pool config → pool state)
Internal representation of pool rules and live figures. Pool config stores status, fee, health, interest rate model, accrual model, and reactivity params — updated via time-locked queue_in_pool_set → apply_pool_set. Pool state stores live numbers: available liquidity, total borrowed, total jTokens/dTokens, collateral, accumulated fees, and the interest rate modifier. Receives updates from both market-admin actions and user actions processed by the market, and serves as the single source of truth for pool totals and fees.
User obligations
Unified storage for all user positions in a market, keyed by ObligationKey. Stores deposits (jTokens + plain collateral), borrows (dTokens), and position counts. Supports different obligation types via the seed: standard (no seed), earn (earn seed), and pair (pair seed). Enforces limits such as MaxPositions and MinCollateralValue, and tracks active Insurance Fund cover requests. Updated on every user action (deposit, borrow, repay, withdraw, add_collateral, remove_collateral, and batch operations), records into the corresponding asset pools, and is evaluated by cross-pool logic for health and liquidation eligibility.
Cross-pool
Shared risk and health logic that operates across pools. Performs cross-pool collateral evaluation, computes position health using pool and oracle data combined with open/close LTV and liability factors, and determines liquidation conditions for unhealthy obligations. Operates on user obligations (all types via ObligationKey), with decisions enforced when a liquidator calls liquidate on the market. Relies on pool state and oracle prices made available by the market.
AMM DEX (Swap Provider)
External swap venue, configurable via update_swap_provider. Executes swaps as part of composable batch operations and supports flash-loan-based operations that need token conversion. Called by the market during submit_requests_batch when swap requests are included; does not initiate interactions on its own.
Oracle
External SEP-40 price oracle. Returns current asset prices for pools, enabling valuation of collateral and debt and supporting health checks and liquidation decisions. Queried by the market whenever up-to-date prices are needed (borrow, withdraw, liquidate), and provides price inputs used by cross-pool logic.
Liquidator
External, permissionless actor (not the borrower). Calls the market's liquidate method on unhealthy positions, repays debt, and receives discounted collateral subject to the pool's liquidation incentive limits. Can also liquidate within batch operations via LiquidateRequest. The market applies cross-pool liquidation rules and updates user obligations and affected asset pools on each liquidation.