From 553e9172d183bab71c0be96f5f98effd4c55c44c Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Fri, 8 May 2026 10:07:25 -0400 Subject: [PATCH 1/4] Hotfix to remove initial owners alpha --- pallets/subtensor/src/subnets/subnet.rs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/pallets/subtensor/src/subnets/subnet.rs b/pallets/subtensor/src/subnets/subnet.rs index fd8b61b5dc..a322ecf023 100644 --- a/pallets/subtensor/src/subnets/subnet.rs +++ b/pallets/subtensor/src/subnets/subnet.rs @@ -211,7 +211,6 @@ impl Pallet { TokenSymbol::::insert(netuid_to_register, symbol); // Keep the locked TAO in the pool instead of recycling the excess. - // Mint the owner alpha separately at the median subnet alpha price. // Size the pool alpha reserve from the total TAO reserve at that same price. let pool_initial_tao: TaoBalance = Self::get_network_min_lock(); let total_pool_tao: TaoBalance = if actual_tao_lock_amount >= pool_initial_tao { @@ -219,8 +218,6 @@ impl Pallet { } else { pool_initial_tao }; - let owner_alpha_tao_equivalent: TaoBalance = - total_pool_tao.saturating_sub(pool_initial_tao); let total_pool_alpha: AlphaBalance = U96F32::saturating_from_num(total_pool_tao.to_u64()) .safe_div(median_subnet_alpha_price) @@ -228,12 +225,7 @@ impl Pallet { .saturating_to_num::() .into(); - let owner_alpha_stake: AlphaBalance = - U96F32::saturating_from_num(owner_alpha_tao_equivalent.to_u64()) - .safe_div(median_subnet_alpha_price) - .saturating_floor() - .saturating_to_num::() - .into(); + let owner_alpha_stake = AlphaBalance::ZERO; // With the full lock retained in the reserve, this will normally be zero. let tao_recycled_for_registration = actual_tao_lock_amount.saturating_sub(total_pool_tao); @@ -250,15 +242,6 @@ impl Pallet { SubnetVolume::::insert(netuid_to_register, 0u128); RAORecycledForRegistration::::insert(netuid_to_register, tao_recycled_for_registration); - if !owner_alpha_stake.is_zero() { - Self::increase_stake_for_hotkey_and_coldkey_on_subnet( - hotkey, - &coldkey, - netuid_to_register, - owner_alpha_stake, - ); - } - if tao_recycled_for_registration > TaoBalance::ZERO { Self::recycle_tao(tao_recycled_for_registration); } From a8f06a59da46ad1708d77373617ede59196f9412 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Fri, 8 May 2026 10:24:24 -0400 Subject: [PATCH 2/4] Bump spec, add test --- pallets/subtensor/src/tests/subnet.rs | 37 +++++++++++++++++++++++++++ runtime/src/lib.rs | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/pallets/subtensor/src/tests/subnet.rs b/pallets/subtensor/src/tests/subnet.rs index 9d734b992a..7363edc152 100644 --- a/pallets/subtensor/src/tests/subnet.rs +++ b/pallets/subtensor/src/tests/subnet.rs @@ -909,3 +909,40 @@ fn test_update_symbol_fails_if_symbol_already_in_use() { ); }); } + +#[test] +fn test_register_network_gives_owner_no_initial_alpha_distribution() { + new_test_ext(1).execute_with(|| { + let owner_coldkey = U256::from(5001); + let owner_hotkey = U256::from(5002); + let lock_cost = SubtensorModule::get_network_lock_cost(); + let netuids_before = SubtensorModule::get_all_subnet_netuids(); + + SubtensorModule::add_balance_to_coldkey_account( + &owner_coldkey, + ExistentialDeposit::get() + lock_cost.into(), + ); + + assert_ok!(SubtensorModule::register_network( + <::RuntimeOrigin>::signed(owner_coldkey), + owner_hotkey + )); + + let netuid = SubtensorModule::get_all_subnet_netuids() + .into_iter() + .find(|netuid| !netuids_before.contains(netuid)) + .expect("new subnet should be added"); + + assert_eq!(SubnetOwner::::get(netuid), owner_coldkey); + assert_eq!(SubnetOwnerHotkey::::get(netuid), owner_hotkey); + assert_eq!(SubnetAlphaOut::::get(netuid), AlphaBalance::ZERO); + assert_eq!( + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &owner_hotkey, + &owner_coldkey, + netuid + ), + AlphaBalance::ZERO + ); + }); +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 7c4112837d..0b8e3c982d 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -272,7 +272,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: 401, + spec_version: 402, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 1f1304640b24ce226d24c367b84914d35c5fd5ee Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Fri, 8 May 2026 11:04:34 -0400 Subject: [PATCH 3/4] clippy --- pallets/subtensor/src/tests/subnet.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/src/tests/subnet.rs b/pallets/subtensor/src/tests/subnet.rs index 7363edc152..282505afa9 100644 --- a/pallets/subtensor/src/tests/subnet.rs +++ b/pallets/subtensor/src/tests/subnet.rs @@ -931,7 +931,7 @@ fn test_register_network_gives_owner_no_initial_alpha_distribution() { let netuid = SubtensorModule::get_all_subnet_netuids() .into_iter() .find(|netuid| !netuids_before.contains(netuid)) - .expect("new subnet should be added"); + .unwrap(); assert_eq!(SubnetOwner::::get(netuid), owner_coldkey); assert_eq!(SubnetOwnerHotkey::::get(netuid), owner_hotkey); From 2bb750c5fd85fbcc8d00bcf8d9db01cab4c15d01 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Mon, 18 May 2026 09:53:00 -0400 Subject: [PATCH 4/4] Add migration to fix TI after evm fees --- pallets/subtensor/src/macros/hooks.rs | 4 +- .../migrate_fix_total_issuance_evm_fees.rs | 45 +++++++++++++++++++ pallets/subtensor/src/migrations/mod.rs | 1 + pallets/subtensor/src/tests/migration.rs | 40 ++++++++++++++++- 4 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 pallets/subtensor/src/migrations/migrate_fix_total_issuance_evm_fees.rs diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index ecd8d4212a..205ae92267 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -174,7 +174,9 @@ mod hooks { // Fix RootClaimed overclaim caused by single-subnet hotkey swap bug .saturating_add(migrations::migrate_fix_root_claimed_overclaim::migrate_fix_root_claimed_overclaim::()) // Mint missing SubnetTAO and SubnetLocked into subnet accounts to make TotalIssuance match in balances and subtensor - .saturating_add(migrations::migrate_subnet_balances::migrate_subnet_balances::()); + .saturating_add(migrations::migrate_subnet_balances::migrate_subnet_balances::()) + // Fix testnet Subtensor TotalIssuance after the EVM fees issue. + .saturating_add(migrations::migrate_fix_total_issuance_evm_fees::migrate_fix_total_issuance_evm_fees::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_fix_total_issuance_evm_fees.rs b/pallets/subtensor/src/migrations/migrate_fix_total_issuance_evm_fees.rs new file mode 100644 index 0000000000..b4851745cb --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_fix_total_issuance_evm_fees.rs @@ -0,0 +1,45 @@ +use super::*; +use frame_support::traits::fungible::Inspect; +use frame_support::weights::Weight; + +pub fn migrate_fix_total_issuance_evm_fees() -> Weight { + let migration_name = b"migrate_fix_total_issuance_evm_fees".to_vec(); + let mut weight = T::DbWeight::get().reads(1); + + if HasMigrationRun::::get(&migration_name) { + log::info!( + "Migration '{:?}' has already run. Skipping.", + String::from_utf8_lossy(&migration_name) + ); + return weight; + } + + log::info!( + "Running migration '{}'", + String::from_utf8_lossy(&migration_name) + ); + + // Fix testnet TotalIssuance after the earlier EVM fees issue caused the + // Subtensor pallet's accounting to diverge from the balances pallet. + let balances_total_issuance = ::Currency::total_issuance(); + let subtensor_total_issuance_before = TotalIssuance::::get(); + TotalIssuance::::put(balances_total_issuance); + weight = weight.saturating_add(T::DbWeight::get().reads_writes(2, 1)); + + log::info!( + "Subtensor TotalIssuance fixed for EVM fees issue: previous: {}, new: {}", + subtensor_total_issuance_before, + balances_total_issuance + ); + + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + target: "runtime", + "Migration '{}' completed successfully.", + String::from_utf8_lossy(&migration_name) + ); + + weight +} diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index d8177a8ccf..caad4b0851 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -23,6 +23,7 @@ pub mod migrate_fix_root_claimed_overclaim; pub mod migrate_fix_root_subnet_tao; pub mod migrate_fix_root_tao_and_alpha_in; pub mod migrate_fix_staking_hot_keys; +pub mod migrate_fix_total_issuance_evm_fees; pub mod migrate_init_tao_flow; pub mod migrate_init_total_issuance; pub mod migrate_kappa_map_to_default; diff --git a/pallets/subtensor/src/tests/migration.rs b/pallets/subtensor/src/tests/migration.rs index bf280556e0..a4c68e9d1b 100644 --- a/pallets/subtensor/src/tests/migration.rs +++ b/pallets/subtensor/src/tests/migration.rs @@ -15,7 +15,7 @@ use frame_support::{ StorageHasher, Twox64Concat, assert_ok, storage::unhashed::{get, get_raw, put, put_raw}, storage_alias, - traits::{StorageInstance, StoredMap}, + traits::{Currency, StorageInstance, StoredMap, fungible::Inspect}, weights::Weight, }; use safe_math::SafeDiv; @@ -4356,3 +4356,41 @@ fn test_migrate_subnet_balances() { assert!(HasMigrationRun::::get(MIGRATION_NAME.to_vec())); }); } + +#[test] +fn test_migrate_fix_total_issuance_evm_fees() { + new_test_ext(1).execute_with(|| { + const MIGRATION_NAME: &[u8] = b"migrate_fix_total_issuance_evm_fees"; + + let account = U256::from(42); + let balances_total_issuance = TaoBalance::from(123_456_789_u64); + Balances::make_free_balance_be(&account, balances_total_issuance); + + let broken_subtensor_total_issuance = TaoBalance::from(987_654_321_u64); + TotalIssuance::::put(broken_subtensor_total_issuance); + + assert_eq!(Balances::total_issuance(), balances_total_issuance); + assert_eq!( + TotalIssuance::::get(), + broken_subtensor_total_issuance + ); + assert!(!HasMigrationRun::::get(MIGRATION_NAME.to_vec())); + + let weight = crate::migrations::migrate_fix_total_issuance_evm_fees::migrate_fix_total_issuance_evm_fees::(); + + assert!(!weight.is_zero(), "weight must be non-zero"); + assert_eq!(TotalIssuance::::get(), balances_total_issuance); + assert!(HasMigrationRun::::get(MIGRATION_NAME.to_vec())); + + let second_wrong_value = TaoBalance::from(555_u64); + TotalIssuance::::put(second_wrong_value); + + crate::migrations::migrate_fix_total_issuance_evm_fees::migrate_fix_total_issuance_evm_fees::(); + + assert_eq!( + TotalIssuance::::get(), + second_wrong_value, + "migration must not run more than once" + ); + }); +}