From 3b30c3636a8e4831b201e1d95602565351e3d46a Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Tue, 15 Mar 2022 08:51:57 +0000 Subject: [PATCH] use `inner` for nested types in nomination pools (#11030) * Use nested inner type for pool * make tests and benchmarks work * remove feat * all tests work now * fix node-runtime --- bin/node/runtime/src/lib.rs | 2 + .../nomination-pools/benchmarking/Cargo.toml | 2 +- .../nomination-pools/benchmarking/src/lib.rs | 34 +- .../nomination-pools/benchmarking/src/mock.rs | 4 +- frame/nomination-pools/src/lib.rs | 505 +++++----- frame/nomination-pools/src/mock.rs | 32 +- frame/nomination-pools/src/tests.rs | 953 ++++++++---------- 7 files changed, 716 insertions(+), 816 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 230de88a019d3..f148e08fd6526 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -698,6 +698,7 @@ impl pallet_bags_list::Config for Runtime { parameter_types! { pub const PostUnbondPoolsWindow: u32 = 4; + pub const NominationPoolsPalletId: PalletId = PalletId(*b"py/npols"); } use sp_runtime::traits::Convert; @@ -723,6 +724,7 @@ impl pallet_nomination_pools::Config for Runtime { type StakingInterface = pallet_staking::Pallet; type PostUnbondingPoolsWindow = PostUnbondPoolsWindow; type MaxMetadataLen = ConstU32<256>; + type PalletId = NominationPoolsPalletId; } parameter_types! { diff --git a/frame/nomination-pools/benchmarking/Cargo.toml b/frame/nomination-pools/benchmarking/Cargo.toml index f6ead8c9af2ad..700e626e79ae0 100644 --- a/frame/nomination-pools/benchmarking/Cargo.toml +++ b/frame/nomination-pools/benchmarking/Cargo.toml @@ -54,4 +54,4 @@ std = [ "pallet-nomination-pools/std", "sp-runtime/std", "sp-staking/std" -] \ No newline at end of file +] diff --git a/frame/nomination-pools/benchmarking/src/lib.rs b/frame/nomination-pools/benchmarking/src/lib.rs index 03292f1ad09fe..cc3f6b314d8c6 100644 --- a/frame/nomination-pools/benchmarking/src/lib.rs +++ b/frame/nomination-pools/benchmarking/src/lib.rs @@ -11,8 +11,8 @@ use frame_election_provider_support::SortedListProvider; use frame_support::{ensure, traits::Get}; use frame_system::RawOrigin as Origin; use pallet_nomination_pools::{ - BalanceOf, BondedPoolStorage, BondedPools, Delegators, Metadata, MinCreateBond, MinJoinBond, - Pallet as Pools, PoolState, RewardPools, SubPoolsStorage, + BalanceOf, BondedPoolInner, BondedPools, Delegators, Metadata, MinCreateBond, MinJoinBond, + Pallet as Pools, PoolRoles, PoolState, RewardPools, SubPoolsStorage, }; use sp_runtime::traits::{StaticLookup, Zero}; use sp_staking::{EraIndex, StakingInterface}; @@ -67,7 +67,7 @@ fn create_pool_account( .unwrap(); let pool_account = pallet_nomination_pools::BondedPools::::iter() - .find(|(_, bonded_pool)| bonded_pool.depositor == pool_creator) + .find(|(_, bonded_pool)| bonded_pool.roles.depositor == pool_creator) .map(|(pool_account, _)| pool_account) .expect("pool_creator created a pool above"); @@ -189,7 +189,7 @@ impl ListScenario { // Sanity check the delegator was added correctly let delegator = Delegators::::get(&joiner).unwrap(); assert_eq!(delegator.points, amount); - assert_eq!(delegator.pool, self.origin1); + assert_eq!(delegator.bonded_pool_account, self.origin1); self } @@ -475,14 +475,16 @@ frame_benchmarking::benchmarks! { let (pool_account, new_pool) = BondedPools::::iter().next().unwrap(); assert_eq!( new_pool, - BondedPoolStorage { + BondedPoolInner { points: min_create_bond, - depositor: depositor.clone(), - root: depositor.clone(), - nominator: depositor.clone(), - state_toggler: depositor.clone(), state: PoolState::Open, - delegator_counter: 1 + delegator_counter: 1, + roles: PoolRoles { + depositor: depositor.clone(), + root: depositor.clone(), + nominator: depositor.clone(), + state_toggler: depositor.clone(), + }, } ); assert_eq!( @@ -516,14 +518,16 @@ frame_benchmarking::benchmarks! { let (pool_account, new_pool) = BondedPools::::iter().next().unwrap(); assert_eq!( new_pool, - BondedPoolStorage { + BondedPoolInner { points: min_create_bond, - depositor: depositor.clone(), - root: depositor.clone(), - nominator: depositor.clone(), - state_toggler: depositor.clone(), state: PoolState::Open, delegator_counter: 1, + roles: PoolRoles { + depositor: depositor.clone(), + root: depositor.clone(), + nominator: depositor.clone(), + state_toggler: depositor.clone(), + } } ); assert_eq!( diff --git a/frame/nomination-pools/benchmarking/src/mock.rs b/frame/nomination-pools/benchmarking/src/mock.rs index 0e89ed09fe6e1..895b9b672c96d 100644 --- a/frame/nomination-pools/benchmarking/src/mock.rs +++ b/frame/nomination-pools/benchmarking/src/mock.rs @@ -16,7 +16,7 @@ // limitations under the License. use frame_election_provider_support::VoteWeight; -use frame_support::{pallet_prelude::*, parameter_types, traits::ConstU64}; +use frame_support::{pallet_prelude::*, parameter_types, traits::ConstU64, PalletId}; use sp_runtime::traits::{Convert, IdentityLookup}; type AccountId = u64; @@ -141,6 +141,7 @@ impl Convert for U256ToBalance { parameter_types! { pub static PostUnbondingPoolsWindow: u32 = 10; + pub const PoolsPalletId: PalletId = PalletId(*b"py/nopls"); } impl pallet_nomination_pools::Config for Runtime { @@ -152,6 +153,7 @@ impl pallet_nomination_pools::Config for Runtime { type StakingInterface = Staking; type PostUnbondingPoolsWindow = PostUnbondingPoolsWindow; type MaxMetadataLen = ConstU32<256>; + type PalletId = PoolsPalletId; } impl crate::Config for Runtime {} diff --git a/frame/nomination-pools/src/lib.rs b/frame/nomination-pools/src/lib.rs index 73f76bbf25a8c..2ac769b50a506 100644 --- a/frame/nomination-pools/src/lib.rs +++ b/frame/nomination-pools/src/lib.rs @@ -12,7 +12,7 @@ //! ## Key terms //! //! * bonded pool: Tracks the distribution of actively staked funds. See [`BondedPool`] and -//! [`BondedPoolStorage`]. Bonded pools are identified via the pools bonded account. +//! [`BondedPoolInner`]. Bonded pools are identified via the pools bonded account. //! * reward pool: Tracks rewards earned by actively staked funds. See [`RewardPool`] and //! [`RewardPools`]. Reward pools are identified via the pools bonded account. //! * unbonding sub pools: Collection of pools at different phases of the unbonding lifecycle. See @@ -286,8 +286,8 @@ // Invariants // * A `delegator.bonded_pool_account` must always be a valid entry in `RewardPools`, and -// `BondedPoolStorage`. -// * Every entry in `BondedPoolStorage` must have a corresponding entry in `RewardPools` +// `BondedPoolInner`. +// * Every entry in `BondedPoolInner` must have a corresponding entry in `RewardPools` // * If a delegator unbonds, the sub pools should always correctly track slashses such that the // calculated amount when withdrawing unbonded is a lower bound of the pools free balance. // * If the depositor is actively unbonding, the pool is in destroying state. To achieve this, once @@ -311,8 +311,7 @@ use frame_support::{ }; use scale_info::TypeInfo; use sp_core::U256; -use sp_io::hashing::blake2_256; -use sp_runtime::traits::{Bounded, Convert, Saturating, StaticLookup, TrailingZeroInput, Zero}; +use sp_runtime::traits::{AccountIdConversion, Bounded, Convert, Saturating, StaticLookup, Zero}; use sp_staking::{EraIndex, OnStakerSlash, StakingInterface}; use sp_std::{collections::btree_map::BTreeMap, ops::Div, vec::Vec}; @@ -331,8 +330,9 @@ pub use weights::WeightInfo; pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; pub type SubPoolsWithEra = BoundedBTreeMap, TotalUnbondingPools>; -// NOTE: this assumes the balance type u128 or smaller. -type RewardPoints = U256; +// NOTE: this assumes the balance type u128 or smaller. TODO: integrity-check +pub type RewardPoints = U256; +pub type PoolId = u32; const POINTS_TO_BALANCE_INIT_RATIO: u32 = 1; @@ -342,31 +342,14 @@ enum PoolBond { Join, } -/// Identifier for encoding different pool account types. -enum AccountType { - /// The bonded account of the pool. This is functionally both the stash and controller account. - Bonded, - /// The reward account of the pool. - Reward, -} - -impl Encode for AccountType { - fn encode(&self) -> Vec { - match self { - Self::Bonded => b"bond".to_vec(), - Self::Reward => b"rewd".to_vec(), - } - } -} - /// A delegator in a pool. #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, RuntimeDebugNoBound)] #[cfg_attr(feature = "std", derive(Clone, PartialEq))] #[codec(mel_bound(T: Config))] #[scale_info(skip_type_params(T))] pub struct Delegator { - /// The bonded account of the pool. - pub bonded_pool_account: T::AccountId, + /// The identifier of the pool to which `who` belongs. + pub pool_id: PoolId, /// The quantity of points this delegator has in the bonded pool or in a sub pool if /// `Self::unbonding_era` is some. pub points: BalanceOf, @@ -380,7 +363,7 @@ pub struct Delegator { } /// A pool's possible states. -#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, RuntimeDebugNoBound, Clone)] +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, RuntimeDebugNoBound, Clone, Copy)] pub enum PoolState { /// The pool is open to be joined, and is working normally. Open, @@ -393,13 +376,19 @@ pub enum PoolState { Destroying, } -// TODO: call Inner +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Debug, PartialEq, Clone)] +pub struct PoolRoles { + pub depositor: AccountId, + pub root: AccountId, + pub nominator: AccountId, + pub state_toggler: AccountId, +} + /// Pool permissions and state -#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, RuntimeDebugNoBound, PartialEq)] -#[cfg_attr(feature = "std", derive(Clone))] +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, DebugNoBound, PartialEq, Clone)] #[codec(mel_bound(T: Config))] #[scale_info(skip_type_params(T))] -pub struct BondedPoolStorage { +pub struct BondedPoolInner { /// See [`BondedPool::points`]. pub points: BalanceOf, /// See [`BondedPool::state_toggler`]. @@ -407,136 +396,86 @@ pub struct BondedPoolStorage { /// See [`BondedPool::delegator_counter`] pub delegator_counter: u32, /// See [`BondedPool::depositor`]. - pub depositor: T::AccountId, - /// See [`BondedPool::admin`]. - pub root: T::AccountId, - /// See [`BondedPool::nominator`]. - pub nominator: T::AccountId, - /// See [`BondedPool::state_toggler`]. - pub state_toggler: T::AccountId, + pub roles: PoolRoles, } +/// A wrapper for bonded pools, with utility functions. +/// +/// The main purpose of this is to wrap a [`BondedPoolInner`], with the account + id of the pool, +/// for easier access. #[derive(RuntimeDebugNoBound)] #[cfg_attr(feature = "std", derive(Clone, PartialEq))] pub struct BondedPool { - /// Points of the pool. - /// - /// Each delegator has some corresponding the points. The portion of points that belong to a - /// delegator represent the portion of the pools bonded funds belong to the delegator. - points: BalanceOf, - /// State of the pool. - state: PoolState, - /// Count of delegators that belong to this pool. - delegator_counter: u32, - /// Account that puts down a deposit to create the pool. - /// - /// This account acts a delegator, but can only unbond if no other delegators belong to the - /// pool. - depositor: T::AccountId, - /// Can perform the same actions as [`Self::nominator`] and [`Self::state_toggler`]. - /// Additionally, this account can set the `nominator` and `state_toggler` at any time. - root: T::AccountId, - /// Can set the pool's nominations at any time. - nominator: T::AccountId, - /// Can toggle the pools state, including setting the pool as blocked or putting the pool into - /// destruction mode. The state toggle can also "kick" delegators by unbonding them. - state_toggler: T::AccountId, - /// AccountId of the pool. - account: T::AccountId, + /// The identifier of the pool. + id: PoolId, + /// The inner fields. + inner: BondedPoolInner, +} + +impl sp_std::ops::Deref for BondedPool { + type Target = BondedPoolInner; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +// TODO: ask a rust guy if this is a bad thing to do. +impl sp_std::ops::DerefMut for BondedPool { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } } impl BondedPool { - fn new( - depositor: T::AccountId, - root: T::AccountId, - nominator: T::AccountId, - state_toggler: T::AccountId, - ) -> Self { + /// Create a new bonded pool with the given roles and identifier. + fn new(id: PoolId, roles: PoolRoles) -> Self { Self { - account: Self::create_account(AccountType::Bonded, depositor.clone()), - depositor, - root, - nominator, - state_toggler, - state: PoolState::Open, - points: Zero::zero(), - delegator_counter: Zero::zero(), + id, + inner: BondedPoolInner { + roles, + state: PoolState::Open, + points: Zero::zero(), + delegator_counter: Zero::zero(), + }, } } - // TODO: figure out if we should ditch BondedPoolStorage vs BondedPool and instead just have - // BondedPool that doesn't have `account` field. Instead just use deterministic accountId - // generation function. Only downside is this will have some increased computational cost. - /// Get [`Self`] from storage. Returns `None` if no entry for `pool_account` exists. - fn get(pool_account: &T::AccountId) -> Option { - BondedPools::::try_get(pool_account).ok().map(|storage| Self { - points: storage.points, - delegator_counter: storage.delegator_counter, - state_toggler: storage.state_toggler, - depositor: storage.depositor, - root: storage.root, - nominator: storage.nominator, - state: storage.state, - account: pool_account.clone(), - }) + fn get(id: PoolId) -> Option { + BondedPools::::try_get(id).ok().map(|inner| Self { id, inner }) } - /// Consume self and put into storage. - fn put(self) { - BondedPools::::insert( - self.account, - BondedPoolStorage { - points: self.points, - delegator_counter: self.delegator_counter, - depositor: self.depositor, - root: self.root, - nominator: self.nominator, - state_toggler: self.state_toggler, - state: self.state, - }, - ); + /// Get the bonded account id of this pool. + fn bonded_account(&self) -> T::AccountId { + Pallet::::create_bonded_account(self.id) } - /// Consume self and remove from storage. - fn remove(self) { - BondedPools::::remove(self.account); + /// Get the reward account id of this pool. + fn reward_account(&self) -> T::AccountId { + Pallet::::create_reward_account(self.id) } - // TODO: put `BondedPool` and `BondedPoolStorage` into a private module, then you have to think - // about which functions need to be public and which not as well. Then make sure public ones are - // documented. - - fn create_account(account_type: AccountType, depositor: T::AccountId) -> T::AccountId { - // TODO: look into make the prefix transparent by not hashing anything - // TODO: look into a using a configurable module id. - // TODO: consult someone experienced about this to figure out faster. - let entropy = (b"npls", account_type, depositor).using_encoded(blake2_256); - Decode::decode(&mut TrailingZeroInput::new(&entropy)).expect("Infinite length input. qed") + /// Consume self and put into storage. + fn put(self) { + BondedPools::::insert(self.id, BondedPoolInner { ..self.inner }); } - fn reward_account(&self) -> T::AccountId { - // TODO: self.depositor can now change. if you keep this scheme for accounts, you should - // store the reward account in the struct itself. So key it by the bonded account, and the - // reward account is stored in it. OR NEVER allow the depositor to change. - Self::create_account(AccountType::Reward, self.depositor.clone()) + /// Consume self and remove from storage. + fn remove(self) { + BondedPools::::remove(self.id); } /// Get the amount of points to issue for some new funds that will be bonded in the pool. fn points_to_issue(&self, new_funds: BalanceOf) -> BalanceOf { let bonded_balance = - T::StakingInterface::bonded_balance(&self.account).unwrap_or(Zero::zero()); - // TODO: I don't see why these are not functions defined on `BondedPool` rather than - // being a standalone function. + T::StakingInterface::bonded_balance(&self.bonded_account()).unwrap_or(Zero::zero()); Pallet::::points_to_issue(bonded_balance, self.points, new_funds) } /// Get the amount of balance to unbond from the pool based on a delegator's points of the pool. fn balance_to_unbond(&self, delegator_points: BalanceOf) -> BalanceOf { let bonded_balance = - T::StakingInterface::bonded_balance(&self.account).unwrap_or(Zero::zero()); - // TODO: I don't see why these are not functions defined on `BondedPool` rather than - // being a standalone function. + T::StakingInterface::bonded_balance(&self.bonded_account()).unwrap_or(Zero::zero()); Pallet::::balance_to_unbond(bonded_balance, self.points, delegator_points) } @@ -572,26 +511,26 @@ impl BondedPool { /// The pools balance that is not locked. This assumes the staking system is the only fn non_locked_balance(&self) -> BalanceOf { - // TODO: how can this ever be NON-zero? The pool always bonds it entire stash, and rewards - // go elsewhere. - T::Currency::free_balance(&self.account) - .saturating_sub(T::StakingInterface::locked_balance(&self.account).unwrap_or_default()) + let account = self.bonded_account(); + T::Currency::free_balance(&account) + .saturating_sub(T::StakingInterface::locked_balance(&account).unwrap_or_default()) } fn can_nominate(&self, who: &T::AccountId) -> bool { - *who == self.root || *who == self.nominator + *who == self.roles.root || *who == self.roles.nominator } fn can_kick(&self, who: &T::AccountId) -> bool { - *who == self.root || *who == self.state_toggler && self.state == PoolState::Blocked + *who == self.roles.root || + *who == self.roles.state_toggler && self.state == PoolState::Blocked } fn can_toggle_state(&self, who: &T::AccountId) -> bool { - *who == self.root || *who == self.state_toggler && !self.is_destroying() + *who == self.roles.root || *who == self.roles.state_toggler && !self.is_destroying() } fn can_set_metadata(&self, who: &T::AccountId) -> bool { - *who == self.root || *who == self.state_toggler + *who == self.roles.root || *who == self.roles.state_toggler } fn is_destroying(&self) -> bool { @@ -604,7 +543,7 @@ impl BondedPool { ensure!(!self.is_destroying(), Error::::CanNotChangeState); let bonded_balance = - T::StakingInterface::bonded_balance(&self.account).unwrap_or(Zero::zero()); + T::StakingInterface::bonded_balance(&self.bonded_account()).unwrap_or(Zero::zero()); ensure!(!bonded_balance.is_zero(), Error::::OverflowRisk); let points_to_balance_ratio_floor = self @@ -646,7 +585,7 @@ impl BondedPool { target_delegator: &Delegator, ) -> Result<(), DispatchError> { let is_permissioned = caller == target_account; - let is_depositor = *target_account == self.depositor; + let is_depositor = *target_account == self.roles.depositor; match (is_permissioned, is_depositor) { // If the pool is blocked, then an admin with kicking permissions can remove a // delegator. If the pool is being destroyed, anyone can remove a delegator @@ -678,7 +617,7 @@ impl BondedPool { target_delegator: &Delegator, sub_pools: &SubPools, ) -> Result { - if *target_account == self.depositor { + if *target_account == self.roles.depositor { // This is a depositor if !sub_pools.no_era.points.is_zero() { // Unbonded pool has some points, so if they are the last delegator they must be @@ -735,7 +674,7 @@ impl BondedPool { // go bond them. T::Currency::transfer( &who, - &self.account, + &self.bonded_account(), amount, match ty { PoolBond::Create => ExistenceRequirement::AllowDeath, @@ -749,16 +688,16 @@ impl BondedPool { match ty { // TODO: Consider making StakingInterface use reference. PoolBond::Create => T::StakingInterface::bond( - self.account.clone(), + self.bonded_account(), // We make the stash and controller the same for simplicity - self.account.clone(), + self.bonded_account(), amount, self.reward_account(), )?, // The pool should always be created in such a way its in a state to bond extra, but if // the active balance is slashed below the minimum bonded or the account cannot be // found, we exit early. - PoolBond::Join => T::StakingInterface::bond_extra(self.account.clone(), amount)?, + PoolBond::Join => T::StakingInterface::bond_extra(self.bonded_account(), amount)?, } Ok(points_issued) @@ -781,8 +720,6 @@ impl BondedPool { #[codec(mel_bound(T: Config))] #[scale_info(skip_type_params(T))] pub struct RewardPool { - /// The reward destination for the pool. - pub account: T::AccountId, /// The balance of this reward pool after the last claimed payout. pub balance: BalanceOf, /// The total earnings _ever_ of this reward pool after the last claimed payout. I.E. the sum @@ -798,8 +735,9 @@ pub struct RewardPool { impl RewardPool { /// Mutate the reward pool by updating the total earnings and current free balance. - fn update_total_earnings_and_balance(&mut self) { - let current_balance = T::Currency::free_balance(&self.account); + fn update_total_earnings_and_balance(&mut self, id: PoolId) { + // TODO: not happy with this. + let current_balance = T::Currency::free_balance(&Pallet::::create_reward_account(id)); // The earnings since the last time it was updated let new_earnings = current_balance.saturating_sub(self.balance); // The lifetime earnings of the of the reward pool @@ -808,9 +746,9 @@ impl RewardPool { } /// Get a reward pool and update its total earnings and balance - fn get_and_update(bonded_pool_account: &T::AccountId) -> Option { - RewardPools::::get(bonded_pool_account).map(|mut r| { - r.update_total_earnings_and_balance(); + fn get_and_update(id: PoolId) -> Option { + RewardPools::::get(id).map(|mut r| { + r.update_total_earnings_and_balance(id); r }) } @@ -939,6 +877,10 @@ pub mod pallet { /// The nominating balance. type Currency: Currency; + /// The nomination pool's pallet id. + #[pallet::constant] + type PalletId: Get; + /// Infallible method for converting `Currency::Balance` to `U256`. type BalanceToU256: Convert, U256>; @@ -993,29 +935,29 @@ pub mod pallet { /// To get or insert a pool see [`BondedPool::get`] and [`BondedPool::put`] #[pallet::storage] pub type BondedPools = - CountedStorageMap<_, Twox64Concat, T::AccountId, BondedPoolStorage>; + CountedStorageMap<_, Twox64Concat, PoolId, BondedPoolInner>; /// Reward pools. This is where there rewards for each pool accumulate. When a delegators payout /// is claimed, the balance comes out fo the reward pool. Keyed by the bonded pools account. #[pallet::storage] - pub type RewardPools = - CountedStorageMap<_, Twox64Concat, T::AccountId, RewardPool>; + pub type RewardPools = CountedStorageMap<_, Twox64Concat, PoolId, RewardPool>; /// Groups of unbonding pools. Each group of unbonding pools belongs to a bonded pool, /// hence the name sub-pools. Keyed by the bonded pools account. #[pallet::storage] - pub type SubPoolsStorage = - CountedStorageMap<_, Twox64Concat, T::AccountId, SubPools>; + pub type SubPoolsStorage = CountedStorageMap<_, Twox64Concat, PoolId, SubPools>; /// Metadata for the pool. #[pallet::storage] - pub type Metadata = CountedStorageMap< - _, - Twox64Concat, - T::AccountId, - BoundedVec, - ValueQuery, - >; + pub type Metadata = + CountedStorageMap<_, Twox64Concat, PoolId, BoundedVec, ValueQuery>; + + #[pallet::storage] + pub type LastPoolId = StorageValue<_, u32, ValueQuery>; + + #[pallet::storage] + pub type ReversePoolIdLookup = + CountedStorageMap<_, Twox64Concat, T::AccountId, PoolId, OptionQuery>; #[pallet::genesis_config] pub struct GenesisConfig { @@ -1059,13 +1001,13 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(crate) fn deposit_event)] pub enum Event { - Created { pool: T::AccountId, depositor: T::AccountId }, - Joined { delegator: T::AccountId, pool: T::AccountId, bonded: BalanceOf }, - PaidOut { delegator: T::AccountId, pool: T::AccountId, payout: BalanceOf }, - Unbonded { delegator: T::AccountId, pool: T::AccountId, amount: BalanceOf }, - Withdrawn { delegator: T::AccountId, pool: T::AccountId, amount: BalanceOf }, - Destroyed { pool: T::AccountId }, - State { pool: T::AccountId, new_state: PoolState }, + Created { depositor: T::AccountId, pool_id: PoolId }, + Joined { delegator: T::AccountId, pool_id: PoolId, bonded: BalanceOf }, + PaidOut { delegator: T::AccountId, pool_id: PoolId, payout: BalanceOf }, + Unbonded { delegator: T::AccountId, pool_id: PoolId, amount: BalanceOf }, + Withdrawn { delegator: T::AccountId, pool_id: PoolId, amount: BalanceOf }, + Destroyed { pool_id: PoolId }, + State { pool_id: PoolId, new_state: PoolState }, } #[pallet::error] @@ -1094,9 +1036,6 @@ pub mod pallet { MinimumBondNotMet, /// The transaction could not be executed due to overflow risk for the pool. OverflowRisk, - // Likely only an error ever encountered in poorly built tests. - /// A pool with the generated account id already exists. - IdInUse, /// A pool must be in [`PoolState::Destroying`] in order for the depositor to unbond or for /// other delegators to be permissionlessly unbonded. NotDestroying, @@ -1134,24 +1073,19 @@ pub mod pallet { /// * Only a pool with [`PoolState::Open`] can be joined #[pallet::weight(T::WeightInfo::join())] #[frame_support::transactional] - pub fn join( - origin: OriginFor, - amount: BalanceOf, - pool_account: T::AccountId, - ) -> DispatchResult { + pub fn join(origin: OriginFor, amount: BalanceOf, pool_id: PoolId) -> DispatchResult { let who = ensure_signed(origin)?; ensure!(amount >= MinJoinBond::::get(), Error::::MinimumBondNotMet); // If a delegator already exists that means they already belong to a pool ensure!(!Delegators::::contains_key(&who), Error::::AccountBelongsToOtherPool); - let mut bonded_pool = - BondedPool::::get(&pool_account).ok_or(Error::::PoolNotFound)?; + let mut bonded_pool = BondedPool::::get(pool_id).ok_or(Error::::PoolNotFound)?; bonded_pool.ok_to_join()?; // don't actually care about writing the reward pool, we just need its total earnings at // this point in time. - let reward_pool = RewardPool::::get_and_update(&pool_account) + let reward_pool = RewardPool::::get_and_update(pool_id) .defensive_ok_or_else(|| Error::::RewardPoolNotFound)?; let points_issued = bonded_pool.try_bond_delegator(&who, amount, PoolBond::Join)?; @@ -1159,7 +1093,7 @@ pub mod pallet { Delegators::insert( who.clone(), Delegator:: { - bonded_pool_account: pool_account.clone(), + pool_id, points: points_issued, // At best the reward pool has the rewards up through the previous era. If the // delegator joins prior to the snapshot they will benefit from the rewards of @@ -1172,11 +1106,7 @@ pub mod pallet { }, ); bonded_pool.put(); - Self::deposit_event(Event::::Joined { - delegator: who, - pool: pool_account, - bonded: amount, - }); + Self::deposit_event(Event::::Joined { delegator: who, pool_id, bonded: amount }); Ok(()) } @@ -1191,7 +1121,7 @@ pub mod pallet { pub fn claim_payout(origin: OriginFor) -> DispatchResult { let who = ensure_signed(origin)?; let mut delegator = Delegators::::get(&who).ok_or(Error::::DelegatorNotFound)?; - let mut bonded_pool = BondedPool::::get(&delegator.bonded_pool_account) + let mut bonded_pool = BondedPool::::get(delegator.pool_id) .defensive_ok_or_else(|| Error::::PoolNotFound)?; let was_destroying = bonded_pool.is_destroying(); @@ -1199,7 +1129,7 @@ pub mod pallet { if bonded_pool.is_destroying() && !was_destroying { Self::deposit_event(Event::::State { - pool: bonded_pool.account.clone(), + pool_id: delegator.pool_id, new_state: PoolState::Destroying, }); } @@ -1214,7 +1144,6 @@ pub mod pallet { /// /// # Conditions for a permissionless dispatch /// - /// TODO: delegator -> target /// * The pool is blocked and the caller is either the root or state-toggler. This is /// refereed to as a kick. /// * The pool is destroying and the delegator is not the depositor. @@ -1230,13 +1159,16 @@ pub mod pallet { /// Note: If there are too many unlocking chunks to unbond with the pool account, /// [`Self::withdraw_unbonded_pool`] can be called to try and minimize unlocking chunks. #[pallet::weight(T::WeightInfo::unbond_other())] - pub fn unbond_other(origin: OriginFor, target: T::AccountId) -> DispatchResult { + pub fn unbond_other( + origin: OriginFor, + delegator_account: T::AccountId, + ) -> DispatchResult { let caller = ensure_signed(origin)?; let mut delegator = - Delegators::::get(&target).ok_or(Error::::DelegatorNotFound)?; - let mut bonded_pool = BondedPool::::get(&delegator.bonded_pool_account) + Delegators::::get(&delegator_account).ok_or(Error::::DelegatorNotFound)?; + let mut bonded_pool = BondedPool::::get(delegator.pool_id) .defensive_ok_or_else(|| Error::::PoolNotFound)?; - bonded_pool.ok_to_unbond_other_with(&caller, &target, &delegator)?; + bonded_pool.ok_to_unbond_other_with(&caller, &delegator_account, &delegator)?; // alternative: do_reward_payout can report if it changed states. let was_destroying = bonded_pool.is_destroying(); @@ -1244,11 +1176,10 @@ pub mod pallet { // Claim the the payout prior to unbonding. Once the user is unbonding their points // no longer exist in the bonded pool and thus they can no longer claim their payouts. // It is not strictly necessary to claim the rewards, but we do it here for UX. - Self::do_reward_payout(target.clone(), &mut delegator, &mut bonded_pool)?; + Self::do_reward_payout(delegator_account.clone(), &mut delegator, &mut bonded_pool)?; // Note that we lazily create the unbonding pools here if they don't already exist - let sub_pools = - SubPoolsStorage::::get(&delegator.bonded_pool_account).unwrap_or_default(); + let sub_pools = SubPoolsStorage::::get(delegator.pool_id).unwrap_or_default(); let current_era = T::StakingInterface::current_era(); let unbond_era = T::StakingInterface::bonding_duration().saturating_add(current_era); @@ -1260,7 +1191,7 @@ pub mod pallet { // Unbond in the actual underlying pool // TODO: can fail after write: better make it transactional. - T::StakingInterface::unbond(delegator.bonded_pool_account.clone(), balance_to_unbond)?; + T::StakingInterface::unbond(bonded_pool.bonded_account(), balance_to_unbond)?; // Merge any older pools into the general, era agnostic unbond pool. Note that we do // this before inserting to ensure we don't go over the max unbonding pools. @@ -1274,23 +1205,23 @@ pub mod pallet { delegator.unbonding_era = Some(unbond_era); Self::deposit_event(Event::::Unbonded { - delegator: target.clone(), - pool: delegator.bonded_pool_account.clone(), + delegator: delegator_account.clone(), + pool_id: delegator.pool_id, amount: balance_to_unbond, }); if bonded_pool.is_destroying() && !was_destroying { // Persist the pool to storage iff the state was updated Self::deposit_event(Event::::State { - pool: bonded_pool.account.clone(), + pool_id: delegator.pool_id, new_state: PoolState::Destroying, }); } // Now that we know everything has worked write the items to storage. bonded_pool.put(); - SubPoolsStorage::insert(&delegator.bonded_pool_account, sub_pools); - Delegators::insert(target, delegator); + SubPoolsStorage::insert(&delegator.pool_id, sub_pools); + Delegators::insert(delegator_account, delegator); Ok(()) } @@ -1302,15 +1233,15 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::pool_withdraw_unbonded(*num_slashing_spans))] pub fn pool_withdraw_unbonded( origin: OriginFor, - pool_account: T::AccountId, + pool_id: PoolId, num_slashing_spans: u32, ) -> DispatchResult { let _ = ensure_signed(origin)?; - let pool = BondedPool::::get(&pool_account).ok_or(Error::::PoolNotFound)?; + let pool = BondedPool::::get(pool_id).ok_or(Error::::PoolNotFound)?; // For now we only allow a pool to withdraw unbonded if its not destroying. If the pool // is destroying then `withdraw_unbonded_other` can be used. ensure!(pool.state != PoolState::Destroying, Error::::NotDestroying); - T::StakingInterface::withdraw_unbonded(pool_account, num_slashing_spans)?; + T::StakingInterface::withdraw_unbonded(pool.bonded_account(), num_slashing_spans)?; Ok(()) } @@ -1335,26 +1266,31 @@ pub mod pallet { )] pub fn withdraw_unbonded_other( origin: OriginFor, - target: T::AccountId, + delegator_account: T::AccountId, num_slashing_spans: u32, ) -> DispatchResultWithPostInfo { let caller = ensure_signed(origin)?; - let delegator = Delegators::::get(&target).ok_or(Error::::DelegatorNotFound)?; + let delegator = + Delegators::::get(&delegator_account).ok_or(Error::::DelegatorNotFound)?; let unbonding_era = delegator.unbonding_era.ok_or(Error::::NotUnbonding)?; let current_era = T::StakingInterface::current_era(); ensure!(current_era >= unbonding_era, Error::::NotUnbondedYet); - let mut sub_pools = SubPoolsStorage::::get(&delegator.bonded_pool_account) + let mut sub_pools = SubPoolsStorage::::get(delegator.pool_id) .defensive_ok_or_else(|| Error::::SubPoolsNotFound)?; - let bonded_pool = BondedPool::::get(&delegator.bonded_pool_account) + let bonded_pool = BondedPool::::get(delegator.pool_id) .defensive_ok_or_else(|| Error::::PoolNotFound)?; - let should_remove_pool = bonded_pool - .ok_to_withdraw_unbonded_other_with(&caller, &target, &delegator, &sub_pools)?; + let should_remove_pool = bonded_pool.ok_to_withdraw_unbonded_other_with( + &caller, + &delegator_account, + &delegator, + &sub_pools, + )?; // Before calculate the `balance_to_unbond`, with call withdraw unbonded to ensure the // `non_locked_balance` is correct. T::StakingInterface::withdraw_unbonded( - delegator.bonded_pool_account.clone(), + bonded_pool.bonded_account(), num_slashing_spans, )?; @@ -1390,38 +1326,51 @@ pub mod pallet { .min(bonded_pool.non_locked_balance()); T::Currency::transfer( - &delegator.bonded_pool_account, - &target, + &bonded_pool.bonded_account(), + &delegator_account, balance_to_unbond, ExistenceRequirement::AllowDeath, ) .defensive_map_err(|e| e)?; Self::deposit_event(Event::::Withdrawn { - delegator: target.clone(), - pool: delegator.bonded_pool_account.clone(), + delegator: delegator_account.clone(), + pool_id: delegator.pool_id, amount: balance_to_unbond, }); let post_info_weight = if should_remove_pool { - let reward_pool = RewardPools::::take(&delegator.bonded_pool_account) - .defensive_ok_or_else(|| Error::::PoolNotFound)?; - Self::deposit_event(Event::::Destroyed { - pool: delegator.bonded_pool_account.clone(), - }); - SubPoolsStorage::::remove(&delegator.bonded_pool_account); + ReversePoolIdLookup::::remove(bonded_pool.bonded_account()); + RewardPools::::remove(delegator.pool_id); + Self::deposit_event(Event::::Destroyed { pool_id: delegator.pool_id }); + SubPoolsStorage::::remove(delegator.pool_id); // Kill accounts from storage by making their balance go below ED. We assume that // the accounts have no references that would prevent destruction once we get to // this point. - T::Currency::make_free_balance_be(&reward_pool.account, Zero::zero()); - T::Currency::make_free_balance_be(&bonded_pool.account, Zero::zero()); + // TODO: in correct scenario, these two accounts should be zero when we reach there + // anyway. + debug_assert_eq!( + T::Currency::free_balance(&bonded_pool.reward_account()), + Zero::zero() + ); + debug_assert_eq!( + T::Currency::free_balance(&bonded_pool.bonded_account()), + Zero::zero() + ); + debug_assert_eq!( + T::StakingInterface::locked_balance(&bonded_pool.bonded_account()) + .unwrap_or_default(), + Zero::zero() + ); + T::Currency::make_free_balance_be(&bonded_pool.reward_account(), Zero::zero()); + T::Currency::make_free_balance_be(&bonded_pool.bonded_account(), Zero::zero()); bonded_pool.remove(); None } else { bonded_pool.dec_delegators().put(); - SubPoolsStorage::::insert(&delegator.bonded_pool_account, sub_pools); + SubPoolsStorage::::insert(&delegator.pool_id, sub_pools); Some(T::WeightInfo::withdraw_unbonded_other_update(num_slashing_spans)) }; - Delegators::::remove(&target); + Delegators::::remove(&delegator_account); Ok(post_info_weight.into()) } @@ -1463,35 +1412,36 @@ pub mod pallet { ); ensure!(!Delegators::::contains_key(&who), Error::::AccountBelongsToOtherPool); - let mut bonded_pool = BondedPool::::new(who.clone(), root, nominator, state_toggler); - // This shouldn't be possible since we are ensured the delegator is not a depositor and - // the the account ID is generated based on the accountId - ensure!(!BondedPools::::contains_key(&bonded_pool.account), Error::::IdInUse); + let pool_id = LastPoolId::::mutate(|id| { + *id += 1; + *id + }); + let mut bonded_pool = BondedPool::::new( + pool_id, + PoolRoles { root, nominator, state_toggler, depositor: who.clone() }, + ); - let points_issued = bonded_pool.try_bond_delegator(&who, amount, PoolBond::Create)?; + let points = bonded_pool.try_bond_delegator(&who, amount, PoolBond::Create)?; - Self::deposit_event(Event::::Created { - depositor: who.clone(), - pool: bonded_pool.account.clone(), - }); Delegators::::insert( - who, + who.clone(), Delegator:: { - bonded_pool_account: bonded_pool.account.clone(), - points: points_issued, + pool_id, + points, reward_pool_total_earnings: Zero::zero(), unbonding_era: None, }, ); RewardPools::::insert( - bonded_pool.account.clone(), + pool_id, RewardPool:: { balance: Zero::zero(), points: U256::zero(), total_earnings: Zero::zero(), - account: bonded_pool.reward_account(), }, ); + ReversePoolIdLookup::::insert(bonded_pool.bonded_account(), pool_id); + Self::deposit_event(Event::::Created { depositor: who, pool_id }); bonded_pool.put(); Ok(()) @@ -1500,28 +1450,25 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::nominate())] pub fn nominate( origin: OriginFor, - pool_account: T::AccountId, + pool_id: PoolId, validators: Vec<::Source>, ) -> DispatchResult { let who = ensure_signed(origin)?; - let bonded_pool = - BondedPool::::get(&pool_account).ok_or(Error::::PoolNotFound)?; + let bonded_pool = BondedPool::::get(pool_id).ok_or(Error::::PoolNotFound)?; ensure!(bonded_pool.can_nominate(&who), Error::::NotNominator); - T::StakingInterface::nominate(pool_account.clone(), validators)?; + T::StakingInterface::nominate(bonded_pool.bonded_account(), validators)?; Ok(()) } #[pallet::weight(T::WeightInfo::set_state_other())] pub fn set_state_other( origin: OriginFor, - pool_account: T::AccountId, + pool_id: PoolId, state: PoolState, ) -> DispatchResult { let who = ensure_signed(origin)?; - let mut bonded_pool = - BondedPool::::get(&pool_account).ok_or(Error::::PoolNotFound)?; + let mut bonded_pool = BondedPool::::get(pool_id).ok_or(Error::::PoolNotFound)?; ensure!(bonded_pool.state != PoolState::Destroying, Error::::CanNotChangeState); - // TODO: [now] we could check if bonded_pool.ok_to_be_open().is_err(), and if thats // true always set the state to destroying, regardless of the stat the caller passes. // The downside is that this seems like a misleading API @@ -1536,7 +1483,7 @@ pub mod pallet { } Self::deposit_event(Event::::State { - pool: bonded_pool.account.clone(), + pool_id, new_state: bonded_pool.state.clone(), }); @@ -1548,20 +1495,20 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::set_metadata())] pub fn set_metadata( origin: OriginFor, - pool_account: T::AccountId, + pool_id: PoolId, metadata: Vec, ) -> DispatchResult { let who = ensure_signed(origin)?; let metadata: BoundedVec<_, _> = metadata.try_into().map_err(|_| Error::::MetadataExceedsMaxLen)?; ensure!( - BondedPool::::get(&pool_account) + BondedPool::::get(pool_id) .ok_or(Error::::PoolNotFound)? .can_set_metadata(&who), Error::::DoesNotHavePermission ); - Metadata::::mutate(&pool_account, |pool_meta| *pool_meta = metadata); + Metadata::::mutate(pool_id, |pool_meta| *pool_meta = metadata); Ok(()) } @@ -1591,6 +1538,18 @@ pub mod pallet { } impl Pallet { + /// Create the main, bonded account of a pool with the given id. + fn create_bonded_account(id: PoolId) -> T::AccountId { + T::PalletId::get().into_sub_account((1u8, id)) + } + + /// Create the reward account of a pool with the given id. + fn create_reward_account(id: PoolId) -> T::AccountId { + // TODO: integrity check for what is the reasonable max number of pools based on this. + // 4 + 8 + 4 + 1 + T::PalletId::get().into_sub_account((2u8, id)) + } + /// Calculate the number of points to issue from a pool as `(current_points / current_balance) * /// new_funds` except for some zero edge cases; see logic and tests for details. fn points_to_issue( @@ -1641,6 +1600,7 @@ impl Pallet { reward_pool: &mut RewardPool, delegator: &mut Delegator, ) -> Result, DispatchError> { + debug_assert_eq!(delegator.pool_id, bonded_pool.id); let u256 = |x| T::BalanceToU256::convert(x); let balance = |x| T::U256ToBalance::convert(x); // If the delegator is unbonding they cannot claim rewards. Note that when the delegator @@ -1648,7 +1608,7 @@ impl Pallet { ensure!(delegator.unbonding_era.is_none(), Error::::AlreadyUnbonding); let last_total_earnings = reward_pool.total_earnings; - reward_pool.update_total_earnings_and_balance(); + reward_pool.update_total_earnings_and_balance(bonded_pool.id); // Notice there is an edge case where total_earnings have not increased and this is zero let new_earnings = u256(reward_pool.total_earnings.saturating_sub(last_total_earnings)); @@ -1708,11 +1668,12 @@ impl Pallet { /// This will persist updates for the reward pool to storage. But it will *not* persist updates /// to the `delegator` or `bonded_pool` to storage, that is the responsibility of the caller. fn do_reward_payout( - delegator_id: T::AccountId, + delegator_account: T::AccountId, delegator: &mut Delegator, bonded_pool: &mut BondedPool, ) -> DispatchResult { - let mut reward_pool = RewardPools::::get(&delegator.bonded_pool_account) + debug_assert_eq!(delegator.pool_id, bonded_pool.id); + let mut reward_pool = RewardPools::::get(delegator.pool_id) .defensive_ok_or_else(|| Error::::RewardPoolNotFound)?; let delegator_payout = @@ -1720,20 +1681,20 @@ impl Pallet { // Transfer payout to the delegator. T::Currency::transfer( - &reward_pool.account, - &delegator_id, + &bonded_pool.reward_account(), + &delegator_account, delegator_payout, ExistenceRequirement::AllowDeath, )?; Self::deposit_event(Event::::PaidOut { - delegator: delegator_id.clone(), - pool: delegator.bonded_pool_account.clone(), + delegator: delegator_account, + pool_id: delegator.pool_id, payout: delegator_payout, }); // Write the reward pool to storage - RewardPools::insert(&delegator.bonded_pool_account, reward_pool); + RewardPools::insert(&delegator.pool_id, reward_pool); Ok(()) } @@ -1742,18 +1703,22 @@ impl Pallet { impl OnStakerSlash> for Pallet { fn on_slash( pool_account: &T::AccountId, - _slashed_bonded: BalanceOf, // Bonded balance is always read directly from staking. + // Bonded balance is always read directly from staking, therefore we need not update + // anything here. + _slashed_bonded: BalanceOf, slashed_unlocking: &BTreeMap>, ) { - let mut sub_pools = match SubPoolsStorage::::get(pool_account) { - Some(sub_pools) => sub_pools, - None => return, - }; - for (era, slashed_balance) in slashed_unlocking.iter() { - if let Some(pool) = sub_pools.with_era.get_mut(era) { - pool.balance = *slashed_balance + if let Some(pool_id) = ReversePoolIdLookup::::get(pool_account) { + let mut sub_pools = match SubPoolsStorage::::get(pool_id).defensive() { + Some(sub_pools) => sub_pools, + None => return, + }; + for (era, slashed_balance) in slashed_unlocking.iter() { + if let Some(pool) = sub_pools.with_era.get_mut(era) { + pool.balance = *slashed_balance + } } + SubPoolsStorage::::insert(pool_id, sub_pools); } - SubPoolsStorage::::insert(pool_account.clone(), sub_pools); } } diff --git a/frame/nomination-pools/src/mock.rs b/frame/nomination-pools/src/mock.rs index 2d74e6464afae..0216df5a01faf 100644 --- a/frame/nomination-pools/src/mock.rs +++ b/frame/nomination-pools/src/mock.rs @@ -1,15 +1,20 @@ use super::*; use crate::{self as pools}; -use frame_support::{assert_ok, parameter_types}; +use frame_support::{assert_ok, parameter_types, PalletId}; use frame_system::RawOrigin; -pub type AccountId = u32; +pub type AccountId = u128; pub type Balance = u128; -/// _Stash_ of the pool that gets created by the [`ExtBuilder`]. -pub const PRIMARY_ACCOUNT: u32 = 1552898353; -/// Reward destination of the pool that gets created by the [`ExtBuilder`]. -pub const REWARDS_ACCOUNT: u32 = 3802151463; +// Ext builder creates a pool with id 1. +pub fn default_bonded_account() -> AccountId { + Pools::create_bonded_account(1) +} + +// Ext builder creates a pool with id 1. +pub fn default_reward_account() -> AccountId { + Pools::create_reward_account(1) +} parameter_types! { pub static CurrentEra: EraIndex = 0; @@ -153,8 +158,8 @@ impl Convert for U256ToBalance { parameter_types! { pub static PostUnbondingPoolsWindow: u32 = 2; pub static MaxMetadataLen: u32 = 2; + pub const PoolsPalletId: PalletId = PalletId(*b"py/nopls"); } - impl pools::Config for Runtime { type Event = Event; type WeightInfo = (); @@ -163,6 +168,7 @@ impl pools::Config for Runtime { type U256ToBalance = U256ToBalance; type StakingInterface = StakingMock; type PostUnbondingPoolsWindow = PostUnbondingPoolsWindow; + type PalletId = PoolsPalletId; type MaxMetadataLen = MaxMetadataLen; } @@ -214,14 +220,10 @@ impl ExtBuilder { Balances::make_free_balance_be(&10, amount_to_bond * 2); assert_ok!(Pools::create(RawOrigin::Signed(10).into(), amount_to_bond, 900, 901, 902)); + let last_pool = LastPoolId::::get(); for (account_id, bonded) in self.delegators { Balances::make_free_balance_be(&account_id, bonded * 2); - - assert_ok!(Pools::join( - RawOrigin::Signed(account_id).into(), - bonded, - PRIMARY_ACCOUNT - )); + assert_ok!(Pools::join(RawOrigin::Signed(account_id).into(), bonded, last_pool)); } }); @@ -242,8 +244,8 @@ impl ExtBuilder { } } -pub(crate) fn unsafe_set_state(pool_account: &AccountId, state: PoolState) -> Result<(), ()> { - BondedPools::::try_mutate(pool_account, |maybe_bonded_pool| { +pub(crate) fn unsafe_set_state(pool_id: PoolId, state: PoolState) -> Result<(), ()> { + BondedPools::::try_mutate(pool_id, |maybe_bonded_pool| { maybe_bonded_pool.as_mut().ok_or(()).map(|bonded_pool| { bonded_pool.state = state; }) diff --git a/frame/nomination-pools/src/tests.rs b/frame/nomination-pools/src/tests.rs index fdc7925f291c2..51c1d33e3a1ca 100644 --- a/frame/nomination-pools/src/tests.rs +++ b/frame/nomination-pools/src/tests.rs @@ -1,8 +1,5 @@ use super::*; -use crate::mock::{ - unsafe_set_state, Balance, Balances, CurrentEra, ExistentialDeposit, ExtBuilder, Nominations, - Origin, Pools, Runtime, StakingMock, PRIMARY_ACCOUNT, REWARDS_ACCOUNT, UNBONDING_BALANCE_MAP, -}; +use crate::mock::*; use frame_support::{assert_noop, assert_ok}; macro_rules! sub_pools_with_era { @@ -13,6 +10,9 @@ macro_rules! sub_pools_with_era { }}; } +pub const DEFAULT_ROLES: PoolRoles = + PoolRoles { depositor: 10, root: 900, nominator: 901, state_toggler: 902 }; + #[test] fn test_setup_works() { ExtBuilder::default().build_and_execute(|| { @@ -22,32 +22,27 @@ fn test_setup_works() { assert_eq!(Delegators::::count(), 1); assert_eq!(StakingMock::bonding_duration(), 3); + let last_pool = LastPoolId::::get(); assert_eq!( - BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(), + BondedPool::::get(last_pool).unwrap(), BondedPool:: { - depositor: 10, - state: PoolState::Open, - points: 10, - account: PRIMARY_ACCOUNT, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 1, + id: last_pool, + inner: BondedPoolInner { + state: PoolState::Open, + points: 10, + delegator_counter: 1, + roles: DEFAULT_ROLES + }, } ); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), - RewardPool:: { - balance: 0, - points: 0.into(), - total_earnings: 0, - account: REWARDS_ACCOUNT - } + RewardPools::::get(last_pool).unwrap(), + RewardPool:: { balance: 0, points: 0.into(), total_earnings: 0 } ); assert_eq!( Delegators::::get(10).unwrap(), Delegator:: { - bonded_pool_account: PRIMARY_ACCOUNT, + pool_id: last_pool, points: 10, reward_pool_total_earnings: 0, unbonding_era: None @@ -71,51 +66,50 @@ mod bonded_pool { #[test] fn points_to_issue_works() { let mut bonded_pool = BondedPool:: { - depositor: 10, - state: PoolState::Open, - points: 100, - account: 123, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 1, + id: 123123, + inner: BondedPoolInner { + state: PoolState::Open, + points: 100, + delegator_counter: 1, + roles: DEFAULT_ROLES, + }, }; // 1 points : 1 balance ratio - StakingMock::set_bonded_balance(123, 100); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 100); assert_eq!(bonded_pool.points_to_issue(10), 10); assert_eq!(bonded_pool.points_to_issue(0), 0); // 2 points : 1 balance ratio - StakingMock::set_bonded_balance(123, 50); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 50); assert_eq!(bonded_pool.points_to_issue(10), 20); // 1 points : 2 balance ratio - StakingMock::set_bonded_balance(123, 100); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 100); bonded_pool.points = 50; assert_eq!(bonded_pool.points_to_issue(10), 5); // 100 points : 0 balance ratio - StakingMock::set_bonded_balance(123, 0); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 0); bonded_pool.points = 100; assert_eq!(bonded_pool.points_to_issue(10), 100 * 10); // 0 points : 100 balance - StakingMock::set_bonded_balance(123, 100); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 100); bonded_pool.points = 100; assert_eq!(bonded_pool.points_to_issue(10), 10); // 10 points : 3 balance ratio - StakingMock::set_bonded_balance(123, 30); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 30); assert_eq!(bonded_pool.points_to_issue(10), 33); // 2 points : 3 balance ratio - StakingMock::set_bonded_balance(123, 300); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 300); bonded_pool.points = 200; assert_eq!(bonded_pool.points_to_issue(10), 6); // 4 points : 9 balance ratio - StakingMock::set_bonded_balance(123, 900); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 900); bonded_pool.points = 400; assert_eq!(bonded_pool.points_to_issue(90), 40); } @@ -124,16 +118,16 @@ mod bonded_pool { fn balance_to_unbond_works() { // 1 balance : 1 points ratio let mut bonded_pool = BondedPool:: { - depositor: 10, - state: PoolState::Open, - points: 100, - account: 123, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 1, + id: 123123, + inner: BondedPoolInner { + state: PoolState::Open, + points: 100, + delegator_counter: 1, + roles: DEFAULT_ROLES, + }, }; - StakingMock::set_bonded_balance(123, 100); + + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 100); assert_eq!(bonded_pool.balance_to_unbond(10), 10); assert_eq!(bonded_pool.balance_to_unbond(0), 0); @@ -142,27 +136,27 @@ mod bonded_pool { assert_eq!(bonded_pool.balance_to_unbond(10), 20); // 100 balance : 0 points ratio - StakingMock::set_bonded_balance(123, 0); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 0); bonded_pool.points = 0; assert_eq!(bonded_pool.balance_to_unbond(10), 0); // 0 balance : 100 points ratio - StakingMock::set_bonded_balance(123, 0); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 0); bonded_pool.points = 100; assert_eq!(bonded_pool.balance_to_unbond(10), 0); // 10 balance : 3 points ratio - StakingMock::set_bonded_balance(123, 100); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 100); bonded_pool.points = 30; assert_eq!(bonded_pool.balance_to_unbond(10), 33); // 2 balance : 3 points ratio - StakingMock::set_bonded_balance(123, 200); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 200); bonded_pool.points = 300; assert_eq!(bonded_pool.balance_to_unbond(10), 6); // 4 balance : 9 points ratio - StakingMock::set_bonded_balance(123, 400); + StakingMock::set_bonded_balance(bonded_pool.bonded_account(), 400); bonded_pool.points = 900; assert_eq!(bonded_pool.balance_to_unbond(90), 40); } @@ -171,33 +165,32 @@ mod bonded_pool { fn ok_to_join_with_works() { ExtBuilder::default().build_and_execute(|| { let pool = BondedPool:: { - depositor: 10, - state: PoolState::Open, - points: 100, - account: 123, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 1, + id: 123, + inner: BondedPoolInner { + state: PoolState::Open, + points: 100, + delegator_counter: 1, + roles: DEFAULT_ROLES, + }, }; // Simulate a 100% slashed pool - StakingMock::set_bonded_balance(123, 0); + StakingMock::set_bonded_balance(pool.bonded_account(), 0); assert_noop!(pool.ok_to_join(), Error::::OverflowRisk); // Simulate a 89% - StakingMock::set_bonded_balance(123, 11); + StakingMock::set_bonded_balance(pool.bonded_account(), 11); assert_ok!(pool.ok_to_join()); // Simulate a 90% slashed pool - StakingMock::set_bonded_balance(123, 10); + StakingMock::set_bonded_balance(pool.bonded_account(), 10); assert_noop!(pool.ok_to_join(), Error::::OverflowRisk); - StakingMock::set_bonded_balance(123, Balance::MAX / 10); + StakingMock::set_bonded_balance(pool.bonded_account(), Balance::MAX / 10); // New bonded balance would be over 1/10th of Balance type assert_noop!(pool.ok_to_join(), Error::::OverflowRisk); // and a sanity check - StakingMock::set_bonded_balance(123, Balance::MAX / 10 - 1); + StakingMock::set_bonded_balance(pool.bonded_account(), Balance::MAX / 10 - 1); assert_ok!(pool.ok_to_join()); }); } @@ -280,6 +273,7 @@ mod unbond_pool { assert_eq!(unbond_pool.balance_to_unbond(90), 40); } } + mod sub_pools { use super::*; @@ -358,14 +352,13 @@ mod join { #[test] fn join_works() { let bonded = |points, delegator_counter| BondedPool:: { - depositor: 10, - state: PoolState::Open, - points, - account: PRIMARY_ACCOUNT, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter, + id: 1, + inner: BondedPoolInner { + state: PoolState::Open, + points, + delegator_counter, + roles: DEFAULT_ROLES, + }, }; ExtBuilder::default().build_and_execute(|| { // Given @@ -373,104 +366,100 @@ mod join { assert!(!Delegators::::contains_key(&11)); // When - assert_ok!(Pools::join(Origin::signed(11), 2, PRIMARY_ACCOUNT)); + assert_ok!(Pools::join(Origin::signed(11), 2, 1)); // then assert_eq!( Delegators::::get(&11).unwrap(), Delegator:: { - bonded_pool_account: PRIMARY_ACCOUNT, + pool_id: 1, points: 2, reward_pool_total_earnings: 0, unbonding_era: None } ); - assert_eq!(BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(), bonded(12, 2)); + assert_eq!(BondedPool::::get(1).unwrap(), bonded(12, 2)); // Given // The bonded balance is slashed in half - StakingMock::set_bonded_balance(PRIMARY_ACCOUNT, 6); + StakingMock::set_bonded_balance(Pools::create_bonded_account(1), 6); + // And Balances::make_free_balance_be(&12, ExistentialDeposit::get() + 12); assert!(!Delegators::::contains_key(&12)); // When - assert_ok!(Pools::join(Origin::signed(12), 12, PRIMARY_ACCOUNT)); + assert_ok!(Pools::join(Origin::signed(12), 12, 1)); // Then assert_eq!( Delegators::::get(&12).unwrap(), Delegator:: { - bonded_pool_account: PRIMARY_ACCOUNT, + pool_id: 1, points: 24, reward_pool_total_earnings: 0, unbonding_era: None } ); - assert_eq!(BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(), bonded(12 + 24, 3)); + assert_eq!(BondedPool::::get(1).unwrap(), bonded(12 + 24, 3)); }); } #[test] fn join_errors_correctly() { ExtBuilder::default().build_and_execute_no_checks(|| { + // 10 is already part of the default pool created. + assert_eq!(Delegators::::get(&10).unwrap().pool_id, 1); + assert_noop!( - Pools::join(Origin::signed(10), 420, PRIMARY_ACCOUNT), + Pools::join(Origin::signed(10), 420, 123), Error::::AccountBelongsToOtherPool ); - assert_noop!(Pools::join(Origin::signed(11), 420, 420), Error::::PoolNotFound); + assert_noop!(Pools::join(Origin::signed(11), 420, 123), Error::::PoolNotFound); // Force the pools bonded balance to 0, simulating a 100% slash - StakingMock::set_bonded_balance(PRIMARY_ACCOUNT, 0); - assert_noop!( - Pools::join(Origin::signed(11), 420, PRIMARY_ACCOUNT), - Error::::OverflowRisk - ); + StakingMock::set_bonded_balance(Pools::create_bonded_account(1), 0); + assert_noop!(Pools::join(Origin::signed(11), 420, 1), Error::::OverflowRisk); // Given a mocked bonded pool BondedPool:: { - depositor: 10, - state: PoolState::Open, - points: 100, - account: 123, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 1, + id: 123, + inner: BondedPoolInner { + delegator_counter: 1, + state: PoolState::Open, + points: 100, + roles: DEFAULT_ROLES, + }, } .put(); + // and reward pool RewardPools::::insert( 123, RewardPool:: { - account: 1123, balance: Zero::zero(), total_earnings: Zero::zero(), - points: U256::from(0), + points: U256::from(0u32), }, ); // Force the points:balance ratio to 100/10 - StakingMock::set_bonded_balance(123, 10); + StakingMock::set_bonded_balance(Pools::create_bonded_account(123), 10); assert_noop!(Pools::join(Origin::signed(11), 420, 123), Error::::OverflowRisk); - StakingMock::set_bonded_balance(123, Balance::MAX / 10); + StakingMock::set_bonded_balance(Pools::create_bonded_account(123), Balance::MAX / 10); // Balance is gt 1/10 of Balance::MAX assert_noop!(Pools::join(Origin::signed(11), 5, 123), Error::::OverflowRisk); - StakingMock::set_bonded_balance(PRIMARY_ACCOUNT, 10); + StakingMock::set_bonded_balance(Pools::create_bonded_account(1), 10); + // Cannot join a pool that isn't open - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Blocked).unwrap(); - assert_noop!( - Pools::join(Origin::signed(11), 10, PRIMARY_ACCOUNT), - Error::::NotOpen - ); - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Destroying).unwrap(); - assert_noop!( - Pools::join(Origin::signed(11), 10, PRIMARY_ACCOUNT), - Error::::NotOpen - ); + unsafe_set_state(123, PoolState::Blocked).unwrap(); + assert_noop!(Pools::join(Origin::signed(11), 10, 123), Error::::NotOpen); + + unsafe_set_state(123, PoolState::Destroying).unwrap(); + assert_noop!(Pools::join(Origin::signed(11), 10, 123), Error::::NotOpen); // Given MinJoinBond::::put(100); @@ -486,17 +475,17 @@ mod join { #[test] #[should_panic = "Defensive failure has been triggered!"] fn join_panics_when_reward_pool_not_found() { + // TODO: but we should fail defensively.. ExtBuilder::default().build_and_execute(|| { - StakingMock::set_bonded_balance(123, 100); + StakingMock::set_bonded_balance(Pools::create_bonded_account(123), 100); BondedPool:: { - depositor: 10, - state: PoolState::Open, - points: 100, - account: 123, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 1, + id: 123, + inner: BondedPoolInner { + state: PoolState::Open, + points: 100, + delegator_counter: 1, + roles: DEFAULT_ROLES, + }, } .put(); let _ = Pools::join(Origin::signed(11), 420, 123); @@ -512,24 +501,23 @@ mod join { let account = i + 100; Balances::make_free_balance_be(&account, 100 + Balances::minimum_balance()); - assert_ok!(Pools::join(Origin::signed(account), 100, PRIMARY_ACCOUNT)); + assert_ok!(Pools::join(Origin::signed(account), 100, 1)); } Balances::make_free_balance_be(&103, 100 + Balances::minimum_balance()); // Then - assert_noop!( - Pools::join(Origin::signed(103), 100, PRIMARY_ACCOUNT), - Error::::MaxDelegators - ); + assert_noop!(Pools::join(Origin::signed(103), 100, 1), Error::::MaxDelegators); // Given assert_eq!(Delegators::::count(), 3); assert_eq!(MaxDelegators::::get(), Some(4)); + Balances::make_free_balance_be(&104, 100 + Balances::minimum_balance()); assert_ok!(Pools::create(Origin::signed(104), 100, 104, 104, 104)); + let pool_account = BondedPools::::iter() - .find(|(_, bonded_pool)| bonded_pool.depositor == 104) + .find(|(_, bonded_pool)| bonded_pool.roles.depositor == 104) .map(|(pool_account, _)| pool_account) .unwrap(); @@ -546,16 +534,11 @@ mod claim_payout { use super::*; fn del(points: Balance, reward_pool_total_earnings: Balance) -> Delegator { - Delegator { - bonded_pool_account: PRIMARY_ACCOUNT, - points, - reward_pool_total_earnings, - unbonding_era: None, - } + Delegator { pool_id: 1, points, reward_pool_total_earnings, unbonding_era: None } } fn rew(balance: Balance, points: u32, total_earnings: Balance) -> RewardPool { - RewardPool { balance, points: points.into(), total_earnings, account: REWARDS_ACCOUNT } + RewardPool { balance, points: points.into(), total_earnings } } #[test] @@ -567,8 +550,9 @@ mod claim_payout { Balances::make_free_balance_be(&10, 0); Balances::make_free_balance_be(&40, 0); Balances::make_free_balance_be(&50, 0); + let reward_account = Pools::create_reward_account(1); // and the reward pool has earned 100 in rewards - Balances::make_free_balance_be(&REWARDS_ACCOUNT, 100); + Balances::make_free_balance_be(&reward_account, 100); // When assert_ok!(Pools::claim_payout(Origin::signed(10))); @@ -578,11 +562,11 @@ mod claim_payout { // balance assert_eq!(Delegators::::get(10).unwrap(), del(10, 100)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(&1).unwrap(), rew(90, 100 * 100 - 100 * 10, 100) ); assert_eq!(Balances::free_balance(&10), 10); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 90); + assert_eq!(Balances::free_balance(&reward_account), 90); // When assert_ok!(Pools::claim_payout(Origin::signed(40))); @@ -591,11 +575,11 @@ mod claim_payout { // Expect payout 40: (400 del virtual points / 900 pool points) * 90 pool balance assert_eq!(Delegators::::get(40).unwrap(), del(40, 100)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(&1).unwrap(), rew(50, 9_000 - 100 * 40, 100) ); assert_eq!(Balances::free_balance(&40), 40); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 50); + assert_eq!(Balances::free_balance(&reward_account), 50); // When assert_ok!(Pools::claim_payout(Origin::signed(50))); @@ -603,12 +587,12 @@ mod claim_payout { // Then // Expect payout 50: (50 del virtual points / 50 pool points) * 50 pool balance assert_eq!(Delegators::::get(50).unwrap(), del(50, 100)); - assert_eq!(RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), rew(0, 0, 100)); + assert_eq!(RewardPools::::get(&1).unwrap(), rew(0, 0, 100)); assert_eq!(Balances::free_balance(&50), 50); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 0); + assert_eq!(Balances::free_balance(&reward_account), 0); // Given the reward pool has some new rewards - Balances::make_free_balance_be(&REWARDS_ACCOUNT, 50); + Balances::make_free_balance_be(&reward_account, 50); // When assert_ok!(Pools::claim_payout(Origin::signed(10))); @@ -616,12 +600,9 @@ mod claim_payout { // Then // Expect payout 5: (500 del virtual points / 5,000 pool points) * 50 pool balance assert_eq!(Delegators::::get(10).unwrap(), del(10, 150)); - assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), - rew(45, 5_000 - 50 * 10, 150) - ); + assert_eq!(RewardPools::::get(&1).unwrap(), rew(45, 5_000 - 50 * 10, 150)); assert_eq!(Balances::free_balance(&10), 10 + 5); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 45); + assert_eq!(Balances::free_balance(&reward_account), 45); // When assert_ok!(Pools::claim_payout(Origin::signed(40))); @@ -630,16 +611,13 @@ mod claim_payout { // Expect payout 20: (2,000 del virtual points / 4,500 pool points) * 45 pool // balance assert_eq!(Delegators::::get(40).unwrap(), del(40, 150)); - assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), - rew(25, 4_500 - 50 * 40, 150) - ); + assert_eq!(RewardPools::::get(&1).unwrap(), rew(25, 4_500 - 50 * 40, 150)); assert_eq!(Balances::free_balance(&40), 40 + 20); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 25); + assert_eq!(Balances::free_balance(&reward_account), 25); // Given del 50 hasn't claimed and the reward pools has just earned 50 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free += 50)); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 75); + assert_ok!(Balances::mutate_account(&reward_account, |a| a.free += 50)); + assert_eq!(Balances::free_balance(&reward_account), 75); // When assert_ok!(Pools::claim_payout(Origin::signed(50))); @@ -649,7 +627,7 @@ mod claim_payout { // pool balance assert_eq!(Delegators::::get(50).unwrap(), del(50, 200)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(&1).unwrap(), rew( 25, // old pool points + points from new earnings - del points. @@ -661,7 +639,7 @@ mod claim_payout { ) ); assert_eq!(Balances::free_balance(&50), 50 + 50); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 25); + assert_eq!(Balances::free_balance(&reward_account), 25); // When assert_ok!(Pools::claim_payout(Origin::signed(10))); @@ -669,16 +647,13 @@ mod claim_payout { // Then // We expect a payout of 5 assert_eq!(Delegators::::get(10).unwrap(), del(10, 200)); - assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), - rew(20, 2_500 - 10 * 50, 200) - ); + assert_eq!(RewardPools::::get(&1).unwrap(), rew(20, 2_500 - 10 * 50, 200)); assert_eq!(Balances::free_balance(&10), 15 + 5); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 20); + assert_eq!(Balances::free_balance(&reward_account), 20); // Given del 40 hasn't claimed and the reward pool has just earned 400 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free += 400)); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 420); + assert_ok!(Balances::mutate_account(&reward_account, |a| a.free += 400)); + assert_eq!(Balances::free_balance(&reward_account), 420); // When assert_ok!(Pools::claim_payout(Origin::signed(10))); @@ -687,7 +662,7 @@ mod claim_payout { // We expect a payout of 40 assert_eq!(Delegators::::get(10).unwrap(), del(10, 600)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(&1).unwrap(), rew( 380, // old pool points + points from new earnings - del points @@ -699,11 +674,11 @@ mod claim_payout { ) ); assert_eq!(Balances::free_balance(&10), 20 + 40); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 380); + assert_eq!(Balances::free_balance(&reward_account), 380); // Given del 40 + del 50 haven't claimed and the reward pool has earned 20 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free += 20)); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 400); + assert_ok!(Balances::mutate_account(&reward_account, |a| a.free += 20)); + assert_eq!(Balances::free_balance(&reward_account), 400); // When assert_ok!(Pools::claim_payout(Origin::signed(10))); @@ -713,11 +688,11 @@ mod claim_payout { // balance assert_eq!(Delegators::::get(10).unwrap(), del(10, 620)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(&1).unwrap(), rew(398, (38_000 + 20 * 100) - 10 * 20, 620) ); assert_eq!(Balances::free_balance(&10), 60 + 2); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 398); + assert_eq!(Balances::free_balance(&reward_account), 398); // When assert_ok!(Pools::claim_payout(Origin::signed(40))); @@ -727,11 +702,11 @@ mod claim_payout { // pool balance assert_eq!(Delegators::::get(40).unwrap(), del(40, 620)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(&1).unwrap(), rew(210, 39_800 - 40 * 470, 620) ); assert_eq!(Balances::free_balance(&40), 60 + 188); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 210); + assert_eq!(Balances::free_balance(&reward_account), 210); // When assert_ok!(Pools::claim_payout(Origin::signed(50))); @@ -740,25 +715,26 @@ mod claim_payout { // Expect payout of 210: (21,000 / 21,000) * 210 assert_eq!(Delegators::::get(50).unwrap(), del(50, 620)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(&1).unwrap(), rew(0, 21_000 - 50 * 420, 620) ); assert_eq!(Balances::free_balance(&50), 100 + 210); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 0); + assert_eq!(Balances::free_balance(&reward_account), 0); }); } #[test] fn do_reward_payout_correctly_sets_pool_state_to_destroying() { ExtBuilder::default().build_and_execute(|| { - let mut bonded_pool = BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(); - let mut reward_pool = RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(); + let mut bonded_pool = BondedPool::::get(1).unwrap(); + let mut reward_pool = RewardPools::::get(1).unwrap(); let mut delegator = Delegators::::get(10).unwrap(); + let reward_account = Pools::create_reward_account(1); // --- reward_pool.total_earnings saturates // Given - Balances::make_free_balance_be(&reward_pool.account, Balance::MAX); + Balances::make_free_balance_be(&reward_account, Balance::MAX); // When assert_ok!(Pools::do_reward_payout(10, &mut delegator, &mut bonded_pool)); @@ -766,18 +742,17 @@ mod claim_payout { // Then assert!(bonded_pool.is_destroying()); - // -- current_points saturates (reward_pool.points + new_earnings * bonded_pool.points) // Given - let mut bonded_pool = BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(); + let mut bonded_pool = BondedPool::::get(1).unwrap(); let mut delegator = Delegators::::get(10).unwrap(); // Force new_earnings * bonded_pool.points == 100 - Balances::make_free_balance_be(&reward_pool.account, 10); + Balances::make_free_balance_be(&reward_account, 10); assert_eq!(bonded_pool.points, 10); // Force reward_pool.points == U256::MAX - new_earnings * bonded_pool.points - reward_pool.points = U256::MAX - U256::from(100); - RewardPools::::insert(PRIMARY_ACCOUNT, reward_pool.clone()); + reward_pool.points = U256::MAX - U256::from(100u32); + RewardPools::::insert(1, reward_pool.clone()); // When assert_ok!(Pools::do_reward_payout(10, &mut delegator, &mut bonded_pool)); @@ -790,8 +765,8 @@ mod claim_payout { #[test] fn calculate_delegator_payout_errors_if_a_delegator_is_unbonding() { ExtBuilder::default().build_and_execute(|| { - let mut bonded_pool = BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(); - let mut reward_pool = RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(); + let mut bonded_pool = BondedPool::::get(1).unwrap(); + let mut reward_pool = RewardPools::::get(1).unwrap(); let mut delegator = Delegators::::get(10).unwrap(); delegator.unbonding_era = Some(0 + 3); @@ -811,9 +786,10 @@ mod claim_payout { let del = |reward_pool_total_earnings| del(10, reward_pool_total_earnings); ExtBuilder::default().build_and_execute(|| { - let mut bonded_pool = BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(); - let mut reward_pool = RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(); + let mut bonded_pool = BondedPool::::get(1).unwrap(); + let mut reward_pool = RewardPools::::get(1).unwrap(); let mut delegator = Delegators::::get(10).unwrap(); + let reward_account = Pools::create_reward_account(1); // Given no rewards have been earned // When @@ -830,7 +806,7 @@ mod claim_payout { assert_eq!(reward_pool, rew(0, 0, 0)); // Given the pool has earned some rewards for the first time - Balances::make_free_balance_be(&reward_pool.account, 5); + Balances::make_free_balance_be(&reward_account, 5); // When let payout = Pools::calculate_delegator_payout( @@ -846,7 +822,7 @@ mod claim_payout { assert_eq!(delegator, del(5)); // Given the pool has earned rewards again - Balances::make_free_balance_be(&REWARDS_ACCOUNT, 10); + Balances::make_free_balance_be(&reward_account, 10); // When let payout = Pools::calculate_delegator_payout( @@ -862,7 +838,7 @@ mod claim_payout { assert_eq!(delegator, del(15)); // Given the pool has earned no new rewards - Balances::make_free_balance_be(&REWARDS_ACCOUNT, 0); + Balances::make_free_balance_be(&reward_account, 0); // When let payout = Pools::calculate_delegator_payout( @@ -884,8 +860,8 @@ mod claim_payout { ExtBuilder::default() .add_delegators(vec![(40, 40), (50, 50)]) .build_and_execute(|| { - let mut bonded_pool = BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(); - let mut reward_pool = RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(); + let mut bonded_pool = BondedPool::::get(1).unwrap(); + let mut reward_pool = RewardPools::::get(1).unwrap(); // Delegator with 10 points let mut del_10 = Delegators::::get(10).unwrap(); // Delegator with 40 points @@ -897,7 +873,7 @@ mod claim_payout { assert_eq!(del_50.points + del_40.points + del_10.points, 100); assert_eq!(bonded_pool.points, 100); // and the reward pool has earned 100 in rewards - Balances::make_free_balance_be(&REWARDS_ACCOUNT, 100); + Balances::make_free_balance_be(&default_reward_account(), 100); // When let payout = Pools::calculate_delegator_payout( @@ -912,7 +888,7 @@ mod claim_payout { assert_eq!(del_10, del(10, 100)); assert_eq!(reward_pool, rew(90, 100 * 100 - 100 * 10, 100)); // Mock the reward pool transferring the payout to del_10 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free -= 10)); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free -= 10)); // When let payout = Pools::calculate_delegator_payout( @@ -935,7 +911,7 @@ mod claim_payout { ) ); // Mock the reward pool transferring the payout to del_40 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free -= 40)); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free -= 40)); // When let payout = Pools::calculate_delegator_payout( @@ -950,10 +926,10 @@ mod claim_payout { assert_eq!(del_50, del(50, 100)); assert_eq!(reward_pool, rew(0, 0, 100)); // Mock the reward pool transferring the payout to del_50 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free -= 50)); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free -= 50)); // Given the reward pool has some new rewards - Balances::make_free_balance_be(&REWARDS_ACCOUNT, 50); + Balances::make_free_balance_be(&default_reward_account(), 50); // When let payout = Pools::calculate_delegator_payout( @@ -968,7 +944,7 @@ mod claim_payout { assert_eq!(del_10, del(10, 150)); assert_eq!(reward_pool, rew(45, 5_000 - 50 * 10, 150)); // Mock the reward pool transferring the payout to del_10 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free -= 5)); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free -= 5)); // When let payout = Pools::calculate_delegator_payout( @@ -982,11 +958,11 @@ mod claim_payout { assert_eq!(payout, 20); // (2,000 del virtual points / 4,500 pool points) * 45 pool balance assert_eq!(del_40, del(40, 150)); assert_eq!(reward_pool, rew(25, 4_500 - 50 * 40, 150)); - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free -= 20)); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free -= 20)); // Given del_50 hasn't claimed and the reward pools has just earned 50 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free += 50)); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 75); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free += 50)); + assert_eq!(Balances::free_balance(&default_reward_account()), 75); // When let payout = Pools::calculate_delegator_payout( @@ -1012,7 +988,7 @@ mod claim_payout { ) ); // Mock the reward pool transferring the payout to del_50 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free -= 50)); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free -= 50)); // When let payout = Pools::calculate_delegator_payout( @@ -1027,11 +1003,11 @@ mod claim_payout { assert_eq!(del_10, del(10, 200)); assert_eq!(reward_pool, rew(20, 2_500 - 10 * 50, 200)); // Mock the reward pool transferring the payout to del_10 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free -= 5)); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free -= 5)); // Given del_40 hasn't claimed and the reward pool has just earned 400 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free += 400)); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 420); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free += 400)); + assert_eq!(Balances::free_balance(&default_reward_account()), 420); // When let payout = Pools::calculate_delegator_payout( @@ -1057,11 +1033,11 @@ mod claim_payout { ) ); // Mock the reward pool transferring the payout to del_10 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free -= 40)); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free -= 40)); // Given del_40 + del_50 haven't claimed and the reward pool has earned 20 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free += 20)); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 400); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free += 20)); + assert_eq!(Balances::free_balance(&default_reward_account()), 400); // When let payout = Pools::calculate_delegator_payout( @@ -1076,7 +1052,7 @@ mod claim_payout { assert_eq!(del_10, del(10, 620)); assert_eq!(reward_pool, rew(398, (38_000 + 20 * 100) - 10 * 20, 620)); // Mock the reward pool transferring the payout to del_10 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free -= 2)); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free -= 2)); // When let payout = Pools::calculate_delegator_payout( @@ -1091,7 +1067,7 @@ mod claim_payout { assert_eq!(del_40, del(40, 620)); assert_eq!(reward_pool, rew(210, 39_800 - 40 * 470, 620)); // Mock the reward pool transferring the payout to del_10 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free -= 188)); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free -= 188)); // When let payout = Pools::calculate_delegator_payout( @@ -1113,7 +1089,7 @@ mod claim_payout { ExtBuilder::default() .add_delegators(vec![(40, 40), (50, 50)]) .build_and_execute(|| { - let mut bonded_pool = BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(); + let mut bonded_pool = BondedPool::::get(1).unwrap(); // Given the bonded pool has 100 points assert_eq!(bonded_pool.points, 100); @@ -1122,7 +1098,7 @@ mod claim_payout { Balances::make_free_balance_be(&40, 0); Balances::make_free_balance_be(&50, 0); // and the reward pool has earned 100 in rewards - Balances::make_free_balance_be(&REWARDS_ACCOUNT, 100); + Balances::make_free_balance_be(&default_reward_account(), 100); let mut del_10 = Delegators::get(10).unwrap(); let mut del_40 = Delegators::get(40).unwrap(); @@ -1136,11 +1112,11 @@ mod claim_payout { // balance assert_eq!(del_10, del(10, 100)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(&1).unwrap(), rew(90, 100 * 100 - 100 * 10, 100) ); assert_eq!(Balances::free_balance(&10), 10); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 90); + assert_eq!(Balances::free_balance(&default_reward_account()), 90); // When assert_ok!(Pools::do_reward_payout(40, &mut del_40, &mut bonded_pool)); @@ -1149,11 +1125,11 @@ mod claim_payout { // Expect payout 40: (400 del virtual points / 900 pool points) * 90 pool balance assert_eq!(del_40, del(40, 100)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(&1).unwrap(), rew(50, 9_000 - 100 * 40, 100) ); assert_eq!(Balances::free_balance(&40), 40); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 50); + assert_eq!(Balances::free_balance(&default_reward_account()), 50); // When assert_ok!(Pools::do_reward_payout(50, &mut del_50, &mut bonded_pool)); @@ -1161,12 +1137,12 @@ mod claim_payout { // Then // Expect payout 50: (50 del virtual points / 50 pool points) * 50 pool balance assert_eq!(del_50, del(50, 100)); - assert_eq!(RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), rew(0, 0, 100)); + assert_eq!(RewardPools::::get(&1).unwrap(), rew(0, 0, 100)); assert_eq!(Balances::free_balance(&50), 50); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 0); + assert_eq!(Balances::free_balance(&default_reward_account()), 0); // Given the reward pool has some new rewards - Balances::make_free_balance_be(&REWARDS_ACCOUNT, 50); + Balances::make_free_balance_be(&default_reward_account(), 50); // When assert_ok!(Pools::do_reward_payout(10, &mut del_10, &mut bonded_pool)); @@ -1174,12 +1150,9 @@ mod claim_payout { // Then // Expect payout 5: (500 del virtual points / 5,000 pool points) * 50 pool balance assert_eq!(del_10, del(10, 150)); - assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), - rew(45, 5_000 - 50 * 10, 150) - ); + assert_eq!(RewardPools::::get(&1).unwrap(), rew(45, 5_000 - 50 * 10, 150)); assert_eq!(Balances::free_balance(&10), 10 + 5); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 45); + assert_eq!(Balances::free_balance(&default_reward_account()), 45); // When assert_ok!(Pools::do_reward_payout(40, &mut del_40, &mut bonded_pool)); @@ -1188,16 +1161,13 @@ mod claim_payout { // Expect payout 20: (2,000 del virtual points / 4,500 pool points) * 45 pool // balance assert_eq!(del_40, del(40, 150)); - assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), - rew(25, 4_500 - 50 * 40, 150) - ); + assert_eq!(RewardPools::::get(1).unwrap(), rew(25, 4_500 - 50 * 40, 150)); assert_eq!(Balances::free_balance(&40), 40 + 20); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 25); + assert_eq!(Balances::free_balance(&default_reward_account()), 25); // Given del 50 hasn't claimed and the reward pools has just earned 50 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free += 50)); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 75); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free += 50)); + assert_eq!(Balances::free_balance(&default_reward_account()), 75); // When assert_ok!(Pools::do_reward_payout(50, &mut del_50, &mut bonded_pool)); @@ -1207,7 +1177,7 @@ mod claim_payout { // pool balance assert_eq!(del_50, del(50, 200)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(1).unwrap(), rew( 25, // old pool points + points from new earnings - del points. @@ -1219,7 +1189,7 @@ mod claim_payout { ) ); assert_eq!(Balances::free_balance(&50), 50 + 50); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 25); + assert_eq!(Balances::free_balance(&default_reward_account()), 25); // When assert_ok!(Pools::do_reward_payout(10, &mut del_10, &mut bonded_pool)); @@ -1227,16 +1197,13 @@ mod claim_payout { // Then // We expect a payout of 5 assert_eq!(del_10, del(10, 200)); - assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), - rew(20, 2_500 - 10 * 50, 200) - ); + assert_eq!(RewardPools::::get(1).unwrap(), rew(20, 2_500 - 10 * 50, 200)); assert_eq!(Balances::free_balance(&10), 15 + 5); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 20); + assert_eq!(Balances::free_balance(&default_reward_account()), 20); // Given del 40 hasn't claimed and the reward pool has just earned 400 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free += 400)); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 420); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free += 400)); + assert_eq!(Balances::free_balance(&default_reward_account()), 420); // When assert_ok!(Pools::do_reward_payout(10, &mut del_10, &mut bonded_pool)); @@ -1245,7 +1212,7 @@ mod claim_payout { // We expect a payout of 40 assert_eq!(del_10, del(10, 600)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(1).unwrap(), rew( 380, // old pool points + points from new earnings - del points @@ -1257,11 +1224,11 @@ mod claim_payout { ) ); assert_eq!(Balances::free_balance(&10), 20 + 40); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 380); + assert_eq!(Balances::free_balance(&default_reward_account()), 380); // Given del 40 + del 50 haven't claimed and the reward pool has earned 20 - assert_ok!(Balances::mutate_account(&REWARDS_ACCOUNT, |a| a.free += 20)); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 400); + assert_ok!(Balances::mutate_account(&default_reward_account(), |a| a.free += 20)); + assert_eq!(Balances::free_balance(&default_reward_account()), 400); // When assert_ok!(Pools::do_reward_payout(10, &mut del_10, &mut bonded_pool)); @@ -1271,11 +1238,11 @@ mod claim_payout { // balance assert_eq!(del_10, del(10, 620)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(1).unwrap(), rew(398, (38_000 + 20 * 100) - 10 * 20, 620) ); assert_eq!(Balances::free_balance(&10), 60 + 2); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 398); + assert_eq!(Balances::free_balance(&default_reward_account()), 398); // When assert_ok!(Pools::do_reward_payout(40, &mut del_40, &mut bonded_pool)); @@ -1285,11 +1252,11 @@ mod claim_payout { // pool balance assert_eq!(del_40, del(40, 620)); assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), + RewardPools::::get(1).unwrap(), rew(210, 39_800 - 40 * 470, 620) ); assert_eq!(Balances::free_balance(&40), 60 + 188); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 210); + assert_eq!(Balances::free_balance(&default_reward_account()), 210); // When assert_ok!(Pools::do_reward_payout(50, &mut del_50, &mut bonded_pool)); @@ -1297,19 +1264,16 @@ mod claim_payout { // Then // Expect payout of 210: (21,000 / 21,000) * 210 assert_eq!(del_50, del(50, 620)); - assert_eq!( - RewardPools::::get(&PRIMARY_ACCOUNT).unwrap(), - rew(0, 21_000 - 50 * 420, 620) - ); + assert_eq!(RewardPools::::get(1).unwrap(), rew(0, 21_000 - 50 * 420, 620)); assert_eq!(Balances::free_balance(&50), 100 + 210); - assert_eq!(Balances::free_balance(&REWARDS_ACCOUNT), 0); + assert_eq!(Balances::free_balance(&default_reward_account()), 0); }); } #[test] fn do_reward_payout_errors_correctly() { ExtBuilder::default().build_and_execute(|| { - let mut bonded_pool = BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(); + let mut bonded_pool = BondedPool::::get(1).unwrap(); let mut delegator = Delegators::::get(10).unwrap(); // The only place this can return an error is with the balance transfer from the @@ -1319,7 +1283,7 @@ mod claim_payout { // Given delegator.points = 15; assert_eq!(bonded_pool.points, 10); - Balances::make_free_balance_be(&REWARDS_ACCOUNT, 10); + Balances::make_free_balance_be(&default_reward_account(), 10); // Then // Expect attempt payout of 15/10 * 10 when free balance is actually 10 @@ -1337,29 +1301,28 @@ mod unbond { #[test] fn unbond_other_of_1_works() { ExtBuilder::default().build_and_execute(|| { - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Destroying).unwrap(); + unsafe_set_state(1, PoolState::Destroying).unwrap(); assert_ok!(Pools::unbond_other(Origin::signed(10), 10)); assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap().with_era, + SubPoolsStorage::::get(1).unwrap().with_era, sub_pools_with_era! { 0 + 3 => UnbondPool:: { points: 10, balance: 10 }} ); assert_eq!( - BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(), + BondedPool::::get(1).unwrap(), BondedPool { - depositor: 10, - state: PoolState::Destroying, - points: 0, - account: PRIMARY_ACCOUNT, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 1, + id: 1, + inner: BondedPoolInner { + state: PoolState::Destroying, + points: 0, + delegator_counter: 1, + roles: DEFAULT_ROLES, + } } ); - assert_eq!(StakingMock::bonded_balance(&PRIMARY_ACCOUNT).unwrap(), 0); + assert_eq!(StakingMock::bonded_balance(&default_bonded_account()).unwrap(), 0); }); } @@ -1369,58 +1332,57 @@ mod unbond { .add_delegators(vec![(40, 40), (550, 550)]) .build_and_execute(|| { // Given a slash from 600 -> 100 - StakingMock::set_bonded_balance(PRIMARY_ACCOUNT, 100); + StakingMock::set_bonded_balance(default_bonded_account(), 100); // and unclaimed rewards of 600. - Balances::make_free_balance_be(&REWARDS_ACCOUNT, 600); + Balances::make_free_balance_be(&default_reward_account(), 600); // When assert_ok!(Pools::unbond_other(Origin::signed(40), 40)); // Then assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap().with_era, + SubPoolsStorage::::get(1).unwrap().with_era, sub_pools_with_era! { 0 + 3 => UnbondPool { points: 6, balance: 6 }} ); assert_eq!( - BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(), + BondedPool::::get(1).unwrap(), BondedPool { - depositor: 10, - state: PoolState::Open, - points: 560, - account: PRIMARY_ACCOUNT, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 3, + id: 1, + inner: BondedPoolInner { + state: PoolState::Open, + points: 560, + delegator_counter: 3, + roles: DEFAULT_ROLES, + } } ); - assert_eq!(StakingMock::bonded_balance(&PRIMARY_ACCOUNT).unwrap(), 94); + + assert_eq!(StakingMock::bonded_balance(&default_bonded_account()).unwrap(), 94); assert_eq!(Delegators::::get(40).unwrap().unbonding_era, Some(0 + 3)); assert_eq!(Balances::free_balance(&40), 40 + 40); // We claim rewards when unbonding // When - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Destroying).unwrap(); + unsafe_set_state(1, PoolState::Destroying).unwrap(); assert_ok!(Pools::unbond_other(Origin::signed(550), 550)); // Then assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap().with_era, + SubPoolsStorage::::get(&1).unwrap().with_era, sub_pools_with_era! { 0 + 3 => UnbondPool { points: 98, balance: 98 }} ); assert_eq!( - BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(), + BondedPool::::get(1).unwrap(), BondedPool { - depositor: 10, - state: PoolState::Destroying, - points: 10, - account: PRIMARY_ACCOUNT, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 3, + id: 1, + inner: BondedPoolInner { + state: PoolState::Destroying, + points: 10, + delegator_counter: 3, + roles: DEFAULT_ROLES + } } ); - assert_eq!(StakingMock::bonded_balance(&PRIMARY_ACCOUNT).unwrap(), 2); + assert_eq!(StakingMock::bonded_balance(&default_bonded_account()).unwrap(), 2); assert_eq!(Delegators::::get(550).unwrap().unbonding_era, Some(0 + 3)); assert_eq!(Balances::free_balance(&550), 550 + 550); @@ -1429,23 +1391,22 @@ mod unbond { // Then assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap().with_era, + SubPoolsStorage::::get(1).unwrap().with_era, sub_pools_with_era! { 0 + 3 => UnbondPool { points: 100, balance: 100 }} ); assert_eq!( - BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(), + BondedPool::::get(1).unwrap(), BondedPool { - depositor: 10, - state: PoolState::Destroying, - points: 0, - account: PRIMARY_ACCOUNT, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 3, + id: 1, + inner: BondedPoolInner { + state: PoolState::Destroying, + points: 0, + delegator_counter: 3, + roles: DEFAULT_ROLES + } } ); - assert_eq!(StakingMock::bonded_balance(&PRIMARY_ACCOUNT).unwrap(), 0); + assert_eq!(StakingMock::bonded_balance(&default_bonded_account()).unwrap(), 0); assert_eq!(Delegators::::get(550).unwrap().unbonding_era, Some(0 + 3)); assert_eq!(Balances::free_balance(&550), 550 + 550); }); @@ -1457,7 +1418,7 @@ mod unbond { // Given assert_eq!(StakingMock::bonding_duration(), 3); SubPoolsStorage::::insert( - PRIMARY_ACCOUNT, + 1, SubPools { no_era: Default::default(), with_era: sub_pools_with_era! { @@ -1467,7 +1428,7 @@ mod unbond { }, }, ); - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Destroying).unwrap(); + unsafe_set_state(1, PoolState::Destroying).unwrap(); // When let current_era = 1 + TotalUnbondingPools::::get(); @@ -1477,7 +1438,7 @@ mod unbond { // Then assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap(), + SubPoolsStorage::::get(1).unwrap(), SubPools { no_era: UnbondPool { balance: 10 + 20, points: 100 + 20 }, with_era: sub_pools_with_era! { @@ -1496,11 +1457,11 @@ mod unbond { .add_delegators(vec![(100, 100), (200, 200)]) .build_and_execute(|| { // Given - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Blocked).unwrap(); - let bonded_pool = BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(); - assert_eq!(bonded_pool.root, 900); - assert_eq!(bonded_pool.nominator, 901); - assert_eq!(bonded_pool.state_toggler, 902); + unsafe_set_state(1, PoolState::Blocked).unwrap(); + let bonded_pool = BondedPool::::get(1).unwrap(); + assert_eq!(bonded_pool.roles.root, 900); + assert_eq!(bonded_pool.roles.nominator, 901); + assert_eq!(bonded_pool.roles.state_toggler, 902); // When the nominator trys to kick, then its a noop assert_noop!( @@ -1515,21 +1476,20 @@ mod unbond { assert_ok!(Pools::unbond_other(Origin::signed(902), 200)); assert_eq!( - BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(), + BondedPool::::get(1).unwrap(), BondedPool { - root: 900, - nominator: 901, - state_toggler: 902, - account: PRIMARY_ACCOUNT, - depositor: 10, - state: PoolState::Blocked, - points: 10, // Only 10 points because 200 + 100 was unbonded - delegator_counter: 3, + id: 1, + inner: BondedPoolInner { + roles: DEFAULT_ROLES, + state: PoolState::Blocked, + points: 10, // Only 10 points because 200 + 100 was unbonded + delegator_counter: 3, + } } ); - assert_eq!(StakingMock::bonded_balance(&PRIMARY_ACCOUNT).unwrap(), 10); + assert_eq!(StakingMock::bonded_balance(&default_bonded_account()).unwrap(), 10); assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap(), + SubPoolsStorage::::get(1).unwrap(), SubPools { no_era: Default::default(), with_era: sub_pools_with_era! { @@ -1538,7 +1498,8 @@ mod unbond { } ); assert_eq!( - UNBONDING_BALANCE_MAP.with(|m| *m.borrow_mut().get(&PRIMARY_ACCOUNT).unwrap()), + UNBONDING_BALANCE_MAP + .with(|m| *m.borrow_mut().get(&default_bonded_account()).unwrap()), 100 + 200 ); }); @@ -1549,7 +1510,7 @@ mod unbond { // Scenarios where non-admin accounts can unbond others ExtBuilder::default().add_delegators(vec![(100, 100)]).build_and_execute(|| { // Given the pool is blocked - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Blocked).unwrap(); + unsafe_set_state(1, PoolState::Blocked).unwrap(); // A permissionless unbond attempt errors assert_noop!( @@ -1558,7 +1519,7 @@ mod unbond { ); // Given the pool is destroying - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Destroying).unwrap(); + unsafe_set_state(1, PoolState::Destroying).unwrap(); // The depositor cannot be unbonded until they are the last delegator assert_noop!( @@ -1570,7 +1531,7 @@ mod unbond { assert_ok!(Pools::unbond_other(Origin::signed(420), 100)); // Given the pool is blocked - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Blocked).unwrap(); + unsafe_set_state(1, PoolState::Blocked).unwrap(); // The depositor cannot be unbonded assert_noop!( @@ -1579,14 +1540,14 @@ mod unbond { ); // Given the pools is destroying - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Destroying).unwrap(); + unsafe_set_state(1, PoolState::Destroying).unwrap(); // The depositor can be unbonded assert_ok!(Pools::unbond_other(Origin::signed(420), 10)); - assert_eq!(BondedPools::::get(&PRIMARY_ACCOUNT).unwrap().points, 0); + assert_eq!(BondedPools::::get(1).unwrap().points, 0); assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap(), + SubPoolsStorage::::get(1).unwrap(), SubPools { no_era: Default::default(), with_era: sub_pools_with_era! { @@ -1594,9 +1555,10 @@ mod unbond { } } ); - assert_eq!(StakingMock::bonded_balance(&PRIMARY_ACCOUNT).unwrap(), 0); + assert_eq!(StakingMock::bonded_balance(&default_bonded_account()).unwrap(), 0); assert_eq!( - UNBONDING_BALANCE_MAP.with(|m| *m.borrow_mut().get(&PRIMARY_ACCOUNT).unwrap()), + UNBONDING_BALANCE_MAP + .with(|m| *m.borrow_mut().get(&default_bonded_account()).unwrap()), 110 ); }); @@ -1613,7 +1575,7 @@ mod unbond { // Add the delegator let delegator = Delegator { - bonded_pool_account: 1, + pool_id: 2, points: 10, reward_pool_total_earnings: 0, unbonding_era: None, @@ -1629,21 +1591,20 @@ mod unbond { fn unbond_panics_when_reward_pool_not_found() { ExtBuilder::default().build_and_execute(|| { let delegator = Delegator { - bonded_pool_account: 1, + pool_id: 2, points: 10, reward_pool_total_earnings: 0, unbonding_era: None, }; Delegators::::insert(11, delegator); BondedPool:: { - depositor: 10, - state: PoolState::Open, - points: 10, - account: 1, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 1, + id: 1, + inner: BondedPoolInner { + state: PoolState::Open, + points: 10, + delegator_counter: 1, + roles: DEFAULT_ROLES, + }, } .put(); @@ -1659,19 +1620,19 @@ mod pool_withdraw_unbonded { fn pool_withdraw_unbonded_works() { ExtBuilder::default().build_and_execute(|| { // Given 10 unbond'ed directly against the pool account - assert_ok!(StakingMock::unbond(PRIMARY_ACCOUNT, 5)); + assert_ok!(StakingMock::unbond(default_bonded_account(), 5)); // and the pool account only has 10 balance - assert_eq!(StakingMock::bonded_balance(&PRIMARY_ACCOUNT), Some(5)); - assert_eq!(StakingMock::locked_balance(&PRIMARY_ACCOUNT), Some(10)); - assert_eq!(Balances::free_balance(&PRIMARY_ACCOUNT), 10); + assert_eq!(StakingMock::bonded_balance(&default_bonded_account()), Some(5)); + assert_eq!(StakingMock::locked_balance(&default_bonded_account()), Some(10)); + assert_eq!(Balances::free_balance(&default_bonded_account()), 10); // When - assert_ok!(Pools::pool_withdraw_unbonded(Origin::signed(10), PRIMARY_ACCOUNT, 0)); + assert_ok!(Pools::pool_withdraw_unbonded(Origin::signed(10), 1, 0)); // Then there unbonding balance is no longer locked - assert_eq!(StakingMock::bonded_balance(&PRIMARY_ACCOUNT), Some(5)); - assert_eq!(StakingMock::locked_balance(&PRIMARY_ACCOUNT), Some(5)); - assert_eq!(Balances::free_balance(&PRIMARY_ACCOUNT), 10); + assert_eq!(StakingMock::bonded_balance(&default_bonded_account()), Some(5)); + assert_eq!(StakingMock::locked_balance(&default_bonded_account()), Some(5)); + assert_eq!(Balances::free_balance(&default_bonded_account()), 10); }); } } @@ -1688,15 +1649,15 @@ mod withdraw_unbonded_other { assert_eq!(StakingMock::bonding_duration(), 3); assert_ok!(Pools::unbond_other(Origin::signed(550), 550)); assert_ok!(Pools::unbond_other(Origin::signed(40), 40)); - assert_eq!(Balances::free_balance(&PRIMARY_ACCOUNT), 600); + assert_eq!(Balances::free_balance(&default_bonded_account()), 600); let mut current_era = 1; CurrentEra::set(current_era); // In a new era, unbond the depositor - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Destroying).unwrap(); + unsafe_set_state(1, PoolState::Destroying).unwrap(); assert_ok!(Pools::unbond_other(Origin::signed(10), 10)); - let mut sub_pools = SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap(); + let mut sub_pools = SubPoolsStorage::::get(1).unwrap(); // TODO: [now] in the future we could use StakingMock::unbond_era_for(current_era) // instead of current_era + 3. let unbond_pool = sub_pools.with_era.get_mut(&(current_era + 3)).unwrap(); @@ -1706,11 +1667,11 @@ mod withdraw_unbonded_other { // Simulate a slash to the pool with_era(current_era), decreasing the balance by // half unbond_pool.balance = 5; - SubPoolsStorage::::insert(PRIMARY_ACCOUNT, sub_pools); + SubPoolsStorage::::insert(1, sub_pools); // Update the equivalent of the unbonding chunks for the `StakingMock` UNBONDING_BALANCE_MAP - .with(|m| *m.borrow_mut().get_mut(&PRIMARY_ACCOUNT).unwrap() -= 5); - Balances::make_free_balance_be(&PRIMARY_ACCOUNT, 595); + .with(|m| *m.borrow_mut().get_mut(&default_bonded_account()).unwrap() -= 5); + Balances::make_free_balance_be(&default_bonded_account(), 595); // Advance the current_era to ensure all `with_era` pools will be merged into // `no_era` pool @@ -1719,12 +1680,11 @@ mod withdraw_unbonded_other { // Simulate some other call to unbond that would merge `with_era` pools into // `no_era` - let sub_pools = SubPoolsStorage::::get(&PRIMARY_ACCOUNT) - .unwrap() - .maybe_merge_pools(current_era + 3); - SubPoolsStorage::::insert(PRIMARY_ACCOUNT, sub_pools); + let sub_pools = + SubPoolsStorage::::get(1).unwrap().maybe_merge_pools(current_era + 3); + SubPoolsStorage::::insert(1, sub_pools); assert_eq!( - SubPoolsStorage::::get(PRIMARY_ACCOUNT).unwrap(), + SubPoolsStorage::::get(1).unwrap(), SubPools { no_era: UnbondPool { points: 550 + 40 + 10, balance: 550 + 40 + 5 }, with_era: Default::default() @@ -1736,11 +1696,11 @@ mod withdraw_unbonded_other { // Then assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap().no_era, + SubPoolsStorage::::get(1).unwrap().no_era, UnbondPool { points: 40 + 10, balance: 40 + 5 + 5 } ); assert_eq!(Balances::free_balance(&550), 550 + 545); - assert_eq!(Balances::free_balance(&PRIMARY_ACCOUNT), 50); + assert_eq!(Balances::free_balance(&default_bonded_account()), 50); assert!(!Delegators::::contains_key(550)); // When @@ -1748,11 +1708,11 @@ mod withdraw_unbonded_other { // Then assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap().no_era, + SubPoolsStorage::::get(1).unwrap().no_era, UnbondPool { points: 10, balance: 10 } ); assert_eq!(Balances::free_balance(&40), 40 + 40); - assert_eq!(Balances::free_balance(&PRIMARY_ACCOUNT), 50 - 40); + assert_eq!(Balances::free_balance(&default_bonded_account()), 50 - 40); assert!(!Delegators::::contains_key(40)); // When @@ -1760,12 +1720,12 @@ mod withdraw_unbonded_other { // Then assert_eq!(Balances::free_balance(&10), 10 + 10); - assert_eq!(Balances::free_balance(&PRIMARY_ACCOUNT), 0); + assert_eq!(Balances::free_balance(&default_bonded_account()), 0); assert!(!Delegators::::contains_key(10)); // Pools are removed from storage because the depositor left - assert!(!SubPoolsStorage::::contains_key(&PRIMARY_ACCOUNT),); - assert!(!RewardPools::::contains_key(&PRIMARY_ACCOUNT),); - assert!(!BondedPools::::contains_key(&PRIMARY_ACCOUNT),); + assert!(!SubPoolsStorage::::contains_key(1),); + assert!(!RewardPools::::contains_key(1),); + assert!(!BondedPools::::contains_key(1),); }); } @@ -1777,17 +1737,17 @@ mod withdraw_unbonded_other { .add_delegators(vec![(40, 40), (550, 550)]) .build_and_execute(|| { // Given - StakingMock::set_bonded_balance(PRIMARY_ACCOUNT, 100); // slash bonded balance - Balances::make_free_balance_be(&PRIMARY_ACCOUNT, 100); - assert_eq!(StakingMock::locked_balance(&PRIMARY_ACCOUNT), Some(100)); + StakingMock::set_bonded_balance(default_bonded_account(), 100); // slash bonded balance + Balances::make_free_balance_be(&default_bonded_account(), 100); + assert_eq!(StakingMock::locked_balance(&default_bonded_account()), Some(100)); assert_ok!(Pools::unbond_other(Origin::signed(40), 40)); assert_ok!(Pools::unbond_other(Origin::signed(550), 550)); - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Destroying).unwrap(); + unsafe_set_state(1, PoolState::Destroying).unwrap(); assert_ok!(Pools::unbond_other(Origin::signed(10), 10)); SubPoolsStorage::::insert( - PRIMARY_ACCOUNT, + 1, SubPools { no_era: Default::default(), with_era: sub_pools_with_era! { 0 + 3 => UnbondPool { points: 600, balance: 100 }}, @@ -1800,11 +1760,11 @@ mod withdraw_unbonded_other { // Then assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap().with_era, + SubPoolsStorage::::get(&1).unwrap().with_era, sub_pools_with_era! { 0 + 3 => UnbondPool { points: 560, balance: 94 }} ); assert_eq!(Balances::free_balance(&40), 40 + 6); - assert_eq!(Balances::free_balance(&PRIMARY_ACCOUNT), 94); + assert_eq!(Balances::free_balance(&default_bonded_account()), 94); assert!(!Delegators::::contains_key(40)); // When @@ -1812,12 +1772,12 @@ mod withdraw_unbonded_other { // Then assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap().with_era, + SubPoolsStorage::::get(&1).unwrap().with_era, sub_pools_with_era! { 0 + 3 => UnbondPool { points: 10, balance: 2 }} ); assert_eq!(Balances::free_balance(&550), 550 + 92); // The account was dusted because it went below ED(5) - assert_eq!(Balances::free_balance(&PRIMARY_ACCOUNT), 0); + assert_eq!(Balances::free_balance(&default_bonded_account()), 0); assert!(!Delegators::::contains_key(550)); // When @@ -1825,12 +1785,12 @@ mod withdraw_unbonded_other { // Then assert_eq!(Balances::free_balance(&10), 10 + 0); - assert_eq!(Balances::free_balance(&PRIMARY_ACCOUNT), 0); + assert_eq!(Balances::free_balance(&default_bonded_account()), 0); assert!(!Delegators::::contains_key(10)); // Pools are removed from storage because the depositor left - assert!(!SubPoolsStorage::::contains_key(&PRIMARY_ACCOUNT),); - assert!(!RewardPools::::contains_key(&PRIMARY_ACCOUNT),); - assert!(!BondedPools::::contains_key(&PRIMARY_ACCOUNT),); + assert!(!SubPoolsStorage::::contains_key(1),); + assert!(!RewardPools::::contains_key(1),); + assert!(!BondedPools::::contains_key(1),); }); } @@ -1840,14 +1800,14 @@ mod withdraw_unbonded_other { // Given assert_eq!(Balances::minimum_balance(), 5); assert_eq!(Balances::free_balance(&10), 10); - assert_eq!(Balances::free_balance(&PRIMARY_ACCOUNT), 10); - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Destroying).unwrap(); + assert_eq!(Balances::free_balance(&default_bonded_account()), 10); + unsafe_set_state(1, PoolState::Destroying).unwrap(); assert_ok!(Pools::unbond_other(Origin::signed(10), 10)); // Simulate a slash that is not accounted for in the sub pools. - Balances::make_free_balance_be(&PRIMARY_ACCOUNT, 5); + Balances::make_free_balance_be(&default_bonded_account(), 5); assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap().with_era, + SubPoolsStorage::::get(1).unwrap().with_era, //------------------------------balance decrease is not account for sub_pools_with_era! { 0 + 3 => UnbondPool { points: 10, balance: 10 } } ); @@ -1859,7 +1819,7 @@ mod withdraw_unbonded_other { // Then assert_eq!(Balances::free_balance(10), 10 + 5); - assert_eq!(Balances::free_balance(&PRIMARY_ACCOUNT), 0); + assert_eq!(Balances::free_balance(&default_bonded_account()), 0); }); } @@ -1879,7 +1839,7 @@ mod withdraw_unbonded_other { ); let mut delegator = Delegator { - bonded_pool_account: PRIMARY_ACCOUNT, + pool_id: 1, points: 10, reward_pool_total_earnings: 0, unbonding_era: None, @@ -1918,16 +1878,15 @@ mod withdraw_unbonded_other { assert_ok!(Pools::unbond_other(Origin::signed(100), 100)); assert_ok!(Pools::unbond_other(Origin::signed(200), 200)); assert_eq!( - BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(), + BondedPool::::get(1).unwrap(), BondedPool { - points: 10, - state: PoolState::Open, - depositor: 10, - account: PRIMARY_ACCOUNT, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 3, + id: 1, + inner: BondedPoolInner { + points: 10, + state: PoolState::Open, + delegator_counter: 3, + roles: DEFAULT_ROLES + } } ); CurrentEra::set(StakingMock::bonding_duration()); @@ -1939,7 +1898,7 @@ mod withdraw_unbonded_other { ); // Given - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Blocked).unwrap(); + unsafe_set_state(1, PoolState::Blocked).unwrap(); // Cannot kick as a nominator assert_noop!( @@ -1957,10 +1916,7 @@ mod withdraw_unbonded_other { assert_eq!(Balances::free_balance(200), 200 + 200); assert!(!Delegators::::contains_key(100)); assert!(!Delegators::::contains_key(200)); - assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap(), - Default::default() - ); + assert_eq!(SubPoolsStorage::::get(1).unwrap(), Default::default()); }); } @@ -1970,16 +1926,15 @@ mod withdraw_unbonded_other { // Given assert_ok!(Pools::unbond_other(Origin::signed(100), 100)); assert_eq!( - BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(), + BondedPool::::get(1).unwrap(), BondedPool { - points: 10, - state: PoolState::Open, - depositor: 10, - account: PRIMARY_ACCOUNT, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 2, + id: 1, + inner: BondedPoolInner { + points: 10, + state: PoolState::Open, + delegator_counter: 2, + roles: DEFAULT_ROLES, + } } ); CurrentEra::set(StakingMock::bonding_duration()); @@ -1992,15 +1947,12 @@ mod withdraw_unbonded_other { ); // Given - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Destroying).unwrap(); + unsafe_set_state(1, PoolState::Destroying).unwrap(); // Can permissionlesly withdraw a delegator that is not the depositor assert_ok!(Pools::withdraw_unbonded_other(Origin::signed(420), 100, 0)); - assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap(), - Default::default(), - ); + assert_eq!(SubPoolsStorage::::get(1).unwrap(), Default::default(),); assert_eq!(Balances::free_balance(100), 100 + 100); assert!(!Delegators::::contains_key(100)); }); @@ -2018,11 +1970,11 @@ mod withdraw_unbonded_other { CurrentEra::set(current_era); assert_ok!(Pools::unbond_other(Origin::signed(200), 200)); - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Destroying).unwrap(); + unsafe_set_state(1, PoolState::Destroying).unwrap(); assert_ok!(Pools::unbond_other(Origin::signed(10), 10)); assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap(), + SubPoolsStorage::::get(1).unwrap(), SubPools { no_era: Default::default(), with_era: sub_pools_with_era! { @@ -2044,7 +1996,7 @@ mod withdraw_unbonded_other { // Given assert_ok!(Pools::withdraw_unbonded_other(Origin::signed(420), 100, 0)); assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap(), + SubPoolsStorage::::get(1).unwrap(), SubPools { no_era: Default::default(), with_era: sub_pools_with_era! { @@ -2063,7 +2015,7 @@ mod withdraw_unbonded_other { // Given assert_ok!(Pools::withdraw_unbonded_other(Origin::signed(420), 200, 0)); assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap(), + SubPoolsStorage::::get(1).unwrap(), SubPools { no_era: Default::default(), with_era: sub_pools_with_era! { @@ -2077,9 +2029,9 @@ mod withdraw_unbonded_other { assert!(!Delegators::::contains_key(10)); assert_eq!(Balances::free_balance(10), 10 + 10); // Pools are removed from storage because the depositor left - assert!(!SubPoolsStorage::::contains_key(&PRIMARY_ACCOUNT),); - assert!(!RewardPools::::contains_key(&PRIMARY_ACCOUNT),); - assert!(!BondedPools::::contains_key(&PRIMARY_ACCOUNT),); + assert!(!SubPoolsStorage::::contains_key(1)); + assert!(!RewardPools::::contains_key(1)); + assert!(!BondedPools::::contains_key(1)); }); } @@ -2088,7 +2040,7 @@ mod withdraw_unbonded_other { ExtBuilder::default().add_delegators(vec![(100, 100)]).build_and_execute(|| { // Given assert_ok!(Pools::unbond_other(Origin::signed(100), 100)); - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Destroying).unwrap(); + unsafe_set_state(1, PoolState::Destroying).unwrap(); assert_ok!(Pools::unbond_other(Origin::signed(10), 10)); // Skip ahead to an era where the `with_era` pools can get merged into the `no_era` // pool. @@ -2096,12 +2048,11 @@ mod withdraw_unbonded_other { CurrentEra::set(current_era); // Simulate some other withdraw that caused the pool to merge - let sub_pools = SubPoolsStorage::::get(&PRIMARY_ACCOUNT) - .unwrap() - .maybe_merge_pools(current_era + 3); - SubPoolsStorage::::insert(&PRIMARY_ACCOUNT, sub_pools); + let sub_pools = + SubPoolsStorage::::get(1).unwrap().maybe_merge_pools(current_era + 3); + SubPoolsStorage::::insert(1, sub_pools); assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap(), + SubPoolsStorage::::get(1).unwrap(), SubPools { no_era: UnbondPool { points: 100 + 10, balance: 100 + 10 }, with_era: Default::default(), @@ -2117,7 +2068,7 @@ mod withdraw_unbonded_other { // Given assert_ok!(Pools::withdraw_unbonded_other(Origin::signed(420), 100, 0)); assert_eq!( - SubPoolsStorage::::get(&PRIMARY_ACCOUNT).unwrap(), + SubPoolsStorage::::get(1).unwrap(), SubPools { no_era: UnbondPool { points: 10, balance: 10 }, with_era: Default::default(), @@ -2129,9 +2080,9 @@ mod withdraw_unbonded_other { assert!(!Delegators::::contains_key(10)); assert_eq!(Balances::free_balance(10), 10 + 10); // Pools are removed from storage because the depositor left - assert!(!SubPoolsStorage::::contains_key(&PRIMARY_ACCOUNT)); - assert!(!RewardPools::::contains_key(&PRIMARY_ACCOUNT)); - assert!(!BondedPools::::contains_key(&PRIMARY_ACCOUNT)); + assert!(!SubPoolsStorage::::contains_key(1)); + assert!(!RewardPools::::contains_key(1)); + assert!(!BondedPools::::contains_key(1)); }); } } @@ -2142,12 +2093,13 @@ mod create { #[test] fn create_works() { ExtBuilder::default().build_and_execute(|| { - let stash = 3548237456; + // next pool id is 2. + let next_pool_stash = Pools::create_bonded_account(2); - assert!(!BondedPools::::contains_key(1)); - assert!(!RewardPools::::contains_key(1)); + assert!(!BondedPools::::contains_key(2)); + assert!(!RewardPools::::contains_key(2)); assert!(!Delegators::::contains_key(11)); - assert_eq!(StakingMock::bonded_balance(&stash), None); + assert_eq!(StakingMock::bonded_balance(&next_pool_stash), None); Balances::make_free_balance_be(&11, StakingMock::minimum_bond()); assert_ok!(Pools::create( @@ -2162,33 +2114,39 @@ mod create { assert_eq!( Delegators::::get(11).unwrap(), Delegator { - bonded_pool_account: stash, + pool_id: 2, points: StakingMock::minimum_bond(), reward_pool_total_earnings: Zero::zero(), unbonding_era: None } ); assert_eq!( - BondedPool::::get(&stash).unwrap(), + BondedPool::::get(2).unwrap(), BondedPool { - points: StakingMock::minimum_bond(), - depositor: 11, - state: PoolState::Open, - account: stash.clone(), - root: 123, - nominator: 456, - state_toggler: 789, - delegator_counter: 1, + id: 2, + inner: BondedPoolInner { + points: StakingMock::minimum_bond(), + delegator_counter: 1, + state: PoolState::Open, + roles: PoolRoles { + depositor: 11, + root: 123, + nominator: 456, + state_toggler: 789 + } + } } ); - assert_eq!(StakingMock::bonded_balance(&stash).unwrap(), StakingMock::minimum_bond()); assert_eq!( - RewardPools::::get(stash).unwrap(), + StakingMock::bonded_balance(&next_pool_stash).unwrap(), + StakingMock::minimum_bond() + ); + assert_eq!( + RewardPools::::get(2).unwrap(), RewardPool { balance: Zero::zero(), points: U256::zero(), total_earnings: Zero::zero(), - account: 1657614948 } ); }); @@ -2197,10 +2155,6 @@ mod create { #[test] fn create_errors_correctly() { ExtBuilder::default().build_and_execute_no_checks(|| { - // assert_noop!( - // Pools::create(Origin::signed(10), 420, 123, 456, 789), - // Error::::AccountBelongsToOtherPool - // ); assert_noop!( Pools::create(Origin::signed(10), 420, 123, 456, 789), Error::::AccountBelongsToOtherPool @@ -2227,14 +2181,13 @@ mod create { // Given BondedPool:: { - depositor: 10, - state: PoolState::Open, - points: 10, - account: 123, - root: 900, - nominator: 901, - state_toggler: 902, - delegator_counter: 1, + id: 2, + inner: BondedPoolInner { + state: PoolState::Open, + points: 10, + delegator_counter: 1, + roles: DEFAULT_ROLES, + }, } .put(); assert_eq!(MaxPools::::get(), Some(2)); @@ -2268,22 +2221,22 @@ mod nominate { ExtBuilder::default().build_and_execute(|| { // Depositor can't nominate assert_noop!( - Pools::nominate(Origin::signed(10), PRIMARY_ACCOUNT, vec![21]), + Pools::nominate(Origin::signed(10), 1, vec![21]), Error::::NotNominator ); // State toggler can't nominate assert_noop!( - Pools::nominate(Origin::signed(902), PRIMARY_ACCOUNT, vec![21]), + Pools::nominate(Origin::signed(902), 1, vec![21]), Error::::NotNominator ); // Root can nominate - assert_ok!(Pools::nominate(Origin::signed(900), PRIMARY_ACCOUNT, vec![21])); + assert_ok!(Pools::nominate(Origin::signed(900), 1, vec![21])); assert_eq!(Nominations::get(), vec![21]); // Nominator can nominate - assert_ok!(Pools::nominate(Origin::signed(901), PRIMARY_ACCOUNT, vec![31])); + assert_ok!(Pools::nominate(Origin::signed(901), 1, vec![31])); assert_eq!(Nominations::get(), vec![31]); // Can't nominate for a pool that doesn't exist @@ -2302,89 +2255,61 @@ mod set_state_other { fn set_state_other_works() { ExtBuilder::default().build_and_execute(|| { // Given - assert_ok!(BondedPool::::get(&PRIMARY_ACCOUNT).unwrap().ok_to_be_open()); + assert_ok!(BondedPool::::get(1).unwrap().ok_to_be_open()); // Only the root and state toggler can change the state when the pool is ok to be open. assert_noop!( - Pools::set_state_other(Origin::signed(10), PRIMARY_ACCOUNT, PoolState::Blocked), + Pools::set_state_other(Origin::signed(10), 1, PoolState::Blocked), Error::::CanNotChangeState ); assert_noop!( - Pools::set_state_other(Origin::signed(901), PRIMARY_ACCOUNT, PoolState::Blocked), + Pools::set_state_other(Origin::signed(901), 1, PoolState::Blocked), Error::::CanNotChangeState ); // Root can change state - assert_ok!(Pools::set_state_other( - Origin::signed(900), - PRIMARY_ACCOUNT, - PoolState::Blocked - )); - assert_eq!( - BondedPool::::get(&PRIMARY_ACCOUNT).unwrap().state, - PoolState::Blocked - ); + assert_ok!(Pools::set_state_other(Origin::signed(900), 1, PoolState::Blocked)); + assert_eq!(BondedPool::::get(1).unwrap().state, PoolState::Blocked); // State toggler can change state - assert_ok!(Pools::set_state_other( - Origin::signed(902), - PRIMARY_ACCOUNT, - PoolState::Destroying - )); - assert_eq!( - BondedPool::::get(&PRIMARY_ACCOUNT).unwrap().state, - PoolState::Destroying - ); + assert_ok!(Pools::set_state_other(Origin::signed(902), 1, PoolState::Destroying)); + assert_eq!(BondedPool::::get(1).unwrap().state, PoolState::Destroying); // If the pool is destroying, then no one can set state assert_noop!( - Pools::set_state_other(Origin::signed(900), PRIMARY_ACCOUNT, PoolState::Blocked), + Pools::set_state_other(Origin::signed(900), 1, PoolState::Blocked), Error::::CanNotChangeState ); assert_noop!( - Pools::set_state_other(Origin::signed(902), PRIMARY_ACCOUNT, PoolState::Blocked), + Pools::set_state_other(Origin::signed(902), 1, PoolState::Blocked), Error::::CanNotChangeState ); // If the pool is not ok to be open, then anyone can set it to destroying // Given - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Open).unwrap(); - let mut bonded_pool = BondedPool::::get(&PRIMARY_ACCOUNT).unwrap(); + unsafe_set_state(1, PoolState::Open).unwrap(); + let mut bonded_pool = BondedPool::::get(1).unwrap(); bonded_pool.points = 100; bonded_pool.put(); // When - assert_ok!(Pools::set_state_other( - Origin::signed(11), - PRIMARY_ACCOUNT, - PoolState::Destroying - )); + assert_ok!(Pools::set_state_other(Origin::signed(11), 1, PoolState::Destroying)); // Then - assert_eq!( - BondedPool::::get(&PRIMARY_ACCOUNT).unwrap().state, - PoolState::Destroying - ); + assert_eq!(BondedPool::::get(1).unwrap().state, PoolState::Destroying); // Given - Balances::make_free_balance_be(&PRIMARY_ACCOUNT, Balance::max_value() / 10); - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Open).unwrap(); + Balances::make_free_balance_be(&default_bonded_account(), Balance::max_value() / 10); + unsafe_set_state(1, PoolState::Open).unwrap(); // When - assert_ok!(Pools::set_state_other( - Origin::signed(11), - PRIMARY_ACCOUNT, - PoolState::Destroying - )); + assert_ok!(Pools::set_state_other(Origin::signed(11), 1, PoolState::Destroying)); // Then - assert_eq!( - BondedPool::::get(&PRIMARY_ACCOUNT).unwrap().state, - PoolState::Destroying - ); + assert_eq!(BondedPool::::get(1).unwrap().state, PoolState::Destroying); // If the pool is not ok to be open, it cannot be permissionleslly set to a state that // isn't destroying - unsafe_set_state(&PRIMARY_ACCOUNT, PoolState::Open).unwrap(); + unsafe_set_state(1, PoolState::Open).unwrap(); assert_noop!( - Pools::set_state_other(Origin::signed(11), PRIMARY_ACCOUNT, PoolState::Blocked), + Pools::set_state_other(Origin::signed(11), 1, PoolState::Blocked), Error::::CanNotChangeState ); }); @@ -2398,28 +2323,28 @@ mod set_metadata { fn set_metadata_works() { ExtBuilder::default().build_and_execute(|| { // Root can set metadata - assert_ok!(Pools::set_metadata(Origin::signed(900), PRIMARY_ACCOUNT, vec![1, 1])); - assert_eq!(Metadata::::get(PRIMARY_ACCOUNT), vec![1, 1]); + assert_ok!(Pools::set_metadata(Origin::signed(900), 1, vec![1, 1])); + assert_eq!(Metadata::::get(1), vec![1, 1]); // State toggler can set metadata - assert_ok!(Pools::set_metadata(Origin::signed(902), PRIMARY_ACCOUNT, vec![2, 2])); - assert_eq!(Metadata::::get(PRIMARY_ACCOUNT), vec![2, 2]); + assert_ok!(Pools::set_metadata(Origin::signed(902), 1, vec![2, 2])); + assert_eq!(Metadata::::get(1), vec![2, 2]); // Depositor can't set metadata assert_noop!( - Pools::set_metadata(Origin::signed(10), PRIMARY_ACCOUNT, vec![3, 3]), + Pools::set_metadata(Origin::signed(10), 1, vec![3, 3]), Error::::DoesNotHavePermission ); // Nominator can't set metadata assert_noop!( - Pools::set_metadata(Origin::signed(901), PRIMARY_ACCOUNT, vec![3, 3]), + Pools::set_metadata(Origin::signed(901), 1, vec![3, 3]), Error::::DoesNotHavePermission ); // Metadata cannot be longer than `MaxMetadataLen` assert_noop!( - Pools::set_metadata(Origin::signed(900), PRIMARY_ACCOUNT, vec![1, 1, 1]), + Pools::set_metadata(Origin::signed(900), 1, vec![1, 1, 1]), Error::::MetadataExceedsMaxLen ); });