Skip to content
This repository was archived by the owner on Jul 4, 2022. It is now read-only.

Commit d047cb3

Browse files
Alex Sedshawntabrizi
andauthored
Cherry-pick the upstream feature "Staking Payout to Any Account" (#137)
* Support Staking Payout to Any Account (#6832) Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
1 parent 27b815f commit d047cb3

File tree

3 files changed

+86
-39
lines changed

3 files changed

+86
-39
lines changed

frame/staking/src/lib.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -334,16 +334,18 @@ pub enum StakerStatus<AccountId> {
334334

335335
/// A destination account for payment.
336336
#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug)]
337-
pub enum RewardDestination {
337+
pub enum RewardDestination<AccountId> {
338338
/// Pay into the stash account, increasing the amount at stake accordingly.
339339
Staked,
340340
/// Pay into the stash account, not increasing the amount at stake.
341341
Stash,
342342
/// Pay into the controller account.
343343
Controller,
344+
/// Pay into a specified account.
345+
Account(AccountId),
344346
}
345347

346-
impl Default for RewardDestination {
348+
impl<AccountId> Default for RewardDestination<AccountId> {
347349
fn default() -> Self {
348350
RewardDestination::Staked
349351
}
@@ -725,7 +727,7 @@ decl_storage! {
725727
=> Option<StakingLedger<T::AccountId, BalanceOf<T>>>;
726728

727729
/// Where the reward payment should be made. Keyed by stash.
728-
pub Payee get(fn payee): map hasher(twox_64_concat) T::AccountId => RewardDestination;
730+
pub Payee get(fn payee): map hasher(twox_64_concat) T::AccountId => RewardDestination<T::AccountId>;
729731

730732
/// The map from (wannabe) validator stash key to the preferences of that validator.
731733
pub Validators get(fn validators):
@@ -993,7 +995,7 @@ decl_module! {
993995
fn bond(origin,
994996
controller: <T::Lookup as StaticLookup>::Source,
995997
#[compact] value: BalanceOf<T>,
996-
payee: RewardDestination
998+
payee: RewardDestination<T::AccountId>,
997999
) {
9981000
let stash = ensure_signed(origin)?;
9991001

@@ -1249,7 +1251,7 @@ decl_module! {
12491251
/// - Writes are limited to the `origin` account key.
12501252
/// # </weight>
12511253
#[weight = SimpleDispatchInfo::FixedNormal(500_000)]
1252-
fn set_payee(origin, payee: RewardDestination) {
1254+
fn set_payee(origin, payee: RewardDestination<T::AccountId>) {
12531255
let controller = ensure_signed(origin)?;
12541256
let ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
12551257
let stash = &ledger.stash;
@@ -1636,6 +1638,9 @@ impl<T: Trait> Module<T> {
16361638
Self::update_ledger(&controller, &l);
16371639
r
16381640
}),
1641+
RewardDestination::Account(dest_account) => {
1642+
Some(T::Currency::deposit_creating(&dest_account, amount))
1643+
}
16391644
}
16401645
}
16411646

frame/staking/src/mock.rs

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ pub struct ExtBuilder {
235235
fair: bool,
236236
num_validators: Option<u32>,
237237
invulnerables: Vec<u64>,
238-
stakers: bool,
238+
has_stakers: bool,
239239
}
240240

241241
impl Default for ExtBuilder {
@@ -250,7 +250,7 @@ impl Default for ExtBuilder {
250250
fair: true,
251251
num_validators: None,
252252
invulnerables: vec![],
253-
stakers: true,
253+
has_stakers: true,
254254
}
255255
}
256256
}
@@ -296,11 +296,8 @@ impl ExtBuilder {
296296
EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit);
297297
SLASH_DEFER_DURATION.with(|v| *v.borrow_mut() = self.slash_defer_duration);
298298
}
299-
300-
// TODO re-evaluate if the following "allow" is still necessary after merging upstream in
301-
#[allow(dead_code)]
302-
pub fn stakers(mut self, has_stakers: bool) -> Self {
303-
self.stakers = has_stakers;
299+
pub fn has_stakers(mut self, has: bool) -> Self {
300+
self.has_stakers = has;
304301
self
305302
}
306303
pub fn build(self) -> sp_io::TestExternalities {
@@ -339,7 +336,7 @@ impl ExtBuilder {
339336
}.assimilate_storage(&mut storage);
340337

341338
let mut stakers = vec![];
342-
if self.stakers {
339+
if self.has_stakers {
343340
let stake_21 = if self.fair { 1000 } else { 2000 };
344341
let stake_31 = if self.validator_pool { balance_factor * 1000 } else { 1 };
345342
let status_41 = if self.validator_pool {
@@ -444,20 +441,36 @@ pub fn assert_ledger_consistent(stash: AccountId) {
444441
assert_eq!(real_total, ledger.total);
445442
}
446443

447-
pub fn bond_validator(acc: u64, val: u64) {
448-
// a = controller
449-
// a + 1 = stash
450-
let _ = Balances::make_free_balance_be(&(acc + 1), val);
451-
assert_ok!(Staking::bond(Origin::signed(acc + 1), acc, val, RewardDestination::Controller));
452-
assert_ok!(Staking::validate(Origin::signed(acc), ValidatorPrefs::default()));
453-
}
454-
455-
pub fn bond_nominator(acc: u64, val: u64, target: Vec<u64>) {
456-
// a = controller
457-
// a + 1 = stash
458-
let _ = Balances::make_free_balance_be(&(acc + 1), val);
459-
assert_ok!(Staking::bond(Origin::signed(acc + 1), acc, val, RewardDestination::Controller));
460-
assert_ok!(Staking::nominate(Origin::signed(acc), target));
444+
pub(crate) fn bond_validator(stash: AccountId, ctrl: AccountId, val: Balance) {
445+
let _ = Balances::make_free_balance_be(&stash, val);
446+
let _ = Balances::make_free_balance_be(&ctrl, val);
447+
assert_ok!(Staking::bond(
448+
Origin::signed(stash),
449+
ctrl,
450+
val,
451+
RewardDestination::Controller,
452+
));
453+
assert_ok!(Staking::validate(
454+
Origin::signed(ctrl),
455+
ValidatorPrefs::default()
456+
));
457+
}
458+
459+
pub(crate) fn bond_nominator(
460+
stash: AccountId,
461+
ctrl: AccountId,
462+
val: Balance,
463+
target: Vec<AccountId>,
464+
) {
465+
let _ = Balances::make_free_balance_be(&stash, val);
466+
let _ = Balances::make_free_balance_be(&ctrl, val);
467+
assert_ok!(Staking::bond(
468+
Origin::signed(stash),
469+
ctrl,
470+
val,
471+
RewardDestination::Controller,
472+
));
473+
assert_ok!(Staking::nominate(Origin::signed(ctrl), target));
461474
}
462475

463476
pub fn advance_session() {

frame/staking/src/tests.rs

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,11 +1733,11 @@ fn phragmen_should_not_overflow_validators() {
17331733
let _ = Staking::chill(Origin::signed(10));
17341734
let _ = Staking::chill(Origin::signed(20));
17351735

1736-
bond_validator(2, u64::max_value());
1737-
bond_validator(4, u64::max_value());
1736+
bond_validator(3, 2, u64::max_value());
1737+
bond_validator(5, 4, u64::max_value());
17381738

1739-
bond_nominator(6, u64::max_value() / 2, vec![3, 5]);
1740-
bond_nominator(8, u64::max_value() / 2, vec![3, 5]);
1739+
bond_nominator(7, 6, u64::max_value() / 2, vec![3, 5]);
1740+
bond_nominator(9, 8, u64::max_value() / 2, vec![3, 5]);
17411741

17421742
start_era(1);
17431743

@@ -1756,11 +1756,11 @@ fn phragmen_should_not_overflow_nominators() {
17561756
let _ = Staking::chill(Origin::signed(10));
17571757
let _ = Staking::chill(Origin::signed(20));
17581758

1759-
bond_validator(2, u64::max_value() / 2);
1760-
bond_validator(4, u64::max_value() / 2);
1759+
bond_validator(3, 2, u64::max_value() / 2);
1760+
bond_validator(5, 4, u64::max_value() / 2);
17611761

1762-
bond_nominator(6, u64::max_value(), vec![3, 5]);
1763-
bond_nominator(8, u64::max_value(), vec![3, 5]);
1762+
bond_nominator(7, 6, u64::max_value(), vec![3, 5]);
1763+
bond_nominator(9, 8, u64::max_value(), vec![3, 5]);
17641764

17651765
start_era(1);
17661766

@@ -1775,11 +1775,11 @@ fn phragmen_should_not_overflow_nominators() {
17751775
#[test]
17761776
fn phragmen_should_not_overflow_ultimate() {
17771777
ExtBuilder::default().nominate(false).build().execute_with(|| {
1778-
bond_validator(2, u64::max_value());
1779-
bond_validator(4, u64::max_value());
1778+
bond_validator(3, 2, u64::max_value());
1779+
bond_validator(5, 4, u64::max_value());
17801780

1781-
bond_nominator(6, u64::max_value(), vec![3, 5]);
1782-
bond_nominator(8, u64::max_value(), vec![3, 5]);
1781+
bond_nominator(7, 6, u64::max_value(), vec![3, 5]);
1782+
bond_nominator(9, 8, u64::max_value(), vec![3, 5]);
17831783

17841784
start_era(1);
17851785

@@ -3043,3 +3043,32 @@ fn assert_migration_is_noop() {
30433043
assert_eq!(era.index, 586);
30443044
assert_eq!(era.start, Some(1585135674000));
30453045
}
3046+
3047+
#[test]
3048+
fn payout_to_any_account_works() {
3049+
ExtBuilder::default().has_stakers(false).build().execute_with(|| {
3050+
let balance = 1000;
3051+
// Create a validator:
3052+
bond_validator(11, 10, balance); // Default(64)
3053+
3054+
// Create a stash/controller pair
3055+
bond_nominator(1234, 1337, 100, vec![11]);
3056+
3057+
// Update payout location
3058+
assert_ok!(Staking::set_payee(Origin::signed(1337), RewardDestination::Account(42)));
3059+
3060+
// Reward Destination account doesn't exist
3061+
assert_eq!(Balances::free_balance(42), 0);
3062+
3063+
mock::start_era(1);
3064+
Staking::reward_by_ids(vec![(11, 1)]);
3065+
// Compute total payout now for whole duration as other parameter won't change
3066+
let total_payout_0 = current_total_payout_for_duration(3 * 1000);
3067+
assert!(total_payout_0 > 100); // Test is meaningful if reward something
3068+
mock::start_era(2);
3069+
assert_ok!(Staking::payout_nominator(Origin::signed(1337), 1, vec![(11, 0)]));
3070+
3071+
// Payment is successful
3072+
assert!(Balances::free_balance(42) > 0);
3073+
})
3074+
}

0 commit comments

Comments
 (0)