From 0c949864f5cab55a297562a5b1458f975bf101ef Mon Sep 17 00:00:00 2001 From: Dairus01 Date: Wed, 31 Dec 2025 15:51:42 +0000 Subject: [PATCH 01/12] Fix SubnetAlphaOut burn discrepancy Correct SubnetAlphaOut updates during burn and stake decrease operations to ensure accurate tracking of burned tokens. Fixes opentensor/subtensor#2274 --- pallets/subtensor/src/lib.rs | 10 +- pallets/subtensor/src/staking/helpers.rs | 7 +- pallets/subtensor/src/tests/mod.rs | 1 + pallets/subtensor/src/tests/recycle_alpha.rs | 6 +- .../src/tests/regression_issue_2274.rs | 94 +++++++++++++++++++ 5 files changed, 109 insertions(+), 9 deletions(-) create mode 100644 pallets/subtensor/src/tests/regression_issue_2274.rs diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index ef2d44e68b..dbc13eb727 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -2633,14 +2633,16 @@ impl> Error::::HotKeyAccountNotExists ); + let actual_alpha = Self::decrease_stake_for_hotkey_and_coldkey_on_subnet( + hotkey, coldkey, netuid, alpha, + ); + // Decrese alpha out counter SubnetAlphaOut::::mutate(netuid, |total| { - *total = total.saturating_sub(alpha); + *total = total.saturating_sub(actual_alpha); }); - Ok(Self::decrease_stake_for_hotkey_and_coldkey_on_subnet( - hotkey, coldkey, netuid, alpha, - )) + Ok(actual_alpha) } } diff --git a/pallets/subtensor/src/staking/helpers.rs b/pallets/subtensor/src/staking/helpers.rs index 1176064e36..8ce2590838 100644 --- a/pallets/subtensor/src/staking/helpers.rs +++ b/pallets/subtensor/src/staking/helpers.rs @@ -376,7 +376,10 @@ impl Pallet { } } - pub fn burn_subnet_alpha(_netuid: NetUid, _amount: AlphaCurrency) { - // Do nothing; TODO: record burned alpha in a tracker + pub fn burn_subnet_alpha(netuid: NetUid, amount: AlphaCurrency) { + // TODO: record burned alpha in a tracker + SubnetAlphaOut::::mutate(netuid, |total| { + *total = total.saturating_sub(amount); + }); } } diff --git a/pallets/subtensor/src/tests/mod.rs b/pallets/subtensor/src/tests/mod.rs index bbaf25af58..e6667ba551 100644 --- a/pallets/subtensor/src/tests/mod.rs +++ b/pallets/subtensor/src/tests/mod.rs @@ -31,3 +31,4 @@ mod swap_hotkey; mod swap_hotkey_with_subnet; mod uids; mod weights; +mod regression_issue_2274; diff --git a/pallets/subtensor/src/tests/recycle_alpha.rs b/pallets/subtensor/src/tests/recycle_alpha.rs index 32a95c700d..922f6a7db3 100644 --- a/pallets/subtensor/src/tests/recycle_alpha.rs +++ b/pallets/subtensor/src/tests/recycle_alpha.rs @@ -246,7 +246,7 @@ fn test_burn_success() { )); assert!(TotalHotkeyAlpha::::get(hotkey, netuid) < initial_alpha); - assert!(SubnetAlphaOut::::get(netuid) == initial_net_alpha); + assert!(SubnetAlphaOut::::get(netuid) < initial_net_alpha); // Expect decrease assert!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid) < stake.into() @@ -307,7 +307,7 @@ fn test_burn_staker_is_nominator() { )); assert!(TotalHotkeyAlpha::::get(hotkey, netuid) < initial_alpha); - assert!(SubnetAlphaOut::::get(netuid) == initial_net_alpha); + assert!(SubnetAlphaOut::::get(netuid) < initial_net_alpha); // Expect decrease assert!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, @@ -376,7 +376,7 @@ fn test_burn_two_stakers() { )); assert!(TotalHotkeyAlpha::::get(hotkey, netuid) < initial_alpha); - assert!(SubnetAlphaOut::::get(netuid) == initial_net_alpha); + assert!(SubnetAlphaOut::::get(netuid) < initial_net_alpha); // Expect decrease assert!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid) < stake.into() diff --git a/pallets/subtensor/src/tests/regression_issue_2274.rs b/pallets/subtensor/src/tests/regression_issue_2274.rs new file mode 100644 index 0000000000..792fd4425e --- /dev/null +++ b/pallets/subtensor/src/tests/regression_issue_2274.rs @@ -0,0 +1,94 @@ +use frame_support::{assert_ok, traits::Currency}; +use sp_core::U256; +use subtensor_runtime_common::{AlphaCurrency, BalanceOps, Currency as CurrencyT}; + +use super::mock::*; +use crate::*; + +#[test] +fn test_burn_extrinsic_updates_subnet_alpha_out() { + new_test_ext(1).execute_with(|| { + let coldkey = U256::from(1); + let hotkey = U256::from(2); + + let owner_coldkey = U256::from(1001); + let owner_hotkey = U256::from(1002); + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + + let initial_balance = 1_000_000_000; + Balances::make_free_balance_be(&coldkey, initial_balance); + + // associate coldkey and hotkey + SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + register_ok_neuron(netuid, hotkey, coldkey, 0); + + assert!(SubtensorModule::if_subnet_exist(netuid)); + + // add stake to coldkey-hotkey pair + let stake = 200_000; + increase_stake_on_coldkey_hotkey_account(&coldkey, &hotkey, stake.into(), netuid); + + // get initial total issuance and alpha out + let initial_net_alpha = SubnetAlphaOut::::get(netuid); + + // amount to burn + let burn_amount = AlphaCurrency::from(stake / 2); + + // burn + assert_ok!(SubtensorModule::burn_alpha( + RuntimeOrigin::signed(coldkey), + hotkey, + burn_amount, + netuid + )); + + let final_net_alpha = SubnetAlphaOut::::get(netuid); + + // Assert that SubnetAlphaOut is reduced + assert!(final_net_alpha < initial_net_alpha, "SubnetAlphaOut should be reduced after burn"); + assert_eq!(final_net_alpha, initial_net_alpha - burn_amount); + }); +} + +#[test] +fn test_balance_ops_decrease_stake_consistency() { + new_test_ext(1).execute_with(|| { + let coldkey = U256::from(1); + let hotkey = U256::from(2); + + let owner_coldkey = U256::from(1001); + let owner_hotkey = U256::from(1002); + let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); + + let initial_balance = 1_000_000_000; + Balances::make_free_balance_be(&coldkey, initial_balance); + + // associate coldkey and hotkey + SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); + register_ok_neuron(netuid, hotkey, coldkey, 0); + + assert!(SubtensorModule::if_subnet_exist(netuid)); + + // add stake to coldkey-hotkey pair + let stake = 200_000; + increase_stake_on_coldkey_hotkey_account(&coldkey, &hotkey, stake.into(), netuid); + + let initial_net_alpha = SubnetAlphaOut::::get(netuid); + + // Scenario: Decrease more stake than available using BalanceOps + let too_much = AlphaCurrency::from(stake * 2); + + // Using BalanceOps::decrease_stake directly + let result = >::decrease_stake( + &coldkey, &hotkey, netuid, too_much + ); + + // Result should be 0 because implementation returns 0 if insufficient + assert_eq!(result, Ok(0.into())); + + let final_net_alpha = SubnetAlphaOut::::get(netuid); + + // We expect SubnetAlphaOut to remain SAME if 0 stake was removed. + assert_eq!(final_net_alpha, initial_net_alpha, "SubnetAlphaOut should NOT change if 0 stake removed"); + }); +} From b912711776ac51374f4e52251d38487be77304a8 Mon Sep 17 00:00:00 2001 From: Dairus Date: Tue, 6 Jan 2026 12:33:35 +0100 Subject: [PATCH 02/12] Fix missing closing brace in CommitmentsInterface From ce5a716338bc127538e67a42a4ba084906338d74 Mon Sep 17 00:00:00 2001 From: Dairus Date: Tue, 6 Jan 2026 12:34:22 +0100 Subject: [PATCH 03/12] Fix missing closing brace in CommitmentsInterface From 07c5d3c4fa76a89bb1749e55689d5fd70c43c197 Mon Sep 17 00:00:00 2001 From: Dairus Date: Tue, 6 Jan 2026 12:37:12 +0100 Subject: [PATCH 04/12] Fix missing newline at end of recycle_alpha.rs From ea7a2882efc57b05e8d1aed72c9cfa0936285fd4 Mon Sep 17 00:00:00 2001 From: Dairus Date: Tue, 6 Jan 2026 12:38:24 +0100 Subject: [PATCH 05/12] Update test to assert SubnetAlphaOut is not reduced --- pallets/subtensor/src/tests/regression_issue_2274.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pallets/subtensor/src/tests/regression_issue_2274.rs b/pallets/subtensor/src/tests/regression_issue_2274.rs index 792fd4425e..a9470795c3 100644 --- a/pallets/subtensor/src/tests/regression_issue_2274.rs +++ b/pallets/subtensor/src/tests/regression_issue_2274.rs @@ -44,9 +44,8 @@ fn test_burn_extrinsic_updates_subnet_alpha_out() { let final_net_alpha = SubnetAlphaOut::::get(netuid); - // Assert that SubnetAlphaOut is reduced - assert!(final_net_alpha < initial_net_alpha, "SubnetAlphaOut should be reduced after burn"); - assert_eq!(final_net_alpha, initial_net_alpha - burn_amount); + // Assert that SubnetAlphaOut is NOT reduced (Correct behavior for burning) + assert_eq!(final_net_alpha, initial_net_alpha, "SubnetAlphaOut should NOT be reduced after burn"); }); } From 67ace5de8f319c2ed3689a5556b500927ed394fe Mon Sep 17 00:00:00 2001 From: Dairus Date: Tue, 6 Jan 2026 21:14:11 +0100 Subject: [PATCH 06/12] Delete pallets/subtensor/src/tests/regression_issue_2274.rs --- .../src/tests/regression_issue_2274.rs | 93 ------------------- 1 file changed, 93 deletions(-) delete mode 100644 pallets/subtensor/src/tests/regression_issue_2274.rs diff --git a/pallets/subtensor/src/tests/regression_issue_2274.rs b/pallets/subtensor/src/tests/regression_issue_2274.rs deleted file mode 100644 index a9470795c3..0000000000 --- a/pallets/subtensor/src/tests/regression_issue_2274.rs +++ /dev/null @@ -1,93 +0,0 @@ -use frame_support::{assert_ok, traits::Currency}; -use sp_core::U256; -use subtensor_runtime_common::{AlphaCurrency, BalanceOps, Currency as CurrencyT}; - -use super::mock::*; -use crate::*; - -#[test] -fn test_burn_extrinsic_updates_subnet_alpha_out() { - new_test_ext(1).execute_with(|| { - let coldkey = U256::from(1); - let hotkey = U256::from(2); - - let owner_coldkey = U256::from(1001); - let owner_hotkey = U256::from(1002); - let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); - - let initial_balance = 1_000_000_000; - Balances::make_free_balance_be(&coldkey, initial_balance); - - // associate coldkey and hotkey - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - register_ok_neuron(netuid, hotkey, coldkey, 0); - - assert!(SubtensorModule::if_subnet_exist(netuid)); - - // add stake to coldkey-hotkey pair - let stake = 200_000; - increase_stake_on_coldkey_hotkey_account(&coldkey, &hotkey, stake.into(), netuid); - - // get initial total issuance and alpha out - let initial_net_alpha = SubnetAlphaOut::::get(netuid); - - // amount to burn - let burn_amount = AlphaCurrency::from(stake / 2); - - // burn - assert_ok!(SubtensorModule::burn_alpha( - RuntimeOrigin::signed(coldkey), - hotkey, - burn_amount, - netuid - )); - - let final_net_alpha = SubnetAlphaOut::::get(netuid); - - // Assert that SubnetAlphaOut is NOT reduced (Correct behavior for burning) - assert_eq!(final_net_alpha, initial_net_alpha, "SubnetAlphaOut should NOT be reduced after burn"); - }); -} - -#[test] -fn test_balance_ops_decrease_stake_consistency() { - new_test_ext(1).execute_with(|| { - let coldkey = U256::from(1); - let hotkey = U256::from(2); - - let owner_coldkey = U256::from(1001); - let owner_hotkey = U256::from(1002); - let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey); - - let initial_balance = 1_000_000_000; - Balances::make_free_balance_be(&coldkey, initial_balance); - - // associate coldkey and hotkey - SubtensorModule::create_account_if_non_existent(&coldkey, &hotkey); - register_ok_neuron(netuid, hotkey, coldkey, 0); - - assert!(SubtensorModule::if_subnet_exist(netuid)); - - // add stake to coldkey-hotkey pair - let stake = 200_000; - increase_stake_on_coldkey_hotkey_account(&coldkey, &hotkey, stake.into(), netuid); - - let initial_net_alpha = SubnetAlphaOut::::get(netuid); - - // Scenario: Decrease more stake than available using BalanceOps - let too_much = AlphaCurrency::from(stake * 2); - - // Using BalanceOps::decrease_stake directly - let result = >::decrease_stake( - &coldkey, &hotkey, netuid, too_much - ); - - // Result should be 0 because implementation returns 0 if insufficient - assert_eq!(result, Ok(0.into())); - - let final_net_alpha = SubnetAlphaOut::::get(netuid); - - // We expect SubnetAlphaOut to remain SAME if 0 stake was removed. - assert_eq!(final_net_alpha, initial_net_alpha, "SubnetAlphaOut should NOT change if 0 stake removed"); - }); -} From cbd1a9e2e425e8b713f410dbd1cd4ec389ac9cff Mon Sep 17 00:00:00 2001 From: Dairus Date: Tue, 6 Jan 2026 21:17:36 +0100 Subject: [PATCH 07/12] Modify burn_subnet_alpha to be a no-op Updated burn_subnet_alpha function to do nothing and added a TODO comment. --- pallets/subtensor/src/staking/helpers.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pallets/subtensor/src/staking/helpers.rs b/pallets/subtensor/src/staking/helpers.rs index 8ce2590838..1176064e36 100644 --- a/pallets/subtensor/src/staking/helpers.rs +++ b/pallets/subtensor/src/staking/helpers.rs @@ -376,10 +376,7 @@ impl Pallet { } } - pub fn burn_subnet_alpha(netuid: NetUid, amount: AlphaCurrency) { - // TODO: record burned alpha in a tracker - SubnetAlphaOut::::mutate(netuid, |total| { - *total = total.saturating_sub(amount); - }); + pub fn burn_subnet_alpha(_netuid: NetUid, _amount: AlphaCurrency) { + // Do nothing; TODO: record burned alpha in a tracker } } From 0ae1709cc591f997265a137224bc12709184c8b4 Mon Sep 17 00:00:00 2001 From: Dairus Date: Tue, 6 Jan 2026 21:19:13 +0100 Subject: [PATCH 08/12] Remove regression_issue_2274 module from tests --- pallets/subtensor/src/tests/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/src/tests/mod.rs b/pallets/subtensor/src/tests/mod.rs index e6667ba551..e1e71b4820 100644 --- a/pallets/subtensor/src/tests/mod.rs +++ b/pallets/subtensor/src/tests/mod.rs @@ -31,4 +31,4 @@ mod swap_hotkey; mod swap_hotkey_with_subnet; mod uids; mod weights; -mod regression_issue_2274; + From dd96f6b3cfb78b84e9ae50b46cac43ef9b906153 Mon Sep 17 00:00:00 2001 From: Dairus Date: Tue, 6 Jan 2026 21:20:30 +0100 Subject: [PATCH 09/12] Reorder weights module import in tests --- pallets/subtensor/src/tests/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/pallets/subtensor/src/tests/mod.rs b/pallets/subtensor/src/tests/mod.rs index e1e71b4820..bbaf25af58 100644 --- a/pallets/subtensor/src/tests/mod.rs +++ b/pallets/subtensor/src/tests/mod.rs @@ -31,4 +31,3 @@ mod swap_hotkey; mod swap_hotkey_with_subnet; mod uids; mod weights; - From 54008069b6b7be9d29b7fc5a19584a04d3714ada Mon Sep 17 00:00:00 2001 From: Dairus Date: Tue, 6 Jan 2026 21:23:01 +0100 Subject: [PATCH 10/12] Add newline at end of recycle_alpha.rs Fix missing newline at end of file From 2b2a0cef540de0f2f11c9c4fc160398f9b7edca4 Mon Sep 17 00:00:00 2001 From: Dairus Date: Tue, 6 Jan 2026 21:25:00 +0100 Subject: [PATCH 11/12] Fix missing closing brace in CommitmentsInterface From 2530581a69c17146357b2b0a1178498abdc568c9 Mon Sep 17 00:00:00 2001 From: Dairus Date: Tue, 6 Jan 2026 21:59:55 +0100 Subject: [PATCH 12/12] Update assertions to check for no decrease in subnet alpha --- pallets/subtensor/src/tests/recycle_alpha.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pallets/subtensor/src/tests/recycle_alpha.rs b/pallets/subtensor/src/tests/recycle_alpha.rs index 922f6a7db3..1b02a11397 100644 --- a/pallets/subtensor/src/tests/recycle_alpha.rs +++ b/pallets/subtensor/src/tests/recycle_alpha.rs @@ -246,7 +246,7 @@ fn test_burn_success() { )); assert!(TotalHotkeyAlpha::::get(hotkey, netuid) < initial_alpha); - assert!(SubnetAlphaOut::::get(netuid) < initial_net_alpha); // Expect decrease + assert!(SubnetAlphaOut::::get(netuid) == initial_net_alpha); // Expect NO decrease assert!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid) < stake.into() @@ -307,7 +307,7 @@ fn test_burn_staker_is_nominator() { )); assert!(TotalHotkeyAlpha::::get(hotkey, netuid) < initial_alpha); - assert!(SubnetAlphaOut::::get(netuid) < initial_net_alpha); // Expect decrease + assert!(SubnetAlphaOut::::get(netuid) == initial_net_alpha); // Expect NO decrease assert!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, @@ -376,7 +376,7 @@ fn test_burn_two_stakers() { )); assert!(TotalHotkeyAlpha::::get(hotkey, netuid) < initial_alpha); - assert!(SubnetAlphaOut::::get(netuid) < initial_net_alpha); // Expect decrease + assert!(SubnetAlphaOut::::get(netuid) == initial_net_alpha); // Expect NO decrease assert!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid) < stake.into()