Skip to content
14 changes: 7 additions & 7 deletions pallets/subtensor/src/macros/dispatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1190,7 +1190,7 @@ mod dispatches {
/// * `BadOrigin` - If the origin is not root.
///
#[pallet::call_index(69)]
#[pallet::weight(Weight::from_parts(10_190_000, 0)
#[pallet::weight(Weight::from_parts(5_841_000, 0)
.saturating_add(T::DbWeight::get().reads(0))
.saturating_add(T::DbWeight::get().writes(1)))]
pub fn sudo_set_tx_childkey_take_rate_limit(
Expand Down Expand Up @@ -1246,9 +1246,9 @@ mod dispatches {

/// User register a new subnetwork
#[pallet::call_index(59)]
#[pallet::weight((Weight::from_parts(235_400_000, 0)
.saturating_add(T::DbWeight::get().reads(37_u64))
.saturating_add(T::DbWeight::get().writes(53_u64)), DispatchClass::Normal, Pays::Yes))]
#[pallet::weight((Weight::from_parts(352_700_000, 0)
.saturating_add(T::DbWeight::get().reads(48_u64))
.saturating_add(T::DbWeight::get().writes(56_u64)), DispatchClass::Normal, Pays::Yes))]
pub fn register_network(origin: OriginFor<T>, hotkey: T::AccountId) -> DispatchResult {
Self::do_register_network(origin, &hotkey, 1, None)
}
Expand Down Expand Up @@ -1456,8 +1456,8 @@ mod dispatches {
/// User register a new subnetwork
#[pallet::call_index(79)]
#[pallet::weight((Weight::from_parts(396_000_000, 0)
.saturating_add(T::DbWeight::get().reads(36_u64))
.saturating_add(T::DbWeight::get().writes(52_u64)), DispatchClass::Normal, Pays::Yes))]
.saturating_add(T::DbWeight::get().reads(47_u64))
.saturating_add(T::DbWeight::get().writes(55_u64)), DispatchClass::Normal, Pays::Yes))]
pub fn register_network_with_identity(
origin: OriginFor<T>,
hotkey: T::AccountId,
Expand Down Expand Up @@ -1849,7 +1849,7 @@ mod dispatches {
/// Will charge based on the weight even if the hotkey is already associated with a coldkey.
#[pallet::call_index(91)]
#[pallet::weight((
Weight::from_parts(27_150_000, 0).saturating_add(T::DbWeight::get().reads_writes(3, 3)),
Weight::from_parts(26_850_000, 0).saturating_add(T::DbWeight::get().reads_writes(3, 3)),
DispatchClass::Normal,
Pays::Yes
))]
Expand Down
73 changes: 72 additions & 1 deletion pallets/subtensor/src/staking/stake_utils.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;
use safe_math::*;
use share_pool::{SafeFloat, SharePool, SharePoolDataOperations};
use sp_std::ops::Neg;
use sp_std::{collections::btree_map::BTreeMap, ops::Neg};
use substrate_fixed::types::{I64F64, I96F32, U96F32};
use subtensor_runtime_common::{AlphaBalance, AuthorshipInfo, NetUid, TaoBalance, Token};
use subtensor_swap_interface::{Order, SwapHandler, SwapResult};
Expand Down Expand Up @@ -69,6 +69,77 @@ impl<T: Config> Pallet<T> {
SubnetMovingPrice::<T>::insert(netuid, new_moving);
}

/// Gets the Median Subnet Alpha Price
pub fn get_median_subnet_alpha_price() -> U96F32 {
let default_price = U96F32::saturating_from_num(1_u64);
let zero_price = U96F32::saturating_from_num(0_u64);
let two = U96F32::saturating_from_num(2_u64);

let mut price_counts: BTreeMap<U96F32, usize> = BTreeMap::new();
let mut total_prices: usize = 0;

for (netuid, added) in NetworksAdded::<T>::iter() {
if !added || netuid == NetUid::ROOT {
continue;
}

let price = T::SwapInterface::current_alpha_price(netuid);
if price <= zero_price {
continue;
}

total_prices = total_prices.saturating_add(1);

if let Some(count) = price_counts.get_mut(&price) {
*count = count.saturating_add(1);
} else {
price_counts.insert(price, 1usize);
}
}

if total_prices == 0 {
return default_price;
}

let Some(last_index) = total_prices.checked_sub(1) else {
return default_price;
};
let Some(lower_target) = last_index.checked_div(2) else {
return default_price;
};
let Some(upper_target) = total_prices.checked_div(2) else {
return default_price;
};

let mut cumulative: usize = 0;
let mut lower_price: Option<U96F32> = None;
let mut upper_price: Option<U96F32> = None;

for (price, count) in price_counts.into_iter() {
let next_cumulative = cumulative.saturating_add(count);

if lower_price.is_none() && lower_target < next_cumulative {
lower_price = Some(price);
}

if upper_price.is_none() && upper_target < next_cumulative {
upper_price = Some(price);
}

if lower_price.is_some() && upper_price.is_some() {
break;
}

cumulative = next_cumulative;
}

match (lower_price, upper_price) {
(Some(_), Some(upper)) if lower_target == upper_target => upper,
(Some(lower), Some(upper)) => lower.saturating_add(upper).safe_div(two),
_ => default_price,
}
}

/// Retrieves the global global weight as a normalized value between 0 and 1.
///
/// This function performs the following steps:
Expand Down
37 changes: 29 additions & 8 deletions pallets/subtensor/src/subnets/subnet.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use super::*;
use safe_math::FixedExt;
use sp_core::Get;
use substrate_fixed::types::U96F32;
use subtensor_runtime_common::{NetUid, TaoBalance};
impl<T: Config> Pallet<T> {
/// Returns true if the subnetwork exists.
Expand Down Expand Up @@ -183,31 +185,41 @@ impl<T: Config> Pallet<T> {
None => Self::get_next_netuid(),
};

// --- 11. Set initial and custom parameters for the network.
// --- 11. Snapshot the current median subnet alpha price before creating the new subnet.
let median_subnet_alpha_price = Self::get_median_subnet_alpha_price();

// --- 12. Set initial and custom parameters for the network.
let default_tempo = DefaultTempo::<T>::get();
Self::init_new_network(netuid_to_register, default_tempo);
log::debug!("init_new_network: {netuid_to_register:?}");

// --- 12. Add the caller to the neuron set.
// --- 13. Add the caller to the neuron set.
Self::create_account_if_non_existent(&coldkey, hotkey);
Self::append_neuron(netuid_to_register, hotkey, current_block);
log::debug!("Appended neuron for netuid {netuid_to_register:?}, hotkey: {hotkey:?}");

// --- 13. Set the mechanism.
// --- 14. Set the mechanism.
SubnetMechanism::<T>::insert(netuid_to_register, mechid);
log::debug!("SubnetMechanism for netuid {netuid_to_register:?} set to: {mechid:?}");

// --- 14. Set the creation terms.
// --- 15. Set the creation terms.
NetworkRegisteredAt::<T>::insert(netuid_to_register, current_block);

// --- 15. Set the symbol.
// --- 16. Set the symbol.
let symbol = Self::get_next_available_symbol(netuid_to_register);
TokenSymbol::<T>::insert(netuid_to_register, symbol);

// The initial TAO is the locked amount
// Put initial TAO from lock into subnet TAO and produce numerically equal amount of Alpha.
// Seed the new subnet pool at a 1:1 reserve ratio.
// Separately, grant the subnet owner outstanding alpha based on the TAO they actually spent
// on registration converted by the current median subnet alpha price.
let pool_initial_tao: TaoBalance = Self::get_network_min_lock();
let pool_initial_alpha: AlphaBalance = pool_initial_tao.to_u64().into();
let owner_alpha_stake: AlphaBalance =
U96F32::saturating_from_num(actual_tao_lock_amount.to_u64())
.safe_div(median_subnet_alpha_price)
.saturating_floor()
.saturating_to_num::<u64>()
.into();
let actual_tao_lock_amount_less_pool_tao =
actual_tao_lock_amount.saturating_sub(pool_initial_tao);

Expand All @@ -219,13 +231,22 @@ impl<T: Config> Pallet<T> {
SubnetLocked::<T>::insert(netuid_to_register, actual_tao_lock_amount);
SubnetTaoProvided::<T>::insert(netuid_to_register, TaoBalance::ZERO);
SubnetAlphaInProvided::<T>::insert(netuid_to_register, AlphaBalance::ZERO);
SubnetAlphaOut::<T>::insert(netuid_to_register, AlphaBalance::ZERO);
SubnetAlphaOut::<T>::insert(netuid_to_register, owner_alpha_stake);
SubnetVolume::<T>::insert(netuid_to_register, 0u128);
RAORecycledForRegistration::<T>::insert(
netuid_to_register,
actual_tao_lock_amount_less_pool_tao,
);

if owner_alpha_stake > AlphaBalance::ZERO {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can also be just !owner_alpha_stake.is_zero().

Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
hotkey,
&coldkey,
netuid_to_register,
owner_alpha_stake,
);
}

if actual_tao_lock_amount_less_pool_tao > TaoBalance::ZERO {
Self::recycle_tao(actual_tao_lock_amount_less_pool_tao);
}
Expand Down
2 changes: 2 additions & 0 deletions pallets/subtensor/src/tests/children.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2978,6 +2978,7 @@ fn test_parent_child_chain_emission() {
let subnet_owner_coldkey = U256::from(1001);
let subnet_owner_hotkey = U256::from(1002);
let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey);
remove_owner_registration_stake(netuid);
SubtensorModule::set_ck_burn(0);
Tempo::<Test>::insert(netuid, 1);

Expand Down Expand Up @@ -3831,6 +3832,7 @@ fn test_do_set_child_as_sn_owner_not_enough_stake() {
let proportion: u64 = 1000;

let netuid = add_dynamic_network(&sn_owner_hotkey, &coldkey);
remove_owner_registration_stake(netuid);
register_ok_neuron(netuid, child_hotkey, child_coldkey, 0);

// Verify stake of sn_owner_hotkey is NOT enough
Expand Down
12 changes: 11 additions & 1 deletion pallets/subtensor/src/tests/claim_root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

use crate::RootAlphaDividendsPerSubnet;
use crate::tests::mock::{
RuntimeOrigin, SubtensorModule, Test, add_dynamic_network, new_test_ext, run_to_block,
RuntimeOrigin, SubtensorModule, Test, add_dynamic_network, new_test_ext,
remove_owner_registration_stake, run_to_block,
};
use crate::{
DefaultMinRootClaimAmount, Error, MAX_NUM_ROOT_CLAIMS, MAX_ROOT_CLAIM_THRESHOLD, NetworksAdded,
Expand Down Expand Up @@ -44,6 +45,7 @@ fn test_claim_root_with_drain_emissions() {
let hotkey = U256::from(1002);
let coldkey = U256::from(1003);
let netuid = add_dynamic_network(&hotkey, &owner_coldkey);
remove_owner_registration_stake(netuid);

SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0

Expand Down Expand Up @@ -765,6 +767,7 @@ fn test_claim_root_with_run_coinbase() {
let hotkey = U256::from(1002);
let coldkey = U256::from(1003);
let netuid = add_dynamic_network(&hotkey, &owner_coldkey);
remove_owner_registration_stake(netuid);

Tempo::<Test>::insert(netuid, 1);
SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0
Expand Down Expand Up @@ -883,6 +886,7 @@ fn test_claim_root_with_block_emissions() {
let hotkey = U256::from(1002);
let coldkey = U256::from(1003);
let netuid = add_dynamic_network(&hotkey, &owner_coldkey);
remove_owner_registration_stake(netuid);

Tempo::<Test>::insert(netuid, 1);
SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0
Expand Down Expand Up @@ -942,6 +946,7 @@ fn test_claim_root_with_block_emissions() {
assert!(new_stake > 0);
});
}

#[test]
fn test_populate_staking_maps() {
new_test_ext(1).execute_with(|| {
Expand Down Expand Up @@ -1117,6 +1122,7 @@ fn test_claim_root_with_swap_coldkey() {
let hotkey = U256::from(1002);
let coldkey = U256::from(1003);
let netuid = add_dynamic_network(&hotkey, &owner_coldkey);
remove_owner_registration_stake(netuid);

SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0

Expand Down Expand Up @@ -1195,13 +1201,15 @@ fn test_claim_root_with_swap_coldkey() {
);
});
}

#[test]
fn test_claim_root_with_swap_hotkey() {
new_test_ext(1).execute_with(|| {
let owner_coldkey = U256::from(1001);
let hotkey = U256::from(1002);
let coldkey = U256::from(1003);
let netuid = add_dynamic_network(&hotkey, &owner_coldkey);
remove_owner_registration_stake(netuid);

SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0

Expand Down Expand Up @@ -1461,6 +1469,7 @@ fn test_claim_root_with_unrelated_subnets() {
let hotkey = U256::from(1002);
let coldkey = U256::from(1003);
let netuid = add_dynamic_network(&hotkey, &owner_coldkey);
remove_owner_registration_stake(netuid);

SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0

Expand Down Expand Up @@ -1639,6 +1648,7 @@ fn test_claim_root_with_keep_subnets() {
let hotkey = U256::from(1002);
let coldkey = U256::from(1003);
let netuid = add_dynamic_network(&hotkey, &owner_coldkey);
remove_owner_registration_stake(netuid);

SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0

Expand Down
5 changes: 5 additions & 0 deletions pallets/subtensor/src/tests/coinbase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,7 @@ fn test_pending_emission() {
let hotkey = U256::from(1);
let coldkey = U256::from(2);
let netuid = add_dynamic_network(&hotkey, &coldkey);
remove_owner_registration_stake(netuid);
Tempo::<Test>::insert(netuid, 1);
FirstEmissionBlockNumber::<Test>::insert(netuid, 0);

Expand Down Expand Up @@ -1825,6 +1826,7 @@ fn test_incentive_to_subnet_owner_is_burned() {
Owner::<Test>::insert(other_hk, other_ck);

let netuid = add_dynamic_network(&subnet_owner_hk, &subnet_owner_ck);
remove_owner_registration_stake(netuid);

let pending_tao: u64 = 1_000_000_000;
let pending_alpha = AlphaBalance::ZERO; // None to valis
Expand Down Expand Up @@ -1875,6 +1877,7 @@ fn test_incentive_to_subnet_owners_hotkey_is_burned() {
OwnedHotkeys::<Test>::insert(subnet_owner_ck, vec![subnet_owner_hk, other_hk]);

let netuid = add_dynamic_network(&subnet_owner_hk, &subnet_owner_ck);
remove_owner_registration_stake(netuid);
Uids::<Test>::insert(netuid, other_hk, 1);

// Set the burn key limit to 2
Expand Down Expand Up @@ -1938,6 +1941,7 @@ fn test_burn_key_sorting() {
);

let netuid = add_dynamic_network(&subnet_owner_hk, &subnet_owner_ck);
remove_owner_registration_stake(netuid);

// Set block of registration and UIDs for other hotkeys
// HK1 has block of registration 2
Expand Down Expand Up @@ -2388,6 +2392,7 @@ fn test_calculate_dividends_and_incentives_only_miners() {
fn test_distribute_emission_no_miners_all_drained() {
new_test_ext(1).execute_with(|| {
let netuid = add_dynamic_network(&U256::from(1), &U256::from(2));
remove_owner_registration_stake(netuid);
let hotkey = U256::from(3);
let coldkey = U256::from(4);
let init_stake = 1;
Expand Down
40 changes: 40 additions & 0 deletions pallets/subtensor/src/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1038,3 +1038,43 @@ pub fn sf_to_u128(sf: &SafeFloat) -> u128 {
pub fn sf_from_u64(val: u64) -> SafeFloat {
SafeFloat::from(val)
}

#[allow(dead_code)]
pub fn remove_owner_registration_stake(netuid: NetUid) {
let owner_hotkey = SubnetOwnerHotkey::<Test>::get(netuid);
let owner_coldkey = SubnetOwner::<Test>::get(netuid);

let owner_stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
&owner_hotkey,
&owner_coldkey,
netuid,
);

if owner_stake.is_zero() {
return;
}

let alpha_out_before = SubnetAlphaOut::<Test>::get(netuid);

SubtensorModule::decrease_stake_for_hotkey_and_coldkey_on_subnet(
&owner_hotkey,
&owner_coldkey,
netuid,
owner_stake,
);

SubnetAlphaOut::<Test>::insert(netuid, alpha_out_before.saturating_sub(owner_stake));

assert_eq!(
SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(
&owner_hotkey,
&owner_coldkey,
netuid,
),
AlphaBalance::ZERO
);
assert_eq!(
TotalHotkeyAlpha::<Test>::get(owner_hotkey, netuid),
AlphaBalance::ZERO
);
}
Loading
Loading