> ## 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.

# Registry

> The on-chain address book that maps identifiers to contract addresses, owners to accounts, and underlying assets to vTokens. The one address every integrator hardcodes.

The Registry is the single dependency injection point of Vanna's architecture. Every other contract is discovered through it. Instead of hardcoding seven contract addresses for every integration, an integrator hardcodes one - the Registry address - and resolves everything else at runtime.

This is the same pattern used by Aave's "Address Provider" and the Ethereum Name Service: a small, stable contract that brokers references to a constellation of larger, upgradable contracts behind it.

## What the Registry Stores

The Registry holds three logical mappings:

| Mapping                 | Purpose                                                                             | Example                               |
| ----------------------- | ----------------------------------------------------------------------------------- | ------------------------------------- |
| **Named addresses**     | Maps human-readable identifiers to contract addresses                               | `"RiskEngine"` → `0x5BeffE679B...`    |
| **Underlying → vToken** | Maps each asset's underlying token to its corresponding [vToken](/learn/vtokens)    | `USDC` → `vUSDC`                      |
| **Owner → accounts**    | Maps each user address to the list of their [Smart Accounts](/learn/smart-accounts) | `0xUser` → `[0xAccount1, 0xAccount2]` |

A fourth mapping exists on EVM for the Controller allowlist:

| Mapping                          | Purpose                                                                      | Example                                                  |
| -------------------------------- | ---------------------------------------------------------------------------- | -------------------------------------------------------- |
| **(target, selector) → allowed** | Whether a specific external contract function is allowlisted for `execute()` | `(Uniswap V2 Router, swapExactTokensForTokens)` → `true` |

## How Integrators Use It

In practice, an integration starts with:

```
registry_address = 0x...  // the single hardcoded constant

account_manager = registry.address_for("AccountManager")
risk_engine    = registry.address_for("RiskEngine")
v_usdc         = registry.v_token_for(USDC_underlying_address)
```

Everything else flows from there. The Account Manager points to its dependencies through the Registry; the Risk Engine reads collateral lists from Smart Accounts whose addresses are resolved through the Registry; the Lending Pools find their Rate Model and Oracle through the Registry.

## Why This Pattern

Consider the alternative - hardcoding every address in every integration:

```
const ACCOUNT_MANAGER = 0xabcd...
const RISK_ENGINE     = 0xef01...
const ORACLE          = 0x2345...
const REGISTRY        = 0x6789...
const VUSDC           = 0xabcd...
const VWETH           = 0xef02...
const VUSDT           = 0x3456...
const VDAI            = 0x7890...
```

Three problems:

1. **Upgrades break the integration.** If Vanna redeploys the Risk Engine to fix a bug, every hardcoded integration becomes wrong.
2. **New assets require integrations to change.** When a new vToken is added, every dashboard that wants to show it has to be updated.
3. **Multi-chain becomes painful.** Each chain has different addresses. An integration that supports Base, Arbitrum, and Optimism would need three constants per contract.

The Registry collapses all of this. There's one address per chain (the Registry itself), and integrators read everything else dynamically. When a contract is upgraded, the Registry entry is updated and every integration picks up the new address on the next read.

<Snippet file="address-registry-note.mdx" />

## Account Discovery

A wallet integrating Vanna wants to show all of a user's open Smart Accounts. The Registry exposes this directly:

```
accounts = registry.accounts_owned_by(user_address)
```

Each entry in the returned list is a Smart Account contract address. The wallet can then call each account's view functions to display collateral, debt, and health factor.

There is no central indexer required. The Registry is the indexer.

## What the Registry Doesn't Do

* **It doesn't hold value.** No tokens, no balances. It's a pure metadata contract.
* **It doesn't execute operations.** It's read-only from an integrator's perspective; only privileged roles (governance, deployment scripts) write to it.
* **It doesn't make access-control decisions.** The Controller allowlist on EVM happens to live in the Registry, but the *decision to allow* is governance's; the Registry merely stores the result.

## Privileged Operations

The Registry has admin-gated functions for registering new contracts, updating addresses, and managing the allowlist. These are governance operations and are not part of the integrator surface. The complete list and access control model is in the [Security overview](/security/overview).

## Chain Support

<Snippet file="chain-support-table.mdx" />

The Registry pattern is identical on every chain - the same lookup functions exist on Soroban and EVM. Only the addresses differ.

The canonical Registry addresses for each chain are published in the [Address Registry resource page](/resources/address-registry).

## Related

* [Address Registry resource](/resources/address-registry) - the canonical list of deployed addresses per chain
* [Registry reference](/developers/contracts/registry) - the function-level interface
* [Protocol Architecture](/learn/protocol-architecture) - how the Registry sits in the dependency graph
* [Smart Accounts](/learn/smart-accounts) - the per-user contracts the Registry tracks
