Transactions

move-stake

Move alpha between hotkeys and/or subnets.

View as Markdown

Re-delegates an existing position without passing through the coldkey's free balance: the stake leaves the origin hotkey on the origin subnet and lands on the destination hotkey at the destination subnet. Moving within one subnet just changes which validator backs the stake. Moving across subnets swaps through both pools and can incur slippage on each leg.

Cross-subnet moves are slippage-protected by default: they compose move_stake_limit with a fill-or-kill price ratio. Same-subnet moves stay a single move_stake. Disable slippage_protection to submit the bare cross-subnet move_stake at any price.

Ownership stays with the signing coldkey — use transfer_stake to hand the position to another coldkey, or swap_stake when only the subnet changes. Pass all to move the entire origin position.

SignerOriginPalletWraps
coldkeysigned account (pallet role may apply)SubtensorModuleSubtensorModule.move_stake, SubtensorModule.move_stake_limit

Parameters

ParameterTypeRequiredDescription
origin_hotkey_ss58stringyesHotkey the stake moves away from.
origin_netuidintegeryesSubnet the stake currently sits on.
dest_hotkey_ss58stringyesHotkey the stake moves to.
dest_netuidintegeryesSubnet the stake ends up on. When it differs from the origin, the position is swapped through both subnet pools, which can incur slippage on each leg.
amount_alphanumber | "all"yesHow much of the origin position to move, or all.
slippage_protectionbooleannoBound the price the swap may execute at (on by default): the call fails (SlippageTooHigh) instead of filling once the pool price moves more than rate_tolerance from the price at submission. Disable to execute at any price.
rate_tolerancenumbernoMaximum price move slippage protection accepts, as a fraction (0.05 = 5%). Ignored when slippage protection is disabled.

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 move-stake \
  --origin-hotkey <ss58|name> \
  --origin-netuid <int> \
  --dest-hotkey <ss58|name> \
  --dest-netuid <int> \
  --amount-alpha <amount|all> --dry-run
btcli tx move-stake \
  --origin-hotkey <ss58|name> \
  --origin-netuid <int> \
  --dest-hotkey <ss58|name> \
  --dest-netuid <int> \
  --amount-alpha <amount|all> -w my_coldkey

Python

import bittensor as bt
from bittensor.wallet import Wallet

wallet = Wallet(name="my_coldkey", hotkey="my_hotkey")
intent = bt.MoveStake(origin_hotkey_ss58="5F...origin", origin_netuid=1, dest_hotkey_ss58="5G...destination", dest_netuid=2, amount_alpha=1.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("move_stake", {...}, wallet)

On-chain implementation

SubtensorModule.move_stakepallets/subtensor/src/macros/dispatches.rs#L1281:

#[pallet::call_index(85)]
#[pallet::weight(<T as crate::pallet::Config>::WeightInfo::move_stake())]
pub fn move_stake(
    origin: OriginFor<T>,
    origin_hotkey: T::AccountId,
    destination_hotkey: T::AccountId,
    origin_netuid: NetUid,
    destination_netuid: NetUid,
    alpha_amount: AlphaBalance,
) -> DispatchResult {
    Self::do_move_stake(
        origin,
        origin_hotkey,
        destination_hotkey,
        origin_netuid,
        destination_netuid,
        alpha_amount,
    )
}

Delegates to do_move_stake.

SubtensorModule.move_stake_limitpallets/subtensor/src/macros/dispatches.rs#L1544:

#[pallet::call_index(149)]
#[pallet::weight(<T as crate::pallet::Config>::WeightInfo::move_stake_limit())]
pub fn move_stake_limit(
    origin: OriginFor<T>,
    origin_hotkey: T::AccountId,
    destination_hotkey: T::AccountId,
    origin_netuid: NetUid,
    destination_netuid: NetUid,
    alpha_amount: AlphaBalance,
    limit_price: TaoBalance,
    allow_partial: bool,
) -> DispatchResult {
    Self::do_move_stake_limit(
        origin,
        origin_hotkey,
        destination_hotkey,
        origin_netuid,
        destination_netuid,
        alpha_amount,
        limit_price,
        allow_partial,
    )
}

Delegates to do_move_stake_limit.

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