---
title: "Pool legs"
description: "What a listed asset is on a BTR pool, why every core has a base leg, what an LP holds against one leg, and how to read a leg's live state."
audience: both
type: guide
status: live
lang: en
publish: true
aliases: [4-3-assets-and-the-hub]
---
# Pool legs

A token is a **leg** of a pool when it has an `assets[token]` slot. Every core designates one of its
legs as the [base asset](/docs/glossary#base-token-num-raire): its unit of account, and the root its
[anchor tree](/docs/glossary#anchor-tree) resolves to. Which assets sit on which core, and which one
is the base, is per instance: see [Pool Composition](/docs/2-3-pool-composition). Routing across
pools is in [Swapping](/docs/4-1-swapping); per-asset addresses, feeds and ERC-20 quirks are in the
[Asset Registry](/docs/2-2-asset-registry).

---

## 1. What a listing is

On chain, a listing is one `assets[token]` slot written by `PoolConfig.initAsset`:

- Decimals are read from the token, never passed in. `initAsset` calls the ERC-20 and stores what it returns. A token reporting 0 or more than 18 decimals cannot be listed.
- `decimals != 0` is the is-configured sentinel. Every reader gates on it, which is why 0 is unlistable: it collides with "not configured".

Listing is admin-only, and one-way-latched. Before `sealBootstrap(pool)` the deployer lists through `Admin.addAsset`. After it, `addAsset` reverts permanently and the only path is the timelocked ADD_ASSET queue: `Admin.requestOp(..., ADD_ASSET, ...)` then `Admin.executeAddAsset(pool, token)`. See [Admin](/docs/1-2-3-admin) for the queue and [Access Control](/docs/3-1-overview) for who may drive it.

Every listed asset, the base included, must carry `kappaCovBps > 0` ([Invariants §I-9](/docs/1-1-8-invariants#i-9-coverage-toll-is-charge-only-and-terminal-only)).

## 2. Why every core has a base leg

Each pool stores one `baseToken`, fixed at `initialize`. A new listing *defaults* its
[anchor](/docs/glossary#anchor-token) to the base (`initAsset` sets
`anchor = (token == baseToken) ? 0 : baseToken`) and `adminSetAnchor` can afterwards re-parent it to
any correlated listed asset, up to `MAX_DEPTH = 4` edges from the root. A core whose whole roster
still carries that default is a depth-1 hub-and-[spoke](/docs/glossary#spoke) star, and any cross
there is at most spoke → base → spoke in a single `Pool.swap`. Deeper trees are configuration, not a
different mechanism: a swap between two assets sharing a parent prices through that parent without
touching the base at all ([Anchor Path Pricing](/docs/1-1-3-anchor-path-pricing)).

The base is the numeraire, so it carries constraints no spoke does:

| Requirement on the base | Why |
|---|---|
| EXTERNAL-quoted | its own depeg halt must be able to bite ([Flow Guards](/docs/3-2-1-flow-guards)) |
| `QUOTE_UNIT_ANCHOR` | it is the unit other legs are attested in |
| spokes carry an independent ref band | a spoke's mark is checked against a second attestation, not against the base alone |

Changing the base is not a pointer swap. `PoolConfig.setBaseToken(newBase, spokes)`, reachable only through `Admin.executeBaseMigration`, reverts unless every one of these holds:

- the incoming base is already listed;
- it is EXTERNAL-quoted;
- it is `QUOTE_UNIT_UOA`;
- it is trading within `BASE_DEPEG_HALT_BPS` of parity;
- the demoted base gains a ref band in the same call.

Off chain the same leg is the router's [hub](/docs/glossary#hub): a pair with no shared pool is
fillable only as one hop through the hub symbol
([Swapping §2](/docs/4-1-swapping#2-route-enumeration)). `pool.baseToken()` is the authority for
which asset that is; no deployment artifact records it.

A cross-core route takes the hub **out** of the source pool and **into** the destination, so the hub
has to be replenishable. On a testnet deployment that rules out an official issuer token nobody can
mint, and the base is the mintable twin instead ([Faucets §2](/docs/4-5-faucets#2-issuer-tokens-versus-mintable-twins)).

## 3. What an LP holds against a leg

One ERC-20 receipt per leg, single-sided, with the leg's own [liquidity index](/docs/glossary#liquidity-index): mint, cooldown and exit are in [Providing Liquidity](/docs/4-3-providing-liquidity). Moving a claim from one leg to another without withdrawing is [Liability Swaps](/docs/4-2-liability-swaps). A leg's [coverage ratio](/docs/glossary#coverage-ratio) prices both sides of a swap and caps a same-asset exit; it is derived in [Inventory Management §5](/docs/1-1-1-inventory-management#5-lp-settlement-at-the-pool-rate).

## 4. Reading a leg's state

Everything a user sees as "this leg is not trading right now" is one of four on-chain reads, each documented where the mechanism lives:

| What you see | Read | Where it is specified |
|---|---|---|
| leg disabled for an action | the leg's flag bits (swap, deposit, withdraw, liability swap) | [Basic Operations §2](/docs/5-1-1-basic-operations#2-check-the-flags-first) |
| leg or pool halted | the halt bits an admin or guardian sets | [Access Control](/docs/3-1-overview), [Guardian](/docs/3-1-4-guardian) |
| quotes rejected as stale or off-band | feed age, deviation, ref band, depeg band | [Oracle Keeper](/docs/3-1-5-oracle-keeper), [Flow Guards](/docs/3-2-1-flow-guards) |
| a size that quoted refuses to fill | per-block and per-window flow caps | [Flow Guards](/docs/3-2-1-flow-guards) |

## 5. Decimals, and gas

The pool rescales per hop with a pure power-of-ten shift between the two legs' stored decimals
(`Pricing.sol`), so decimals never touch pricing and show up only in raw amounts. Read `decimals()`
on the deployed token before scaling one: the decimals column of the
[Asset Registry](/docs/2-2-asset-registry) describes an asset's mainnet reference, which is not
always the token in your wallet on a testnet instance.

Where a chain pays gas in a token that is also a listed leg, a "max" that spends the whole balance
cannot afford its own transaction fee, so the app reserves a gas buffer on that input. Which chains
those are, and what the gas token's ERC-20 view looks like:
[Deployments §1](/docs/2-overview#1-testnet-policy).

---

## 6. Related documentation

- [Swapping](/docs/4-1-swapping): how a swap is routed, within a pool and across pools
- [Faucets](/docs/4-5-faucets): mintable twins and how testnet balances are obtained
- [Asset Registry](/docs/2-2-asset-registry): per-asset addresses, feeds, ERC-20 oddities
- [Pool Composition](/docs/2-3-pool-composition): which assets sit on which core
- [Anchor Path Pricing](/docs/1-1-3-anchor-path-pricing): the anchor column and leg pricing
- [Admin](/docs/1-2-3-admin): the timelocked listing and base-migration queues
- [Spread & Fees](/docs/1-1-4-spread-fees): what a listed asset's fee floor and coverage wall cost
