Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 110 additions & 110 deletions pallets/proxy/src/weights.rs

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions pallets/subtensor/src/coinbase/block_step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ use substrate_fixed::types::U96F32;
use subtensor_runtime_common::NetUid;

impl<T: Config + pallet_drand::Config> Pallet<T> {
pub fn get_burn_root_prop() -> bool {
BurnRootProp::<T>::get()
}

pub fn set_burn_root_prop(enabled: bool) {
BurnRootProp::<T>::put(enabled);
Self::deposit_event(Event::BurnRootPropSet { enabled });
}

/// Executes the necessary operations for each block.
pub fn block_step() -> Result<(), &'static str> {
let block_number: u64 = Self::get_current_block_as_u64();
Expand Down Expand Up @@ -65,6 +74,14 @@ impl<T: Config + pallet_drand::Config> Pallet<T> {
}

pub fn root_proportion(netuid: NetUid) -> U96F32 {
if Self::get_burn_root_prop() {
return U96F32::from_num(0.0);
}

Self::raw_root_proportion(netuid)
}

pub fn raw_root_proportion(netuid: NetUid) -> U96F32 {
let alpha_issuance = U96F32::from_num(Self::get_alpha_issuance(netuid));
let root_tao: U96F32 = U96F32::from_num(Self::get_subnet_tao(NetUid::ROOT));
let tao_weight: U96F32 = root_tao.saturating_mul(Self::get_tao_weight());
Expand Down
33 changes: 28 additions & 5 deletions pallets/subtensor/src/coinbase/run_coinbase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ impl<T: Config> Pallet<T> {
// --- 3. Inject ALPHA for participants.
let cut_percent: U96F32 = Self::get_float_subnet_owner_cut();

let burn_root_prop = Self::get_burn_root_prop();
for netuid_i in subnets_to_emit_to.iter() {
// Get alpha_out for this block.
let mut alpha_out_i: U96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0));
Expand All @@ -273,7 +274,11 @@ impl<T: Config> Pallet<T> {
});

// Get root proportional dividends.
let root_proportion = Self::root_proportion(*netuid_i);
let root_proportion = if burn_root_prop {
Self::raw_root_proportion(*netuid_i)
} else {
Self::root_proportion(*netuid_i)
};
log::debug!("root_proportion: {root_proportion:?}");

// Get root alpha from root prop.
Expand Down Expand Up @@ -302,14 +307,16 @@ impl<T: Config> Pallet<T> {
*total = total.saturating_add(tou64!(pending_validator_alpha).into());
});

if root_sell_flag {
// Only accumulate root alpha divs if root sell is allowed.
let root_alpha_amount = AlphaBalance::from(tou64!(root_alpha));

if burn_root_prop || root_sell_flag {
// Burn mode still creates root-sell pressure; the TAO proceeds are burned in root_claim_on_subnet.
PendingRootAlphaDivs::<T>::mutate(*netuid_i, |total| {
*total = total.saturating_add(tou64!(root_alpha).into());
*total = total.saturating_add(root_alpha_amount);
});
} else {
// If we are not selling the root alpha, we should recycle it.
Self::recycle_subnet_alpha(*netuid_i, AlphaBalance::from(tou64!(root_alpha)));
Self::recycle_subnet_alpha(*netuid_i, root_alpha_amount);
}
}
}
Expand Down Expand Up @@ -680,13 +687,29 @@ impl<T: Config> Pallet<T> {
}

// Distribute root alpha divs.
let burn_root_prop = Self::get_burn_root_prop();
let _ = RootAlphaDividendsPerSubnet::<T>::clear_prefix(netuid, u32::MAX, None);
for (hotkey, mut root_alpha) in root_alpha_dividends {
if burn_root_prop {
// Keep root yield in the root-claim path so it is sold through the pool first.
Self::increase_root_claimable_for_hotkey_and_subnet(
&hotkey,
netuid,
tou64!(root_alpha).into(),
);
RootAlphaDividendsPerSubnet::<T>::mutate(netuid, &hotkey, |divs| {
*divs = divs.saturating_add(tou64!(root_alpha).into());
});
continue;
}

// Get take prop
let alpha_take: U96F32 =
Self::get_hotkey_take_float(&hotkey).saturating_mul(root_alpha);

// Remove take prop from root_alpha
root_alpha = root_alpha.saturating_sub(alpha_take);

// Give the validator their take.
log::debug!("hotkey: {hotkey:?} alpha_take: {alpha_take:?}");
Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
Expand Down
4 changes: 4 additions & 0 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,10 @@ pub mod pallet {
pub type RootProp<T: Config> =
StorageMap<_, Identity, NetUid, U96F32, ValueQuery, DefaultRootProp<T>>;

/// --- ITEM --> burn_root_prop | Sell root-proportional subnet yield through subnet pools and burn the TAO proceeds.
#[pallet::storage]
pub type BurnRootProp<T: Config> = StorageValue<_, bool, ValueQuery, DefaultFalse<T>>;

/// --- MAP ( netuid ) --> total_volume | The total amount of TAO bought and sold since the start of the network.
#[pallet::storage]
pub type SubnetVolume<T: Config> =
Expand Down
15 changes: 15 additions & 0 deletions pallets/subtensor/src/macros/dispatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2594,5 +2594,20 @@ mod dispatches {
let coldkey = ensure_signed(origin)?;
Self::do_move_lock(&coldkey, &destination_hotkey, netuid)
}

/// Sets whether root-proportional subnet yield is sold and burned instead of paid to root stakers.
///
/// This is root-only. When enabled, root stakers receive zero yield from the
/// root-proportional portion on every subnet; root alpha is still sold through
/// the subnet pool and the resulting TAO is burned.
#[pallet::call_index(139)]
#[pallet::weight(
Weight::from_parts(6_000, 0).saturating_add(T::DbWeight::get().writes(1))
)]
pub fn sudo_set_burn_root_prop(origin: OriginFor<T>, enabled: bool) -> DispatchResult {
ensure_root(origin)?;
Self::set_burn_root_prop(enabled);
Ok(())
}
}
}
6 changes: 6 additions & 0 deletions pallets/subtensor/src/macros/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,12 @@ mod events {
root_claim_type: RootClaimTypeEnum,
},

/// Root-proportional subnet yield burn mode has been toggled.
BurnRootPropSet {
/// Whether root-proportional yield is sold through subnet pools and burned instead of paid to root stakers.
enabled: bool,
},

/// Voting power tracking has been enabled for a subnet.
VotingPowerTrackingEnabled {
/// The subnet ID
Expand Down
99 changes: 59 additions & 40 deletions pallets/subtensor/src/staking/claim_root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<T: Config> Pallet<T> {
.unwrap_or(I96F32::saturating_from_num(0.0));

// Unlikely to happen. This is mostly for test environment sanity checks.
if u64::from(amount) > total.saturating_to_num::<u64>() {
if u64::from(amount) > total.saturating_to_num::<u64>() && !Self::get_burn_root_prop() {
log::warn!("Not enough root stake. NetUID = {netuid}");

let owner = Owner::<T>::get(hotkey);
Expand Down Expand Up @@ -157,11 +157,14 @@ impl<T: Config> Pallet<T> {
return; // no-op
}

let swap = match root_claim_type {
RootClaimTypeEnum::Swap => true,
RootClaimTypeEnum::Keep => false,
RootClaimTypeEnum::KeepSubnets { subnets } => !subnets.contains(&netuid),
};
let burn_root_prop = Self::get_burn_root_prop();

let swap = burn_root_prop
|| match root_claim_type {
RootClaimTypeEnum::Swap => true,
RootClaimTypeEnum::Keep => false,
RootClaimTypeEnum::KeepSubnets { subnets } => !subnets.contains(&netuid),
};

if swap {
// Increase stake on root. Swap the alpha owed to TAO
Expand All @@ -186,44 +189,60 @@ impl<T: Config> Pallet<T> {
});
Self::record_protocol_outflow(netuid, root_sell_tao);

// Transfer unstaked TAO from subnet account to the root subnet account
// and increase root stake.
if let Some(root_subnet_account_id) = Self::get_subnet_account_id(NetUid::ROOT)
&& Self::transfer_tao_from_subnet(
netuid,
&root_subnet_account_id,
owed_tao.amount_paid_out.into(),
)
.is_ok()
{
Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
if burn_root_prop {
if let Some(subnet_account_id) = Self::get_subnet_account_id(netuid) {
if let Err(err) =
Self::burn_tao(&subnet_account_id, owed_tao.amount_paid_out.into())
{
log::error!("Could not burn root prop TAO: {err:?}");
return;
}
} else {
log::error!(
"Could not burn root prop TAO: subnet account does not exist for netuid {netuid}"
);
return;
}
} else {
// Transfer unstaked TAO from subnet account to the root subnet account
// and increase root stake.
if let Some(root_subnet_account_id) = Self::get_subnet_account_id(NetUid::ROOT)
&& Self::transfer_tao_from_subnet(
netuid,
&root_subnet_account_id,
owed_tao.amount_paid_out.into(),
)
.is_ok()
{
Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
hotkey,
coldkey,
NetUid::ROOT,
owed_tao.amount_paid_out.to_u64().into(),
);

// Increase root subnet SubnetTAO
SubnetTAO::<T>::mutate(NetUid::ROOT, |total| {
*total = total.saturating_add(owed_tao.amount_paid_out.into());
});

// Increase root SubnetAlphaOut
SubnetAlphaOut::<T>::mutate(NetUid::ROOT, |total| {
*total = total.saturating_add(u64::from(owed_tao.amount_paid_out).into());
});

// Increase Total Stake
TotalStake::<T>::mutate(|total| {
*total = total.saturating_add(owed_tao.amount_paid_out.into());
});
}

Self::add_stake_adjust_root_claimed_for_hotkey_and_coldkey(
hotkey,
coldkey,
NetUid::ROOT,
owed_tao.amount_paid_out.to_u64().into(),
owed_tao.amount_paid_out.into(),
);

// Increase root subnet SubnetTAO
SubnetTAO::<T>::mutate(NetUid::ROOT, |total| {
*total = total.saturating_add(owed_tao.amount_paid_out.into());
});

// Increase root SubnetAlphaOut
SubnetAlphaOut::<T>::mutate(NetUid::ROOT, |total| {
*total = total.saturating_add(u64::from(owed_tao.amount_paid_out).into());
});

// Increase Total Stake
TotalStake::<T>::mutate(|total| {
*total = total.saturating_add(owed_tao.amount_paid_out.into());
});
}

Self::add_stake_adjust_root_claimed_for_hotkey_and_coldkey(
hotkey,
coldkey,
owed_tao.amount_paid_out.into(),
);
} else
/* Keep */
{
Expand Down
Loading
Loading