Env argument. Amounts use raw token units
unless a scale is specified. Use the full HubAssetKey to identify a market.
Construction uses __constructor(admin: Address) and leaves the controller paused.
Types are defined in Data types. Error codes are
listed in Errors. Events are listed in
Events.
Governance owns the controller. Configuration follows the
governance execution rules.
Reading the tables
User and maintenance calls require the explicitcaller, liquidator, or
payer to authorize. The Auth column gives the additional account check.
Admin calls require the controller owner to authorize. accept_ownership
requires the pending owner.
Pause:
gated calls fail while the controller is paused. open calls remain
available. Account, listing-flag, and pool checks still apply.
Flash-loan guard: financial calls fail with #400 FlashLoanOngoing during a
flash loan. Account renewal and delegate changes use their own authorization
checks. The flash-position callback can use allowed controller calls; final
account checks still apply.
Core lending
supplycreates accounts inPositionMode::Normal; see account creation for the zero-id convention.- A caller who is neither owner nor delegate may only add to hub assets the account already holds a supply position in. New accounts skip the check because the caller becomes the owner.
toselects the recipient onborrowandwithdraw; it defaults tocaller. Debt is always booked toaccount_id.- On
withdraw, a zero amount withdraws the entire position for that asset. The return value reports the resolved pool payout for each asset. - Anyone may repay an account’s debt; the caller’s signature is needed only to pull the tokens.
- Amounts credited are measured from receipts. A token that delivers less than it is sent credits the delivered amount.
Liquidation
seize_mode is SeizeMode::Transfer (pool pays underlying, withholding the
protocol fee) or SeizeMode::Credit(account_id) (seized supply shares move to a
controller account). Credit(0) creates the receiving account and liquidate
returns its id; Transfer returns 0. See
Liquidations.
Leverage and strategies
All calls below are pause-gated. Account strategies check final solvency and publish position updates.flash_loan settles principal plus fee and creates no
account debt. See Strategies.
swap and convert_swap are opaque route bytes. The published SDK 1.0.228
builders accept routeXdr for swap routes. Equal underlying tokens require empty
route bytes. repay_debt_with_collateral nets supply against debt directly only
when the full HubAssetKey matches. close_position = true requires an empty
debt map before it withdraws all remaining collateral.
multiply and swap_debt charge a strategy fee on gross new debt.
flash_position mints fee-free debt and must finish with supply and positive debt
in its declared debt market.
For an existing account, multiply and flash_position require mode to match
the stored mode (#25 AccountModeMismatch). Receiver requirements are described
in Flash positions and
Flash loans.
Account and delegation
add_delegaterequires an active, governance-approved position manager. Delegates are capped at 16 (#45 RegistryCapReached).remove_delegateremains available during a controller pause.- A delegate grant is bound to the owner who made it. Transferring the position NFT deactivates the previous owner’s grants immediately.
renew_accountextends both the account’s storage TTL and the NFTOwnerentry.
Permissionless maintenance
Caller-signed; none carries a privileged role.Owner-gated configuration
Configuration calls require the owner, exceptaccept_ownership, which requires
the pending owner. get_app_version is public. In production, governance owns
the controller and applies its proposal and timelock rules.
set_spoke_asset_flags and edit_asset_in_spoke can retain or tighten halt
flags. They cannot clear a set flag (#317 SpokeAssetFlagRelaxation). Clear flags
with timelocked AdminOperation::RelaxSpokeAssetFlags and the current
get_spoke_asset_flags_epoch as expected_epoch.
Governance checks the epoch at proposal time. The controller checks it again at
execution. A later flag write invalidates the old proposal (#319 SpokeFlagsEpochMismatch). Listing and relisting advance the epoch. Explicit flag
writes advance it even when the requested flags are unchanged. Risk-only edits
that retain all flags do not advance it. Removing a listing preserves the epoch.
Views
Views require no authorization and do not persist economic state. Storage reads can renew TTL.get_market_indexes_detailed and get_liquidation_estimate accept
at most MAX_VIEW_INPUTS = 256 inputs. A larger list fails with #16.
Account risk
Account state
Simulation
get_liquidation_estimate(account_id: u64, debt_payments: Vec<(HubAssetKey, i128)>, seize_mode: SeizeMode) -> LiquidationEstimate
returns seized_collaterals, protocol_fees, refunds, max_payment_wad, and
bonus_rate_bps.
Market and configuration
get_collateral_amount and get_borrow_amount use half-up rounding. A full
withdrawal floors its payout; a full debt repayment needs the ceiling-rounded
debt. Do not use a display balance as an exact close amount.
There is no max_withdraw, max_borrow, or max_supply view on the
controller. Size an action against get_collateral_amount,
get_ltv_collateral_usd, get_spoke_usage, and the pool’s get_reserves, or
simulate the call.
Account creation and batching
account_id = 0creates an account. It applies tosupply,multiply,flash_position,migrate_from_blend, and asSeizeMode::Credit(0)inliquidate. Each returns the resolved account id. Creating an account mints its position NFT; there is no separate account-creation entrypoint.- The spoke id is fixed at creation. Calls accepting a spoke id check it against
existing account metadata (
#310 SpokeMismatch); others use the stored spoke. - Position mode is fixed at creation.
- Zero has different meanings. On entry legs (
supply,borrow,repay) zero is rejected. Onwithdrawit means “the entire position”. - Payment batches sum duplicate legs by full
HubAssetKey. They preserve first-appearance order. Overflow fails with#33 MathOverflow.flash_positioncollateral declarations instead require distinct tokens.
account_id is the position NFT’s token_id. Ownership and transfer
behavior are documented in Position NFT.
