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/subnets/subnet.rs b/pallets/subtensor/src/subnets/subnet.rs index 1c5422c964..65e58e5928 100644 --- a/pallets/subtensor/src/subnets/subnet.rs +++ b/pallets/subtensor/src/subnets/subnet.rs @@ -235,6 +235,9 @@ impl Pallet { 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); + // Core pool + ownership SubnetTAO::::insert(netuid_to_register, total_pool_tao); SubnetAlphaIn::::insert(netuid_to_register, total_pool_alpha); @@ -245,6 +248,15 @@ impl Pallet { SubnetAlphaInProvided::::insert(netuid_to_register, AlphaBalance::ZERO); SubnetAlphaOut::::insert(netuid_to_register, owner_alpha_stake); SubnetVolume::::insert(netuid_to_register, 0u128); + RAORecycledForRegistration::::insert(netuid_to_register, tao_recycled_for_registration); + + if tao_recycled_for_registration > TaoBalance::ZERO + && let Some(subnet_account_id) = Self::get_subnet_account_id(netuid_to_register) + { + // The subnet account ID is guaranteed to have adequate balance for this + // recycle because of transfer operation earlier. No need to check this result. + let _ = Self::recycle_tao(&subnet_account_id, tao_recycled_for_registration); + } if total_pool_tao > TaoBalance::ZERO { // Record in TotalStake the initial TAO in the pool. 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" + ); + }); +}