Skip to main content
A lending account groups supply and borrow positions under one owner. Every account binds to a spoke at creation; its spoke and position mode remain fixed. The spoke determines which markets the account can use and their risk terms.

Account identity and ownership

The controller API uses a u64 account id. It matches a position-NFT token id, which uses u32; 0 is reserved for account creation on supported entrypoints. The NFT holder owns the account, and the controller resolves ownership from that contract when authority is required. Transferring the NFT transfers all collateral and debt. The spoke, mode, and stored risk parameters remain with the account. See Position NFT for transfer and approval rules. Calls accepting spoke_id compare it with existing account metadata. A mismatch reverts with #310 SpokeMismatch; other calls use the stored spoke.

Positions and limits

Supply and debt positions are keyed by HubAssetKey. Each stores a scaled RAY balance; market indexes convert it into an underlying token amount. Supply positions also store loan-to-value (LTV), liquidation threshold, liquidation bonus, and liquidation fee snapshots. See Interest and revenue for conversion and rounding. Governance sets separate supply- and borrow-position limits, each at most POSITION_LIMIT_MAX = 5. Adding a position above the configured limit reverts with #109 PositionLimitExceeded. Existing positions remain usable if governance lowers a limit below the account’s position count.

Account authority

Borrow, withdraw, and account-strategy calls require the owner or an active delegate. renew_account requires the account owner to authorize; a delegate grant does not permit renewal through this controller entrypoint. The following flows allow other authenticated callers:

Delegates

An owner grants authority with add_delegate. The delegate must be a registered, active position manager when the grant is made and when it is used. Governance controls that manager registry. Each account allows at most MAX_DELEGATES = 16; exceeding it returns #45 RegistryCapReached. Grants record the granting owner. When the NFT moves to another address, the old grants become inactive. A delegate write by the new owner replaces stale grant state. remove_delegate remains callable while globally paused.
If the NFT returns to the granting owner before a subsequent delegate write replaces the old grants, those grants become active again, provided the manager is still active. NFT transfer approvals and controller delegate grants are separate permissions.

Risk gates

Borrow, indebted withdrawal, and account-strategy finalization check both LTV-weighted collateral and health factor. They also enforce the configured minimum LTV-weighted collateral value while debt remains. Each collateral position below 3 decimals must then hold at least two token base units. Such a market must be the account’s only supply market. Plain repayment does not run these gates or refresh collateral parameters. The Health factor page defines the formulas, rounding, and debt-free behavior. The Risk parameters page defines spoke caps and halt flags.

Risk-parameter refresh

Stored LTV and liquidation terms have different update rules: The liquidation tuple contains threshold, bonus, and fee. With debt, a lower threshold, higher bonus, or lower fee applies only if the hypothetical HF using the proposed threshold is at least 1.05 WAD. Otherwise the entire old tuple remains while LTV can update. Borrowing power therefore uses min(LTV, stored liquidation threshold). Unlisted positions retain their snapshots. update_account_threshold is permissionless but globally pause-gated. It skips missing account metadata, empty supply maps, and accounts whose NFT ownership cannot be resolved. Changed positions emit ParamUpd legs; no funds move.

Account deletion

An empty account is removed and its position NFT is burned. Confirm deletion with a successful account_exists(account_id) == false read before clearing a stored id. Failed RPC, restoration, or ownership reads do not prove deletion. An empty API response can also reflect indexing lag or an NFT transfer.

Position modes

Strategy entrypoints enforce the required mode. See Strategies for account creation and route execution, and Storage for account records.