From 253d8073f6f52a4b102b6c87c33bcf30bd68ecbf Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Fri, 30 May 2025 13:35:53 -0500 Subject: [PATCH 1/4] 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/4] 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/4] 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/4] 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!(