From 253d8073f6f52a4b102b6c87c33bcf30bd68ecbf Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Fri, 30 May 2025 13:35:53 -0500 Subject: [PATCH 1/9] impl --- pallets/subtensor/src/lib.rs | 2 +- pallets/subtensor/src/staking/stake_utils.rs | 6 ++++++ runtime/src/lib.rs | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index f4f511e74a..5a6decd597 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -1785,7 +1785,7 @@ pub mod pallet { } /// Ensure subtoken enalbed - pub fn ensure_subtoken_enabled(subnet: u16) -> DispatchResult { + pub fn ensure_subtoken_enabled(subnet: u16) -> Result<(), Error> { ensure!( SubtokenEnabled::::get(subnet), Error::::SubtokenDisabled diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index 058622177e..2f9704a6b9 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -911,6 +911,9 @@ impl Pallet { // Ensure that the subnet exists. ensure!(Self::if_subnet_exist(netuid), Error::::SubnetNotExists); + // Ensure that the subnet is enabled. + Self::ensure_subtoken_enabled(netuid)?; + // Get the minimum balance (and amount) that satisfies the transaction let min_amount = DefaultMinStake::::get().saturating_add(DefaultStakingFee::::get()); @@ -964,6 +967,9 @@ impl Pallet { // Ensure that the subnet exists. ensure!(Self::if_subnet_exist(netuid), Error::::SubnetNotExists); + // Ensure that the subnet is enabled. + Self::ensure_subtoken_enabled(netuid)?; + // Ensure that the stake amount to be removed is above the minimum in tao equivalent. if let Some(tao_equivalent) = Self::sim_swap_alpha_for_tao(netuid, alpha_unstaked) { ensure!( diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 0b64ee3cde..9bf932b298 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -209,7 +209,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 273, + spec_version: 274, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From e43afcd6fdacb15f4925f2c850a4caa7e0d093fa Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Fri, 30 May 2025 13:35:58 -0500 Subject: [PATCH 2/9] tests --- pallets/subtensor/src/tests/subnet.rs | 42 +++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/pallets/subtensor/src/tests/subnet.rs b/pallets/subtensor/src/tests/subnet.rs index ec737f8601..8a09b881e1 100644 --- a/pallets/subtensor/src/tests/subnet.rs +++ b/pallets/subtensor/src/tests/subnet.rs @@ -251,6 +251,8 @@ fn test_subtoken_enable_reject_trading_before_enable() { let hotkey_account_2_id: U256 = U256::from(3); let amount = DefaultMinStake::::get() * 10; + let limit_price = 1000; // not important + add_network_disable_subtoken(netuid, 10, 0); add_network_disable_subtoken(netuid2, 10, 0); @@ -273,6 +275,46 @@ fn test_subtoken_enable_reject_trading_before_enable() { Error::::SubtokenDisabled ); + assert_noop!( + SubtensorModule::add_stake_limit( + RuntimeOrigin::signed(coldkey_account_id), + hotkey_account_id, + netuid, + amount, + limit_price, + false + ), + Error::::SubtokenDisabled + ); + + assert_noop!( + SubtensorModule::unstake_all( + RuntimeOrigin::signed(coldkey_account_id), + hotkey_account_id + ), + Error::::SubtokenDisabled + ); + + assert_noop!( + SubtensorModule::unstake_all_alpha( + RuntimeOrigin::signed(coldkey_account_id), + hotkey_account_id + ), + Error::::SubtokenDisabled + ); + + assert_noop!( + SubtensorModule::remove_stake_limit( + RuntimeOrigin::signed(coldkey_account_id), + hotkey_account_id, + netuid, + amount, + limit_price, + false + ), + Error::::SubtokenDisabled + ); + assert_noop!( SubtensorModule::remove_stake( RuntimeOrigin::signed(coldkey_account_id), From ec7303fe4d3bc14f2940f7dee74d79103440d9ab Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Fri, 30 May 2025 13:38:56 -0500 Subject: [PATCH 3/9] update comment --- pallets/subtensor/src/macros/dispatches.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index 650fb50451..5c71c64179 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -551,11 +551,11 @@ mod dispatches { Self::do_increase_take(origin, hotkey, take) } - /// --- Adds stake to a hotkey. The call is made from the - /// coldkey account linked in the hotkey. - /// Only the associated coldkey is allowed to make staking and - /// unstaking requests. This protects the neuron against - /// attacks on its hotkey running in production code. + /// --- Adds stake to a hotkey. The call is made from a coldkey account. + /// This delegates stake to the hotkey. + /// + /// Note: the coldkey account may own the hotkey, in which case they are + /// delegating to themselves. /// /// # Args: /// * 'origin': (Origin): From 423b3ce8e240c9749ed573a4fdaa2f1233fc89af Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Fri, 30 May 2025 13:51:55 -0500 Subject: [PATCH 4/9] fix tests --- pallets/subtensor/src/tests/subnet.rs | 47 ++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/pallets/subtensor/src/tests/subnet.rs b/pallets/subtensor/src/tests/subnet.rs index 8a09b881e1..fdcaa00222 100644 --- a/pallets/subtensor/src/tests/subnet.rs +++ b/pallets/subtensor/src/tests/subnet.rs @@ -251,11 +251,20 @@ fn test_subtoken_enable_reject_trading_before_enable() { let hotkey_account_2_id: U256 = U256::from(3); let amount = DefaultMinStake::::get() * 10; - let limit_price = 1000; // not important + let stake_bal = 10_000_000_000; // 10 Alpha + + let limit_price = 1_000_000_000; // not important add_network_disable_subtoken(netuid, 10, 0); add_network_disable_subtoken(netuid2, 10, 0); + assert!(!SubtokenEnabled::::get(netuid)); + assert!(!SubtokenEnabled::::get(netuid2)); + + // Set liq high enough to not trigger other errors + SubnetTAO::::set(netuid, 20_000_000_000); + SubnetAlphaIn::::set(netuid, 20_000_000_000); + // Register so staking *could* work register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, 0); register_ok_neuron(netuid2, hotkey_account_id, coldkey_account_id, 100); @@ -264,6 +273,14 @@ fn test_subtoken_enable_reject_trading_before_enable() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10_000); + // Give some stake + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey_account_id, + &coldkey_account_id, + netuid, + stake_bal, + ); + // all trading extrinsic should be rejected. assert_noop!( SubtensorModule::add_stake( @@ -287,20 +304,40 @@ fn test_subtoken_enable_reject_trading_before_enable() { Error::::SubtokenDisabled ); - assert_noop!( + // For unstake_all and unstake_all_alpha, the result is Ok, but the + // operation is not performed. + assert_ok!( SubtensorModule::unstake_all( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id ), - Error::::SubtokenDisabled + () + ); + // Check that the stake is still the same + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey_account_id, + &coldkey_account_id, + netuid + ), + stake_bal ); - assert_noop!( + assert_ok!( SubtensorModule::unstake_all_alpha( RuntimeOrigin::signed(coldkey_account_id), hotkey_account_id ), - Error::::SubtokenDisabled + () + ); + // Check that the stake is still the same + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey_account_id, + &coldkey_account_id, + netuid + ), + stake_bal ); assert_noop!( From 619ef06546441cf362aa82664e9f55e021751cd1 Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Tue, 10 Jun 2025 13:06:35 -0400 Subject: [PATCH 5/9] remove subnet exists check on validate_remove_stake --- pallets/subtensor/src/staking/stake_utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index 2f9704a6b9..fe0eff1a05 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -965,7 +965,7 @@ impl Pallet { allow_partial: bool, ) -> Result<(), Error> { // Ensure that the subnet exists. - ensure!(Self::if_subnet_exist(netuid), Error::::SubnetNotExists); + // ensure!(Self::if_subnet_exist(netuid), Error::::SubnetNotExists); // Ensure that the subnet is enabled. Self::ensure_subtoken_enabled(netuid)?; From a69315bc5275818f8d89abf3497a3c3ea019d92b Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Tue, 10 Jun 2025 13:17:04 -0400 Subject: [PATCH 6/9] whoops, wrong line --- pallets/subtensor/src/staking/stake_utils.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index fe0eff1a05..78f9c245db 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -965,10 +965,10 @@ impl Pallet { allow_partial: bool, ) -> Result<(), Error> { // Ensure that the subnet exists. - // ensure!(Self::if_subnet_exist(netuid), Error::::SubnetNotExists); + ensure!(Self::if_subnet_exist(netuid), Error::::SubnetNotExists); // Ensure that the subnet is enabled. - Self::ensure_subtoken_enabled(netuid)?; + // Self::ensure_subtoken_enabled(netuid)?; // Ensure that the stake amount to be removed is above the minimum in tao equivalent. if let Some(tao_equivalent) = Self::sim_swap_alpha_for_tao(netuid, alpha_unstaked) { From 315dedcdfb1bc56263e5f4009a74a1cb3e332202 Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Tue, 10 Jun 2025 13:20:49 -0400 Subject: [PATCH 7/9] fix test --- pallets/subtensor/src/tests/subnet.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/pallets/subtensor/src/tests/subnet.rs b/pallets/subtensor/src/tests/subnet.rs index fdcaa00222..10358076ed 100644 --- a/pallets/subtensor/src/tests/subnet.rs +++ b/pallets/subtensor/src/tests/subnet.rs @@ -340,17 +340,15 @@ fn test_subtoken_enable_reject_trading_before_enable() { stake_bal ); - assert_noop!( - SubtensorModule::remove_stake_limit( - RuntimeOrigin::signed(coldkey_account_id), - hotkey_account_id, - netuid, - amount, - limit_price, - false - ), - Error::::SubtokenDisabled - ); + SubtensorModule::remove_stake_limit( + RuntimeOrigin::signed(coldkey_account_id), + hotkey_account_id, + netuid, + amount, + limit_price, + false, + ) + .unwrap(); assert_noop!( SubtensorModule::remove_stake( From 5f552ae52d5b96ad9ba0cc23e0daabbc43f3e3a0 Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Tue, 10 Jun 2025 13:23:00 -0400 Subject: [PATCH 8/9] clippy --- pallets/subtensor/src/tests/subnet.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pallets/subtensor/src/tests/subnet.rs b/pallets/subtensor/src/tests/subnet.rs index 10358076ed..c95a841736 100644 --- a/pallets/subtensor/src/tests/subnet.rs +++ b/pallets/subtensor/src/tests/subnet.rs @@ -239,7 +239,9 @@ fn test_subtoken_enable() { }); } -// cargo test --package pallet-subtensor --lib -- tests::subnet::test_subtoken_enable_reject_trading_before_enable --exact --show-output +// cargo test --package pallet-subtensor --lib -- +// tests::subnet::test_subtoken_enable_reject_trading_before_enable --exact --show-output +#[allow(clippy::unwrap_used)] #[test] fn test_subtoken_enable_reject_trading_before_enable() { // ensure_subtoken_enabled From cb5db2bba9e2173be58ad76c8712bb8633870625 Mon Sep 17 00:00:00 2001 From: John Reed <87283488+JohnReedV@users.noreply.github.com> Date: Tue, 10 Jun 2025 13:01:38 -0700 Subject: [PATCH 9/9] update reads --- pallets/subtensor/src/macros/dispatches.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index 5d8c78526d..d1a6f36884 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -1786,7 +1786,7 @@ mod dispatches { /// #[pallet::call_index(88)] #[pallet::weight((Weight::from_parts(159_200_000, 0) - .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().reads(14)) .saturating_add(T::DbWeight::get().writes(10)), DispatchClass::Normal, Pays::No))] pub fn add_stake_limit( origin: OriginFor,