Skip to content

Commit 373f4c9

Browse files
authored
Merge pull request #1308 from opentensor/devnet-ready
devnet deploy 2/16/2025
2 parents bb26e74 + dbbfb61 commit 373f4c9

File tree

4 files changed

+332
-7
lines changed

4 files changed

+332
-7
lines changed

pallets/subtensor/src/staking/stake_utils.rs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,15 @@ impl<T: Config> Pallet<T> {
549549
alpha_share_pool.update_value_for_one(coldkey, amount as i64);
550550
}
551551

552+
pub fn try_increase_stake_for_hotkey_and_coldkey_on_subnet(
553+
hotkey: &T::AccountId,
554+
netuid: u16,
555+
amount: u64,
556+
) -> bool {
557+
let mut alpha_share_pool = Self::get_alpha_share_pool(hotkey.clone(), netuid);
558+
alpha_share_pool.sim_update_value_for_one(amount as i64)
559+
}
560+
552561
/// Sell shares in the hotkey on a given subnet
553562
///
554563
/// The function updates share totals given current prices.
@@ -877,11 +886,18 @@ impl<T: Config> Pallet<T> {
877886
Error::<T>::HotKeyAccountNotExists
878887
);
879888

889+
let expected_alpha = Self::sim_swap_tao_for_alpha(netuid, stake_to_be_added);
890+
880891
// Ensure that we have adequate liquidity
881-
ensure!(
882-
Self::sim_swap_tao_for_alpha(netuid, stake_to_be_added).is_some(),
883-
Error::<T>::InsufficientLiquidity
892+
ensure!(expected_alpha.is_some(), Error::<T>::InsufficientLiquidity);
893+
894+
// Ensure hotkey pool is precise enough
895+
let try_stake_result = Self::try_increase_stake_for_hotkey_and_coldkey_on_subnet(
896+
hotkey,
897+
netuid,
898+
expected_alpha.unwrap_or(0),
884899
);
900+
ensure!(try_stake_result, Error::<T>::InsufficientLiquidity);
885901

886902
Ok(())
887903
}
@@ -937,7 +953,7 @@ impl<T: Config> Pallet<T> {
937953
origin_coldkey: &T::AccountId,
938954
_destination_coldkey: &T::AccountId,
939955
origin_hotkey: &T::AccountId,
940-
_destination_hotkey: &T::AccountId,
956+
destination_hotkey: &T::AccountId,
941957
origin_netuid: u16,
942958
destination_netuid: u16,
943959
alpha_amount: u64,
@@ -975,7 +991,8 @@ impl<T: Config> Pallet<T> {
975991
);
976992

977993
// Ensure that the stake amount to be removed is above the minimum in tao equivalent.
978-
if let Some(tao_equivalent) = Self::sim_swap_alpha_for_tao(origin_netuid, alpha_amount) {
994+
let tao_equivalent_result = Self::sim_swap_alpha_for_tao(origin_netuid, alpha_amount);
995+
if let Some(tao_equivalent) = tao_equivalent_result {
979996
ensure!(
980997
tao_equivalent > DefaultMinStake::<T>::get(),
981998
Error::<T>::AmountTooLow
@@ -992,6 +1009,18 @@ impl<T: Config> Pallet<T> {
9921009
}
9931010
}
9941011

1012+
let expected_alpha =
1013+
Self::sim_swap_tao_for_alpha(destination_netuid, tao_equivalent_result.unwrap_or(0))
1014+
.unwrap_or(0);
1015+
1016+
// Ensure that the amount being staked to the new hotkey is precise enough
1017+
let try_stake_result = Self::try_increase_stake_for_hotkey_and_coldkey_on_subnet(
1018+
destination_hotkey,
1019+
destination_netuid,
1020+
expected_alpha,
1021+
);
1022+
ensure!(try_stake_result, Error::<T>::InsufficientLiquidity);
1023+
9951024
if check_transfer_toggle {
9961025
// Ensure transfer is toggled.
9971026
ensure!(

pallets/subtensor/src/tests/staking.rs

Lines changed: 274 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use approx::assert_abs_diff_eq;
1010
use frame_support::dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays};
1111
use frame_support::sp_runtime::DispatchError;
1212
use sp_core::{Get, H256, U256};
13-
use substrate_fixed::types::{I96F32, U96F32};
13+
use substrate_fixed::types::{I96F32, U64F64, U96F32};
1414

1515
/***********************************************************
1616
staking::add_stake() tests
@@ -3495,3 +3495,276 @@ fn test_remove_stake_limit_fill_or_kill() {
34953495
),);
34963496
});
34973497
}
3498+
3499+
// #[test]
3500+
// fn test_add_stake_specific() {
3501+
// new_test_ext(1).execute_with(|| {
3502+
// let sn_owner_coldkey = U256::from(55453);
3503+
3504+
// let hotkey_account_id = U256::from(533453);
3505+
// let coldkey_account_id = U256::from(55454);
3506+
// let hotkey_owner_account_id = U256::from(533454);
3507+
3508+
// let existing_shares: U64F64 =
3509+
// U64F64::from_num(161_986_254).saturating_div(U64F64::from_num(u64::MAX));
3510+
// let existing_stake = 36_711_495_953;
3511+
// let amount_added = 1_274_280_132;
3512+
3513+
// //add network
3514+
// let netuid: u16 = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey);
3515+
3516+
// // Register hotkey on netuid
3517+
// register_ok_neuron(netuid, hotkey_account_id, hotkey_owner_account_id, 0);
3518+
// // Check we have zero staked
3519+
// assert_eq!(
3520+
// SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id),
3521+
// 0
3522+
// );
3523+
3524+
// // Set a hotkey pool for the hotkey
3525+
// let mut hotkey_pool = SubtensorModule::get_alpha_share_pool(hotkey_account_id, netuid);
3526+
// hotkey_pool.update_value_for_one(&hotkey_owner_account_id, 1234); // Doesn't matter, will be overridden
3527+
3528+
// // Adjust the total hotkey stake and shares to match the existing values
3529+
// TotalHotkeyShares::<Test>::insert(hotkey_account_id, netuid, existing_shares);
3530+
// TotalHotkeyAlpha::<Test>::insert(hotkey_account_id, netuid, existing_stake);
3531+
3532+
// // Make the hotkey a delegate
3533+
// Delegates::<Test>::insert(hotkey_account_id, 0);
3534+
3535+
// // Add stake as new hotkey
3536+
// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
3537+
// &hotkey_account_id,
3538+
// &coldkey_account_id,
3539+
// netuid,
3540+
// amount_added,
3541+
// );
3542+
3543+
// // Check the stake and shares are correct
3544+
// assert!(Alpha::<Test>::get((&hotkey_account_id, &coldkey_account_id, netuid)) > 0);
3545+
// assert_eq!(
3546+
// TotalHotkeyAlpha::<Test>::get(hotkey_account_id, netuid),
3547+
// amount_added + existing_stake
3548+
// );
3549+
// });
3550+
// }
3551+
3552+
// #[test]
3553+
// // RUST_LOG=info cargo test --package pallet-subtensor --lib -- tests::staking::test_add_stake_specific_stake_into_subnet --exact --show-output
3554+
// fn test_add_stake_specific_stake_into_subnet() {
3555+
// new_test_ext(1).execute_with(|| {
3556+
// let sn_owner_coldkey = U256::from(55453);
3557+
3558+
// let hotkey_account_id = U256::from(533453);
3559+
// let coldkey_account_id = U256::from(55454);
3560+
// let hotkey_owner_account_id = U256::from(533454);
3561+
3562+
// let existing_shares: U64F64 =
3563+
// U64F64::from_num(161_986_254).saturating_div(U64F64::from_num(u64::MAX));
3564+
// let existing_stake = 36_711_495_953;
3565+
3566+
// let tao_in = 2_409_892_148_947;
3567+
// let alpha_in = 15_358_708_513_716;
3568+
3569+
// let tao_staked = 200_000_000;
3570+
// let fee = DefaultStakingFee::<Test>::get();
3571+
3572+
// //add network
3573+
// let netuid: u16 = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey);
3574+
3575+
// // Register hotkey on netuid
3576+
// register_ok_neuron(netuid, hotkey_account_id, hotkey_owner_account_id, 0);
3577+
// // Check we have zero staked
3578+
// assert_eq!(
3579+
// SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id),
3580+
// 0
3581+
// );
3582+
3583+
// // Set a hotkey pool for the hotkey
3584+
// let mut hotkey_pool = SubtensorModule::get_alpha_share_pool(hotkey_account_id, netuid);
3585+
// hotkey_pool.update_value_for_one(&hotkey_owner_account_id, 1234); // Doesn't matter, will be overridden
3586+
3587+
// // Adjust the total hotkey stake and shares to match the existing values
3588+
// TotalHotkeyShares::<Test>::insert(hotkey_account_id, netuid, existing_shares);
3589+
// TotalHotkeyAlpha::<Test>::insert(hotkey_account_id, netuid, existing_stake);
3590+
3591+
// // Make the hotkey a delegate
3592+
// Delegates::<Test>::insert(hotkey_account_id, 0);
3593+
3594+
// // Setup Subnet pool
3595+
// SubnetAlphaIn::<Test>::insert(netuid, alpha_in);
3596+
// SubnetTAO::<Test>::insert(netuid, tao_in);
3597+
3598+
// // Add stake as new hotkey
3599+
// SubtensorModule::stake_into_subnet(
3600+
// &hotkey_account_id,
3601+
// &coldkey_account_id,
3602+
// netuid,
3603+
// tao_staked,
3604+
// fee,
3605+
// );
3606+
3607+
// // Check the stake and shares are correct
3608+
// assert!(Alpha::<Test>::get((&hotkey_account_id, &coldkey_account_id, netuid)) > 0);
3609+
// log::info!(
3610+
// "Alpha: {}",
3611+
// Alpha::<Test>::get((&hotkey_account_id, &coldkey_account_id, netuid))
3612+
// );
3613+
// log::info!(
3614+
// "TotalHotkeyAlpha: {}",
3615+
// TotalHotkeyAlpha::<Test>::get(hotkey_account_id, netuid)
3616+
// );
3617+
// });
3618+
// }
3619+
3620+
#[test]
3621+
// RUST_LOG=info cargo test --package pallet-subtensor --lib -- tests::staking::test_add_stake_specific_stake_into_subnet_fail --exact --show-output
3622+
fn test_add_stake_specific_stake_into_subnet_fail() {
3623+
new_test_ext(1).execute_with(|| {
3624+
let sn_owner_coldkey = U256::from(55453);
3625+
3626+
let hotkey_account_id = U256::from(533453);
3627+
let coldkey_account_id = U256::from(55454);
3628+
let hotkey_owner_account_id = U256::from(533454);
3629+
3630+
let existing_shares: U64F64 =
3631+
U64F64::from_num(161_986_254).saturating_div(U64F64::from_num(u64::MAX));
3632+
let existing_stake = 36_711_495_953;
3633+
3634+
let tao_in = 2_409_892_148_947;
3635+
let alpha_in = 15_358_708_513_716;
3636+
3637+
let tao_staked = 200_000_000;
3638+
3639+
//add network
3640+
let netuid: u16 = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey);
3641+
3642+
// Register hotkey on netuid
3643+
register_ok_neuron(netuid, hotkey_account_id, hotkey_owner_account_id, 0);
3644+
// Check we have zero staked
3645+
assert_eq!(
3646+
SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id),
3647+
0
3648+
);
3649+
3650+
// Set a hotkey pool for the hotkey
3651+
let mut hotkey_pool = SubtensorModule::get_alpha_share_pool(hotkey_account_id, netuid);
3652+
hotkey_pool.update_value_for_one(&hotkey_owner_account_id, 1234); // Doesn't matter, will be overridden
3653+
3654+
// Adjust the total hotkey stake and shares to match the existing values
3655+
TotalHotkeyShares::<Test>::insert(hotkey_account_id, netuid, existing_shares);
3656+
TotalHotkeyAlpha::<Test>::insert(hotkey_account_id, netuid, existing_stake);
3657+
3658+
// Make the hotkey a delegate
3659+
Delegates::<Test>::insert(hotkey_account_id, 0);
3660+
3661+
// Setup Subnet pool
3662+
SubnetAlphaIn::<Test>::insert(netuid, alpha_in);
3663+
SubnetTAO::<Test>::insert(netuid, tao_in);
3664+
3665+
// Give TAO balance to coldkey
3666+
SubtensorModule::add_balance_to_coldkey_account(
3667+
&coldkey_account_id,
3668+
tao_staked + 1_000_000_000,
3669+
);
3670+
3671+
// Add stake as new hotkey
3672+
assert_noop!(
3673+
SubtensorModule::add_stake(
3674+
RuntimeOrigin::signed(coldkey_account_id),
3675+
hotkey_account_id,
3676+
netuid,
3677+
tao_staked,
3678+
),
3679+
Error::<Test>::InsufficientLiquidity
3680+
);
3681+
});
3682+
}
3683+
3684+
#[test]
3685+
// RUST_LOG=info cargo test --package pallet-subtensor --lib -- tests::staking::test_move_stake_specific_stake_into_subnet_fail --exact --show-output
3686+
fn test_move_stake_specific_stake_into_subnet_fail() {
3687+
new_test_ext(1).execute_with(|| {
3688+
let sn_owner_coldkey = U256::from(55453);
3689+
3690+
let hotkey_account_id = U256::from(533453);
3691+
let coldkey_account_id = U256::from(55454);
3692+
let hotkey_owner_account_id = U256::from(533454);
3693+
3694+
let existing_shares: U64F64 =
3695+
U64F64::from_num(161_986_254).saturating_div(U64F64::from_num(u64::MAX));
3696+
let existing_stake = 36_711_495_953;
3697+
3698+
let tao_in = 2_409_892_148_947;
3699+
let alpha_in = 15_358_708_513_716;
3700+
3701+
let tao_staked = 200_000_000;
3702+
3703+
//add network
3704+
let netuid: u16 = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey);
3705+
3706+
let origin_netuid: u16 = add_dynamic_network(&sn_owner_coldkey, &sn_owner_coldkey);
3707+
3708+
// Register hotkey on netuid
3709+
register_ok_neuron(netuid, hotkey_account_id, hotkey_owner_account_id, 0);
3710+
// Register hotkey on origin netuid
3711+
register_ok_neuron(origin_netuid, hotkey_account_id, hotkey_owner_account_id, 0);
3712+
3713+
// Check we have zero staked
3714+
assert_eq!(
3715+
SubtensorModule::get_total_stake_for_hotkey(&hotkey_account_id),
3716+
0
3717+
);
3718+
3719+
// Set a hotkey pool for the hotkey on destination subnet
3720+
let mut hotkey_pool = SubtensorModule::get_alpha_share_pool(hotkey_account_id, netuid);
3721+
hotkey_pool.update_value_for_one(&hotkey_owner_account_id, 1234); // Doesn't matter, will be overridden
3722+
3723+
// Adjust the total hotkey stake and shares to match the existing values
3724+
TotalHotkeyShares::<Test>::insert(hotkey_account_id, netuid, existing_shares);
3725+
TotalHotkeyAlpha::<Test>::insert(hotkey_account_id, netuid, existing_stake);
3726+
3727+
// Make the hotkey a delegate
3728+
Delegates::<Test>::insert(hotkey_account_id, 0);
3729+
3730+
// Setup Subnet pool
3731+
SubnetAlphaIn::<Test>::insert(netuid, alpha_in);
3732+
SubnetTAO::<Test>::insert(netuid, tao_in);
3733+
3734+
// Give TAO balance to coldkey
3735+
SubtensorModule::add_balance_to_coldkey_account(
3736+
&coldkey_account_id,
3737+
tao_staked + 1_000_000_000,
3738+
);
3739+
3740+
// Setup Subnet pool for origin netuid
3741+
SubnetAlphaIn::<Test>::insert(origin_netuid, alpha_in + 10_000_000);
3742+
SubnetTAO::<Test>::insert(origin_netuid, tao_in + 10_000_000);
3743+
3744+
// Add stake as new hotkey
3745+
assert_ok!(SubtensorModule::add_stake(
3746+
RuntimeOrigin::signed(coldkey_account_id),
3747+
hotkey_account_id,
3748+
origin_netuid,
3749+
tao_staked,
3750+
),);
3751+
let alpha_to_move = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
3752+
&hotkey_account_id,
3753+
&coldkey_account_id,
3754+
origin_netuid,
3755+
);
3756+
3757+
// Move stake to destination subnet
3758+
assert_noop!(
3759+
SubtensorModule::move_stake(
3760+
RuntimeOrigin::signed(coldkey_account_id),
3761+
hotkey_account_id,
3762+
hotkey_account_id,
3763+
origin_netuid,
3764+
netuid,
3765+
alpha_to_move,
3766+
),
3767+
Error::<Test>::InsufficientLiquidity
3768+
);
3769+
});
3770+
}

primitives/share-pool/src/lib.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,29 @@ where
7575
});
7676
}
7777

78+
pub fn sim_update_value_for_one(&mut self, update: i64) -> bool {
79+
let shared_value: U64F64 = self.state_ops.get_shared_value();
80+
let denominator: U64F64 = self.state_ops.get_denominator();
81+
82+
// Then, update this key's share
83+
if denominator == 0 {
84+
true
85+
} else {
86+
// There are already keys in the pool, set or update this key
87+
let value_per_share: I64F64 = I64F64::saturating_from_num(
88+
shared_value
89+
.checked_div(denominator) // denominator is never 0 here
90+
.unwrap_or(U64F64::saturating_from_num(0)),
91+
);
92+
93+
let shares_per_update: I64F64 = I64F64::saturating_from_num(update)
94+
.checked_div(value_per_share)
95+
.unwrap_or(I64F64::saturating_from_num(0));
96+
97+
shares_per_update != 0
98+
}
99+
}
100+
78101
/// Update the value associated with an item identified by the Key
79102
pub fn update_value_for_one(&mut self, key: &K, update: i64) {
80103
let shared_value: U64F64 = self.state_ops.get_shared_value();

0 commit comments

Comments
 (0)