@@ -24,8 +24,7 @@ use frame_system::pallet_prelude::*;
2424use sp_core:: blake2_256;
2525use sp_runtime:: { Percent , traits:: TrailingZeroInput } ;
2626use 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
3029pub 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