Transactions

remove-stake-limit

Unstake alpha with a limit price (slippage protection).

View as Markdown

Same as remove_stake except the alpha-to-TAO swap only executes while the pool price stays within the limit. With allow_partial it unstakes what it can within the limit and leaves the rest staked; without it the whole call fails once the limit would be breached. Pass all to target the entire position (the build fails if nothing is staked there). Like remove_stake, a partial unstake must leave a remainder worth at least 0.002 TAO at the simulated pool price (AmountTooLow). Prefer this over plain remove_stake when exiting large positions.

On root (netuid 0), pass claim=True to redeem this validator's whole basket entitlement first, then unstake. That is not a proportional payout: the claim pays 100% of the basket.

SignerOriginPalletWraps
coldkeysigned account (pallet role may apply)SubtensorModuleSubtensorModule.remove_stake_limit, SubtensorModule.remove_stake, SubtensorModule.claim_root_with_hotkey, Utility.batch_all

Parameters

ParameterTypeRequiredDescription
hotkey_ss58stringyesHotkey the stake is held on (the validator backing the position).
netuidintegeryesSubnet the stake lives on (netuid 0 is the root network).
amount_alphanumber | "all"yesHow much to unstake from this position, or all.
limit_price_raointegeryesWorst pool price you will accept for the swap. The call fails (or fills partially when allow-partial is set) instead of executing beyond this price.
allow_partialbooleannoExecute whatever portion fits within the limit price and drop the remainder, instead of failing the whole call when the limit would be breached.
claimbooleannoAlso redeem this validator's whole basket entitlement before unstaking, in one atomic batch. Root only (netuid 0). This is not a proportional payout: unstaking 40% still claims 100% of the basket. The chain has no proportional-claim call. Claimed yield is restaked on root, then the unstake runs — pass all to take principal and yield out together. Unavailable while RootStakeUnlockInterval is nonzero, because the claim starts a new hold window; claim first, wait, then unstake in that mode.

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 remove-stake-limit \
  --hotkey <ss58|name> \
  --netuid <int> \
  --amount-alpha <amount|all> \
  --limit-price-rao <int> --dry-run
btcli tx remove-stake-limit \
  --hotkey <ss58|name> \
  --netuid <int> \
  --amount-alpha <amount|all> \
  --limit-price-rao <int> -w my_coldkey

Python

import bittensor as bt
from bittensor.wallet import Wallet

wallet = Wallet(name="my_coldkey", hotkey="my_hotkey")
intent = bt.RemoveStakeLimit(hotkey_ss58="5F...", netuid=1, amount_alpha=1.0, limit_price_rao=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("remove_stake_limit", {...}, wallet)

On-chain implementation

Chain callSource
SubtensorModule.remove_stake_limitpallets/subtensor/src/macros/dispatches.rs#L1470
SubtensorModule.remove_stakepallets/subtensor/src/macros/dispatches.rs#L612
SubtensorModule.claim_root_with_hotkeypallets/subtensor/src/macros/dispatches.rs#L1993
Utility.batch_allpallets/utility/src/lib.rs#L314

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