# Basket trading (/docs/guides/basket-trading)

**Basket trading** (runtime v461) lets a root validator actively manage the
basket its root dividends built. It is the only lever: dividends accumulate
in place on the subnet they were earned on, direct deposits mirror the
current holdings, and neither changes the fund's composition. The
[`swap-basket`](/docs/tx/swap-basket) call sells part of one holding for TAO
and buys another holding with it, in one transaction — that is how a fund's
composition moves.

This guide is for the operator of a root validator. It assumes you know the
fund model from [Root Reborn](/docs/guides/root-reborn): one escrowed fund
per validator, stakers hold **beta** (a share of the fund), and the fund's
value is its **NAV** — what selling every holding would fetch right now.
For what changed on chain in v461, see the
[release notes](/releases/v461-upgrade). Two companion pages cover the other
seats at the table: [Basket trading for governance](/docs/guides/basket-trading-governance)
(enable, freeze, tune) and [Basket trading for stakers](/docs/guides/basket-trading-for-stakers)
(what changes for the people whose beta you manage: nothing to do, and how
to watch).

<Callout type="note">
  Trading launches **gated off** network-wide. Until governance enables it,
  every `swap_basket` fails with `BasketTradingDisabled`. Everything else in
  this guide (the proxy type, the reads, btcli) works from the upgrade block.
</Callout>

## What a beta basket is [#what-a-beta-basket-is]

Every root validator runs one fund. Its root dividends arrive as subnet
alpha and are held in a chain-owned **escrow** account, as ordinary stake
on the validator's hotkey. Stakers on that validator accrue **beta**: a
share of the whole fund, never of any particular position. A claim pays a
staker their fraction of NAV as TAO.

Three facts make trading safe to add on top:

* **A trade changes what the fund holds, not who owns it.** Shares, each
  staker's entitlement, and the fund's dividend accrual do not move.
* **NAV is realizable.** The fund is valued at the TAO its holdings would
  actually fetch at current pool depth, so a trade cannot inflate the
  fund's book value by pumping a thin pool.
* **The escrow cannot act on its own.** Only the validator's coldkey, or a
  proxy it has granted, can trade.

## What `swap_basket` does [#what-swap_basket-does]

```text
swap_basket(hotkey, origin_netuid, destination_netuid, amount, min_amount_out)
```

| Argument             | Meaning                                                                                                                                                                                                                                                         |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `hotkey`             | The root-registered validator whose fund to rebalance.                                                                                                                                                                                                          |
| `origin_netuid`      | The subnet to **sell out of**. `0` is the fund's TAO cash slot.                                                                                                                                                                                                 |
| `destination_netuid` | The subnet to **buy into**. `0` is the fund's TAO cash slot.                                                                                                                                                                                                    |
| `amount`             | How much of the origin holding to sell, in the origin subnet's alpha (TAO when the origin is `0`). `all` sells the whole holding.                                                                                                                               |
| `min_amount_out`     | Your floor on the fill: the least the buy leg must credit to the destination holding, after fees, in the destination subnet's alpha (TAO when the destination is `0`). `0` sets no floor. Below it the trade fails with `BasketMinOutNotMet` and nothing moves. |

The trade has two legs. The **sell leg** turns `amount` of origin alpha into
TAO on that subnet's pool. The **buy leg** spends that TAO on the
destination pool. Both legs run inside one transaction: if anything fails —
a guardrail, a price limit, a rollback in the pool — nothing moves.

The TAO that passes between the legs is called `tao_mid`. It is what the
turnover budget (below) counts, and it is reported in the `BasketSwapped`
event together with `alpha_sold` and `alpha_bought`.

### The TAO cash slot (netuid 0) [#the-tao-cash-slot-netuid-0]

Netuid 0 is the root network. A fund's holding there is plain TAO, held as
root stake, worth exactly its face value. Use it on either side of a trade:

* `--from 3 --to 0` sells netuid 3 and parks the TAO as cash.
* `--from 0 --to 64` spends cash on netuid 64.

The cash slot has no pool, so a leg on netuid 0 has no price band, no fee,
and no slippage. The cash slot **is** a capped destination: it counts
against the 1/16 concentration cap like any other holding, so a fund cannot
move more than 1/16 of NAV into cash in one trade.

## Setting up the trader key [#setting-up-the-trader-key]

The intended setup is that the validator's coldkey stays offline and a
separate **trader key** (usually a multisig) does the trading through a
proxy. Runtime v461 adds a proxy type for exactly this:

* **`BasketTrading`** (proxy type index 18) admits one call:
  `swap_basket`. A `BasketTrading` delegate cannot stake, unstake,
  transfer, claim, or change keys.
* No existing proxy gains trading rights at the upgrade. `NonTransfer`,
  `NonCritical`, `Staking`, and `NonFungible` delegates are all refused
  `swap_basket`. Only `Any` and `BasketTrading` admit it.

Grant it once from the coldkey ([Proxy accounts](/docs/guides/proxies)
covers delays and the proxy book):

```bash
# validator coldkey: delegate trading to the desk key or multisig
btcli proxy add --delegate <desk address> --proxy-type BasketTrading -w validator_cold

# check the grant
btcli proxy list --coldkey <validator coldkey>
```

From then on the desk signs with its own wallet and names the validator's
coldkey with `--proxy-for` (SDK: `proxy_for=`). Revoke with
`btcli proxy remove --delegate <desk address> --proxy-type BasketTrading`.

### The MEV shield [#the-mev-shield]

A pending trade tells everyone in the block which pool it is about to buy.
The **MEV shield** encrypts the call so that block builders and other
traders cannot front-run it. Trading commands shield by default
(`SwapBasket` sets `mev_shield_default = True`), so you do not need to pass
anything. Use `--no-mev-shield` only if you must submit in the clear, for
example against a node without shield support. The shield wraps the
already-proxied call; the two compose.

## Worked example [#worked-example]

The desk wants to sell 250 α of netuid 8 out of validator `5F...val`'s fund
and buy netuid 64 with the proceeds.

### 1. Look at the fund and the budget [#1-look-at-the-fund-and-the-budget]

```bash
btcli root list 5F...val                                 # holdings, NAV, lifetime return
btcli query validator-basket --hotkey 5F...val           # (netuid, alpha, TAO value) rows
btcli query basket-trading-status --hotkey 5F...val      # gates and the turnover bucket
```

A status read looks like this:

```text
enabled               True
frozen                False
budget_tao            τ1,250.000
remaining_tao         τ980.000
used_tao              τ270.000
refill_per_block_tao  τ0.1736
refill_blocks         7200
```

`remaining_tao` is the most TAO this fund can push through the middle of a
trade *right now*. The trade below moves roughly 250 α × price of netuid 8,
so check that it fits. See [How to read the budget](#how-to-read-the-budget)
for what the other fields mean.

### 2. Swap with btcli [#2-swap-with-btcli]

```bash
btcli root swap --from 8 --to 64 --amount 250 --hotkey 5F...val \
  --max-slippage 1 -w desk --proxy-for 5F...validator_coldkey
```

btcli quotes the fund and the trade first, then shows a review card before
you sign: the origin holding being sold, the destination holding, the
**expected out** (what the buy leg would credit at current pool prices,
after fees), the **minimum out** it will insist on, and how much of the
bucket is left (with a red warning if trading is disabled or the fund is
frozen). Confirm, and the call is proxied, shielded, and submitted. Pass
`--dry-run` to see the card and the fee without submitting.

`--max-slippage` is a percentage (default `1.0`). btcli sets
`min_amount_out = expected out × (1 − max_slippage / 100)`. If the quote
fails (an unreachable read, an older node), the card shows a yellow
warning row and `min_amount_out` is `0`: the trade then has only the
chain's own band. See [Your floor and the protocol band](#your-floor-and-the-protocol-band).

Other shapes of the same command:

```bash
btcli root swap --from 3 --to 0 --amount all --hotkey 5F...val ...   # exit netuid 3 to cash
btcli root swap --from 0 --to 21 --amount 500 --hotkey 5F...val ...  # spend 500 τ of cash on netuid 21
btcli root swap --from 8 --to 64 --amount 250 --max-slippage 0.5 ...  # tighter floor: fill within 0.5% of the quote
```

### 3. Swap with the Python SDK [#3-swap-with-the-python-sdk]

```python
import bittensor as bt
from bittensor.wallet import Wallet

HOTKEY = "5F...val"
VALIDATOR_COLDKEY = "5F...validator_coldkey"
desk = Wallet(name="desk")

async with bt.Subtensor("finney") as client:
    status = await client.read("basket_trading_status", hotkey_ss58=HOTKEY)
    if not status["enabled"] or status["frozen"]:
        raise SystemExit("trading is off for this fund")

    # Quote the trade yourself: sell leg on netuid 8, buy leg on netuid 64.
    tao_mid = (await client.read("quote_unstake", netuid=8, amount_alpha=250)).tao
    expected = (await client.read("quote_stake", netuid=64, amount_tao=tao_mid.tao)).alpha
    floor = bt.Balance.from_rao(expected.rao * 99 // 100, 64)   # 1% under the quote

    intent = bt.SwapBasket(
        hotkey_ss58=HOTKEY,
        origin_netuid=8,
        dest_netuid=64,
        amount=250,          # α of netuid 8; "all" sells the whole holding
        min_amount_out=floor,   # α of netuid 64; 0 (the default) sets no floor
    )
    result = await client.execute(intent, desk, proxy_for=VALIDATOR_COLDKEY)
    if not result.success:
        print(result.error.code, result.error.remediation)
```

`SwapBasket` is an ordinary intent: `client.plan(intent, desk)` previews the fee
and the guardrail preflight, and `client.execute` submits. The intent
shields by default. `min_amount_out` is denominated like the destination:
alpha of `dest_netuid`, or TAO when `dest_netuid` is `0`. On success the
chain emits `BasketSwapped` with the exact amounts on both legs.

## Your floor and the protocol band [#your-floor-and-the-protocol-band]

Two separate rules bound the price a trade can fill at. They protect
against different things, and you control only one of them.

|                        | Protocol band (`SlippageTooHigh`)                                                               | Your floor (`BasketMinOutNotMet`)                                                                               |
| ---------------------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| Who sets it            | The runtime: a 2% constant, per leg.                                                            | You: `min_amount_out`, per trade.                                                                               |
| What it measures       | Each leg's fill **price** against the subnet's moving and spot price.                           | The **amount** the buy leg credits, after fees, against your number.                                            |
| What it protects       | The fund from a stolen key or a pumped pool: a leg can never fill far from the reference price. | You from a fill that is worse than the quote you signed on, because the pool moved between quote and execution. |
| Can it be switched off | No.                                                                                             | Yes: `min_amount_out = 0` (btcli: `--max-slippage 100`).                                                        |

The band is a price rule on each leg. It does not know what you were
quoted. A trade whose two legs each move 1.5% passes the band while
delivering about 3% less than the quote; a trade that happens to land in
the same block as a large opposite trade can pass the band and still fill
below your quote. Your floor catches those cases. The band is still
checked first, inside each leg: a leg that misses it fails with
`SlippageTooHigh` whatever floor you set.

Pick `--max-slippage` from the quote, not from the band. Both legs pay the
AMM fee and their own price impact, and the quote already includes those,
so 1% (the default) is room for the pool to move against you, not for the
trade's own cost. A floor tighter than the movement you expect between
signing and inclusion (a block or two) fails often; a floor looser than 2%
per leg adds nothing the band does not already give.

## The guardrails [#the-guardrails]

A trading key is a new way for a fund to lose value, so every trade must
pass every check below. The numbers are the launch defaults;
[governance](#governance-knobs) can move the caps and the budget. Each
check names the exact error you see when it refuses the trade.

### 2% price band per leg → `SlippageTooHigh` [#2-price-band-per-leg--slippagetoohigh]

Each leg must fill **completely** within 2% of the strictest of three
reference prices:

* the subnet's **slow moving price** (`SubnetMovingPrice`, the emission
  EMA — an exponential moving average with a half-life of about a month on
  mainnet, capped at 1 τ per α);
* its **fast moving price** (`SubnetFastMovingPrice`, an EMA of spot with a
  600-block half-life, about two hours, written once per block from the
  previous block's closing price and not capped);
* its **spot price**.

A buy may not fill above `1.02 × min(slow, fast, spot)`. A sell may not fill
below `0.98 × max(slow, fast, spot)`.

Each anchor closes a different hole. Spot caps the trade's own price impact.
The fast anchor is a price nobody can move inside a block: if someone lifts
spot and then has the fund buy — or dumps spot and has the fund sell — the
fund is still bound to within 2% of where the pool traded before the move,
so it never fills at the manipulated price. Pulling the fast anchor along
means holding the pump, and the capital behind it, against arbitrage for
several half-lives. The slow anchor is the level cap: even a pump held for
hours cannot carry the fund past 2% of the monthly average. If either leg
would cross its bound, the trade fails with `SlippageTooHigh` and nothing
moves. Practical consequences:

* **Size legs to the pool.** On a constant-product pool a buy of about 1% of
  the TAO reserve moves the price about 2%. Split larger positions into
  slices and let the pool settle between them.
* **You cannot trade a move that just happened.** Legs are bound to within
  2% of the last couple of hours' average price. After a real 5% move, the
  fast anchor is back within the band about four hours later; the slow
  anchor still applies on top, so a holding whose spot has fallen more than
  2% below its monthly average cannot be sold until that average catches
  up (weeks after a large drop), and the same holds for buying after a
  spike. Stop-losses are not possible by design.
* A subnet with no moving price yet (before `start_call`, or a subnet that
  does not emit) cannot be traded. The slow price is capped at 1 τ per α,
  so a subnet trading above that cannot be bought within the band.

### Turnover budget: a token bucket of 10% of NAV per day → `BasketTurnoverBudgetExceeded` [#turnover-budget-a-token-bucket-of-10-of-nav-per-day--basketturnoverbudgetexceeded]

Each fund has a **bucket** whose capacity is `BasketDailyTurnoverCap` of
its current **guarded NAV** — default 10%. The guarded NAV marks every
holding at the lower of its realizable value and its alpha times the slow
moving price (the concentration cap section below explains why). Every trade takes `tao_mid` out of the bucket. The bucket refills continuously at `capacity / 7200` per block, so
an empty bucket is full again after one day (7200 blocks at 12 seconds).

Two properties follow:

* **At most one budget at any instant.** The level is clamped to one
  capacity, so a fund can never move more than 10% of NAV through the
  middle in a burst, no matter how long it waited.
* **About one budget per day sustained.** A fund trading continuously can
  turn over 10% of NAV per day; a full rotation of the fund takes about ten
  days.

A trade whose `tao_mid` is larger than the bucket's current level fails with
`BasketTurnoverBudgetExceeded`. A fund that has never traded starts with a
full bucket. The bucket follows the fund through a hotkey swap.

### 1/16 concentration cap → `BasketConcentrationCapExceeded` [#116-concentration-cap--basketconcentrationcapexceeded]

After the trade, the destination holding's realizable value may not exceed
`BasketConcentrationCap` of the fund's **guarded NAV** — default 1/16, so a
traded fund spreads across at least 16 holdings. Topping up a holding that
is already at the cap is refused, and so is moving more than 1/16 of NAV
into the cash slot. Only buys are checked: a holding that grows past the cap
through price moves or in-place dividends is left alone. On a chain with
fewer than 16 subnets the check is skipped. Refusal is
`BasketConcentrationCapExceeded`.

The guarded NAV exists because a holding's realizable value is bounded only
by its pool's TAO reserve, and anyone can grow that reserve for one block by
buying into the pool. A same-block pump of a thin pool the fund holds could
otherwise mark that holding at roughly the pump size, inflating the NAV
both this cap and the turnover budget are measured against, and turning a
refused oversize buy into an admitted one. The guarded NAV marks each
holding at `min(realizable value, alpha × slow moving price)`; the slow
price cannot be moved inside a block, so neither guard can be pumped. The
cap on the mark is one-sided on purpose: a pool trading above its monthly
average (or above 1 τ per α, where the slow price is capped) is under-marked,
which only tightens the guards. `basket_trading_status` reports the budget
from the same guarded NAV a trade uses.

### 10% per-pool liquidity cap → `BasketLiquidityCapExceeded` [#10-per-pool-liquidity-cap--basketliquiditycapexceeded]

After the buy leg, the fund may not hold more than `BasketLiquidityCap` of
the destination subnet's **alpha reserve** — default 10% of the alpha in
the pool. This is a different question from the concentration cap: not
"how big is this position in my fund?" but "how big is my fund in this
pool?".

It exists because realizable value is bounded by a pool's TAO reserve. A
fund could otherwise keep buying a thin subnet in band-sized slices while
a counterparty sells alpha back to it between slices; every slice passes
the band, the budget, and the concentration cap, yet the fund's NAV falls
by roughly the TAO it spends. With the liquidity cap the value at risk on a
pool with TAO reserve `R` is about `R × L² / (1 + L)` — about 0.9% of `R`
at the 10% default. The cash slot has no pool and is exempt. Refusal is
`BasketLiquidityCapExceeded`.

### Enable and freeze switches → `BasketTradingDisabled` / `BasketTradingFrozen` [#enable-and-freeze-switches--baskettradingdisabled--baskettradingfrozen]

* `BasketTradingEnabled` is the network-wide gate, **off** at launch. While
  it is off every trade fails with `BasketTradingDisabled`.
* `BasketTradingFrozen[hotkey]` lets governance freeze one fund's trading,
  for example after a suspected key compromise. A frozen fund still accepts
  deposits, pays claims, and accrues dividends; only `swap_basket` fails,
  with `BasketTradingFrozen`. The freeze follows the fund through a hotkey
  swap.

### Other refusals [#other-refusals]

| Error                                 | Cause                                                                                          |
| ------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `BasketSameSubnet`                    | Origin and destination are the same netuid.                                                    |
| `NonAssociatedColdKey`                | The signer (or the `--proxy-for` account) does not own the hotkey.                             |
| `HotKeyNotRegisteredInSubNet`         | The hotkey is not registered on root.                                                          |
| `NotEnoughStakeToWithdraw`            | The fund holds less than `amount` on the origin.                                               |
| `BasketMinOutNotMet`                  | The buy leg credited less than your `min_amount_out`. Re-quote and retry, or loosen the floor. |
| `AmountTooLow`                        | `amount` is zero, or the sell leg yields less than the minimum stake.                          |
| `SubnetNotExists`, `SubtokenDisabled` | A side does not exist, or the destination's token is not enabled.                              |
| `BetaBasketSeedInProgress`            | The basket seed migration is still running.                                                    |
| `ColdkeySwapAnnounced`                | A coldkey swap is announced for the signer.                                                    |

## How to read the budget [#how-to-read-the-budget]

[`basket-trading-status`](/docs/query/basket-trading-status) returns the
gates and the bucket for one validator:

| Field                  | Meaning                                                                                                                                                 |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`              | The network-wide gate.                                                                                                                                  |
| `frozen`               | Whether governance froze this fund.                                                                                                                     |
| `budget_tao`           | The bucket's capacity: 10% of the fund's guarded NAV (holdings marked at the lower of realizable value and slow-moving-price value). It moves with NAV. |
| `remaining_tao`        | What is in the bucket now — the largest `tao_mid` a trade at this block could push through.                                                             |
| `used_tao`             | `budget_tao − remaining_tao`.                                                                                                                           |
| `refill_per_block_tao` | How much the bucket gains every block: `budget_tao / refill_blocks`.                                                                                    |
| `refill_blocks`        | Blocks for an empty bucket to fill completely (7200).                                                                                                   |

To size a trade: estimate `tao_mid` as the origin amount times the origin
subnet's price (or the TAO amount itself when selling cash), and keep it
under `remaining_tao`. To plan a series: after a trade of `X` TAO, the
bucket is back to full after `X / refill_per_block_tao` blocks. NAV changes
move `budget_tao`, and the level is clamped to the new capacity, so a
falling NAV can lower `remaining_tao` without any trade.

## What is not restricted [#what-is-not-restricted]

* **Selling is never capped.** The concentration and liquidity caps apply to
  the destination only. You can always sell out of a position that has
  grown past either cap, and a sell into the cash slot is bounded only by
  the band, the bucket, and the 1/16 cash rule.
* **Winners run.** A holding that appreciates past 1/16 of NAV or past 10%
  of its pool is not clipped. The caps stop you from *buying* more of it,
  not from holding it.
* **Dividends keep flowing.** Root dividends accumulate in place exactly as
  before, whether trading is enabled, disabled, or frozen. Deposits and
  claims are not touched by any trading gate.
* **Stakers are unaffected by the mechanics.** A trade does not change
  shares, entitlements, or the claim path. What changes is the fund's
  composition — and, over time, its NAV.

## Governance knobs [#governance-knobs]

All five setters are root-only calls on `AdminUtils`:

| Call                                             | Effect                                                                                                  | Default       |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------- | ------------- |
| `sudo_set_basket_trading_enabled(enabled)`       | Network-wide on/off switch.                                                                             | off           |
| `sudo_set_basket_trading_frozen(hotkey, frozen)` | Freeze or unfreeze one fund.                                                                            | not frozen    |
| `sudo_set_basket_daily_turnover_cap(cap)`        | Bucket capacity as a u16 share of NAV (`65535` = 100%). Zero is rejected.                               | `6553` (10%)  |
| `sudo_set_basket_liquidity_cap(cap)`             | Largest share of a pool's alpha reserve a fund may hold after a buy (`65535` = 100%). Zero is rejected. | `6553` (10%)  |
| `sudo_set_basket_concentration_cap(cap)`         | Largest share of fund NAV one holding may reach through a buy (`65535` = 100%). Zero is rejected.       | `4096` (1/16) |

The 2% band and the 7200-block refill period are runtime constants, not
hyperparameters.

Raise the liquidity cap if funds legitimately need larger positions in
mid-depth pools; lower it to tighten the per-pool value at risk. Raise the
turnover cap only once the liquidity cap is in place.

**What a stolen trader key can extract.** The band is what bounds this, so
the number depends on which price the band is anchored to.

* *Attacks inside a block, or shorter than a few fast half-lives.* The fund
  can only fill within 2% of a price the attacker did not move. Replaying
  the audit's lift-buy-dump and dump-sell-buyback sequences at slow-EMA/spot
  divergences of 1.35×, 2× and 4× against the fixed band, the attacker's
  cash profit is at most rounding (≤ 0.01% of NAV) on either leg and the
  fund fills at most one in-band leg. Before the fast anchor the same
  sequences took 1.1% / 4.1% / 6.9% of NAV per day on the buy leg and 1.1% /
  3.1% / 4.7% on the sell leg, because the band re-anchored to the
  manipulated spot on every leg while the stale slow price stayed the only
  smoothed reference.
* *A pump held for most of a day.* An attacker who buys 30–100% of a pool's
  TAO reserve and holds that price against arbitrage for roughly five fast
  half-lives (about ten hours) drags the fast anchor to the held level; the
  slow anchor still caps how far. Only then does the older analysis apply:
  with the default 10% budget and 10% liquidity cap the most a stolen key
  and a willing counterparty can extract is about 13% of the TAO traded —
  9% through a thin pool and 4% at the edges of the band, plus fees — which
  is about 1.3% of NAV per full bucket, about that much per day until
  governance freezes the fund, and now at the capital-time cost of the held
  pump rather than for free. That bound assumes pools near the 0.5
  balancer-weight equilibrium; if a pool's balancer weights skew far from
  equilibrium, the price-impact estimate behind the 9% figure becomes less
  accurate, while the 2% band and the turnover bucket still hold exactly.

The guarded NAV keeps the budget and the cap honest through all of this: a
same-block pump of a held pool no longer enlarges the bucket or admits an
oversize buy.

## Reference [#reference]

* Transaction: [`swap-basket`](/docs/tx/swap-basket)
* Read: [`basket-trading-status`](/docs/query/basket-trading-status),
  [`validator-basket`](/docs/query/validator-basket)
* Errors: [`BasketTradingDisabled`](/docs/errors/chain/BasketTradingDisabled),
  [`BasketTradingFrozen`](/docs/errors/chain/BasketTradingFrozen),
  [`BasketTurnoverBudgetExceeded`](/docs/errors/chain/BasketTurnoverBudgetExceeded),
  [`BasketLiquidityCapExceeded`](/docs/errors/chain/BasketLiquidityCapExceeded),
  [`BasketMinOutNotMet`](/docs/errors/chain/BasketMinOutNotMet),
  [`BasketSameSubnet`](/docs/errors/chain/BasketSameSubnet)
* Guides: [Basket trading for governance](/docs/guides/basket-trading-governance),
  [Basket trading for stakers](/docs/guides/basket-trading-for-stakers),
  [Root Reborn](/docs/guides/root-reborn),
  [Proxy accounts](/docs/guides/proxies), [Multisig](/docs/guides/multisig)
* Release: [v461 — Basket Trading](/releases/v461-upgrade)
