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
827
    fn shares_to_stake(
59
827
        candidate: &Candidate<T>,
60
827
        shares: Shares<T::Balance>,
61
827
    ) -> Result<Stake<T::Balance>, Error<T>> {
62
827
        let total_staked = Self::total_staked(candidate).0;
63
827
        let supply = Self::shares_supply(candidate).0;
64
827
        ensure!(!supply.is_zero(), Error::NoOneIsStaking);
65

            
66
827
        Ok(Stake(shares.0.mul_div(total_staked, supply)?))
67
827
    }
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
317
    fn shares_to_stake_or_init(
72
317
        candidate: &Candidate<T>,
73
317
        shares: Shares<T::Balance>,
74
317
    ) -> Result<Stake<T::Balance>, Error<T>> {
75
317
        if Self::total_staked(candidate).0.is_zero() {
76
266
            Ok(Stake(shares.0.err_mul(&Self::initial_share_value().0)?))
77
        } else {
78
51
            Self::shares_to_stake(candidate, shares)
79
        }
80
317
    }
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
90
    fn stake_to_shares(
85
90
        candidate: &Candidate<T>,
86
90
        stake: Stake<T::Balance>,
87
90
    ) -> Result<Shares<T::Balance>, Error<T>> {
88
90
        let total_staked = Self::total_staked(candidate).0;
89
90
        let supply = Self::shares_supply(candidate).0;
90
90
        ensure!(!supply.is_zero(), Error::NoOneIsStaking);
91

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

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

            
104
248
        Self::shares_to_stake(candidate, shares)
105
449
    }
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
300
    fn stake_to_shares_or_init(
110
300
        candidate: &Candidate<T>,
111
300
        stake: Stake<T::Balance>,
112
300
    ) -> Result<Shares<T::Balance>, Error<T>> {
113
300
        if Self::total_staked(candidate).0.is_zero() {
114
            Ok(Shares(
115
262
                stake
116
262
                    .0
117
262
                    .checked_div(&Self::initial_share_value().0)
118
262
                    .ok_or(Error::<T>::InvalidPalletSetting)?,
119
            ))
120
        } else {
121
38
            Self::stake_to_shares(candidate, stake)
122
        }
123
300
    }
124

            
125
    /// Increase the total stake of a pool without creating new shares, which basically increase
126
    /// the value of each share.
127
28
    fn share_stake_among_holders(
128
28
        candidate: &Candidate<T>,
129
28
        stake: Stake<T::Balance>,
130
28
    ) -> Result<(), Error<T>> {
131
28
        let total_staked = Self::total_staked(candidate).0;
132
28
        let total_staked = total_staked.err_add(&stake.0)?;
133
28
        Self::set_total_staked(candidate, Stake(total_staked));
134
28
        Ok(())
135
28
    }
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
313
    fn add_shares(
153
313
        candidate: &Candidate<T>,
154
313
        delegator: &Delegator<T>,
155
313
        shares: Shares<T::Balance>,
156
313
    ) -> Result<Stake<T::Balance>, Error<T>> {
157
313
        ensure!(!shares.0.is_zero(), Error::StakeMustBeNonZero);
158

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

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

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

            
169
313
        Ok(stake)
170
313
    }
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
152
    fn sub_shares(
176
152
        candidate: &Candidate<T>,
177
152
        delegator: &Delegator<T>,
178
152
        shares: Shares<T::Balance>,
179
152
    ) -> Result<Stake<T::Balance>, Error<T>> {
180
152
        ensure!(!shares.0.is_zero(), Error::StakeMustBeNonZero);
181

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

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

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

            
192
149
        Ok(stake)
193
152
    }
194

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

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

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

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

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

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

            
233
294
    Ok(())
234
294
}
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
1266
            fn shares(candidate: &Candidate<T>, delegator: &Delegator<T>) -> Shares<T::Balance> {
241
1266
                Shares(Pools::<T>::get(
242
1266
                    candidate,
243
1266
                    &PoolsKey::$shares {
244
1266
                        delegator: delegator.clone(),
245
1266
                    },
246
1266
                ))
247
1266
            }
248

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

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

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

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

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

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

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

            
302
316
            fn initial_share_value() -> Stake<T::Balance> {
303
316
                Stake($init)
304
316
            }
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
23
    pub fn increase_rewards(
373
23
        candidate: &Candidate<T>,
374
23
        rewards: Stake<T::Balance>,
375
23
    ) -> Result<Stake<T::Balance>, Error<T>> {
376
23
        let Shares(supply) = Self::shares_supply(candidate);
377
23
        if supply.is_zero() {
378
            return Ok(Stake(Zero::zero()));
379
23
        }
380

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

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

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

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

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

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

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

            
415
66
        if diff.is_zero() {
416
59
            return Ok(Stake(0u32.into()));
417
7
        }
418

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

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

            
430
7
        Ok(Stake(rewards))
431
66
    }
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
2139
#[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
713
fn distribute_rewards_inner<T: Config>(
480
713
    candidate: &Candidate<T>,
481
713
    rewards: T::Balance,
482
713
) -> Result<T::Balance, Error<T>> {
483
713
    // `RewardsCollatorCommission` is a `Perbill` so we're not worried about overflow.
484
713
    let candidate_rewards = T::RewardsCollatorCommission::get() * rewards;
485
713
    let delegators_rewards = rewards.err_sub(&candidate_rewards)?;
486

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

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

            
497
    // Distribute delegators ManualRewards rewards, it implies some rounding.
498
713
    let delegators_manual_rewards = if manual_total_stake.is_zero() {
499
690
        Zero::zero()
500
    } else {
501
23
        let rewards = delegators_rewards.mul_div(manual_total_stake, combined_total_stake)?;
502
23
        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
713
    let delegators_auto_rewards = delegators_rewards.err_sub(&delegators_manual_rewards)?;
511
713
    let (delegators_auto_rewards, delegators_auto_dust) = if !auto_total_stake.is_zero() {
512
20
        AutoCompounding::<T>::share_stake_among_holders(candidate, Stake(delegators_auto_rewards))?;
513
20
        (delegators_auto_rewards, Zero::zero())
514
    } else {
515
693
        (Zero::zero(), delegators_auto_rewards)
516
    };
517

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

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

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

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

            
539
13
            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
713
    let candidate_manual_rewards = candidate_rewards
546
713
        .err_sub(&candidate_auto_rewards)?
547
713
        .err_add(&delegators_auto_dust)?;
548

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

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

            
563
713
    Ok(candidate_manual_rewards)
564
713
}