Transactions

claim-root

Redeem accrued root dividends across every validator for the coldkey.

View as Markdown

Root dividends accrue as shares of each validator's basket — an escrowed index fund of subnet alpha built from the validator's root dividends, each held on the subnet it was earned on (the validator reshapes it only with swap_basket). This call redeems the signing coldkey's owed shares on every validator it root-stakes to. The subnets argument is retained for call-data compatibility with pre-basket clients and is ignored — baskets have no per-subnet claim selection.

Prefer :class:ClaimRootWithHotkey to claim a single validator.

Since spec 468 each fund's dust rows are left unsold (a row worth less than min(1 TAO, 0.1% of the fund's anchored NAV), or one where this claimant's slice is worth less than 0.0001 TAO, when that slice is at most the 0.01 TAO forfeit cap); the whole entitlement is settled, so those slices stay in the fund for the remaining holders. A claim that is admitted and then fails pays for the work it did, not the declared envelope.

plan (and btcli root claim --dry-run) estimates the reserved inclusion fee versus the fee that will actually settle, compares that spent fee to accrued yield, warns when the claim loses money, and refuses when free TAO cannot cover the reserve.

SignerOriginPalletWraps
coldkeysigned account (pallet role may apply)SubtensorModuleSubtensorModule.claim_root

Parameters

ParameterTypeRequiredDescription
subnetsarray of integernoIgnored (kept for old-client call-data compatibility). Pass any non-empty netuid list; baskets claim fund-level.

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 claim-root --dry-run
btcli tx claim-root -w my_coldkey

Python

import bittensor as bt
from bittensor.wallet import Wallet

wallet = Wallet(name="my_coldkey", hotkey="my_hotkey")
intent = bt.ClaimRoot()

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("claim_root", {...}, wallet)

On-chain implementation

SubtensorModule.claim_root — pallets/subtensor/src/macros/dispatches.rs#L2084:

#[pallet::call_index(121)]
#[pallet::weight(
    Pallet::<T>::root_claim_declared_weight()
)]
pub fn claim_root(
    origin: OriginFor<T>,
    subnets: BTreeSet<NetUid>,
) -> DispatchResultWithPostInfo {
    let coldkey: T::AccountId = ensure_signed(origin)?;
    let _ = subnets; // ignored: basket claims are fund-level, not per-subnet

    let staking_hotkeys = StakingHotkeys::<T>::get(&coldkey);
    let selection_scanned = u32::try_from(staking_hotkeys.len()).unwrap_or(u32::MAX);
    // Admission failures keep the declared envelope: the admission scan's cost is
    // not precisely metered, so refunding it could under-charge. Only a claim that
    // was admitted and then failed is billed for the work it actually did.
    ensure!(
        selection_scanned <= Self::root_claim_declared_work(),
        Error::<T>::RootClaimTooHeavy
    );
    let hotkeys = Self::root_claim_hotkeys(&coldkey, staking_hotkeys);
    ensure!(
        Self::root_claim_fits_declared_budget(&hotkeys),
        Error::<T>::RootClaimTooHeavy
    );
    let hotkey_count = hotkeys.len() as u32;
    let admitted = Self::root_claim_admission_weight(
        selection_scanned.saturating_add(Self::root_claim_declared_work()),
    );
    let outcome = Self::do_root_claim_tracked(coldkey.clone(), hotkeys).map_err(
        |(done, error)| {
            Self::fail_with_weight(
                error,
                Self::root_claim_actual_weight(hotkey_count, selection_scanned, &done)
                    .saturating_add(admitted),
            )
        },
    )?;
    Self::maybe_add_coldkey_index(&coldkey);

    let weight = Self::root_claim_actual_weight(hotkey_count, selection_scanned, &outcome);
    Ok((Some(weight), Pays::Yes).into())
}

Delegates to root_claim_declared_work, root_claim_hotkeys, root_claim_fits_declared_budget.

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