Transactions

trim-subnet

Trim a subnet to at most `max_n` UIDs (subnet owner).

View as Markdown

Lowers the subnet's UID capacity and immediately deregisters the lowest-emission neurons above the new limit — those miners lose their slots and would have to re-register (paying the burn cost) to return. max_n must be between the chain's minimum allowed UIDs (64) and the subnet's current max_allowed_uids. Owner-immune and temporally immune UIDs are skipped, and the call fails if immune UIDs would exceed 80% of max_n. Surviving UIDs are renumbered consecutively from zero, so UID values change. Rate-limited to once per 216,000 blocks (30 days) and blocked during the end-of-epoch admin freeze window. Owner-only and disruptive to affected participants, so announce it before shrinking a live subnet. To simply cap future growth without evicting anyone, set the max_allowed_uids hyperparameter to a value at or above the current UID count instead.

SignerOriginPalletWraps
coldkeysubnet ownerAdminUtilsAdminUtils.sudo_trim_to_max_allowed_uids

Parameters

ParameterTypeRequiredDescription
netuidintegeryesSubnet to trim; the signer must be its owner.
max_nintegeryesNew maximum number of UIDs; lowest-emission neurons above this are removed.

Address parameters (--hotkey, --coldkey, --dest, ...) accept a raw ss58 address, an address-book or proxy-book name, or a local wallet/hotkey name.

CLI

Preview with --dry-run (shows fee, effects, and policy result without submitting), then submit:

btcli tx trim-subnet \
  --netuid <int> \
  --max-n <int> --dry-run
btcli tx trim-subnet \
  --netuid <int> \
  --max-n <int> -w my_coldkey

Python

import bittensor as bt
from bittensor.wallet import Wallet

wallet = Wallet(name="my_coldkey", hotkey="my_hotkey")
intent = bt.TrimSubnet(netuid=1, max_n=0)

sub = bt.Subtensor()
plan = sub.plan(intent, wallet)   # fee, effects, policy — no submission
result = sub.execute(intent, wallet)
if not result.success:
    print(result.error.code, result.error.remediation)

(bt.Subtensor is also the async client — async with bt.Subtensor() as client: — see The client.) Or build the intent by op name, as an agent would:

result = sub.execute_tool("trim_subnet", {...}, wallet)

On-chain implementation

AdminUtils.sudo_trim_to_max_allowed_uidspallets/admin-utils/src/lib.rs#L1927:

#[pallet::call_index(78)]
#[pallet::weight(<T as pallet::Config>::WeightInfo::sudo_trim_to_max_allowed_uids())]
pub fn sudo_trim_to_max_allowed_uids(
    origin: OriginFor<T>,
    netuid: NetUid,
    max_n: u16,
) -> DispatchResult {
    let maybe_owner = pallet_subtensor::Pallet::<T>::ensure_sn_owner_or_root_with_limits(
        origin.clone(),
        netuid,
        &[TransactionType::MaxUidsTrimming],
    )?;
    pallet_subtensor::Pallet::<T>::ensure_admin_window_open(netuid)?;

    pallet_subtensor::Pallet::<T>::trim_to_max_allowed_uids(netuid, max_n)?;

    pallet_subtensor::Pallet::<T>::record_owner_rl(
        maybe_owner,
        netuid,
        &[TransactionType::MaxUidsTrimming],
    );
    Ok(())
}

Every file is browsable under /code exactly as built into the runtime, or as plain text under /code/raw/<path> (index: /code/index.json).