Skip to main content
LiquidityPool is a single contract that holds pooled liquidity and accounting for every listed market, keyed by HubAssetKey. The same token on two hubs is two independent markets. The controller owns the pool and authorizes every mutating call. Signatures omit the Soroban-injected Env argument. Construction uses __constructor(admin: Address) to set the owner. Types are in Data types. Pool events are in Events.

Lifecycle

create_market validates params and initializes the market with indexes at RAY and zero balances. It raises #2 AssetAlreadySupported if the market already exists. update_params accrues at the old rate before replacing the model.

Accounting calls

supply, borrow, withdraw, and repay return one mutation per input entry. Each entry identifies its market with a full HubAssetKey.

Flash loan

The pool records its token balance, transfers amount, and checks the exact pool balance decrease. It calls receiver.execute_flash_loan(initiator, asset, amount, fee, pool, data) and checks that the callback did not change the pool balance. It then pulls amount + fee with transfer_from and checks final_balance = pre_balance + fee. The receiver must be a deployed Wasm contract (#412). It must approve the pool for principal plus fee. An allowance or balance mismatch fails with #402. Token transfer failures can instead return the token contract’s error. The pool books the fee as revenue and returns it.

Views

Views require no authorization. Market loads renew TTL. Balance and rate views use stored indexes; get_bulk_indexes projects accrual to the current ledger time without committing accounting state. A mutation can accrue again before settlement. Direct token donations are excluded from get_reserves. For the balance checks used during settlement, see Token and accounting assumptions.

Maintenance and revenue

update_indexes accrues interest to ledger time without moving tokens. claim_revenue syncs the indexes, reconstructs the revenue claim, caps the payout at available cash, burns enough revenue shares (ceil-rounded), and transfers the payout. It always pays its owner, the controller, which forwards the proceeds to the configured accumulator.

Accounting checks

Pool paths apply local accounting checks. Which checks run depends on the operation:
  • Rejects invalid amounts (#14); full withdrawal uses i128::MAX.
  • Panics #30 PoolNotInitialized if the market’s Params / State keys are absent.
  • Checks available cash (#112). Debt mints also preserve the liquidation buffer. Ordinary withdrawals do not apply that buffer.
  • Debt mints and ordinary withdrawals check max utilization (#127). Liquidation withdrawals and empty closes skip that check.
  • Rejects a positive movement that would change zero shares (#47, #49, #50, #51, #52).
  • Applies operation-specific solvency checks (#123). Backing checks compare floored supply claims with cash plus ceiling-rounded debt. Withdrawals also reject zero supply with remaining debt.
  • Validates the rate model on create_market and update_params.
  • Verifies flash-loan repayment with a pre/post balance check.
Full withdrawals floor the payout. Display supply and debt views use half-up rounding. Full repayment uses ceiling-rounded debt. Revenue is outstanding supply shares, not a cumulative counter; a claim reduces it. Pool state, parameter updates, and strategy fees are published through the pool events.

Next

Controller ABI

The public entrypoints that call this interface.

Storage

The HubAssetKey-keyed PoolKey layout, durability, and TTL.