From a1c1c2a2a670981f8470788ee4ebe867a2bf63e1 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Thu, 4 Jun 2026 12:24:00 -0400 Subject: [PATCH 1/4] Add lock-aware stake transfer extrinsic --- pallets/subtensor/src/macros/dispatches.rs | 28 +++++ pallets/subtensor/src/staking/lock.rs | 32 +++++- pallets/subtensor/src/staking/move_stake.rs | 62 ++++++++++ pallets/subtensor/src/staking/stake_utils.rs | 9 +- pallets/subtensor/src/subnets/leasing.rs | 2 + pallets/subtensor/src/tests/locks.rs | 114 +++++++++++++++++++ 6 files changed, 243 insertions(+), 4 deletions(-) diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index b471328aec..64bab6941b 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -1558,6 +1558,34 @@ mod dispatches { ) } + /// Transfers locked or unlocked stake from one coldkey to another, optionally across subnets, + /// while keeping the same hotkey. + /// + /// If `locked` is true, the call transfers at most the currently locked alpha and moves + /// the corresponding lock state. If `locked` is false, it transfers at most the currently + /// unlocked alpha. + #[pallet::call_index(139)] + #[pallet::weight(::WeightInfo::transfer_stake())] + pub fn transfer_stake_lock_aware( + origin: OriginFor, + destination_coldkey: T::AccountId, + hotkey: T::AccountId, + origin_netuid: NetUid, + destination_netuid: NetUid, + alpha_amount: AlphaBalance, + locked: bool, + ) -> DispatchResult { + Self::do_transfer_stake_lock_aware( + origin, + destination_coldkey, + hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + locked, + ) + } + /// Swaps a specified amount of stake from one subnet to another, while keeping the same coldkey and hotkey. /// /// # Arguments diff --git a/pallets/subtensor/src/staking/lock.rs b/pallets/subtensor/src/staking/lock.rs index 27c5e5d646..a1a621139b 100644 --- a/pallets/subtensor/src/staking/lock.rs +++ b/pallets/subtensor/src/staking/lock.rs @@ -680,6 +680,20 @@ impl Pallet { } } + /// Returns the transferable alpha in either the locked or unlocked bucket. + pub fn lock_aware_transferable_alpha( + coldkey: &T::AccountId, + netuid: NetUid, + locked: bool, + ) -> AlphaBalance { + if locked { + Self::get_current_locked(coldkey, netuid) + .min(Self::total_coldkey_alpha_on_subnet(coldkey, netuid)) + } else { + Self::available_to_unstake(coldkey, netuid) + } + } + /// Ensures that the amount can be unstaked pub fn ensure_available_to_unstake( coldkey: &T::AccountId, @@ -1671,6 +1685,7 @@ impl Pallet { destination_coldkey: &T::AccountId, netuid: NetUid, amount: AlphaBalance, + lock_aware_transfer: Option, ) -> DispatchResult { let now = Self::get_current_block_as_u64(); @@ -1719,9 +1734,20 @@ impl Pallet { let unavailable = source_lock.locked_mass; let available_stake = total_alpha.saturating_sub(unavailable); - // Reduce remaining_to_transfer by min(remaining_to_transfer, available stake) - let available_transfer = remaining_to_transfer.min(available_stake); - remaining_to_transfer = remaining_to_transfer.saturating_sub(available_transfer); + // In the default mode, transfers consume unlocked stake first. Any amount + // left in `remaining_to_transfer` after this subtraction must come from + // the lock and needs lock state moved with it. In locked-only mode, skip + // this subtraction so the whole capped amount is treated as locked. + if lock_aware_transfer != Some(true) { + let available_transfer = remaining_to_transfer.min(available_stake); + remaining_to_transfer = remaining_to_transfer.saturating_sub(available_transfer); + } + + // In unlocked-only mode, the capped amount has already been fully covered + // by unlocked stake, so no lock state should be transferred. + if lock_aware_transfer == Some(false) { + remaining_to_transfer = AlphaBalance::ZERO; + } // If result is non-zero, check the hotkey match between source and destination coldkey locks // (if destination coldkey lock exists). If no match, error out with LockHotkeyMismatch, otherwise, diff --git a/pallets/subtensor/src/staking/move_stake.rs b/pallets/subtensor/src/staking/move_stake.rs index aafefa28ed..9bebf65eb0 100644 --- a/pallets/subtensor/src/staking/move_stake.rs +++ b/pallets/subtensor/src/staking/move_stake.rs @@ -51,6 +51,7 @@ impl Pallet { None, false, true, + None, )?; // Log the event. @@ -142,6 +143,7 @@ impl Pallet { None, true, false, + None, )?; // 9. Emit an event for logging/monitoring. @@ -161,6 +163,53 @@ impl Pallet { Ok(()) } + /// Transfers either locked or unlocked stake from one coldkey to another. + /// + /// This follows `do_transfer_stake`, but caps the requested amount to the + /// selected lock bucket. If `locked` is true, only locked alpha can move and + /// the matching lock state follows the stake. If `locked` is false, only + /// unlocked alpha can move. + pub fn do_transfer_stake_lock_aware( + origin: OriginFor, + destination_coldkey: T::AccountId, + hotkey: T::AccountId, + origin_netuid: NetUid, + destination_netuid: NetUid, + alpha_amount: AlphaBalance, + locked: bool, + ) -> dispatch::DispatchResult { + let coldkey = ensure_signed(origin)?; + + let tao_moved = Self::transition_stake_internal( + &coldkey, + &destination_coldkey, + &hotkey, + &hotkey, + origin_netuid, + destination_netuid, + alpha_amount, + None, + None, + true, + false, + Some(locked), + )?; + + log::debug!( + "StakeTransferred(origin_coldkey: {coldkey:?}, destination_coldkey: {destination_coldkey:?}, hotkey: {hotkey:?}, origin_netuid: {origin_netuid:?}, destination_netuid: {destination_netuid:?}, amount: {tao_moved:?})" + ); + Self::deposit_event(Event::StakeTransferred( + coldkey, + destination_coldkey, + hotkey, + origin_netuid, + destination_netuid, + tao_moved, + )); + + Ok(()) + } + /// Swaps a specified amount of stake for the same `(coldkey, hotkey)` pair from one subnet /// (`origin_netuid`) to another (`destination_netuid`). /// @@ -207,6 +256,7 @@ impl Pallet { None, false, true, + None, )?; // Emit an event for logging. @@ -275,6 +325,7 @@ impl Pallet { Some(allow_partial), false, true, + None, )?; // Emit an event for logging. @@ -307,6 +358,7 @@ impl Pallet { maybe_allow_partial: Option, check_transfer_toggle: bool, set_limit: bool, + lock_aware_transfer: Option, ) -> Result { // Cap the alpha_amount at available Alpha because user might be paying transaxtion fees // in Alpha and their total is already reduced by now. @@ -316,6 +368,15 @@ impl Pallet { origin_netuid, ); let alpha_amount = alpha_amount.min(alpha_available); + let alpha_amount = lock_aware_transfer + .map(|locked| { + alpha_amount.min(Self::lock_aware_transferable_alpha( + origin_coldkey, + origin_netuid, + locked, + )) + }) + .unwrap_or(alpha_amount); // Calculate the maximum amount that can be executed let max_amount = if origin_netuid != destination_netuid { @@ -399,6 +460,7 @@ impl Pallet { destination_hotkey, origin_netuid, move_amount, + lock_aware_transfer, ) } } diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index 0f6a553c91..c2e1d79322 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -959,9 +959,16 @@ impl Pallet { destination_hotkey: &T::AccountId, netuid: NetUid, alpha: AlphaBalance, + lock_aware_transfer: Option, ) -> Result { // Transfer lock (may fail if destination coldkey has a conflicting lock) - Self::transfer_lock(origin_coldkey, destination_coldkey, netuid, alpha)?; + Self::transfer_lock( + origin_coldkey, + destination_coldkey, + netuid, + alpha, + lock_aware_transfer, + )?; // Decrease alpha on origin keys Self::decrease_stake_for_hotkey_and_coldkey_on_subnet( diff --git a/pallets/subtensor/src/subnets/leasing.rs b/pallets/subtensor/src/subnets/leasing.rs index d3e1b84df5..22256395b1 100644 --- a/pallets/subtensor/src/subnets/leasing.rs +++ b/pallets/subtensor/src/subnets/leasing.rs @@ -312,6 +312,7 @@ impl Pallet { &lease.hotkey, lease.netuid, alpha_for_contributor.into(), + None, )?; alpha_distributed = alpha_distributed.saturating_add(alpha_for_contributor.into()); @@ -332,6 +333,7 @@ impl Pallet { &lease.hotkey, lease.netuid, beneficiary_cut_alpha.into(), + None, )?; Self::deposit_event(Event::SubnetLeaseDividendsDistributed { lease_id, diff --git a/pallets/subtensor/src/tests/locks.rs b/pallets/subtensor/src/tests/locks.rs index 4b452d639f..46f530d8f7 100644 --- a/pallets/subtensor/src/tests/locks.rs +++ b/pallets/subtensor/src/tests/locks.rs @@ -1738,6 +1738,120 @@ fn test_transfer_stake_cross_coldkey_allowed_partial() { }); } +#[test] +fn test_transfer_stake_lock_aware_transfers_only_locked_stake() { + new_test_ext(1).execute_with(|| { + let coldkey_sender = U256::from(1); + let coldkey_receiver = U256::from(5); + let hotkey = U256::from(2); + let netuid = setup_subnet_with_stake(coldkey_sender, hotkey, 100_000_000_000); + DecayingLock::::insert(coldkey_receiver, netuid, false); + + let total = SubtensorModule::total_coldkey_alpha_on_subnet(&coldkey_sender, netuid); + let lock_amount = total / 3.into(); + assert_ok!(SubtensorModule::do_lock_stake( + &coldkey_sender, + netuid, + &hotkey, + lock_amount, + )); + + let sender_lock_before = + Lock::::get((coldkey_sender, netuid, hotkey)).expect("sender lock should exist"); + + step_block(1); + + assert_ok!(SubtensorModule::transfer_stake_lock_aware( + RuntimeOrigin::signed(coldkey_sender), + coldkey_receiver, + hotkey, + netuid, + netuid, + total, + true, + )); + + let expected_lock = roll_forward_lock( + sender_lock_before, + SubtensorModule::get_current_block_as_u64(), + false, + true, + ); + + assert_eq!( + get_alpha(&hotkey, &coldkey_receiver, netuid), + expected_lock.locked_mass + ); + assert_eq!( + get_alpha(&hotkey, &coldkey_sender, netuid), + total.saturating_sub(expected_lock.locked_mass) + ); + assert!(Lock::::get((coldkey_sender, netuid, hotkey)).is_none()); + + let receiver_lock = Lock::::get((coldkey_receiver, netuid, hotkey)) + .expect("receiver lock should exist"); + assert_eq!(receiver_lock.locked_mass, expected_lock.locked_mass); + assert_eq!(receiver_lock.conviction, expected_lock.conviction); + }); +} + +#[test] +fn test_transfer_stake_lock_aware_transfers_only_unlocked_stake() { + new_test_ext(1).execute_with(|| { + let coldkey_sender = U256::from(1); + let coldkey_receiver = U256::from(5); + let hotkey = U256::from(2); + let netuid = setup_subnet_with_stake(coldkey_sender, hotkey, 100_000_000_000); + + let total = SubtensorModule::total_coldkey_alpha_on_subnet(&coldkey_sender, netuid); + let lock_amount = total / 4.into(); + assert_ok!(SubtensorModule::do_lock_stake( + &coldkey_sender, + netuid, + &hotkey, + lock_amount, + )); + + let sender_lock_before = + Lock::::get((coldkey_sender, netuid, hotkey)).expect("sender lock should exist"); + + step_block(1); + + assert_ok!(SubtensorModule::do_transfer_stake_lock_aware( + RuntimeOrigin::signed(coldkey_sender), + coldkey_receiver, + hotkey, + netuid, + netuid, + total, + false, + )); + + let expected_lock = roll_forward_lock( + sender_lock_before, + SubtensorModule::get_current_block_as_u64(), + false, + true, + ); + let expected_unlocked = total.saturating_sub(expected_lock.locked_mass); + + assert_eq!( + get_alpha(&hotkey, &coldkey_receiver, netuid), + expected_unlocked + ); + assert_eq!( + get_alpha(&hotkey, &coldkey_sender, netuid), + expected_lock.locked_mass + ); + + let sender_lock_after = + Lock::::get((coldkey_sender, netuid, hotkey)).expect("sender lock should remain"); + assert_eq!(sender_lock_after.locked_mass, expected_lock.locked_mass); + assert_eq!(sender_lock_after.conviction, expected_lock.conviction); + assert!(Lock::::get((coldkey_receiver, netuid, hotkey)).is_none()); + }); +} + // ========================================================================= // GROUP 8: Multi-subnet locks // ========================================================================= From 5ac2650260c1e6e862057e5598b48275421538c1 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Thu, 4 Jun 2026 12:57:39 -0400 Subject: [PATCH 2/4] Add locked transfer test --- pallets/subtensor/src/staking/lock.rs | 4 +- pallets/subtensor/src/tests/locks.rs | 102 ++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/pallets/subtensor/src/staking/lock.rs b/pallets/subtensor/src/staking/lock.rs index a1a621139b..87a9bc5307 100644 --- a/pallets/subtensor/src/staking/lock.rs +++ b/pallets/subtensor/src/staking/lock.rs @@ -1737,7 +1737,9 @@ impl Pallet { // In the default mode, transfers consume unlocked stake first. Any amount // left in `remaining_to_transfer` after this subtraction must come from // the lock and needs lock state moved with it. In locked-only mode, skip - // this subtraction so the whole capped amount is treated as locked. + // this subtraction so the whole capped amount is treated as locked so + // effectively we start the transfer from the locked portion without accounting + // for unlocked alpha. if lock_aware_transfer != Some(true) { let available_transfer = remaining_to_transfer.min(available_stake); remaining_to_transfer = remaining_to_transfer.saturating_sub(available_transfer); diff --git a/pallets/subtensor/src/tests/locks.rs b/pallets/subtensor/src/tests/locks.rs index 46f530d8f7..0f160213c9 100644 --- a/pallets/subtensor/src/tests/locks.rs +++ b/pallets/subtensor/src/tests/locks.rs @@ -1852,6 +1852,108 @@ fn test_transfer_stake_lock_aware_transfers_only_unlocked_stake() { }); } +#[test] +fn test_transfer_stake_lock_aware_owner_lock_moves_all_lock_and_conviction() { + new_test_ext(1).execute_with(|| { + let coldkey1 = U256::from(1); + let coldkey2 = U256::from(5); + let hotkey1 = U256::from(2); + let netuid = add_dynamic_network(&hotkey1, &coldkey1); + let stake_tao = 100_000_000_000u64; + + setup_reserves( + netuid, + (stake_tao * 1_000_000).into(), + (stake_tao * 10_000_000).into(), + ); + assert_ok!(SubtensorModule::create_account_if_non_existent( + &coldkey1, &hotkey1 + )); + add_balance_to_coldkey_account(&coldkey1, stake_tao.into()); + SubtensorModule::stake_into_subnet( + &hotkey1, + &coldkey1, + netuid, + stake_tao.into(), + ::SwapInterface::max_price(), + false, + false, + ) + .unwrap(); + DecayingLock::::insert(coldkey1, netuid, false); + DecayingLock::::insert(coldkey2, netuid, false); + + let total = get_alpha(&hotkey1, &coldkey1, netuid); + let lock_amount = total / 2.into(); + assert_ok!(SubtensorModule::do_lock_stake( + &coldkey1, + netuid, + &hotkey1, + lock_amount, + )); + let coldkey1_lock_before = + Lock::::get((coldkey1, netuid, hotkey1)).expect("coldkey1 lock should exist"); + + step_block(10); + + let expected_transferred_lock = roll_forward_lock( + coldkey1_lock_before, + SubtensorModule::get_current_block_as_u64(), + true, + true, + ); + assert!(expected_transferred_lock.conviction > U64F64::from_num(0)); + + assert_ok!(SubtensorModule::transfer_stake_lock_aware( + RuntimeOrigin::signed(coldkey1), + coldkey2, + hotkey1, + netuid, + netuid, + total, + true, + )); + + assert_eq!( + get_alpha(&hotkey1, &coldkey2, netuid), + expected_transferred_lock.locked_mass + ); + assert_eq!( + get_alpha(&hotkey1, &coldkey1, netuid), + total.saturating_sub(expected_transferred_lock.locked_mass) + ); + + assert!(Lock::::get((coldkey1, netuid, hotkey1)).is_none()); + assert_eq!( + SubtensorModule::get_current_locked(&coldkey1, netuid), + AlphaBalance::ZERO + ); + assert_eq!( + SubtensorModule::get_conviction(&coldkey1, netuid), + U64F64::from_num(0) + ); + + let coldkey2_lock = + Lock::::get((coldkey2, netuid, hotkey1)).expect("coldkey2 lock should exist"); + assert_eq!( + coldkey2_lock.locked_mass, + expected_transferred_lock.locked_mass + ); + assert_eq!( + coldkey2_lock.conviction, + expected_transferred_lock.conviction + ); + assert_eq!( + SubtensorModule::get_current_locked(&coldkey2, netuid), + expected_transferred_lock.locked_mass + ); + assert_eq!( + SubtensorModule::get_conviction(&coldkey2, netuid), + expected_transferred_lock.conviction + ); + }); +} + // ========================================================================= // GROUP 8: Multi-subnet locks // ========================================================================= From 17aaa777ec24281b462ca0ce5a61c4d5107abf72 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Thu, 4 Jun 2026 14:04:55 -0400 Subject: [PATCH 3/4] Address AI reviewer concern --- pallets/subtensor/src/staking/stake_utils.rs | 30 +++++----- pallets/subtensor/src/tests/locks.rs | 58 ++++++++++++++++++++ 2 files changed, 73 insertions(+), 15 deletions(-) diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index c2e1d79322..f179ad2bfb 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -961,6 +961,21 @@ impl Pallet { alpha: AlphaBalance, lock_aware_transfer: Option, ) -> Result { + // Calculate TAO equivalent based on current price (it is accurate because + // there's no slippage in this move) and validate it before mutating lock + // or stake storage. + let current_price = + ::SwapInterface::current_alpha_price(netuid.into()); + let tao_equivalent: TaoBalance = current_price + .saturating_mul(U96F32::saturating_from_num(alpha)) + .saturating_to_num::() + .into(); + + ensure!( + tao_equivalent >= DefaultMinStake::::get(), + Error::::AmountTooLow + ); + // Transfer lock (may fail if destination coldkey has a conflicting lock) Self::transfer_lock( origin_coldkey, @@ -1000,21 +1015,6 @@ impl Pallet { ); } - // Calculate TAO equivalent based on current price (it is accurate because - // there's no slippage in this move) - let current_price = - ::SwapInterface::current_alpha_price(netuid.into()); - let tao_equivalent: TaoBalance = current_price - .saturating_mul(U96F32::saturating_from_num(alpha)) - .saturating_to_num::() - .into(); - - // Ensure tao_equivalent is above DefaultMinStake - ensure!( - tao_equivalent >= DefaultMinStake::::get(), - Error::::AmountTooLow - ); - // Step 3: Update StakingHotkeys if the hotkey's total alpha, across all subnets, is zero // TODO: fix. // if Self::get_stake(hotkey, coldkey) == 0 { diff --git a/pallets/subtensor/src/tests/locks.rs b/pallets/subtensor/src/tests/locks.rs index 0f160213c9..3cce8ee2dd 100644 --- a/pallets/subtensor/src/tests/locks.rs +++ b/pallets/subtensor/src/tests/locks.rs @@ -1852,6 +1852,64 @@ fn test_transfer_stake_lock_aware_transfers_only_unlocked_stake() { }); } +#[test] +fn test_transfer_stake_lock_aware_sub_minimum_cap_does_not_mutate_internal_call() { + new_test_ext(1).execute_with(|| { + let coldkey_sender = U256::from(1); + let coldkey_receiver = U256::from(5); + let hotkey = U256::from(2); + let netuid = setup_subnet_with_stake(coldkey_sender, hotkey, 100_000_000_000); + DecayingLock::::insert(coldkey_receiver, netuid, false); + + let total = get_alpha(&hotkey, &coldkey_sender, netuid); + let tiny_lock = AlphaBalance::from(1u64); + assert_ok!(SubtensorModule::do_lock_stake( + &coldkey_sender, + netuid, + &hotkey, + tiny_lock, + )); + + let sender_alpha_before = get_alpha(&hotkey, &coldkey_sender, netuid); + let receiver_alpha_before = get_alpha(&hotkey, &coldkey_receiver, netuid); + let sender_lock_before = + Lock::::get((coldkey_sender, netuid, hotkey)).expect("sender lock should exist"); + let hotkey_lock_before = + HotkeyLock::::get(netuid, hotkey).expect("hotkey lock should exist"); + + assert_noop!( + SubtensorModule::do_transfer_stake_lock_aware( + RuntimeOrigin::signed(coldkey_sender), + coldkey_receiver, + hotkey, + netuid, + netuid, + total, + true, + ), + Error::::AmountTooLow + ); + + assert_eq!( + get_alpha(&hotkey, &coldkey_sender, netuid), + sender_alpha_before + ); + assert_eq!( + get_alpha(&hotkey, &coldkey_receiver, netuid), + receiver_alpha_before + ); + assert_eq!( + Lock::::get((coldkey_sender, netuid, hotkey)), + Some(sender_lock_before) + ); + assert!(Lock::::get((coldkey_receiver, netuid, hotkey)).is_none()); + assert_eq!( + HotkeyLock::::get(netuid, hotkey), + Some(hotkey_lock_before) + ); + }); +} + #[test] fn test_transfer_stake_lock_aware_owner_lock_moves_all_lock_and_conviction() { new_test_ext(1).execute_with(|| { From 3e46a8fcf2f6aceec2e219f690890ddb958e1b8f Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Fri, 5 Jun 2026 12:01:55 -0400 Subject: [PATCH 4/4] Address AI reviewer comment --- pallets/subtensor/src/macros/dispatches.rs | 8 +++----- pallets/subtensor/src/staking/move_stake.rs | 15 +++++++-------- pallets/subtensor/src/tests/locks.rs | 4 ---- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index 64bab6941b..9f32a249df 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -1558,7 +1558,7 @@ mod dispatches { ) } - /// Transfers locked or unlocked stake from one coldkey to another, optionally across subnets, + /// Transfers locked or unlocked stake from one coldkey to another, within one subnet, /// while keeping the same hotkey. /// /// If `locked` is true, the call transfers at most the currently locked alpha and moves @@ -1570,8 +1570,7 @@ mod dispatches { origin: OriginFor, destination_coldkey: T::AccountId, hotkey: T::AccountId, - origin_netuid: NetUid, - destination_netuid: NetUid, + netuid: NetUid, alpha_amount: AlphaBalance, locked: bool, ) -> DispatchResult { @@ -1579,8 +1578,7 @@ mod dispatches { origin, destination_coldkey, hotkey, - origin_netuid, - destination_netuid, + netuid, alpha_amount, locked, ) diff --git a/pallets/subtensor/src/staking/move_stake.rs b/pallets/subtensor/src/staking/move_stake.rs index 1ce2506377..7ee969f9d8 100644 --- a/pallets/subtensor/src/staking/move_stake.rs +++ b/pallets/subtensor/src/staking/move_stake.rs @@ -161,7 +161,7 @@ impl Pallet { Ok(()) } - /// Transfers either locked or unlocked stake from one coldkey to another. + /// Transfers either locked or unlocked stake from one coldkey to another within one subnet. /// /// This follows `do_transfer_stake`, but caps the requested amount to the /// selected lock bucket. If `locked` is true, only locked alpha can move and @@ -171,8 +171,7 @@ impl Pallet { origin: OriginFor, destination_coldkey: T::AccountId, hotkey: T::AccountId, - origin_netuid: NetUid, - destination_netuid: NetUid, + netuid: NetUid, alpha_amount: AlphaBalance, locked: bool, ) -> dispatch::DispatchResult { @@ -183,8 +182,8 @@ impl Pallet { &destination_coldkey, &hotkey, &hotkey, - origin_netuid, - destination_netuid, + netuid, + netuid, alpha_amount, None, None, @@ -193,14 +192,14 @@ impl Pallet { )?; log::debug!( - "StakeTransferred(origin_coldkey: {coldkey:?}, destination_coldkey: {destination_coldkey:?}, hotkey: {hotkey:?}, origin_netuid: {origin_netuid:?}, destination_netuid: {destination_netuid:?}, amount: {tao_moved:?})" + "StakeTransferred(origin_coldkey: {coldkey:?}, destination_coldkey: {destination_coldkey:?}, hotkey: {hotkey:?}, netuid: {netuid:?}, amount: {tao_moved:?})" ); Self::deposit_event(Event::StakeTransferred( coldkey, destination_coldkey, hotkey, - origin_netuid, - destination_netuid, + netuid, + netuid, tao_moved, )); diff --git a/pallets/subtensor/src/tests/locks.rs b/pallets/subtensor/src/tests/locks.rs index 7d9f77b51a..eba1e329f6 100644 --- a/pallets/subtensor/src/tests/locks.rs +++ b/pallets/subtensor/src/tests/locks.rs @@ -1764,7 +1764,6 @@ fn test_transfer_stake_lock_aware_transfers_only_locked_stake() { coldkey_receiver, hotkey, netuid, - netuid, total, true, )); @@ -1820,7 +1819,6 @@ fn test_transfer_stake_lock_aware_transfers_only_unlocked_stake() { coldkey_receiver, hotkey, netuid, - netuid, total, false, )); @@ -1881,7 +1879,6 @@ fn test_transfer_stake_lock_aware_sub_minimum_cap_does_not_mutate_internal_call( coldkey_receiver, hotkey, netuid, - netuid, total, true, ), @@ -1964,7 +1961,6 @@ fn test_transfer_stake_lock_aware_owner_lock_moves_all_lock_and_conviction() { coldkey2, hotkey1, netuid, - netuid, total, true, ));