diff --git a/pallets/subtensor/src/coinbase/block_emission.rs b/pallets/subtensor/src/coinbase/block_emission.rs index 1a63c16a07..cd9d778b8a 100644 --- a/pallets/subtensor/src/coinbase/block_emission.rs +++ b/pallets/subtensor/src/coinbase/block_emission.rs @@ -1,7 +1,10 @@ use super::*; use frame_support::traits::Get; use safe_math::*; -use substrate_fixed::{transcendental::log2, types::I96F32}; +use substrate_fixed::{ + transcendental::log2, + types::{I96F32, U96F32}, +}; impl Pallet { /// Calculates the dynamic TAO emission for a given subnet. @@ -31,15 +34,15 @@ impl Pallet { alpha_block_emission: u64, ) -> (u64, u64, u64) { // Init terms. - let mut tao_in_emission: I96F32 = I96F32::saturating_from_num(tao_emission); - let float_alpha_block_emission: I96F32 = I96F32::saturating_from_num(alpha_block_emission); + let mut tao_in_emission: U96F32 = U96F32::saturating_from_num(tao_emission); + let float_alpha_block_emission: U96F32 = U96F32::saturating_from_num(alpha_block_emission); // Get alpha price for subnet. - let alpha_price: I96F32 = Self::get_alpha_price(netuid); + let alpha_price: U96F32 = Self::get_alpha_price(netuid); log::debug!("{:?} - alpha_price: {:?}", netuid, alpha_price); // Get initial alpha_in - let mut alpha_in_emission: I96F32 = I96F32::saturating_from_num(tao_emission) + let mut alpha_in_emission: U96F32 = U96F32::saturating_from_num(tao_emission) .checked_div(alpha_price) .unwrap_or(float_alpha_block_emission); @@ -60,11 +63,11 @@ impl Pallet { } // Avoid rounding errors. - if tao_in_emission < I96F32::saturating_from_num(1) - || alpha_in_emission < I96F32::saturating_from_num(1) + if tao_in_emission < U96F32::saturating_from_num(1) + || alpha_in_emission < U96F32::saturating_from_num(1) { - alpha_in_emission = I96F32::saturating_from_num(0); - tao_in_emission = I96F32::saturating_from_num(0); + alpha_in_emission = U96F32::saturating_from_num(0); + tao_in_emission = U96F32::saturating_from_num(0); } // Set Alpha in emission. diff --git a/pallets/subtensor/src/coinbase/block_step.rs b/pallets/subtensor/src/coinbase/block_step.rs index 669f8e09da..a7e658e89a 100644 --- a/pallets/subtensor/src/coinbase/block_step.rs +++ b/pallets/subtensor/src/coinbase/block_step.rs @@ -1,7 +1,7 @@ use super::*; use frame_support::storage::IterableStorageMap; use safe_math::*; -use substrate_fixed::types::{I96F32, I110F18}; +use substrate_fixed::types::{U96F32, U110F18}; impl Pallet { /// Executes the necessary operations for each block. @@ -11,8 +11,8 @@ impl Pallet { // --- 1. Adjust difficulties. Self::adjust_registration_terms_for_networks(); // --- 2. Get the current coinbase emission. - let block_emission: I96F32 = - I96F32::saturating_from_num(Self::get_block_emission().unwrap_or(0)); + let block_emission: U96F32 = + U96F32::saturating_from_num(Self::get_block_emission().unwrap_or(0)); log::debug!("Block emission: {:?}", block_emission); // --- 3. Run emission through network. Self::run_coinbase(block_emission); @@ -191,7 +191,7 @@ impl Pallet { } /// Calculates the upgraded difficulty by multiplying the current difficulty by the ratio ( reg_actual + reg_target / reg_target + reg_target ) - /// We use I110F18 to avoid any overflows on u64. Also min_difficulty and max_difficulty bound the range. + /// We use U110F18 to avoid any overflows on u64. Also min_difficulty and max_difficulty bound the range. /// pub fn upgraded_difficulty( netuid: u16, @@ -199,25 +199,25 @@ impl Pallet { registrations_this_interval: u16, target_registrations_per_interval: u16, ) -> u64 { - let updated_difficulty: I110F18 = I110F18::saturating_from_num(current_difficulty) - .saturating_mul(I110F18::saturating_from_num( + let updated_difficulty: U110F18 = U110F18::saturating_from_num(current_difficulty) + .saturating_mul(U110F18::saturating_from_num( registrations_this_interval.saturating_add(target_registrations_per_interval), )) - .safe_div(I110F18::saturating_from_num( + .safe_div(U110F18::saturating_from_num( target_registrations_per_interval.saturating_add(target_registrations_per_interval), )); - let alpha: I110F18 = I110F18::saturating_from_num(Self::get_adjustment_alpha(netuid)) - .safe_div(I110F18::saturating_from_num(u64::MAX)); - let next_value: I110F18 = alpha - .saturating_mul(I110F18::saturating_from_num(current_difficulty)) + let alpha: U110F18 = U110F18::saturating_from_num(Self::get_adjustment_alpha(netuid)) + .safe_div(U110F18::saturating_from_num(u64::MAX)); + let next_value: U110F18 = alpha + .saturating_mul(U110F18::saturating_from_num(current_difficulty)) .saturating_add( - I110F18::saturating_from_num(1.0) + U110F18::saturating_from_num(1.0) .saturating_sub(alpha) .saturating_mul(updated_difficulty), ); - if next_value >= I110F18::saturating_from_num(Self::get_max_difficulty(netuid)) { + if next_value >= U110F18::saturating_from_num(Self::get_max_difficulty(netuid)) { Self::get_max_difficulty(netuid) - } else if next_value <= I110F18::saturating_from_num(Self::get_min_difficulty(netuid)) { + } else if next_value <= U110F18::saturating_from_num(Self::get_min_difficulty(netuid)) { return Self::get_min_difficulty(netuid); } else { return next_value.saturating_to_num::(); @@ -225,7 +225,7 @@ impl Pallet { } /// Calculates the upgraded burn by multiplying the current burn by the ratio ( reg_actual + reg_target / reg_target + reg_target ) - /// We use I110F18 to avoid any overflows on u64. Also min_burn and max_burn bound the range. + /// We use U110F18 to avoid any overflows on u64. Also min_burn and max_burn bound the range. /// pub fn upgraded_burn( netuid: u16, @@ -233,25 +233,25 @@ impl Pallet { registrations_this_interval: u16, target_registrations_per_interval: u16, ) -> u64 { - let updated_burn: I110F18 = I110F18::saturating_from_num(current_burn) - .saturating_mul(I110F18::saturating_from_num( + let updated_burn: U110F18 = U110F18::saturating_from_num(current_burn) + .saturating_mul(U110F18::saturating_from_num( registrations_this_interval.saturating_add(target_registrations_per_interval), )) - .safe_div(I110F18::saturating_from_num( + .safe_div(U110F18::saturating_from_num( target_registrations_per_interval.saturating_add(target_registrations_per_interval), )); - let alpha: I110F18 = I110F18::saturating_from_num(Self::get_adjustment_alpha(netuid)) - .safe_div(I110F18::saturating_from_num(u64::MAX)); - let next_value: I110F18 = alpha - .saturating_mul(I110F18::saturating_from_num(current_burn)) + let alpha: U110F18 = U110F18::saturating_from_num(Self::get_adjustment_alpha(netuid)) + .safe_div(U110F18::saturating_from_num(u64::MAX)); + let next_value: U110F18 = alpha + .saturating_mul(U110F18::saturating_from_num(current_burn)) .saturating_add( - I110F18::saturating_from_num(1.0) + U110F18::saturating_from_num(1.0) .saturating_sub(alpha) .saturating_mul(updated_burn), ); - if next_value >= I110F18::saturating_from_num(Self::get_max_burn_as_u64(netuid)) { + if next_value >= U110F18::saturating_from_num(Self::get_max_burn_as_u64(netuid)) { Self::get_max_burn_as_u64(netuid) - } else if next_value <= I110F18::saturating_from_num(Self::get_min_burn_as_u64(netuid)) { + } else if next_value <= U110F18::saturating_from_num(Self::get_min_burn_as_u64(netuid)) { return Self::get_min_burn_as_u64(netuid); } else { return next_value.saturating_to_num::(); diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 1f4b5284bd..df08a6d2a5 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -1,7 +1,7 @@ use super::*; use alloc::collections::BTreeMap; use safe_math::*; -use substrate_fixed::types::I96F32; +use substrate_fixed::types::U96F32; use tle::stream_ciphers::AESGCMStreamCipherProvider; use tle::tlock::tld; @@ -21,7 +21,7 @@ pub struct WeightsTlockPayload { // Distribute dividends to each hotkey macro_rules! asfloat { ($val:expr) => { - I96F32::saturating_from_num($val) + U96F32::saturating_from_num($val) }; } @@ -32,7 +32,7 @@ macro_rules! tou64 { } impl Pallet { - pub fn run_coinbase(block_emission: I96F32) { + pub fn run_coinbase(block_emission: U96F32) { // --- 0. Get current block. let current_block: u64 = Self::get_current_block_as_u64(); log::debug!("Current block: {:?}", current_block); @@ -52,7 +52,7 @@ impl Pallet { log::debug!("Subnets to emit to: {:?}", subnets_to_emit_to); // --- 2. Get sum of tao reserves ( in a later version we will switch to prices. ) - let mut total_moving_prices: I96F32 = I96F32::saturating_from_num(0.0); + let mut total_moving_prices: U96F32 = U96F32::saturating_from_num(0.0); // Only get price EMA for subnets that we emit to. for netuid_i in subnets_to_emit_to.iter() { // Get and update the moving price of each subnet adding the total together. @@ -63,31 +63,31 @@ impl Pallet { // --- 3. Get subnet terms (tao_in, alpha_in, and alpha_out) // Computation is described in detail in the dtao whitepaper. - let mut tao_in: BTreeMap = BTreeMap::new(); - let mut alpha_in: BTreeMap = BTreeMap::new(); - let mut alpha_out: BTreeMap = BTreeMap::new(); + let mut tao_in: BTreeMap = BTreeMap::new(); + let mut alpha_in: BTreeMap = BTreeMap::new(); + let mut alpha_out: BTreeMap = BTreeMap::new(); // Only calculate for subnets that we are emitting to. for netuid_i in subnets_to_emit_to.iter() { // Get subnet price. - let price_i: I96F32 = Self::get_alpha_price(*netuid_i); + let price_i: U96F32 = Self::get_alpha_price(*netuid_i); log::debug!("price_i: {:?}", price_i); // Get subnet TAO. - let moving_price_i: I96F32 = Self::get_moving_alpha_price(*netuid_i); + let moving_price_i: U96F32 = Self::get_moving_alpha_price(*netuid_i); log::debug!("moving_price_i: {:?}", moving_price_i); // Emission is price over total. - let mut tao_in_i: I96F32 = block_emission + let mut tao_in_i: U96F32 = block_emission .saturating_mul(moving_price_i) .checked_div(total_moving_prices) .unwrap_or(asfloat!(0.0)); log::debug!("tao_in_i: {:?}", tao_in_i); // Get alpha_emission total - let alpha_emission_i: I96F32 = asfloat!( + let alpha_emission_i: U96F32 = asfloat!( Self::get_block_emission_for_issuance(Self::get_alpha_issuance(*netuid_i)) .unwrap_or(0) ); log::debug!("alpha_emission_i: {:?}", alpha_emission_i); // Get initial alpha_in - let alpha_in_i: I96F32 = tao_in_i + let alpha_in_i: U96F32 = tao_in_i .checked_div(price_i) .unwrap_or(alpha_emission_i) .min(alpha_emission_i); @@ -142,14 +142,14 @@ impl Pallet { // --- 5. Compute owner cuts and remove them from alpha_out remaining. // Remove owner cuts here so that we can properly seperate root dividends in the next step. // Owner cuts are accumulated and then fed to the drain at the end of this func. - let cut_percent: I96F32 = Self::get_float_subnet_owner_cut(); - let mut owner_cuts: BTreeMap = BTreeMap::new(); + let cut_percent: U96F32 = Self::get_float_subnet_owner_cut(); + let mut owner_cuts: BTreeMap = BTreeMap::new(); for netuid_i in subnets_to_emit_to.iter() { // Get alpha out. - let alpha_out_i: I96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0)); + let alpha_out_i: U96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0)); log::debug!("alpha_out_i: {:?}", alpha_out_i); // Calculate the owner cut. - let owner_cut_i: I96F32 = alpha_out_i.saturating_mul(cut_percent); + let owner_cut_i: U96F32 = alpha_out_i.saturating_mul(cut_percent); log::debug!("owner_cut_i: {:?}", owner_cut_i); // Save owner cut. *owner_cuts.entry(*netuid_i).or_insert(asfloat!(0)) = owner_cut_i; @@ -165,30 +165,30 @@ impl Pallet { // Then accumulate those dividends for later. for netuid_i in subnets_to_emit_to.iter() { // Get remaining alpha out. - let alpha_out_i: I96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0.0)); + let alpha_out_i: U96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0.0)); log::debug!("alpha_out_i: {:?}", alpha_out_i); // Get total TAO on root. - let root_tao: I96F32 = asfloat!(SubnetTAO::::get(0)); + let root_tao: U96F32 = asfloat!(SubnetTAO::::get(0)); log::debug!("root_tao: {:?}", root_tao); // Get total ALPHA on subnet. - let alpha_issuance: I96F32 = asfloat!(Self::get_alpha_issuance(*netuid_i)); + let alpha_issuance: U96F32 = asfloat!(Self::get_alpha_issuance(*netuid_i)); log::debug!("alpha_issuance: {:?}", alpha_issuance); // Get tao_weight - let tao_weight: I96F32 = root_tao.saturating_mul(Self::get_tao_weight()); + let tao_weight: U96F32 = root_tao.saturating_mul(Self::get_tao_weight()); log::debug!("tao_weight: {:?}", tao_weight); // Get root proportional dividends. - let root_proportion: I96F32 = tao_weight + let root_proportion: U96F32 = tao_weight .checked_div(tao_weight.saturating_add(alpha_issuance)) .unwrap_or(asfloat!(0.0)); log::debug!("root_proportion: {:?}", root_proportion); // Get root proportion of alpha_out dividends. - let root_alpha: I96F32 = root_proportion + let root_alpha: U96F32 = root_proportion .saturating_mul(alpha_out_i) // Total alpha emission per block remaining. .saturating_mul(asfloat!(0.5)); // 50% to validators. // Remove root alpha from alpha_out. log::debug!("root_alpha: {:?}", root_alpha); // Get pending alpha as original alpha_out - root_alpha. - let pending_alpha: I96F32 = alpha_out_i.saturating_sub(root_alpha); + let pending_alpha: U96F32 = alpha_out_i.saturating_sub(root_alpha); log::debug!("pending_alpha: {:?}", pending_alpha); // Sell root emission through the pool. let root_tao: u64 = Self::swap_alpha_for_tao(*netuid_i, tou64!(root_alpha)); @@ -265,10 +265,10 @@ impl Pallet { pub fn calculate_dividends_and_incentives( netuid: u16, hotkey_emission: Vec<(T::AccountId, u64, u64)>, - ) -> (BTreeMap, BTreeMap) { + ) -> (BTreeMap, BTreeMap) { // Accumulate emission of dividends and incentive per hotkey. let mut incentives: BTreeMap = BTreeMap::new(); - let mut dividends: BTreeMap = BTreeMap::new(); + let mut dividends: BTreeMap = BTreeMap::new(); for (hotkey, incentive, dividend) in hotkey_emission { // Accumulate incentives to miners. incentives @@ -295,12 +295,12 @@ impl Pallet { pub fn calculate_dividend_distribution( pending_alpha: u64, pending_tao: u64, - tao_weight: I96F32, + tao_weight: U96F32, stake_map: BTreeMap, - dividends: BTreeMap, + dividends: BTreeMap, ) -> ( - BTreeMap, - BTreeMap, + BTreeMap, + BTreeMap, ) { log::debug!("dividends: {:?}", dividends); log::debug!("stake_map: {:?}", stake_map); @@ -309,31 +309,31 @@ impl Pallet { log::debug!("tao_weight: {:?}", tao_weight); // Setup. - let zero: I96F32 = asfloat!(0.0); + let zero: U96F32 = asfloat!(0.0); // Accumulate root divs and alpha_divs. For each hotkey we compute their // local and root dividend proportion based on their alpha_stake/root_stake - let mut total_root_divs: I96F32 = asfloat!(0); - let mut total_alpha_divs: I96F32 = asfloat!(0); - let mut root_dividends: BTreeMap = BTreeMap::new(); - let mut alpha_dividends: BTreeMap = BTreeMap::new(); + let mut total_root_divs: U96F32 = asfloat!(0); + let mut total_alpha_divs: U96F32 = asfloat!(0); + let mut root_dividends: BTreeMap = BTreeMap::new(); + let mut alpha_dividends: BTreeMap = BTreeMap::new(); for (hotkey, dividend) in dividends { if let Some((alpha_stake_u64, root_stake_u64)) = stake_map.get(&hotkey) { // Get hotkey ALPHA on subnet. - let alpha_stake: I96F32 = asfloat!(*alpha_stake_u64); + let alpha_stake: U96F32 = asfloat!(*alpha_stake_u64); // Get hotkey TAO on root. - let root_stake: I96F32 = asfloat!(*root_stake_u64); + let root_stake: U96F32 = asfloat!(*root_stake_u64); // Convert TAO to alpha with weight. - let root_alpha: I96F32 = root_stake.saturating_mul(tao_weight); + let root_alpha: U96F32 = root_stake.saturating_mul(tao_weight); // Get total from root and local - let total_alpha: I96F32 = alpha_stake.saturating_add(root_alpha); + let total_alpha: U96F32 = alpha_stake.saturating_add(root_alpha); // Compute root prop. - let root_prop: I96F32 = root_alpha.checked_div(total_alpha).unwrap_or(zero); + let root_prop: U96F32 = root_alpha.checked_div(total_alpha).unwrap_or(zero); // Compute root dividends - let root_divs: I96F32 = dividend.saturating_mul(root_prop).max(zero); + let root_divs: U96F32 = dividend.saturating_mul(root_prop); // Compute alpha dividends - let alpha_divs: I96F32 = dividend.saturating_sub(root_divs).max(zero); + let alpha_divs: U96F32 = dividend.saturating_sub(root_divs); // Record the alpha dividends. alpha_dividends .entry(hotkey.clone()) @@ -356,13 +356,13 @@ impl Pallet { log::debug!("total_alpha_divs: {:?}", total_alpha_divs); // Compute root divs as TAO. Here we take - let mut tao_dividends: BTreeMap = BTreeMap::new(); + let mut tao_dividends: BTreeMap = BTreeMap::new(); for (hotkey, root_divs) in root_dividends { // Root proportion. - let root_share: I96F32 = root_divs.checked_div(total_root_divs).unwrap_or(zero); + let root_share: U96F32 = root_divs.checked_div(total_root_divs).unwrap_or(zero); log::debug!("hotkey: {:?}, root_share: {:?}", hotkey, root_share); // Root proportion in TAO - let root_tao: I96F32 = asfloat!(pending_tao).saturating_mul(root_share); + let root_tao: U96F32 = asfloat!(pending_tao).saturating_mul(root_share); log::debug!("hotkey: {:?}, root_tao: {:?}", hotkey, root_tao); // Record root dividends as TAO. tao_dividends @@ -373,14 +373,14 @@ impl Pallet { log::debug!("tao_dividends: {:?}", tao_dividends); // Compute proportional alpha divs using the pending alpha and total alpha divs from the epoch. - let mut prop_alpha_dividends: BTreeMap = BTreeMap::new(); + let mut prop_alpha_dividends: BTreeMap = BTreeMap::new(); for (hotkey, alpha_divs) in alpha_dividends { // Alpha proportion. - let alpha_share: I96F32 = alpha_divs.checked_div(total_alpha_divs).unwrap_or(zero); + let alpha_share: U96F32 = alpha_divs.checked_div(total_alpha_divs).unwrap_or(zero); log::debug!("hotkey: {:?}, alpha_share: {:?}", hotkey, alpha_share); // Compute the proportional pending_alpha to this hotkey. - let prop_alpha: I96F32 = asfloat!(pending_alpha).saturating_mul(alpha_share); + let prop_alpha: U96F32 = asfloat!(pending_alpha).saturating_mul(alpha_share); log::debug!("hotkey: {:?}, prop_alpha: {:?}", hotkey, prop_alpha); // Record the proportional alpha dividends. prop_alpha_dividends @@ -397,8 +397,8 @@ impl Pallet { netuid: u16, owner_cut: u64, incentives: BTreeMap, - alpha_dividends: BTreeMap, - tao_dividends: BTreeMap, + alpha_dividends: BTreeMap, + tao_dividends: BTreeMap, ) { // Distribute the owner cut. if let Ok(owner_coldkey) = SubnetOwner::::try_get(netuid) { @@ -446,7 +446,7 @@ impl Pallet { let _ = AlphaDividendsPerSubnet::::clear_prefix(netuid, u32::MAX, None); for (hotkey, mut alpha_divs) in alpha_dividends { // Get take prop - let alpha_take: I96F32 = + let alpha_take: U96F32 = Self::get_hotkey_take_float(&hotkey).saturating_mul(alpha_divs); // Remove take prop from alpha_divs alpha_divs = alpha_divs.saturating_sub(alpha_take); @@ -471,7 +471,7 @@ impl Pallet { let _ = TaoDividendsPerSubnet::::clear_prefix(netuid, u32::MAX, None); for (hotkey, mut root_tao) in tao_dividends { // Get take prop - let tao_take: I96F32 = Self::get_hotkey_take_float(&hotkey).saturating_mul(root_tao); + let tao_take: U96F32 = Self::get_hotkey_take_float(&hotkey).saturating_mul(root_tao); // Remove take prop from root_tao root_tao = root_tao.saturating_sub(tao_take); // Give the validator their take. @@ -517,12 +517,12 @@ impl Pallet { pending_tao: u64, pending_validator_alpha: u64, hotkey_emission: Vec<(T::AccountId, u64, u64)>, - tao_weight: I96F32, + tao_weight: U96F32, ) -> ( BTreeMap, ( - BTreeMap, - BTreeMap, + BTreeMap, + BTreeMap, ), ) { let (incentives, dividends) = @@ -609,31 +609,31 @@ impl Pallet { pub fn get_self_contribution(hotkey: &T::AccountId, netuid: u16) -> u64 { // Get all childkeys for this hotkey. let childkeys = Self::get_children(hotkey, netuid); - let mut remaining_proportion: I96F32 = I96F32::saturating_from_num(1.0); + let mut remaining_proportion: U96F32 = U96F32::saturating_from_num(1.0); for (proportion, _) in childkeys { remaining_proportion = remaining_proportion.saturating_sub( - I96F32::saturating_from_num(proportion) // Normalize - .safe_div(I96F32::saturating_from_num(u64::MAX)), + U96F32::saturating_from_num(proportion) // Normalize + .safe_div(U96F32::saturating_from_num(u64::MAX)), ); } // Get TAO weight - let tao_weight: I96F32 = Self::get_tao_weight(); + let tao_weight: U96F32 = Self::get_tao_weight(); // Get the hotkey's stake including weight - let root_stake: I96F32 = I96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet( + let root_stake: U96F32 = U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet( hotkey, Self::get_root_netuid(), )); - let alpha_stake: I96F32 = - I96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(hotkey, netuid)); + let alpha_stake: U96F32 = + U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(hotkey, netuid)); // Calculate the - let alpha_contribution: I96F32 = alpha_stake.saturating_mul(remaining_proportion); - let root_contribution: I96F32 = root_stake + let alpha_contribution: U96F32 = alpha_stake.saturating_mul(remaining_proportion); + let root_contribution: U96F32 = root_stake .saturating_mul(remaining_proportion) .saturating_mul(tao_weight); - let combined_contribution: I96F32 = alpha_contribution.saturating_add(root_contribution); + let combined_contribution: U96F32 = alpha_contribution.saturating_add(root_contribution); // Return the combined contribution as a u64 combined_contribution.saturating_to_num::() @@ -661,11 +661,11 @@ impl Pallet { let mut dividend_tuples: Vec<(T::AccountId, u64)> = vec![]; // Calculate the hotkey's share of the validator emission based on its childkey take - let validating_emission: I96F32 = I96F32::saturating_from_num(dividends); - let mut remaining_emission: I96F32 = validating_emission; - let childkey_take_proportion: I96F32 = - I96F32::saturating_from_num(Self::get_childkey_take(hotkey, netuid)) - .safe_div(I96F32::saturating_from_num(u16::MAX)); + 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)); log::debug!( "Childkey take proportion: {:?} for hotkey {:?}", childkey_take_proportion, @@ -678,14 +678,14 @@ impl Pallet { // Initialize variables to track emission distribution let mut to_parents: u64 = 0; - let mut total_child_emission_take: I96F32 = I96F32::saturating_from_num(0); + let mut total_child_emission_take: U96F32 = U96F32::saturating_from_num(0); // Initialize variables to calculate total stakes from parents - let mut total_contribution: I96F32 = I96F32::saturating_from_num(0); - let mut parent_contributions: Vec<(T::AccountId, I96F32)> = Vec::new(); + let mut total_contribution: U96F32 = U96F32::saturating_from_num(0); + let mut parent_contributions: Vec<(T::AccountId, U96F32)> = Vec::new(); // Get the weights for root and alpha stakes in emission distribution - let tao_weight: I96F32 = Self::get_tao_weight(); + let tao_weight: U96F32 = Self::get_tao_weight(); // Get self contribution, removing any childkey proportions. let self_contribution = Self::get_self_contribution(hotkey, netuid); @@ -697,27 +697,27 @@ impl Pallet { ); // Add self contribution to total contribution but not to the parent contributions. total_contribution = - total_contribution.saturating_add(I96F32::saturating_from_num(self_contribution)); + total_contribution.saturating_add(U96F32::saturating_from_num(self_contribution)); // Calculate total root and alpha (subnet-specific) stakes from all parents for (proportion, parent) in Self::get_parents(hotkey, netuid) { // Convert the parent's stake proportion to a fractional value - let parent_proportion: I96F32 = I96F32::saturating_from_num(proportion) - .safe_div(I96F32::saturating_from_num(u64::MAX)); + let parent_proportion: U96F32 = U96F32::saturating_from_num(proportion) + .safe_div(U96F32::saturating_from_num(u64::MAX)); // Get the parent's root and subnet-specific (alpha) stakes - let parent_root: I96F32 = I96F32::saturating_from_num( + let parent_root: U96F32 = U96F32::saturating_from_num( Self::get_stake_for_hotkey_on_subnet(&parent, Self::get_root_netuid()), ); - let parent_alpha: I96F32 = - I96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(&parent, netuid)); + let parent_alpha: U96F32 = + U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(&parent, netuid)); // Calculate the parent's contribution to the hotkey's stakes - let parent_alpha_contribution: I96F32 = parent_alpha.saturating_mul(parent_proportion); - let parent_root_contribution: I96F32 = parent_root + let parent_alpha_contribution: U96F32 = parent_alpha.saturating_mul(parent_proportion); + let parent_root_contribution: U96F32 = parent_root .saturating_mul(parent_proportion) .saturating_mul(tao_weight); - let combined_contribution: I96F32 = + let combined_contribution: U96F32 = parent_alpha_contribution.saturating_add(parent_root_contribution); // Add to the total stakes @@ -738,22 +738,22 @@ impl Pallet { let parent_owner = Self::get_owning_coldkey_for_hotkey(&parent); // Get the stake contribution of this parent key of the total stake. - let emission_factor: I96F32 = contribution + let emission_factor: U96F32 = contribution .checked_div(total_contribution) - .unwrap_or(I96F32::saturating_from_num(0)); + .unwrap_or(U96F32::saturating_from_num(0)); // Get the parent's portion of the validating emission based on their contribution. - let mut parent_emission: I96F32 = validating_emission.saturating_mul(emission_factor); + let mut parent_emission: U96F32 = validating_emission.saturating_mul(emission_factor); // Remove this emission from the remaining emission. remaining_emission = remaining_emission.saturating_sub(parent_emission); // Get the childkey take for this parent. - let child_emission_take: I96F32 = if parent_owner == childkey_owner { + 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. - I96F32::saturating_from_num(0) + U96F32::saturating_from_num(0) } else { childkey_take_proportion - .saturating_mul(I96F32::saturating_from_num(parent_emission)) + .saturating_mul(U96F32::saturating_from_num(parent_emission)) }; // Remove the childkey take from the parent's emission. diff --git a/pallets/subtensor/src/rpc_info/stake_info.rs b/pallets/subtensor/src/rpc_info/stake_info.rs index 7ac5b6b0c6..8a3888061f 100644 --- a/pallets/subtensor/src/rpc_info/stake_info.rs +++ b/pallets/subtensor/src/rpc_info/stake_info.rs @@ -2,7 +2,7 @@ use super::*; use frame_support::pallet_prelude::{Decode, Encode}; extern crate alloc; use codec::Compact; -use substrate_fixed::types::I96F32; +use substrate_fixed::types::U96F32; #[freeze_struct("5cfb3c84c3af3116")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] @@ -139,7 +139,7 @@ impl Pallet { &origin_coldkey_account, destination_, &destination_coldkey_account, - I96F32::saturating_from_num(amount), + U96F32::saturating_from_num(amount), ) } } diff --git a/pallets/subtensor/src/staking/helpers.rs b/pallets/subtensor/src/staking/helpers.rs index 5aff56ea28..9ee04f36a8 100644 --- a/pallets/subtensor/src/staking/helpers.rs +++ b/pallets/subtensor/src/staking/helpers.rs @@ -1,5 +1,6 @@ use super::*; -use substrate_fixed::types::I96F32; +use safe_math::*; +use substrate_fixed::types::U96F32; use frame_support::traits::{ Imbalance, @@ -46,10 +47,10 @@ impl Pallet { Self::get_all_subnet_netuids() .iter() .map(|netuid| { - let alpha: I96F32 = I96F32::saturating_from_num( + let alpha: U96F32 = U96F32::saturating_from_num( Self::get_stake_for_hotkey_on_subnet(hotkey, *netuid), ); - let tao_price: I96F32 = Self::get_alpha_price(*netuid); + let tao_price: U96F32 = Self::get_alpha_price(*netuid); alpha.saturating_mul(tao_price).saturating_to_num::() }) .sum() @@ -66,9 +67,9 @@ impl Pallet { for (netuid, _) in Alpha::::iter_prefix((hotkey, coldkey)) { let alpha_stake = Self::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid); - let tao_price: I96F32 = Self::get_alpha_price(netuid); + let tao_price: U96F32 = Self::get_alpha_price(netuid); total_stake = total_stake.saturating_add( - I96F32::saturating_from_num(alpha_stake) + U96F32::saturating_from_num(alpha_stake) .saturating_mul(tao_price) .saturating_to_num::(), ); @@ -128,10 +129,9 @@ impl Pallet { pub fn get_hotkey_take(hotkey: &T::AccountId) -> u16 { Delegates::::get(hotkey) } - pub fn get_hotkey_take_float(hotkey: &T::AccountId) -> I96F32 { - I96F32::saturating_from_num(Self::get_hotkey_take(hotkey)) - .checked_div(I96F32::saturating_from_num(u16::MAX)) - .unwrap_or(I96F32::saturating_from_num(0.0)) + pub fn get_hotkey_take_float(hotkey: &T::AccountId) -> U96F32 { + U96F32::saturating_from_num(Self::get_hotkey_take(hotkey)) + .safe_div(U96F32::saturating_from_num(u16::MAX)) } /// Returns true if the hotkey account has been created. diff --git a/pallets/subtensor/src/staking/move_stake.rs b/pallets/subtensor/src/staking/move_stake.rs index 1ccc932157..4198d29efc 100644 --- a/pallets/subtensor/src/staking/move_stake.rs +++ b/pallets/subtensor/src/staking/move_stake.rs @@ -1,7 +1,7 @@ use super::*; use safe_math::*; use sp_core::Get; -use substrate_fixed::types::{I96F32, U64F64}; +use substrate_fixed::types::{U64F64, U96F32}; impl Pallet { /// Moves stake from one hotkey to another across subnets. @@ -343,7 +343,7 @@ impl Pallet { origin_coldkey, Some((destination_hotkey, destination_netuid)), destination_coldkey, - I96F32::saturating_from_num(alpha_amount), + U96F32::saturating_from_num(alpha_amount), ) .safe_div(2); diff --git a/pallets/subtensor/src/staking/remove_stake.rs b/pallets/subtensor/src/staking/remove_stake.rs index 96c04c9456..b902cb6641 100644 --- a/pallets/subtensor/src/staking/remove_stake.rs +++ b/pallets/subtensor/src/staking/remove_stake.rs @@ -1,5 +1,5 @@ use super::*; -use substrate_fixed::types::I96F32; +use substrate_fixed::types::U96F32; impl Pallet { /// ---- The implementation for the extrinsic remove_stake: Removes stake from a hotkey account and adds it onto a coldkey. @@ -63,7 +63,7 @@ impl Pallet { &coldkey, None, &coldkey, - I96F32::saturating_from_num(alpha_unstaked), + U96F32::saturating_from_num(alpha_unstaked), ); let tao_unstaked: u64 = Self::unstake_from_subnet(&hotkey, &coldkey, netuid, alpha_unstaked, fee); @@ -139,7 +139,7 @@ impl Pallet { &coldkey, None, &coldkey, - I96F32::saturating_from_num(alpha_unstaked), + U96F32::saturating_from_num(alpha_unstaked), ); if alpha_unstaked > 0 { @@ -216,7 +216,7 @@ impl Pallet { &coldkey, None, &coldkey, - I96F32::saturating_from_num(alpha_unstaked), + U96F32::saturating_from_num(alpha_unstaked), ); if alpha_unstaked > 0 { @@ -325,7 +325,7 @@ impl Pallet { &coldkey, None, &coldkey, - I96F32::saturating_from_num(alpha_unstaked), + U96F32::saturating_from_num(alpha_unstaked), ); let tao_unstaked = Self::unstake_from_subnet(&hotkey, &coldkey, netuid, possible_alpha, fee); diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index 7757851649..e54541d12e 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -2,7 +2,7 @@ use super::*; use safe_math::*; use share_pool::{SharePool, SharePoolDataOperations}; use sp_std::ops::Neg; -use substrate_fixed::types::{I64F64, I96F32, I110F18, U64F64}; +use substrate_fixed::types::{I64F64, I96F32, U64F64, U96F32, U110F18}; impl Pallet { /// Retrieves the total alpha issuance for a given subnet. @@ -30,34 +30,35 @@ impl Pallet { /// /// # Returns /// * `I96F32` - The price of alpha for the specified subnet. - pub fn get_alpha_price(netuid: u16) -> I96F32 { + pub fn get_alpha_price(netuid: u16) -> U96F32 { if netuid == Self::get_root_netuid() { - return I96F32::saturating_from_num(1.0); // Root. + return U96F32::saturating_from_num(1.0); // Root. } if SubnetMechanism::::get(netuid) == 0 { - return I96F32::saturating_from_num(1.0); // Stable + return U96F32::saturating_from_num(1.0); // Stable } if SubnetAlphaIn::::get(netuid) == 0 { - I96F32::saturating_from_num(0) + U96F32::saturating_from_num(0) } else { - I96F32::saturating_from_num(SubnetTAO::::get(netuid)) - .checked_div(I96F32::saturating_from_num(SubnetAlphaIn::::get(netuid))) - .unwrap_or(I96F32::saturating_from_num(0)) + U96F32::saturating_from_num(SubnetTAO::::get(netuid)) + .checked_div(U96F32::saturating_from_num(SubnetAlphaIn::::get(netuid))) + .unwrap_or(U96F32::saturating_from_num(0)) } } - pub fn get_moving_alpha_price(netuid: u16) -> I96F32 { + pub fn get_moving_alpha_price(netuid: u16) -> U96F32 { + let one = U96F32::saturating_from_num(1.0); if netuid == Self::get_root_netuid() { // Root. - I96F32::saturating_from_num(1.0) + one } else if SubnetMechanism::::get(netuid) == 0 { // Stable - I96F32::saturating_from_num(1.0) + one } else { - SubnetMovingPrice::::get(netuid) + U96F32::saturating_from_num(SubnetMovingPrice::::get(netuid)) } } pub fn update_moving_price(netuid: u16) { - let blocks_since_registration = I96F32::saturating_from_num( + let blocks_since_registration = U96F32::saturating_from_num( Self::get_current_block_as_u64().saturating_sub(NetworkRegisteredAt::::get(netuid)), ); @@ -66,16 +67,20 @@ impl Pallet { // will take in order for the distance between current EMA of price and current price to shorten // by half. let halving_time = EMAPriceHalvingBlocks::::get(netuid); - let alpha: I96F32 = - SubnetMovingAlpha::::get().saturating_mul(blocks_since_registration.safe_div( - blocks_since_registration.saturating_add(I96F32::saturating_from_num(halving_time)), - )); - let minus_alpha: I96F32 = I96F32::saturating_from_num(1.0).saturating_sub(alpha); - let current_price: I96F32 = alpha - .saturating_mul(Self::get_alpha_price(netuid).min(I96F32::saturating_from_num(1.0))); - let current_moving: I96F32 = - minus_alpha.saturating_mul(Self::get_moving_alpha_price(netuid)); - let new_moving: I96F32 = current_price.saturating_add(current_moving); + let current_ma_unsigned = U96F32::saturating_from_num(SubnetMovingAlpha::::get()); + let alpha: U96F32 = current_ma_unsigned.saturating_mul(blocks_since_registration.safe_div( + blocks_since_registration.saturating_add(U96F32::saturating_from_num(halving_time)), + )); + // Because alpha = b / (b + h), where b and h > 0, alpha < 1, so 1 - alpha > 0. + // We can use unsigned type here: U96F32 + let one_minus_alpha: U96F32 = U96F32::saturating_from_num(1.0).saturating_sub(alpha); + let current_price: U96F32 = alpha + .saturating_mul(Self::get_alpha_price(netuid).min(U96F32::saturating_from_num(1.0))); + let current_moving: U96F32 = + one_minus_alpha.saturating_mul(Self::get_moving_alpha_price(netuid)); + // Convert batch to signed I96F32 to avoid migration of SubnetMovingPrice for now`` + let new_moving: I96F32 = + I96F32::saturating_from_num(current_price.saturating_add(current_moving)); SubnetMovingPrice::::insert(netuid, new_moving); } @@ -83,28 +88,28 @@ impl Pallet { /// /// This function performs the following steps: /// 1. Fetches the global weight from storage using the TaoWeight storage item. - /// 2. Converts the retrieved u64 value to a fixed-point number (I96F32). + /// 2. Converts the retrieved u64 value to a fixed-point number (U96F32). /// 3. Normalizes the weight by dividing it by the maximum possible u64 value. - /// 4. Returns the normalized weight as an I96F32 fixed-point number. + /// 4. Returns the normalized weight as an U96F32 fixed-point number. /// /// The normalization ensures that the returned value is always between 0 and 1, /// regardless of the actual stored weight value. /// /// # Returns - /// * `I96F32` - The normalized global global weight as a fixed-point number between 0 and 1. + /// * `U96F32` - The normalized global global weight as a fixed-point number between 0 and 1. /// /// # Note /// This function uses saturating division to prevent potential overflow errors. - pub fn get_tao_weight() -> I96F32 { + pub fn get_tao_weight() -> U96F32 { // Step 1: Fetch the global weight from storage let stored_weight = TaoWeight::::get(); - // Step 2: Convert the u64 weight to I96F32 - let weight_fixed = I96F32::saturating_from_num(stored_weight); + // Step 2: Convert the u64 weight to U96F32 + let weight_fixed = U96F32::saturating_from_num(stored_weight); // Step 3: Normalize the weight by dividing by u64::MAX // This ensures the result is always between 0 and 1 - weight_fixed.safe_div(I96F32::saturating_from_num(u64::MAX)) + weight_fixed.safe_div(U96F32::saturating_from_num(u64::MAX)) } /// Sets the global global weight in storage. @@ -237,13 +242,13 @@ impl Pallet { /// # Note /// This function uses saturating arithmetic to prevent overflows. pub fn get_tao_inherited_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: u16) -> u64 { - let initial_tao: I96F32 = I96F32::saturating_from_num( + let initial_tao: U96F32 = U96F32::saturating_from_num( Self::get_stake_for_hotkey_on_subnet(hotkey, Self::get_root_netuid()), ); // Initialize variables to track alpha allocated to children and inherited from parents. - let mut tao_to_children: I96F32 = I96F32::saturating_from_num(0); - let mut tao_from_parents: I96F32 = I96F32::saturating_from_num(0); + let mut tao_to_children: U96F32 = U96F32::saturating_from_num(0); + let mut tao_from_parents: U96F32 = U96F32::saturating_from_num(0); // Step 2: Retrieve the lists of parents and children for the hotkey on the subnet. let parents: Vec<(u64, T::AccountId)> = Self::get_parents(hotkey, netuid); @@ -264,16 +269,16 @@ impl Pallet { // Step 3: Calculate the total tao allocated to children. for (proportion, _) in children { // Convert the proportion to a normalized value between 0 and 1. - let normalized_proportion: I96F32 = I96F32::saturating_from_num(proportion) - .safe_div(I96F32::saturating_from_num(u64::MAX)); + let normalized_proportion: U96F32 = U96F32::saturating_from_num(proportion) + .safe_div(U96F32::saturating_from_num(u64::MAX)); log::trace!( "Normalized proportion for child: {:?}", normalized_proportion ); // Calculate the amount of tao to be allocated to this child. - let tao_proportion_to_child: I96F32 = - I96F32::saturating_from_num(initial_tao).saturating_mul(normalized_proportion); + let tao_proportion_to_child: U96F32 = + U96F32::saturating_from_num(initial_tao).saturating_mul(normalized_proportion); log::trace!("Tao proportion to child: {:?}", tao_proportion_to_child); // Add this child's allocation to the total tao allocated to children. @@ -284,7 +289,7 @@ impl Pallet { // Step 4: Calculate the total tao inherited from parents. for (proportion, parent) in parents { // Retrieve the parent's total stake on this subnet. - let parent_tao: I96F32 = I96F32::saturating_from_num( + let parent_tao: U96F32 = U96F32::saturating_from_num( Self::get_stake_for_hotkey_on_subnet(&parent, Self::get_root_netuid()), ); log::trace!( @@ -295,16 +300,16 @@ impl Pallet { ); // Convert the proportion to a normalized value between 0 and 1. - let normalized_proportion: I96F32 = I96F32::saturating_from_num(proportion) - .safe_div(I96F32::saturating_from_num(u64::MAX)); + let normalized_proportion: U96F32 = U96F32::saturating_from_num(proportion) + .safe_div(U96F32::saturating_from_num(u64::MAX)); log::trace!( "Normalized proportion from parent: {:?}", normalized_proportion ); // Calculate the amount of tao to be inherited from this parent. - let tao_proportion_from_parent: I96F32 = - I96F32::saturating_from_num(parent_tao).saturating_mul(normalized_proportion); + let tao_proportion_from_parent: U96F32 = + U96F32::saturating_from_num(parent_tao).saturating_mul(normalized_proportion); log::trace!( "Tao proportion from parent: {:?}", tao_proportion_from_parent @@ -316,7 +321,7 @@ impl Pallet { log::trace!("Total tao inherited from parents: {:?}", tao_from_parents); // Step 5: Calculate the final inherited tao for the hotkey. - let finalized_tao: I96F32 = initial_tao + let finalized_tao: U96F32 = initial_tao .saturating_sub(tao_to_children) // Subtract tao allocated to children .saturating_add(tao_from_parents); // Add tao inherited from parents log::trace!( @@ -332,8 +337,8 @@ impl Pallet { pub fn get_inherited_for_hotkey_on_subnet(hotkey: &T::AccountId, netuid: u16) -> u64 { // Step 1: Retrieve the initial total stake (alpha) for the hotkey on the specified subnet. - let initial_alpha: I96F32 = - I96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(hotkey, netuid)); + let initial_alpha: U96F32 = + U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(hotkey, netuid)); log::debug!( "Initial alpha for hotkey {:?} on subnet {}: {:?}", hotkey, @@ -345,8 +350,8 @@ impl Pallet { } // Initialize variables to track alpha allocated to children and inherited from parents. - let mut alpha_to_children: I96F32 = I96F32::saturating_from_num(0); - let mut alpha_from_parents: I96F32 = I96F32::saturating_from_num(0); + let mut alpha_to_children: U96F32 = U96F32::saturating_from_num(0); + let mut alpha_from_parents: U96F32 = U96F32::saturating_from_num(0); // Step 2: Retrieve the lists of parents and children for the hotkey on the subnet. let parents: Vec<(u64, T::AccountId)> = Self::get_parents(hotkey, netuid); @@ -367,16 +372,16 @@ impl Pallet { // Step 3: Calculate the total alpha allocated to children. for (proportion, _) in children { // Convert the proportion to a normalized value between 0 and 1. - let normalized_proportion: I96F32 = I96F32::saturating_from_num(proportion) - .safe_div(I96F32::saturating_from_num(u64::MAX)); + let normalized_proportion: U96F32 = U96F32::saturating_from_num(proportion) + .safe_div(U96F32::saturating_from_num(u64::MAX)); log::trace!( "Normalized proportion for child: {:?}", normalized_proportion ); // Calculate the amount of alpha to be allocated to this child. - let alpha_proportion_to_child: I96F32 = - I96F32::saturating_from_num(initial_alpha).saturating_mul(normalized_proportion); + let alpha_proportion_to_child: U96F32 = + U96F32::saturating_from_num(initial_alpha).saturating_mul(normalized_proportion); log::trace!("Alpha proportion to child: {:?}", alpha_proportion_to_child); // Add this child's allocation to the total alpha allocated to children. @@ -387,8 +392,8 @@ impl Pallet { // Step 4: Calculate the total alpha inherited from parents. for (proportion, parent) in parents { // Retrieve the parent's total stake on this subnet. - let parent_alpha: I96F32 = - I96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(&parent, netuid)); + let parent_alpha: U96F32 = + U96F32::saturating_from_num(Self::get_stake_for_hotkey_on_subnet(&parent, netuid)); log::trace!( "Parent alpha for parent {:?} on subnet {}: {:?}", parent, @@ -397,16 +402,16 @@ impl Pallet { ); // Convert the proportion to a normalized value between 0 and 1. - let normalized_proportion: I96F32 = I96F32::saturating_from_num(proportion) - .safe_div(I96F32::saturating_from_num(u64::MAX)); + let normalized_proportion: U96F32 = U96F32::saturating_from_num(proportion) + .safe_div(U96F32::saturating_from_num(u64::MAX)); log::trace!( "Normalized proportion from parent: {:?}", normalized_proportion ); // Calculate the amount of alpha to be inherited from this parent. - let alpha_proportion_from_parent: I96F32 = - I96F32::saturating_from_num(parent_alpha).saturating_mul(normalized_proportion); + let alpha_proportion_from_parent: U96F32 = + U96F32::saturating_from_num(parent_alpha).saturating_mul(normalized_proportion); log::trace!( "Alpha proportion from parent: {:?}", alpha_proportion_from_parent @@ -421,7 +426,7 @@ impl Pallet { ); // Step 5: Calculate the final inherited alpha for the hotkey. - let finalized_alpha: I96F32 = initial_alpha + let finalized_alpha: U96F32 = initial_alpha .saturating_sub(alpha_to_children) // Subtract alpha allocated to children .saturating_add(alpha_from_parents); // Add alpha inherited from parents log::trace!( @@ -620,15 +625,15 @@ impl Pallet { // Step 2: Initialized vars. if mechanism_id == 1 { // Step 3.a.1: Dynamic mechanism calculations - let tao_reserves: I110F18 = I110F18::saturating_from_num(SubnetTAO::::get(netuid)); - let alpha_reserves: I110F18 = - I110F18::saturating_from_num(SubnetAlphaIn::::get(netuid)); + let tao_reserves: U110F18 = U110F18::saturating_from_num(SubnetTAO::::get(netuid)); + let alpha_reserves: U110F18 = + U110F18::saturating_from_num(SubnetAlphaIn::::get(netuid)); // Step 3.a.2: Compute constant product k = alpha * tao - let k: I110F18 = alpha_reserves.saturating_mul(tao_reserves); + let k: U110F18 = alpha_reserves.saturating_mul(tao_reserves); // Calculate new alpha reserve - let new_alpha_reserves: I110F18 = - k.safe_div(tao_reserves.saturating_add(I110F18::saturating_from_num(tao))); + let new_alpha_reserves: U110F18 = + k.safe_div(tao_reserves.saturating_add(U110F18::saturating_from_num(tao))); // Step 3.a.3: Calculate alpha staked using the constant product formula // alpha_stake_recieved = current_alpha - (k / (current_tao + new_tao)) @@ -659,16 +664,16 @@ impl Pallet { // Step 2: Swap alpha and attain tao if mechanism_id == 1 { // Step 3.a.1: Dynamic mechanism calculations - let tao_reserves: I110F18 = I110F18::saturating_from_num(SubnetTAO::::get(netuid)); - let alpha_reserves: I110F18 = - I110F18::saturating_from_num(SubnetAlphaIn::::get(netuid)); + let tao_reserves: U110F18 = U110F18::saturating_from_num(SubnetTAO::::get(netuid)); + let alpha_reserves: U110F18 = + U110F18::saturating_from_num(SubnetAlphaIn::::get(netuid)); // Step 3.a.2: Compute constant product k = alpha * tao - let k: I110F18 = alpha_reserves.saturating_mul(tao_reserves); + let k: U110F18 = alpha_reserves.saturating_mul(tao_reserves); // Calculate new tao reserve - let new_tao_reserves: I110F18 = k - .checked_div(alpha_reserves.saturating_add(I110F18::saturating_from_num(alpha))) - .unwrap_or(I110F18::saturating_from_num(0)); + let new_tao_reserves: U110F18 = k + .checked_div(alpha_reserves.saturating_add(U110F18::saturating_from_num(alpha))) + .unwrap_or(U110F18::saturating_from_num(0)); // Step 3.a.3: Calculate alpha staked using the constant product formula // tao_recieved = tao_reserves - (k / (alpha_reserves + new_tao)) @@ -1081,7 +1086,7 @@ impl Pallet { _origin_coldkey: &T::AccountId, destination: Option<(&T::AccountId, u16)>, _destination_coldkey: &T::AccountId, - alpha_estimate: I96F32, + alpha_estimate: U96F32, ) -> u64 { match origin { // If origin is defined, we are removing/moving stake @@ -1103,11 +1108,11 @@ impl Pallet { // Otherwise, calculate the fee based on the alpha estimate let mut fee = alpha_estimate .saturating_mul( - I96F32::saturating_from_num(AlphaDividendsPerSubnet::::get( + U96F32::saturating_from_num(AlphaDividendsPerSubnet::::get( origin_netuid, &origin_hotkey, )) - .safe_div(I96F32::saturating_from_num( + .safe_div(U96F32::saturating_from_num( TotalHotkeyAlpha::::get(&origin_hotkey, origin_netuid), )), ) @@ -1116,7 +1121,7 @@ impl Pallet { // 0.005% per epoch matches to 44% annual in compound interest. Do not allow the fee // to be lower than that. (1.00005^(365*20) ~= 1.44) - let apr_20_percent = I96F32::saturating_from_num(0.00005); + let apr_20_percent = U96F32::saturating_from_num(0.00005); fee = fee.max( alpha_estimate .saturating_mul(apr_20_percent) diff --git a/pallets/subtensor/src/tests/children.rs b/pallets/subtensor/src/tests/children.rs index faf48a8366..34c7b5459b 100644 --- a/pallets/subtensor/src/tests/children.rs +++ b/pallets/subtensor/src/tests/children.rs @@ -4,7 +4,7 @@ use super::mock::*; use approx::assert_abs_diff_eq; use frame_support::{assert_err, assert_noop, assert_ok}; -use substrate_fixed::types::{I64F64, I96F32}; +use substrate_fixed::types::{I64F64, I96F32, U96F32}; use crate::{utils::rate_limiting::TransactionType, *}; use sp_core::U256; @@ -961,7 +961,7 @@ fn test_childkey_take_rate_limiting() { last_block, limit, passes, - current_block.saturating_sub(last_block) + current_block - last_block ); }; @@ -2764,9 +2764,7 @@ fn test_set_weights_no_parent() { // Set a minimum stake to set weights SubtensorModule::set_stake_threshold( - curr_stake_weight - .saturating_sub(I64F64::saturating_from_num(5)) - .saturating_to_num::(), + (curr_stake_weight - I64F64::from_num(5)).to_num::(), ); // Check if the stake for the hotkey is above @@ -3029,7 +3027,7 @@ fn test_parent_child_chain_emission() { // Set the weight of root TAO to be 0%, so only alpha is effective. SubtensorModule::set_tao_weight(0); - let emission: I96F32 = I96F32::from_num(SubtensorModule::get_block_emission().unwrap_or(0)); + let emission: U96F32 = U96F32::from_num(SubtensorModule::get_block_emission().unwrap_or(0)); // Set pending emission to 0 PendingEmission::::insert(netuid, 0); diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 0a95f6dd60..eaa1997556 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -6,8 +6,7 @@ use alloc::collections::BTreeMap; use approx::assert_abs_diff_eq; use frame_support::assert_ok; use sp_core::U256; -use substrate_fixed::types::I64F64; -use substrate_fixed::types::I96F32; +use substrate_fixed::types::{I64F64, I96F32, U96F32}; #[allow(clippy::arithmetic_side_effects)] fn close(value: u64, target: u64, eps: u64) { @@ -74,7 +73,7 @@ fn test_dynamic_function_various_values() { #[test] fn test_coinbase_basecase() { new_test_ext(1).execute_with(|| { - SubtensorModule::run_coinbase(I96F32::from_num(0.0)); + SubtensorModule::run_coinbase(U96F32::from_num(0.0)); }); } @@ -91,7 +90,7 @@ fn test_coinbase_tao_issuance_base() { let emission: u64 = 1_234_567; add_network(netuid, 1, 0); assert_eq!(SubnetTAO::::get(netuid), 0); - SubtensorModule::run_coinbase(I96F32::from_num(emission)); + SubtensorModule::run_coinbase(U96F32::from_num(emission)); assert_eq!(SubnetTAO::::get(netuid), emission); assert_eq!(TotalIssuance::::get(), emission); assert_eq!(TotalStake::::get(), emission); @@ -106,7 +105,7 @@ fn test_coinbase_tao_issuance_base_low() { let emission: u64 = 1; add_network(netuid, 1, 0); assert_eq!(SubnetTAO::::get(netuid), 0); - SubtensorModule::run_coinbase(I96F32::from_num(emission)); + SubtensorModule::run_coinbase(U96F32::from_num(emission)); assert_eq!(SubnetTAO::::get(netuid), emission); assert_eq!(TotalIssuance::::get(), emission); assert_eq!(TotalStake::::get(), emission); @@ -133,7 +132,7 @@ fn test_coinbase_tao_issuance_multiple() { assert_eq!(SubnetTAO::::get(netuid1), 0); assert_eq!(SubnetTAO::::get(netuid2), 0); assert_eq!(SubnetTAO::::get(netuid3), 0); - SubtensorModule::run_coinbase(I96F32::from_num(emission)); + SubtensorModule::run_coinbase(U96F32::from_num(emission)); assert_eq!(SubnetTAO::::get(netuid1), emission / 3); assert_eq!(SubnetTAO::::get(netuid2), emission / 3); assert_eq!(SubnetTAO::::get(netuid3), emission / 3); @@ -166,7 +165,7 @@ fn test_coinbase_tao_issuance_different_prices() { assert_eq!(SubnetTAO::::get(netuid1), 0); assert_eq!(SubnetTAO::::get(netuid2), 0); // Run the coinbase with the emission amount. - SubtensorModule::run_coinbase(I96F32::from_num(emission)); + SubtensorModule::run_coinbase(U96F32::from_num(emission)); // Assert tao emission is split evenly. assert_eq!(SubnetTAO::::get(netuid1), emission / 3); assert_eq!(SubnetTAO::::get(netuid2), emission / 3 + emission / 3); @@ -213,7 +212,7 @@ fn test_coinbase_moving_prices() { // Run moving 1 times. SubtensorModule::update_moving_price(netuid); // Assert price is ~ 100% of the real price. - assert!(I96F32::from_num(1.0) - SubtensorModule::get_moving_alpha_price(netuid) < 0.05); + assert!(U96F32::from_num(1.0) - SubtensorModule::get_moving_alpha_price(netuid) < 0.05); // Set price to zero. SubnetMovingPrice::::insert(netuid, I96F32::from_num(0)); SubnetMovingAlpha::::set(I96F32::from_num(0.1)); @@ -227,9 +226,10 @@ fn test_coinbase_moving_prices() { } // Assert price is > 50% of the real price. - assert!( - (I96F32::from_num(0.512325) - SubtensorModule::get_moving_alpha_price(netuid)).abs() - < 0.001 + assert_abs_diff_eq!( + 0.512325, + SubtensorModule::get_moving_alpha_price(netuid).to_num::(), + epsilon = 0.001 ); }); } @@ -305,7 +305,7 @@ fn test_coinbase_alpha_issuance_base() { SubnetTAO::::insert(netuid2, initial); SubnetAlphaIn::::insert(netuid2, initial); // Check initial - SubtensorModule::run_coinbase(I96F32::from_num(emission)); + SubtensorModule::run_coinbase(U96F32::from_num(emission)); // tao_in = 500_000 // alpha_in = 500_000/price = 500_000 assert_eq!(SubnetAlphaIn::::get(netuid1), initial + emission / 2); @@ -340,7 +340,7 @@ fn test_coinbase_alpha_issuance_different() { SubnetMovingPrice::::insert(netuid1, I96F32::from_num(1)); SubnetMovingPrice::::insert(netuid2, I96F32::from_num(2)); // Run coinbase - SubtensorModule::run_coinbase(I96F32::from_num(emission)); + SubtensorModule::run_coinbase(U96F32::from_num(emission)); // tao_in = 333_333 // alpha_in = 333_333/price = 333_333 + initial assert_eq!(SubnetAlphaIn::::get(netuid1), initial + emission / 3); @@ -376,7 +376,7 @@ fn test_coinbase_alpha_issuance_with_cap_trigger() { SubnetMovingPrice::::insert(netuid1, I96F32::from_num(1)); SubnetMovingPrice::::insert(netuid2, I96F32::from_num(2)); // Run coinbase - SubtensorModule::run_coinbase(I96F32::from_num(emission)); + SubtensorModule::run_coinbase(U96F32::from_num(emission)); // tao_in = 333_333 // alpha_in = 333_333/price > 1_000_000_000 --> 1_000_000_000 + initial_alpha assert_eq!( @@ -420,7 +420,7 @@ fn test_coinbase_alpha_issuance_with_cap_trigger_and_block_emission() { SubnetMovingPrice::::insert(netuid1, I96F32::from_num(1)); SubnetMovingPrice::::insert(netuid2, I96F32::from_num(2)); // Run coinbase - SubtensorModule::run_coinbase(I96F32::from_num(emission)); + SubtensorModule::run_coinbase(U96F32::from_num(emission)); // tao_in = 333_333 // alpha_in = 333_333/price > 1_000_000_000 --> 0 + initial_alpha assert_eq!(SubnetAlphaIn::::get(netuid1), initial_alpha); @@ -441,10 +441,10 @@ fn test_owner_cut_base() { add_network(netuid, 1, 0); SubtensorModule::set_tempo(netuid, 10000); // Large number (dont drain) SubtensorModule::set_subnet_owner_cut(0); - SubtensorModule::run_coinbase(I96F32::from_num(0)); + SubtensorModule::run_coinbase(U96F32::from_num(0)); assert_eq!(PendingOwnerCut::::get(netuid), 0); // No cut SubtensorModule::set_subnet_owner_cut(u16::MAX); - SubtensorModule::run_coinbase(I96F32::from_num(0)); + SubtensorModule::run_coinbase(U96F32::from_num(0)); assert_eq!(PendingOwnerCut::::get(netuid), 1_000_000_000); // Full cut. }); } @@ -456,14 +456,14 @@ fn test_pending_swapped() { let netuid: u16 = 1; let emission: u64 = 1_000_000; add_network(netuid, 1, 0); - SubtensorModule::run_coinbase(I96F32::from_num(0)); + SubtensorModule::run_coinbase(U96F32::from_num(0)); assert_eq!(PendingAlphaSwapped::::get(netuid), 0); // Zero tao weight and no root. SubnetTAO::::insert(0, 1_000_000_000); // Add root weight. - SubtensorModule::run_coinbase(I96F32::from_num(0)); + SubtensorModule::run_coinbase(U96F32::from_num(0)); assert_eq!(PendingAlphaSwapped::::get(netuid), 0); // Zero tao weight with 1 root. SubtensorModule::set_tempo(netuid, 10000); // Large number (dont drain) SubtensorModule::set_tao_weight(u64::MAX); // Set TAO weight to 1.0 - SubtensorModule::run_coinbase(I96F32::from_num(0)); + SubtensorModule::run_coinbase(U96F32::from_num(0)); assert_eq!(PendingAlphaSwapped::::get(netuid), 125000000); // 1 TAO / ( 1 + 3 ) = 0.25 * 1 / 2 = 125000000 assert_eq!( PendingEmission::::get(netuid), @@ -1484,19 +1484,19 @@ fn test_incentive_to_subnet_owner_is_burned() { fn test_calculate_dividend_distribution_totals() { new_test_ext(1).execute_with(|| { let mut stake_map: BTreeMap = BTreeMap::new(); - let mut dividends: BTreeMap = BTreeMap::new(); + let mut dividends: BTreeMap = BTreeMap::new(); let pending_validator_alpha: u64 = 183_123_567_452; let pending_tao: u64 = 837_120_949_872; - let tao_weight: I96F32 = I96F32::saturating_from_num(0.18); // 18% + let tao_weight: U96F32 = U96F32::saturating_from_num(0.18); // 18% let hotkeys = [U256::from(0), U256::from(1)]; // Stake map and dividends shouldn't matter for this test. stake_map.insert(hotkeys[0], (4_859_302, 2_342_352)); stake_map.insert(hotkeys[1], (23_423, 859_273)); - dividends.insert(hotkeys[0], 77_783_738.into()); - dividends.insert(hotkeys[1], 19_283_940.into()); + dividends.insert(hotkeys[0], 77_783_738_u64.into()); + dividends.insert(hotkeys[1], 19_283_940_u64.into()); let (alpha_dividends, tao_dividends) = SubtensorModule::calculate_dividend_distribution( pending_validator_alpha, @@ -1507,8 +1507,8 @@ fn test_calculate_dividend_distribution_totals() { ); // Verify the total of each dividends type is close to the inputs. - let total_alpha_dividends = alpha_dividends.values().sum::(); - let total_tao_dividends = tao_dividends.values().sum::(); + let total_alpha_dividends = alpha_dividends.values().sum::(); + let total_tao_dividends = tao_dividends.values().sum::(); assert_abs_diff_eq!( total_alpha_dividends.saturating_to_num::(), @@ -1527,19 +1527,19 @@ fn test_calculate_dividend_distribution_totals() { fn test_calculate_dividend_distribution_total_only_tao() { new_test_ext(1).execute_with(|| { let mut stake_map: BTreeMap = BTreeMap::new(); - let mut dividends: BTreeMap = BTreeMap::new(); + let mut dividends: BTreeMap = BTreeMap::new(); let pending_validator_alpha: u64 = 0; let pending_tao: u64 = 837_120_949_872; - let tao_weight: I96F32 = I96F32::saturating_from_num(0.18); // 18% + let tao_weight: U96F32 = U96F32::saturating_from_num(0.18); // 18% let hotkeys = [U256::from(0), U256::from(1)]; // Stake map and dividends shouldn't matter for this test. stake_map.insert(hotkeys[0], (4_859_302, 2_342_352)); stake_map.insert(hotkeys[1], (23_423, 859_273)); - dividends.insert(hotkeys[0], 77_783_738.into()); - dividends.insert(hotkeys[1], 19_283_940.into()); + dividends.insert(hotkeys[0], 77_783_738_u64.into()); + dividends.insert(hotkeys[1], 19_283_940_u64.into()); let (alpha_dividends, tao_dividends) = SubtensorModule::calculate_dividend_distribution( pending_validator_alpha, @@ -1550,8 +1550,8 @@ fn test_calculate_dividend_distribution_total_only_tao() { ); // Verify the total of each dividends type is close to the inputs. - let total_alpha_dividends = alpha_dividends.values().sum::(); - let total_tao_dividends = tao_dividends.values().sum::(); + let total_alpha_dividends = alpha_dividends.values().sum::(); + let total_tao_dividends = tao_dividends.values().sum::(); assert_abs_diff_eq!( total_alpha_dividends.saturating_to_num::(), @@ -1570,19 +1570,19 @@ fn test_calculate_dividend_distribution_total_only_tao() { fn test_calculate_dividend_distribution_total_no_tao_weight() { new_test_ext(1).execute_with(|| { let mut stake_map: BTreeMap = BTreeMap::new(); - let mut dividends: BTreeMap = BTreeMap::new(); + let mut dividends: BTreeMap = BTreeMap::new(); let pending_validator_alpha: u64 = 183_123_567_452; let pending_tao: u64 = 0; // If tao weight is 0, then only alpha dividends should be input. - let tao_weight: I96F32 = I96F32::saturating_from_num(0.0); // 0% + let tao_weight: U96F32 = U96F32::saturating_from_num(0.0); // 0% let hotkeys = [U256::from(0), U256::from(1)]; // Stake map and dividends shouldn't matter for this test. stake_map.insert(hotkeys[0], (4_859_302, 2_342_352)); stake_map.insert(hotkeys[1], (23_423, 859_273)); - dividends.insert(hotkeys[0], 77_783_738.into()); - dividends.insert(hotkeys[1], 19_283_940.into()); + dividends.insert(hotkeys[0], 77_783_738_u64.into()); + dividends.insert(hotkeys[1], 19_283_940_u64.into()); let (alpha_dividends, tao_dividends) = SubtensorModule::calculate_dividend_distribution( pending_validator_alpha, @@ -1593,8 +1593,8 @@ fn test_calculate_dividend_distribution_total_no_tao_weight() { ); // Verify the total of each dividends type is close to the inputs. - let total_alpha_dividends = alpha_dividends.values().sum::(); - let total_tao_dividends = tao_dividends.values().sum::(); + let total_alpha_dividends = alpha_dividends.values().sum::(); + let total_tao_dividends = tao_dividends.values().sum::(); assert_abs_diff_eq!( total_alpha_dividends.saturating_to_num::(), @@ -1613,19 +1613,19 @@ fn test_calculate_dividend_distribution_total_no_tao_weight() { fn test_calculate_dividend_distribution_total_only_alpha() { new_test_ext(1).execute_with(|| { let mut stake_map: BTreeMap = BTreeMap::new(); - let mut dividends: BTreeMap = BTreeMap::new(); + let mut dividends: BTreeMap = BTreeMap::new(); let pending_validator_alpha: u64 = 183_123_567_452; let pending_tao: u64 = 0; - let tao_weight: I96F32 = I96F32::saturating_from_num(0.18); // 18% + let tao_weight: U96F32 = U96F32::saturating_from_num(0.18); // 18% let hotkeys = [U256::from(0), U256::from(1)]; // Stake map and dividends shouldn't matter for this test. stake_map.insert(hotkeys[0], (4_859_302, 2_342_352)); stake_map.insert(hotkeys[1], (23_423, 859_273)); - dividends.insert(hotkeys[0], 77_783_738.into()); - dividends.insert(hotkeys[1], 19_283_940.into()); + dividends.insert(hotkeys[0], 77_783_738_u64.into()); + dividends.insert(hotkeys[1], 19_283_940_u64.into()); let (alpha_dividends, tao_dividends) = SubtensorModule::calculate_dividend_distribution( pending_validator_alpha, @@ -1636,8 +1636,8 @@ fn test_calculate_dividend_distribution_total_only_alpha() { ); // Verify the total of each dividends type is close to the inputs. - let total_alpha_dividends = alpha_dividends.values().sum::(); - let total_tao_dividends = tao_dividends.values().sum::(); + let total_alpha_dividends = alpha_dividends.values().sum::(); + let total_tao_dividends = tao_dividends.values().sum::(); assert_abs_diff_eq!( total_alpha_dividends.saturating_to_num::(), @@ -1672,7 +1672,7 @@ fn test_calculate_dividend_and_incentive_distribution() { let pending_validator_alpha = pending_alpha / 2; // Pay half to validators. let pending_tao: u64 = 0; let pending_swapped = 0; // Only alpha output. - let tao_weight: I96F32 = I96F32::saturating_from_num(0.0); // 0% + let tao_weight: U96F32 = U96F32::saturating_from_num(0.0); // 0% // Hotkey, Incentive, Dividend let hotkey_emission = vec![(hotkey, pending_alpha / 2, pending_alpha / 2)]; @@ -1689,7 +1689,7 @@ fn test_calculate_dividend_and_incentive_distribution() { let incentives_total = incentives.values().sum::(); let dividends_total = alpha_dividends .values() - .sum::() + .sum::() .saturating_to_num::(); assert_abs_diff_eq!( @@ -1719,7 +1719,7 @@ fn test_calculate_dividend_and_incentive_distribution_all_to_validators() { let pending_alpha = 123_456_789; let pending_validator_alpha = pending_alpha; // Pay all to validators. let pending_tao: u64 = 0; - let tao_weight: I96F32 = I96F32::saturating_from_num(0.0); // 0% + let tao_weight: U96F32 = U96F32::saturating_from_num(0.0); // 0% // Hotkey, Incentive, Dividend let hotkey_emission = vec![(hotkey, 0, pending_alpha)]; @@ -1736,7 +1736,7 @@ fn test_calculate_dividend_and_incentive_distribution_all_to_validators() { let incentives_total = incentives.values().sum::(); let dividends_total = alpha_dividends .values() - .sum::() + .sum::() .saturating_to_num::(); assert_eq!( @@ -1775,7 +1775,7 @@ fn test_calculate_dividends_and_incentives() { let incentives_total = incentives.values().sum::(); let dividends_total = dividends .values() - .sum::() + .sum::() .saturating_to_num::(); assert_eq!( @@ -1813,7 +1813,7 @@ fn test_calculate_dividends_and_incentives_only_validators() { let incentives_total = incentives.values().sum::(); let dividends_total = dividends .values() - .sum::() + .sum::() .saturating_to_num::(); assert_eq!(dividends_total, divdends); @@ -1849,7 +1849,7 @@ fn test_calculate_dividends_and_incentives_only_miners() { let incentives_total = incentives.values().sum::(); let dividends_total = dividends .values() - .sum::() + .sum::() .saturating_to_num::(); assert_eq!(incentives_total, incentive); @@ -2018,7 +2018,7 @@ fn test_run_coinbase_not_started() { assert!(SubtensorModule::should_run_epoch(netuid, current_block)); // Run coinbase with emission. - SubtensorModule::run_coinbase(I96F32::saturating_from_num(100_000_000)); + SubtensorModule::run_coinbase(U96F32::saturating_from_num(100_000_000)); // We expect that the epoch ran. assert_eq!(BlocksSinceLastStep::::get(netuid), 0); @@ -2100,7 +2100,7 @@ fn test_run_coinbase_not_started_start_after() { assert!(SubtensorModule::should_run_epoch(netuid, current_block)); // Run coinbase with emission. - SubtensorModule::run_coinbase(I96F32::saturating_from_num(100_000_000)); + SubtensorModule::run_coinbase(U96F32::saturating_from_num(100_000_000)); // We expect that the epoch ran. assert_eq!(BlocksSinceLastStep::::get(netuid), 0); @@ -2120,7 +2120,7 @@ fn test_run_coinbase_not_started_start_after() { ); // Run coinbase with emission. - SubtensorModule::run_coinbase(I96F32::saturating_from_num(100_000_000)); + SubtensorModule::run_coinbase(U96F32::saturating_from_num(100_000_000)); // We expect that the epoch ran. assert_eq!(BlocksSinceLastStep::::get(netuid), 0); diff --git a/pallets/subtensor/src/tests/delegate_info.rs b/pallets/subtensor/src/tests/delegate_info.rs index 6fbcbbfb87..fa9aa942f7 100644 --- a/pallets/subtensor/src/tests/delegate_info.rs +++ b/pallets/subtensor/src/tests/delegate_info.rs @@ -22,9 +22,8 @@ fn test_return_per_1000_tao() { // We expect 82 TAO per day with 10% of total_stake let expected_return_per_1000 = U64F64::from_num(82.0); - let diff_from_expected: f64 = (return_per_1000 / U64F64::from_num(1e9)) - .saturating_sub(expected_return_per_1000) - .to_num::(); + let diff_from_expected: f64 = + ((return_per_1000 / U64F64::from_num(1e9)) - expected_return_per_1000).to_num::(); let eps: f64 = 0.0005e9; // Precision within 0.0005 TAO assert!( diff --git a/pallets/subtensor/src/tests/emission.rs b/pallets/subtensor/src/tests/emission.rs index 61a08ccd32..c4d8d51e3c 100644 --- a/pallets/subtensor/src/tests/emission.rs +++ b/pallets/subtensor/src/tests/emission.rs @@ -102,7 +102,7 @@ fn test_consecutive_blocks() { let mut last_result = SubtensorModule::blocks_until_next_epoch(netuid, tempo, 0); for i in 1..tempo - 1 { let current_result = SubtensorModule::blocks_until_next_epoch(netuid, tempo, i as u64); - assert_eq!(current_result, last_result.saturating_sub(1)); + assert_eq!(current_result, last_result - 1); last_result = current_result; } }); diff --git a/pallets/subtensor/src/tests/move_stake.rs b/pallets/subtensor/src/tests/move_stake.rs index afaee9b980..0b7584a4f0 100644 --- a/pallets/subtensor/src/tests/move_stake.rs +++ b/pallets/subtensor/src/tests/move_stake.rs @@ -3,7 +3,7 @@ use crate::*; use approx::assert_abs_diff_eq; use frame_support::{assert_err, assert_noop, assert_ok}; use sp_core::{Get, U256}; -use substrate_fixed::types::{I96F32, U64F64}; +use substrate_fixed::types::{U64F64, U96F32}; // 1. test_do_move_success // Description: Test a successful move of stake between two hotkeys in the same subnet @@ -112,9 +112,9 @@ fn test_do_move_different_subnets() { ), 0 ); - let alpha_fee: I96F32 = - I96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); - let expected_value = I96F32::from_num(alpha) + let alpha_fee: U96F32 = + U96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); + let expected_value = U96F32::from_num(alpha) * SubtensorModule::get_alpha_price(origin_netuid) / SubtensorModule::get_alpha_price(destination_netuid); assert_abs_diff_eq!( @@ -709,8 +709,8 @@ fn test_do_move_storage_updates() { 0 ); let alpha_fee = - I96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); - let alpha2 = I96F32::from_num(alpha) * SubtensorModule::get_alpha_price(origin_netuid) + U96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); + let alpha2 = U96F32::from_num(alpha) * SubtensorModule::get_alpha_price(origin_netuid) / SubtensorModule::get_alpha_price(destination_netuid); assert_abs_diff_eq!( SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( @@ -1080,7 +1080,7 @@ fn test_do_transfer_different_subnets() { &destination_coldkey, destination_netuid, ); - let expected_value = I96F32::from_num(stake_amount - fee) + let expected_value = U96F32::from_num(stake_amount - fee) / SubtensorModule::get_alpha_price(destination_netuid); assert_abs_diff_eq!( dest_stake, @@ -1134,8 +1134,8 @@ fn test_do_swap_success() { destination_netuid, ); let alpha_fee = - I96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); - let expected_value = I96F32::from_num(alpha_before) + U96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); + let expected_value = U96F32::from_num(alpha_before) * SubtensorModule::get_alpha_price(origin_netuid) / SubtensorModule::get_alpha_price(destination_netuid); assert_abs_diff_eq!( @@ -1353,8 +1353,8 @@ fn test_do_swap_partial_stake() { ); let alpha_fee = - I96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); - let expected_value = I96F32::from_num(swap_amount) + U96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); + let expected_value = U96F32::from_num(swap_amount) * SubtensorModule::get_alpha_price(origin_netuid) / SubtensorModule::get_alpha_price(destination_netuid); assert_abs_diff_eq!( @@ -1408,8 +1408,8 @@ fn test_do_swap_storage_updates() { ); let alpha_fee = - I96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); - let expected_value = I96F32::from_num(alpha) + U96F32::from_num(fee) / SubtensorModule::get_alpha_price(destination_netuid); + let expected_value = U96F32::from_num(alpha) * SubtensorModule::get_alpha_price(origin_netuid) / SubtensorModule::get_alpha_price(destination_netuid); assert_abs_diff_eq!( @@ -1543,7 +1543,7 @@ fn test_swap_stake_limit_validate() { // Setup limit price so that it doesn't allow much slippage at all let limit_price = ((SubtensorModule::get_alpha_price(origin_netuid) / SubtensorModule::get_alpha_price(destination_netuid)) - * I96F32::from_num(1_000_000_000)) + * U96F32::from_num(1_000_000_000)) .to_num::() - 1_u64; @@ -1737,8 +1737,8 @@ fn test_move_stake_specific_stake_into_subnet_fail() { 0 ); let fee = DefaultStakingFee::::get(); - let alpha_fee: I96F32 = I96F32::from_num(fee) / SubtensorModule::get_alpha_price(netuid); - let expected_value = I96F32::from_num(alpha_to_move) + let alpha_fee: U96F32 = U96F32::from_num(fee) / SubtensorModule::get_alpha_price(netuid); + let expected_value = U96F32::from_num(alpha_to_move) * SubtensorModule::get_alpha_price(origin_netuid) / SubtensorModule::get_alpha_price(netuid); assert_abs_diff_eq!( diff --git a/pallets/subtensor/src/tests/staking.rs b/pallets/subtensor/src/tests/staking.rs index 1fc4e7b590..b4506c65c6 100644 --- a/pallets/subtensor/src/tests/staking.rs +++ b/pallets/subtensor/src/tests/staking.rs @@ -387,7 +387,7 @@ fn test_remove_stake_ok_no_emission() { // Add subnet TAO for the equivalent amount added at price let amount_tao = - I96F32::saturating_from_num(amount) * SubtensorModule::get_alpha_price(netuid); + U96F32::saturating_from_num(amount) * SubtensorModule::get_alpha_price(netuid); SubnetTAO::::mutate(netuid, |v| *v += amount_tao.saturating_to_num::()); TotalStake::::mutate(|v| *v += amount_tao.saturating_to_num::()); @@ -404,7 +404,7 @@ fn test_remove_stake_ok_no_emission() { &coldkey_account_id, None, &coldkey_account_id, - I96F32::saturating_from_num(amount), + U96F32::saturating_from_num(amount), ); // we do not expect the exact amount due to slippage @@ -568,7 +568,7 @@ fn test_remove_stake_total_balance_no_change() { // Add subnet TAO for the equivalent amount added at price let amount_tao = - I96F32::saturating_from_num(amount) * SubtensorModule::get_alpha_price(netuid); + U96F32::saturating_from_num(amount) * SubtensorModule::get_alpha_price(netuid); SubnetTAO::::mutate(netuid, |v| *v += amount_tao.saturating_to_num::()); TotalStake::::mutate(|v| *v += amount_tao.saturating_to_num::()); @@ -585,7 +585,7 @@ fn test_remove_stake_total_balance_no_change() { &coldkey_account_id, None, &coldkey_account_id, - I96F32::saturating_from_num(amount), + U96F32::saturating_from_num(amount), ); assert_abs_diff_eq!( SubtensorModule::get_coldkey_balance(&coldkey_account_id), @@ -3526,8 +3526,11 @@ fn test_add_stake_limit_ok() { // Check that price has updated to ~24 = (150+450) / (100 - 75) let exp_price = U96F32::from_num(24.0); let current_price: U96F32 = U96F32::from_num(SubtensorModule::get_alpha_price(netuid)); - assert!(exp_price.saturating_sub(current_price) < 0.0001); - assert!(current_price.saturating_sub(exp_price) < 0.0001); + assert_abs_diff_eq!( + exp_price.to_num::(), + current_price.to_num::(), + epsilon = 0.0001, + ); }); } diff --git a/pallets/subtensor/src/tests/staking2.rs b/pallets/subtensor/src/tests/staking2.rs index 57f880ffba..6fbabf83b2 100644 --- a/pallets/subtensor/src/tests/staking2.rs +++ b/pallets/subtensor/src/tests/staking2.rs @@ -6,7 +6,7 @@ use frame_support::{ weights::Weight, }; use sp_core::U256; -use substrate_fixed::types::I96F32; +use substrate_fixed::types::{I96F32, U96F32}; // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --workspace --test staking2 -- test_swap_tao_for_alpha_dynamic_mechanism --exact --nocapture #[test] @@ -673,7 +673,7 @@ fn test_stake_fee_api() { &coldkey1, Some((&hotkey1, netuid0)), &coldkey1, - I96F32::saturating_from_num(stake_amount), + U96F32::saturating_from_num(stake_amount), ); assert_eq!(stake_fee_0, dynamic_fee_0); @@ -690,7 +690,7 @@ fn test_stake_fee_api() { &coldkey1, None, &coldkey1, - I96F32::saturating_from_num(stake_amount), + U96F32::saturating_from_num(stake_amount), ); assert_eq!(stake_fee_1, dynamic_fee_1); @@ -707,7 +707,7 @@ fn test_stake_fee_api() { &coldkey1, Some((&hotkey1, netuid0)), &coldkey1, - I96F32::saturating_from_num(stake_amount), + U96F32::saturating_from_num(stake_amount), ); assert_eq!(stake_fee_2, dynamic_fee_2); @@ -724,7 +724,7 @@ fn test_stake_fee_api() { &coldkey1, Some((&hotkey2, root_netuid)), &coldkey1, - I96F32::saturating_from_num(stake_amount), + U96F32::saturating_from_num(stake_amount), ); assert_eq!(stake_fee_3, dynamic_fee_3); @@ -741,7 +741,7 @@ fn test_stake_fee_api() { &coldkey1, Some((&hotkey1, root_netuid)), &coldkey2, - I96F32::saturating_from_num(stake_amount), + U96F32::saturating_from_num(stake_amount), ); assert_eq!(stake_fee_4, dynamic_fee_4); @@ -758,7 +758,7 @@ fn test_stake_fee_api() { &coldkey1, Some((&hotkey1, root_netuid)), &coldkey1, - I96F32::saturating_from_num(stake_amount), + U96F32::saturating_from_num(stake_amount), ); assert_eq!(stake_fee_5, dynamic_fee_5); @@ -775,7 +775,7 @@ fn test_stake_fee_api() { &coldkey1, Some((&hotkey2, netuid0)), &coldkey1, - I96F32::saturating_from_num(stake_amount), + U96F32::saturating_from_num(stake_amount), ); assert_eq!(stake_fee_6, dynamic_fee_6); @@ -792,7 +792,7 @@ fn test_stake_fee_api() { &coldkey1, Some((&hotkey1, netuid0)), &coldkey2, - I96F32::saturating_from_num(stake_amount), + U96F32::saturating_from_num(stake_amount), ); assert_eq!(stake_fee_7, dynamic_fee_7); @@ -809,7 +809,7 @@ fn test_stake_fee_api() { &coldkey1, Some((&hotkey1, netuid1)), &coldkey1, - I96F32::saturating_from_num(stake_amount), + U96F32::saturating_from_num(stake_amount), ); assert_eq!(stake_fee_8, dynamic_fee_8); }); @@ -861,7 +861,7 @@ fn test_stake_fee_calculation() { &coldkey1, Some((&hotkey1, netuid0)), &coldkey1, - I96F32::from_num(stake_amount), + U96F32::from_num(stake_amount), ); // Default for adding stake assert_eq!(stake_fee_0, default_fee); @@ -871,7 +871,7 @@ fn test_stake_fee_calculation() { &coldkey1, None, &coldkey1, - I96F32::from_num(stake_amount), + U96F32::from_num(stake_amount), ); // Default for removing stake from root assert_eq!(stake_fee_1, default_fee); @@ -881,7 +881,7 @@ fn test_stake_fee_calculation() { &coldkey1, Some((&hotkey1, netuid0)), &coldkey1, - I96F32::from_num(stake_amount), + U96F32::from_num(stake_amount), ); // Default for moving stake from root to non-root assert_eq!(stake_fee_2, default_fee); @@ -891,7 +891,7 @@ fn test_stake_fee_calculation() { &coldkey1, Some((&hotkey2, root_netuid)), &coldkey1, - I96F32::from_num(stake_amount), + U96F32::from_num(stake_amount), ); // Default for moving stake between hotkeys on root assert_eq!(stake_fee_3, default_fee); @@ -901,7 +901,7 @@ fn test_stake_fee_calculation() { &coldkey1, Some((&hotkey1, root_netuid)), &coldkey2, - I96F32::from_num(stake_amount), + U96F32::from_num(stake_amount), ); // Default for moving stake between coldkeys on root assert_eq!(stake_fee_4, default_fee); @@ -911,7 +911,7 @@ fn test_stake_fee_calculation() { &coldkey1, Some((&hotkey1, root_netuid)), &coldkey1, - I96F32::from_num(stake_amount), + U96F32::from_num(stake_amount), ); // Charged a dynamic fee assert_ne!(stake_fee_5, default_fee); @@ -921,7 +921,7 @@ fn test_stake_fee_calculation() { &coldkey1, Some((&hotkey2, netuid0)), &coldkey1, - I96F32::from_num(stake_amount), + U96F32::from_num(stake_amount), ); // Charge the default fee assert_eq!(stake_fee_6, default_fee); @@ -931,7 +931,7 @@ fn test_stake_fee_calculation() { &coldkey1, Some((&hotkey1, netuid0)), &coldkey2, - I96F32::from_num(stake_amount), + U96F32::from_num(stake_amount), ); // Charge the default fee; stake did not leave the subnet. assert_eq!(stake_fee_7, default_fee); @@ -941,7 +941,7 @@ fn test_stake_fee_calculation() { &coldkey1, Some((&hotkey1, netuid1)), &coldkey1, - I96F32::from_num(stake_amount), + U96F32::from_num(stake_amount), ); // Charged a dynamic fee assert_ne!(stake_fee_8, default_fee); }); diff --git a/pallets/subtensor/src/tests/swap_coldkey.rs b/pallets/subtensor/src/tests/swap_coldkey.rs index 96394743a4..beb4df59a5 100644 --- a/pallets/subtensor/src/tests/swap_coldkey.rs +++ b/pallets/subtensor/src/tests/swap_coldkey.rs @@ -14,7 +14,7 @@ use frame_support::traits::schedule::DispatchTime; use frame_support::traits::schedule::v3::Named as ScheduleNamed; use sp_core::{Get, H256, U256}; use sp_runtime::DispatchError; -use substrate_fixed::types::I96F32; +use substrate_fixed::types::U96F32; // // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_coldkey -- test_swap_total_hotkey_coldkey_stakes_this_interval --exact --nocapture // #[test] @@ -539,7 +539,7 @@ fn test_swap_concurrent_modifications() { let initial_stake = 1_000_000_000_000; let additional_stake = 500_000_000_000; let initial_stake_alpha = - I96F32::from(initial_stake).saturating_mul(SubtensorModule::get_alpha_price(netuid)); + U96F32::from(initial_stake).saturating_mul(SubtensorModule::get_alpha_price(netuid)); let fee = SubtensorModule::calculate_staking_fee( None, &new_coldkey, diff --git a/pallets/subtensor/src/tests/weights.rs b/pallets/subtensor/src/tests/weights.rs index 5fcbbcb698..14b80a0310 100644 --- a/pallets/subtensor/src/tests/weights.rs +++ b/pallets/subtensor/src/tests/weights.rs @@ -3110,7 +3110,7 @@ fn test_reveal_at_exact_block() { let current_block = SubtensorModule::get_current_block_as_u64(); if current_block < reveal_epoch_start_block { // Advance to one block before the reveal epoch starts - let blocks_to_advance = reveal_epoch_start_block.saturating_sub(current_block); + let blocks_to_advance = reveal_epoch_start_block - current_block; if blocks_to_advance > 1 { // Advance to one block before the reveal epoch let new_block_number = current_block + blocks_to_advance - 1; @@ -3181,9 +3181,7 @@ fn test_reveal_at_exact_block() { let commit_epoch = SubtensorModule::get_epoch_index(netuid, commit_block); let reveal_epoch = commit_epoch.saturating_add(reveal_period); let expiration_epoch = reveal_epoch.saturating_add(1); - let expiration_epoch_start_block = expiration_epoch - .saturating_mul(tempo_plus_one) - .saturating_sub(netuid_plus_one); + let expiration_epoch_start_block = expiration_epoch * tempo_plus_one - netuid_plus_one; let current_block = SubtensorModule::get_current_block_as_u64(); if current_block < expiration_epoch_start_block { diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index 19d07248d2..c46cf8b36f 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -7,7 +7,7 @@ use safe_math::*; use sp_core::Get; use sp_core::U256; use sp_runtime::Saturating; -use substrate_fixed::types::{I32F32, I96F32}; +use substrate_fixed::types::{I32F32, U96F32}; impl Pallet { pub fn ensure_subnet_owner_or_root( @@ -598,9 +598,9 @@ impl Pallet { pub fn get_subnet_owner_cut() -> u16 { SubnetOwnerCut::::get() } - pub fn get_float_subnet_owner_cut() -> I96F32 { - I96F32::saturating_from_num(SubnetOwnerCut::::get()) - .safe_div(I96F32::saturating_from_num(u16::MAX)) + pub fn get_float_subnet_owner_cut() -> U96F32 { + U96F32::saturating_from_num(SubnetOwnerCut::::get()) + .safe_div(U96F32::saturating_from_num(u16::MAX)) } pub fn set_subnet_owner_cut(subnet_owner_cut: u16) { SubnetOwnerCut::::set(subnet_owner_cut); diff --git a/pallets/utility/src/tests.rs b/pallets/utility/src/tests.rs index 16ae0a3a51..34ed8d323e 100644 --- a/pallets/utility/src/tests.rs +++ b/pallets/utility/src/tests.rs @@ -18,6 +18,7 @@ // Tests for Utility Pallet #![cfg(test)] +#![allow(clippy::arithmetic_side_effects)] use super::*; @@ -689,7 +690,7 @@ fn batch_all_handles_weight_refund() { assert_err_ignore_postinfo!(result, "The cake is a lie."); assert_eq!( extract_actual_weight(&result, &info), - info.weight.saturating_sub(diff.saturating_mul(batch_len)) + info.weight - diff * batch_len ); // Partial batch completion diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index dc00e1d2fa..96e4306002 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -207,7 +207,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: 258, + spec_version: 259, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1,