From 986c6888b48aad6098448bc943eaba2950a83506 Mon Sep 17 00:00:00 2001 From: open-junius Date: Mon, 1 Sep 2025 08:56:38 +0800 Subject: [PATCH 1/6] childkey tax rate --- pallets/admin-utils/src/lib.rs | 11 +++++++++++ pallets/subtensor/src/lib.rs | 8 ++++++++ pallets/subtensor/src/utils/misc.rs | 24 ++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 03a20a5f21..1f6c0ea1c0 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -1682,6 +1682,17 @@ pub mod pallet { pallet_subtensor::Pallet::::set_owner_immune_neuron_limit(netuid, immune_neurons)?; Ok(()) } + + #[pallet::call_index(73)] + #[pallet::weight(Weight::from_parts(15_000_000, 0))] + pub fn sudo_set_childkey_tax_rate( + origin: OriginFor, + childkey_tax_rate: u16, + ) -> DispatchResult { + ensure_root(origin)?; + pallet_subtensor::Pallet::::set_childkey_tax_rate(childkey_tax_rate)?; + Ok(()) + } } } diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index ef41b07c78..4f785dde86 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -1482,6 +1482,14 @@ pub mod pallet { pub type ImmuneOwnerUidsLimit = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultImmuneOwnerUidsLimit>; + #[pallet::type_value] + /// Default value for childkey tax rate + pub fn DefaultChildkeyTaxRate() -> u16 { + 18 + } + #[pallet::storage] + pub type ChildkeyTaxRate = StorageValue<_, u16, ValueQuery, DefaultChildkeyTaxRate>; + /// ======================================= /// ==== Subnetwork Consensus Storage ==== /// ======================================= diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index f64962f094..dcf876518d 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -829,4 +829,28 @@ impl Pallet { ImmuneOwnerUidsLimit::::insert(netuid, limit); Ok(()) } + + /// Get the childkey tax rate + /// + /// # Returns + /// - `u16` - The childkey tax rate. + pub fn get_childkey_tax_rate() -> u16 { + ChildkeyTaxRate::::get() + } + + /// Set the childkey tax rate + /// + /// # Arguments + /// + /// * `childkey_tax_rate` - The new childkey tax rate. + /// + /// # Returns + /// - `Ok(())` on success. + /// - `Err(Error::::InvalidValue)` if `childkey_tax_rate` is outside `[0, 100]`. + pub fn set_childkey_tax_rate(childkey_tax_rate: u16) -> DispatchResult { + ensure!(childkey_tax_rate <= 100, Error::::InvalidValue); + + ChildkeyTaxRate::::set(childkey_tax_rate); + Ok(()) + } } From 8f4288bad25c758d5b931808f77c750e65cace25 Mon Sep 17 00:00:00 2001 From: open-junius Date: Mon, 1 Sep 2025 08:58:28 +0800 Subject: [PATCH 2/6] bump version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 00cc24b411..679e5e55b2 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -220,7 +220,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: 307, + spec_version: 308, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From d73e5591c7f2ce63e215a3aeb60ec5976aade497 Mon Sep 17 00:00:00 2001 From: open-junius Date: Mon, 1 Sep 2025 09:18:26 +0800 Subject: [PATCH 3/6] apply tax to coinbase --- pallets/subtensor/src/coinbase/run_coinbase.rs | 17 +++++++++++++++-- pallets/subtensor/src/lib.rs | 4 ++-- pallets/subtensor/src/utils/misc.rs | 2 -- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 73fc928e90..4748ad7b9f 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -743,6 +743,7 @@ impl Pallet { // Calculate the hotkey's share of the validator emission based on its childkey take let validating_emission: U96F32 = U96F32::saturating_from_num(dividends); let mut remaining_emission: U96F32 = validating_emission; + let childkey_take_proportion: U96F32 = U96F32::saturating_from_num(Self::get_childkey_take(hotkey, netuid)) .safe_div(U96F32::saturating_from_num(u16::MAX)); @@ -826,14 +827,26 @@ impl Pallet { .saturating_mul(U96F32::saturating_from_num(parent_emission)) }; + let childkey_emission_take_tax: U96F32 = child_emission_take + .saturating_mul(U96F32::saturating_from_num(Self::get_childkey_tax_rate())) + .safe_div(U96F32::saturating_from_num(u16::MAX)); + + let child_emission_take_after_tax: U96F32 = + child_emission_take.saturating_sub(childkey_emission_take_tax); + // Remove the childkey take from the parent's emission. parent_emission = parent_emission.saturating_sub(child_emission_take); // Add the childkey take to the total childkey take tracker. total_child_emission_take = - total_child_emission_take.saturating_add(child_emission_take); + total_child_emission_take.saturating_add(child_emission_take_after_tax); - log::debug!("Child emission take: {child_emission_take:?} for hotkey {hotkey:?}"); + log::debug!( + "Child emission take tax: {childkey_emission_take_tax:?} for hotkey {hotkey:?}" + ); + log::debug!( + "Child emission take after tax: {child_emission_take_after_tax:?} for hotkey {hotkey:?}" + ); log::debug!("Parent emission: {parent_emission:?} for hotkey {hotkey:?}"); log::debug!("remaining emission: {remaining_emission:?}"); diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 4f785dde86..9b35c7e266 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -1483,9 +1483,9 @@ pub mod pallet { StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultImmuneOwnerUidsLimit>; #[pallet::type_value] - /// Default value for childkey tax rate + /// Default value for childkey tax rate, 18% pub fn DefaultChildkeyTaxRate() -> u16 { - 18 + 11_796 } #[pallet::storage] pub type ChildkeyTaxRate = StorageValue<_, u16, ValueQuery, DefaultChildkeyTaxRate>; diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index dcf876518d..b46a3e4a10 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -848,8 +848,6 @@ impl Pallet { /// - `Ok(())` on success. /// - `Err(Error::::InvalidValue)` if `childkey_tax_rate` is outside `[0, 100]`. pub fn set_childkey_tax_rate(childkey_tax_rate: u16) -> DispatchResult { - ensure!(childkey_tax_rate <= 100, Error::::InvalidValue); - ChildkeyTaxRate::::set(childkey_tax_rate); Ok(()) } From d028698091cdce64e9ad7881afd2f062b60cf0bd Mon Sep 17 00:00:00 2001 From: open-junius Date: Mon, 1 Sep 2025 09:19:34 +0800 Subject: [PATCH 4/6] add doc --- pallets/admin-utils/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 1f6c0ea1c0..6d7ede9f46 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -1683,6 +1683,7 @@ pub mod pallet { Ok(()) } + /// Sets the childkey tax rate #[pallet::call_index(73)] #[pallet::weight(Weight::from_parts(15_000_000, 0))] pub fn sudo_set_childkey_tax_rate( From 2d28109da1ef9ebd7b1346756ddda643e19dff63 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 1 Sep 2025 03:17:47 +0000 Subject: [PATCH 5/6] auto-update benchmark weights --- pallets/subtensor/src/macros/dispatches.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index 46b4aaf92b..d40cee3223 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -120,9 +120,9 @@ mod dispatches { /// - On failure for each failed item in the batch. /// #[pallet::call_index(80)] - #[pallet::weight((Weight::from_parts(19_330_000, 0) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(0_u64)), DispatchClass::Normal, Pays::No))] + #[pallet::weight((Weight::from_parts(94_830_000, 0) + .saturating_add(T::DbWeight::get().reads(14_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)), DispatchClass::Normal, Pays::No))] pub fn batch_set_weights( origin: OriginFor, netuids: Vec>, From 7621360dd4476c186eb2f9feeaa566887afdaaa0 Mon Sep 17 00:00:00 2001 From: open-junius Date: Tue, 2 Sep 2025 19:25:30 +0800 Subject: [PATCH 6/6] apply tax to parent --- .../subtensor/src/coinbase/run_coinbase.rs | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 4748ad7b9f..5572ba681d 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -818,6 +818,14 @@ impl Pallet { // Remove this emission from the remaining emission. remaining_emission = remaining_emission.saturating_sub(parent_emission); + let parent_emission_tax = parent_emission + .saturating_mul(U96F32::saturating_from_num(Self::get_childkey_tax_rate())) + .safe_div(U96F32::saturating_from_num(u16::MAX)); + log::debug!("Parent emission tax: {parent_emission_tax:?} for hotkey {hotkey:?}"); + + parent_emission = parent_emission.saturating_sub(parent_emission_tax); + log::debug!("Parent emission after tax: {parent_emission:?} for hotkey {hotkey:?}"); + // Get the childkey take for this parent. let child_emission_take: U96F32 = if parent_owner == childkey_owner { // The parent is from the same coldkey, so we don't remove any childkey take. @@ -827,26 +835,14 @@ impl Pallet { .saturating_mul(U96F32::saturating_from_num(parent_emission)) }; - let childkey_emission_take_tax: U96F32 = child_emission_take - .saturating_mul(U96F32::saturating_from_num(Self::get_childkey_tax_rate())) - .safe_div(U96F32::saturating_from_num(u16::MAX)); - - let child_emission_take_after_tax: U96F32 = - child_emission_take.saturating_sub(childkey_emission_take_tax); - // Remove the childkey take from the parent's emission. parent_emission = parent_emission.saturating_sub(child_emission_take); // Add the childkey take to the total childkey take tracker. total_child_emission_take = - total_child_emission_take.saturating_add(child_emission_take_after_tax); + total_child_emission_take.saturating_add(child_emission_take); - log::debug!( - "Child emission take tax: {childkey_emission_take_tax:?} for hotkey {hotkey:?}" - ); - log::debug!( - "Child emission take after tax: {child_emission_take_after_tax:?} for hotkey {hotkey:?}" - ); + log::debug!("Child emission take: {child_emission_take:?} for hotkey {hotkey:?}"); log::debug!("Parent emission: {parent_emission:?} for hotkey {hotkey:?}"); log::debug!("remaining emission: {remaining_emission:?}");