LiquidityPool is a single contract that holds pooled liquidity and accounting
for every listed market, keyed by HubAssetKey (PoolKey::Params(key) /
PoolKey::State(key)). The same token on two hubs is two independent markets.
The controller is the pool’s owner; every mutator is controller-only.
Types are in Data types. Pool events are in
Events.
Lifecycle
create_market registers one market: it validates params, writes
PoolKey::Params(key) and a fresh PoolKey::State(key) (indexes at RAY,
zeroed totals), and raises #2 AssetAlreadySupported if the market already
exists. update_params accrues at the old rate before replacing the model.
Accounting verbs
All the position-moving verbs are batched — they take a vector of entries and return a vector of mutations, one per market touched.Flash loan
amount to receiver, invokes
receiver.execute_flash_loan(initiator, asset, amount, fee, pool, data), then
pulls back amount + fee and asserts the final balance equals
pre_balance + fee. The receiver must be a deployed Wasm contract (#412);
any repayment shortfall raises #402. The fee is recorded as protocol revenue
and returned to the caller.
Views
No auth. All take aHubAssetKey.
get_reserves reports the market’s cash figure. Reserves are not a separate
quantity from cash. It is persisted PoolStateRaw.cash, the liquidity source for
borrows, withdrawals, and revenue claims — direct token donations to the pool
address are excluded. Flash-loan settlement is the one place that reads the live
token balance; see
Security model.Maintenance and revenue
update_indexes accrues interest to now. No tokens move.
claim_revenue does four things in order: sync the indexes, burn enough revenue
shares (ceil-rounded) to cover the payout, cap the payout at available cash, and
transfer. It always pays its owner, the controller, which forwards the proceeds
to the configured accumulator.
Events
The pool publishes three events, contrary to older versions of these docs:PoolMarketStateBatchEvent (["market", "batch_state_update"]),
PoolMarketParamsBatchEvent (["market", "batch_params_update"]), and
StrategyFeeEvent (["strategy", "fee"]). See
Events for the wire shapes.
Defense-in-depth checks
Each mutating path validates locally so a controller bug cannot silently corrupt pool state:- Rejects non-positive amounts (
#14). - Panics
#30 PoolNotInitializedif the market’sParams/Statekeys are absent. - Checks cash before any outgoing transfer (
#112) and enforces the liquidation-buffer and max-utilization guards (#127). - Rejects a positive movement that would change zero shares (
#47,#49,#50,#51,#52). - Guards solvency: supplier claims may not exceed cash plus outstanding debt
(
#123 PoolInsolvent). - Validates the rate model on
create_marketandupdate_params. - Verifies flash-loan repayment with a pre/post balance check.
Controller dependency
The controller depends on the pool ABI, not the pool implementation crate. Runtime coupling is on the ABI only, which keeps the controller – pool trust boundary explicit. See Security model.Next
Controller ABI
The public entrypoints that call this interface.
Storage
The
HubAssetKey-keyed PoolKey layout, durability, and TTL.
