diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 53ac3c6ac..66d1ab458 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -34,13 +34,17 @@ impl Pallet { // 2. Get subnets to emit to and emissions let subnet_emissions = Self::get_subnet_block_emissions(&subnets, block_emission); let subnets_to_emit_to: Vec = subnet_emissions.keys().copied().collect(); + let total_ema_price: U96F32 = subnets_to_emit_to + .iter() + .map(|netuid| Self::get_moving_alpha_price(*netuid)) + .sum(); // --- 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 is_subsidized: BTreeMap = BTreeMap::new(); + let subsidy_mode = total_ema_price <= U96F32::saturating_from_num(1); // Only calculate for subnets that we are emitting to. for netuid_i in subnets_to_emit_to.iter() { // Get subnet price. @@ -79,15 +83,11 @@ impl Pallet { ); if let Ok(buy_swap_result_ok) = buy_swap_result { let bought_alpha = AlphaCurrency::from(buy_swap_result_ok.amount_paid_out); - SubnetAlphaOut::::mutate(*netuid_i, |total| { - *total = total.saturating_sub(bought_alpha); - }); + Self::recycle_subnet_alpha(*netuid_i, bought_alpha); } - is_subsidized.insert(*netuid_i, true); } else { tao_in_i = default_tao_in_i; alpha_in_i = tao_in_i.safe_div_or(price_i, alpha_emission_i); - is_subsidized.insert(*netuid_i, false); } log::debug!("alpha_in_i: {alpha_in_i:?}"); @@ -198,8 +198,7 @@ impl Pallet { let pending_alpha: U96F32 = alpha_out_i.saturating_sub(root_alpha); log::debug!("pending_alpha: {pending_alpha:?}"); - let subsidized: bool = *is_subsidized.get(netuid_i).unwrap_or(&false); - if !subsidized { + if !subsidy_mode { PendingRootAlphaDivs::::mutate(*netuid_i, |total| { *total = total.saturating_add(tou64!(root_alpha).into()); }); diff --git a/pallets/subtensor/src/staking/claim_root.rs b/pallets/subtensor/src/staking/claim_root.rs index 7071a1ad5..85d3c56b3 100644 --- a/pallets/subtensor/src/staking/claim_root.rs +++ b/pallets/subtensor/src/staking/claim_root.rs @@ -3,7 +3,7 @@ use frame_support::weights::Weight; use sp_core::Get; use sp_std::collections::btree_set::BTreeSet; use substrate_fixed::types::I96F32; -use subtensor_swap_interface::SwapHandler; +use subtensor_swap_interface::{Order, SwapHandler}; impl Pallet { pub fn block_hash_to_indices(block_hash: T::Hash, k: u64, n: u64) -> Vec { @@ -196,6 +196,13 @@ impl Pallet { netuid, owed_u64.into(), ); + + // Sim-swap and record positive TAO flow + let order = GetTaoForAlpha::::with_amount(AlphaCurrency::from(owed_u64)); + let maybe_result = T::SwapInterface::sim_swap(netuid.into(), order); + if let Ok(result) = maybe_result { + Self::record_tao_inflow(netuid, TaoCurrency::from(result.amount_paid_out)); + } } }; diff --git a/pallets/subtensor/src/tests/claim_root.rs b/pallets/subtensor/src/tests/claim_root.rs index e73417a32..b973ebf2d 100644 --- a/pallets/subtensor/src/tests/claim_root.rs +++ b/pallets/subtensor/src/tests/claim_root.rs @@ -3,12 +3,7 @@ use crate::tests::mock::{ RuntimeOrigin, SubtensorModule, Test, add_dynamic_network, new_test_ext, run_to_block, }; -use crate::{ - DefaultMinRootClaimAmount, Error, MAX_NUM_ROOT_CLAIMS, MAX_ROOT_CLAIM_THRESHOLD, NetworksAdded, - NumRootClaim, NumStakingColdkeys, PendingRootAlphaDivs, RootClaimable, RootClaimableThreshold, - StakingColdkeys, StakingColdkeysByIndex, SubnetAlphaIn, SubnetMechanism, SubnetTAO, - SubtokenEnabled, Tempo, pallet, -}; +use crate::*; use crate::{RootClaimType, RootClaimTypeEnum, RootClaimed}; use approx::assert_abs_diff_eq; use frame_support::dispatch::RawOrigin; @@ -118,6 +113,8 @@ fn test_claim_root_with_drain_emissions() { ),); assert_eq!(RootClaimType::::get(coldkey), RootClaimTypeEnum::Keep); + let tao_flow_before = SubnetTaoFlow::::get(netuid); + assert_ok!(SubtensorModule::claim_root( RuntimeOrigin::signed(coldkey), BTreeSet::from([netuid]) @@ -138,6 +135,9 @@ fn test_claim_root_with_drain_emissions() { let claimed = RootClaimed::::get((netuid, &hotkey, &coldkey)); assert_eq!(u128::from(new_stake), claimed); + // Check positive TAO flow is recorded + assert!(SubnetTaoFlow::::get(netuid) > tao_flow_before); + // Distribute pending root alpha (round 2) SubtensorModule::drain_pending_emission( @@ -763,6 +763,7 @@ fn test_claim_root_with_run_coinbase() { let root_stake = 200_000_000u64; SubnetTAO::::insert(NetUid::ROOT, TaoCurrency::from(root_stake)); + SubnetMovingPrice::::insert(netuid, I96F32::from(2)); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, @@ -869,6 +870,7 @@ fn test_claim_root_with_block_emissions() { let root_stake = 200_000_000u64; SubnetTAO::::insert(NetUid::ROOT, TaoCurrency::from(root_stake)); + SubnetMovingPrice::::insert(netuid, I96F32::from(2)); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, @@ -973,6 +975,9 @@ fn test_claim_root_coinbase_distribution() { let initial_tao = 200_000_000u64; SubnetTAO::::insert(NetUid::ROOT, TaoCurrency::from(initial_tao)); + // Avoid subsidy mode + SubnetMovingPrice::::insert(netuid, I96F32::from(2)); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &coldkey, @@ -996,7 +1001,12 @@ fn test_claim_root_coinbase_distribution() { run_to_block(2); let alpha_issuance = SubtensorModule::get_alpha_issuance(netuid); - assert_eq!(initial_alpha_issuance + alpha_emissions, alpha_issuance); + + // Both alpha_in and alpha_out are increased, hence multiply emissions by 2 to get total issuance increase + assert_eq!( + initial_alpha_issuance + alpha_emissions * AlphaCurrency::from(2), + alpha_issuance + ); let root_prop = initial_tao as f64 / (u64::from(alpha_issuance) + initial_tao) as f64; let root_validators_share = 0.5f64; diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 266a75570..d95eb45ee 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -220,7 +220,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 338, + spec_version: 339, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1,