> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vanna.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Oracle System

> How Vanna fetches real-time asset prices to value collateral and compute account health.

## The Core Problem

A Smart Margin Account might hold XLM as collateral and borrow USDC. To know whether that account is healthy - whether the collateral is worth more than the debt - the protocol needs a common unit. That unit is USD.

The oracle's job is simple: **convert any token balance into a USD value the Risk Engine can use.**

Without an oracle, there's no health factor. Without a health factor, there's no lending protocol.

***

## How Vanna Gets Prices

On Stellar, Vanna uses **[Reflector](https://reflector.network)** - a decentralized on-chain oracle protocol built on Soroban.

Vanna's Oracle contract wraps the Reflector client. When a price is needed, it calls:

```
reflector.lastprice(asset) → Option<PriceData>
reflector.decimals()       → u32
```

`lastprice` returns `Some({ price, timestamp })` if the asset is known, or `None` if it isn't. Vanna's oracle checks immediately: **if the result is `None`, the transaction panics**. No default, no fallback, no stale cache.

The `decimals()` call gives the number of decimal places Reflector uses for this price feed. Vanna divides by `10^decimals` and multiplies by `1e18` to normalize everything to WAD format before passing it to the Risk Engine.

***

## How Prices Flow into Health Calculations

Every time the Risk Engine checks an account - for a borrow, a withdrawal, a liquidation check - it needs prices for every asset in the account. Here's what happens:

<Steps>
  <Step title="Enumerate all assets">
    The Risk Engine reads the account's full collateral list and identifies every token held.
  </Step>

  <Step title="Fetch each price once">
    For each unique asset, the oracle is called once. All prices are cached in memory for the duration of the transaction - so no matter how many times the same asset appears in calculations, it's only fetched from Reflector once.
  </Step>

  <Step title="Convert balances to USD">
    Each token balance is multiplied by its USD price. All values are in WAD scale (1e18).
  </Step>

  <Step title="Sum and compare">
    Total collateral USD = sum of all asset values. This is divided by total debt USD to produce the health factor.
  </Step>
</Steps>

The price cache is scoped to one transaction. Every transaction starts fresh - prices cannot carry over from a previous block and silently become stale within Vanna's logic.

***

## Pricing Blend Pool Positions

Smart Margin Accounts can deposit into [Blend](https://blend.capital) lending pools to earn yield while keeping collateral in Vanna. These positions are held as Blend receipt tokens (bXLM, bUSDC) rather than the underlying asset directly.

The Risk Engine handles these specially:

* It detects Blend tracking tokens by their symbol (`BLEND_XLM`, `BLEND_USDC`)
* It reads the account's tracking token balance for that symbol
* It queries Blend's pool for the current `b_rate` (Blend's exchange rate between b\_tokens and the underlying asset)
* It converts: `underlying_amount = b_token_balance × b_rate / 1e12`
* It then prices the resulting underlying amount at the XLM or USDC oracle price

This means Blend yield accrual is automatically reflected in collateral value - as Blend's b\_rate rises, the same b\_token balance converts to more underlying, increasing the account's collateral value without any action from the trader.

***

## What Happens When the Oracle Fails

Vanna is built to **fail closed**. If the oracle cannot return a price, the entire transaction reverts.

| Scenario                          | What happens                            |
| --------------------------------- | --------------------------------------- |
| Price is available                | Transaction proceeds normally           |
| Asset not supported by Reflector  | Transaction reverts - operation blocked |
| Reflector contract is unavailable | Transaction reverts - operation blocked |

There is no degraded mode. A blocked borrow or withdrawal is a recoverable situation. A borrow processed at an unknown price is not.

***

## Price Update Cadence

Vanna does not control when oracle prices update - that is Reflector's responsibility. By default:

* **Resolution**: Prices update every **5 minutes**
* **Retention**: 24 hours of historical price data is available
* **TWAP**: Reflector supports time-weighted average prices, though Vanna reads `lastprice` (spot)

Between Reflector updates, the price the Risk Engine sees is the last confirmed price. If a major market move happens between two 5-minute windows, it will only be reflected after the next Reflector update.

***

## Oracle Risk

The protocol trusts the oracle completely. There are two risks this creates:

**Stale prices** - If Reflector stops updating (network outage, validator issues), prices freeze at their last known value. Accounts that should be liquidated may not be, and accounts that are actually healthy may be blocked from borrowing if their collateral's true value hasn't been captured yet.

**Bad data** - If Reflector publishes an incorrect price - due to a bug, manipulation, or an external data source issue - collateral valuations inside Vanna will be wrong. Liquidations can be triggered incorrectly, or positions that should be liquidated can stay open.

These risks are bounded by Reflector's own security model, which aggregates data from multiple sources and uses decentralized validators. For the full treatment of oracle risk in Vanna's security model, see [Security → Risk Model](/security/risk-model).

***

## Related

* [Health Factor](/learn/health-factor) - how collateral and debt values are compared
* [Liquidation](/learn/liquidation) - what happens when oracle prices push an account below the threshold
* [Smart Accounts](/learn/smart-accounts) - the collateral the oracle values
* [Oracle reference](/developers/contracts/oracle) - contract addresses and function interface
