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, CandidateSummaries, Config,
20
        CreditOf, Delegator, DelegatorCandidateSummaries, Error, Event, Pallet, Pools, PoolsKey,
21
        Shares, Stake,
22
    },
23
    core::marker::PhantomData,
24
    frame_support::{
25
        ensure,
26
        pallet_prelude::*,
27
        traits::{fungible::Balanced, Imbalance},
28
    },
29
    serde::{Deserialize, Serialize},
30
    sp_core::Get,
31
    sp_runtime::traits::{CheckedAdd, CheckedDiv, Zero},
32
    tp_maths::{ErrAdd, ErrMul, ErrSub, MulDiv},
33
};
34

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

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

            
55
    /// Get the initial value of a share in case none exist yet.
56
    fn initial_share_value() -> Stake<T::Balance>;
57
    /// Pool variant in PoolKind
58
    fn pool_kind() -> PoolKind;
59

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

            
70
1107
        Ok(Stake(shares.0.mul_div(total_staked, supply)?))
71
1108
    }
72

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

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

            
96
146
        Ok(Shares(stake.0.mul_div(supply, total_staked)?))
97
146
    }
98

            
99
491
    fn computed_stake(
100
491
        candidate: &Candidate<T>,
101
491
        delegator: &Delegator<T>,
102
491
    ) -> Result<Stake<T::Balance>, Error<T>> {
103
491
        let shares = Self::shares(candidate, delegator);
104
491
        if shares.0.is_zero() {
105
223
            return Ok(Stake(Zero::zero()));
106
268
        }
107
268

            
108
268
        Self::shares_to_stake(candidate, shares)
109
491
    }
110

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

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

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

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

            
163
493
        let stake = Self::shares_to_stake_or_init(candidate, shares)?;
164

            
165
493
        let old_shares = Self::shares(candidate, delegator);
166

            
167
493
        let new_shares_supply = Self::shares_supply(candidate).0.err_add(&shares.0)?;
168
493
        let new_shares = old_shares.0.err_add(&shares.0)?;
169
493
        let new_total_stake = Self::total_staked(candidate).0.err_add(&stake.0)?;
170

            
171
493
        let new_pool_member = old_shares.0.is_zero();
172
493
        let mut new_delegator = false;
173
493

            
174
493
        DelegatorCandidateSummaries::<T>::mutate(&delegator, &candidate, |summary| {
175
493
            if summary.is_empty() {
176
424
                new_delegator = true;
177
424
            }
178
493
            summary.set_pool(Self::pool_kind(), true);
179
493
        });
180
493

            
181
493
        CandidateSummaries::<T>::mutate(&candidate, |summary| {
182
493
            if new_pool_member {
183
453
                let count = summary.pool_delegators_mut(Self::pool_kind());
184
453
                *count = count.saturating_add(1);
185
453
            }
186

            
187
493
            if new_delegator {
188
424
                summary.delegators = summary.delegators.saturating_add(1);
189
424
            }
190
493
        });
191
493

            
192
493
        Self::set_shares_supply(candidate, Shares(new_shares_supply));
193
493
        Self::set_shares(candidate, delegator, Shares(new_shares));
194
493
        Self::set_total_staked(candidate, Stake(new_total_stake));
195
493

            
196
493
        Ok(stake)
197
493
    }
198

            
199
    /// Remove shares for that delegator towards the given candidate.
200
    /// Function returns the value of those removed shares.
201
    /// Returns an error if that delegator don't have enough shares or if underflow/overflows occurs.
202
238
    fn sub_shares(
203
238
        candidate: &Candidate<T>,
204
238
        delegator: &Delegator<T>,
205
238
        shares: Shares<T::Balance>,
206
238
    ) -> Result<Stake<T::Balance>, Error<T>> {
207
238
        ensure!(!shares.0.is_zero(), Error::StakeMustBeNonZero);
208

            
209
238
        let stake = Self::shares_to_stake(candidate, shares)?;
210

            
211
238
        let new_shares_supply = Self::shares_supply(candidate).0.err_sub(&shares.0)?;
212
233
        let new_shares = Self::shares(candidate, delegator).0.err_sub(&shares.0)?;
213
233
        let new_total_stake = Self::total_staked(candidate).0.err_sub(&stake.0)?;
214

            
215
233
        let rem_pool_member = new_shares.is_zero();
216
233
        let mut rem_delegator = false;
217
233

            
218
233
        DelegatorCandidateSummaries::<T>::mutate_exists(&delegator, &candidate, |summary| {
219
233
            let mut s = summary.unwrap_or_default();
220
233

            
221
233
            if rem_pool_member {
222
216
                s.set_pool(Self::pool_kind(), false);
223
216
            }
224

            
225
            // storage entry will be deleted if empty
226
233
            if s.is_empty() {
227
200
                rem_delegator = true;
228
200
                *summary = None;
229
200
            } else {
230
33
                *summary = Some(s)
231
            };
232
233
        });
233
233

            
234
233
        CandidateSummaries::<T>::mutate_exists(&candidate, |summary| {
235
233
            let mut s = summary.unwrap_or_default();
236
233

            
237
233
            if rem_pool_member {
238
216
                let count = s.pool_delegators_mut(Self::pool_kind());
239
216
                *count = count.saturating_sub(1);
240
216
            }
241

            
242
233
            if rem_delegator {
243
200
                s.delegators = s.delegators.saturating_sub(1);
244
200
            }
245

            
246
            // storage entry will be deleted if empty
247
233
            if s.delegators == 0 {
248
159
                *summary = None;
249
159
            } else {
250
74
                *summary = Some(s)
251
            }
252
233
        });
253
233

            
254
233
        Self::set_shares_supply(candidate, Shares(new_shares_supply));
255
233
        Self::set_shares(candidate, delegator, Shares(new_shares));
256
233
        Self::set_total_staked(candidate, Stake(new_total_stake));
257
233

            
258
233
        Ok(stake)
259
238
    }
260

            
261
474
    fn increase_hold(
262
474
        candidate: &Candidate<T>,
263
474
        delegator: &Delegator<T>,
264
474
        stake: &Stake<T::Balance>,
265
474
    ) -> Result<(), Error<T>> {
266
474
        let hold = Self::hold(candidate, delegator);
267
474
        let hold = hold.0.err_add(&stake.0)?;
268
474
        Self::set_hold(candidate, delegator, Stake(hold));
269
474
        Ok(())
270
474
    }
271

            
272
233
    fn decrease_hold(
273
233
        candidate: &Candidate<T>,
274
233
        delegator: &Delegator<T>,
275
233
        stake: &Stake<T::Balance>,
276
233
    ) -> Result<(), Error<T>> {
277
233
        let hold = Self::hold(candidate, delegator);
278
233
        let hold = hold.0.err_sub(&stake.0)?;
279
233
        Self::set_hold(candidate, delegator, Stake(hold));
280
233
        Ok(())
281
233
    }
282
}
283

            
284
470
pub fn check_candidate_consistency<T: Config>(candidate: &Candidate<T>) -> Result<(), Error<T>> {
285
470
    let total0 = Pools::<T>::get(candidate, &PoolsKey::CandidateTotalStake);
286
470

            
287
470
    let joining = Joining::<T>::total_staked(candidate).0;
288
470
    let auto = AutoCompounding::<T>::total_staked(candidate).0;
289
470
    let manual = ManualRewards::<T>::total_staked(candidate).0;
290

            
291
470
    let total1 = joining
292
470
        .checked_add(&auto)
293
470
        .ok_or(Error::InconsistentState)?
294
470
        .checked_add(&manual)
295
470
        .ok_or(Error::InconsistentState)?;
296

            
297
470
    ensure!(total0 == total1, Error::InconsistentState);
298

            
299
470
    Ok(())
300
470
}
301

            
302
macro_rules! impl_pool {
303
    ($name:ident, $shares:ident, $supply:ident, $total:ident, $hold: ident, $init:expr $(,)?) => {
304
        pub struct $name<T>(PhantomData<T>);
305
        impl<T: Config> Pool<T> for $name<T> {
306
1710
            fn shares(candidate: &Candidate<T>, delegator: &Delegator<T>) -> Shares<T::Balance> {
307
1710
                Shares(Pools::<T>::get(
308
1710
                    candidate,
309
1710
                    &PoolsKey::$shares {
310
1710
                        delegator: delegator.clone(),
311
1710
                    },
312
1710
                ))
313
1710
            }
314

            
315
3049
            fn shares_supply(candidate: &Candidate<T>) -> Shares<T::Balance> {
316
3049
                Shares(Pools::<T>::get(candidate, &PoolsKey::$supply))
317
3049
            }
318

            
319
6498
            fn total_staked(candidate: &Candidate<T>) -> Stake<T::Balance> {
320
6498
                Stake(Pools::<T>::get(candidate, &PoolsKey::$total))
321
6498
            }
322

            
323
1196
            fn hold(candidate: &Candidate<T>, delegator: &Delegator<T>) -> Stake<T::Balance> {
324
1196
                Stake(Pools::<T>::get(
325
1196
                    candidate,
326
1196
                    &PoolsKey::$hold {
327
1196
                        delegator: delegator.clone(),
328
1196
                    },
329
1196
                ))
330
1196
            }
331

            
332
726
            fn set_shares(
333
726
                candidate: &Candidate<T>,
334
726
                delegator: &Delegator<T>,
335
726
                value: Shares<T::Balance>,
336
726
            ) {
337
726
                Pools::<T>::set(
338
726
                    candidate,
339
726
                    &PoolsKey::$shares {
340
726
                        delegator: delegator.clone(),
341
726
                    },
342
726
                    value.0,
343
726
                )
344
726
            }
345

            
346
726
            fn set_shares_supply(candidate: &Candidate<T>, value: Shares<T::Balance>) {
347
726
                Pools::<T>::set(candidate, &PoolsKey::$supply, value.0)
348
726
            }
349

            
350
760
            fn set_total_staked(candidate: &Candidate<T>, value: Stake<T::Balance>) {
351
760
                Pools::<T>::set(candidate, &PoolsKey::$total, value.0)
352
760
            }
353

            
354
722
            fn set_hold(
355
722
                candidate: &Candidate<T>,
356
722
                delegator: &Delegator<T>,
357
722
                value: Stake<T::Balance>,
358
722
            ) {
359
722
                Pools::<T>::set(
360
722
                    candidate,
361
722
                    &PoolsKey::$hold {
362
722
                        delegator: delegator.clone(),
363
722
                    },
364
722
                    value.0,
365
722
                )
366
722
            }
367

            
368
496
            fn initial_share_value() -> Stake<T::Balance> {
369
496
                Stake($init)
370
496
            }
371

            
372
1418
            fn pool_kind() -> PoolKind {
373
1418
                PoolKind::$name
374
1418
            }
375
        }
376
    };
377
}
378

            
379
impl_pool!(
380
    Joining,
381
    JoiningShares,
382
    JoiningSharesSupply,
383
    JoiningSharesTotalStaked,
384
    JoiningSharesHeldStake,
385
    if cfg!(test) { 2u32 } else { 1 }.into(),
386
);
387

            
388
impl_pool!(
389
    AutoCompounding,
390
    AutoCompoundingShares,
391
    AutoCompoundingSharesSupply,
392
    AutoCompoundingSharesTotalStaked,
393
    AutoCompoundingSharesHeldStake,
394
    T::InitialAutoCompoundingShareValue::get(),
395
);
396

            
397
impl_pool!(
398
    ManualRewards,
399
    ManualRewardsShares,
400
    ManualRewardsSharesSupply,
401
    ManualRewardsSharesTotalStaked,
402
    ManualRewardsSharesHeldStake,
403
    T::InitialManualClaimShareValue::get(),
404
);
405

            
406
impl_pool!(
407
    Leaving,
408
    LeavingShares,
409
    LeavingSharesSupply,
410
    LeavingSharesTotalStaked,
411
    LeavingSharesHeldStake,
412
    if cfg!(test) { 3u32 } else { 1u32 }.into(),
413
);
414

            
415
impl<T: Config> ManualRewards<T> {
416
    #[allow(dead_code)]
417
16
    pub fn pending_rewards(
418
16
        candidate: &Candidate<T>,
419
16
        delegator: &Delegator<T>,
420
16
    ) -> Result<Stake<T::Balance>, Error<T>> {
421
16
        let shares = Self::shares(candidate, delegator);
422
16

            
423
16
        if shares.0.is_zero() {
424
5
            return Ok(Stake(0u32.into()));
425
11
        }
426
11

            
427
11
        let counter = Pools::<T>::get(candidate, &PoolsKey::ManualRewardsCounter);
428
11
        let checkpoint = Pools::<T>::get(
429
11
            candidate,
430
11
            &PoolsKey::ManualRewardsCheckpoint {
431
11
                delegator: delegator.clone(),
432
11
            },
433
11
        );
434

            
435
        // TODO: Should be safe to wrap around.
436
11
        let diff = counter.err_sub(&checkpoint)?;
437
11
        Ok(Stake(diff.err_mul(&shares.0)?))
438
16
    }
439

            
440
    /// Increase the rewards of the ManualRewards pool with best effort.
441
    /// Returns the actual amount distributed (after rounding).
442
29
    pub fn increase_rewards(
443
29
        candidate: &Candidate<T>,
444
29
        rewards: Stake<T::Balance>,
445
29
    ) -> Result<Stake<T::Balance>, Error<T>> {
446
29
        let Shares(supply) = Self::shares_supply(candidate);
447
29
        if supply.is_zero() {
448
            return Ok(Stake(Zero::zero()));
449
29
        }
450

            
451
29
        let rewards_per_share = rewards
452
29
            .0
453
29
            .checked_div(&supply)
454
29
            .ok_or(Error::<T>::InconsistentState)?;
455
29
        if rewards_per_share.is_zero() {
456
            return Ok(Stake(Zero::zero()));
457
29
        }
458

            
459
29
        let rewards = rewards_per_share.err_mul(&supply)?;
460

            
461
29
        let counter = Pools::<T>::get(candidate, &PoolsKey::ManualRewardsCounter);
462
29
        let counter = counter.err_add(&rewards_per_share)?;
463
29
        Pools::<T>::set(candidate, &PoolsKey::ManualRewardsCounter, counter);
464
29

            
465
29
        Ok(Stake(rewards))
466
29
    }
467

            
468
89
    pub fn claim_rewards(
469
89
        candidate: &Candidate<T>,
470
89
        delegator: &Delegator<T>,
471
89
    ) -> Result<Stake<T::Balance>, Error<T>> {
472
89
        let shares = Self::shares(candidate, delegator);
473
89

            
474
89
        let counter = Pools::<T>::get(candidate, &PoolsKey::ManualRewardsCounter);
475
89
        let checkpoint = Pools::<T>::get(
476
89
            candidate,
477
89
            &PoolsKey::ManualRewardsCheckpoint {
478
89
                delegator: delegator.clone(),
479
89
            },
480
89
        );
481

            
482
        // TODO: Should be safe to wrap around.
483
89
        let diff = counter.err_sub(&checkpoint)?;
484

            
485
89
        if diff.is_zero() {
486
80
            return Ok(Stake(0u32.into()));
487
9
        }
488

            
489
9
        let rewards = diff.err_mul(&shares.0)?;
490

            
491
        // Update checkpoint
492
9
        Pools::<T>::set(
493
9
            candidate,
494
9
            &PoolsKey::ManualRewardsCheckpoint {
495
9
                delegator: delegator.clone(),
496
9
            },
497
9
            counter,
498
9
        );
499
9

            
500
9
        Ok(Stake(rewards))
501
89
    }
502
}
503

            
504
/// Perform rewards distribution for the provided candidate.
505
///
506
/// The pallet considered that it already posses the rewards in its account,
507
/// and it is the responsibility of the caller to transfer or mint the currency
508
/// to the staking pallet account.
509
///
510
/// Rewards are split using `RewardsCollatorCommission` between the candidate
511
/// and all the delegators (including the candidate self-delegation). For each,
512
/// the rewards are then split according to the value of all the ManualRewards
513
/// and AutoCompounding shares.
514
///
515
/// As candidate rewards will give increase the candidate auto compounding
516
/// self-delegation, the delegator rewards are distributed first. ManualRewards
517
/// pool rewards are first distributed by increasing the pool counter, which may
518
/// result in some rounding. As distributing the AutoCompounding pool rewards
519
/// consists of simply increasing `AutoCompoundingSharesTotalStaked`, it is not
520
/// subject to rounding and it can absorb the rounding dust from ManualRewards
521
/// reward distribution.
522
///
523
/// Then it is time to distribute the candidate dedicated rewards. For
524
/// AutoCompounding, it is as if the candidate received the rewards then
525
/// self-delegated (instantly). It is thus implemented by creating new
526
/// AutoCompounding shares. This can lead to some rounding, which will be
527
/// absorbed in the ManualRewards distribution, which simply consist of
528
/// transfering the funds to the candidate account.
529
#[frame_support::transactional]
530
pub fn distribute_rewards<T: Config>(
531
    candidate: &Candidate<T>,
532
    rewards: CreditOf<T>,
533
) -> DispatchResultWithPostInfo {
534
    let candidate_manual_rewards = distribute_rewards_inner::<T>(candidate, rewards.peek())?;
535

            
536
    let (candidate_manual_rewards, other_rewards) = rewards.split(candidate_manual_rewards);
537

            
538
    if !candidate_manual_rewards.peek().is_zero() {
539
        T::Currency::resolve(candidate, candidate_manual_rewards)
540
1
            .map_err(|_| DispatchError::NoProviders)?;
541
    }
542

            
543
    T::Currency::resolve(&T::StakingAccount::get(), other_rewards)
544
33
        .map_err(|_| DispatchError::NoProviders)?;
545

            
546
    Ok(Some(T::WeightInfo::distribute_rewards()).into())
547
}
548

            
549
1045
fn distribute_rewards_inner<T: Config>(
550
1045
    candidate: &Candidate<T>,
551
1045
    rewards: T::Balance,
552
1045
) -> Result<T::Balance, Error<T>> {
553
1045
    // `RewardsCollatorCommission` is a `Perbill` so we're not worried about overflow.
554
1045
    let candidate_rewards = T::RewardsCollatorCommission::get() * rewards;
555
1045
    let delegators_rewards = rewards.err_sub(&candidate_rewards)?;
556

            
557
1045
    let Stake(auto_total_stake) = AutoCompounding::<T>::total_staked(candidate);
558
1045
    let Stake(manual_total_stake) = ManualRewards::<T>::total_staked(candidate);
559
1045
    let combined_total_stake = auto_total_stake.err_add(&manual_total_stake)?;
560

            
561
1045
    let candidate_manual_stake = if manual_total_stake.is_zero() {
562
1016
        Zero::zero()
563
    } else {
564
29
        ManualRewards::<T>::computed_stake(candidate, candidate)?.0
565
    };
566

            
567
    // Distribute delegators ManualRewards rewards, it implies some rounding.
568
1045
    let delegators_manual_rewards = if manual_total_stake.is_zero() {
569
1016
        Zero::zero()
570
    } else {
571
29
        let rewards = delegators_rewards.mul_div(manual_total_stake, combined_total_stake)?;
572
29
        ManualRewards::<T>::increase_rewards(candidate, Stake(rewards))?.0
573
    };
574

            
575
    // Distribute delegators AutoCompounding rewards with dust from ManualRewards.
576
    // If there is no auto compounding stake but auto compounding rewards it
577
    // means it comes from manual rewards rounding. Having non-zero total stake
578
    // with 0 share supply will cause issues, so in this case we distribute this
579
    // dust as candidate manual rewards.
580
1045
    let delegators_auto_rewards = delegators_rewards.err_sub(&delegators_manual_rewards)?;
581
1045
    let (delegators_auto_rewards, delegators_auto_dust) = if !auto_total_stake.is_zero() {
582
24
        AutoCompounding::<T>::share_stake_among_holders(candidate, Stake(delegators_auto_rewards))?;
583
24
        (delegators_auto_rewards, Zero::zero())
584
    } else {
585
1021
        (Zero::zero(), delegators_auto_rewards)
586
    };
587

            
588
    // Distribute candidate AutoCompounding rewards, it implies some rounding.
589
1045
    let candidate_auto_rewards = if auto_total_stake.is_zero() {
590
1021
        Zero::zero()
591
    } else {
592
        'a: {
593
24
            let candidate_auto_stake =
594
24
                AutoCompounding::<T>::computed_stake(candidate, candidate)?.0;
595
24
            let candidate_combined_stake = candidate_manual_stake.err_add(&candidate_auto_stake)?;
596

            
597
24
            if candidate_combined_stake.is_zero() {
598
1
                break 'a Zero::zero();
599
23
            }
600

            
601
23
            let rewards =
602
23
                candidate_rewards.mul_div(candidate_auto_stake, candidate_combined_stake)?;
603
23
            let new_shares = AutoCompounding::<T>::stake_to_shares(candidate, Stake(rewards))?;
604

            
605
23
            if new_shares.0.is_zero() {
606
6
                break 'a Zero::zero();
607
17
            }
608
17

            
609
17
            AutoCompounding::<T>::add_shares(candidate, candidate, new_shares)?.0
610
        }
611
    };
612

            
613
    // Distribute candidate ManualRewards rewards with dust from AutoCompounding.
614
    // The amount is returned by the function and will be transfered to the candidate account.
615
1045
    let candidate_manual_rewards = candidate_rewards
616
1045
        .err_sub(&candidate_auto_rewards)?
617
1045
        .err_add(&delegators_auto_dust)?;
618

            
619
1045
    let additional_stake = delegators_auto_rewards.err_add(&candidate_auto_rewards)?;
620
1045
    Candidates::<T>::add_total_stake(candidate, &Stake(additional_stake))?;
621

            
622
1045
    Pallet::<T>::deposit_event(Event::<T>::RewardedCollator {
623
1045
        collator: candidate.clone(),
624
1045
        auto_compounding_rewards: candidate_auto_rewards,
625
1045
        manual_claim_rewards: candidate_manual_rewards,
626
1045
    });
627
1045
    Pallet::<T>::deposit_event(Event::<T>::RewardedDelegators {
628
1045
        collator: candidate.clone(),
629
1045
        auto_compounding_rewards: delegators_auto_rewards,
630
1045
        manual_claim_rewards: delegators_manual_rewards,
631
1045
    });
632
1045

            
633
1045
    Ok(candidate_manual_rewards)
634
1045
}
635

            
636
const MASK_JOINING: u8 = 1u8;
637
const MASK_AUTO: u8 = 1u8 << 1;
638
const MASK_MANUAL: u8 = 1u8 << 2;
639
const MASK_LEAVING: u8 = 1u8 << 3;
640

            
641
/// Enum of all available pools.
642
/// Must match with the names of the pool structs generated with `impl_pool!`.
643
#[derive(
644
    RuntimeDebug,
645
    PartialEq,
646
    Eq,
647
    Encode,
648
    Decode,
649
    DecodeWithMemTracking,
650
    Copy,
651
    Clone,
652
4944
    TypeInfo,
653
    Serialize,
654
    Deserialize,
655
)]
656
pub enum PoolKind {
657
    Joining,
658
    AutoCompounding,
659
    ManualRewards,
660
    Leaving,
661
}
662

            
663
/// Restricted list of pools that represent active delegation. Those can be targetted by joining
664
/// requests.
665
#[derive(
666
    RuntimeDebug,
667
    PartialEq,
668
    Eq,
669
    Encode,
670
    Decode,
671
    DecodeWithMemTracking,
672
    Copy,
673
    Clone,
674
2472
    TypeInfo,
675
    Serialize,
676
    Deserialize,
677
)]
678
pub enum ActivePoolKind {
679
412
    AutoCompounding,
680
415
    ManualRewards,
681
}
682

            
683
impl From<ActivePoolKind> for PoolKind {
684
6
    fn from(value: ActivePoolKind) -> Self {
685
6
        match value {
686
3
            ActivePoolKind::AutoCompounding => PoolKind::AutoCompounding,
687
3
            ActivePoolKind::ManualRewards => PoolKind::ManualRewards,
688
        }
689
6
    }
690
}
691

            
692
impl PoolKind {
693
6190
    fn to_bitmask(&self) -> u8 {
694
6190
        match self {
695
3445
            Self::Joining => MASK_JOINING,
696
1735
            Self::AutoCompounding => MASK_AUTO,
697
315
            Self::ManualRewards => MASK_MANUAL,
698
695
            Self::Leaving => MASK_LEAVING,
699
        }
700
6190
    }
701
}
702

            
703
/// Keeps track of which pools of some candidate a delegator is into.
704
/// This is used in storage to have a quick way to fetch all the delegations of
705
/// a delegator, and then know exactly which storage entries to look at to get
706
/// more detailed info.
707
#[derive(
708
    RuntimeDebug,
709
    Default,
710
    PartialEq,
711
    Eq,
712
    Encode,
713
    Decode,
714
    Copy,
715
    Clone,
716
1236
    TypeInfo,
717
    Serialize,
718
    Deserialize,
719
    MaxEncodedLen,
720
)]
721
pub struct DelegatorCandidateSummary(pub(crate) u8);
722

            
723
impl DelegatorCandidateSummary {
724
18
    pub fn new() -> Self {
725
18
        Self(0)
726
18
    }
727

            
728
    fn bit(&self, mask: u8) -> bool {
729
        self.0 & mask != 0
730
    }
731

            
732
6266
    fn set_bit(&mut self, mask: u8, value: bool) {
733
6266
        if value {
734
4391
            self.0 = self.0 | mask
735
        } else {
736
1806
            self.0 = self.0 & !mask
737
        }
738
6266
    }
739

            
740
6323
    pub fn is_empty(&self) -> bool {
741
6323
        self.0 == 0
742
6323
    }
743

            
744
    pub fn joining(&self) -> bool {
745
        self.bit(MASK_JOINING)
746
    }
747

            
748
    pub fn auto(&self) -> bool {
749
        self.bit(MASK_AUTO)
750
    }
751

            
752
    pub fn manual(&self) -> bool {
753
        self.bit(MASK_MANUAL)
754
    }
755

            
756
    pub fn leaving(&self) -> bool {
757
        self.bit(MASK_LEAVING)
758
    }
759

            
760
    pub fn pool(&self, pool: PoolKind) -> bool {
761
        self.bit(pool.to_bitmask())
762
    }
763

            
764
6168
    pub fn set_pool(&mut self, pool: PoolKind, value: bool) {
765
6168
        self.set_bit(pool.to_bitmask(), value)
766
6168
    }
767

            
768
29
    pub fn with_bit(mut self, mask: u8, value: bool) -> Self {
769
29
        self.set_bit(mask, value);
770
29
        self
771
29
    }
772

            
773
3
    pub fn with_joining(self, value: bool) -> Self {
774
3
        self.with_bit(MASK_JOINING, value)
775
3
    }
776

            
777
1
    pub fn with_auto(self, value: bool) -> Self {
778
1
        self.with_bit(MASK_AUTO, value)
779
1
    }
780

            
781
1
    pub fn with_manual(self, value: bool) -> Self {
782
1
        self.with_bit(MASK_MANUAL, value)
783
1
    }
784

            
785
2
    pub fn with_leaving(self, value: bool) -> Self {
786
2
        self.with_bit(MASK_LEAVING, value)
787
2
    }
788

            
789
22
    pub fn with_pool(self, pool: PoolKind, value: bool) -> Self {
790
22
        self.with_bit(pool.to_bitmask(), value)
791
22
    }
792
}
793

            
794
/// Keeps track of stats that are useful for dApps and block explorers which can
795
/// be tricky or expensive to gather otherwise.
796
#[derive(
797
    RuntimeDebug,
798
    Default,
799
    PartialEq,
800
    Eq,
801
    Encode,
802
    Decode,
803
    Copy,
804
    Clone,
805
6180
    TypeInfo,
806
    Serialize,
807
    Deserialize,
808
    MaxEncodedLen,
809
)]
810
pub struct CandidateSummary {
811
    /// Amount of delegators in any pool without duplicates.
812
    pub delegators: u32,
813
    /// Amount of joining delegators. A single delegator joining multiple times
814
    /// only count once.
815
    pub joining_delegators: u32,
816
    /// Amount of delegators in the auto compounding pool.
817
    pub auto_compounding_delegators: u32,
818
    /// Amount of delegators in the manual rewards pool.
819
    pub manual_rewards_delegators: u32,
820
    /// Amount of leaving delegators. A single delegator leaving multiple times
821
    //// only count once.
822
    pub leaving_delegators: u32,
823
}
824

            
825
impl CandidateSummary {
826
5789
    pub fn pool_delegators_mut(&mut self, pool: PoolKind) -> &mut u32 {
827
5789
        match pool {
828
3226
            PoolKind::Joining => &mut self.joining_delegators,
829
1702
            PoolKind::AutoCompounding => &mut self.auto_compounding_delegators,
830
310
            PoolKind::ManualRewards => &mut self.manual_rewards_delegators,
831
551
            PoolKind::Leaving => &mut self.leaving_delegators,
832
        }
833
5789
    }
834

            
835
18
    pub fn with_pool(mut self, pool: PoolKind, count: u32) -> Self {
836
18
        let pool = self.pool_delegators_mut(pool);
837
18
        *pool = count;
838
18
        self
839
18
    }
840
}