Account identity and ownership
The controller API uses au64 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 byHubAssetKey. 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 withadd_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.
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 successfulaccount_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.

