@@ -249,6 +249,20 @@ impl<T: Config> Pallet<T> {
249249 } ) ;
250250 }
251251
252+ /// Calculates the nonviable stake for a nominator.
253+ /// The nonviable stake is the stake that was added by the nominator since the last emission drain.
254+ /// This stake will not receive emission until the next emission drain.
255+ /// Note: if the stake delta is below zero, we return zero. We don't allow more stake than the nominator has.
256+ pub fn get_nonviable_stake ( hotkey : & T :: AccountId , nominator : & T :: AccountId ) -> u64 {
257+ let stake_delta = StakeDeltaSinceLastEmissionDrain :: < T > :: get ( hotkey, nominator) ;
258+ if stake_delta. is_negative ( ) {
259+ 0
260+ } else {
261+ // Should never fail the into, but we handle it anyway.
262+ stake_delta. try_into ( ) . unwrap_or ( u64:: MAX )
263+ }
264+ }
265+
252266 //. --- 4. Drains the accumulated hotkey emission through to the nominators. The hotkey takes a proportion of the emission.
253267 /// The remainder is drained through to the nominators keeping track of the last stake increase event to ensure that the hotkey does not
254268 /// gain more emission than it's stake since the last drain.
@@ -268,71 +282,67 @@ impl<T: Config> Pallet<T> {
268282 // --- 1.0 Drain the hotkey emission.
269283 PendingdHotkeyEmission :: < T > :: insert ( hotkey, 0 ) ;
270284
271- // --- 2 Retrieve the last time this hotkey's emissions were drained.
272- let last_emission_drain: u64 = LastHotkeyEmissionDrain :: < T > :: get ( hotkey) ;
273-
274- // --- 3 Update the block value to the current block number.
285+ // --- 2 Update the block value to the current block number.
275286 LastHotkeyEmissionDrain :: < T > :: insert ( hotkey, block_number) ;
276287
277- // --- 4 Retrieve the total stake for the hotkey from all nominations.
288+ // --- 3 Retrieve the total stake for the hotkey from all nominations.
278289 let total_hotkey_stake: u64 = Self :: get_total_stake_for_hotkey ( hotkey) ;
279290
280- // --- 5 Calculate the emission take for the hotkey.
291+ // --- 4 Calculate the emission take for the hotkey.
281292 let take_proportion: I64F64 = I64F64 :: from_num ( Delegates :: < T > :: get ( hotkey) )
282293 . saturating_div ( I64F64 :: from_num ( u16:: MAX ) ) ;
283294 let hotkey_take: u64 =
284295 ( take_proportion. saturating_mul ( I64F64 :: from_num ( emission) ) ) . to_num :: < u64 > ( ) ;
285296
286- // --- 6 Compute the remaining emission after deducting the hotkey's take.
297+ // --- 5 Compute the remaining emission after deducting the hotkey's take.
287298 let emission_minus_take: u64 = emission. saturating_sub ( hotkey_take) ;
288299
289- // --- 7 Calculate the remaining emission after the hotkey's take.
300+ // --- 6 Calculate the remaining emission after the hotkey's take.
290301 let mut remainder: u64 = emission_minus_take;
291302
292- // --- 8 Iterate over each nominator and get all viable stake.
303+ // --- 7 Iterate over each nominator and get all viable stake.
293304 let mut total_viable_nominator_stake: u64 = total_hotkey_stake;
294- for ( nominator, nominator_stake ) in Stake :: < T > :: iter_prefix ( hotkey) {
295- if false && LastAddStakeIncrease :: < T > :: get ( hotkey, nominator) > last_emission_drain {
296- total_viable_nominator_stake =
297- total_viable_nominator_stake. saturating_sub ( nominator_stake ) ;
298- }
305+ for ( nominator, _ ) in Stake :: < T > :: iter_prefix ( hotkey) {
306+ let nonviable_nomintaor_stake = Self :: get_nonviable_stake ( hotkey, & nominator) ;
307+
308+ total_viable_nominator_stake =
309+ total_viable_nominator_stake . saturating_sub ( nonviable_nomintaor_stake ) ;
299310 }
300311
301- // --- 9 Iterate over each nominator.
312+ // --- 8 Iterate over each nominator.
302313 if total_viable_nominator_stake != 0 {
303314 for ( nominator, nominator_stake) in Stake :: < T > :: iter_prefix ( hotkey) {
304- // --- 10 Check if the stake was manually increased by the user since the last emission drain for this hotkey.
305- // If it was, skip this nominator as they will not receive their proportion of the emission.
306- if false
307- && LastAddStakeIncrease :: < T > :: get ( hotkey, nominator. clone ( ) )
308- > last_emission_drain
309- {
310- continue ;
311- }
315+ // --- 9 Skip emission for any stake the was added by the nominator since the last emission drain.
316+ // This means the nominator will get emission on existing stake, but not on new stake, until the next emission drain.
317+ let viable_nominator_stake =
318+ nominator_stake. saturating_sub ( Self :: get_nonviable_stake ( hotkey, & nominator) ) ;
312319
313- // --- 11 Calculate this nominator's share of the emission.
314- let nominator_emission: I64F64 = I64F64 :: from_num ( nominator_stake )
320+ // --- 10 Calculate this nominator's share of the emission.
321+ let nominator_emission: I64F64 = I64F64 :: from_num ( viable_nominator_stake )
315322 . checked_div ( I64F64 :: from_num ( total_viable_nominator_stake) )
316323 . unwrap_or ( I64F64 :: from_num ( 0 ) )
317324 . saturating_mul ( I64F64 :: from_num ( emission_minus_take) ) ;
318325
319- // --- 12 Increase the stake for the nominator.
326+ // --- 11 Increase the stake for the nominator.
320327 Self :: increase_stake_on_coldkey_hotkey_account (
321328 & nominator,
322329 hotkey,
323330 nominator_emission. to_num :: < u64 > ( ) ,
324331 ) ;
325332
326- // --- 13 * Record event and Subtract the nominator's emission from the remainder.
333+ // --- 12 * Record event and Subtract the nominator's emission from the remainder.
327334 total_new_tao = total_new_tao. saturating_add ( nominator_emission. to_num :: < u64 > ( ) ) ;
328335 remainder = remainder. saturating_sub ( nominator_emission. to_num :: < u64 > ( ) ) ;
329336 }
330337 }
331338
332- // --- 14 Finally, add the stake to the hotkey itself, including its take and the remaining emission.
339+ // --- 13 Finally, add the stake to the hotkey itself, including its take and the remaining emission.
333340 let hotkey_new_tao: u64 = hotkey_take. saturating_add ( remainder) ;
334341 Self :: increase_stake_on_hotkey_account ( hotkey, hotkey_new_tao) ;
335342
343+ // --- 14 Reset the stake delta for the hotkey.
344+ let _ = StakeDeltaSinceLastEmissionDrain :: < T > :: clear_prefix ( hotkey, u32:: MAX , None ) ;
345+
336346 // --- 15 Record new tao creation event and return the amount created.
337347 total_new_tao = total_new_tao. saturating_add ( hotkey_new_tao) ;
338348 total_new_tao
0 commit comments