Skip to content

Commit d9a79d7

Browse files
committed
rebase PR
2 parents f86204d + 11dbff3 commit d9a79d7

File tree

10 files changed

+426
-170
lines changed

10 files changed

+426
-170
lines changed

pallets/subtensor/src/macros/events.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,5 +467,15 @@ mod events {
467467
/// Claim type
468468
root_claim_type: RootClaimTypeEnum,
469469
},
470+
471+
/// Subnet lease dividends have been distributed.
472+
SubnetLeaseDividendsDistributed {
473+
/// The lease ID
474+
lease_id: LeaseId,
475+
/// The contributor
476+
contributor: T::AccountId,
477+
/// The amount of alpha distributed
478+
alpha: AlphaCurrency,
479+
},
470480
}
471481
}

pallets/subtensor/src/staking/stake_utils.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ impl<T: Config> Pallet<T> {
2121
SubnetAlphaIn::<T>::get(netuid).saturating_add(SubnetAlphaOut::<T>::get(netuid))
2222
}
2323

24+
pub fn get_protocol_tao(netuid: NetUid) -> TaoCurrency {
25+
T::SwapInterface::get_protocol_tao(netuid)
26+
}
27+
2428
pub fn get_moving_alpha_price(netuid: NetUid) -> U96F32 {
2529
let one = U96F32::saturating_from_num(1.0);
2630
if netuid.is_root() {
@@ -688,6 +692,9 @@ impl<T: Config> Pallet<T> {
688692
price_limit: TaoCurrency,
689693
drop_fees: bool,
690694
) -> Result<TaoCurrency, DispatchError> {
695+
// Record the protocol TAO before the swap.
696+
let protocol_tao = Self::get_protocol_tao(netuid);
697+
691698
// Decrease alpha on subnet
692699
let actual_alpha_decrease =
693700
Self::decrease_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid, alpha);
@@ -696,6 +703,11 @@ impl<T: Config> Pallet<T> {
696703
let swap_result =
697704
Self::swap_alpha_for_tao(netuid, actual_alpha_decrease, price_limit, drop_fees)?;
698705

706+
// Record the protocol TAO after the swap.
707+
let protocol_tao_after = Self::get_protocol_tao(netuid);
708+
// This should decrease as we are removing TAO from the protocol.
709+
let protocol_tao_delta: TaoCurrency = protocol_tao.saturating_sub(protocol_tao_after);
710+
699711
// Refund the unused alpha (in case if limit price is hit)
700712
let refund = actual_alpha_decrease.saturating_sub(
701713
swap_result
@@ -722,7 +734,7 @@ impl<T: Config> Pallet<T> {
722734
// }
723735

724736
// Record TAO outflow
725-
Self::record_tao_outflow(netuid, swap_result.amount_paid_out.into());
737+
Self::record_tao_outflow(netuid, protocol_tao_delta);
726738

727739
LastColdkeyHotkeyStakeBlock::<T>::insert(coldkey, hotkey, Self::get_current_block_as_u64());
728740

@@ -761,9 +773,18 @@ impl<T: Config> Pallet<T> {
761773
set_limit: bool,
762774
drop_fees: bool,
763775
) -> Result<AlphaCurrency, DispatchError> {
776+
// Record the protocol TAO before the swap.
777+
let protocol_tao = Self::get_protocol_tao(netuid);
778+
764779
// Swap the tao to alpha.
765780
let swap_result = Self::swap_tao_for_alpha(netuid, tao, price_limit, drop_fees)?;
766781

782+
// Record the protocol TAO after the swap.
783+
let protocol_tao_after = Self::get_protocol_tao(netuid);
784+
785+
// This should increase as we are adding TAO to the protocol.
786+
let protocol_tao_delta: TaoCurrency = protocol_tao_after.saturating_sub(protocol_tao);
787+
767788
ensure!(
768789
!swap_result.amount_paid_out.is_zero(),
769790
Error::<T>::AmountTooLow
@@ -799,7 +820,7 @@ impl<T: Config> Pallet<T> {
799820
}
800821

801822
// Record TAO inflow
802-
Self::record_tao_inflow(netuid, swap_result.amount_paid_in.into());
823+
Self::record_tao_inflow(netuid, protocol_tao_delta);
803824

804825
LastColdkeyHotkeyStakeBlock::<T>::insert(coldkey, hotkey, Self::get_current_block_as_u64());
805826

pallets/subtensor/src/subnets/leasing.rs

Lines changed: 56 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ use frame_system::pallet_prelude::*;
2424
use sp_core::blake2_256;
2525
use sp_runtime::{Percent, traits::TrailingZeroInput};
2626
use substrate_fixed::types::U64F64;
27-
use subtensor_runtime_common::{AlphaCurrency, NetUid, TaoCurrency};
28-
use subtensor_swap_interface::SwapHandler;
27+
use subtensor_runtime_common::{AlphaCurrency, NetUid};
2928

3029
pub type LeaseId = u32;
3130

@@ -130,6 +129,9 @@ impl<T: Config> Pallet<T> {
130129
);
131130
SubnetUidToLeaseId::<T>::insert(netuid, lease_id);
132131

132+
// The lease take should be 0% to allow all contributors to receive dividends entirely.
133+
Self::delegate_hotkey(&lease_hotkey, 0);
134+
133135
// Get all the contributions to the crowdloan except for the beneficiary
134136
// because its share will be computed as the dividends are distributed
135137
let contributions = pallet_crowdloan::Contributions::<T>::iter_prefix(crowdloan_id)
@@ -249,9 +251,8 @@ impl<T: Config> Pallet<T> {
249251

250252
/// Hook used when the subnet owner's cut is distributed to split the amount into dividends
251253
/// for the contributors and the beneficiary in shares relative to their initial contributions.
252-
///
253-
/// It will ensure the subnet has enough alpha in its liquidity pool before swapping it to tao to be distributed,
254-
/// and if not enough liquidity is available, it will accumulate the dividends for later distribution.
254+
/// It accumulates dividends to be distributed later when the interval for distribution is reached.
255+
/// Distribution is made in alpha and stake to the contributor coldkey and lease hotkey.
255256
pub fn distribute_leased_network_dividends(lease_id: LeaseId, owner_cut_alpha: AlphaCurrency) {
256257
// Ensure the lease exists
257258
let Some(lease) = SubnetLeases::<T>::get(lease_id) else {
@@ -290,55 +291,60 @@ impl<T: Config> Pallet<T> {
290291
return;
291292
}
292293

293-
// Ensure there is enough liquidity to unstake the contributors cut
294-
if let Err(err) = Self::validate_remove_stake(
295-
&lease.coldkey,
296-
&lease.hotkey,
297-
lease.netuid,
298-
total_contributors_cut_alpha,
299-
total_contributors_cut_alpha,
300-
false,
301-
) {
302-
log::debug!("Couldn't distributing dividends for lease {lease_id}: {err:?}");
303-
AccumulatedLeaseDividends::<T>::set(lease_id, total_contributors_cut_alpha);
304-
return;
305-
}
306-
307-
// Unstake the contributors cut from the subnet as tao to the lease coldkey
308-
let tao_unstaked = match Self::unstake_from_subnet(
309-
&lease.hotkey,
310-
&lease.coldkey,
311-
lease.netuid,
312-
total_contributors_cut_alpha,
313-
T::SwapInterface::min_price(),
314-
false,
315-
) {
316-
Ok(tao_unstaked) => tao_unstaked,
317-
Err(err) => {
318-
log::debug!("Couldn't distributing dividends for lease {lease_id}: {err:?}");
319-
AccumulatedLeaseDividends::<T>::set(lease_id, total_contributors_cut_alpha);
320-
return;
294+
// We use a storage layer to ensure the distribution is atomic.
295+
if let Err(err) = frame_support::storage::with_storage_layer(|| {
296+
let mut alpha_distributed = AlphaCurrency::ZERO;
297+
298+
// Distribute the contributors cut to the contributors and accumulate the alpha
299+
// distributed so far to obtain how much alpha is left to distribute to the beneficiary
300+
for (contributor, share) in SubnetLeaseShares::<T>::iter_prefix(lease_id) {
301+
let alpha_for_contributor = share
302+
.saturating_mul(U64F64::from(total_contributors_cut_alpha.to_u64()))
303+
.ceil()
304+
.saturating_to_num::<u64>();
305+
306+
Self::transfer_stake_within_subnet(
307+
&lease.coldkey,
308+
&lease.hotkey,
309+
&contributor,
310+
&lease.hotkey,
311+
lease.netuid,
312+
alpha_for_contributor.into(),
313+
)?;
314+
alpha_distributed = alpha_distributed.saturating_add(alpha_for_contributor.into());
315+
316+
Self::deposit_event(Event::SubnetLeaseDividendsDistributed {
317+
lease_id,
318+
contributor,
319+
alpha: alpha_for_contributor.into(),
320+
});
321321
}
322-
};
323322

324-
// Distribute the contributors cut to the contributors and accumulate the tao
325-
// distributed so far to obtain how much tao is left to distribute to the beneficiary
326-
let mut tao_distributed = TaoCurrency::ZERO;
327-
for (contributor, share) in SubnetLeaseShares::<T>::iter_prefix(lease_id) {
328-
let tao_for_contributor = share
329-
.saturating_mul(U64F64::from(tao_unstaked.to_u64()))
330-
.floor()
331-
.saturating_to_num::<u64>();
332-
Self::add_balance_to_coldkey_account(&contributor, tao_for_contributor);
333-
tao_distributed = tao_distributed.saturating_add(tao_for_contributor.into());
334-
}
323+
// Distribute the leftover alpha to the beneficiary
324+
let beneficiary_cut_alpha =
325+
total_contributors_cut_alpha.saturating_sub(alpha_distributed);
326+
Self::transfer_stake_within_subnet(
327+
&lease.coldkey,
328+
&lease.hotkey,
329+
&lease.beneficiary,
330+
&lease.hotkey,
331+
lease.netuid,
332+
beneficiary_cut_alpha.into(),
333+
)?;
334+
Self::deposit_event(Event::SubnetLeaseDividendsDistributed {
335+
lease_id,
336+
contributor: lease.beneficiary.clone(),
337+
alpha: beneficiary_cut_alpha.into(),
338+
});
335339

336-
// Distribute the leftover tao to the beneficiary
337-
let beneficiary_cut_tao = tao_unstaked.saturating_sub(tao_distributed);
338-
Self::add_balance_to_coldkey_account(&lease.beneficiary, beneficiary_cut_tao.into());
340+
// Reset the accumulated dividends
341+
AccumulatedLeaseDividends::<T>::insert(lease_id, AlphaCurrency::ZERO);
339342

340-
// Reset the accumulated dividends
341-
AccumulatedLeaseDividends::<T>::insert(lease_id, AlphaCurrency::ZERO);
343+
Ok::<(), DispatchError>(())
344+
}) {
345+
log::debug!("Couldn't distributing dividends for lease {lease_id}: {err:?}");
346+
AccumulatedLeaseDividends::<T>::set(lease_id, total_contributors_cut_alpha);
347+
};
342348
}
343349

344350
fn lease_coldkey(lease_id: LeaseId) -> Result<T::AccountId, DispatchError> {

0 commit comments

Comments
 (0)