Skip to content

Commit 4fdcdbc

Browse files
committed
fix leasing to distribute alpha only
1 parent 2af7993 commit 4fdcdbc

File tree

2 files changed

+280
-136
lines changed

2 files changed

+280
-136
lines changed

pallets/subtensor/src/subnets/leasing.rs

Lines changed: 44 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,48 @@ 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+
Self::transfer_stake_within_subnet(
306+
&lease.coldkey,
307+
&lease.hotkey,
308+
&contributor,
309+
&lease.hotkey,
310+
lease.netuid,
311+
alpha_for_contributor.into(),
312+
)?;
313+
alpha_distributed = alpha_distributed.saturating_add(alpha_for_contributor.into());
321314
}
322-
};
323315

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-
}
316+
// Distribute the leftover alpha to the beneficiary
317+
let beneficiary_cut_alpha =
318+
total_contributors_cut_alpha.saturating_sub(alpha_distributed);
319+
Self::transfer_stake_within_subnet(
320+
&lease.coldkey,
321+
&lease.hotkey,
322+
&lease.beneficiary,
323+
&lease.hotkey,
324+
lease.netuid,
325+
beneficiary_cut_alpha.into(),
326+
)?;
335327

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());
328+
// Reset the accumulated dividends
329+
AccumulatedLeaseDividends::<T>::insert(lease_id, AlphaCurrency::ZERO);
339330

340-
// Reset the accumulated dividends
341-
AccumulatedLeaseDividends::<T>::insert(lease_id, AlphaCurrency::ZERO);
331+
Ok::<(), DispatchError>(())
332+
}) {
333+
log::debug!("Couldn't distributing dividends for lease {lease_id}: {err:?}");
334+
AccumulatedLeaseDividends::<T>::set(lease_id, total_contributors_cut_alpha);
335+
};
342336
}
343337

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

0 commit comments

Comments
 (0)