diff --git a/Cargo.lock b/Cargo.lock index 5a28aa85de..f2d46b21b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2117,6 +2117,7 @@ dependencies = [ "sp-std", "sp-transaction-pool", "sp-version", + "strum 0.19.2", "substrate-wasm-builder-runner", ] @@ -3301,6 +3302,8 @@ dependencies = [ "parity-scale-codec", "serde", "sp-runtime", + "strum 0.19.2", + "strum_macros 0.19.2", ] [[package]] @@ -3529,7 +3532,6 @@ dependencies = [ "frame-system", "pallet-balances", "pallet-common", - "pallet-content-working-group", "pallet-governance", "pallet-hiring", "pallet-membership", @@ -3541,8 +3543,6 @@ dependencies = [ "pallet-staking-reward-curve", "pallet-timestamp", "pallet-token-mint", - "pallet-versioned-store", - "pallet-versioned-store-permissions", "pallet-working-group", "parity-scale-codec", "serde", @@ -3552,6 +3552,7 @@ dependencies = [ "sp-runtime", "sp-staking", "sp-std", + "strum 0.19.2", ] [[package]] @@ -6459,7 +6460,7 @@ dependencies = [ "lazy_static", "sp-core", "sp-runtime", - "strum", + "strum 0.16.0", ] [[package]] @@ -6802,9 +6803,15 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6138f8f88a16d90134763314e3fc76fa3ed6a7db4725d6acf9a3ef95a3188d22" dependencies = [ - "strum_macros", + "strum_macros 0.16.0", ] +[[package]] +name = "strum" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3924a58d165da3b7b2922c667ab0673c7b5fd52b5c19ea3442747bcb3cd15abe" + [[package]] name = "strum_macros" version = "0.16.0" @@ -6817,6 +6824,18 @@ dependencies = [ "syn 1.0.17", ] +[[package]] +name = "strum_macros" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2ab682ecdcae7f5f45ae85cd7c1e6c8e68ea42c8a612d47fedf831c037146a" +dependencies = [ + "heck", + "proc-macro2", + "quote 1.0.7", + "syn 1.0.17", +] + [[package]] name = "substrate-bip39" version = "0.4.1" diff --git a/node/src/chain_spec/mod.rs b/node/src/chain_spec/mod.rs index 7fdff8fff6..17f86de95a 100644 --- a/node/src/chain_spec/mod.rs +++ b/node/src/chain_spec/mod.rs @@ -352,12 +352,6 @@ pub fn testnet_genesis( .set_election_parameters_proposal_voting_period, set_election_parameters_proposal_grace_period: cpcp .set_election_parameters_proposal_grace_period, - set_content_working_group_mint_capacity_proposal_voting_period: cpcp - .set_content_working_group_mint_capacity_proposal_voting_period, - set_content_working_group_mint_capacity_proposal_grace_period: cpcp - .set_content_working_group_mint_capacity_proposal_grace_period, - set_lead_proposal_voting_period: cpcp.set_lead_proposal_voting_period, - set_lead_proposal_grace_period: cpcp.set_lead_proposal_grace_period, spending_proposal_voting_period: cpcp.spending_proposal_voting_period, spending_proposal_grace_period: cpcp.spending_proposal_grace_period, add_working_group_opening_proposal_voting_period: cpcp @@ -373,9 +367,9 @@ pub fn testnet_genesis( fill_working_group_leader_opening_proposal_grace_period: cpcp .fill_working_group_leader_opening_proposal_grace_period, set_working_group_mint_capacity_proposal_voting_period: cpcp - .set_content_working_group_mint_capacity_proposal_voting_period, + .set_working_group_mint_capacity_proposal_voting_period, set_working_group_mint_capacity_proposal_grace_period: cpcp - .set_content_working_group_mint_capacity_proposal_grace_period, + .set_working_group_mint_capacity_proposal_grace_period, decrease_working_group_leader_stake_proposal_voting_period: cpcp .decrease_working_group_leader_stake_proposal_voting_period, decrease_working_group_leader_stake_proposal_grace_period: cpcp diff --git a/runtime-modules/common/Cargo.toml b/runtime-modules/common/Cargo.toml index b4c98bd9a7..4bc8489248 100644 --- a/runtime-modules/common/Cargo.toml +++ b/runtime-modules/common/Cargo.toml @@ -6,6 +6,8 @@ edition = '2018' [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } +strum = {version = "0.19", optional = true} +strum_macros = {version = "0.19", optional = true} codec = { package = 'parity-scale-codec', version = '1.3.1', default-features = false, features = ['derive'] } sp-runtime = { package = 'sp-runtime', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'} frame-support = { package = 'frame-support', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'} @@ -16,6 +18,8 @@ pallet-timestamp = { package = 'pallet-timestamp', default-features = false, git default = ['std'] std = [ 'serde', + 'strum', + 'strum_macros', 'codec/std', 'sp-runtime/std', 'frame-support/std', diff --git a/runtime-modules/common/src/working_group.rs b/runtime-modules/common/src/working_group.rs index 23c58632b7..bb3b2a0935 100644 --- a/runtime-modules/common/src/working_group.rs +++ b/runtime-modules/common/src/working_group.rs @@ -1,9 +1,11 @@ use codec::{Decode, Encode}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "std")] +use strum_macros::EnumIter; /// Defines well-known working groups. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, EnumIter))] #[derive(Encode, Decode, Clone, PartialEq, Eq, Copy, Debug)] pub enum WorkingGroup { /* Reserved @@ -12,4 +14,6 @@ pub enum WorkingGroup { */ /// Storage working group: working_group::Instance2. Storage, + /// Storage working group: working_group::Instance3. + Content, } diff --git a/runtime-modules/content-directory/src/lib.rs b/runtime-modules/content-directory/src/lib.rs index 2caa1f56c4..97b35d7bf5 100755 --- a/runtime-modules/content-directory/src/lib.rs +++ b/runtime-modules/content-directory/src/lib.rs @@ -2554,9 +2554,9 @@ impl Module { maximum_entities_count: T::EntityId, default_entity_creation_voucher_upper_bound: T::EntityId, ) -> Result<(), Error> { - // Ensure `per_controller_entities_creation_limit` does not exceed + // Ensure default_entity_creation_voucher_upper_bound does not exceed default_entity_creation_voucher_upper_bound ensure!( - default_entity_creation_voucher_upper_bound < maximum_entities_count, + default_entity_creation_voucher_upper_bound <= maximum_entities_count, Error::::PerControllerEntitiesCreationLimitExceedsOverallLimit ); diff --git a/runtime-modules/governance/src/mock.rs b/runtime-modules/governance/src/mock.rs index 88076e52f7..4c2f6a5674 100644 --- a/runtime-modules/governance/src/mock.rs +++ b/runtime-modules/governance/src/mock.rs @@ -71,7 +71,7 @@ impl election::Trait for Test { } impl membership::Trait for Test { type Event = (); - type MemberId = u32; + type MemberId = u64; type SubscriptionId = u32; type PaidTermId = u32; type ActorId = u32; diff --git a/runtime-modules/membership/src/mock.rs b/runtime-modules/membership/src/mock.rs index d121d1797e..0a7a6c629d 100644 --- a/runtime-modules/membership/src/mock.rs +++ b/runtime-modules/membership/src/mock.rs @@ -80,7 +80,7 @@ impl GovernanceCurrency for Test { impl Trait for Test { type Event = (); - type MemberId = u32; + type MemberId = u64; type PaidTermId = u32; type SubscriptionId = u32; type ActorId = u32; diff --git a/runtime-modules/membership/src/tests.rs b/runtime-modules/membership/src/tests.rs index 650d40bdd0..9d4db399ab 100644 --- a/runtime-modules/membership/src/tests.rs +++ b/runtime-modules/membership/src/tests.rs @@ -5,7 +5,7 @@ use super::mock::*; use frame_support::*; -fn get_membership_by_id(member_id: u32) -> crate::Membership { +fn get_membership_by_id(member_id: u64) -> crate::Membership { if >::contains_key(member_id) { Members::membership(member_id) } else { diff --git a/runtime-modules/proposals/codex/Cargo.toml b/runtime-modules/proposals/codex/Cargo.toml index d921ac5136..a873dd75bf 100644 --- a/runtime-modules/proposals/codex/Cargo.toml +++ b/runtime-modules/proposals/codex/Cargo.toml @@ -21,7 +21,6 @@ governance = { package = 'pallet-governance', default-features = false, path = ' hiring = { package = 'pallet-hiring', default-features = false, path = '../../hiring'} minting = { package = 'pallet-token-mint', default-features = false, path = '../../token-minting'} working-group = { package = 'pallet-working-group', default-features = false, path = '../../working-group'} -content-working-group = { package = 'pallet-content-working-group', default-features = false, path = '../../content-working-group'} common = { package = 'pallet-common', default-features = false, path = '../../common'} proposals-engine = { package = 'pallet-proposals-engine', default-features = false, path = '../engine'} proposals-discussion = { package = 'pallet-proposals-discussion', default-features = false, path = '../discussion'} @@ -32,8 +31,7 @@ sp-core = { package = 'sp-core', default-features = false, git = 'https://github sp-staking = { package = 'sp-staking', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'} pallet-staking-reward-curve = { package = 'pallet-staking-reward-curve', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'} recurring-rewards = { package = 'pallet-recurring-reward', default-features = false, path = '../../recurring-reward'} -versioned-store = { package = 'pallet-versioned-store', default-features = false, path = '../../versioned-store'} -versioned-store-permissions = { package = 'pallet-versioned-store-permissions', default-features = false, path = '../../versioned-store-permissions'} +strum = {version = "0.19", default-features = false} [features] default = ['std'] @@ -53,7 +51,6 @@ std = [ 'governance/std', 'hiring/std', 'minting/std', - 'content-working-group/std', 'working-group/std', 'common/std', 'proposals-engine/std', diff --git a/runtime-modules/proposals/codex/src/lib.rs b/runtime-modules/proposals/codex/src/lib.rs index 891aed9817..42bac53fb2 100644 --- a/runtime-modules/proposals/codex/src/lib.rs +++ b/runtime-modules/proposals/codex/src/lib.rs @@ -21,10 +21,6 @@ //! - [create_set_election_parameters_proposal](./struct.Module.html#method.create_set_election_parameters_proposal) //! - [create_spending_proposal](./struct.Module.html#method.create_spending_proposal) //! -//! ### Content working group proposals -//! - [create_set_lead_proposal](./struct.Module.html#method.create_set_lead_proposal) -//! - [create_set_content_working_group_mint_capacity_proposal](./struct.Module.html#method.create_set_content_working_group_mint_capacity_proposal) -//! //! ### Working group proposals //! - [create_add_working_group_leader_opening_proposal](./struct.Module.html#method.create_add_working_group_leader_opening_proposal) //! - [create_begin_review_working_group_leader_applications_proposal](./struct.Module.html#method.create_begin_review_working_group_leader_applications_proposal) @@ -86,8 +82,6 @@ pub use proposal_types::{ProposalDetails, ProposalDetailsOf, ProposalEncoder}; // 'Set working group mint capacity' proposal limit const WORKING_GROUP_MINT_CAPACITY_MAX_VALUE: u32 = 5_000_000; -// 'Set content working group mint capacity' proposal limit -const CONTENT_WORKING_GROUP_MINT_CAPACITY_MAX_VALUE: u32 = 1_000_000; // Max allowed value for 'spending' proposal const MAX_SPENDING_PROPOSAL_VALUE: u32 = 5_000_000_u32; // Max validator count for the 'set validator count' proposal @@ -145,7 +139,7 @@ pub trait Trait: + proposals_discussion::Trait + membership::Trait + governance::election::Trait - + content_working_group::Trait + + hiring::Trait + staking::Trait { /// Defines max allowed text proposal length. @@ -294,22 +288,6 @@ decl_storage! { /// Grace period for the 'text' proposal pub TextProposalGracePeriod get(fn text_proposal_grace_period) config(): T::BlockNumber; - /// Voting period for the 'set content working group mint capacity' proposal - pub SetContentWorkingGroupMintCapacityProposalVotingPeriod get(fn set_content_working_group_mint_capacity_proposal_voting_period) - config(): T::BlockNumber; - - /// Grace period for the 'set content working group mint capacity' proposal - pub SetContentWorkingGroupMintCapacityProposalGracePeriod get(fn set_content_working_group_mint_capacity_proposal_grace_period) - config(): T::BlockNumber; - - /// Voting period for the 'set lead' proposal - pub SetLeadProposalVotingPeriod get(fn set_lead_proposal_voting_period) - config(): T::BlockNumber; - - /// Grace period for the 'set lead' proposal - pub SetLeadProposalGracePeriod get(fn set_lead_proposal_grace_period) - config(): T::BlockNumber; - /// Voting period for the 'spending' proposal pub SpendingProposalVotingPeriod get(fn spending_proposal_voting_period) config(): T::BlockNumber; @@ -477,37 +455,6 @@ decl_module! { Self::create_proposal(params)?; } - /// Create 'Set content working group mint capacity' proposal type. - /// This proposal uses `set_mint_capacity()` extrinsic from the `content-working-group` module. - #[weight = 10_000_000] // TODO: adjust weight - pub fn create_set_content_working_group_mint_capacity_proposal( - origin, - member_id: MemberId, - title: Vec, - description: Vec, - stake_balance: Option>, - mint_balance: BalanceOfMint, - ) { - ensure!( - mint_balance <= >::from(CONTENT_WORKING_GROUP_MINT_CAPACITY_MAX_VALUE), - Error::::InvalidContentWorkingGroupMintCapacity - ); - - let proposal_details = ProposalDetails::SetContentWorkingGroupMintCapacity(mint_balance); - let params = CreateProposalParameters{ - origin, - member_id, - title, - description, - stake_balance, - proposal_details: proposal_details.clone(), - proposal_parameters: proposal_types::parameters::set_content_working_group_mint_capacity_proposal::(), - proposal_code: T::ProposalEncoder::encode_proposal(proposal_details) - }; - - Self::create_proposal(params)?; - } - /// Create 'Spending' proposal type. /// This proposal uses `spend_from_council_mint()` extrinsic from the `governance::council` module. #[weight = 10_000_000] // TODO: adjust weight @@ -541,39 +488,6 @@ decl_module! { Self::create_proposal(params)?; } - /// Create 'Set lead' proposal type. - /// This proposal uses `replace_lead()` extrinsic from the `content_working_group` module. - #[weight = 10_000_000] // TODO: adjust weight - pub fn create_set_lead_proposal( - origin, - member_id: MemberId, - title: Vec, - description: Vec, - stake_balance: Option>, - new_lead: Option<(T::MemberId, T::AccountId)> - ) { - if let Some(lead) = new_lead.clone() { - let account_id = lead.1; - ensure!( - !>::is_councilor(&account_id), - Error::::InvalidSetLeadParameterCannotBeCouncilor - ); - } - let proposal_details = ProposalDetails::SetLead(new_lead); - let params = CreateProposalParameters{ - origin, - member_id, - title, - description, - stake_balance, - proposal_details: proposal_details.clone(), - proposal_parameters: proposal_types::parameters::set_lead_proposal::(), - proposal_code: T::ProposalEncoder::encode_proposal(proposal_details) - }; - - Self::create_proposal(params)?; - } - /// Create 'Evict storage provider' proposal type. /// This proposal uses `set_validator_count()` extrinsic from the Substrate `staking` module. #[weight = 10_000_000] // TODO: adjust weight @@ -1063,18 +977,6 @@ impl Module { >::put(T::BlockNumber::from( p.set_election_parameters_proposal_grace_period, )); - >::put(T::BlockNumber::from( - p.set_content_working_group_mint_capacity_proposal_voting_period, - )); - >::put(T::BlockNumber::from( - p.set_content_working_group_mint_capacity_proposal_grace_period, - )); - >::put(T::BlockNumber::from( - p.set_lead_proposal_voting_period, - )); - >::put(T::BlockNumber::from( - p.set_lead_proposal_grace_period, - )); >::put(T::BlockNumber::from( p.spending_proposal_voting_period, )); diff --git a/runtime-modules/proposals/codex/src/proposal_types/mod.rs b/runtime-modules/proposals/codex/src/proposal_types/mod.rs index 8145cd467c..1980963189 100644 --- a/runtime-modules/proposals/codex/src/proposal_types/mod.rs +++ b/runtime-modules/proposals/codex/src/proposal_types/mod.rs @@ -22,7 +22,6 @@ pub type ProposalDetailsOf = ProposalDetails< crate::BalanceOfGovernanceCurrency, ::BlockNumber, ::AccountId, - crate::MemberId, working_group::OpeningId, working_group::ApplicationId, crate::BalanceOf, @@ -37,7 +36,6 @@ pub enum ProposalDetails< CurrencyBalance, BlockNumber, AccountId, - MemberId, OpeningId, ApplicationId, StakeBalance, @@ -55,12 +53,6 @@ pub enum ProposalDetails< /// Balance and destination account for the `spending` proposal Spending(MintedBalance, AccountId), - /// New leader memberId and account_id for the `set lead` proposal - SetLead(Option<(MemberId, AccountId)>), - - /// Balance for the `set content working group mint capacity` proposal - SetContentWorkingGroupMintCapacity(MintedBalance), - /// ********** Deprecated during the Nicaea release. /// It is kept only for backward compatibility in the Pioneer. ********** /// AccountId for the `evict storage provider` proposal @@ -106,7 +98,6 @@ impl< CurrencyBalance, BlockNumber, AccountId, - MemberId, OpeningId, ApplicationId, StakeBalance, @@ -117,7 +108,6 @@ impl< CurrencyBalance, BlockNumber, AccountId, - MemberId, OpeningId, ApplicationId, StakeBalance, @@ -246,12 +236,6 @@ pub struct ProposalsConfigParameters { /// 'Set election parameters' proposal grace period pub set_election_parameters_proposal_grace_period: u32, - /// 'Set content working group mint capacity' proposal voting period - pub set_content_working_group_mint_capacity_proposal_voting_period: u32, - - /// 'Set content working group mint capacity' proposal grace period - pub set_content_working_group_mint_capacity_proposal_grace_period: u32, - /// 'Set lead' proposal voting period pub set_lead_proposal_voting_period: u32, @@ -324,8 +308,6 @@ impl Default for ProposalsConfigParameters { text_proposal_grace_period: 0u32, set_election_parameters_proposal_voting_period: 72000u32, set_election_parameters_proposal_grace_period: 201_601_u32, - set_content_working_group_mint_capacity_proposal_voting_period: 43200u32, - set_content_working_group_mint_capacity_proposal_grace_period: 0u32, set_lead_proposal_voting_period: 43200u32, set_lead_proposal_grace_period: 0u32, spending_proposal_voting_period: 72000u32, @@ -364,8 +346,6 @@ impl ProposalsConfigParameters { text_proposal_grace_period: 0, set_election_parameters_proposal_voting_period: voting_period, set_election_parameters_proposal_grace_period: grace_period, - set_content_working_group_mint_capacity_proposal_voting_period: voting_period, - set_content_working_group_mint_capacity_proposal_grace_period: 0, set_lead_proposal_voting_period: voting_period, set_lead_proposal_grace_period: 0, spending_proposal_voting_period: voting_period, diff --git a/runtime-modules/proposals/codex/src/proposal_types/parameters.rs b/runtime-modules/proposals/codex/src/proposal_types/parameters.rs index 64919efd0b..89cea06e4d 100644 --- a/runtime-modules/proposals/codex/src/proposal_types/parameters.rs +++ b/runtime-modules/proposals/codex/src/proposal_types/parameters.rs @@ -55,21 +55,6 @@ pub(crate) fn set_election_parameters_proposal( } } -// Proposal parameters for the 'Set content working group mint capacity' proposal -pub(crate) fn set_content_working_group_mint_capacity_proposal( -) -> ProposalParameters> { - ProposalParameters { - voting_period: >::set_content_working_group_mint_capacity_proposal_voting_period( - ), - grace_period: >::set_content_working_group_mint_capacity_proposal_grace_period(), - approval_quorum_percentage: 60, - approval_threshold_percentage: 75, - slashing_quorum_percentage: 60, - slashing_threshold_percentage: 80, - required_stake: Some(>::from(50000u32)), - } -} - // Proposal parameters for the 'Spending' proposal pub(crate) fn spending_proposal( ) -> ProposalParameters> { @@ -84,20 +69,6 @@ pub(crate) fn spending_proposal( } } -// Proposal parameters for the 'Set lead' proposal -pub(crate) fn set_lead_proposal( -) -> ProposalParameters> { - ProposalParameters { - voting_period: >::set_lead_proposal_voting_period(), - grace_period: >::set_lead_proposal_grace_period(), - approval_quorum_percentage: 60, - approval_threshold_percentage: 75, - slashing_quorum_percentage: 60, - slashing_threshold_percentage: 80, - required_stake: Some(>::from(50000u32)), - } -} - // Proposal parameters for the 'Add working group leader' proposal pub(crate) fn add_working_group_leader_opening_proposal( ) -> ProposalParameters> { diff --git a/runtime-modules/proposals/codex/src/tests/mock.rs b/runtime-modules/proposals/codex/src/tests/mock.rs index 071e58a4ba..70e799bf78 100644 --- a/runtime-modules/proposals/codex/src/tests/mock.rs +++ b/runtime-modules/proposals/codex/src/tests/mock.rs @@ -154,8 +154,24 @@ impl governance::election::Trait for Test { type CouncilElected = (); } -impl content_working_group::Trait for Test { +// The content directory working group instance alias. +pub type ContentDirectoryWorkingGroupInstance = working_group::Instance3; + +// The storage working group instance alias. +pub type StorageWorkingGroupInstance = working_group::Instance2; + +parameter_types! { + pub const MaxWorkerNumberLimit: u32 = 100; +} + +impl working_group::Trait for Test { type Event = (); + type MaxWorkerNumberLimit = MaxWorkerNumberLimit; +} + +impl working_group::Trait for Test { + type Event = (); + type MaxWorkerNumberLimit = MaxWorkerNumberLimit; } impl recurring_rewards::Trait for Test { @@ -164,16 +180,6 @@ impl recurring_rewards::Trait for Test { type RewardRelationshipId = u64; } -impl versioned_store_permissions::Trait for Test { - type Credential = u64; - type CredentialChecker = (); - type CreateClassPermissionsChecker = (); -} - -impl versioned_store::Trait for Test { - type Event = (); -} - impl hiring::Trait for Test { type OpeningId = u64; type ApplicationId = u64; diff --git a/runtime-modules/proposals/codex/src/tests/mod.rs b/runtime-modules/proposals/codex/src/tests/mod.rs index a11990f683..f8fecaedd9 100644 --- a/runtime-modules/proposals/codex/src/tests/mod.rs +++ b/runtime-modules/proposals/codex/src/tests/mod.rs @@ -16,6 +16,8 @@ use crate::*; use crate::{BalanceOf, Error, ProposalDetails}; pub use mock::*; +use strum::IntoEnumIterator; + pub(crate) fn increase_total_balance_issuance(balance: u64) { increase_total_balance_issuance_using_account_id(999, balance); } @@ -40,7 +42,7 @@ where invalid_stake_call: InvalidStakeCall, successful_call: SuccessfulCall, proposal_parameters: ProposalParameters, - proposal_details: ProposalDetails, + proposal_details: ProposalDetails, } impl @@ -471,78 +473,6 @@ fn create_set_election_parameters_call_fails_with_incorrect_parameters() { }); } -#[test] -fn create_content_working_group_mint_capacity_proposal_fails_with_invalid_parameters() { - initial_test_ext().execute_with(|| { - increase_total_balance_issuance_using_account_id(1, 500000); - - assert_eq!( - ProposalCodex::create_set_content_working_group_mint_capacity_proposal( - RawOrigin::Signed(1).into(), - 1, - b"title".to_vec(), - b"body".to_vec(), - Some(>::from(50000u32)), - (crate::CONTENT_WORKING_GROUP_MINT_CAPACITY_MAX_VALUE + 1) as u64, - ), - Err(Error::::InvalidContentWorkingGroupMintCapacity.into()) - ); - }); -} - -#[test] -fn create_set_content_working_group_mint_capacity_proposal_common_checks_succeed() { - initial_test_ext().execute_with(|| { - increase_total_balance_issuance(500000); - - let proposal_fixture = ProposalTestFixture { - insufficient_rights_call: || { - ProposalCodex::create_set_content_working_group_mint_capacity_proposal( - RawOrigin::None.into(), - 1, - b"title".to_vec(), - b"body".to_vec(), - None, - 0, - ) - }, - empty_stake_call: || { - ProposalCodex::create_set_content_working_group_mint_capacity_proposal( - RawOrigin::Signed(1).into(), - 1, - b"title".to_vec(), - b"body".to_vec(), - None, - 0, - ) - }, - invalid_stake_call: || { - ProposalCodex::create_set_content_working_group_mint_capacity_proposal( - RawOrigin::Signed(1).into(), - 1, - b"title".to_vec(), - b"body".to_vec(), - Some(>::from(5000u32)), - 0, - ) - }, - successful_call: || { - ProposalCodex::create_set_content_working_group_mint_capacity_proposal( - RawOrigin::Signed(1).into(), - 1, - b"title".to_vec(), - b"body".to_vec(), - Some(>::from(50000u32)), - 10, - ) - }, - proposal_parameters: crate::proposal_types::parameters::set_content_working_group_mint_capacity_proposal::(), - proposal_details: ProposalDetails::SetContentWorkingGroupMintCapacity(10), - }; - proposal_fixture.check_all(); - }); -} - #[test] fn create_spending_proposal_common_checks_succeed() { initial_test_ext().execute_with(|| { @@ -633,85 +563,6 @@ fn create_spending_proposal_call_fails_with_incorrect_balance() { }); } -#[test] -fn create_set_lead_proposal_fails_with_proposed_councilor() { - initial_test_ext().execute_with(|| { - increase_total_balance_issuance_using_account_id(1, 500000); - - let lead_account_id = 20; - >::set_council( - RawOrigin::Root.into(), - vec![lead_account_id], - ) - .unwrap(); - - assert_eq!( - ProposalCodex::create_set_lead_proposal( - RawOrigin::Signed(1).into(), - 1, - b"title".to_vec(), - b"body".to_vec(), - Some(>::from(1250u32)), - Some((20, lead_account_id)), - ), - Err(Error::::InvalidSetLeadParameterCannotBeCouncilor.into()) - ); - }); -} - -#[test] -fn create_set_lead_proposal_common_checks_succeed() { - initial_test_ext().execute_with(|| { - increase_total_balance_issuance(500000); - - let proposal_fixture = ProposalTestFixture { - insufficient_rights_call: || { - ProposalCodex::create_set_lead_proposal( - RawOrigin::None.into(), - 1, - b"title".to_vec(), - b"body".to_vec(), - None, - Some((20, 10)), - ) - }, - empty_stake_call: || { - ProposalCodex::create_set_lead_proposal( - RawOrigin::Signed(1).into(), - 1, - b"title".to_vec(), - b"body".to_vec(), - None, - Some((20, 10)), - ) - }, - invalid_stake_call: || { - ProposalCodex::create_set_lead_proposal( - RawOrigin::Signed(1).into(), - 1, - b"title".to_vec(), - b"body".to_vec(), - Some(>::from(5000u32)), - Some((20, 10)), - ) - }, - successful_call: || { - ProposalCodex::create_set_lead_proposal( - RawOrigin::Signed(1).into(), - 1, - b"title".to_vec(), - b"body".to_vec(), - Some(>::from(50000u32)), - Some((20, 10)), - ) - }, - proposal_parameters: crate::proposal_types::parameters::set_lead_proposal::(), - proposal_details: ProposalDetails::SetLead(Some((20, 10))), - }; - proposal_fixture.check_all(); - }); -} - #[test] fn create_set_validator_count_proposal_common_checks_succeed() { initial_test_ext().execute_with(|| { @@ -838,22 +689,6 @@ fn set_default_proposal_parameters_succeeded() { >::get(), p.set_election_parameters_proposal_grace_period as u64 ); - assert_eq!( - >::get(), - p.set_content_working_group_mint_capacity_proposal_voting_period as u64 - ); - assert_eq!( - >::get(), - p.set_content_working_group_mint_capacity_proposal_grace_period as u64 - ); - assert_eq!( - >::get(), - p.set_lead_proposal_voting_period as u64 - ); - assert_eq!( - >::get(), - p.set_lead_proposal_grace_period as u64 - ); assert_eq!( >::get(), p.spending_proposal_voting_period as u64 @@ -931,12 +766,21 @@ fn set_default_proposal_parameters_succeeded() { #[test] fn create_add_working_group_leader_opening_proposal_common_checks_succeed() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + run_create_add_working_group_leader_opening_proposal_common_checks_succeed(group); + } +} + +fn run_create_add_working_group_leader_opening_proposal_common_checks_succeed( + working_group: WorkingGroup, +) { initial_test_ext().execute_with(|| { let add_opening_parameters = AddOpeningParameters { activate_at: ActivateOpeningAt::CurrentBlock, commitment: OpeningPolicyCommitment::default(), human_readable_text: b"some text".to_vec(), - working_group: WorkingGroup::Storage, + working_group, }; increase_total_balance_issuance_using_account_id(1, 500000); @@ -993,6 +837,17 @@ fn create_add_working_group_leader_opening_proposal_common_checks_succeed() { #[test] fn create_begin_review_working_group_leader_applications_proposal_common_checks_succeed() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + run_create_begin_review_working_group_leader_applications_proposal_common_checks_succeed( + group, + ); + } +} + +fn run_create_begin_review_working_group_leader_applications_proposal_common_checks_succeed( + working_group: WorkingGroup, +) { initial_test_ext().execute_with(|| { let opening_id = 1; // random opening id. @@ -1007,7 +862,7 @@ fn create_begin_review_working_group_leader_applications_proposal_common_checks_ b"body".to_vec(), None, opening_id, - WorkingGroup::Storage + working_group ) }, empty_stake_call: || { @@ -1018,7 +873,7 @@ fn create_begin_review_working_group_leader_applications_proposal_common_checks_ b"body".to_vec(), None, opening_id, - WorkingGroup::Storage + working_group ) }, invalid_stake_call: || { @@ -1029,7 +884,7 @@ fn create_begin_review_working_group_leader_applications_proposal_common_checks_ b"body".to_vec(), Some(>::from(5000u32)), opening_id, - WorkingGroup::Storage + working_group ) }, successful_call: || { @@ -1040,14 +895,14 @@ fn create_begin_review_working_group_leader_applications_proposal_common_checks_ b"body".to_vec(), Some(>::from(25000u32)), opening_id, - WorkingGroup::Storage + working_group ) }, proposal_parameters: crate::proposal_types::parameters::begin_review_working_group_leader_applications_proposal::< Test, >(), proposal_details: ProposalDetails::BeginReviewWorkingGroupLeaderApplications(opening_id, - WorkingGroup::Storage), + working_group), }; proposal_fixture.check_all(); }); @@ -1055,6 +910,15 @@ fn create_begin_review_working_group_leader_applications_proposal_common_checks_ #[test] fn create_fill_working_group_leader_opening_proposal_common_checks_succeed() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + run_create_fill_working_group_leader_opening_proposal_common_checks_succeed(group); + } +} + +fn run_create_fill_working_group_leader_opening_proposal_common_checks_succeed( + working_group: WorkingGroup, +) { initial_test_ext().execute_with(|| { let opening_id = 1; // random opening id. @@ -1062,7 +926,7 @@ fn create_fill_working_group_leader_opening_proposal_common_checks_succeed() { opening_id, successful_application_id: 1, reward_policy: None, - working_group: WorkingGroup::Storage, + working_group, }; increase_total_balance_issuance_using_account_id(1, 500000); @@ -1119,6 +983,15 @@ fn create_fill_working_group_leader_opening_proposal_common_checks_succeed() { #[test] fn create_working_group_mint_capacity_proposal_fails_with_invalid_parameters() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + run_create_working_group_mint_capacity_proposal_fails_with_invalid_parameters(group); + } +} + +fn run_create_working_group_mint_capacity_proposal_fails_with_invalid_parameters( + working_group: WorkingGroup, +) { initial_test_ext().execute_with(|| { increase_total_balance_issuance_using_account_id(1, 500000); @@ -1130,7 +1003,7 @@ fn create_working_group_mint_capacity_proposal_fails_with_invalid_parameters() { b"body".to_vec(), Some(>::from(50000u32)), (crate::WORKING_GROUP_MINT_CAPACITY_MAX_VALUE + 1) as u64, - WorkingGroup::Storage, + working_group, ), Err(Error::::InvalidWorkingGroupMintCapacity.into()) ); @@ -1139,6 +1012,15 @@ fn create_working_group_mint_capacity_proposal_fails_with_invalid_parameters() { #[test] fn create_set_working_group_mint_capacity_proposal_common_checks_succeed() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + run_create_set_working_group_mint_capacity_proposal_common_checks_succeed(group); + } +} + +fn run_create_set_working_group_mint_capacity_proposal_common_checks_succeed( + working_group: WorkingGroup, +) { initial_test_ext().execute_with(|| { increase_total_balance_issuance(500000); @@ -1151,7 +1033,7 @@ fn create_set_working_group_mint_capacity_proposal_common_checks_succeed() { b"body".to_vec(), None, 0, - WorkingGroup::Storage, + working_group, ) }, empty_stake_call: || { @@ -1162,7 +1044,7 @@ fn create_set_working_group_mint_capacity_proposal_common_checks_succeed() { b"body".to_vec(), None, 0, - WorkingGroup::Storage, + working_group, ) }, invalid_stake_call: || { @@ -1173,7 +1055,7 @@ fn create_set_working_group_mint_capacity_proposal_common_checks_succeed() { b"body".to_vec(), Some(>::from(5000u32)), 0, - WorkingGroup::Storage, + working_group, ) }, successful_call: || { @@ -1184,16 +1066,13 @@ fn create_set_working_group_mint_capacity_proposal_common_checks_succeed() { b"body".to_vec(), Some(>::from(50000u32)), 10, - WorkingGroup::Storage, + working_group, ) }, proposal_parameters: crate::proposal_types::parameters::set_working_group_mint_capacity_proposal::( ), - proposal_details: ProposalDetails::SetWorkingGroupMintCapacity( - 10, - WorkingGroup::Storage, - ), + proposal_details: ProposalDetails::SetWorkingGroupMintCapacity(10, working_group), }; proposal_fixture.check_all(); }); @@ -1201,6 +1080,15 @@ fn create_set_working_group_mint_capacity_proposal_common_checks_succeed() { #[test] fn create_decrease_working_group_leader_stake_proposal_common_checks_succeed() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + run_create_decrease_working_group_leader_stake_proposal_common_checks_succeed(group); + } +} + +fn run_create_decrease_working_group_leader_stake_proposal_common_checks_succeed( + working_group: WorkingGroup, +) { initial_test_ext().execute_with(|| { increase_total_balance_issuance(500000); @@ -1214,7 +1102,7 @@ fn create_decrease_working_group_leader_stake_proposal_common_checks_succeed() { None, 0, 10, - WorkingGroup::Storage, + working_group, ) }, empty_stake_call: || { @@ -1226,7 +1114,7 @@ fn create_decrease_working_group_leader_stake_proposal_common_checks_succeed() { None, 0, 10, - WorkingGroup::Storage, + working_group, ) }, invalid_stake_call: || { @@ -1238,7 +1126,7 @@ fn create_decrease_working_group_leader_stake_proposal_common_checks_succeed() { Some(>::from(5000u32)), 0, 10, - WorkingGroup::Storage, + working_group, ) }, successful_call: || { @@ -1250,7 +1138,7 @@ fn create_decrease_working_group_leader_stake_proposal_common_checks_succeed() { Some(>::from(50000u32)), 10, 10, - WorkingGroup::Storage, + working_group, ) }, proposal_parameters: @@ -1260,7 +1148,7 @@ fn create_decrease_working_group_leader_stake_proposal_common_checks_succeed() { proposal_details: ProposalDetails::DecreaseWorkingGroupLeaderStake( 10, 10, - WorkingGroup::Storage, + working_group, ), }; proposal_fixture.check_all(); @@ -1269,6 +1157,15 @@ fn create_decrease_working_group_leader_stake_proposal_common_checks_succeed() { #[test] fn create_slash_working_group_leader_stake_proposal_common_checks_succeed() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + run_create_slash_working_group_leader_stake_proposal_common_checks_succeed(group); + } +} + +fn run_create_slash_working_group_leader_stake_proposal_common_checks_succeed( + working_group: WorkingGroup, +) { initial_test_ext().execute_with(|| { increase_total_balance_issuance(500000); @@ -1282,7 +1179,7 @@ fn create_slash_working_group_leader_stake_proposal_common_checks_succeed() { None, 0, 10, - WorkingGroup::Storage, + working_group, ) }, empty_stake_call: || { @@ -1294,7 +1191,7 @@ fn create_slash_working_group_leader_stake_proposal_common_checks_succeed() { None, 0, 10, - WorkingGroup::Storage, + working_group, ) }, invalid_stake_call: || { @@ -1306,7 +1203,7 @@ fn create_slash_working_group_leader_stake_proposal_common_checks_succeed() { Some(>::from(5000u32)), 0, 10, - WorkingGroup::Storage, + working_group, ) }, successful_call: || { @@ -1318,7 +1215,7 @@ fn create_slash_working_group_leader_stake_proposal_common_checks_succeed() { Some(>::from(50000u32)), 10, 10, - WorkingGroup::Storage, + working_group, ) }, proposal_parameters: @@ -1328,7 +1225,7 @@ fn create_slash_working_group_leader_stake_proposal_common_checks_succeed() { proposal_details: ProposalDetails::SlashWorkingGroupLeaderStake( 10, 10, - WorkingGroup::Storage, + working_group, ), }; proposal_fixture.check_all(); @@ -1337,6 +1234,13 @@ fn create_slash_working_group_leader_stake_proposal_common_checks_succeed() { #[test] fn slash_stake_with_zero_staking_balance_fails() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + run_slash_stake_with_zero_staking_balance_fails(group); + } +} + +fn run_slash_stake_with_zero_staking_balance_fails(working_group: WorkingGroup) { initial_test_ext().execute_with(|| { increase_total_balance_issuance_using_account_id(1, 500000); @@ -1356,7 +1260,7 @@ fn slash_stake_with_zero_staking_balance_fails() { Some(>::from(50000u32)), 10, 0, - WorkingGroup::Storage, + working_group, ), Err(Error::::SlashingStakeIsZero.into()) ); @@ -1365,6 +1269,13 @@ fn slash_stake_with_zero_staking_balance_fails() { #[test] fn decrease_stake_with_zero_staking_balance_fails() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + run_decrease_stake_with_zero_staking_balance_fails(group); + } +} + +fn run_decrease_stake_with_zero_staking_balance_fails(working_group: WorkingGroup) { initial_test_ext().execute_with(|| { increase_total_balance_issuance_using_account_id(1, 500000); @@ -1384,7 +1295,7 @@ fn decrease_stake_with_zero_staking_balance_fails() { Some(>::from(50000u32)), 10, 0, - WorkingGroup::Storage, + working_group, ), Err(Error::::DecreasingStakeIsZero.into()) ); @@ -1393,6 +1304,15 @@ fn decrease_stake_with_zero_staking_balance_fails() { #[test] fn create_set_working_group_leader_reward_proposal_common_checks_succeed() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + run_create_set_working_group_leader_reward_proposal_common_checks_succeed(group); + } +} + +fn run_create_set_working_group_leader_reward_proposal_common_checks_succeed( + working_group: WorkingGroup, +) { initial_test_ext().execute_with(|| { let proposal_fixture = ProposalTestFixture { insufficient_rights_call: || { @@ -1404,7 +1324,7 @@ fn create_set_working_group_leader_reward_proposal_common_checks_succeed() { None, 0, 10, - WorkingGroup::Storage, + working_group, ) }, empty_stake_call: || { @@ -1416,7 +1336,7 @@ fn create_set_working_group_leader_reward_proposal_common_checks_succeed() { None, 0, 10, - WorkingGroup::Storage, + working_group, ) }, invalid_stake_call: || { @@ -1428,7 +1348,7 @@ fn create_set_working_group_leader_reward_proposal_common_checks_succeed() { Some(>::from(5000u32)), 0, 10, - WorkingGroup::Storage, + working_group, ) }, successful_call: || { @@ -1440,17 +1360,13 @@ fn create_set_working_group_leader_reward_proposal_common_checks_succeed() { Some(>::from(50000u32)), 10, 10, - WorkingGroup::Storage, + working_group, ) }, proposal_parameters: crate::proposal_types::parameters::set_working_group_leader_reward_proposal::( ), - proposal_details: ProposalDetails::SetWorkingGroupLeaderReward( - 10, - 10, - WorkingGroup::Storage, - ), + proposal_details: ProposalDetails::SetWorkingGroupLeaderReward(10, 10, working_group), }; proposal_fixture.check_all(); }); @@ -1458,6 +1374,15 @@ fn create_set_working_group_leader_reward_proposal_common_checks_succeed() { #[test] fn create_terminate_working_group_leader_role_proposal_common_checks_succeed() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + run_create_terminate_working_group_leader_role_proposal_common_checks_succeed(group); + } +} + +fn run_create_terminate_working_group_leader_role_proposal_common_checks_succeed( + working_group: WorkingGroup, +) { initial_test_ext().execute_with(|| { increase_total_balance_issuance(500000); @@ -1465,7 +1390,7 @@ fn create_terminate_working_group_leader_role_proposal_common_checks_succeed() { worker_id: 10, rationale: Vec::new(), slash: false, - working_group: WorkingGroup::Storage, + working_group, }; let proposal_fixture = ProposalTestFixture { diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 565ba1ade0..e56e573b50 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -82,7 +82,7 @@ content-directory = { package = 'pallet-content-directory', default-features = f [dev-dependencies] sp-io = { package = 'sp-io', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'} - +strum = {version = "0.19", default-features = false} [build-dependencies] wasm-builder-runner = { package = "substrate-wasm-builder-runner", git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' } diff --git a/runtime/src/integration/content_working_group.rs b/runtime/src/integration/content_working_group.rs index 653db28ca6..bd438c0af2 100644 --- a/runtime/src/integration/content_working_group.rs +++ b/runtime/src/integration/content_working_group.rs @@ -73,6 +73,7 @@ impl versioned_store_permissions::CredentialChecker for ContentWorkingG } } +#[allow(dead_code)] pub struct ContentWorkingGroupStakingEventHandler {} impl stake::StakingEventsHandler for ContentWorkingGroupStakingEventHandler { fn unstaked( diff --git a/runtime/src/integration/proposals/proposal_encoder.rs b/runtime/src/integration/proposals/proposal_encoder.rs index d924d95aa4..388e1343d2 100644 --- a/runtime/src/integration/proposals/proposal_encoder.rs +++ b/runtime/src/integration/proposals/proposal_encoder.rs @@ -18,6 +18,9 @@ use sp_std::vec::Vec; macro_rules! wrap_working_group_call { ($working_group:expr, $working_group_instance_call:expr) => {{ match $working_group { + WorkingGroup::Content => { + Call::ContentDirectoryWorkingGroup($working_group_instance_call) + } WorkingGroup::Storage => Call::StorageWorkingGroup($working_group_instance_call), } }}; @@ -35,17 +38,9 @@ impl ProposalEncoder for ExtrinsicProposalEncoder { ProposalDetails::SetElectionParameters(election_parameters) => Call::CouncilElection( governance::election::Call::set_election_parameters(election_parameters), ), - ProposalDetails::SetContentWorkingGroupMintCapacity(mint_balance) => { - Call::ContentWorkingGroup(content_working_group::Call::set_mint_capacity( - mint_balance, - )) - } ProposalDetails::Spending(balance, destination) => Call::Council( governance::council::Call::spend_from_council_mint(balance, destination), ), - ProposalDetails::SetLead(new_lead) => { - Call::ContentWorkingGroup(content_working_group::Call::replace_lead(new_lead)) - } ProposalDetails::SetValidatorCount(new_validator_count) => Call::Staking( pallet_staking::Call::set_validator_count(new_validator_count), ), diff --git a/runtime/src/integration/working_group.rs b/runtime/src/integration/working_group.rs index 8c11350845..6c13de8ad0 100644 --- a/runtime/src/integration/working_group.rs +++ b/runtime/src/integration/working_group.rs @@ -1,15 +1,59 @@ use frame_support::StorageMap; use sp_std::marker::PhantomData; -use crate::StorageWorkingGroupInstance; +use crate::{ContentDirectoryWorkingGroupInstance, StorageWorkingGroupInstance}; use stake::{BalanceOf, NegativeImbalance}; -pub struct StakingEventsHandler { +pub struct ContentDirectoryWGStakingEventsHandler { + pub marker: PhantomData, +} + +impl> + stake::StakingEventsHandler for ContentDirectoryWGStakingEventsHandler +{ + /// Unstake remaining sum back to the source_account_id + fn unstaked( + stake_id: &::StakeId, + _unstaked_amount: BalanceOf, + remaining_imbalance: NegativeImbalance, + ) -> NegativeImbalance { + // Stake not related to a staked role managed by the hiring module. + if !hiring::ApplicationIdByStakingId::::contains_key(*stake_id) { + return remaining_imbalance; + } + + let hiring_application_id = hiring::ApplicationIdByStakingId::::get(*stake_id); + + if working_group::MemberIdByHiringApplicationId::::contains_key( + hiring_application_id, + ) { + return >::refund_working_group_stake( + *stake_id, + remaining_imbalance, + ); + } + + remaining_imbalance + } + + /// Empty handler for the slashing. + fn slashed( + _: &::StakeId, + _: Option<::SlashId>, + _: BalanceOf, + _: BalanceOf, + remaining_imbalance: NegativeImbalance, + ) -> NegativeImbalance { + remaining_imbalance + } +} + +pub struct StorageWgStakingEventsHandler { pub marker: PhantomData, } impl> - stake::StakingEventsHandler for StakingEventsHandler + stake::StakingEventsHandler for StorageWgStakingEventsHandler { /// Unstake remaining sum back to the source_account_id fn unstaked( diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index b09fd16fc1..dff8848097 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -453,10 +453,10 @@ impl stake::Trait for Runtime { type Currency = ::Currency; type StakePoolId = StakePoolId; type StakingEventsHandler = ( - crate::integration::content_working_group::ContentWorkingGroupStakingEventHandler, + crate::integration::proposals::StakingEventsHandler, ( - crate::integration::proposals::StakingEventsHandler, - crate::integration::working_group::StakingEventsHandler, + crate::integration::working_group::ContentDirectoryWGStakingEventsHandler, + crate::integration::working_group::StorageWgStakingEventsHandler, ), ); type StakeId = u64; @@ -509,8 +509,6 @@ impl storage::data_object_storage_registry::Trait for Runtime { type ContentIdExists = DataDirectory; } -pub type MemberId = u64; - impl membership::Trait for Runtime { type Event = Event; type MemberId = MemberId; diff --git a/runtime/src/primitives.rs b/runtime/src/primitives.rs index 99ea7258e3..912036ed7d 100644 --- a/runtime/src/primitives.rs +++ b/runtime/src/primitives.rs @@ -63,6 +63,9 @@ pub type PostId = u64; /// Represent an actor in membership group, which is the same in the working groups. pub type ActorId = u64; +/// Represent an member in membership group, which is the same in the working groups. +pub type MemberId = u64; + /// App-specific crypto used for reporting equivocation/misbehavior in BABE and /// GRANDPA. Any rewards for misbehavior reporting will be paid out to this /// account. diff --git a/runtime/src/tests/mod.rs b/runtime/src/tests/mod.rs index 96cb974568..c43408a688 100644 --- a/runtime/src/tests/mod.rs +++ b/runtime/src/tests/mod.rs @@ -1,6 +1,7 @@ //! The Joystream Substrate Node runtime integration tests. #![cfg(test)] +#[macro_use] mod proposals_integration; mod storage_integration; diff --git a/runtime/src/tests/proposals_integration/mod.rs b/runtime/src/tests/proposals_integration/mod.rs index 44ab718938..0419c69dae 100644 --- a/runtime/src/tests/proposals_integration/mod.rs +++ b/runtime/src/tests/proposals_integration/mod.rs @@ -31,7 +31,6 @@ pub type ProposalsEngine = proposals_engine::Module; pub type Council = governance::council::Module; pub type Election = governance::election::Module; pub type ProposalCodex = proposals_codex::Module; -pub type Mint = minting::Module; fn setup_members(count: u8) { let authority_account_id = ::AccountId::default(); @@ -567,32 +566,6 @@ fn text_proposal_execution_succeeds() { }); } -#[test] -fn set_lead_proposal_execution_succeeds() { - initial_test_ext().execute_with(|| { - let member_id = 10; - let account_id: [u8; 32] = [member_id; 32]; - - let codex_extrinsic_test_fixture = CodexProposalTestFixture::default_for_call(|| { - ProposalCodex::create_set_lead_proposal( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, - b"title".to_vec(), - b"body".to_vec(), - Some(>::from(50000u32)), - Some((member_id as u64, account_id.into())), - ) - }) - .with_member_id(member_id as u64); - - assert!(content_working_group::Module::::ensure_lead_is_set().is_err()); - - codex_extrinsic_test_fixture.call_extrinsic_and_assert(); - - assert!(content_working_group::Module::::ensure_lead_is_set().is_ok()); - }); -} - #[test] fn spending_proposal_execution_succeeds() { initial_test_ext().execute_with(|| { @@ -626,36 +599,6 @@ fn spending_proposal_execution_succeeds() { }); } -#[test] -fn set_content_working_group_mint_capacity_execution_succeeds() { - initial_test_ext().execute_with(|| { - let member_id = 1; - let account_id: [u8; 32] = [member_id; 32]; - let new_balance = >::from(55u32); - - let mint_id = - Mint::add_mint(0, None).expect("Failed to create a mint for the content working group"); - >::put(mint_id); - - assert_eq!(Mint::get_mint_capacity(mint_id), Ok(0)); - - let codex_extrinsic_test_fixture = CodexProposalTestFixture::default_for_call(|| { - ProposalCodex::create_set_content_working_group_mint_capacity_proposal( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, - b"title".to_vec(), - b"body".to_vec(), - Some(>::from(50000u32)), - new_balance, - ) - }); - - codex_extrinsic_test_fixture.call_extrinsic_and_assert(); - - assert_eq!(Mint::get_mint_capacity(mint_id), Ok(new_balance)); - }); -} - #[test] fn set_election_parameters_proposal_execution_succeeds() { initial_test_ext().execute_with(|| { diff --git a/runtime/src/tests/proposals_integration/working_group_proposals.rs b/runtime/src/tests/proposals_integration/working_group_proposals.rs index b6c04ebe45..515e274973 100644 --- a/runtime/src/tests/proposals_integration/working_group_proposals.rs +++ b/runtime/src/tests/proposals_integration/working_group_proposals.rs @@ -1,3 +1,6 @@ +#![allow(unnameable_test_items)] +#![allow(dead_code)] + use super::*; use system::RawOrigin; @@ -7,33 +10,53 @@ use hiring::ActivateOpeningAt; use proposals_codex::AddOpeningParameters; use working_group::{OpeningPolicyCommitment, RewardPolicy}; -use crate::{Balance, BlockNumber, StorageWorkingGroupInstance}; +use crate::{ + Balance, BlockNumber, ContentDirectoryWorkingGroup, ContentDirectoryWorkingGroupInstance, + StorageWorkingGroup, StorageWorkingGroupInstance, +}; use sp_std::collections::btree_set::BTreeSet; -type StorageWorkingGroup = working_group::Module; +use crate::primitives::{ActorId, MemberId}; +use frame_support::traits; +use strum::IntoEnumIterator; + +type WorkingGroupInstance = working_group::Module; type Hiring = hiring::Module; fn add_opening( - member_id: u8, + member_id: MemberId, account_id: [u8; 32], activate_at: hiring::ActivateOpeningAt, opening_policy_commitment: Option>, sequence_number: u32, // action sequence number to align with other actions + working_group: WorkingGroup, ) -> u64 { let expected_proposal_id = sequence_number; let run_to_block = sequence_number * 2; - let opening_id = StorageWorkingGroup::next_opening_id(); - - assert!(!>::contains_key(opening_id)); + let opening_id = match working_group { + WorkingGroup::Content => { + let opening_id = ContentDirectoryWorkingGroup::next_opening_id(); + assert!(!>::contains_key(opening_id)); + opening_id + } + WorkingGroup::Storage => { + let opening_id = StorageWorkingGroup::next_opening_id(); + assert!(!>::contains_key(opening_id)); + opening_id + } + }; let codex_extrinsic_test_fixture = CodexProposalTestFixture::default_for_call(|| { ProposalCodex::create_add_working_group_leader_opening_proposal( - RawOrigin::Signed(account_id.clone().into()).into(), + RawOrigin::Signed(account_id.into()).into(), member_id as u64, b"title".to_vec(), b"body".to_vec(), @@ -44,7 +67,7 @@ fn add_opening( .clone() .unwrap_or(OpeningPolicyCommitment::default()), human_readable_text: Vec::new(), - working_group: WorkingGroup::Storage, + working_group, }, ) }) @@ -57,23 +80,24 @@ fn add_opening( } fn begin_review_applications( - member_id: u8, + member_id: MemberId, account_id: [u8; 32], opening_id: u64, sequence_number: u32, // action sequence number to align with other actions + working_group: WorkingGroup, ) { let expected_proposal_id = sequence_number; let run_to_block = sequence_number * 2; let codex_extrinsic_test_fixture = CodexProposalTestFixture::default_for_call(|| { ProposalCodex::create_begin_review_working_group_leader_applications_proposal( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, + RawOrigin::Signed(account_id.into()).into(), + member_id, b"title".to_vec(), b"body".to_vec(), Some(>::from(25_000_u32)), opening_id, - WorkingGroup::Storage, + working_group, ) }) .disable_setup_enviroment() @@ -84,20 +108,21 @@ fn begin_review_applications( } fn fill_opening( - member_id: u8, + member_id: MemberId, account_id: [u8; 32], opening_id: u64, successful_application_id: u64, reward_policy: Option>, sequence_number: u32, // action sequence number to align with other actions + working_group: WorkingGroup, ) { let expected_proposal_id = sequence_number; let run_to_block = sequence_number * 2; let codex_extrinsic_test_fixture = CodexProposalTestFixture::default_for_call(|| { ProposalCodex::create_fill_working_group_leader_opening_proposal( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, + RawOrigin::Signed(account_id.into()).into(), + member_id, b"title".to_vec(), b"body".to_vec(), Some(>::from(50_000_u32)), @@ -105,7 +130,7 @@ fn fill_opening( opening_id, successful_application_id, reward_policy: reward_policy.clone(), - working_group: WorkingGroup::Storage, + working_group, }, ) }) @@ -125,25 +150,26 @@ fn get_stake_balance(stake: stake::Stake) -> Balance } fn decrease_stake( - member_id: u8, + member_id: u64, account_id: [u8; 32], leader_worker_id: u64, stake_amount: Balance, sequence_number: u32, // action sequence number to align with other actions + working_group: WorkingGroup, ) { let expected_proposal_id = sequence_number; let run_to_block = sequence_number * 2; let codex_extrinsic_test_fixture = CodexProposalTestFixture::default_for_call(|| { ProposalCodex::create_decrease_working_group_leader_stake_proposal( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, + RawOrigin::Signed(account_id.into()).into(), + member_id, b"title".to_vec(), b"body".to_vec(), Some(>::from(50_000_u32)), leader_worker_id, stake_amount, - WorkingGroup::Storage, + working_group, ) }) .disable_setup_enviroment() @@ -154,25 +180,26 @@ fn decrease_stake( } fn slash_stake( - member_id: u8, + member_id: MemberId, account_id: [u8; 32], - leader_worker_id: u64, + leader_worker_id: ActorId, stake_amount: Balance, sequence_number: u32, // action sequence number to align with other actions + working_group: WorkingGroup, ) { let expected_proposal_id = sequence_number; let run_to_block = sequence_number * 2; let codex_extrinsic_test_fixture = CodexProposalTestFixture::default_for_call(|| { ProposalCodex::create_slash_working_group_leader_stake_proposal( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, + RawOrigin::Signed(account_id.into()).into(), + member_id, b"title".to_vec(), b"body".to_vec(), Some(>::from(50_000_u32)), leader_worker_id, stake_amount, - WorkingGroup::Storage, + working_group, ) }) .disable_setup_enviroment() @@ -183,25 +210,26 @@ fn slash_stake( } fn set_reward( - member_id: u8, + member_id: MemberId, account_id: [u8; 32], leader_worker_id: u64, reward_amount: Balance, sequence_number: u32, // action sequence number to align with other actions + working_group: WorkingGroup, ) { let expected_proposal_id = sequence_number; let run_to_block = sequence_number * 2; let codex_extrinsic_test_fixture = CodexProposalTestFixture::default_for_call(|| { ProposalCodex::create_set_working_group_leader_reward_proposal( - RawOrigin::Signed(account_id.clone().into()).into(), + RawOrigin::Signed(account_id.into()).into(), member_id as u64, b"title".to_vec(), b"body".to_vec(), Some(>::from(50_000_u32)), leader_worker_id, reward_amount, - WorkingGroup::Storage, + working_group, ) }) .disable_setup_enviroment() @@ -211,31 +239,38 @@ fn set_reward( codex_extrinsic_test_fixture.call_extrinsic_and_assert(); } -fn set_mint_capacity( - member_id: u8, +fn set_mint_capacity< + T: working_group::Trait + system::Trait + minting::Trait, + I: working_group::Instance, +>( + member_id: MemberId, account_id: [u8; 32], mint_capacity: Balance, sequence_number: u32, // action sequence number to align with other actions setup_environment: bool, -) { + working_group: WorkingGroup, +) where + ::MintId: From, +{ let expected_proposal_id = sequence_number; let run_to_block = sequence_number * 2; let mint_id_result = >::add_mint(0, None); if let Ok(mint_id) = mint_id_result { - >::put(mint_id); + let mint_id: ::MintId = mint_id.into(); + >::put(mint_id); } let codex_extrinsic_test_fixture = CodexProposalTestFixture::default_for_call(|| { ProposalCodex::create_set_working_group_mint_capacity_proposal( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, + RawOrigin::Signed(account_id.into()).into(), + member_id, b"title".to_vec(), b"body".to_vec(), Some(>::from(50_000_u32)), mint_capacity, - WorkingGroup::Storage, + working_group, ) }) .with_setup_enviroment(setup_environment) @@ -246,19 +281,20 @@ fn set_mint_capacity( } fn terminate_role( - member_id: u8, + member_id: MemberId, account_id: [u8; 32], leader_worker_id: u64, slash: bool, sequence_number: u32, // action sequence number to align with other actions + working_group: WorkingGroup, ) { let expected_proposal_id = sequence_number; let run_to_block = sequence_number * 2; let codex_extrinsic_test_fixture = CodexProposalTestFixture::default_for_call(|| { ProposalCodex::create_terminate_working_group_leader_role_proposal( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, + RawOrigin::Signed(account_id.into()).into(), + member_id, b"title".to_vec(), b"body".to_vec(), Some(>::from(100_000_u32)), @@ -266,7 +302,7 @@ fn terminate_role( worker_id: leader_worker_id, rationale: Vec::new(), slash, - working_group: WorkingGroup::Storage, + working_group, }, ) }) @@ -279,53 +315,110 @@ fn terminate_role( #[test] fn create_add_working_group_leader_opening_proposal_execution_succeeds() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + match group { + WorkingGroup::Content => { + run_create_add_working_group_leader_opening_proposal_execution_succeeds::< + Runtime, + ContentDirectoryWorkingGroupInstance, + >(group); + } + WorkingGroup::Storage => { + run_create_add_working_group_leader_opening_proposal_execution_succeeds::< + Runtime, + StorageWorkingGroupInstance, + >(group); + } + } + } +} + +fn run_create_add_working_group_leader_opening_proposal_execution_succeeds< + T: working_group::Trait + system::Trait + stake::Trait, + I: working_group::Instance, +>( + working_group: WorkingGroup, +) where + ::MemberId: From, + ::OpeningId: From, +{ initial_test_ext().execute_with(|| { - let member_id = 1; - let account_id: [u8; 32] = [member_id; 32]; + let member_id: MemberId = 1; + let account_id: [u8; 32] = [member_id as u8; 32]; - let next_opening_id = StorageWorkingGroup::next_opening_id(); + let next_opening_id = WorkingGroupInstance::::next_opening_id(); - assert!(!>::contains_key(next_opening_id)); + assert!(!>::contains_key( + next_opening_id + )); - let opening_id = add_opening( + let opening_id: ::OpeningId = add_opening( member_id, account_id, ActivateOpeningAt::CurrentBlock, None, 1, - ); + working_group, + ) + .into(); // Check for expected opening id. assert_eq!(opening_id, next_opening_id); // Check for the new opening creation. - assert!(>::contains_key(opening_id)); + assert!(>::contains_key(opening_id)); }); } #[test] fn create_begin_review_working_group_leader_applications_proposal_execution_succeeds() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + match group { + WorkingGroup::Content => { + run_create_begin_review_working_group_leader_applications_proposal_execution_succeeds::< + Runtime, + ContentDirectoryWorkingGroupInstance, + >(group); + } + WorkingGroup::Storage => { + run_create_begin_review_working_group_leader_applications_proposal_execution_succeeds::< + Runtime, + StorageWorkingGroupInstance, + >(group); + } + } + } +} + +fn run_create_begin_review_working_group_leader_applications_proposal_execution_succeeds< + T: working_group::Trait + system::Trait + stake::Trait, + I: working_group::Instance, +>( + working_group: WorkingGroup, +) where + ::OpeningId: From + Into, +{ initial_test_ext().execute_with(|| { - let member_id = 1; - let account_id: [u8; 32] = [member_id; 32]; + let member_id: MemberId = 1; + let account_id: [u8; 32] = [member_id as u8; 32]; let opening_id = add_opening( member_id, - account_id.clone(), + account_id, ActivateOpeningAt::CurrentBlock, None, 1, + working_group, ); - let opening = StorageWorkingGroup::opening_by_id(opening_id); + let opening = WorkingGroupInstance::::opening_by_id( + ::OpeningId::from(opening_id), + ); - let hiring_opening = Hiring::opening_by_id(opening.hiring_opening_id); + let hiring_opening_id: u64 = opening.hiring_opening_id.into(); + let hiring_opening = Hiring::opening_by_id(hiring_opening_id); assert_eq!( hiring_opening.stage, hiring::OpeningStage::Active { @@ -339,9 +432,9 @@ fn create_begin_review_working_group_leader_applications_proposal_execution_succ } ); - begin_review_applications(member_id, account_id, opening_id, 2); + begin_review_applications(member_id, account_id, opening_id, 2, working_group); - let hiring_opening = Hiring::opening_by_id(opening.hiring_opening_id); + let hiring_opening = Hiring::opening_by_id(hiring_opening_id); assert_eq!( hiring_opening.stage, hiring::OpeningStage::Active { @@ -360,475 +453,741 @@ fn create_begin_review_working_group_leader_applications_proposal_execution_succ #[test] fn create_fill_working_group_leader_opening_proposal_execution_succeeds() { - initial_test_ext().execute_with(|| { - let member_id = 1; - let account_id: [u8; 32] = [member_id; 32]; - - let opening_id = add_opening( - member_id, - account_id.clone(), - ActivateOpeningAt::CurrentBlock, - None, - 1, - ); - - let apply_result = StorageWorkingGroup::apply_on_opening( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, - opening_id, - account_id.clone().into(), - None, - None, - Vec::new(), - ); - - assert_eq!(apply_result, Ok(())); - - let expected_application_id = 0; - - begin_review_applications(member_id, account_id, opening_id, 2); - - let lead = StorageWorkingGroup::current_lead(); - assert!(lead.is_none()); - - fill_opening( - member_id, - account_id, - opening_id, - expected_application_id, - None, - 3, - ); - - let lead = StorageWorkingGroup::current_lead(); - assert!(lead.is_some()); - }); -} - -#[test] -fn create_decrease_group_leader_stake_proposal_execution_succeeds() { - initial_test_ext().execute_with(|| { - let member_id = 1; - let account_id: [u8; 32] = [member_id; 32]; - let stake_amount = 100; - - let opening_policy_commitment = OpeningPolicyCommitment { - role_staking_policy: Some(hiring::StakingPolicy { - amount: 100, - amount_mode: hiring::StakingAmountLimitMode::AtLeast, - crowded_out_unstaking_period_length: None, - review_period_expired_unstaking_period_length: None, - }), - ..OpeningPolicyCommitment::default() - }; - - let opening_id = add_opening( - member_id, - account_id.clone(), - ActivateOpeningAt::CurrentBlock, - Some(opening_policy_commitment), - 1, - ); - - let apply_result = StorageWorkingGroup::apply_on_opening( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, - opening_id, - account_id.clone().into(), - Some(stake_amount), - None, - Vec::new(), - ); - - assert_eq!(apply_result, Ok(())); - - let expected_application_id = 0; - - begin_review_applications(member_id, account_id, opening_id, 2); - - let lead = StorageWorkingGroup::current_lead(); - assert!(lead.is_none()); - - fill_opening( - member_id, - account_id, - opening_id, - expected_application_id, - None, - 3, - ); - - let leader_worker_id = StorageWorkingGroup::current_lead().unwrap(); - - let stake_id = 1; - let old_balance = Balances::free_balance(&account_id.into()); - let old_stake = >::stakes(stake_id); - - assert_eq!(get_stake_balance(old_stake), stake_amount); - - let decreasing_stake_amount = 30; - decrease_stake( - member_id, - account_id, - leader_worker_id, - decreasing_stake_amount, - 4, - ); - - let new_balance = Balances::free_balance(&account_id.into()); - let new_stake = >::stakes(stake_id); - - assert_eq!( - get_stake_balance(new_stake), - stake_amount - decreasing_stake_amount - ); - assert_eq!(new_balance, old_balance + decreasing_stake_amount); - }); -} - -#[test] -fn create_slash_group_leader_stake_proposal_execution_succeeds() { - initial_test_ext().execute_with(|| { - let member_id = 1; - let account_id: [u8; 32] = [member_id; 32]; - let stake_amount = 100; - - let opening_policy_commitment = OpeningPolicyCommitment { - role_staking_policy: Some(hiring::StakingPolicy { - amount: 100, - amount_mode: hiring::StakingAmountLimitMode::AtLeast, - crowded_out_unstaking_period_length: None, - review_period_expired_unstaking_period_length: None, - }), - ..OpeningPolicyCommitment::default() - }; - - let opening_id = add_opening( - member_id, - account_id.clone(), - ActivateOpeningAt::CurrentBlock, - Some(opening_policy_commitment), - 1, - ); - - let apply_result = StorageWorkingGroup::apply_on_opening( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, - opening_id, - account_id.clone().into(), - Some(stake_amount), - None, - Vec::new(), - ); - - assert_eq!(apply_result, Ok(())); - - let expected_application_id = 0; - - begin_review_applications(member_id, account_id, opening_id, 2); - - let lead = StorageWorkingGroup::current_lead(); - assert!(lead.is_none()); - - fill_opening( - member_id, - account_id, - opening_id, - expected_application_id, - None, - 3, - ); - - let leader_worker_id = StorageWorkingGroup::current_lead().unwrap(); - - let stake_id = 1; - let old_balance = Balances::free_balance(&account_id.into()); - let old_stake = >::stakes(stake_id); - - assert_eq!(get_stake_balance(old_stake), stake_amount); - - let slashing_stake_amount = 30; - slash_stake( - member_id, - account_id, - leader_worker_id, - slashing_stake_amount, - 4, - ); - - let new_balance = Balances::free_balance(&account_id.into()); - let new_stake = >::stakes(stake_id); - - assert_eq!( - get_stake_balance(new_stake), - stake_amount - slashing_stake_amount - ); - assert_eq!(new_balance, old_balance); - }); -} - -#[test] -fn create_set_working_group_mint_capacity_proposal_execution_succeeds() { - initial_test_ext().execute_with(|| { - let member_id = 1; - let account_id: [u8; 32] = [member_id; 32]; - - assert_eq!(StorageWorkingGroup::mint(), 0); - - let mint_capacity = 999999; - set_mint_capacity(member_id, account_id, mint_capacity, 1, true); - - let mint_id = StorageWorkingGroup::mint(); - let mint = >::mints(mint_id); - - assert_eq!(mint.capacity(), mint_capacity); - }); -} - -#[test] -fn create_set_group_leader_reward_proposal_execution_succeeds() { - initial_test_ext().execute_with(|| { - let member_id = 1; - let account_id: [u8; 32] = [member_id; 32]; - let stake_amount = 100; - - let opening_policy_commitment = OpeningPolicyCommitment { - role_staking_policy: Some(hiring::StakingPolicy { - amount: 100, - amount_mode: hiring::StakingAmountLimitMode::AtLeast, - crowded_out_unstaking_period_length: None, - review_period_expired_unstaking_period_length: None, - }), - ..OpeningPolicyCommitment::default() - }; - - let opening_id = add_opening( - member_id, - account_id.clone(), - ActivateOpeningAt::CurrentBlock, - Some(opening_policy_commitment), - 1, - ); - - let apply_result = StorageWorkingGroup::apply_on_opening( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, - opening_id, - account_id.clone().into(), - Some(stake_amount), - None, - Vec::new(), - ); - - assert_eq!(apply_result, Ok(())); - - let expected_application_id = 0; - - begin_review_applications(member_id, account_id, opening_id, 2); - - let lead = StorageWorkingGroup::current_lead(); - assert!(lead.is_none()); + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + match group { + WorkingGroup::Content => { + run_create_fill_working_group_leader_opening_proposal_execution_succeeds::< + Runtime, + ContentDirectoryWorkingGroupInstance, + >(group); + } + WorkingGroup::Storage => { + run_create_fill_working_group_leader_opening_proposal_execution_succeeds::< + Runtime, + StorageWorkingGroupInstance, + >(group); + } + } + } - let old_reward_amount = 100; - let reward_policy = Some(RewardPolicy { - amount_per_payout: old_reward_amount, - next_payment_at_block: 9999, - payout_interval: None, + fn run_create_fill_working_group_leader_opening_proposal_execution_succeeds< + T: working_group::Trait + system::Trait + stake::Trait, + I: working_group::Instance, + >( + working_group: WorkingGroup, + ) where + ::AccountId: From<[u8; 32]>, + ::MemberId: From, + ::OpeningId: From, + { + initial_test_ext().execute_with(|| { + let member_id: MemberId = 1; + let account_id: [u8; 32] = [member_id as u8; 32]; + + let opening_id = add_opening( + member_id, + account_id, + ActivateOpeningAt::CurrentBlock, + None, + 1, + working_group, + ); + + let apply_result = WorkingGroupInstance::::apply_on_opening( + RawOrigin::Signed(account_id.into()).into(), + member_id.into(), + opening_id.into(), + account_id.into(), + None, + None, + Vec::new(), + ); + + assert_eq!(apply_result, Ok(())); + + let expected_application_id = 0; + + begin_review_applications(member_id, account_id, opening_id, 2, working_group); + + let lead = WorkingGroupInstance::::current_lead(); + assert!(lead.is_none()); + + fill_opening( + member_id, + account_id, + opening_id, + expected_application_id, + None, + 3, + working_group, + ); + + let lead = WorkingGroupInstance::::current_lead(); + assert!(lead.is_some()); }); + } - set_mint_capacity(member_id, account_id, 999999, 3, false); - - fill_opening( - member_id, - account_id, - opening_id, - expected_application_id, - reward_policy, - 4, - ); - - let leader_worker_id = StorageWorkingGroup::current_lead().unwrap(); - - let worker = StorageWorkingGroup::worker_by_id(leader_worker_id); - let relationship_id = worker.reward_relationship.unwrap(); - - let relationship = recurring_rewards::RewardRelationships::::get(relationship_id); - assert_eq!(relationship.amount_per_payout, old_reward_amount); - - let new_reward_amount = 999; - set_reward( - member_id, - account_id, - leader_worker_id, - new_reward_amount, - 5, - ); - - let relationship = recurring_rewards::RewardRelationships::::get(relationship_id); - assert_eq!(relationship.amount_per_payout, new_reward_amount); - }); -} - -#[test] -fn create_terminate_group_leader_role_proposal_execution_succeeds() { - initial_test_ext().execute_with(|| { - let member_id = 1; - let account_id: [u8; 32] = [member_id; 32]; - let stake_amount = 100; - - let opening_policy_commitment = OpeningPolicyCommitment { - role_staking_policy: Some(hiring::StakingPolicy { - amount: 100, - amount_mode: hiring::StakingAmountLimitMode::AtLeast, - crowded_out_unstaking_period_length: None, - review_period_expired_unstaking_period_length: None, - }), - ..OpeningPolicyCommitment::default() - }; - - let opening_id = add_opening( - member_id, - account_id.clone(), - ActivateOpeningAt::CurrentBlock, - Some(opening_policy_commitment), - 1, - ); - - let apply_result = StorageWorkingGroup::apply_on_opening( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, - opening_id, - account_id.clone().into(), - Some(stake_amount), - None, - Vec::new(), - ); - - assert_eq!(apply_result, Ok(())); - - let expected_application_id = 0; - - begin_review_applications(member_id, account_id, opening_id, 2); - - let lead = StorageWorkingGroup::current_lead(); - assert!(lead.is_none()); + #[test] + fn create_decrease_group_leader_stake_proposal_execution_succeeds() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + match group { + WorkingGroup::Content => { + run_create_decrease_group_leader_stake_proposal_execution_succeeds::< + Runtime, + ContentDirectoryWorkingGroupInstance, + >(group); + } + WorkingGroup::Storage => { + run_create_decrease_group_leader_stake_proposal_execution_succeeds::< + Runtime, + StorageWorkingGroupInstance, + >(group); + } + } + } + } - let old_reward_amount = 100; - let reward_policy = Some(RewardPolicy { - amount_per_payout: old_reward_amount, - next_payment_at_block: 9999, - payout_interval: None, +fn run_create_decrease_group_leader_stake_proposal_execution_succeeds< + T: working_group::Trait + system::Trait + stake::Trait, + I: working_group::Instance, +>( + working_group: WorkingGroup, +) where + ::AccountId: From<[u8; 32]>, + ::OpeningId: From, + ::MemberId: From, + ::ActorId: Into, + <::Currency as traits::Currency<::AccountId>>::Balance: + From, +{ + initial_test_ext().execute_with(|| { + let member_id: MemberId = 1; + let account_id: [u8; 32] = [member_id as u8; 32]; + let stake_amount: Balance = 100; + + let opening_policy_commitment = OpeningPolicyCommitment { + role_staking_policy: Some(hiring::StakingPolicy { + amount: 100, + amount_mode: hiring::StakingAmountLimitMode::AtLeast, + crowded_out_unstaking_period_length: None, + review_period_expired_unstaking_period_length: None, + }), + ..OpeningPolicyCommitment::default() + }; + + let opening_id = add_opening( + member_id, + account_id, + ActivateOpeningAt::CurrentBlock, + Some(opening_policy_commitment), + 1, + working_group, + ); + + let apply_result = WorkingGroupInstance::::apply_on_opening( + RawOrigin::Signed(account_id.into()).into(), + member_id.into(), + opening_id.into(), + account_id.into(), + Some(stake_amount.into()), + None, + Vec::new(), + ); + + assert_eq!(apply_result, Ok(())); + + let expected_application_id = 0; + + begin_review_applications(member_id, account_id, opening_id, 2, working_group); + + let lead = WorkingGroupInstance::::current_lead(); + assert!(lead.is_none()); + + fill_opening( + member_id, + account_id, + opening_id, + expected_application_id, + None, + 3, + working_group, + ); + + let leader_worker_id = WorkingGroupInstance::::current_lead().unwrap(); + + let stake_id = 1; + let old_balance = Balances::free_balance(&account_id.into()); + let old_stake = >::stakes(stake_id); + + assert_eq!(get_stake_balance(old_stake), stake_amount); + + let decreasing_stake_amount = 30; + decrease_stake( + member_id, + account_id, + leader_worker_id.into(), + decreasing_stake_amount, + 4, + working_group, + ); + + let new_balance = Balances::free_balance(&account_id.into()); + let new_stake = >::stakes(stake_id); + + assert_eq!( + get_stake_balance(new_stake), + stake_amount - decreasing_stake_amount + ); + assert_eq!(new_balance, old_balance + decreasing_stake_amount); }); + } - set_mint_capacity(member_id, account_id, 999999, 3, false); - - fill_opening( - member_id, - account_id, - opening_id, - expected_application_id, - reward_policy, - 4, - ); - - let leader_worker_id = StorageWorkingGroup::current_lead().unwrap(); - - let stake_id = 1; - let old_balance = Balances::free_balance(&account_id.into()); - let old_stake = >::stakes(stake_id); - - assert_eq!(get_stake_balance(old_stake), stake_amount); - - terminate_role(member_id, account_id, leader_worker_id, false, 5); - - assert!(StorageWorkingGroup::current_lead().is_none()); - - let new_balance = Balances::free_balance(&account_id.into()); - let new_stake = >::stakes(stake_id); - - assert_eq!(new_stake.staking_status, stake::StakingStatus::NotStaked); - assert_eq!(new_balance, old_balance + stake_amount); - }); -} - -#[test] -fn create_terminate_group_leader_role_proposal_with_slashing_execution_succeeds() { - initial_test_ext().execute_with(|| { - let member_id = 1; - let account_id: [u8; 32] = [member_id; 32]; - let stake_amount = 100; - - let opening_policy_commitment = OpeningPolicyCommitment { - role_staking_policy: Some(hiring::StakingPolicy { - amount: 100, - amount_mode: hiring::StakingAmountLimitMode::AtLeast, - crowded_out_unstaking_period_length: None, - review_period_expired_unstaking_period_length: None, - }), - ..OpeningPolicyCommitment::default() - }; - - let opening_id = add_opening( - member_id, - account_id.clone(), - ActivateOpeningAt::CurrentBlock, - Some(opening_policy_commitment), - 1, - ); - - let apply_result = StorageWorkingGroup::apply_on_opening( - RawOrigin::Signed(account_id.clone().into()).into(), - member_id as u64, - opening_id, - account_id.clone().into(), - Some(stake_amount), - None, - Vec::new(), - ); - - assert_eq!(apply_result, Ok(())); - - let expected_application_id = 0; - - begin_review_applications(member_id, account_id, opening_id, 2); - - let lead = StorageWorkingGroup::current_lead(); - assert!(lead.is_none()); + #[test] + fn create_slash_group_leader_stake_proposal_execution_succeeds() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + match group { + WorkingGroup::Content => { + run_create_slash_group_leader_stake_proposal_execution_succeeds::< + Runtime, + ContentDirectoryWorkingGroupInstance, + >(group) + } + WorkingGroup::Storage => { + run_create_slash_group_leader_stake_proposal_execution_succeeds::< + Runtime, + StorageWorkingGroupInstance, + >(group) + } + } + } + } - let old_reward_amount = 100; - let reward_policy = Some(RewardPolicy { - amount_per_payout: old_reward_amount, - next_payment_at_block: 9999, - payout_interval: None, +fn run_create_slash_group_leader_stake_proposal_execution_succeeds< + T: working_group::Trait + system::Trait + stake::Trait, + I: working_group::Instance, +>( + working_group: WorkingGroup, +) where + ::AccountId: From<[u8; 32]>, + ::OpeningId: From, + ::MemberId: From, + ::ActorId: Into, + <::Currency as traits::Currency<::AccountId>>::Balance: + From, +{ + initial_test_ext().execute_with(|| { + let member_id: MemberId = 1; + let account_id: [u8; 32] = [member_id as u8; 32]; + let stake_amount: Balance = 100; + + let opening_policy_commitment = OpeningPolicyCommitment { + role_staking_policy: Some(hiring::StakingPolicy { + amount: 100, + amount_mode: hiring::StakingAmountLimitMode::AtLeast, + crowded_out_unstaking_period_length: None, + review_period_expired_unstaking_period_length: None, + }), + ..OpeningPolicyCommitment::default() + }; + + let opening_id = add_opening( + member_id, + account_id, + ActivateOpeningAt::CurrentBlock, + Some(opening_policy_commitment), + 1, + working_group, + ); + + let apply_result = WorkingGroupInstance::::apply_on_opening( + RawOrigin::Signed(account_id.into()).into(), + member_id.into(), + opening_id.into(), + account_id.into(), + Some(stake_amount.into()), + None, + Vec::new(), + ); + + assert_eq!(apply_result, Ok(())); + + let expected_application_id = 0; + + begin_review_applications(member_id, account_id, opening_id, 2, working_group); + + let lead = WorkingGroupInstance::::current_lead(); + + assert!(lead.is_none()); + + fill_opening( + member_id, + account_id, + opening_id, + expected_application_id, + None, + 3, + working_group, + ); + + let leader_worker_id = WorkingGroupInstance::::current_lead().unwrap(); + + let stake_id = 1; + let old_balance = Balances::free_balance(&account_id.into()); + let old_stake = >::stakes(stake_id); + + assert_eq!(get_stake_balance(old_stake), stake_amount); + + let slashing_stake_amount = 30; + slash_stake( + member_id, + account_id, + leader_worker_id.into(), + slashing_stake_amount, + 4, + working_group, + ); + + let new_balance = Balances::free_balance(&account_id.into()); + let new_stake = >::stakes(stake_id); + + assert_eq!( + get_stake_balance(new_stake), + stake_amount as u128 - slashing_stake_amount + ); + assert_eq!(new_balance, old_balance); }); + } - set_mint_capacity(member_id, account_id, 999999, 3, false); - - fill_opening( - member_id, - account_id, - opening_id, - expected_application_id, - reward_policy, - 4, - ); - - let leader_worker_id = StorageWorkingGroup::current_lead().unwrap(); - - let stake_id = 1; - let old_balance = Balances::free_balance(&account_id.into()); - let old_stake = >::stakes(stake_id); - - assert_eq!(get_stake_balance(old_stake), stake_amount); - - terminate_role(member_id, account_id, leader_worker_id, true, 5); - - assert!(StorageWorkingGroup::current_lead().is_none()); - - let new_balance = Balances::free_balance(&account_id.into()); - let new_stake = >::stakes(stake_id); - - assert_eq!(new_stake.staking_status, stake::StakingStatus::NotStaked); - assert_eq!(new_balance, old_balance); - }); + #[test] + fn create_set_working_group_mint_capacity_proposal_execution_succeeds() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + match group { + WorkingGroup::Content => { + run_create_set_working_group_mint_capacity_proposal_execution_succeeds::< + Runtime, + ContentDirectoryWorkingGroupInstance, + >(group); + } + WorkingGroup::Storage => { + run_create_set_working_group_mint_capacity_proposal_execution_succeeds::< + Runtime, + StorageWorkingGroupInstance, + >(group); + } + } + } + + fn run_create_set_working_group_mint_capacity_proposal_execution_succeeds< + T: working_group::Trait + system::Trait + minting::Trait, + I: working_group::Instance, + >( + working_group: WorkingGroup, + ) where + ::AccountId: From<[u8; 32]>, + ::MemberId: From, + ::MintId: From, + <::Currency as traits::Currency< + ::AccountId, + >>::Balance: From, + { + initial_test_ext().execute_with(|| { + let member_id: MemberId = 1; + let account_id: [u8; 32] = [member_id as u8; 32]; + + assert_eq!(WorkingGroupInstance::::mint(), 0.into()); + + let mint_capacity = 999999; + set_mint_capacity::( + member_id, + account_id, + mint_capacity, + 1, + true, + working_group, + ); + + let mint_id = WorkingGroupInstance::::mint(); + let mint = >::mints(mint_id); + + assert_eq!(mint.capacity(), mint_capacity.into()); + }); + } + + #[test] + fn create_set_group_leader_reward_proposal_execution_succeeds() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + match group { + WorkingGroup::Content => { + run_create_set_working_group_mint_capacity_proposal_execution_succeeds::< + Runtime, + ContentDirectoryWorkingGroupInstance, + >(group); + } + WorkingGroup::Storage => { + run_create_set_working_group_mint_capacity_proposal_execution_succeeds::< + Runtime, + StorageWorkingGroupInstance, + >(group); + } + } + } + } + + fn run_create_set_group_leader_reward_proposal_execution_succeeds< + T: working_group::Trait + system::Trait + minting::Trait, + I: working_group::Instance, + >( + working_group: WorkingGroup, + ) where + ::AccountId: From<[u8; 32]>, + ::MemberId: From, + ::ActorId: Into, + ::MintId: From, + ::OpeningId: From, + <::Currency as traits::Currency< + ::AccountId, + >>::Balance: From, + { + initial_test_ext().execute_with(|| { + let member_id: MemberId = 1; + let account_id: [u8; 32] = [member_id as u8; 32]; + let stake_amount = 100; + + let opening_policy_commitment = OpeningPolicyCommitment { + role_staking_policy: Some(hiring::StakingPolicy { + amount: 100, + amount_mode: hiring::StakingAmountLimitMode::AtLeast, + crowded_out_unstaking_period_length: None, + review_period_expired_unstaking_period_length: None, + }), + ..OpeningPolicyCommitment::default() + }; + + let opening_id = add_opening( + member_id, + account_id, + ActivateOpeningAt::CurrentBlock, + Some(opening_policy_commitment), + 1, + working_group, + ); + + let apply_result = WorkingGroupInstance::::apply_on_opening( + RawOrigin::Signed(account_id.into()).into(), + member_id.into(), + opening_id.into(), + account_id.into(), + Some(stake_amount.into()), + None, + Vec::new(), + ); + + assert_eq!(apply_result, Ok(())); + + let expected_application_id = 0; + + begin_review_applications(member_id, account_id, opening_id, 2, working_group); + + let lead = WorkingGroupInstance::::current_lead(); + assert!(lead.is_none()); + + let old_reward_amount = 100; + let reward_policy = Some(RewardPolicy { + amount_per_payout: old_reward_amount, + next_payment_at_block: 9999, + payout_interval: None, + }); + + set_mint_capacity::(member_id, account_id, 999999, 3, false, working_group); + + fill_opening( + member_id, + account_id, + opening_id, + expected_application_id, + reward_policy, + 4, + working_group, + ); + + let leader_worker_id = WorkingGroupInstance::::current_lead().unwrap(); + + let worker = WorkingGroupInstance::::worker_by_id(leader_worker_id); + let relationship_id = worker.reward_relationship.unwrap(); + + let relationship = + recurring_rewards::RewardRelationships::::get(relationship_id); + assert_eq!(relationship.amount_per_payout, old_reward_amount.into()); + + let new_reward_amount = 999; + set_reward( + member_id, + account_id, + leader_worker_id.into(), + new_reward_amount, + 5, + working_group, + ); + + let relationship = + recurring_rewards::RewardRelationships::::get(relationship_id); + assert_eq!(relationship.amount_per_payout, new_reward_amount.into()); + }); + } + + #[test] + fn create_terminate_group_leader_role_proposal_execution_succeeds() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + match group { + WorkingGroup::Content => { + run_create_terminate_group_leader_role_proposal_execution_succeeds::< + Runtime, + ContentDirectoryWorkingGroupInstance, + >(group); + } + WorkingGroup::Storage => { + run_create_terminate_group_leader_role_proposal_execution_succeeds::< + Runtime, + StorageWorkingGroupInstance, + >(group); + } + } + } + } + + fn run_create_terminate_group_leader_role_proposal_execution_succeeds< + T: working_group::Trait + system::Trait + minting::Trait, + I: working_group::Instance, + >( + working_group: WorkingGroup, + ) where + ::AccountId: From<[u8; 32]>, + ::MemberId: From, + ::ActorId: Into, + ::MintId: From, + ::OpeningId: From, + <::Currency as traits::Currency< + ::AccountId, + >>::Balance: From, + { + initial_test_ext().execute_with(|| { + let member_id: MemberId = 1; + let account_id: [u8; 32] = [0; 32]; + let stake_amount = 100_u128; + + let opening_policy_commitment = OpeningPolicyCommitment { + role_staking_policy: Some(hiring::StakingPolicy { + amount: 100, + amount_mode: hiring::StakingAmountLimitMode::AtLeast, + crowded_out_unstaking_period_length: None, + review_period_expired_unstaking_period_length: None, + }), + ..OpeningPolicyCommitment::default() + }; + + let opening_id = add_opening( + member_id.into(), + account_id, + ActivateOpeningAt::CurrentBlock, + Some(opening_policy_commitment), + 1, + working_group, + ); + + let apply_result = WorkingGroupInstance::::apply_on_opening( + RawOrigin::Signed(account_id.into()).into(), + member_id.into(), + opening_id.into(), + account_id.into(), + Some(stake_amount.into()), + None, + Vec::new(), + ); + + assert_eq!(apply_result, Ok(())); + + let expected_application_id = 0; + + begin_review_applications(member_id, account_id, opening_id, 2, working_group); + + let lead = WorkingGroupInstance::::current_lead(); + assert!(lead.is_none()); + + let old_reward_amount = 100; + let reward_policy = Some(RewardPolicy { + amount_per_payout: old_reward_amount, + next_payment_at_block: 9999, + payout_interval: None, + }); + + set_mint_capacity::(member_id, account_id, 999999, 3, false, working_group); + + fill_opening( + member_id, + account_id, + opening_id, + expected_application_id, + reward_policy, + 4, + working_group, + ); + + let stake_id = 1; + let old_balance = Balances::free_balance(&account_id.into()); + let old_stake = >::stakes(stake_id); + + assert_eq!(get_stake_balance(old_stake), stake_amount); + + let leader_worker_id = WorkingGroupInstance::::current_lead().unwrap(); + + terminate_role( + member_id, + account_id, + leader_worker_id.into(), + false, + 5, + working_group, + ); + + assert!(WorkingGroupInstance::::current_lead().is_none()); + + let new_balance = Balances::free_balance(&account_id.into()); + let new_stake = >::stakes(stake_id); + + assert_eq!(new_stake.staking_status, stake::StakingStatus::NotStaked); + assert_eq!(new_balance, old_balance + stake_amount); + }); + } + + #[test] + fn create_terminate_group_leader_role_proposal_with_slashing_execution_succeeds() { + // This uses strum crate for enum iteration + for group in WorkingGroup::iter() { + match group { + WorkingGroup::Content => { + run_create_terminate_group_leader_role_proposal_with_slashing_execution_succeeds::(group); + } + WorkingGroup::Storage => { + run_create_terminate_group_leader_role_proposal_with_slashing_execution_succeeds::(group); + } + } + } + } + + fn run_create_terminate_group_leader_role_proposal_with_slashing_execution_succeeds< + T: working_group::Trait + system::Trait + minting::Trait, + I: working_group::Instance, + >( + working_group: WorkingGroup, + ) where + ::AccountId: From<[u8; 32]>, + ::MemberId: From, + ::ActorId: Into, + ::MintId: From, + ::OpeningId: From, + <::Currency as traits::Currency< + ::AccountId, + >>::Balance: From, + { + initial_test_ext().execute_with(|| { + let member_id: MemberId = 1; + let account_id: [u8; 32] = [0; 32]; + let stake_amount = 100_u128; + + let opening_policy_commitment = OpeningPolicyCommitment { + role_staking_policy: Some(hiring::StakingPolicy { + amount: 100, + amount_mode: hiring::StakingAmountLimitMode::AtLeast, + crowded_out_unstaking_period_length: None, + review_period_expired_unstaking_period_length: None, + }), + ..OpeningPolicyCommitment::default() + }; + + let opening_id = add_opening( + member_id, + account_id, + ActivateOpeningAt::CurrentBlock, + Some(opening_policy_commitment), + 1, + working_group, + ); + + let apply_result = WorkingGroupInstance::::apply_on_opening( + RawOrigin::Signed(account_id.into()).into(), + member_id.into(), + opening_id.into(), + account_id.into(), + Some(stake_amount.into()), + None, + Vec::new(), + ); + + assert_eq!(apply_result, Ok(())); + + let expected_application_id = 0; + + begin_review_applications( + member_id, + account_id, + opening_id.into(), + 2, + working_group, + ); + + let lead = WorkingGroupInstance::::current_lead(); + assert!(lead.is_none()); + + let old_reward_amount = 100; + let reward_policy = Some(RewardPolicy { + amount_per_payout: old_reward_amount, + next_payment_at_block: 9999, + payout_interval: None, + }); + + set_mint_capacity::(member_id, account_id, 999999, 3, false, working_group); + + fill_opening( + member_id, + account_id, + opening_id, + expected_application_id, + reward_policy, + 4, + working_group, + ); + + let stake_id = 1; + let old_balance = Balances::free_balance(&account_id.into()); + let old_stake = >::stakes(stake_id); + + assert_eq!(get_stake_balance(old_stake), stake_amount); + + let leader_worker_id = WorkingGroupInstance::::current_lead().unwrap(); + + terminate_role( + member_id, + account_id, + leader_worker_id.into(), + true, + 5, + working_group, + ); + + assert!(WorkingGroupInstance::::current_lead().is_none()); + + let new_balance = Balances::free_balance(&account_id.into()); + let new_stake = >::stakes(stake_id); + + assert_eq!(new_stake.staking_status, stake::StakingStatus::NotStaked); + assert_eq!(new_balance, old_balance); + }); + } + } }