Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 0 additions & 130 deletions pallets/admin-utils/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -931,136 +931,6 @@ mod sudo_set_nominator_min_required_stake {
);
});
}

#[test]
fn clears_staker_nominations_below_min() {
new_test_ext().execute_with(|| {
System::set_block_number(1);

// Create accounts.
let netuid = 1;
let hot1 = U256::from(1);
let hot2 = U256::from(2);
let cold1 = U256::from(3);
let cold2 = U256::from(4);

// SubtensorModule::set_target_stakes_per_interval(10);
// Register network.
add_network(netuid, 0);

// Register hot1.
register_ok_neuron(netuid, hot1, cold1, 0);
assert_eq!(SubtensorModule::get_owning_coldkey_for_hotkey(&hot1), cold1);

// Register hot2.
register_ok_neuron(netuid, hot2, cold2, 0);
assert_eq!(SubtensorModule::get_owning_coldkey_for_hotkey(&hot2), cold2);

// Add stake cold1 --> hot1 (non delegation.)
SubtensorModule::add_balance_to_coldkey_account(&cold1, 5);
assert_ok!(SubtensorModule::add_stake(
<<Test as Config>::RuntimeOrigin>::signed(cold1),
hot1,
netuid,
1
));
assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot1, &cold1, netuid),
1
);
assert_eq!(Balances::free_balance(cold1), 4);

// Add stake cold2 --> hot1 (is delegation.)
SubtensorModule::add_balance_to_coldkey_account(&cold2, 5);
assert_ok!(SubtensorModule::add_stake(
<<Test as Config>::RuntimeOrigin>::signed(cold2),
hot1,
netuid,
1
));
assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot1, &cold2, netuid),
1
);
assert_eq!(Balances::free_balance(cold2), 4);

// Add stake cold1 --> hot2
SubtensorModule::add_balance_to_coldkey_account(&cold1, 5);
assert_ok!(SubtensorModule::add_stake(
<<Test as Config>::RuntimeOrigin>::signed(cold1),
hot2,
netuid,
1
));
assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot2, &cold1, netuid),
1
);
assert_eq!(Balances::free_balance(cold1), 8);

// Add stake cold2 --> hot2
SubtensorModule::add_balance_to_coldkey_account(&cold2, 5);
assert_ok!(SubtensorModule::add_stake(
<<Test as Config>::RuntimeOrigin>::signed(cold2),
hot2,
netuid,
1
));
assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot2, &cold2, netuid),
1
);
assert_eq!(Balances::free_balance(cold2), 8);

// Set min stake to 0 (noop)
assert_ok!(AdminUtils::sudo_set_nominator_min_required_stake(
<<Test as Config>::RuntimeOrigin>::root(),
0u64
));
assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot1, &cold1, netuid),
1
);
assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot2, &cold1, netuid),
1
);
assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot1, &cold2, netuid),
1
);
assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot2, &cold2, netuid),
1
);

// Set min nomination to 10: should clear (cold2, hot1) and (cold1, hot2).
assert_ok!(AdminUtils::sudo_set_nominator_min_required_stake(
<<Test as Config>::RuntimeOrigin>::root(),
10u64
));
assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot1, &cold1, netuid),
1
);
assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot2, &cold1, netuid),
0
);
assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot1, &cold2, netuid),
0
);
assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hot2, &cold2, netuid),
1
);

// Balances have been added back into accounts.
assert_eq!(Balances::free_balance(cold1), 9);
assert_eq!(Balances::free_balance(cold2), 9);
});
}
}

#[test]
Expand Down
7 changes: 7 additions & 0 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,13 @@ pub mod pallet {
1_000_000_000_000
}

#[pallet::type_value]
/// Default minimum stake.
/// 2M rao matches $1 at $500/TAO
pub fn DefaultMinStake<T: Config>() -> u64 {
2_000_000
}

#[pallet::type_value]
/// Default unicode vector for tau symbol.
pub fn DefaultUnicodeVecU8<T: Config>() -> Vec<u8> {
Expand Down
41 changes: 41 additions & 0 deletions pallets/subtensor/src/macros/dispatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1555,5 +1555,46 @@ mod dispatches {
pub fn unstake_all_alpha(origin: OriginFor<T>, hotkey: T::AccountId) -> DispatchResult {
Self::do_unstake_all_alpha(origin, hotkey)
}

/// ---- The implementation for the extrinsic move_stake: Moves specified amount of stake from a hotkey to another across subnets.
///
/// # Args:
/// * `origin` - (<T as frame_system::Config>::Origin):
/// - The signature of the caller's coldkey.
///
/// * `origin_hotkey` (T::AccountId):
/// - The hotkey account to move stake from.
///
/// * `destination_hotkey` (T::AccountId):
/// - The hotkey account to move stake to.
///
/// * `origin_netuid` (T::AccountId):
/// - The subnet ID to move stake from.
///
/// * `destination_netuid` (T::AccountId):
/// - The subnet ID to move stake to.
///
/// * `alpha_amount` (T::AccountId):
/// - The alpha stake amount to move.
///
#[pallet::call_index(85)]
#[pallet::weight((Weight::from_parts(3_000_000, 0).saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No))]
pub fn move_stake(
origin: T::RuntimeOrigin,
origin_hotkey: T::AccountId,
destination_hotkey: T::AccountId,
origin_netuid: u16,
destination_netuid: u16,
alpha_amount: u64,
) -> DispatchResult {
Self::do_move_stake(
origin,
origin_hotkey,
destination_hotkey,
origin_netuid,
destination_netuid,
alpha_amount,
)
}
}
}
2 changes: 2 additions & 0 deletions pallets/subtensor/src/macros/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,5 +183,7 @@ mod errors {
InputLengthsUnequal,
/// A transactor exceeded the rate limit for setting weights.
CommittingWeightsTooFast,
/// Stake amount is too low.
AmountTooLow,
}
}
2 changes: 2 additions & 0 deletions pallets/subtensor/src/macros/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ mod events {
StakeAdded(T::AccountId, T::AccountId, u64, u64, u16),
/// stake has been removed from the hotkey staking account onto the coldkey account.
StakeRemoved(T::AccountId, T::AccountId, u64, u64, u16),
/// stake has been moved from origin (hotkey, subnet ID) to destination (hotkey, subnet ID) of this amount (in TAO).
StakeMoved(T::AccountId, T::AccountId, u16, T::AccountId, u16, u64),
/// a caller successfully sets their weights on a subnetwork.
WeightsSet(u16, u16),
/// a new neuron account has been registered to the chain.
Expand Down
7 changes: 7 additions & 0 deletions pallets/subtensor/src/staking/add_stake.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::*;
use sp_core::Get;

impl<T: Config> Pallet<T> {
/// ---- The implementation for the extrinsic add_stake: Adds stake to a hotkey account.
Expand Down Expand Up @@ -61,6 +62,12 @@ impl<T: Config> Pallet<T> {
Error::<T>::HotKeyAccountNotExists
);

// Ensure stake_to_be_added is at least DefaultMinStake
ensure!(
stake_to_be_added >= DefaultMinStake::<T>::get(),
Error::<T>::AmountTooLow
);

// 5. Ensure the remove operation from the coldkey is a success.
let tao_staked: u64 =
Self::remove_balance_from_coldkey_account(&coldkey, stake_to_be_added)?;
Expand Down
1 change: 1 addition & 0 deletions pallets/subtensor/src/staking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod add_stake;
pub mod decrease_take;
pub mod helpers;
pub mod increase_take;
pub mod move_stake;
pub mod remove_stake;
pub mod set_children;
pub mod stake_utils;
15 changes: 13 additions & 2 deletions pallets/subtensor/src/staking/move_stake.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::*;
// use substrate_fixed::types::I96F32;
use sp_core::Get;

impl<T: Config> Pallet<T> {
/// Moves stake from one hotkey to another across subnets.
Expand Down Expand Up @@ -57,7 +57,11 @@ impl<T: Config> Pallet<T> {
);

// --- 6. Get the current alpha stake for the origin hotkey-coldkey pair in the origin subnet
let origin_alpha = Self::get_stake_for_hotkey_and_coldkey_on_subnet( &origin_hotkey, &coldkey, origin_netuid );
let origin_alpha = Self::get_stake_for_hotkey_and_coldkey_on_subnet(
&origin_hotkey,
&coldkey,
origin_netuid,
);
ensure!(
alpha_amount <= origin_alpha,
Error::<T>::NotEnoughStakeToWithdraw
Expand All @@ -71,6 +75,12 @@ impl<T: Config> Pallet<T> {
alpha_amount,
);

// Ensure origin_tao is at least DefaultMinStake
ensure!(
origin_tao >= DefaultMinStake::<T>::get(),
Error::<T>::AmountTooLow
);

// --- 8. Stake the resulting TAO into the destination subnet for the destination hotkey
Self::stake_into_subnet(
&destination_hotkey.clone(),
Expand All @@ -94,6 +104,7 @@ impl<T: Config> Pallet<T> {
origin_netuid,
destination_hotkey,
destination_netuid,
origin_tao,
));

// -- 10. Ok and return.
Expand Down
70 changes: 40 additions & 30 deletions pallets/subtensor/src/tests/children.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3058,28 +3058,34 @@ fn test_childkey_multiple_parents_emission() {

// Register neurons and add initial stakes
let initial_stakes: Vec<(bool, U256, U256, u64)> = vec![
(false, coldkey_parent1, parent1, 200_000),
(true, coldkey_parent2, parent2, 150_000),
(true, coldkey_child, child, 20_000),
(true, coldkey_weight_setter, weight_setter, 100_000),
(false, coldkey_parent1, parent1, 200_000_000),
(true, coldkey_parent2, parent2, 150_000_000),
(true, coldkey_child, child, 20_000_000),
(true, coldkey_weight_setter, weight_setter, 100_000_000),
];

for (register, coldkey, hotkey, stake) in initial_stakes.iter() {
SubtensorModule::add_balance_to_coldkey_account(coldkey, *stake);
if *register {
// Register a neuron
register_ok_neuron(netuid, *hotkey, *coldkey, 0);
} else {
// Just create hotkey account
SubtensorModule::create_account_if_non_existent(coldkey, hotkey);
}
assert_ok!(SubtensorModule::add_stake(
RuntimeOrigin::signed(*coldkey),
*hotkey,
netuid,
*stake
));
}
let initial_actual_stakes: Vec<u64> = initial_stakes
.iter()
.map(|(register, coldkey, hotkey, stake)| {
SubtensorModule::add_balance_to_coldkey_account(coldkey, *stake);
if *register {
// Register a neuron
register_ok_neuron(netuid, *hotkey, *coldkey, 0);
} else {
// Just create hotkey account
SubtensorModule::create_account_if_non_existent(coldkey, hotkey);
}
assert_ok!(SubtensorModule::add_stake(
RuntimeOrigin::signed(*coldkey),
*hotkey,
netuid,
*stake
));

// Return actual stake
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid)
})
.collect();

SubtensorModule::set_weights_set_rate_limit(netuid, 0);
step_block(2);
Expand Down Expand Up @@ -3152,23 +3158,26 @@ fn test_childkey_multiple_parents_emission() {
);

assert!(
parent1_stake > 200_000,
parent1_stake > initial_actual_stakes[0],
"Parent1 should have received emission"
);
assert!(
parent2_stake > 150_000,
parent2_stake > initial_actual_stakes[1],
"Parent2 should have received emission"
);
assert!(child_stake > 20_000, "Child should have received emission");
assert!(
weight_setter_stake > 100_000,
child_stake > initial_actual_stakes[2],
"Child should have received emission"
);
assert!(
weight_setter_stake > initial_actual_stakes[3],
"Weight setter should have received emission"
);

// Check individual stake increases
let parent1_stake_increase = parent1_stake - 200_000;
let parent2_stake_increase = parent2_stake - 150_000;
let child_stake_increase = child_stake - 20_000;
let parent1_stake_increase = parent1_stake - initial_actual_stakes[0];
let parent2_stake_increase = parent2_stake - initial_actual_stakes[1];
let child_stake_increase = child_stake - initial_actual_stakes[2];

log::debug!(
"Stake increases - Parent1: {}, Parent2: {}, Child: {}",
Expand All @@ -3192,12 +3201,13 @@ fn test_childkey_multiple_parents_emission() {
);

// Check that the total stake has increased by the emission amount
// Allow 1% slippage
let total_stake = parent1_stake + parent2_stake + child_stake + weight_setter_stake;
let initial_total_stake: u64 = initial_stakes.iter().map(|(_, _, _, stake)| stake).sum();
let initial_total_stake: u64 = initial_actual_stakes.iter().sum::<u64>();
assert_abs_diff_eq!(
total_stake,
initial_total_stake + total_emission - 2,
epsilon = total_emission / 10_000
initial_total_stake + total_emission,
epsilon = total_emission / 100
);
});
}
Expand Down
Loading
Loading