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, traits::Timer, weights::WeightInfo, Candidate, CandidateSummaries,
20
        Config, Delegator, DelegatorCandidateSummaries, Error, Event, Pallet, Pools, PoolsKey,
21
        Shares, Stake,
22
    },
23
    alloc::{collections::BTreeMap, vec::Vec},
24
    core::marker::PhantomData,
25
    frame_support::{
26
        ensure,
27
        pallet_prelude::*,
28
        traits::{
29
            fungible::{Balanced, Mutate},
30
            tokens::Preservation,
31
            Imbalance,
32
        },
33
    },
34
    serde::{Deserialize, Serialize},
35
    sp_core::Get,
36
    sp_runtime::traits::{CheckedAdd, CheckedDiv, Zero},
37
    tp_maths::{ErrAdd, ErrMul, ErrSub, MulDiv},
38
};
39

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

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

            
60
    /// Get the initial value of a share in case none exist yet.
61
    fn initial_share_value() -> Stake<T::Balance>;
62
    /// Pool variant in PoolKind
63
    fn pool_kind() -> PoolKind;
64

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

            
75
882
        Ok(Stake(shares.0.mul_div(total_staked, supply)?))
76
883
    }
77

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

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

            
101
101
        Ok(Shares(stake.0.mul_div(supply, total_staked)?))
102
101
    }
103

            
104
464
    fn computed_stake(
105
464
        candidate: &Candidate<T>,
106
464
        delegator: &Delegator<T>,
107
464
    ) -> Result<Stake<T::Balance>, Error<T>> {
108
464
        let shares = Self::shares(candidate, delegator);
109
464
        if shares.0.is_zero() {
110
212
            return Ok(Stake(Zero::zero()));
111
252
        }
112

            
113
252
        Self::shares_to_stake(candidate, shares)
114
464
    }
115

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

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

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

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

            
168
336
        let stake = Self::shares_to_stake_or_init(candidate, shares)?;
169

            
170
336
        let old_shares = Self::shares(candidate, delegator);
171

            
172
336
        let new_shares_supply = Self::shares_supply(candidate).0.err_add(&shares.0)?;
173
336
        let new_shares = old_shares.0.err_add(&shares.0)?;
174
336
        let new_total_stake = Self::total_staked(candidate).0.err_add(&stake.0)?;
175

            
176
336
        let new_pool_member = old_shares.0.is_zero();
177
336
        let mut new_delegator = false;
178

            
179
336
        DelegatorCandidateSummaries::<T>::mutate(delegator, candidate, |summary| {
180
336
            if summary.is_empty() {
181
274
                new_delegator = true;
182
274
            }
183
336
            summary.set_pool(Self::pool_kind(), true);
184
336
        });
185

            
186
336
        CandidateSummaries::<T>::mutate(candidate, |summary| {
187
336
            if new_pool_member {
188
307
                let count = summary.pool_delegators_mut(Self::pool_kind());
189
307
                *count = count.saturating_add(1);
190
307
            }
191

            
192
336
            if new_delegator {
193
274
                summary.delegators = summary.delegators.saturating_add(1);
194
274
            }
195
336
        });
196

            
197
336
        Self::set_shares_supply(candidate, Shares(new_shares_supply));
198
336
        Self::set_shares(candidate, delegator, Shares(new_shares));
199
336
        Self::set_total_staked(candidate, Stake(new_total_stake));
200

            
201
336
        Ok(stake)
202
336
    }
203

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

            
214
176
        let stake = Self::shares_to_stake(candidate, shares)?;
215

            
216
176
        let new_shares_supply = Self::shares_supply(candidate).0.err_sub(&shares.0)?;
217
171
        let new_shares = Self::shares(candidate, delegator).0.err_sub(&shares.0)?;
218
171
        let new_total_stake = Self::total_staked(candidate).0.err_sub(&stake.0)?;
219

            
220
171
        let rem_pool_member = new_shares.is_zero();
221
171
        let mut rem_delegator = false;
222

            
223
171
        DelegatorCandidateSummaries::<T>::mutate_exists(delegator, candidate, |summary| {
224
171
            let mut s = summary.unwrap_or_default();
225

            
226
171
            if rem_pool_member {
227
152
                s.set_pool(Self::pool_kind(), false);
228
152
            }
229

            
230
            // storage entry will be deleted if empty
231
171
            if s.is_empty() {
232
134
                rem_delegator = true;
233
134
                *summary = None;
234
134
            } else {
235
37
                *summary = Some(s)
236
            };
237
171
        });
238

            
239
171
        CandidateSummaries::<T>::mutate_exists(candidate, |summary| {
240
171
            let mut s = summary.unwrap_or_default();
241

            
242
171
            if rem_pool_member {
243
152
                let count = s.pool_delegators_mut(Self::pool_kind());
244
152
                *count = count.saturating_sub(1);
245
152
            }
246

            
247
171
            if rem_delegator {
248
134
                s.delegators = s.delegators.saturating_sub(1);
249
134
            }
250

            
251
            // storage entry will be deleted if empty
252
171
            if s.delegators == 0 {
253
117
                *summary = None;
254
117
            } else {
255
54
                *summary = Some(s)
256
            }
257
171
        });
258

            
259
171
        Self::set_shares_supply(candidate, Shares(new_shares_supply));
260
171
        Self::set_shares(candidate, delegator, Shares(new_shares));
261
171
        Self::set_total_staked(candidate, Stake(new_total_stake));
262

            
263
171
        Ok(stake)
264
176
    }
265

            
266
330
    fn increase_hold(
267
330
        candidate: &Candidate<T>,
268
330
        delegator: &Delegator<T>,
269
330
        stake: &Stake<T::Balance>,
270
330
    ) -> Result<(), Error<T>> {
271
330
        let hold = Self::hold(candidate, delegator);
272
330
        let hold = hold.0.err_add(&stake.0)?;
273
330
        Self::set_hold(candidate, delegator, Stake(hold));
274
330
        Ok(())
275
330
    }
276

            
277
171
    fn decrease_hold(
278
171
        candidate: &Candidate<T>,
279
171
        delegator: &Delegator<T>,
280
171
        stake: &Stake<T::Balance>,
281
171
    ) -> Result<(), Error<T>> {
282
171
        let hold = Self::hold(candidate, delegator);
283
171
        let hold = hold.0.err_sub(&stake.0)?;
284
171
        Self::set_hold(candidate, delegator, Stake(hold));
285
171
        Ok(())
286
171
    }
287
}
288

            
289
326
pub fn check_candidate_consistency<T: Config>(candidate: &Candidate<T>) -> Result<(), Error<T>> {
290
326
    let total0 = Pools::<T>::get(candidate, &PoolsKey::CandidateTotalStake);
291

            
292
326
    let joining = Joining::<T>::total_staked(candidate).0;
293
326
    let auto = AutoCompounding::<T>::total_staked(candidate).0;
294
326
    let manual = ManualRewards::<T>::total_staked(candidate).0;
295

            
296
326
    let total1 = joining
297
326
        .checked_add(&auto)
298
326
        .ok_or(Error::InconsistentState)?
299
326
        .checked_add(&manual)
300
326
        .ok_or(Error::InconsistentState)?;
301

            
302
326
    ensure!(total0 == total1, Error::InconsistentState);
303

            
304
326
    Ok(())
305
326
}
306

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

            
320
2256
            fn shares_supply(candidate: &Candidate<T>) -> Shares<T::Balance> {
321
2256
                Shares(Pools::<T>::get(candidate, &PoolsKey::$supply))
322
2256
            }
323

            
324
3245
            fn total_staked(candidate: &Candidate<T>) -> Stake<T::Balance> {
325
3245
                Stake(Pools::<T>::get(candidate, &PoolsKey::$total))
326
3245
            }
327

            
328
978
            fn hold(candidate: &Candidate<T>, delegator: &Delegator<T>) -> Stake<T::Balance> {
329
978
                Stake(Pools::<T>::get(
330
978
                    candidate,
331
978
                    &PoolsKey::$hold {
332
978
                        delegator: delegator.clone(),
333
978
                    },
334
978
                ))
335
978
            }
336

            
337
507
            fn set_shares(
338
507
                candidate: &Candidate<T>,
339
507
                delegator: &Delegator<T>,
340
507
                value: Shares<T::Balance>,
341
507
            ) {
342
507
                Pools::<T>::set(
343
507
                    candidate,
344
507
                    &PoolsKey::$shares {
345
507
                        delegator: delegator.clone(),
346
507
                    },
347
507
                    value.0,
348
                )
349
507
            }
350

            
351
507
            fn set_shares_supply(candidate: &Candidate<T>, value: Shares<T::Balance>) {
352
507
                Pools::<T>::set(candidate, &PoolsKey::$supply, value.0)
353
507
            }
354

            
355
530
            fn set_total_staked(candidate: &Candidate<T>, value: Stake<T::Balance>) {
356
530
                Pools::<T>::set(candidate, &PoolsKey::$total, value.0)
357
530
            }
358

            
359
516
            fn set_hold(
360
516
                candidate: &Candidate<T>,
361
516
                delegator: &Delegator<T>,
362
516
                value: Stake<T::Balance>,
363
516
            ) {
364
516
                Pools::<T>::set(
365
516
                    candidate,
366
516
                    &PoolsKey::$hold {
367
516
                        delegator: delegator.clone(),
368
516
                    },
369
516
                    value.0,
370
                )
371
516
            }
372

            
373
588
            fn initial_share_value() -> Stake<T::Balance> {
374
588
                Stake($init)
375
588
            }
376

            
377
987
            fn pool_kind() -> PoolKind {
378
987
                PoolKind::$name
379
987
            }
380
        }
381
    };
382
}
383

            
384
impl_pool!(
385
    Joining,
386
    JoiningShares,
387
    JoiningSharesSupply,
388
    JoiningSharesTotalStaked,
389
    JoiningSharesHeldStake,
390
    if cfg!(test) { 2u32 } else { 1 }.into(),
391
);
392

            
393
impl_pool!(
394
    AutoCompounding,
395
    AutoCompoundingShares,
396
    AutoCompoundingSharesSupply,
397
    AutoCompoundingSharesTotalStaked,
398
    AutoCompoundingSharesHeldStake,
399
    T::InitialAutoCompoundingShareValue::get(),
400
);
401

            
402
impl_pool!(
403
    ManualRewards,
404
    ManualRewardsShares,
405
    ManualRewardsSharesSupply,
406
    ManualRewardsSharesTotalStaked,
407
    ManualRewardsSharesHeldStake,
408
    T::InitialManualClaimShareValue::get(),
409
);
410

            
411
impl_pool!(
412
    Leaving,
413
    LeavingShares,
414
    LeavingSharesSupply,
415
    LeavingSharesTotalStaked,
416
    LeavingSharesHeldStake,
417
    if cfg!(test) { 3u32 } else { 1u32 }.into(),
418
);
419

            
420
impl<T: Config> ManualRewards<T> {
421
    #[allow(dead_code)]
422
16
    pub fn pending_rewards(
423
16
        candidate: &Candidate<T>,
424
16
        delegator: &Delegator<T>,
425
16
    ) -> Result<Stake<T::Balance>, Error<T>> {
426
16
        let shares = Self::shares(candidate, delegator);
427

            
428
16
        if shares.0.is_zero() {
429
5
            return Ok(Stake(0u32.into()));
430
11
        }
431

            
432
11
        let counter = Pools::<T>::get(candidate, &PoolsKey::ManualRewardsCounter);
433
11
        let checkpoint = Pools::<T>::get(
434
11
            candidate,
435
11
            &PoolsKey::ManualRewardsCheckpoint {
436
11
                delegator: delegator.clone(),
437
11
            },
438
        );
439

            
440
        // TODO: Should be safe to wrap around.
441
11
        let diff = counter.err_sub(&checkpoint)?;
442
11
        Ok(Stake(diff.err_mul(&shares.0)?))
443
16
    }
444

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

            
456
13
        let rewards_per_share = rewards
457
13
            .0
458
13
            .checked_div(&supply)
459
13
            .ok_or(Error::<T>::InconsistentState)?;
460
13
        if rewards_per_share.is_zero() {
461
            return Ok(Stake(Zero::zero()));
462
13
        }
463

            
464
13
        let rewards = rewards_per_share.err_mul(&supply)?;
465

            
466
13
        let counter = Pools::<T>::get(candidate, &PoolsKey::ManualRewardsCounter);
467
13
        let counter = counter.err_add(&rewards_per_share)?;
468
13
        Pools::<T>::set(candidate, &PoolsKey::ManualRewardsCounter, counter);
469

            
470
13
        Ok(Stake(rewards))
471
13
    }
472

            
473
58
    pub fn claim_rewards(
474
58
        candidate: &Candidate<T>,
475
58
        delegator: &Delegator<T>,
476
58
    ) -> Result<Stake<T::Balance>, Error<T>> {
477
58
        let shares = Self::shares(candidate, delegator);
478

            
479
58
        let counter = Pools::<T>::get(candidate, &PoolsKey::ManualRewardsCounter);
480
58
        let checkpoint = Pools::<T>::get(
481
58
            candidate,
482
58
            &PoolsKey::ManualRewardsCheckpoint {
483
58
                delegator: delegator.clone(),
484
58
            },
485
        );
486

            
487
        // TODO: Should be safe to wrap around.
488
58
        let diff = counter.err_sub(&checkpoint)?;
489

            
490
58
        if diff.is_zero() {
491
55
            return Ok(Stake(0u32.into()));
492
3
        }
493

            
494
3
        let rewards = diff.err_mul(&shares.0)?;
495

            
496
        // Update checkpoint
497
3
        Pools::<T>::set(
498
3
            candidate,
499
3
            &PoolsKey::ManualRewardsCheckpoint {
500
3
                delegator: delegator.clone(),
501
3
            },
502
3
            counter,
503
        );
504

            
505
3
        Ok(Stake(rewards))
506
58
    }
507
}
508

            
509
101
pub fn accumulate_rewards<T: Config>(
510
101
    candidate: Candidate<T>,
511
101
    rewards: crate::CreditOf<T>,
512
101
) -> DispatchResultWithPostInfo {
513
101
    let rewards_amount = rewards.peek();
514
    // Resolve rewards currency in staking account.
515
101
    T::Currency::resolve(&T::StakingAccount::get(), rewards)
516
101
        .map_err(|_| DispatchError::NoProviders)?;
517

            
518
100
    let mut pending = crate::PendingRewards::<T>::get().unwrap_or_else(|| PendingRewards {
519
        last_distribution: T::RewardsDistributionTimer::now(),
520
        rewards: Default::default(),
521
    });
522

            
523
    // Aggregate rewards
524
100
    let entry: &mut T::Balance = pending.rewards.entry(candidate.clone()).or_default();
525
100
    *entry = entry.err_add(&rewards_amount).map_err(Error::<T>::from)?;
526

            
527
    // Update storage
528
100
    crate::PendingRewards::<T>::put(pending);
529

            
530
    // Read+write PendingRewards & Currency balance
531
100
    Ok(Some(T::DbWeight::get().reads(2) + T::DbWeight::get().writes(2)).into())
532
101
}
533

            
534
1571
pub fn distribute_accumulated_rewards<T: Config>(
535
1571
    pending_rewards: &mut PendingRewards<
536
1571
        <T::RewardsDistributionTimer as Timer>::Instant,
537
1571
        Candidate<T>,
538
1571
        T::Balance,
539
1571
    >,
540
1571
) -> DispatchResultWithPostInfo {
541
1571
    let mut weight = Weight::zero();
542

            
543
1571
    let candidates: Vec<_> = pending_rewards.rewards.keys().cloned().collect();
544

            
545
    // Iterate over the rewards. Only remove the rewards on success. In case of issue this prevents
546
    // rewards to be dropped and allow us to investigate more easily.
547
1571
    for candidate in candidates.into_iter() {
548
35
        let reward = pending_rewards
549
35
            .rewards
550
35
            .get(&candidate)
551
35
            .cloned()
552
35
            .unwrap_or_default();
553

            
554
        // skip empty rewards if any
555
35
        if reward.is_zero() {
556
            pending_rewards.rewards.remove(&candidate);
557
            continue;
558
35
        }
559

            
560
35
        match distribute_rewards::<T>(&candidate, reward) {
561
21
            Ok(post_info) => weight.saturating_accrue(post_info.actual_weight.unwrap_or_default()),
562
14
            Err(mut err) => {
563
14
                err.post_info.actual_weight =
564
14
                    Some(weight.saturating_add(err.post_info.actual_weight.unwrap_or_default()));
565
14
                log::error!(
566
                    "failed to distribute rewards for candidate {candidate:?}: {:?}",
567
                    err.error
568
                );
569
14
                return Err(err);
570
            }
571
        }
572

            
573
21
        pending_rewards.rewards.remove(&candidate);
574
    }
575

            
576
1557
    Ok(Some(weight).into())
577
1571
}
578

            
579
16029
pub fn distribute_accumulated_rewards_on_timer<T: Config>() -> DispatchResultWithPostInfo {
580
    // 2 reads: PendingRewards + RewardsDistributionTimer inner
581
16029
    let mut weight = T::DbWeight::get().reads(2);
582
16029
    let mut pending = match crate::PendingRewards::<T>::get() {
583
15218
        Some(x) => x,
584
        None => {
585
            // 1 write: PendingRewards
586
811
            weight.saturating_accrue(T::DbWeight::get().writes(1));
587

            
588
            // if it doesn't exist yet we initialize it
589
811
            let pending = PendingRewards {
590
811
                last_distribution: T::RewardsDistributionTimer::now(),
591
811
                rewards: Default::default(),
592
811
            };
593
811
            crate::PendingRewards::<T>::put(pending.clone());
594
811
            pending
595
        }
596
    };
597

            
598
    // Distribute only when the timer is elapsed.
599
16029
    if !T::RewardsDistributionTimer::is_elapsed(&pending.last_distribution) {
600
14467
        return Ok(Some(weight).into());
601
1562
    }
602
1562
    pending.last_distribution = T::RewardsDistributionTimer::now();
603

            
604
    // We try to distribute the rewards. In case of issue some of the rewards may already have been
605
    // distributed, so we store the updated pending rewards in all cases.
606
1562
    let result = distribute_accumulated_rewards::<T>(&mut pending);
607
1562
    crate::PendingRewards::<T>::put(pending);
608
1562
    let post_info = match result {
609
1548
        Ok(post) => post,
610
14
        Err(err) => err.post_info,
611
    };
612

            
613
    // 1 write: PendingRewards
614
    // + distribution weight
615
1562
    weight.saturating_accrue(T::DbWeight::get().writes(1));
616
1562
    weight.saturating_accrue(post_info.actual_weight.unwrap_or_default());
617
1562
    Ok(Some(weight).into())
618
16029
}
619

            
620
/// Used in tests to more simply trigger distribution
621
#[cfg(test)]
622
9
pub fn distribute_accumulated_rewards_immediately<T: Config>() -> DispatchResultWithPostInfo {
623
9
    let Some(mut pending) = crate::PendingRewards::<T>::get() else {
624
        return Ok(().into());
625
    };
626

            
627
9
    distribute_accumulated_rewards::<T>(&mut pending)?;
628
9
    crate::PendingRewards::<T>::put(pending);
629

            
630
9
    Ok(().into())
631
9
}
632

            
633
/// Perform rewards distribution for the provided candidate.
634
///
635
/// The pallet considered that it already posses the rewards in its account,
636
/// and it is the responsibility of the caller to transfer or mint the currency
637
/// to the staking pallet account.
638
///
639
/// Rewards are split using `RewardsCollatorCommission` between the candidate
640
/// and all the delegators (including the candidate self-delegation). For each,
641
/// the rewards are then split according to the value of all the ManualRewards
642
/// and AutoCompounding shares.
643
///
644
/// As candidate rewards will give increase the candidate auto compounding
645
/// self-delegation, the delegator rewards are distributed first. ManualRewards
646
/// pool rewards are first distributed by increasing the pool counter, which may
647
/// result in some rounding. As distributing the AutoCompounding pool rewards
648
/// consists of simply increasing `AutoCompoundingSharesTotalStaked`, it is not
649
/// subject to rounding and it can absorb the rounding dust from ManualRewards
650
/// reward distribution.
651
///
652
/// Then it is time to distribute the candidate dedicated rewards. For
653
/// AutoCompounding, it is as if the candidate received the rewards then
654
/// self-delegated (instantly). It is thus implemented by creating new
655
/// AutoCompounding shares. This can lead to some rounding, which will be
656
/// absorbed in the ManualRewards distribution, which simply consist of
657
/// transfering the funds to the candidate account.
658
#[frame_support::transactional]
659
pub fn distribute_rewards<T: Config>(
660
    candidate: &Candidate<T>,
661
    rewards: T::Balance,
662
) -> DispatchResultWithPostInfo {
663
    let candidate_manual_rewards = distribute_rewards_inner::<T>(candidate, rewards)?;
664

            
665
    if !candidate_manual_rewards.is_zero() {
666
        T::Currency::transfer(
667
            &T::StakingAccount::get(),
668
            candidate,
669
            candidate_manual_rewards,
670
            Preservation::Preserve,
671
        )?;
672
    }
673

            
674
    Ok(Some(T::WeightInfo::distribute_rewards()).into())
675
}
676

            
677
35
fn distribute_rewards_inner<T: Config>(
678
35
    candidate: &Candidate<T>,
679
35
    rewards: T::Balance,
680
35
) -> Result<T::Balance, Error<T>> {
681
    // `RewardsCollatorCommission` is a `Perbill` so we're not worried about overflow.
682
35
    let candidate_rewards = T::RewardsCollatorCommission::get() * rewards;
683
35
    let delegators_rewards = rewards.err_sub(&candidate_rewards)?;
684

            
685
35
    let Stake(auto_total_stake) = AutoCompounding::<T>::total_staked(candidate);
686
35
    let Stake(manual_total_stake) = ManualRewards::<T>::total_staked(candidate);
687
35
    let combined_total_stake = auto_total_stake.err_add(&manual_total_stake)?;
688

            
689
35
    let candidate_manual_stake = if manual_total_stake.is_zero() {
690
22
        Zero::zero()
691
    } else {
692
13
        ManualRewards::<T>::computed_stake(candidate, candidate)?.0
693
    };
694

            
695
    // Distribute delegators ManualRewards rewards, it implies some rounding.
696
35
    let delegators_manual_rewards = if manual_total_stake.is_zero() {
697
22
        Zero::zero()
698
    } else {
699
13
        let rewards = delegators_rewards.mul_div(manual_total_stake, combined_total_stake)?;
700
13
        ManualRewards::<T>::increase_rewards(candidate, Stake(rewards))?.0
701
    };
702

            
703
    // Distribute delegators AutoCompounding rewards with dust from ManualRewards.
704
    // If there is no auto compounding stake but auto compounding rewards it
705
    // means it comes from manual rewards rounding. Having non-zero total stake
706
    // with 0 share supply will cause issues, so in this case we distribute this
707
    // dust as candidate manual rewards.
708
35
    let delegators_auto_rewards = delegators_rewards.err_sub(&delegators_manual_rewards)?;
709
35
    let (delegators_auto_rewards, delegators_auto_dust) = if !auto_total_stake.is_zero() {
710
13
        AutoCompounding::<T>::share_stake_among_holders(candidate, Stake(delegators_auto_rewards))?;
711
13
        (delegators_auto_rewards, Zero::zero())
712
    } else {
713
22
        (Zero::zero(), delegators_auto_rewards)
714
    };
715

            
716
    // Distribute candidate AutoCompounding rewards, it implies some rounding.
717
35
    let candidate_auto_rewards = if auto_total_stake.is_zero() {
718
22
        Zero::zero()
719
    } else {
720
        'a: {
721
13
            let candidate_auto_stake =
722
13
                AutoCompounding::<T>::computed_stake(candidate, candidate)?.0;
723
13
            let candidate_combined_stake = candidate_manual_stake.err_add(&candidate_auto_stake)?;
724

            
725
13
            if candidate_combined_stake.is_zero() {
726
1
                break 'a Zero::zero();
727
12
            }
728

            
729
12
            let rewards =
730
12
                candidate_rewards.mul_div(candidate_auto_stake, candidate_combined_stake)?;
731
12
            let new_shares = AutoCompounding::<T>::stake_to_shares(candidate, Stake(rewards))?;
732

            
733
12
            if new_shares.0.is_zero() {
734
8
                break 'a Zero::zero();
735
4
            }
736

            
737
4
            AutoCompounding::<T>::add_shares(candidate, candidate, new_shares)?.0
738
        }
739
    };
740

            
741
    // Distribute candidate ManualRewards rewards with dust from AutoCompounding.
742
    // The amount is returned by the function and will be transfered to the candidate account.
743
35
    let candidate_manual_rewards = candidate_rewards
744
35
        .err_sub(&candidate_auto_rewards)?
745
35
        .err_add(&delegators_auto_dust)?;
746

            
747
35
    let additional_stake = delegators_auto_rewards.err_add(&candidate_auto_rewards)?;
748
35
    Candidates::<T>::add_total_stake(candidate, &Stake(additional_stake))?;
749

            
750
35
    Pallet::<T>::deposit_event(Event::<T>::RewardsDistributed {
751
35
        collator: candidate.clone(),
752
35
        collator_ac_rewards: candidate_auto_rewards,
753
35
        collator_mc_rewards: candidate_manual_rewards,
754
35
        delegators_ac_rewards: delegators_auto_rewards,
755
35
        delegators_mc_rewards: delegators_manual_rewards,
756
35
    });
757

            
758
35
    Ok(candidate_manual_rewards)
759
35
}
760

            
761
const MASK_JOINING: u8 = 1u8;
762
const MASK_AUTO: u8 = 1u8 << 1;
763
const MASK_MANUAL: u8 = 1u8 << 2;
764
const MASK_LEAVING: u8 = 1u8 << 3;
765

            
766
/// Enum of all available pools.
767
/// Must match with the names of the pool structs generated with `impl_pool!`.
768
#[derive(
769
    RuntimeDebug,
770
    PartialEq,
771
    Eq,
772
    Encode,
773
    Decode,
774
    DecodeWithMemTracking,
775
    Copy,
776
    Clone,
777
    TypeInfo,
778
    Serialize,
779
    Deserialize,
780
)]
781
pub enum PoolKind {
782
    Joining,
783
    AutoCompounding,
784
    ManualRewards,
785
    Leaving,
786
}
787

            
788
/// Restricted list of pools that represent active delegation. Those can be targetted by joining
789
/// requests.
790
#[derive(
791
    RuntimeDebug,
792
    PartialEq,
793
    Eq,
794
    Encode,
795
    Decode,
796
    DecodeWithMemTracking,
797
    Copy,
798
    Clone,
799
    TypeInfo,
800
    Serialize,
801
    Deserialize,
802
)]
803
pub enum ActivePoolKind {
804
    AutoCompounding,
805
    ManualRewards,
806
}
807

            
808
impl From<ActivePoolKind> for PoolKind {
809
6
    fn from(value: ActivePoolKind) -> Self {
810
6
        match value {
811
3
            ActivePoolKind::AutoCompounding => PoolKind::AutoCompounding,
812
3
            ActivePoolKind::ManualRewards => PoolKind::ManualRewards,
813
        }
814
6
    }
815
}
816

            
817
impl PoolKind {
818
6713
    fn to_bitmask(self) -> u8 {
819
6713
        match self {
820
3849
            Self::Joining => MASK_JOINING,
821
1825
            Self::AutoCompounding => MASK_AUTO,
822
314
            Self::ManualRewards => MASK_MANUAL,
823
725
            Self::Leaving => MASK_LEAVING,
824
        }
825
6713
    }
826
}
827

            
828
/// Keeps track of which pools of some candidate a delegator is into.
829
/// This is used in storage to have a quick way to fetch all the delegations of
830
/// a delegator, and then know exactly which storage entries to look at to get
831
/// more detailed info.
832
#[derive(
833
    RuntimeDebug,
834
    Default,
835
    PartialEq,
836
    Eq,
837
    Encode,
838
    Decode,
839
    Copy,
840
    Clone,
841
    TypeInfo,
842
    Serialize,
843
    Deserialize,
844
    MaxEncodedLen,
845
)]
846
pub struct DelegatorCandidateSummary(pub(crate) u8);
847

            
848
impl DelegatorCandidateSummary {
849
18
    pub fn new() -> Self {
850
18
        Self(0)
851
18
    }
852

            
853
    fn bit(&self, mask: u8) -> bool {
854
        self.0 & mask != 0
855
    }
856

            
857
6795
    fn set_bit(&mut self, mask: u8, value: bool) {
858
6795
        if value {
859
4818
            self.0 |= mask
860
        } else {
861
1977
            self.0 &= !mask
862
        }
863
6795
    }
864

            
865
6860
    pub fn is_empty(&self) -> bool {
866
6860
        self.0 == 0
867
6860
    }
868

            
869
    pub fn joining(&self) -> bool {
870
        self.bit(MASK_JOINING)
871
    }
872

            
873
    pub fn auto(&self) -> bool {
874
        self.bit(MASK_AUTO)
875
    }
876

            
877
    pub fn manual(&self) -> bool {
878
        self.bit(MASK_MANUAL)
879
    }
880

            
881
    pub fn leaving(&self) -> bool {
882
        self.bit(MASK_LEAVING)
883
    }
884

            
885
    pub fn pool(&self, pool: PoolKind) -> bool {
886
        self.bit(pool.to_bitmask())
887
    }
888

            
889
6691
    pub fn set_pool(&mut self, pool: PoolKind, value: bool) {
890
6691
        self.set_bit(pool.to_bitmask(), value)
891
6691
    }
892

            
893
29
    pub fn with_bit(mut self, mask: u8, value: bool) -> Self {
894
29
        self.set_bit(mask, value);
895
29
        self
896
29
    }
897

            
898
3
    pub fn with_joining(self, value: bool) -> Self {
899
3
        self.with_bit(MASK_JOINING, value)
900
3
    }
901

            
902
1
    pub fn with_auto(self, value: bool) -> Self {
903
1
        self.with_bit(MASK_AUTO, value)
904
1
    }
905

            
906
1
    pub fn with_manual(self, value: bool) -> Self {
907
1
        self.with_bit(MASK_MANUAL, value)
908
1
    }
909

            
910
2
    pub fn with_leaving(self, value: bool) -> Self {
911
2
        self.with_bit(MASK_LEAVING, value)
912
2
    }
913

            
914
22
    pub fn with_pool(self, pool: PoolKind, value: bool) -> Self {
915
22
        self.with_bit(pool.to_bitmask(), value)
916
22
    }
917
}
918

            
919
/// Keeps track of stats that are useful for dApps and block explorers which can
920
/// be tricky or expensive to gather otherwise.
921
#[derive(
922
    RuntimeDebug,
923
    Default,
924
    PartialEq,
925
    Eq,
926
    Encode,
927
    Decode,
928
    Copy,
929
    Clone,
930
    TypeInfo,
931
    Serialize,
932
    Deserialize,
933
    MaxEncodedLen,
934
)]
935
pub struct CandidateSummary {
936
    /// Amount of delegators in any pool without duplicates.
937
    pub delegators: u32,
938
    /// Amount of joining delegators. A single delegator joining multiple times
939
    /// only count once.
940
    pub joining_delegators: u32,
941
    /// Amount of delegators in the auto compounding pool.
942
    pub auto_compounding_delegators: u32,
943
    /// Amount of delegators in the manual rewards pool.
944
    pub manual_rewards_delegators: u32,
945
    /// Amount of leaving delegators. A single delegator leaving multiple times
946
    //// only count once.
947
    pub leaving_delegators: u32,
948
}
949

            
950
impl CandidateSummary {
951
6305
    pub fn pool_delegators_mut(&mut self, pool: PoolKind) -> &mut u32 {
952
6305
        match pool {
953
3610
            PoolKind::Joining => &mut self.joining_delegators,
954
1817
            PoolKind::AutoCompounding => &mut self.auto_compounding_delegators,
955
309
            PoolKind::ManualRewards => &mut self.manual_rewards_delegators,
956
569
            PoolKind::Leaving => &mut self.leaving_delegators,
957
        }
958
6305
    }
959

            
960
18
    pub fn with_pool(mut self, pool: PoolKind, count: u32) -> Self {
961
18
        let pool = self.pool_delegators_mut(pool);
962
18
        *pool = count;
963
18
        self
964
18
    }
965
}
966

            
967
#[derive(RuntimeDebug, PartialEq, Eq, Encode, Decode, Clone, TypeInfo, Serialize, Deserialize)]
968
pub struct PendingRewards<Instant, Candidate: Ord, Balance> {
969
    pub last_distribution: Instant,
970
    pub rewards: BTreeMap<Candidate, Balance>,
971
}