From b5500310206c37304744d5e0b76bb09096e61ee6 Mon Sep 17 00:00:00 2001 From: Ankan Date: Sun, 31 Mar 2024 19:34:23 +0200 Subject: [PATCH] rename all delegatee to agent --- .../frame/delegated-staking/src/impls.rs | 75 +++--- substrate/frame/delegated-staking/src/lib.rs | 139 ++++++----- substrate/frame/delegated-staking/src/mock.rs | 23 +- .../frame/delegated-staking/src/tests.rs | 222 ++++++++++-------- .../frame/delegated-staking/src/types.rs | 102 ++++---- substrate/primitives/staking/src/lib.rs | 64 +++++ 6 files changed, 340 insertions(+), 285 deletions(-) diff --git a/substrate/frame/delegated-staking/src/impls.rs b/substrate/frame/delegated-staking/src/impls.rs index 7be0866f8ded..72884718dfde 100644 --- a/substrate/frame/delegated-staking/src/impls.rs +++ b/substrate/frame/delegated-staking/src/impls.rs @@ -22,10 +22,7 @@ use super::*; use sp_staking::{DelegatedStakeInterface, OnStakingUpdate}; -/// StakingInterface implementation with delegation support. -/// -/// Only supports Nominators via Delegated Bonds. It is possible for a nominator to migrate and -/// become a `delegatee`. +/// Wrapper `StakingInterface` implementation for `Agents`. impl StakingInterface for Pallet { type Balance = BalanceOf; type AccountId = T::AccountId; @@ -90,10 +87,10 @@ impl StakingInterface for Pallet { ) -> DispatchResult { // ensure who is not already staked ensure!(T::CoreStaking::status(who).is_err(), Error::::AlreadyStaking); - let delegatee = Delegatee::::from(who)?; + let agent = Agent::::from(who)?; - ensure!(delegatee.available_to_bond() >= value, Error::::NotEnoughFunds); - ensure!(delegatee.ledger.payee == *payee, Error::::InvalidRewardDestination); + ensure!(agent.available_to_bond() >= value, Error::::NotEnoughFunds); + ensure!(agent.ledger.payee == *payee, Error::::InvalidRewardDestination); T::CoreStaking::virtual_bond(who, value, payee) } @@ -116,8 +113,8 @@ impl StakingInterface for Pallet { } fn unbond(stash: &Self::AccountId, value: Self::Balance) -> DispatchResult { - let delegatee = Delegatee::::from(stash)?; - ensure!(delegatee.bonded_stake() >= value, Error::::NotEnoughFunds); + let agent = Agent::::from(stash)?; + ensure!(agent.bonded_stake() >= value, Error::::NotEnoughFunds); T::CoreStaking::unbond(stash, value) } @@ -128,13 +125,13 @@ impl StakingInterface for Pallet { /// Withdraw unbonding funds until current era. /// - /// Funds are moved to unclaimed_withdrawals register of the `DelegateeLedger`. + /// Funds are moved to unclaimed_withdrawals register of the `AgentLedger`. fn withdraw_unbonded( - delegatee_acc: Self::AccountId, + agent_acc: Self::AccountId, num_slashing_spans: u32, ) -> Result { - Pallet::::withdraw_unbonded(&delegatee_acc, num_slashing_spans) - .map(|delegatee| delegatee.ledger.total_delegated.is_zero()) + Pallet::::withdraw_unbonded(&agent_acc, num_slashing_spans) + .map(|agent| agent.ledger.total_delegated.is_zero()) } fn desired_validator_count() -> u32 { @@ -191,10 +188,10 @@ impl StakingInterface for Pallet { } impl DelegatedStakeInterface for Pallet { - /// Effective balance of the delegatee account. - fn delegatee_balance(who: &Self::AccountId) -> Self::Balance { - Delegatee::::from(who) - .map(|delegatee| delegatee.ledger.effective_balance()) + /// Effective balance of the `Agent` account. + fn agent_balance(who: &Self::AccountId) -> Self::Balance { + Agent::::from(who) + .map(|agent| agent.ledger.effective_balance()) .unwrap_or_default() } @@ -202,71 +199,63 @@ impl DelegatedStakeInterface for Pallet { Delegation::::get(delegator).map(|d| d.amount).unwrap_or_default() } - /// Delegate funds to `Delegatee`. + /// Delegate funds to an `Agent`. fn delegate( who: &Self::AccountId, - delegatee: &Self::AccountId, + agent: &Self::AccountId, reward_account: &Self::AccountId, amount: Self::Balance, ) -> DispatchResult { Pallet::::register_agent( - RawOrigin::Signed(delegatee.clone()).into(), + RawOrigin::Signed(agent.clone()).into(), reward_account.clone(), )?; - // Delegate the funds from who to the delegatee account. - Pallet::::delegate_to_agent( - RawOrigin::Signed(who.clone()).into(), - delegatee.clone(), - amount, - ) + // Delegate the funds from who to the `Agent` account. + Pallet::::delegate_to_agent(RawOrigin::Signed(who.clone()).into(), agent.clone(), amount) } - /// Add more delegation to the delegatee account. + /// Add more delegation to the `Agent` account. fn delegate_extra( who: &Self::AccountId, - delegatee: &Self::AccountId, + agent: &Self::AccountId, amount: Self::Balance, ) -> DispatchResult { - Pallet::::delegate_to_agent( - RawOrigin::Signed(who.clone()).into(), - delegatee.clone(), - amount, - ) + Pallet::::delegate_to_agent(RawOrigin::Signed(who.clone()).into(), agent.clone(), amount) } - /// Withdraw delegation of `delegator` to `delegatee`. + /// Withdraw delegation of `delegator` to `Agent`. /// - /// If there are funds in `delegatee` account that can be withdrawn, then those funds would be + /// If there are funds in `Agent` account that can be withdrawn, then those funds would be /// unlocked/released in the delegator's account. fn withdraw_delegation( delegator: &Self::AccountId, - delegatee: &Self::AccountId, + agent: &Self::AccountId, amount: Self::Balance, ) -> DispatchResult { // fixme(ank4n): Can this not require slashing spans? Pallet::::release_delegation( - RawOrigin::Signed(delegatee.clone()).into(), + RawOrigin::Signed(agent.clone()).into(), delegator.clone(), amount, 0, ) } - /// Returns true if the `delegatee` have any slash pending to be applied. - fn has_pending_slash(delegatee: &Self::AccountId) -> bool { - Delegatee::::from(delegatee) + /// Returns true if the `Agent` have any slash pending to be applied. + fn has_pending_slash(agent: &Self::AccountId) -> bool { + Agent::::from(agent) .map(|d| !d.ledger.pending_slash.is_zero()) .unwrap_or(false) } fn delegator_slash( - delegatee: &Self::AccountId, + agent: &Self::AccountId, delegator: &Self::AccountId, value: Self::Balance, maybe_reporter: Option, ) -> sp_runtime::DispatchResult { - Pallet::::do_slash(delegatee.clone(), delegator.clone(), value, maybe_reporter) + Pallet::::do_slash(agent.clone(), delegator.clone(), value, maybe_reporter) } } @@ -278,7 +267,7 @@ impl OnStakingUpdate> for Pallet { slashed_total: BalanceOf, ) { >::mutate(who, |maybe_register| match maybe_register { - // if delegatee, register the slashed amount as pending slash. + // if existing agent, register the slashed amount as pending slash. Some(register) => register.pending_slash.saturating_accrue(slashed_total), None => { // nothing to do diff --git a/substrate/frame/delegated-staking/src/lib.rs b/substrate/frame/delegated-staking/src/lib.rs index e831c0f95400..2de5ae44b85b 100644 --- a/substrate/frame/delegated-staking/src/lib.rs +++ b/substrate/frame/delegated-staking/src/lib.rs @@ -30,8 +30,8 @@ //! behalf for staking these delegated funds. Also, sometimes referred as `Delegatee`. //! - **Delegator**: An account who delegates their funds to an `agent` and authorises them to use //! it for staking. -//! - **DelegateeLedger**: A data structure that holds important information about the `agent` such -//! as total delegations they have received, any slashes posted to them, etc. +//! - **AgentLedger**: A data structure that holds important information about the `agent` such as +//! total delegations they have received, any slashes posted to them, etc. //! - **Delegation**: A data structure that stores the amount of funds delegated to an `agent` by a //! `delegator`. //! @@ -79,7 +79,7 @@ //! nominators are slashed at the same time. This is expensive and needs to be bounded operation. //! //! This pallet implements a lazy slashing mechanism. Any slashes to the `agent` are posted in its -//! `DelegateeLedger` as a pending slash. Since the actual amount is held in the multiple +//! `AgentLedger` as a pending slash. Since the actual amount is held in the multiple //! `delegator` accounts, this pallet has no way to know how to apply slash. It is the `agent`'s //! responsibility to apply slashes for each delegator, one at a time. Staking pallet ensures the //! pending slash never exceeds staked amount and would freeze further withdraws until all pending @@ -258,11 +258,11 @@ pub mod pallet { /// Map of `Agent` to their `Ledger`. #[pallet::storage] pub(crate) type Agents = - CountedStorageMap<_, Twox64Concat, T::AccountId, DelegateeLedger, OptionQuery>; + CountedStorageMap<_, Twox64Concat, T::AccountId, AgentLedger, OptionQuery>; - // This pallet is not currently written with the intention of exposing any calls. But the - // functions defined in the following impl block should act as a good reference for how the - // exposed calls would look like when exposed. + /// This pallet is not currently written with the intention of exposing any calls. But the + /// functions defined in the following impl block should act as a good reference for how the + /// exposed calls would look like when exposed. impl Pallet { /// Register an account to become a stake `Agent`. Sometimes also called a `Delegatee`. /// @@ -301,7 +301,7 @@ pub mod pallet { /// /// The origin needs to /// - be a `Nominator` with `CoreStaking`, - /// - not already a `Delegatee`, + /// - not already an `Agent`, /// - have enough funds to transfer existential deposit to a delegator account created for /// the migration. /// @@ -367,7 +367,7 @@ pub mod pallet { ensure!(!Self::is_delegator(&delegator), Error::::NotAllowed); ensure!(Self::not_direct_staker(&delegator), Error::::AlreadyStaking); - // ensure delegatee is sane. + // ensure agent is sane. ensure!(Self::is_agent(&agent), Error::::NotAgent); // and has enough delegated balance to migrate. @@ -433,12 +433,9 @@ pub mod pallet { } impl Pallet { - /// Derive a (keyless) pot account from the given delegatee account and account type. - pub(crate) fn sub_account( - account_type: AccountType, - delegatee_account: T::AccountId, - ) -> T::AccountId { - T::PalletId::get().into_sub_account_truncating((account_type, delegatee_account.clone())) + /// Derive a (keyless) pot account from the given agent account and account type. + pub(crate) fn sub_account(account_type: AccountType, agent: T::AccountId) -> T::AccountId { + T::PalletId::get().into_sub_account_truncating((account_type, agent.clone())) } /// Balance of a delegator that is delegated. @@ -446,12 +443,12 @@ impl Pallet { T::Currency::balance_on_hold(&HoldReason::Delegating.into(), who) } - /// Returns true if who is registered as a `Delegatee`. + /// Returns true if who is registered as an `Agent`. fn is_agent(who: &T::AccountId) -> bool { >::contains_key(who) } - /// Returns true if who is delegating to a `Delegatee` account. + /// Returns true if who is delegating to an `Agent` account. fn is_delegator(who: &T::AccountId) -> bool { >::contains_key(who) } @@ -469,10 +466,11 @@ impl Pallet { } fn do_register_agent(who: &T::AccountId, reward_account: &T::AccountId) { - DelegateeLedger::::new(reward_account).save(who); + AgentLedger::::new(reward_account).save(who); - // Delegatee is a virtual account. Make this account exist. - // TODO: Someday if we expose these calls in a runtime, we should take a deposit for + // Agent does not hold balance of its own but this pallet will provide for this to exist. + // This is expected to be a keyless account and not created by any user directly so safe. + // TODO: Someday if we allow anyone to be an agent, we should take a deposit for // being a delegator. frame_system::Pallet::::inc_providers(who); } @@ -508,29 +506,29 @@ impl Pallet { Self::do_delegate(&proxy_delegator, who, stake.total) } - fn do_bond(delegatee_acc: &T::AccountId, amount: BalanceOf) -> DispatchResult { - let delegatee = Delegatee::::from(delegatee_acc)?; + fn do_bond(agent_acc: &T::AccountId, amount: BalanceOf) -> DispatchResult { + let agent = Agent::::from(agent_acc)?; - let available_to_bond = delegatee.available_to_bond(); + let available_to_bond = agent.available_to_bond(); defensive_assert!(amount == available_to_bond, "not expected value to bond"); - if delegatee.is_bonded() { - T::CoreStaking::bond_extra(&delegatee.key, amount) + if agent.is_bonded() { + T::CoreStaking::bond_extra(&agent.key, amount) } else { - T::CoreStaking::virtual_bond(&delegatee.key, amount, delegatee.reward_account()) + T::CoreStaking::virtual_bond(&agent.key, amount, agent.reward_account()) } } fn do_delegate( delegator: &T::AccountId, - delegatee: &T::AccountId, + agent: &T::AccountId, amount: BalanceOf, ) -> DispatchResult { - let mut ledger = DelegateeLedger::::get(delegatee).ok_or(Error::::NotAgent)?; + let mut ledger = AgentLedger::::get(agent).ok_or(Error::::NotAgent)?; let new_delegation_amount = if let Some(existing_delegation) = Delegation::::get(delegator) { - ensure!(&existing_delegation.delegatee == delegatee, Error::::InvalidDelegation); + ensure!(&existing_delegation.agent == agent, Error::::InvalidDelegation); existing_delegation .amount .checked_add(&amount) @@ -539,15 +537,15 @@ impl Pallet { amount }; - Delegation::::from(delegatee, new_delegation_amount).save_or_kill(delegator); + Delegation::::from(agent, new_delegation_amount).save_or_kill(delegator); ledger.total_delegated = ledger.total_delegated.checked_add(&amount).ok_or(ArithmeticError::Overflow)?; - ledger.save(delegatee); + ledger.save(agent); T::Currency::hold(&HoldReason::Delegating.into(), delegator, amount)?; Self::deposit_event(Event::::Delegated { - agent: delegatee.clone(), + agent: agent.clone(), delegator: delegator.clone(), amount, }); @@ -561,24 +559,24 @@ impl Pallet { amount: BalanceOf, num_slashing_spans: u32, ) -> DispatchResult { - let mut delegatee = Delegatee::::from(who)?; + let mut agent = Agent::::from(who)?; let mut delegation = Delegation::::get(delegator).ok_or(Error::::NotDelegator)?; // make sure delegation to be released is sound. - ensure!(&delegation.delegatee == who, Error::::NotAgent); + ensure!(&delegation.agent == who, Error::::NotAgent); ensure!(delegation.amount >= amount, Error::::NotEnoughFunds); // if we do not already have enough funds to be claimed, try withdraw some more. - if delegatee.ledger.unclaimed_withdrawals < amount { - // get the updated delegatee - delegatee = Self::withdraw_unbonded(who, num_slashing_spans)?; + if agent.ledger.unclaimed_withdrawals < amount { + // get the updated agent. + agent = Self::withdraw_unbonded(who, num_slashing_spans)?; } // if we still do not have enough funds to release, abort. - ensure!(delegatee.ledger.unclaimed_withdrawals >= amount, Error::::NotEnoughFunds); + ensure!(agent.ledger.unclaimed_withdrawals >= amount, Error::::NotEnoughFunds); - // claim withdraw from delegatee. - delegatee.remove_unclaimed_withdraw(amount)?.save_or_kill()?; + // claim withdraw from agent. + agent.remove_unclaimed_withdraw(amount)?.save_or_kill()?; // book keep delegation delegation.amount = delegation @@ -608,17 +606,17 @@ impl Pallet { } fn withdraw_unbonded( - delegatee_acc: &T::AccountId, + agent_acc: &T::AccountId, num_slashing_spans: u32, - ) -> Result, DispatchError> { - let delegatee = Delegatee::::from(delegatee_acc)?; - let pre_total = T::CoreStaking::stake(delegatee_acc).defensive()?.total; + ) -> Result, DispatchError> { + let agent = Agent::::from(agent_acc)?; + let pre_total = T::CoreStaking::stake(agent_acc).defensive()?.total; let stash_killed: bool = - T::CoreStaking::withdraw_unbonded(delegatee_acc.clone(), num_slashing_spans) + T::CoreStaking::withdraw_unbonded(agent_acc.clone(), num_slashing_spans) .map_err(|_| Error::::WithdrawFailed)?; - let maybe_post_total = T::CoreStaking::stake(delegatee_acc); + let maybe_post_total = T::CoreStaking::stake(agent_acc); // One of them should be true defensive_assert!( !(stash_killed && maybe_post_total.is_ok()), @@ -630,11 +628,11 @@ impl Pallet { let new_withdrawn = pre_total.checked_sub(&post_total).defensive_ok_or(Error::::BadState)?; - let delegatee = delegatee.add_unclaimed_withdraw(new_withdrawn)?; + let agent = agent.add_unclaimed_withdraw(new_withdrawn)?; - delegatee.clone().save(); + agent.clone().save(); - Ok(delegatee) + Ok(agent) } /// Migrates delegation of `amount` from `source` account to `destination` account. @@ -653,8 +651,7 @@ impl Pallet { ); // update delegations - Delegation::::from(&source_delegation.delegatee, amount) - .save_or_kill(destination_delegator); + Delegation::::from(&source_delegation.agent, amount).save_or_kill(destination_delegator); source_delegation .decrease_delegation(amount) @@ -688,15 +685,15 @@ impl Pallet { } pub fn do_slash( - delegatee_acc: T::AccountId, + agent_acc: T::AccountId, delegator: T::AccountId, amount: BalanceOf, maybe_reporter: Option, ) -> DispatchResult { - let delegatee = Delegatee::::from(&delegatee_acc)?; + let agent = Agent::::from(&agent_acc)?; let delegation = >::get(&delegator).ok_or(Error::::NotDelegator)?; - ensure!(delegation.delegatee == delegatee_acc, Error::::NotAgent); + ensure!(delegation.agent == agent_acc, Error::::NotAgent); ensure!(delegation.amount >= amount, Error::::NotEnoughFunds); let (mut credit, missing) = @@ -706,8 +703,8 @@ impl Pallet { let actual_slash = credit.peek(); - // remove the applied slashed amount from delegatee. - delegatee.remove_slash(actual_slash).save(); + // remove the applied slashed amount from agent. + agent.remove_slash(actual_slash).save(); delegation .decrease_delegation(actual_slash) @@ -726,7 +723,7 @@ impl Pallet { T::OnSlash::on_unbalanced(credit); - Self::deposit_event(Event::::Slashed { agent: delegatee_acc, delegator, amount }); + Self::deposit_event(Event::::Slashed { agent: agent_acc, delegator, amount }); Ok(()) } @@ -734,8 +731,8 @@ impl Pallet { /// Total balance that is available for stake. Includes already staked amount. #[cfg(test)] pub(crate) fn stakeable_balance(who: &T::AccountId) -> BalanceOf { - Delegatee::::from(who) - .map(|delegatee| delegatee.ledger.stakeable_balance()) + Agent::::from(who) + .map(|agent| agent.ledger.stakeable_balance()) .unwrap_or_default() } } @@ -757,21 +754,21 @@ impl Pallet { } fn check_delegates( - ledgers: BTreeMap>, + ledgers: BTreeMap>, ) -> Result<(), sp_runtime::TryRuntimeError> { - for (delegatee, ledger) in ledgers { + for (agent, ledger) in ledgers { ensure!( matches!( - T::CoreStaking::status(&delegatee).expect("delegatee should be bonded"), + T::CoreStaking::status(&agent).expect("agent should be bonded"), StakerStatus::Nominator(_) | StakerStatus::Idle ), - "delegatee should be bonded and not validator" + "agent should be bonded and not validator" ); ensure!( ledger.stakeable_balance() >= - T::CoreStaking::total_stake(&delegatee) - .expect("delegatee should exist as a nominator"), + T::CoreStaking::total_stake(&agent) + .expect("agent should exist as a nominator"), "Cannot stake more than balance" ); } @@ -781,7 +778,7 @@ impl Pallet { fn check_delegators( delegations: BTreeMap>, - ledger: BTreeMap>, + ledger: BTreeMap>, ) -> Result<(), sp_runtime::TryRuntimeError> { let mut delegation_aggregation = BTreeMap::>::new(); for (delegator, delegation) in delegations.iter() { @@ -789,18 +786,18 @@ impl Pallet { T::CoreStaking::status(delegator).is_err(), "delegator should not be directly staked" ); - ensure!(!Self::is_agent(delegator), "delegator cannot be delegatee"); + ensure!(!Self::is_agent(delegator), "delegator cannot be an agent"); delegation_aggregation - .entry(delegation.delegatee.clone()) + .entry(delegation.agent.clone()) .and_modify(|e| *e += delegation.amount) .or_insert(delegation.amount); } - for (delegatee, total_delegated) in delegation_aggregation { - ensure!(!Self::is_delegator(&delegatee), "delegatee cannot be delegator"); + for (agent, total_delegated) in delegation_aggregation { + ensure!(!Self::is_delegator(&agent), "agent cannot be delegator"); - let ledger = ledger.get(&delegatee).expect("ledger should exist"); + let ledger = ledger.get(&agent).expect("ledger should exist"); ensure!( ledger.total_delegated == total_delegated, "ledger total delegated should match delegations" diff --git a/substrate/frame/delegated-staking/src/mock.rs b/substrate/frame/delegated-staking/src/mock.rs index 1a4f079735b7..f98e0c5843bb 100644 --- a/substrate/frame/delegated-staking/src/mock.rs +++ b/substrate/frame/delegated-staking/src/mock.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{self as delegated_staking, types::Delegatee, HoldReason}; +use crate::{self as delegated_staking, types::Agent, HoldReason}; use frame_support::{ assert_ok, derive_impl, pallet_prelude::*, @@ -257,17 +257,14 @@ pub(crate) fn fund(who: &AccountId, amount: Balance) { /// `delegate_amount` is incremented by the amount `increment` starting with `base_delegate_amount` /// from lower index to higher index of delegators. pub(crate) fn setup_delegation_stake( - delegatee: AccountId, + agent: AccountId, reward_acc: AccountId, delegators: Vec, base_delegate_amount: Balance, increment: Balance, ) -> Balance { - fund(&delegatee, 100); - assert_ok!(DelegatedStaking::register_agent( - RawOrigin::Signed(delegatee).into(), - reward_acc - )); + fund(&agent, 100); + assert_ok!(DelegatedStaking::register_agent(RawOrigin::Signed(agent).into(), reward_acc)); let mut delegated_amount: Balance = 0; for (index, delegator) in delegators.iter().enumerate() { let amount_to_delegate = base_delegate_amount + increment * index as Balance; @@ -276,14 +273,14 @@ pub(crate) fn setup_delegation_stake( fund(delegator, amount_to_delegate + ExistentialDeposit::get()); assert_ok!(DelegatedStaking::delegate_to_agent( RawOrigin::Signed(*delegator).into(), - delegatee, + agent, amount_to_delegate )); } // sanity checks - assert_eq!(DelegatedStaking::stakeable_balance(&delegatee), delegated_amount); - assert_eq!(Delegatee::::from(&delegatee).unwrap().available_to_bond(), 0); + assert_eq!(DelegatedStaking::stakeable_balance(&agent), delegated_amount); + assert_eq!(Agent::::from(&agent).unwrap().available_to_bond(), 0); delegated_amount } @@ -294,11 +291,11 @@ pub(crate) fn start_era(era: sp_staking::EraIndex) { pub(crate) fn eq_stake(who: AccountId, total: Balance, active: Balance) -> bool { Staking::stake(&who).unwrap() == Stake { total, active } && - get_delegatee(&who).ledger.stakeable_balance() == total + get_agent(&who).ledger.stakeable_balance() == total } -pub(crate) fn get_delegatee(delegatee: &AccountId) -> Delegatee { - Delegatee::::from(delegatee).expect("delegate should exist") +pub(crate) fn get_agent(agent: &AccountId) -> Agent { + Agent::::from(agent).expect("delegate should exist") } #[allow(unused)] diff --git a/substrate/frame/delegated-staking/src/tests.rs b/substrate/frame/delegated-staking/src/tests.rs index 9b9dd92bc227..715436153081 100644 --- a/substrate/frame/delegated-staking/src/tests.rs +++ b/substrate/frame/delegated-staking/src/tests.rs @@ -23,16 +23,16 @@ use frame_support::{assert_noop, assert_ok, traits::fungible::InspectHold}; use pallet_staking::Error as StakingError; #[test] -fn create_a_delegatee_with_first_delegator() { +fn create_a_agent_with_first_delegator() { ExtBuilder::default().build_and_execute(|| { - let delegatee: AccountId = 200; + let agent: AccountId = 200; let reward_account: AccountId = 201; let delegator: AccountId = 202; // set intention to accept delegation. - fund(&delegatee, 1000); + fund(&agent, 1000); assert_ok!(DelegatedStaking::register_agent( - RawOrigin::Signed(delegatee).into(), + RawOrigin::Signed(agent).into(), reward_account )); @@ -40,27 +40,27 @@ fn create_a_delegatee_with_first_delegator() { fund(&delegator, 1000); assert_ok!(DelegatedStaking::delegate_to_agent( RawOrigin::Signed(delegator).into(), - delegatee, + agent, 100 )); // verify - assert!(DelegatedStaking::is_agent(&delegatee)); - assert_eq!(DelegatedStaking::stakeable_balance(&delegatee), 100); + assert!(DelegatedStaking::is_agent(&agent)); + assert_eq!(DelegatedStaking::stakeable_balance(&agent), 100); assert_eq!(Balances::balance_on_hold(&HoldReason::Delegating.into(), &delegator), 100); }); } #[test] -fn cannot_become_delegatee() { +fn cannot_become_agent() { ExtBuilder::default().build_and_execute(|| { - // cannot set reward account same as delegatee account + // cannot set reward account same as agent account assert_noop!( DelegatedStaking::register_agent(RawOrigin::Signed(100).into(), 100), Error::::InvalidRewardDestination ); - // an existing validator cannot become delegatee + // an existing validator cannot become agent assert_noop!( DelegatedStaking::register_agent( RawOrigin::Signed(mock::GENESIS_VALIDATOR).into(), @@ -69,7 +69,7 @@ fn cannot_become_delegatee() { Error::::AlreadyStaking ); - // an existing nominator cannot become delegatee + // an existing nominator cannot become agent assert_noop!( DelegatedStaking::register_agent( RawOrigin::Signed(mock::GENESIS_NOMINATOR_ONE).into(), @@ -90,17 +90,17 @@ fn cannot_become_delegatee() { #[test] fn create_multiple_delegators() { ExtBuilder::default().build_and_execute(|| { - let delegatee: AccountId = 200; + let agent: AccountId = 200; let reward_account: AccountId = 201; - // stakeable balance is 0 for non delegatee - fund(&delegatee, 1000); - assert!(!DelegatedStaking::is_agent(&delegatee)); - assert_eq!(DelegatedStaking::stakeable_balance(&delegatee), 0); + // stakeable balance is 0 for non agent + fund(&agent, 1000); + assert!(!DelegatedStaking::is_agent(&agent)); + assert_eq!(DelegatedStaking::stakeable_balance(&agent), 0); // set intention to accept delegation. assert_ok!(DelegatedStaking::register_agent( - RawOrigin::Signed(delegatee).into(), + RawOrigin::Signed(agent).into(), reward_account )); @@ -109,65 +109,61 @@ fn create_multiple_delegators() { fund(&i, 100 + ExistentialDeposit::get()); assert_ok!(DelegatedStaking::delegate_to_agent( RawOrigin::Signed(i).into(), - delegatee, + agent, 100 )); - // Balance of 100 held on delegator account for delegating to the delegatee. + // Balance of 100 held on delegator account for delegating to the agent. assert_eq!(Balances::balance_on_hold(&HoldReason::Delegating.into(), &i), 100); } // verify - assert!(DelegatedStaking::is_agent(&delegatee)); - assert_eq!(DelegatedStaking::stakeable_balance(&delegatee), 100 * 100); + assert!(DelegatedStaking::is_agent(&agent)); + assert_eq!(DelegatedStaking::stakeable_balance(&agent), 100 * 100); }); } #[test] -fn delegatee_restrictions() { +fn agent_restrictions() { // Similar to creating a nomination pool ExtBuilder::default().build_and_execute(|| { - let delegatee_one = 200; + let agent_one = 200; let delegator_one = 210; - fund(&delegatee_one, 100); + fund(&agent_one, 100); assert_ok!(DelegatedStaking::register_agent( - RawOrigin::Signed(delegatee_one).into(), - delegatee_one + 1 + RawOrigin::Signed(agent_one).into(), + agent_one + 1 )); fund(&delegator_one, 200); assert_ok!(DelegatedStaking::delegate_to_agent( RawOrigin::Signed(delegator_one).into(), - delegatee_one, + agent_one, 100 )); - let delegatee_two = 300; + let agent_two = 300; let delegator_two = 310; - fund(&delegatee_two, 100); + fund(&agent_two, 100); assert_ok!(DelegatedStaking::register_agent( - RawOrigin::Signed(delegatee_two).into(), - delegatee_two + 1 + RawOrigin::Signed(agent_two).into(), + agent_two + 1 )); fund(&delegator_two, 200); assert_ok!(DelegatedStaking::delegate_to_agent( RawOrigin::Signed(delegator_two).into(), - delegatee_two, + agent_two, 100 )); - // delegatee one tries to delegate to delegatee 2 + // agent one tries to delegate to agent 2 assert_noop!( - DelegatedStaking::delegate_to_agent( - RawOrigin::Signed(delegatee_one).into(), - delegatee_two, - 10 - ), + DelegatedStaking::delegate_to_agent(RawOrigin::Signed(agent_one).into(), agent_two, 10), Error::::InvalidDelegation ); - // delegatee one tries to delegate to a delegator + // agent one tries to delegate to a delegator assert_noop!( DelegatedStaking::delegate_to_agent( - RawOrigin::Signed(delegatee_one).into(), + RawOrigin::Signed(agent_one).into(), delegator_one, 10 ), @@ -175,19 +171,19 @@ fn delegatee_restrictions() { ); assert_noop!( DelegatedStaking::delegate_to_agent( - RawOrigin::Signed(delegatee_one).into(), + RawOrigin::Signed(agent_one).into(), delegator_two, 10 ), Error::::InvalidDelegation ); - // delegator one tries to delegate to delegatee 2 as well (it already delegates to delegatee + // delegator one tries to delegate to agent 2 as well (it already delegates to agent // 1) assert_noop!( DelegatedStaking::delegate_to_agent( RawOrigin::Signed(delegator_one).into(), - delegatee_two, + agent_two, 10 ), Error::::InvalidDelegation @@ -211,17 +207,17 @@ mod staking_integration { #[test] fn bond() { ExtBuilder::default().build_and_execute(|| { - let delegatee: AccountId = 99; + let agent: AccountId = 99; let reward_acc: AccountId = 100; - assert_eq!(Staking::status(&delegatee), Err(StakingError::::NotStash.into())); + assert_eq!(Staking::status(&agent), Err(StakingError::::NotStash.into())); - // set intention to become a delegatee - fund(&delegatee, 100); + // set intention to become an agent + fund(&agent, 100); assert_ok!(DelegatedStaking::register_agent( - RawOrigin::Signed(delegatee).into(), + RawOrigin::Signed(agent).into(), reward_acc )); - assert_eq!(DelegatedStaking::stakeable_balance(&delegatee), 0); + assert_eq!(DelegatedStaking::stakeable_balance(&agent), 0); let mut delegated_balance: Balance = 0; @@ -230,7 +226,7 @@ mod staking_integration { fund(&delegator, 200); assert_ok!(DelegatedStaking::delegate_to_agent( RawOrigin::Signed(delegator).into(), - delegatee, + agent, 100 )); delegated_balance += 100; @@ -239,16 +235,13 @@ mod staking_integration { 100 ); - let delegatee_obj = get_delegatee(&delegatee); - assert_eq!(delegatee_obj.ledger.stakeable_balance(), delegated_balance); - assert_eq!(delegatee_obj.available_to_bond(), 0); - assert_eq!(delegatee_obj.bonded_stake(), delegated_balance); + let agent_obj = get_agent(&agent); + assert_eq!(agent_obj.ledger.stakeable_balance(), delegated_balance); + assert_eq!(agent_obj.available_to_bond(), 0); + assert_eq!(agent_obj.bonded_stake(), delegated_balance); } - assert_eq!( - Staking::stake(&delegatee).unwrap(), - Stake { total: 50 * 100, active: 50 * 100 } - ) + assert_eq!(Staking::stake(&agent).unwrap(), Stake { total: 50 * 100, active: 50 * 100 }) }); } @@ -257,89 +250,109 @@ mod staking_integration { ExtBuilder::default().build_and_execute(|| { // initial era start_era(1); - let delegatee: AccountId = 200; + let agent: AccountId = 200; let reward_acc: AccountId = 201; let delegators: Vec = (301..=350).collect(); let total_staked = - setup_delegation_stake(delegatee, reward_acc, delegators.clone(), 10, 10); + setup_delegation_stake(agent, reward_acc, delegators.clone(), 10, 10); // lets go to a new era start_era(2); - assert!(eq_stake(delegatee, total_staked, total_staked)); + assert!(eq_stake(agent, total_staked, total_staked)); // Withdrawing without unbonding would fail. assert_noop!( - DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 301, 50, 0), + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 301, 50, 0), Error::::NotEnoughFunds ); - // assert_noop!(DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 200, 50, - // 0), Error::::NotAllowed); active and total stake remains same - assert!(eq_stake(delegatee, total_staked, total_staked)); + // assert_noop!(DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), + // 200, 50, 0), Error::::NotAllowed); active and total stake remains same + assert!(eq_stake(agent, total_staked, total_staked)); // 305 wants to unbond 50 in era 2, withdrawable in era 5. - assert_ok!(DelegatedStaking::unbond(&delegatee, 50)); + assert_ok!(DelegatedStaking::unbond(&agent, 50)); // 310 wants to unbond 100 in era 3, withdrawable in era 6. start_era(3); - assert_ok!(DelegatedStaking::unbond(&delegatee, 100)); + assert_ok!(DelegatedStaking::unbond(&agent, 100)); // 320 wants to unbond 200 in era 4, withdrawable in era 7. start_era(4); - assert_ok!(DelegatedStaking::unbond(&delegatee, 200)); + assert_ok!(DelegatedStaking::unbond(&agent, 200)); // active stake is now reduced.. let expected_active = total_staked - (50 + 100 + 200); - assert!(eq_stake(delegatee, total_staked, expected_active)); + assert!(eq_stake(agent, total_staked, expected_active)); // nothing to withdraw at era 4 assert_noop!( - DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 305, 50, 0), + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 305, 50, 0), Error::::NotEnoughFunds ); - assert!(eq_stake(delegatee, total_staked, expected_active)); - assert_eq!(get_delegatee(&delegatee).available_to_bond(), 0); + assert!(eq_stake(agent, total_staked, expected_active)); + assert_eq!(get_agent(&agent).available_to_bond(), 0); // full amount is still delegated - assert_eq!(get_delegatee(&delegatee).ledger.effective_balance(), total_staked); + assert_eq!(get_agent(&agent).ledger.effective_balance(), total_staked); start_era(5); // at era 5, 50 tokens are withdrawable, cannot withdraw more. assert_noop!( - DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 305, 51, 0), + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 305, 51, 0), Error::::NotEnoughFunds ); // less is possible - assert_ok!(DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 305, 30, 0)); - assert_ok!(DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 305, 20, 0)); + assert_ok!(DelegatedStaking::release_delegation( + RawOrigin::Signed(agent).into(), + 305, + 30, + 0 + )); + assert_ok!(DelegatedStaking::release_delegation( + RawOrigin::Signed(agent).into(), + 305, + 20, + 0 + )); // Lets go to future era where everything is unbonded. Withdrawable amount: 100 + 200 start_era(7); // 305 has no more amount delegated so it cannot withdraw. assert_noop!( - DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 305, 5, 0), + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 305, 5, 0), Error::::NotDelegator ); // 309 is an active delegator but has total delegation of 90, so it cannot withdraw more // than that. assert_noop!( - DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 309, 91, 0), + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 309, 91, 0), Error::::NotEnoughFunds ); // 310 cannot withdraw more than delegated funds. assert_noop!( - DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 310, 101, 0), + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 310, 101, 0), Error::::NotEnoughFunds ); // but can withdraw all its delegation amount. - assert_ok!(DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 310, 100, 0)); + assert_ok!(DelegatedStaking::release_delegation( + RawOrigin::Signed(agent).into(), + 310, + 100, + 0 + )); // 320 can withdraw all its delegation amount. - assert_ok!(DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 320, 200, 0)); + assert_ok!(DelegatedStaking::release_delegation( + RawOrigin::Signed(agent).into(), + 320, + 200, + 0 + )); // cannot withdraw anything more.. assert_noop!( - DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 301, 1, 0), + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 301, 1, 0), Error::::NotEnoughFunds ); assert_noop!( - DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 350, 1, 0), + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 350, 1, 0), Error::::NotEnoughFunds ); }); @@ -348,12 +361,12 @@ mod staking_integration { #[test] fn withdraw_happens_with_unbonded_balance_first() { ExtBuilder::default().build_and_execute(|| { - let delegatee = 200; - setup_delegation_stake(delegatee, 201, (300..350).collect(), 100, 0); + let agent = 200; + setup_delegation_stake(agent, 201, (300..350).collect(), 100, 0); // verify withdraw not possible yet assert_noop!( - DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 300, 100, 0), + DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 300, 100, 0), Error::::NotEnoughFunds ); @@ -363,15 +376,15 @@ mod staking_integration { // withdrawn and test its claimed from there first. // fund(&300, 1000); - // assert_ok!(DelegatedStaking::delegate_to_agent(RawOrigin::Signed(300.into()), delegate, - // 100)); + // assert_ok!(DelegatedStaking::delegate_to_agent(RawOrigin::Signed(300.into()), + // delegate, 100)); // // // verify unbonded balance - // assert_eq!(get_delegatee(&delegatee).available_to_bond(), 100); + // assert_eq!(get_agent(&agent).available_to_bond(), 100); // // // withdraw works now without unbonding - // assert_ok!(DelegatedStaking::release_delegation(RawOrigin::Signed(delegatee).into(), 300, 100, - // 0)); assert_eq!(get_delegatee(&delegatee).available_to_bond(), 0); + // assert_ok!(DelegatedStaking::release_delegation(RawOrigin::Signed(agent).into(), 300, + // 100, 0)); assert_eq!(get_agent(&agent).available_to_bond(), 0); }); } @@ -382,7 +395,7 @@ mod staking_integration { fund(&200, 1000); let balance_200 = Balances::free_balance(200); - // `delegatee` account cannot be reward destination + // `Agent` account cannot be reward destination assert_noop!( DelegatedStaking::register_agent(RawOrigin::Signed(200).into(), 200), Error::::InvalidRewardDestination @@ -392,7 +405,11 @@ mod staking_integration { assert_ok!(DelegatedStaking::register_agent(RawOrigin::Signed(200).into(), 201)); // add some delegations to it fund(&300, 1000); - assert_ok!(DelegatedStaking::delegate_to_agent(RawOrigin::Signed(300).into(), 200, 100)); + assert_ok!(DelegatedStaking::delegate_to_agent( + RawOrigin::Signed(300).into(), + 200, + 100 + )); // if delegate calls Staking pallet directly with a different reward destination, it // fails. @@ -409,8 +426,8 @@ mod staking_integration { // amount is staked correctly assert!(eq_stake(200, 100, 100)); - assert_eq!(get_delegatee(&200).available_to_bond(), 0); - assert_eq!(get_delegatee(&200).ledger.effective_balance(), 100); + assert_eq!(get_agent(&200).available_to_bond(), 0); + assert_eq!(get_agent(&200).ledger.effective_balance(), 100); // free balance of delegate is untouched assert_eq!(Balances::free_balance(200), balance_200); @@ -418,7 +435,7 @@ mod staking_integration { } #[test] - fn delegatee_restrictions() { + fn agent_restrictions() { ExtBuilder::default().build_and_execute(|| { setup_delegation_stake(200, 201, (202..203).collect(), 100, 0); @@ -441,10 +458,7 @@ mod staking_integration { Error::::AlreadyStaking ); assert_noop!( - DelegatedStaking::register_agent( - RawOrigin::Signed(GENESIS_VALIDATOR).into(), - 201 - ), + DelegatedStaking::register_agent(RawOrigin::Signed(GENESIS_VALIDATOR).into(), 201), Error::::AlreadyStaking ); }); @@ -498,8 +512,8 @@ mod staking_integration { 5000 - staked_amount - ExistentialDeposit::get() ); assert_eq!(DelegatedStaking::stake(&200).unwrap(), init_stake); - assert_eq!(get_delegatee(&200).ledger.effective_balance(), 4000); - assert_eq!(get_delegatee(&200).available_to_bond(), 0); + assert_eq!(get_agent(&200).ledger.effective_balance(), 4000); + assert_eq!(get_agent(&200).available_to_bond(), 0); // now lets migrate the delegators let delegator_share = staked_amount / 4; @@ -525,8 +539,8 @@ mod staking_integration { // delegate stake is unchanged. assert_eq!(DelegatedStaking::stake(&200).unwrap(), init_stake); - assert_eq!(get_delegatee(&200).ledger.effective_balance(), 4000); - assert_eq!(get_delegatee(&200).available_to_bond(), 0); + assert_eq!(get_agent(&200).ledger.effective_balance(), 4000); + assert_eq!(get_agent(&200).available_to_bond(), 0); } // cannot use migrate delegator anymore diff --git a/substrate/frame/delegated-staking/src/types.rs b/substrate/frame/delegated-staking/src/types.rs index c15ed9f71385..70965374305c 100644 --- a/substrate/frame/delegated-staking/src/types.rs +++ b/substrate/frame/delegated-staking/src/types.rs @@ -24,9 +24,9 @@ use frame_support::traits::DefensiveSaturating; /// The type of pot account being created. #[derive(Encode, Decode)] pub(crate) enum AccountType { - /// A proxy delegator account created for a nominator who migrated to a `delegatee` account. + /// A proxy delegator account created for a nominator who migrated to an `Agent` account. /// - /// Funds for unmigrated `delegator` accounts of the `delegatee` are kept here. + /// Funds for unmigrated `delegator` accounts of the `Agent` are kept here. ProxyDelegator, } @@ -35,7 +35,7 @@ pub(crate) enum AccountType { #[scale_info(skip_type_params(T))] pub struct Delegation { /// The target of delegation. - pub delegatee: T::AccountId, + pub agent: T::AccountId, /// The amount delegated. pub amount: BalanceOf, } @@ -47,19 +47,19 @@ impl Delegation { } /// Create and return a new delegation instance. - pub(crate) fn from(delegatee: &T::AccountId, amount: BalanceOf) -> Self { - Delegation { delegatee: delegatee.clone(), amount } + pub(crate) fn from(agent: &T::AccountId, amount: BalanceOf) -> Self { + Delegation { agent: agent.clone(), amount } } /// Ensure the delegator is either a new delegator or they are adding more delegation to the - /// existing delegatee. + /// existing agent. /// - /// Delegators are prevented from delegating to multiple delegatees at the same time. - pub(crate) fn can_delegate(delegator: &T::AccountId, delegatee: &T::AccountId) -> bool { + /// Delegators are prevented from delegating to multiple agents at the same time. + pub(crate) fn can_delegate(delegator: &T::AccountId, agent: &T::AccountId) -> bool { Delegation::::get(delegator) - .map(|delegation| delegation.delegatee == delegatee.clone()) + .map(|delegation| delegation.agent == agent.clone()) .unwrap_or( - // all good if its a new delegator except it should not be an existing delegatee. + // all good if it is a new delegator except it should not be an existing agent. !>::contains_key(delegator), ) } @@ -67,14 +67,14 @@ impl Delegation { /// Checked decrease of delegation amount. Consumes self and returns a new copy. pub(crate) fn decrease_delegation(self, amount: BalanceOf) -> Option { let updated_delegation = self.amount.checked_sub(&amount)?; - Some(Delegation::from(&self.delegatee, updated_delegation)) + Some(Delegation::from(&self.agent, updated_delegation)) } /// Checked increase of delegation amount. Consumes self and returns a new copy. #[allow(unused)] pub(crate) fn increase_delegation(self, amount: BalanceOf) -> Option { let updated_delegation = self.amount.checked_add(&amount)?; - Some(Delegation::from(&self.delegatee, updated_delegation)) + Some(Delegation::from(&self.agent, updated_delegation)) } /// Save self to storage. If the delegation amount is zero, remove the delegation. @@ -89,36 +89,36 @@ impl Delegation { } } -/// Ledger of all delegations to a `Delegatee`. +/// Ledger of all delegations to an `Agent`. /// -/// This keeps track of the active balance of the `delegatee` that is made up from the funds that -/// are currently delegated to this `delegatee`. It also tracks the pending slashes yet to be +/// This keeps track of the active balance of the `Agent` that is made up from the funds that +/// are currently delegated to this `Agent`. It also tracks the pending slashes yet to be /// applied among other things. #[derive(Default, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] #[scale_info(skip_type_params(T))] -pub struct DelegateeLedger { +pub struct AgentLedger { /// Where the reward should be paid out. pub payee: T::AccountId, - /// Sum of all delegated funds to this `delegatee`. + /// Sum of all delegated funds to this `Agent`. #[codec(compact)] pub total_delegated: BalanceOf, /// Funds that are withdrawn from core staking but not released to delegator/s. It is a subset /// of `total_delegated` and can never be greater than it. /// - /// We need this register to ensure that the `delegatee` does not bond funds from delegated + /// We need this register to ensure that the `Agent` does not bond funds from delegated /// funds that are withdrawn and should be claimed by delegators. // FIXME(ank4n): Check/test about rebond: where delegator rebond what is unlocking. #[codec(compact)] pub unclaimed_withdrawals: BalanceOf, - /// Slashes that are not yet applied. This affects the effective balance of the `delegatee`. + /// Slashes that are not yet applied. This affects the effective balance of the `Agent`. #[codec(compact)] pub pending_slash: BalanceOf, } -impl DelegateeLedger { - /// Create a new instance of `DelegateeLedger`. +impl AgentLedger { + /// Create a new instance of `AgentLedger`. pub(crate) fn new(reward_destination: &T::AccountId) -> Self { - DelegateeLedger { + AgentLedger { payee: reward_destination.clone(), total_delegated: Zero::zero(), unclaimed_withdrawals: Zero::zero(), @@ -126,7 +126,7 @@ impl DelegateeLedger { } } - /// Get `DelegateeLedger` from storage. + /// Get `AgentLedger` from storage. pub(crate) fn get(key: &T::AccountId) -> Option { >::get(key) } @@ -136,9 +136,9 @@ impl DelegateeLedger { >::insert(key, self) } - /// Effective total balance of the `delegatee`. + /// Effective total balance of the `Agent`. /// - /// This takes into account any slashes reported to `Delegatee` but unapplied. + /// This takes into account any slashes reported to `Agent` but unapplied. pub(crate) fn effective_balance(&self) -> BalanceOf { defensive_assert!( self.total_delegated >= self.pending_slash, @@ -149,26 +149,26 @@ impl DelegateeLedger { self.total_delegated.saturating_sub(self.pending_slash) } - /// Delegatee balance that can be staked/bonded in [`T::CoreStaking`]. + /// Agent balance that can be staked/bonded in [`T::CoreStaking`]. pub(crate) fn stakeable_balance(&self) -> BalanceOf { self.effective_balance().saturating_sub(self.unclaimed_withdrawals) } } -/// Wrapper around `DelegateeLedger` to provide additional functionality. +/// Wrapper around `AgentLedger` to provide some helper functions to mutate the ledger. #[derive(Clone)] -pub struct Delegatee { +pub struct Agent { /// storage key pub key: T::AccountId, /// storage value - pub ledger: DelegateeLedger, + pub ledger: AgentLedger, } -impl Delegatee { - /// Get `Delegatee` from storage if it exists or return an error. - pub(crate) fn from(delegatee: &T::AccountId) -> Result, DispatchError> { - let ledger = DelegateeLedger::::get(delegatee).ok_or(Error::::NotAgent)?; - Ok(Delegatee { key: delegatee.clone(), ledger }) +impl Agent { + /// Get `Agent` from storage if it exists or return an error. + pub(crate) fn from(agent: &T::AccountId) -> Result, DispatchError> { + let ledger = AgentLedger::::get(agent).ok_or(Error::::NotAgent)?; + Ok(Agent { key: agent.clone(), ledger }) } /// Remove funds that are withdrawn from [Config::CoreStaking] but not claimed by a delegator. @@ -190,8 +190,8 @@ impl Delegatee { .checked_sub(&amount) .defensive_ok_or(ArithmeticError::Overflow)?; - Ok(Delegatee { - ledger: DelegateeLedger { + Ok(Agent { + ledger: AgentLedger { total_delegated: new_total_delegated, unclaimed_withdrawals: new_unclaimed_withdrawals, ..self.ledger @@ -211,11 +211,8 @@ impl Delegatee { .checked_add(&amount) .defensive_ok_or(ArithmeticError::Overflow)?; - Ok(Delegatee { - ledger: DelegateeLedger { - unclaimed_withdrawals: new_unclaimed_withdrawals, - ..self.ledger - }, + Ok(Agent { + ledger: AgentLedger { unclaimed_withdrawals: new_unclaimed_withdrawals, ..self.ledger }, ..self }) } @@ -230,34 +227,31 @@ impl Delegatee { defensive_assert!( stakeable >= bonded_stake, - "cannot be bonded with more than delegatee balance" + "cannot be bonded with more than total amount delegated to agent" ); stakeable.saturating_sub(bonded_stake) } - /// Remove slashes from the `DelegateeLedger`. + /// Remove slashes from the `AgentLedger`. pub(crate) fn remove_slash(self, amount: BalanceOf) -> Self { let pending_slash = self.ledger.pending_slash.defensive_saturating_sub(amount); let total_delegated = self.ledger.total_delegated.defensive_saturating_sub(amount); - Delegatee { - ledger: DelegateeLedger { pending_slash, total_delegated, ..self.ledger }, - ..self - } + Agent { ledger: AgentLedger { pending_slash, total_delegated, ..self.ledger }, ..self } } - /// Get the total stake of delegatee bonded in [`Config::CoreStaking`]. + /// Get the total stake of agent bonded in [`Config::CoreStaking`]. pub(crate) fn bonded_stake(&self) -> BalanceOf { T::CoreStaking::total_stake(&self.key).unwrap_or(Zero::zero()) } - /// Returns true if the delegatee is bonded in [`Config::CoreStaking`]. + /// Returns true if the agent is bonded in [`Config::CoreStaking`]. pub(crate) fn is_bonded(&self) -> bool { T::CoreStaking::stake(&self.key).is_ok() } - /// Returns the reward account registered by the delegatee. + /// Returns the reward account registered by the agent. pub(crate) fn reward_account(&self) -> &T::AccountId { &self.ledger.payee } @@ -291,14 +285,14 @@ impl Delegatee { /// Reloads self from storage. #[cfg(test)] #[allow(unused)] - pub(crate) fn refresh(&self) -> Result, DispatchError> { + pub(crate) fn refresh(&self) -> Result, DispatchError> { Self::from(&self.key) } - /// Balance of `Delegatee` that is not bonded. + /// Balance of `Agent` that is not bonded. /// /// This is similar to [Self::available_to_bond] except it also includes `unclaimed_withdrawals` - /// of `Delegatee`. + /// of `Agent`. #[cfg(test)] #[allow(unused)] pub(crate) fn total_unbonded(&self) -> BalanceOf { @@ -308,7 +302,7 @@ impl Delegatee { defensive_assert!( net_balance >= bonded_stake, - "cannot be bonded with more than the delegatee balance" + "cannot be bonded with more than the agent balance" ); net_balance.saturating_sub(bonded_stake) diff --git a/substrate/primitives/staking/src/lib.rs b/substrate/primitives/staking/src/lib.rs index 0e1812e10ab2..13cfbe8e326d 100644 --- a/substrate/primitives/staking/src/lib.rs +++ b/substrate/primitives/staking/src/lib.rs @@ -449,4 +449,68 @@ pub struct PagedExposureMetadata { pub page_count: Page, } +/// Extension of [`StakingInterface`] with delegation functionality. +/// +/// Introduces two new actors: +/// - `Delegator`: An account that delegates funds to a `Agent`. +/// - `Agent`: An account that receives delegated funds from `Delegators`. It can then use these +/// funds to participate in the staking system. It can never use its own funds to stake. +/// +/// The `Agent` is responsible for managing rewards and slashing for all the `Delegators` that +/// have delegated funds to it. +pub trait DelegatedStakeInterface: StakingInterface { + /// Effective balance of the `Agent` account. + /// + /// This takes into account any pending slashes to `Agent`. + fn agent_balance(agent: &Self::AccountId) -> Self::Balance; + + /// Returns the total amount of funds delegated by a `delegator`. + fn delegator_balance(delegator: &Self::AccountId) -> Self::Balance; + + /// Delegate funds to `Agent`. + /// + /// Only used for the initial delegation. Use [`Self::delegate_extra`] to add more delegation. + fn delegate( + delegator: &Self::AccountId, + agent: &Self::AccountId, + reward_account: &Self::AccountId, + amount: Self::Balance, + ) -> DispatchResult; + + /// Add more delegation to the `Agent`. + /// + /// If this is the first delegation, use [`Self::delegate`] instead. + fn delegate_extra( + delegator: &Self::AccountId, + agent: &Self::AccountId, + amount: Self::Balance, + ) -> DispatchResult; + + /// Withdraw or revoke delegation to `Agent`. + /// + /// If there are `Agent` funds upto `amount` available to withdraw, then those funds would + /// be released to the `delegator` + fn withdraw_delegation( + delegator: &Self::AccountId, + agent: &Self::AccountId, + amount: Self::Balance, + ) -> DispatchResult; + + /// Returns true if there are pending slashes posted to the `Agent` account. + /// + /// Slashes to `Agent` account are not immediate and are applied lazily. Since `Agent` + /// has an unbounded number of delegators, immediate slashing is not possible. + fn has_pending_slash(agent: &Self::AccountId) -> bool; + + /// Apply a pending slash to a `Agent` by slashing `value` from `delegator`. + /// + /// If a reporter is provided, the reporter will receive a fraction of the slash as reward. + fn delegator_slash( + agent: &Self::AccountId, + delegator: &Self::AccountId, + value: Self::Balance, + maybe_reporter: Option, + ) -> sp_runtime::DispatchResult; +} + sp_core::generate_feature_enabled_macro!(runtime_benchmarks_enabled, feature = "runtime-benchmarks", $);