1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>
16

            
17
use {
18
    crate::{
19
        candidate::Candidates, weights::WeightInfo, Candidate, Config, CreditOf, Delegator, Error,
20
        Event, Pallet, Pools, PoolsKey, Shares, Stake,
21
    },
22
    core::marker::PhantomData,
23
    frame_support::{
24
        ensure,
25
        pallet_prelude::*,
26
        traits::{fungible::Balanced, Imbalance},
27
    },
28
    sp_core::Get,
29
    sp_runtime::traits::{CheckedAdd, CheckedDiv, Zero},
30
    tp_maths::{ErrAdd, ErrMul, ErrSub, MulDiv},
31
};
32

            
33
#[allow(dead_code)]
34
pub trait Pool<T: Config> {
35
    /// Get the amount of shares a delegator have for given candidate.
36
    fn shares(candidate: &Candidate<T>, delegator: &Delegator<T>) -> Shares<T::Balance>;
37
    /// Get the total amount of shares all delegators have for given candidate.
38
    fn shares_supply(candidate: &Candidate<T>) -> Shares<T::Balance>;
39
    /// Get the total amount of currency staked for given candidate / the value of all shares.
40
    fn total_staked(candidate: &Candidate<T>) -> Stake<T::Balance>;
41
    /// Get the amount of currency held for that pool in the delegator account.
42
    fn hold(candidate: &Candidate<T>, delegator: &Delegator<T>) -> Stake<T::Balance>;
43

            
44
    /// Set the amount of shares a delegator have for given candidate.
45
    fn set_shares(candidate: &Candidate<T>, delegator: &Delegator<T>, value: Shares<T::Balance>);
46
    /// Set the total amount of shares all delegators have for given candidate.
47
    fn set_shares_supply(candidate: &Candidate<T>, value: Shares<T::Balance>);
48
    /// Set the total amount of currency staked for given candidate / the value of all shares.
49
    fn set_total_staked(candidate: &Candidate<T>, value: Stake<T::Balance>);
50
    /// Set the amount of currency held for that pool in the delegator account.
51
    fn set_hold(candidate: &Candidate<T>, delegator: &Delegator<T>, value: Stake<T::Balance>);
52

            
53
    /// Get the initial value of a share in case none exist yet.
54
    fn initial_share_value() -> Stake<T::Balance>;
55

            
56
    /// Convert an amount of shares to an amount of staked currency for given candidate.
57
    /// Returns an error if there are no shares for that candidate.
58
907
    fn shares_to_stake(
59
907
        candidate: &Candidate<T>,
60
907
        shares: Shares<T::Balance>,
61
907
    ) -> Result<Stake<T::Balance>, Error<T>> {
62
907
        let total_staked = Self::total_staked(candidate).0;
63
907
        let supply = Self::shares_supply(candidate).0;
64
907
        ensure!(!supply.is_zero(), Error::NoOneIsStaking);
65

            
66
907
        Ok(Stake(shares.0.mul_div(total_staked, supply)?))
67
907
    }
68

            
69
    /// Convert an amount of shares to an amount of staked currency for given candidate.
70
    /// If this candidate have no shares then it uses `initial_share_value` to compute the value.
71
369
    fn shares_to_stake_or_init(
72
369
        candidate: &Candidate<T>,
73
369
        shares: Shares<T::Balance>,
74
369
    ) -> Result<Stake<T::Balance>, Error<T>> {
75
369
        if Self::total_staked(candidate).0.is_zero() {
76
306
            Ok(Stake(shares.0.err_mul(&Self::initial_share_value().0)?))
77
        } else {
78
63
            Self::shares_to_stake(candidate, shares)
79
        }
80
369
    }
81

            
82
    /// Convert an amount of staked currency to an amount of shares for given candidate.
83
    /// Returns an error if there are no shares for that candidate.
84
106
    fn stake_to_shares(
85
106
        candidate: &Candidate<T>,
86
106
        stake: Stake<T::Balance>,
87
106
    ) -> Result<Shares<T::Balance>, Error<T>> {
88
106
        let total_staked = Self::total_staked(candidate).0;
89
106
        let supply = Self::shares_supply(candidate).0;
90
106
        ensure!(!supply.is_zero(), Error::NoOneIsStaking);
91

            
92
106
        Ok(Shares(stake.0.mul_div(supply, total_staked)?))
93
106
    }
94

            
95
459
    fn computed_stake(
96
459
        candidate: &Candidate<T>,
97
459
        delegator: &Delegator<T>,
98
459
    ) -> Result<Stake<T::Balance>, Error<T>> {
99
459
        let shares = Self::shares(candidate, delegator);
100
459
        if shares.0.is_zero() {
101
205
            return Ok(Stake(Zero::zero()));
102
254
        }
103
254

            
104
254
        Self::shares_to_stake(candidate, shares)
105
459
    }
106

            
107
    /// Convert an amount of staked currency to an amount of shares for given candidate.
108
    /// If this candidate have no shares then it uses `initial_share_value` to compute the value.
109
348
    fn stake_to_shares_or_init(
110
348
        candidate: &Candidate<T>,
111
348
        stake: Stake<T::Balance>,
112
348
    ) -> Result<Shares<T::Balance>, Error<T>> {
113
348
        if Self::total_staked(candidate).0.is_zero() {
114
            Ok(Shares(
115
302
                stake
116
302
                    .0
117
302
                    .checked_div(&Self::initial_share_value().0)
118
302
                    .ok_or(Error::<T>::InvalidPalletSetting)?,
119
            ))
120
        } else {
121
46
            Self::stake_to_shares(candidate, stake)
122
        }
123
348
    }
124

            
125
    /// Increase the total stake of a pool without creating new shares, which basically increase
126
    /// the value of each share.
127
32
    fn share_stake_among_holders(
128
32
        candidate: &Candidate<T>,
129
32
        stake: Stake<T::Balance>,
130
32
    ) -> Result<(), Error<T>> {
131
32
        let total_staked = Self::total_staked(candidate).0;
132
32
        let total_staked = total_staked.err_add(&stake.0)?;
133
32
        Self::set_total_staked(candidate, Stake(total_staked));
134
32
        Ok(())
135
32
    }
136

            
137
    /// Decrease the total stake of a pool without creating new shares, which basically decrease
138
    /// the value of each share.
139
2
    fn slash_stake_among_holders(
140
2
        candidate: &Candidate<T>,
141
2
        stake: Stake<T::Balance>,
142
2
    ) -> Result<(), Error<T>> {
143
2
        let total_staked = Self::total_staked(candidate).0;
144
2
        let total_staked = total_staked.err_sub(&stake.0)?;
145
2
        Self::set_total_staked(candidate, Stake(total_staked));
146
2
        Ok(())
147
2
    }
148

            
149
    /// Add new shares for that delegator towards the given candidate.
150
    /// Function returns the value of those new shares.
151
    /// Returns an error if underflow/overflows occurs.
152
365
    fn add_shares(
153
365
        candidate: &Candidate<T>,
154
365
        delegator: &Delegator<T>,
155
365
        shares: Shares<T::Balance>,
156
365
    ) -> Result<Stake<T::Balance>, Error<T>> {
157
365
        ensure!(!shares.0.is_zero(), Error::StakeMustBeNonZero);
158

            
159
365
        let stake = Self::shares_to_stake_or_init(candidate, shares)?;
160

            
161
365
        let new_shares_supply = Self::shares_supply(candidate).0.err_add(&shares.0)?;
162
365
        let new_shares = Self::shares(candidate, delegator).0.err_add(&shares.0)?;
163
365
        let new_total_stake = Self::total_staked(candidate).0.err_add(&stake.0)?;
164

            
165
365
        Self::set_shares_supply(candidate, Shares(new_shares_supply));
166
365
        Self::set_shares(candidate, delegator, Shares(new_shares));
167
365
        Self::set_total_staked(candidate, Stake(new_total_stake));
168
365

            
169
365
        Ok(stake)
170
365
    }
171

            
172
    /// Remove shares for that delegator towards the given candidate.
173
    /// Function returns the value of those removed shares.
174
    /// Returns an error if that delegator don't have enough shares or if underflow/overflows occurs.
175
172
    fn sub_shares(
176
172
        candidate: &Candidate<T>,
177
172
        delegator: &Delegator<T>,
178
172
        shares: Shares<T::Balance>,
179
172
    ) -> Result<Stake<T::Balance>, Error<T>> {
180
172
        ensure!(!shares.0.is_zero(), Error::StakeMustBeNonZero);
181

            
182
172
        let stake = Self::shares_to_stake(candidate, shares)?;
183

            
184
172
        let new_shares_supply = Self::shares_supply(candidate).0.err_sub(&shares.0)?;
185
169
        let new_shares = Self::shares(candidate, delegator).0.err_sub(&shares.0)?;
186
169
        let new_total_stake = Self::total_staked(candidate).0.err_sub(&stake.0)?;
187

            
188
169
        Self::set_shares_supply(candidate, Shares(new_shares_supply));
189
169
        Self::set_shares(candidate, delegator, Shares(new_shares));
190
169
        Self::set_total_staked(candidate, Stake(new_total_stake));
191
169

            
192
169
        Ok(stake)
193
172
    }
194

            
195
346
    fn increase_hold(
196
346
        candidate: &Candidate<T>,
197
346
        delegator: &Delegator<T>,
198
346
        stake: &Stake<T::Balance>,
199
346
    ) -> Result<(), Error<T>> {
200
346
        let hold = Self::hold(candidate, delegator);
201
346
        let hold = hold.0.err_add(&stake.0)?;
202
346
        Self::set_hold(candidate, delegator, Stake(hold));
203
346
        Ok(())
204
346
    }
205

            
206
169
    fn decrease_hold(
207
169
        candidate: &Candidate<T>,
208
169
        delegator: &Delegator<T>,
209
169
        stake: &Stake<T::Balance>,
210
169
    ) -> Result<(), Error<T>> {
211
169
        let hold = Self::hold(candidate, delegator);
212
169
        let hold = hold.0.err_sub(&stake.0)?;
213
169
        Self::set_hold(candidate, delegator, Stake(hold));
214
169
        Ok(())
215
169
    }
216
}
217

            
218
342
pub fn check_candidate_consistency<T: Config>(candidate: &Candidate<T>) -> Result<(), Error<T>> {
219
342
    let total0 = Pools::<T>::get(candidate, &PoolsKey::CandidateTotalStake);
220
342

            
221
342
    let joining = Joining::<T>::total_staked(candidate).0;
222
342
    let auto = AutoCompounding::<T>::total_staked(candidate).0;
223
342
    let manual = ManualRewards::<T>::total_staked(candidate).0;
224

            
225
342
    let total1 = joining
226
342
        .checked_add(&auto)
227
342
        .ok_or(Error::InconsistentState)?
228
342
        .checked_add(&manual)
229
342
        .ok_or(Error::InconsistentState)?;
230

            
231
342
    ensure!(total0 == total1, Error::InconsistentState);
232

            
233
342
    Ok(())
234
342
}
235

            
236
macro_rules! impl_pool {
237
    ($name:ident, $shares:ident, $supply:ident, $total:ident, $hold: ident, $init:expr $(,)?) => {
238
        pub struct $name<T>(PhantomData<T>);
239
        impl<T: Config> Pool<T> for $name<T> {
240
1396
            fn shares(candidate: &Candidate<T>, delegator: &Delegator<T>) -> Shares<T::Balance> {
241
1396
                Shares(Pools::<T>::get(
242
1396
                    candidate,
243
1396
                    &PoolsKey::$shares {
244
1396
                        delegator: delegator.clone(),
245
1396
                    },
246
1396
                ))
247
1396
            }
248

            
249
2362
            fn shares_supply(candidate: &Candidate<T>) -> Shares<T::Balance> {
250
2362
                Shares(Pools::<T>::get(candidate, &PoolsKey::$supply))
251
2362
            }
252

            
253
5425
            fn total_staked(candidate: &Candidate<T>) -> Stake<T::Balance> {
254
5425
                Stake(Pools::<T>::get(candidate, &PoolsKey::$total))
255
5425
            }
256

            
257
953
            fn hold(candidate: &Candidate<T>, delegator: &Delegator<T>) -> Stake<T::Balance> {
258
953
                Stake(Pools::<T>::get(
259
953
                    candidate,
260
953
                    &PoolsKey::$hold {
261
953
                        delegator: delegator.clone(),
262
953
                    },
263
953
                ))
264
953
            }
265

            
266
534
            fn set_shares(
267
534
                candidate: &Candidate<T>,
268
534
                delegator: &Delegator<T>,
269
534
                value: Shares<T::Balance>,
270
534
            ) {
271
534
                Pools::<T>::set(
272
534
                    candidate,
273
534
                    &PoolsKey::$shares {
274
534
                        delegator: delegator.clone(),
275
534
                    },
276
534
                    value.0,
277
534
                )
278
534
            }
279

            
280
534
            fn set_shares_supply(candidate: &Candidate<T>, value: Shares<T::Balance>) {
281
534
                Pools::<T>::set(candidate, &PoolsKey::$supply, value.0)
282
534
            }
283

            
284
568
            fn set_total_staked(candidate: &Candidate<T>, value: Stake<T::Balance>) {
285
568
                Pools::<T>::set(candidate, &PoolsKey::$total, value.0)
286
568
            }
287

            
288
528
            fn set_hold(
289
528
                candidate: &Candidate<T>,
290
528
                delegator: &Delegator<T>,
291
528
                value: Stake<T::Balance>,
292
528
            ) {
293
528
                Pools::<T>::set(
294
528
                    candidate,
295
528
                    &PoolsKey::$hold {
296
528
                        delegator: delegator.clone(),
297
528
                    },
298
528
                    value.0,
299
528
                )
300
528
            }
301

            
302
364
            fn initial_share_value() -> Stake<T::Balance> {
303
364
                Stake($init)
304
364
            }
305
        }
306
    };
307
}
308

            
309
impl_pool!(
310
    Joining,
311
    JoiningShares,
312
    JoiningSharesSupply,
313
    JoiningSharesTotalStaked,
314
    JoiningSharesHeldStake,
315
    if cfg!(test) { 2u32 } else { 1 }.into(),
316
);
317

            
318
impl_pool!(
319
    AutoCompounding,
320
    AutoCompoundingShares,
321
    AutoCompoundingSharesSupply,
322
    AutoCompoundingSharesTotalStaked,
323
    AutoCompoundingSharesHeldStake,
324
    T::InitialAutoCompoundingShareValue::get(),
325
);
326

            
327
impl_pool!(
328
    ManualRewards,
329
    ManualRewardsShares,
330
    ManualRewardsSharesSupply,
331
    ManualRewardsSharesTotalStaked,
332
    ManualRewardsSharesHeldStake,
333
    T::InitialManualClaimShareValue::get(),
334
);
335

            
336
impl_pool!(
337
    Leaving,
338
    LeavingShares,
339
    LeavingSharesSupply,
340
    LeavingSharesTotalStaked,
341
    LeavingSharesHeldStake,
342
    if cfg!(test) { 3u32 } else { 1u32 }.into(),
343
);
344

            
345
impl<T: Config> ManualRewards<T> {
346
    #[allow(dead_code)]
347
16
    pub fn pending_rewards(
348
16
        candidate: &Candidate<T>,
349
16
        delegator: &Delegator<T>,
350
16
    ) -> Result<Stake<T::Balance>, Error<T>> {
351
16
        let shares = Self::shares(candidate, delegator);
352
16

            
353
16
        if shares.0.is_zero() {
354
5
            return Ok(Stake(0u32.into()));
355
11
        }
356
11

            
357
11
        let counter = Pools::<T>::get(candidate, &PoolsKey::ManualRewardsCounter);
358
11
        let checkpoint = Pools::<T>::get(
359
11
            candidate,
360
11
            &PoolsKey::ManualRewardsCheckpoint {
361
11
                delegator: delegator.clone(),
362
11
            },
363
11
        );
364

            
365
        // TODO: Should be safe to wrap around.
366
11
        let diff = counter.err_sub(&checkpoint)?;
367
11
        Ok(Stake(diff.err_mul(&shares.0)?))
368
16
    }
369

            
370
    /// Increase the rewards of the ManualRewards pool with best effort.
371
    /// Returns the actual amount distributed (after rounding).
372
29
    pub fn increase_rewards(
373
29
        candidate: &Candidate<T>,
374
29
        rewards: Stake<T::Balance>,
375
29
    ) -> Result<Stake<T::Balance>, Error<T>> {
376
29
        let Shares(supply) = Self::shares_supply(candidate);
377
29
        if supply.is_zero() {
378
            return Ok(Stake(Zero::zero()));
379
29
        }
380

            
381
29
        let rewards_per_share = rewards
382
29
            .0
383
29
            .checked_div(&supply)
384
29
            .ok_or(Error::<T>::InconsistentState)?;
385
29
        if rewards_per_share.is_zero() {
386
            return Ok(Stake(Zero::zero()));
387
29
        }
388

            
389
29
        let rewards = rewards_per_share.err_mul(&supply)?;
390

            
391
29
        let counter = Pools::<T>::get(candidate, &PoolsKey::ManualRewardsCounter);
392
29
        let counter = counter.err_add(&rewards_per_share)?;
393
29
        Pools::<T>::set(candidate, &PoolsKey::ManualRewardsCounter, counter);
394
29

            
395
29
        Ok(Stake(rewards))
396
29
    }
397

            
398
76
    pub fn claim_rewards(
399
76
        candidate: &Candidate<T>,
400
76
        delegator: &Delegator<T>,
401
76
    ) -> Result<Stake<T::Balance>, Error<T>> {
402
76
        let shares = Self::shares(candidate, delegator);
403
76

            
404
76
        let counter = Pools::<T>::get(candidate, &PoolsKey::ManualRewardsCounter);
405
76
        let checkpoint = Pools::<T>::get(
406
76
            candidate,
407
76
            &PoolsKey::ManualRewardsCheckpoint {
408
76
                delegator: delegator.clone(),
409
76
            },
410
76
        );
411

            
412
        // TODO: Should be safe to wrap around.
413
76
        let diff = counter.err_sub(&checkpoint)?;
414

            
415
76
        if diff.is_zero() {
416
67
            return Ok(Stake(0u32.into()));
417
9
        }
418

            
419
9
        let rewards = diff.err_mul(&shares.0)?;
420

            
421
        // Update checkpoint
422
9
        Pools::<T>::set(
423
9
            candidate,
424
9
            &PoolsKey::ManualRewardsCheckpoint {
425
9
                delegator: delegator.clone(),
426
9
            },
427
9
            counter,
428
9
        );
429
9

            
430
9
        Ok(Stake(rewards))
431
76
    }
432
}
433

            
434
/// Perform rewards distribution for the provided candidate.
435
///
436
/// The pallet considered that it already posses the rewards in its account,
437
/// and it is the responsibility of the caller to transfer or mint the currency
438
/// to the staking pallet account.
439
///
440
/// Rewards are split using `RewardsCollatorCommission` between the candidate
441
/// and all the delegators (including the candidate self-delegation). For each,
442
/// the rewards are then split according to the value of all the ManualRewards
443
/// and AutoCompounding shares.
444
///
445
/// As candidate rewards will give increase the candidate auto compounding
446
/// self-delegation, the delegator rewards are distributed first. ManualRewards
447
/// pool rewards are first distributed by increasing the pool counter, which may
448
/// result in some rounding. As distributing the AutoCompounding pool rewards
449
/// consists of simply increasing `AutoCompoundingSharesTotalStaked`, it is not
450
/// subject to rounding and it can absorb the rounding dust from ManualRewards
451
/// reward distribution.
452
///
453
/// Then it is time to distribute the candidate dedicated rewards. For
454
/// AutoCompounding, it is as if the candidate received the rewards then
455
/// self-delegated (instantly). It is thus implemented by creating new
456
/// AutoCompounding shares. This can lead to some rounding, which will be
457
/// absorbed in the ManualRewards distribution, which simply consist of
458
/// transfering the funds to the candidate account.
459
3135
#[frame_support::transactional]
460
pub fn distribute_rewards<T: Config>(
461
    candidate: &Candidate<T>,
462
    rewards: CreditOf<T>,
463
) -> DispatchResultWithPostInfo {
464
    let candidate_manual_rewards = distribute_rewards_inner::<T>(candidate, rewards.peek())?;
465

            
466
    let (candidate_manual_rewards, other_rewards) = rewards.split(candidate_manual_rewards);
467

            
468
    if !candidate_manual_rewards.peek().is_zero() {
469
        T::Currency::resolve(candidate, candidate_manual_rewards)
470
1
            .map_err(|_| DispatchError::NoProviders)?;
471
    }
472

            
473
    T::Currency::resolve(&T::StakingAccount::get(), other_rewards)
474
33
        .map_err(|_| DispatchError::NoProviders)?;
475

            
476
    Ok(Some(T::WeightInfo::distribute_rewards()).into())
477
}
478

            
479
1045
fn distribute_rewards_inner<T: Config>(
480
1045
    candidate: &Candidate<T>,
481
1045
    rewards: T::Balance,
482
1045
) -> Result<T::Balance, Error<T>> {
483
1045
    // `RewardsCollatorCommission` is a `Perbill` so we're not worried about overflow.
484
1045
    let candidate_rewards = T::RewardsCollatorCommission::get() * rewards;
485
1045
    let delegators_rewards = rewards.err_sub(&candidate_rewards)?;
486

            
487
1045
    let Stake(auto_total_stake) = AutoCompounding::<T>::total_staked(candidate);
488
1045
    let Stake(manual_total_stake) = ManualRewards::<T>::total_staked(candidate);
489
1045
    let combined_total_stake = auto_total_stake.err_add(&manual_total_stake)?;
490

            
491
1045
    let candidate_manual_stake = if manual_total_stake.is_zero() {
492
1016
        Zero::zero()
493
    } else {
494
29
        ManualRewards::<T>::computed_stake(candidate, candidate)?.0
495
    };
496

            
497
    // Distribute delegators ManualRewards rewards, it implies some rounding.
498
1045
    let delegators_manual_rewards = if manual_total_stake.is_zero() {
499
1016
        Zero::zero()
500
    } else {
501
29
        let rewards = delegators_rewards.mul_div(manual_total_stake, combined_total_stake)?;
502
29
        ManualRewards::<T>::increase_rewards(candidate, Stake(rewards))?.0
503
    };
504

            
505
    // Distribute delegators AutoCompounding rewards with dust from ManualRewards.
506
    // If there is no auto compounding stake but auto compounding rewards it
507
    // means it comes from manual rewards rounding. Having non-zero total stake
508
    // with 0 share supply will cause issues, so in this case we distribute this
509
    // dust as candidate manual rewards.
510
1045
    let delegators_auto_rewards = delegators_rewards.err_sub(&delegators_manual_rewards)?;
511
1045
    let (delegators_auto_rewards, delegators_auto_dust) = if !auto_total_stake.is_zero() {
512
24
        AutoCompounding::<T>::share_stake_among_holders(candidate, Stake(delegators_auto_rewards))?;
513
24
        (delegators_auto_rewards, Zero::zero())
514
    } else {
515
1021
        (Zero::zero(), delegators_auto_rewards)
516
    };
517

            
518
    // Distribute candidate AutoCompounding rewards, it implies some rounding.
519
1045
    let candidate_auto_rewards = if auto_total_stake.is_zero() {
520
1021
        Zero::zero()
521
    } else {
522
        'a: {
523
24
            let candidate_auto_stake =
524
24
                AutoCompounding::<T>::computed_stake(candidate, candidate)?.0;
525
24
            let candidate_combined_stake = candidate_manual_stake.err_add(&candidate_auto_stake)?;
526

            
527
24
            if candidate_combined_stake.is_zero() {
528
1
                break 'a Zero::zero();
529
23
            }
530

            
531
23
            let rewards =
532
23
                candidate_rewards.mul_div(candidate_auto_stake, candidate_combined_stake)?;
533
23
            let new_shares = AutoCompounding::<T>::stake_to_shares(candidate, Stake(rewards))?;
534

            
535
23
            if new_shares.0.is_zero() {
536
6
                break 'a Zero::zero();
537
17
            }
538
17

            
539
17
            AutoCompounding::<T>::add_shares(candidate, candidate, new_shares)?.0
540
        }
541
    };
542

            
543
    // Distribute candidate ManualRewards rewards with dust from AutoCompounding.
544
    // The amount is returned by the function and will be transfered to the candidate account.
545
1045
    let candidate_manual_rewards = candidate_rewards
546
1045
        .err_sub(&candidate_auto_rewards)?
547
1045
        .err_add(&delegators_auto_dust)?;
548

            
549
1045
    let additional_stake = delegators_auto_rewards.err_add(&candidate_auto_rewards)?;
550
1045
    Candidates::<T>::add_total_stake(candidate, &Stake(additional_stake))?;
551

            
552
1045
    Pallet::<T>::deposit_event(Event::<T>::RewardedCollator {
553
1045
        collator: candidate.clone(),
554
1045
        auto_compounding_rewards: candidate_auto_rewards,
555
1045
        manual_claim_rewards: candidate_manual_rewards,
556
1045
    });
557
1045
    Pallet::<T>::deposit_event(Event::<T>::RewardedDelegators {
558
1045
        collator: candidate.clone(),
559
1045
        auto_compounding_rewards: delegators_auto_rewards,
560
1045
        manual_claim_rewards: delegators_manual_rewards,
561
1045
    });
562
1045

            
563
1045
    Ok(candidate_manual_rewards)
564
1045
}