Skip to main content
SmartAccount is a per-user deployed contract — each margin account is a separate on-chain instance. It stores all collateral balances, records which assets have been borrowed, and executes external protocol calls on behalf of its owner. Important: SmartAccount functions cannot be called directly by users. All calls must originate from the registered AccountManager. Every function begins with account_manager.require_auth().
Individual SmartAccount addresses are determined at account creation time. Use Registry.get_accounts(trader_address) or listen for AccountCreationEvent to find a user’s SmartAccount address.

Account State

activate_account

Sets IsAccountActive = true. Called by AccountManager immediately after deploying or reusing a SmartAccount.

deactivate_account

Sets IsAccountActive = false. Called by AccountManager when the account is closed and pushed to the inactive pool.

has_debt

Returns true if any borrowed tokens are listed in BorrowedTokensList.

set_has_debt

Sets the HasDebt flag. Called by AccountManager when the debt list transitions from empty to non-empty or vice versa.

Collateral Management

get_all_collateral_tokens

Returns the list of all token symbols currently held as collateral. Used by RiskEngine to enumerate assets when computing health factor.

add_collateral_token

Appends symbol to CollateralTokensList if not already present. Called by AccountManager on first deposit of a new token type.

get_collateral_token_balance

Returns the balance of symbol held in this account, in WAD format.

set_collateral_token_balance

Overwrites the stored balance for symbol. Called by AccountManager after deposit or withdrawal.

remove_collateral_token_balance

Transfers amount (in native decimals) of symbol to trader, subtracts from stored CollateralBalanceWAD, and removes the token from CollateralTokensList if balance reaches zero.

sweep_to

Transfers all collateral tokens to to_address. Called in two scenarios:
  • close_account() — sweeps to owner
  • liquidate() — sweeps remaining collateral (after debt repayment) to trader
For XLM, USDC: actual token balances are transferred.
For tracking tokens (BLEND_XLM, AQ_XLM_USDC, etc.): the internal balance record is zeroed but the underlying position in the external protocol (Blend pool, Aquarius pool) is not unwound. The external position remains.

Debt Management

get_all_borrowed_tokens

Returns the list of all token symbols with outstanding debt.

add_borrowed_token

Appends symbol to BorrowedTokensList. Called by AccountManager after a successful borrow.

remove_borrowed_token

Removes symbol from BorrowedTokensList. Called when debt is fully repaid.

get_borrowed_token_debt

Queries the corresponding LendingPool for the current outstanding debt (in WAD) for this account and symbol.

remove_borrowed_token_balance

Repays amount of symbol debt to the LendingPool. Called during repayment or liquidation.

External Protocol Execution

execute

Routes a call to an external protocol (Blend, Aquarius, or Soroswap). Returns: (success: bool, token_delta: i128) where token_delta is the net token change (positive = received, negative = sent). AccountManager uses this delta to mint or burn TrackingTokens.

Action Types


Blend Deposit

  1. Reads current b-token positions from Blend
  2. Authorizes native XLM transfer to Blend pool
  3. Calls BlendPool.submit([{request_type: 0, address: xlm_address, amount: 1000_0000000}])
  4. Reads updated positions
  5. token_delta = positions_after - positions_before (b-tokens received)
  6. AccountManager mints TrackingToken(BLEND_XLM) for the SmartAccount

Blend Withdraw

Inverse of deposit. Submits a withdrawal request to Blend, receives underlying XLM, burns TrackingTokens.

Aquarius Add Liquidity

  1. Fetches pool reserves
  2. Computes optimal amounts (see Math Reference)
  3. Authorizes token transfers to pool
  4. Calls Pool.deposit(desired_a, desired_b, min_a, min_b)
  5. token_delta = LP tokens received
  6. AccountManager mints TrackingToken(AQ_XLM_USDC)

Aquarius Remove Liquidity

Burns LP tokens, receives XLM and USDC back into SmartAccount. AccountManager burns TrackingTokens.

Soroswap Swap

Swaps XLM for USDC (or the pair’s other asset):
  1. Reads pair reserves
  2. Computes output via constant-product formula (0.3% fee)
  3. Authorizes XLM transfer to pair
  4. Calls Pair.swap(amount_out, 0, smart_account)
  5. token_delta = USDC received

Storage Layout


Events


Error Codes


  • AccountManager — the only authorized caller of SmartAccount
  • Tracking Tokens — how external positions are represented
  • Risk Engine — reads SmartAccount state to compute health factor
  • Architecture — full call graph showing how SmartAccount fits in the system