Transaction Fees in Bittensor
This page describes the blockchain transaction fees charged by Bittensor and shows how to estimate them prior to your transactions.
Many extrinsic transactions that change the state of the blockchain are subject to a transaction fee based on a combination of transaction weight (computational load) and transaction length (storage load).
Staking and unstaking operations incur this transaction fee as well as amount-based swap fees of 0.05% of the transacted liquidity.
Reading the state of the chain is always free.
This page also covers:
- The alpha fallback mechanism, whereby transaction fees are paid in alpha when a wallet's TAO balance is insufficient (not yet active).
- Fee-free extrinsics.
- Proxy call fees — how fees and deposits work when dispatching through a proxy.
- Batch transaction fees — how fees are aggregated (or waived) across batched calls.
In-depth example (fees for a cross-subnet move_stake) and Estimating fees (how to estimate before sending).
General Transaction Fees
Each fee-bearing extrinsic is charged two components, both paid from the sender’s TAO free balance and recycled (deducted from TotalIssuance; see Recycling and Burning):
-
Weight fee — proportional to compute time (weight; specifically the
ref_timecomponent, in picoseconds). Calculated as rao. -
Length fee — 1 rao per byte of the encoded extrinsic.
Extrinsics that are fee-free (e.g. set_weights, commit_weights, reveal_weights, sudo) pay neither component.
See affected extrinsics
Staking Operations
add_stakeremove_stakeadd_stake_limitremove_stake_limitremove_stake_full_limitmove_staketransfer_stakeswap_stakeswap_stake_limitunstake_allunstake_all_alpha
Wallet and Identity Management
set_identityset_subnet_identitytry_associate_hotkeyschedule_swap_coldkeyset_coldkey_auto_stake_hotkey
Registration
Subnet Management
Burn/Recycle Alpha
Child Hotkey Management
Governance
See how fees are calculated
Weight fee — source: pallets/transaction-fee/src/lib.rs:44-56
pub struct LinearWeightToFee;
impl WeightToFeePolynomial for LinearWeightToFee {
type Balance = Balance;
fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
let coefficient = WeightToFeeCoefficient {
coeff_integer: 0,
coeff_frac: Perbill::from_parts(50_000), // 0.005%
negative: false,
degree: 1,
};
smallvec!(coefficient)
}
}
Length fee — runtime config sets LengthToFee = IdentityFee: 1 rao per byte of the encoded extrinsic. Source: runtime/src/lib.rs and the standard FRAME Transaction Payment pallet.
Swap Fees for Stake and Unstake Operations
In addition to the weight-based fee above, staking and unstaking operations are subject to fees based on a percentage of the quantity of transacted liquidity. When moving stake between subnets—whether through a transfer, swap, or move—a 0.05% fee is applied. If the move happens within the same subnet, no additional fee is incurred, only the weight-based fee.
Fee Details:
- Rate: 0.05%
- For staking: Fee paid in TAO from the staking amount
- For unstaking: Fee paid in Alpha from the unstaking amount
Source code references:
Alpha Fallback
This feature is not yet active. The alpha fallback logic is implemented but currently disabled in the chain. At present, if a coldkey cannot cover the transaction fee in TAO, the transaction is rejected.
For the unstaking and stake-movement extrinsics listed below, if the sender's TAO balance cannot cover the transaction fee, the chain will fall back to charging the fee in Alpha instead. If both TAO and Alpha balances are insufficient to cover the fee, the transaction is rejected before it is processed. When fees are paid in Alpha, the TAO fee amount is converted to Alpha at the current Alpha price with no slippage.
Affected extrinsics
remove_stakeremove_stake_limitremove_stake_full_limitunstake_allunstake_all_alphamove_staketransfer_stakeswap_stakeswap_stake_limitrecycle_alphaburn_alpha
- For
remove_stake,remove_stake_limit,recycle_alpha, andburn_alpha: after withdrawing Alpha fees, if the remaining Alpha balance is too small to keep as a dust balance, the transaction will consume and process the entire remaining Alpha balance in the same call. - For
remove_stake,remove_stake_limit,recycle_alpha, andburn_alpha: if the requested amount exceeds the available Alpha, the amount is capped at the available Alpha and the extrinsic succeeds (assuming no other errors).
Proxy Call Fees
When a call is dispatched through the proxy extrinsic, the total transaction fee covers the proxy's own overhead plus the inner call's weight. Crucially, the outer extrinsic inherits pays_fee and dispatch_class directly from the inner call (pallets/proxy/src/lib.rs:232–238):
#[pallet::weight({
let di = call.get_dispatch_info();
(T::WeightInfo::proxy(T::MaxProxies::get())
.saturating_add(T::DbWeight::get().reads_writes(1, 1))
.saturating_add(di.call_weight),
di.class, di.pays_fee)
})]
This means that if the inner call is fee-free (e.g. set_weights, commit_weights), the entire proxy call is also free — no transaction fee is charged.
Proxy registration deposits
Registering a proxy relationship locks a reserved balance from the real account's free TAO — this is not burned. It is returned in full when the proxy is removed. The total deposit for n proxies on a single real account is:
| Constant | Rao | TAO |
|---|---|---|
ProxyDepositBase | 60,000,000 | τ 0.06 |
ProxyDepositFactor | 33,000,000 | τ 0.033 per proxy |
So one proxy relationship costs τ 0.093 reserved; each additional proxy on the same real account adds τ 0.033.
Source code: deposit formula runtime/src/lib.rs:199–204, constants runtime/src/lib.rs:539–543, deposit calculation pallets/proxy/src/lib.rs:964–971.
Verify deposit amounts on-chain
These values are runtime constants (compiled into the WASM blob) and can only change with a runtime upgrade. To verify the current live values against what is documented here:
import bittensor as bt
sub = bt.Subtensor(network="finney")
s = sub.substrate
for name in [
"ProxyDepositBase",
"ProxyDepositFactor",
"AnnouncementDepositBase",
"AnnouncementDepositFactor",
"MaxProxies",
"MaxPending",
]:
print(f"{name}: {s.get_constant('Proxy', name)}")
ProxyDepositBase: 60000000
ProxyDepositFactor: 33000000
AnnouncementDepositBase: 36000000
AnnouncementDepositFactor: 68000000
MaxProxies: 20
MaxPending: 75
Announcement deposits
Proxies configured with a non-zero delay must announce calls before executing them. Each pending announcement locks an additional reserved balance (also returned on removal or execution):
| Constant | Rao | TAO |
|---|---|---|
AnnouncementDepositBase | 36,000,000 | τ 0.036 |
AnnouncementDepositFactor | 68,000,000 | τ 0.068 per announcement |
Up to 75 pending announcements are allowed per account (MaxPending). Source code: runtime/src/lib.rs:546–549.
Proxy management extrinsics
add_proxy, remove_proxy, remove_proxies, create_pure, kill_pure, announce, remove_announcement, and reject_announcement all pay the standard weight + length fee. add_proxy and remove_proxy additionally adjust the reserved proxy deposit.
See Proxies: Overview for a full description of proxy types, delays, and use cases.
Batch Transaction Fees
The utility pallet's batch, batch_all, and force_batch extrinsics aggregate the fees of their inner calls. The weight of the outer extrinsic is the sum of the inner call weights plus a small per-call overhead for the batch wrapper itself.
The pays_fee for the entire batch is determined by weight_and_dispatch_class:
let mut pays = Pays::No;
for di in calls.iter().map(|call| call.get_dispatch_info()) {
total_weight = total_weight.saturating_add(di.call_weight);
if di.pays_fee == Pays::Yes {
pays = Pays::Yes;
}
}
The batch pays a fee if any inner call is fee-bearing. The batch is free only if all inner calls are fee-free. For example, batching set_weights (free) with add_stake (fee-bearing) results in a fee being charged for the batch.
This applies only to the weight + length transaction fee. Swap fees for staking operations are assessed per-call inside the runtime and are not affected by the batch's pays_fee.
batch vs batch_all vs force_batch
All three behave identically for fee purposes. They differ only in error handling:
| Extrinsic | On error |
|---|---|
batch | Stops at first failure; prior calls succeed. Emits BatchInterrupted. |
batch_all | Reverts all calls atomically on any failure. |
force_batch | Continues past failures; failed calls are skipped. |
Source code: batch pallets/utility/src/lib.rs:197–201, batch_all pallets/utility/src/lib.rs:309–313, force_batch pallets/utility/src/lib.rs:408–412, weight_and_dispatch_class pallets/utility/src/lib.rs:606–618.
Using batch calls with the SDK
The Bittensor SDK does not have a high-level batch wrapper — add_stake_multiple and unstake_multiple send individual extrinsics sequentially, not a single batch extrinsic. To submit a true batch (one extrinsic on-chain), use the low-level compose_call + sign_and_send_extrinsic path directly.
Use batch_all (atomic) when all inner calls must succeed or none should. Use batch if partial success is acceptable, or force_batch to continue past failures. See the comparison table above.
Example: stake to two hotkeys in a single atomic batch extrinsic
import bittensor as bt
sub = bt.Subtensor(network="finney")
wallet = bt.Wallet(name="my_wallet", hotkey="my_hotkey")
wallet.unlock_coldkey()
hotkey_1 = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
hotkey_2 = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
netuid = 1
amount = bt.Balance.from_tao(10)
# Compose each inner call individually
call_1 = sub.compose_call(
call_module="SubtensorModule",
call_function="add_stake",
call_params={
"hotkey": hotkey_1,
"netuid": netuid,
"amount_staked": amount.rao,
},
)
call_2 = sub.compose_call(
call_module="SubtensorModule",
call_function="add_stake",
call_params={
"hotkey": hotkey_2,
"netuid": netuid,
"amount_staked": amount.rao,
},
)
# Wrap in a Utility.batch_all — reverts all calls atomically on any failure
batch_call = sub.compose_call(
call_module="Utility",
call_function="batch_all",
call_params={"calls": [call_1, call_2]},
)
# Submit the batch as a single extrinsic
success, error_message = sub.sign_and_send_extrinsic(
call=batch_call,
wallet=wallet,
wait_for_inclusion=True,
wait_for_finalization=False,
)
print(f"Success: {success}" if success else f"Failed: {error_message}")
add_stake_multiple is not a batch extrinsicsubtensor.add_stake_multiple() and subtensor.unstake_multiple() loop over their inputs and submit one extrinsic per hotkey. Each transaction is settled independently — they are not atomic. Use the Utility.batch_all pattern above when you need all-or-nothing semantics or want to pay a single transaction fee for the group.
Estimating fees (before you send a transaction)
The chain and the SDK expose two separate estimation paths: one for the swap/liquidity fee (stake, unstake, move, swap) and one for the transaction fee (weight + length). Use both when you want the full cost of a staking-related call.
Swap simulator
The SimSwap Runtime API simulates a swap and returns the liquidity fee and expected amounts. It does not include the transaction (extrinsic) fee.
For add_stake, remove_stake, move_stake, or swap_stake:
- Swap fee:
sim_swap(origin_netuid, destination_netuid, amount)→ usetao_feeoralpha_feeas appropriate (and same-subnet moves have no swap fee). - Transaction fee: Compose the extrinsic, then
get_payment_info(call, keypair)orget_extrinsic_fee(call, keypair)→partial_fee.
Total estimated cost = transaction fee (in TAO) + swap fee (in TAO or alpha, depending on direction).
On chain, the runtime implements SwapRuntimeApi with:
sim_swap_tao_for_alpha(netuid, tao)— simulates TAO → alpha (e.g. add_stake). ReturnsSimSwapResult:tao_amount,alpha_amount,tao_fee,alpha_fee.sim_swap_alpha_for_tao(netuid, alpha)— simulates alpha → TAO (e.g. remove_stake). ReturnsSimSwapResultwith fee and amounts.
Both official clients, BTCLI and the Python SDK, support sim swaps.
- BTCLI
- Bittensor SDK
BCLI does not offer a separate sim swap command, but when you run stake add, stake remove, or stake move, BTCLI shows a preview table with the swap fee (Fee (τ)) and Extrinsic Fee (τ) (transaction fee) before you confirm:
the only way to see these fees in BTCLI is to run the actual stake command; the table is printed before execution. Use the default prompt and answer "no" at "Would you like to continue?" to exit without sending the transaction.
btcli stake add
...
Amount to stake (TAO τ): 100
Staking to:
Wallet: 2MuchTau!, Coldkey ss58: 5Xj...
Network: test
┃ ┃ ┃ ┃ ┃ ┃ ┃ Rate with ┃ Partial
┃ ┃ ┃ ┃ Est. ┃ ┃ Extrinsic ┃ tolerance: ┃ stake
Netuid ┃ Hotkey ┃ Amount (τ) ┃ Rate (per τ) ┃ Received ┃ Fee (τ) ┃ Fee (τ) ┃ (0.5%) ┃ enabled
━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━
2 │ 5GrwvaEF5zX… │ 100.0000 τ │ 2416.813286… │ 241,556.4147 │ Τ 0.0504 │ 0.0013 τ │ 2404.7893 │ False
│ │ │ β/Τ │ β │ │ │ β/Τ │
────────┼──────────────┼────────────┼──────────────┼──────────────┼──────────┼──────────────┼──────────────┼──────────────
│ │ │ │ │ │ │ │
The table lists each hotkey/netuid with Fee (τ) (swap fee) and Extrinsic Fee (τ). To only view fees without executing, answer no at the confirmation prompt.
Use the SDK's subtensor.sim_swap(origin_netuid, destination_netuid, amount).
This method hits the blockchain's SimSwap runtime API to compute the swap simulation, and for cross-subnet moves, simulates two swaps and combines the result. The result is a SimSwapResult with:
tao_fee,alpha_fee— the swap/liquidity fee (in TAO or alpha)tao_amount,alpha_amount— expected output amounts- Slippage fields
Btcli uses sim_swap to show “Fee (τ)” and “Est. Received” in stake add/remove/move. The SDK’s get_fee_for_stake_add, get_fee_for_stake_remove, and get_fee_for_move_stake use sim_swap for the liquidity-fee part.
This example estimates swap fee and output for add_stake (TAO → alpha for SN 14):
import bittensor as bt
sub = bt.Subtensor(network="finney")
netuid = 14
amount_stake = bt.Balance.from_tao(0.1)
result = sub.sim_swap(
origin_netuid=0,
destination_netuid=netuid,
amount=amount_stake,
)
print(result)
SimSwapResult(tao_amount=τ0.099949646, alpha_amount=2.635103285γ, tao_fee=τ0.000050354, alpha_fee=0.000000000γ)
This example estimates swap fee and output for remove_stake (alpha for SN 14 → TAO):
import bittensor as bt
sub = bt.Subtensor(network="finney")
netuid = 14
amount_stake = bt.Balance.from_tao(0.1)
result = sub.sim_swap(
origin_netuid=14,
destination_netuid=0,
amount=amount_stake,
)
print(result)
SimSwapResult(tao_amount=τ0.000964782, alpha_amount=0.099949646ξ, tao_fee=τ0.000000000, alpha_fee=0.000050354ξ)
This example estimates swap for a cross-subnet move (subnet 14 → subnet 5):
import bittensor as bt
sub = bt.Subtensor(network="finney")
amount_alpha = bt.Balance.from_tao(1).set_unit(5)
result = sub.sim_swap(
origin_netuid=14,
destination_netuid=5,
amount=amount_alpha,
)
print(result)
SimSwapResult(tao_amount=τ0.009642946, alpha_amount=0.625912713ξ, tao_fee=τ0.000004858, alpha_fee=0.000503280ξ)
Code references: Runtime SwapRuntimeApi (sim_swap_tao_for_alpha, sim_swap_alpha_for_tao); swap pallet sim_swap; SDK sim_swap and btcli subtensor_interface.sim_swap; chain_data SimSwapResult.
Transaction (extrinsic) fee
To estimate the weight + length fee for any extrinsic (including stake calls), you can use the chain's payment query APIs in the polkadot browser app, or use the Bittensor Python SDK
- Polkadot.js App
- BTCLI
- Bittensor SDK
You can query fee details directly from the chain using the Polkadot.js browser app connected to Finney. Under Developer → Runtime Calls, use TransactionPaymentApi:
query_info(uxt, len)orquery_fee_details(uxt, len)— full fee breakdown for a given extrinsic and its encoded lengthquery_weight_to_fee(weight)— weight component onlyquery_length_to_fee(length)— length component only
The stake add, stake remove, and stake move commands display Extrinsic Fee (τ) (the transaction fee) in the preview table alongside the swap fee, as described above:
the only way to see these fees in BTCLI is to run the actual stake command; the table is printed before execution. Use the default prompt and answer "no" at "Would you like to continue?" to exit without sending the transaction.
btcli stake add
...
Amount to stake (TAO τ): 100
Staking to:
Wallet: 2MuchTau!, Coldkey ss58: 5Xj...
Network: test
┃ ┃ ┃ ┃ ┃ ┃ ┃ Rate with ┃ Partial
┃ ┃ ┃ ┃ Est. ┃ ┃ Extrinsic ┃ tolerance: ┃ stake
Netuid ┃ Hotkey ┃ Amount (τ) ┃ Rate (per τ) ┃ Received ┃ Fee (τ) ┃ Fee (τ) ┃ (0.5%) ┃ enabled
━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━
2 │ 5GrwvaEF5zX… │ 100.0000 τ │ 2416.813286… │ 241,556.4147 │ Τ 0.0504 │ 0.0013 τ │ 2404.7893 │ False
│ │ │ β/Τ │ β │ │ │ β/Τ │
────────┼──────────────┼────────────┼──────────────┼──────────────┼──────────┼──────────────┼──────────────┼──────────────
│ │ │ │ │ │ │ │
subtensor.get_payment_info(call, keypair)— returns a dict includingpartial_fee(the total transaction fee in rao). Used by btcli for “Extrinsic Fee”.subtensor.get_extrinsic_fee(call, keypair)— same underlyingsubstrate.get_payment_info(call, keypair); returns aBalancefrompartial_fee.
You must compose the call (e.g. the exact add_stake, move_stake, or other extrinsic and params) before calling these; they simulate the fee for that call and keypair.
Example: estimate transaction fee for an add_stake extrinsic
import bittensor as bt
sub = bt.Subtensor(network="test")
wallet = bt.Wallet(name="my_wallet", hotkey="my_hotkey")
wallet.unlock_coldkey()
netuid = 1
hotkey_ss58 = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
amount = bt.Balance.from_tao(10)
# Compose the add_stake call (same params you would use to send the tx)
call = sub.compose_call(
call_module="SubtensorModule",
call_function="add_stake",
call_params={
"hotkey": hotkey_ss58,
"netuid": netuid,
"amount_staked": amount.rao,
},
)
# Keypair is the account that pays the fee (coldkey)
fee = sub.get_extrinsic_fee(call=call, keypair=wallet.coldkeypub)
print(f"Estimated transaction fee: {fee}")
Estimated transaction fee: τ0.001337128
Fee-Free Extrinsics
The following extrinsics are free.
Weight Setting & Commit-Reveal
set_weights- Setting validator weightscommit_weights- Commit weight hashbatch_commit_weights- Batch commit weight hashesreveal_weights- Reveal committed weightscommit_crv3_weights- Commit CRv3 encrypted weightsbatch_reveal_weights- Batch reveal committed weights
In-depth example: fees for a cross-subnet move_stake
This section traces a single move_stake transaction from the moment it is submitted until the chain has applied every fee. It shows how the transaction fee (weight + length) and the swap/liquidity fee combine, and how the chain avoids double-charging on moves. All claims below are backed by source references; see Code references for this section at the end.
Scenario (from Managing stake with the SDK):
You move stake from subnet 5 (origin) to subnet 18 (destination). The amount is 1 TAO worth of alpha on subnet 5 (the coldkey signs; the amount is specified in origin-subnet alpha). Same coldkey, different hotkeys and subnets.
What the chain does
-
Validate and charge the transaction fee (before dispatch)
The runtime treats the call as a normal signed extrinsic: it computes weight and length (the size in bytes of the encoded extrinsic; see Length-Based Transaction Fee), then charges:- Weight fee: rao (from
LinearWeightToFee:Perbill::from_parts(50_000)). - Length fee: 1 rao per byte of the encoded extrinsic (from runtime config
LengthToFee = IdentityFee).
This is withdrawn from the coldkey’s TAO free balance. If the coldkey cannot pay, the extrinsic fails at validation and nothing else runs. Fee withdrawal:OnChargeTransaction::withdraw_fee.
- Weight fee: rao (from
-
Execute the move (transition_stake_internal)
do_move_stakecallstransition_stake_internal. Becauseorigin_netuid != destination_netuid, the chain:- Unstake on origin (subnet 5): Converts the requested alpha to TAO via the subnet's swap. A swap fee is applied here unless the origin is root (see below). Source:
unstake_from_subnetwithdrop_fee_origin. - Stake on destination (subnet 18): Converts the resulting TAO to alpha on subnet 18 (
stake_into_subnetwithdrop_fee_destination). For move_stake (and swap_stake), the chain does not charge a second swap fee on the destination when the origin is not root: it setsdrop_fee_destination = trueso that only one liquidity fee is taken (on the origin unstake). This avoids double-charging on a single move.
- Unstake on origin (subnet 5): Converts the requested alpha to TAO via the subnet's swap. A swap fee is applied here unless the origin is root (see below). Source:
-
Fee logic for moves
In the code,drop_fee_origin = origin_netuid == NetUid::ROOTanddrop_fee_destination = !drop_fee_origin. So:- Move from a non-root subnet (e.g. 5) to another subnet (e.g. 18): Fee is charged only on the origin (alpha→TAO on subnet 5). No fee on the destination stake.
- Move from root to a subnet: Fee is charged only on the destination (TAO→alpha). No fee on the “unstake” from root.
So for subnet 5 → subnet 18, the user pays:
- The transaction fee (weight + length) in TAO from the coldkey.
- One swap fee (on subnet 5’s alpha→TAO conversion), taken from the moved liquidity (in alpha).
Calculating the fees
1. Transaction fee (weight component)
The move_stake extrinsic has a declared weight of (dispatches.rs):
Weight::from_parts(164_300_000, 0)
+ DbWeight::reads(15)
+ DbWeight::writes(7)
The chain converts this to rao using the fee formula: . The exact weight contribution of each read and write is determined by the chain’s DbWeight constants. For illustration, if the total weight is about 165_000_000:
- Weight fee 8,250 rao (about 0.00000825 TAO).
2. Transaction fee (length component)
The encoded extrinsic includes the call index, two account IDs (32 bytes each), two netuids, and an alpha amount. A typical size is on the order of 100–200 bytes. At 1 rao per byte (LengthToFee = IdentityFee):
- Length fee ≈ 100–200 rao.
3. Swap fee (liquidity component)
For subnet 5 (mechanism 1), the fee is (calculate_fee_amount for mechanism 1), where 65,535 is the maximum possible fee rate value. With the default DefaultFeeRate of 33:
- Rate .
- For 1 TAO worth of alpha on subnet 5, the swap fee is about 0.0005 TAO (about 500_000 rao), taken in alpha from the amount moved.
So in this example, total cost to the user is roughly:
- Transaction fee: ~8_250 + ~150 ≈ ~8_400 rao (0.0000084 TAO), paid from the coldkey’s TAO balance.
- Swap fee: ~0.05% of the moved amount, paid in alpha (from the stake on subnet 5).
The swap fee is much larger than the transaction fee for typical move amounts; the transaction fee is still required and must be covered by the coldkey’s TAO.
Same-subnet move
If you move_stake (or transfer_stake) within the same subnet (same hotkey or different hotkey, same netuid), the chain uses transfer_stake_within_subnet: it only reattributes alpha between hotkeys/coldkeys. There is no swap, so no swap fee—only the weight and length transaction fee apply. (Comment in code: "Does not incur any swapping nor fees".)
How to get exact numbers
- Transaction fee: Use the runtime’s
TransactionPaymentApi.query_fee_details(uxt, len)or the SDK’sget_payment_info(call, keypair)to get the actual inclusive fee (e.g.partial_fee) for the constructed extrinsic. - Swap fee for a move: Use the runtime API
get_stake_fee(origin, origin_coldkey, destination, destination_coldkey, amount) or the SimSwap API / SDKsim_swapfor the path and amount you use. For move_stake, the chain charges only one side (origin or destination) as above, so the displayed “stake fee” from these APIs should be interpreted in that light.
Code references
| Claim | Source |
|---|---|
| move_stake weight (164_300_000 + reads(15) + writes(7)) | dispatches.rs L1535-L1538 |
| Weight-to-fee: 50_000/10^9 | transaction-fee/src/lib.rs L43-L56 |
| Length-to-fee: IdentityFee | runtime/src/lib.rs L504 |
| Fee withdrawal | transaction-fee/src/lib.rs L307-L335 |
| do_move_stake, transition_stake_internal | move_stake.rs L30-L75, L298-L398 |
| drop_fee_origin / drop_fee_destination | move_stake.rs L354-L355 |
| unstake_from_subnet / stake_into_subnet | move_stake.rs L356-L383 |
| transfer_stake_within_subnet (no swap) | stake_utils.rs L850-L857 |
| Swap fee: FeeRate/u16::MAX, DefaultFeeRate=33 | swap/impls.rs L362-L381, swap/mod.rs L75-L83 |
| get_stake_fee runtime API | runtime/src/lib.rs L2476-L2477 |