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

            
70
884
        Ok(Stake(shares.0.mul_div(total_staked, supply)?))
71
885
    }
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
329
    fn shares_to_stake_or_init(
76
329
        candidate: &Candidate<T>,
77
329
        shares: Shares<T::Balance>,
78
329
    ) -> Result<Stake<T::Balance>, Error<T>> {
79
329
        if Self::total_staked(candidate).0.is_zero() {
80
290
            Ok(Stake(shares.0.err_mul(&Self::initial_share_value().0)?))
81
        } else {
82
39
            Self::shares_to_stake(candidate, shares)
83
        }
84
329
    }
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
102
    fn stake_to_shares(
89
102
        candidate: &Candidate<T>,
90
102
        stake: Stake<T::Balance>,
91
102
    ) -> Result<Shares<T::Balance>, Error<T>> {
92
102
        let total_staked = Self::total_staked(candidate).0;
93
102
        let supply = Self::shares_supply(candidate).0;
94
102
        ensure!(!supply.is_zero(), Error::NoOneIsStaking);
95

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

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

            
108
258
        Self::shares_to_stake(candidate, shares)
109
477
    }
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
320
    fn stake_to_shares_or_init(
114
320
        candidate: &Candidate<T>,
115
320
        stake: Stake<T::Balance>,
116
320
    ) -> Result<Shares<T::Balance>, Error<T>> {
117
320
        if Self::total_staked(candidate).0.is_zero() {
118
            Ok(Shares(
119
286
                stake
120
286
                    .0
121
286
                    .checked_div(&Self::initial_share_value().0)
122
286
                    .ok_or(Error::<T>::InvalidPalletSetting)?,
123
            ))
124
        } else {
125
34
            Self::stake_to_shares(candidate, stake)
126
        }
127
320
    }
128

            
129
    /// Increase the total stake of a pool without creating new shares, which basically increase
130
    /// the value of each share.
131
28
    fn share_stake_among_holders(
132
28
        candidate: &Candidate<T>,
133
28
        stake: Stake<T::Balance>,
134
28
    ) -> Result<(), Error<T>> {
135
28
        let total_staked = Self::total_staked(candidate).0;
136
28
        let total_staked = total_staked.err_add(&stake.0)?;
137
28
        Self::set_total_staked(candidate, Stake(total_staked));
138
28
        Ok(())
139
28
    }
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
325
    fn add_shares(
157
325
        candidate: &Candidate<T>,
158
325
        delegator: &Delegator<T>,
159
325
        shares: Shares<T::Balance>,
160
325
    ) -> Result<Stake<T::Balance>, Error<T>> {
161
325
        ensure!(!shares.0.is_zero(), Error::StakeMustBeNonZero);
162

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

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

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

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

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

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

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

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

            
196
325
        Ok(stake)
197
325
    }
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
170
    fn sub_shares(
203
170
        candidate: &Candidate<T>,
204
170
        delegator: &Delegator<T>,
205
170
        shares: Shares<T::Balance>,
206
170
    ) -> Result<Stake<T::Balance>, Error<T>> {
207
170
        ensure!(!shares.0.is_zero(), Error::StakeMustBeNonZero);
208

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

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

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

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

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

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

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

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

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

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

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

            
258
165
        Ok(stake)
259
170
    }
260

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

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

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

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

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

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

            
299
314
    Ok(())
300
314
}
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
1333
            fn shares(candidate: &Candidate<T>, delegator: &Delegator<T>) -> Shares<T::Balance> {
307
1333
                Shares(Pools::<T>::get(
308
1333
                    candidate,
309
1333
                    &PoolsKey::$shares {
310
1333
                        delegator: delegator.clone(),
311
1333
                    },
312
1333
                ))
313
1333
            }
314

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

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

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

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

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

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

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

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

            
372
958
            fn pool_kind() -> PoolKind {
373
958
                PoolKind::$name
374
958
            }
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

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

            
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
        );
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
19
    pub fn increase_rewards(
443
19
        candidate: &Candidate<T>,
444
19
        rewards: Stake<T::Balance>,
445
19
    ) -> Result<Stake<T::Balance>, Error<T>> {
446
19
        let Shares(supply) = Self::shares_supply(candidate);
447
19
        if supply.is_zero() {
448
            return Ok(Stake(Zero::zero()));
449
19
        }
450

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

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

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

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

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

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

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

            
485
55
        if diff.is_zero() {
486
52
            return Ok(Stake(0u32.into()));
487
3
        }
488

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

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

            
500
3
        Ok(Stake(rewards))
501
55
    }
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
            .map_err(|_| DispatchError::NoProviders)?;
541
    }
542

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

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

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

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

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

            
567
    // Distribute delegators ManualRewards rewards, it implies some rounding.
568
90
    let delegators_manual_rewards = if manual_total_stake.is_zero() {
569
71
        Zero::zero()
570
    } else {
571
19
        let rewards = delegators_rewards.mul_div(manual_total_stake, combined_total_stake)?;
572
19
        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
90
    let delegators_auto_rewards = delegators_rewards.err_sub(&delegators_manual_rewards)?;
581
90
    let (delegators_auto_rewards, delegators_auto_dust) = if !auto_total_stake.is_zero() {
582
20
        AutoCompounding::<T>::share_stake_among_holders(candidate, Stake(delegators_auto_rewards))?;
583
20
        (delegators_auto_rewards, Zero::zero())
584
    } else {
585
70
        (Zero::zero(), delegators_auto_rewards)
586
    };
587

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

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

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

            
605
19
            if new_shares.0.is_zero() {
606
14
                break 'a Zero::zero();
607
5
            }
608

            
609
5
            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
90
    let candidate_manual_rewards = candidate_rewards
616
90
        .err_sub(&candidate_auto_rewards)?
617
90
        .err_add(&delegators_auto_dust)?;
618

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

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

            
633
90
    Ok(candidate_manual_rewards)
634
90
}
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
    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
    TypeInfo,
675
    Serialize,
676
    Deserialize,
677
)]
678
pub enum ActivePoolKind {
679
    AutoCompounding,
680
    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
6698
    fn to_bitmask(self) -> u8 {
694
6698
        match self {
695
3839
            Self::Joining => MASK_JOINING,
696
1823
            Self::AutoCompounding => MASK_AUTO,
697
311
            Self::ManualRewards => MASK_MANUAL,
698
725
            Self::Leaving => MASK_LEAVING,
699
        }
700
6698
    }
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
    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
6780
    fn set_bit(&mut self, mask: u8, value: bool) {
733
6780
        if value {
734
4807
            self.0 |= mask
735
        } else {
736
1973
            self.0 &= !mask
737
        }
738
6780
    }
739

            
740
6843
    pub fn is_empty(&self) -> bool {
741
6843
        self.0 == 0
742
6843
    }
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
6676
    pub fn set_pool(&mut self, pool: PoolKind, value: bool) {
765
6676
        self.set_bit(pool.to_bitmask(), value)
766
6676
    }
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
    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
6291
    pub fn pool_delegators_mut(&mut self, pool: PoolKind) -> &mut u32 {
827
6291
        match pool {
828
3602
            PoolKind::Joining => &mut self.joining_delegators,
829
1814
            PoolKind::AutoCompounding => &mut self.auto_compounding_delegators,
830
306
            PoolKind::ManualRewards => &mut self.manual_rewards_delegators,
831
569
            PoolKind::Leaving => &mut self.leaving_delegators,
832
        }
833
6291
    }
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
}