Browse Source

Merge pull request #2024 from iorveth/membership_benchmarking

Membership benchmarking
Gabriel Alejandro Steinberg 4 years ago
parent
commit
f2bb2edb44

+ 2 - 1
Cargo.lock

@@ -3886,8 +3886,9 @@ dependencies = [
 
 [[package]]
 name = "pallet-membership"
-version = "4.0.0"
+version = "4.0.1"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
  "pallet-balances",

+ 62 - 3
runtime-modules/council/src/mock.rs

@@ -283,7 +283,7 @@ impl referendum::Trait<ReferendumInstance> for Runtime {
     type RevealStageDuration = RevealStageDuration;
 
     type MinimumStake = MinimumVotingStake;
-    type WeightInfo = ReferendumWeightInfo;
+    type WeightInfo = Weights;
 
     type MaxWinnerTargetCount = MaxWinnerTargetCount;
 
@@ -340,8 +340,9 @@ impl referendum::Trait<ReferendumInstance> for Runtime {
     }
 }
 
-pub struct ReferendumWeightInfo;
-impl referendum::WeightInfo for ReferendumWeightInfo {
+// Weights info stub
+pub struct Weights;
+impl referendum::WeightInfo for Weights {
     fn on_initialize_revealing(_: u32) -> Weight {
         0
     }
@@ -368,6 +369,63 @@ impl referendum::WeightInfo for ReferendumWeightInfo {
     }
 }
 
+impl membership::WeightInfo for Weights {
+    fn buy_membership_without_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn buy_membership_with_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_profile(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_none() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_root() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_controller() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_both() -> Weight {
+        unimplemented!()
+    }
+    fn set_referral_cut() -> Weight {
+        unimplemented!()
+    }
+    fn transfer_invites() -> Weight {
+        unimplemented!()
+    }
+    fn invite_member(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn set_membership_price() -> Weight {
+        unimplemented!()
+    }
+    fn update_profile_verification() -> Weight {
+        unimplemented!()
+    }
+    fn set_leader_invitation_quota() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_balance() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_count() -> Weight {
+        unimplemented!()
+    }
+    fn add_staking_account_candidate() -> Weight {
+        unimplemented!()
+    }
+    fn confirm_staking_account() -> Weight {
+        unimplemented!()
+    }
+    fn remove_staking_account() -> Weight {
+        unimplemented!()
+    }
+}
+
 impl balances::Trait for Runtime {
     type Balance = u64;
     type Event = TestEvent;
@@ -382,6 +440,7 @@ impl membership::Trait for Runtime {
     type Event = TestEvent;
     type DefaultMembershipPrice = DefaultMembershipPrice;
     type WorkingGroup = ();
+    type WeightInfo = Weights;
     type DefaultInitialInvitationBalance = DefaultInitialInvitationBalance;
     type InvitedMemberStakingHandler = staking_handler::StakingManager<Self, InvitedMemberLockId>;
 }

+ 78 - 1
runtime-modules/forum/src/mock.rs

@@ -7,6 +7,7 @@ use sp_core::H256;
 
 use crate::{GenesisConfig, Module, Trait};
 use frame_support::traits::{LockIdentifier, OnFinalize, OnInitialize};
+use sp_std::cell::RefCell;
 use staking_handler::LockComparator;
 
 use frame_support::{impl_outer_event, impl_outer_origin, parameter_types};
@@ -223,11 +224,87 @@ impl working_group::WeightInfo for Weights {
     }
 }
 
+impl membership::WeightInfo for Weights {
+    fn buy_membership_without_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn buy_membership_with_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_profile(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_none() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_root() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_controller() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_both() -> Weight {
+        unimplemented!()
+    }
+    fn set_referral_cut() -> Weight {
+        unimplemented!()
+    }
+    fn transfer_invites() -> Weight {
+        unimplemented!()
+    }
+    fn invite_member(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn set_membership_price() -> Weight {
+        unimplemented!()
+    }
+    fn update_profile_verification() -> Weight {
+        unimplemented!()
+    }
+    fn set_leader_invitation_quota() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_balance() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_count() -> Weight {
+        unimplemented!()
+    }
+    fn add_staking_account_candidate() -> Weight {
+        unimplemented!()
+    }
+    fn confirm_staking_account() -> Weight {
+        unimplemented!()
+    }
+    fn remove_staking_account() -> Weight {
+        unimplemented!()
+    }
+}
+
+pub const WORKING_GROUP_BUDGET: u64 = 100;
+
+thread_local! {
+    pub static WG_BUDGET: RefCell<u64> = RefCell::new(WORKING_GROUP_BUDGET);
+}
+
+impl common::working_group::WorkingGroupBudgetHandler<Runtime> for () {
+    fn get_budget() -> u64 {
+        WG_BUDGET.with(|val| *val.borrow())
+    }
+
+    fn set_budget(new_value: u64) {
+        WG_BUDGET.with(|val| {
+            *val.borrow_mut() = new_value;
+        });
+    }
+}
+
 impl membership::Trait for Runtime {
     type Event = TestEvent;
     type DefaultMembershipPrice = DefaultMembershipPrice;
     type DefaultInitialInvitationBalance = DefaultInitialInvitationBalance;
-    type WorkingGroup = working_group::Module<Self, ForumWorkingGroupInstance>;
+    type WorkingGroup = ();
+    type WeightInfo = Weights;
     type InvitedMemberStakingHandler = staking_handler::StakingManager<Self, InviteMemberLockId>;
 }
 

+ 7 - 1
runtime-modules/membership/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'pallet-membership'
-version = '4.0.0'
+version = '4.0.1'
 authors = ['Joystream contributors']
 edition = '2018'
 
@@ -17,6 +17,9 @@ balances = { package = 'pallet-balances', default-features = false, git = 'https
 common = { package = 'pallet-common', default-features = false, path = '../common'}
 staking-handler = { package = 'pallet-staking-handler', default-features = false, path = '../staking-handler'}
 
+# Benchmarking dependencies
+frame-benchmarking = { package = 'frame-benchmarking', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca', optional = true}
+
 [dev-dependencies]
 sp-io = { package = 'sp-io', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 sp-core = { package = 'sp-core', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
@@ -24,6 +27,9 @@ working-group = { package = 'pallet-working-group', default-features = false, pa
 
 [features]
 default = ['std']
+runtime-benchmarks = [
+    'frame-benchmarking',
+]
 std = [
 	'serde',
 	'codec/std',

+ 784 - 0
runtime-modules/membership/src/benchmarking.rs

@@ -0,0 +1,784 @@
+#![cfg(feature = "runtime-benchmarks")]
+use super::*;
+use crate::{
+    BuyMembershipParameters, InviteMembershipParameters, MemberIdByHandleHash, Membership,
+    MembershipById, MembershipObject, StakingAccountIdMemberStatus, StakingAccountMemberBinding,
+    Trait,
+};
+use balances::Module as Balances;
+use core::convert::TryInto;
+use frame_benchmarking::{account, benchmarks};
+use frame_support::storage::StorageMap;
+use frame_support::traits::Currency;
+use frame_system::Module as System;
+use frame_system::{EventRecord, RawOrigin};
+use sp_arithmetic::traits::One;
+use sp_runtime::traits::Bounded;
+use sp_std::prelude::*;
+
+/// Balance alias for `balances` module.
+pub type BalanceOf<T> = <T as balances::Trait>::Balance;
+
+pub trait MembershipWorkingGroupHelper<AccountId, MemberId, ActorId> {
+    /// Set membership working group lead
+    fn insert_a_lead(opening_id: u32, caller_id: &AccountId, member_id: MemberId) -> ActorId;
+}
+
+const SEED: u32 = 0;
+const MAX_BYTES: u32 = 16384;
+
+fn get_byte(num: u32, byte_number: u8) -> u8 {
+    ((num & (0xff << (8 * byte_number))) >> 8 * byte_number) as u8
+}
+
+fn assert_last_event<T: Trait>(generic_event: <T as Trait>::Event) {
+    let events = System::<T>::events();
+    let system_event: <T as frame_system::Trait>::Event = generic_event.into();
+    // compare to the last event record
+    let EventRecord { event, .. } = &events[events.len() - 1];
+    assert_eq!(event, &system_event);
+}
+
+fn member_funded_account<T: Trait + balances::Trait>(
+    name: &'static str,
+    id: u32,
+) -> (T::AccountId, T::MemberId) {
+    let account_id = account::<T::AccountId>(name, id, SEED);
+
+    let handle = handle_from_id::<T>(id);
+
+    let _ = Balances::<T>::make_free_balance_be(&account_id, BalanceOf::<T>::max_value());
+
+    let params = BuyMembershipParameters {
+        root_account: account_id.clone(),
+        controller_account: account_id.clone(),
+        name: None,
+        handle: Some(handle),
+        avatar_uri: None,
+        about: None,
+        referrer_id: None,
+    };
+
+    Module::<T>::buy_membership(RawOrigin::Signed(account_id.clone()).into(), params).unwrap();
+
+    let _ = Balances::<T>::make_free_balance_be(&account_id, BalanceOf::<T>::max_value());
+
+    let member_id = T::MemberId::from(id.try_into().unwrap());
+
+    (account_id, member_id)
+}
+
+// Method to generate a distintic valid handle
+// for a membership. For each index.
+fn handle_from_id<T: Trait>(id: u32) -> Vec<u8> {
+    let mut handle = vec![];
+
+    for j in 0..4 {
+        handle.push(get_byte(id, j));
+    }
+
+    while handle.len() < (id as usize) {
+        handle.push(0u8);
+    }
+
+    handle
+}
+
+benchmarks! {
+    where_clause { where T: balances::Trait, T: Trait, T: MembershipWorkingGroupHelper<<T as
+        frame_system::Trait>::AccountId, <T as common::Trait>::MemberId, <T as common::Trait>::ActorId> }
+    _{  }
+
+    buy_membership_without_referrer{
+
+        let i in 0 .. MAX_BYTES;
+
+        let j in 0 .. MAX_BYTES;
+
+        let member_id = 0;
+
+        let account_id = account::<T::AccountId>("member", member_id, SEED);
+
+        let handle = handle_from_id::<T>(i);
+
+        let member_id = T::MemberId::from(member_id.try_into().unwrap());
+
+        let free_balance = BalanceOf::<T>::max_value();
+
+        let _ = Balances::<T>::make_free_balance_be(&account_id, free_balance);
+
+        let fee = Module::<T>::membership_price();
+
+        let name = vec![0u8].repeat(j as usize);
+
+        let params = BuyMembershipParameters {
+            root_account: account_id.clone(),
+            controller_account: account_id.clone(),
+            name: Some(name),
+            handle: Some(handle.clone()),
+            avatar_uri: None,
+            about: None,
+            referrer_id: None,
+        };
+
+    }: buy_membership(RawOrigin::Signed(account_id.clone()), params)
+    verify {
+
+        // Ensure membership for given member_id is successfully bought
+        assert_eq!(Module::<T>::members_created(), member_id + T::MemberId::one());
+
+        assert_eq!(Balances::<T>::free_balance(&account_id.clone()), free_balance - fee);
+
+        let handle_hash = T::Hashing::hash(&handle).as_ref().to_vec();
+
+        let membership: Membership<T> = MembershipObject {
+            handle_hash: handle_hash.clone(),
+            root_account: account_id.clone(),
+            controller_account: account_id.clone(),
+            verified: false,
+            // Save the updated profile.
+            invites: 5,
+        };
+
+        assert_eq!(MemberIdByHandleHash::<T>::get(&handle_hash), member_id);
+
+        assert_eq!(MembershipById::<T>::get(member_id), membership);
+
+        assert_last_event::<T>(RawEvent::MemberRegistered(member_id).into());
+    }
+
+    buy_membership_with_referrer{
+
+        let i in 0 .. MAX_BYTES;
+
+        let member_id = 0;
+
+        let account_id = account::<T::AccountId>("member", member_id, SEED);
+
+        let handle = handle_from_id::<T>(i);
+
+        let _ = Balances::<T>::make_free_balance_be(&account_id, BalanceOf::<T>::max_value());
+
+        let fee = Module::<T>::membership_price();
+
+        let mut params = BuyMembershipParameters {
+            root_account: account_id.clone(),
+            controller_account: account_id.clone(),
+            name: None,
+            handle: Some(handle.clone()),
+            avatar_uri: None,
+            about: None,
+            referrer_id: None,
+        };
+
+        Module::<T>::buy_membership(RawOrigin::Signed(account_id.clone()).into(), params.clone()).unwrap();
+
+        let referral_cut: BalanceOf<T> = 1.into();
+
+        Module::<T>::set_referral_cut(RawOrigin::Root.into(), referral_cut).unwrap();
+
+        let member_id = T::MemberId::from(member_id.try_into().unwrap());
+
+        params.referrer_id = Some(member_id);
+        let second_handle = handle_from_id::<T>(i + 1);
+
+        params.handle = Some(second_handle.clone());
+
+        let free_balance = Balances::<T>::free_balance(&account_id);
+
+    }: buy_membership(RawOrigin::Signed(account_id.clone()), params)
+    verify {
+
+        // Ensure membership for given member_id is successfully bought
+        assert_eq!(Module::<T>::members_created(), member_id + T::MemberId::one() + T::MemberId::one());
+
+        // Same account id gets reward for being referral.
+        assert_eq!(Balances::<T>::free_balance(&account_id.clone()), free_balance - fee + referral_cut);
+
+        let second_handle_hash = T::Hashing::hash(&second_handle).as_ref().to_vec();
+
+        let membership: Membership<T> = MembershipObject {
+            handle_hash: second_handle_hash.clone(),
+            root_account: account_id.clone(),
+            controller_account: account_id.clone(),
+            verified: false,
+            // Save the updated profile.
+            invites: 5,
+        };
+
+        let second_member_id = member_id + T::MemberId::one();
+
+        assert_eq!(MemberIdByHandleHash::<T>::get(second_handle_hash), second_member_id);
+
+        assert_eq!(MembershipById::<T>::get(second_member_id), membership);
+
+        assert_last_event::<T>(RawEvent::MemberRegistered(second_member_id).into());
+    }
+
+    update_profile{
+
+        let i in 0 .. MAX_BYTES;
+
+        let member_id = 0;
+
+        let account_id = account::<T::AccountId>("member", member_id, SEED);
+
+        let handle = handle_from_id::<T>(i);
+
+        let _ = Balances::<T>::make_free_balance_be(&account_id, BalanceOf::<T>::max_value());
+
+        let member_id = T::MemberId::from(member_id.try_into().unwrap());
+
+        let params = BuyMembershipParameters {
+            root_account: account_id.clone(),
+            controller_account: account_id.clone(),
+            name: None,
+            handle: Some(handle.clone()),
+            avatar_uri: None,
+            about: None,
+            referrer_id: None,
+        };
+
+        Module::<T>::buy_membership(RawOrigin::Signed(account_id.clone()).into(), params.clone()).unwrap();
+
+        let handle_updated = handle_from_id::<T>(i + 1);
+
+    }: _ (RawOrigin::Signed(account_id.clone()), member_id, None, Some(handle_updated.clone()), None, None)
+    verify {
+
+        // Ensure membership profile is successfully updated
+        let handle_hash = T::Hashing::hash(&handle_updated).as_ref().to_vec();
+
+        assert!(!MemberIdByHandleHash::<T>::contains_key(handle));
+
+        assert_eq!(MemberIdByHandleHash::<T>::get(handle_updated), member_id);
+
+        assert_last_event::<T>(RawEvent::MemberProfileUpdated(member_id).into());
+    }
+
+    update_accounts_none{
+
+        let member_id = 0;
+
+        let (account_id, member_id) = member_funded_account::<T>("member", member_id);
+
+    }: update_accounts(RawOrigin::Signed(account_id.clone()), member_id, None, None)
+
+    update_accounts_root{
+
+        let member_id = 0;
+
+        let new_root_account_id = account::<T::AccountId>("root", member_id, SEED);
+
+        let handle = handle_from_id::<T>(member_id);
+
+        let (account_id, member_id) = member_funded_account::<T>("member", member_id);
+
+    }: update_accounts(RawOrigin::Signed(account_id.clone()), member_id, Some(new_root_account_id.clone()), None)
+
+    verify {
+
+        // Ensure root account is successfully updated
+        let handle_hash = T::Hashing::hash(&handle).as_ref().to_vec();
+
+        let membership: Membership<T> = MembershipObject {
+            handle_hash: handle_hash.clone(),
+            root_account: new_root_account_id.clone(),
+            controller_account: account_id.clone(),
+            verified: false,
+            // Save the updated profile.
+            invites: 5,
+        };
+
+        assert_eq!(MembershipById::<T>::get(member_id), membership);
+
+        assert_last_event::<T>(RawEvent::MemberAccountsUpdated(member_id).into());
+    }
+
+    update_accounts_controller{
+
+        let member_id = 0;
+
+        let new_controller_account_id = account::<T::AccountId>("controller", member_id, SEED);
+
+        let handle = handle_from_id::<T>(member_id);
+
+        let (account_id, member_id) = member_funded_account::<T>("member", member_id);
+
+    }: update_accounts(RawOrigin::Signed(account_id.clone()), member_id, None, Some(new_controller_account_id.clone()))
+
+    verify {
+        // Ensure controller account is successfully updated
+
+        let handle_hash = T::Hashing::hash(&handle).as_ref().to_vec();
+
+        let membership: Membership<T> = MembershipObject {
+            handle_hash: handle_hash.clone(),
+            root_account: account_id.clone(),
+            controller_account: new_controller_account_id.clone(),
+            verified: false,
+            // Save the updated profile.
+            invites: 5,
+        };
+
+        assert_eq!(MembershipById::<T>::get(member_id), membership);
+
+        assert_last_event::<T>(RawEvent::MemberAccountsUpdated(member_id).into());
+    }
+
+    update_accounts_both{
+
+        let member_id = 0;
+
+        let new_controller_account_id = account::<T::AccountId>("controller", member_id, SEED);
+
+        let new_root_account_id = account::<T::AccountId>("root", member_id, SEED);
+
+        let handle = handle_from_id::<T>(member_id);
+
+        let (account_id, member_id) = member_funded_account::<T>("member", member_id);
+
+    }: update_accounts(RawOrigin::Signed(account_id.clone()), member_id, Some(new_root_account_id.clone()), Some(new_controller_account_id.clone()))
+
+    verify {
+
+        // Ensure both root and controller accounts are successfully updated
+        let handle_hash = T::Hashing::hash(&handle).as_ref().to_vec();
+
+        let membership: Membership<T> = MembershipObject {
+            handle_hash: handle_hash.clone(),
+            root_account: new_root_account_id.clone(),
+            controller_account: new_controller_account_id.clone(),
+            verified: false,
+            // Save the updated profile.
+            invites: 5,
+        };
+
+        assert_eq!(MembershipById::<T>::get(member_id), membership);
+
+        assert_last_event::<T>(RawEvent::MemberAccountsUpdated(member_id).into());
+    }
+
+    set_referral_cut {
+        let member_id = 0;
+
+        let referral_cut: BalanceOf<T> = 1.into();
+
+    }: _(RawOrigin::Root, referral_cut)
+
+    verify {
+
+        assert_eq!(Module::<T>::referral_cut(), referral_cut);
+
+        assert_last_event::<T>(RawEvent::ReferralCutUpdated(referral_cut).into());
+    }
+
+    transfer_invites{
+
+        let first_member_id = 0;
+
+        let second_member_id = 1;
+
+        let first_handle = handle_from_id::<T>(first_member_id);
+        let (first_account_id, first_member_id) = member_funded_account::<T>("first_member", first_member_id);
+
+        let second_handle = handle_from_id::<T>(second_member_id);
+        let (second_account_id, second_member_id) = member_funded_account::<T>("second_member", second_member_id);
+
+        let number_of_invites = 5;
+
+    }: _(RawOrigin::Signed(first_account_id.clone()), first_member_id, second_member_id, number_of_invites)
+
+    verify {
+        // Ensure invites are successfully transfered
+
+        let first_handle_hash = T::Hashing::hash(&first_handle).as_ref().to_vec();
+
+        let second_handle_hash = T::Hashing::hash(&second_handle).as_ref().to_vec();
+
+        let first_membership: Membership<T> = MembershipObject {
+            handle_hash: first_handle_hash,
+            root_account: first_account_id.clone(),
+            controller_account: first_account_id.clone(),
+            verified: false,
+            invites: 0,
+        };
+
+        let second_membership: Membership<T> = MembershipObject {
+            handle_hash: second_handle_hash,
+            root_account: second_account_id.clone(),
+            controller_account: second_account_id.clone(),
+            verified: false,
+            invites: 10,
+        };
+
+        assert_eq!(MembershipById::<T>::get(first_member_id), first_membership);
+
+        assert_eq!(MembershipById::<T>::get(second_member_id), second_membership);
+
+        assert_last_event::<T>(RawEvent::InvitesTransferred(first_member_id, second_member_id, number_of_invites).into());
+    }
+
+    invite_member {
+        let member_id = 0;
+
+        let i in 1 .. MAX_BYTES;
+
+        let member_id = 0;
+
+        let (account_id, member_id) = member_funded_account::<T>("member", member_id);
+
+        let handle = handle_from_id::<T>(i);
+
+        let invite_params = InviteMembershipParameters {
+            inviting_member_id: member_id,
+            root_account: account_id.clone(),
+            controller_account: account_id.clone(),
+            name: None,
+            handle: Some(handle.clone()),
+            avatar_uri: None,
+            about: None,
+        };
+
+        let default_invitation_balance = T::DefaultInitialInvitationBalance::get();
+
+        T::WorkingGroup::set_budget(default_invitation_balance + default_invitation_balance);
+
+        let current_wg_budget = T::WorkingGroup::get_budget();
+
+    }: _(RawOrigin::Signed(account_id.clone()), invite_params)
+
+    verify {
+
+        // Ensure member is successfully invited
+        let invited_member_id = member_id + T::MemberId::one();
+
+        let handle_hash = T::Hashing::hash(&handle).as_ref().to_vec();
+
+        let invited_membership: Membership<T> = MembershipObject {
+            handle_hash: handle_hash.clone(),
+            root_account: account_id.clone(),
+            controller_account: account_id.clone(),
+            verified: false,
+            invites: 0,
+        };
+
+        let new_wg_budget = current_wg_budget.saturating_sub(default_invitation_balance);
+
+        assert_eq!(T::WorkingGroup::get_budget(), new_wg_budget);
+
+        assert_eq!(MemberIdByHandleHash::<T>::get(&handle_hash), invited_member_id);
+
+        assert_eq!(MembershipById::<T>::get(invited_member_id), invited_membership);
+
+        assert_last_event::<T>(RawEvent::MemberRegistered(invited_member_id).into());
+
+    }
+
+    set_membership_price {
+        let membership_price: BalanceOf<T> = 1000.into();
+
+    }: _(RawOrigin::Root, membership_price)
+    verify {
+        assert_eq!(Module::<T>::membership_price(), membership_price);
+
+        assert_last_event::<T>(RawEvent::MembershipPriceUpdated(membership_price).into());
+    }
+
+    update_profile_verification {
+
+        let member_id = 0;
+
+        let handle = handle_from_id::<T>(member_id);
+        let (account_id, member_id) = member_funded_account::<T>("member", member_id);
+
+        Module::<T>::add_staking_account_candidate(
+            RawOrigin::Signed(account_id.clone()).into(),
+            member_id.clone(),
+        )
+        .unwrap();
+        Module::<T>::confirm_staking_account(
+            RawOrigin::Signed(account_id.clone()).into(),
+            member_id.clone(),
+            account_id.clone(),
+        )
+        .unwrap();
+
+        // Set leader member id
+        let leader_id = T::insert_a_lead(0, &account_id, member_id);
+
+        let is_verified = true;
+
+        let leader_member_id = T::WorkingGroup::get_leader_member_id();
+    }: _(RawOrigin::Signed(account_id.clone()), leader_id, member_id, is_verified)
+
+    verify {
+        // Ensure profile verification status is successfully updated
+
+        let handle_hash = T::Hashing::hash(&handle).as_ref().to_vec();
+
+        let membership: Membership<T> = MembershipObject {
+            handle_hash: handle_hash.clone(),
+            root_account: account_id.clone(),
+            controller_account: account_id.clone(),
+            verified: is_verified,
+            invites: 5,
+        };
+
+        assert_eq!(MembershipById::<T>::get(member_id), membership);
+
+        assert_last_event::<T>(RawEvent::MemberVerificationStatusUpdated(member_id, is_verified).into());
+    }
+
+    set_leader_invitation_quota {
+        // Set leader member id
+
+        let member_id = 0;
+
+        let (account_id, member_id) = member_funded_account::<T>("member", member_id);
+
+        Module::<T>::add_staking_account_candidate(
+            RawOrigin::Signed(account_id.clone()).into(),
+            member_id.clone(),
+        )
+        .unwrap();
+        Module::<T>::confirm_staking_account(
+            RawOrigin::Signed(account_id.clone()).into(),
+            member_id.clone(),
+            account_id.clone(),
+        )
+        .unwrap();
+
+        // Set leader member id
+        T::insert_a_lead(0, &account_id, member_id);
+
+        let leader_member_id = T::WorkingGroup::get_leader_member_id();
+
+        let invitation_quota = 100;
+
+    }: _(RawOrigin::Root, invitation_quota)
+    verify {
+        // Ensure leader invitation quota is successfully updated
+
+        assert_eq!(MembershipById::<T>::get(leader_member_id.unwrap()).invites, invitation_quota);
+
+        assert_last_event::<T>(RawEvent::LeaderInvitationQuotaUpdated(invitation_quota).into());
+    }
+
+    set_initial_invitation_balance {
+        let invitation_balance: BalanceOf<T> = 1000.into();
+
+    }: _(RawOrigin::Root, invitation_balance)
+    verify {
+
+        assert_eq!(Module::<T>::initial_invitation_balance(), invitation_balance);
+
+        assert_last_event::<T>(RawEvent::InitialInvitationBalanceUpdated(invitation_balance).into());
+
+    }
+
+    set_initial_invitation_count {
+        let initial_invitation_count = 10;
+
+    }: _(RawOrigin::Root, initial_invitation_count)
+    verify {
+        assert_eq!(Module::<T>::initial_invitation_count(), initial_invitation_count);
+
+        assert_last_event::<T>(RawEvent::InitialInvitationCountUpdated(initial_invitation_count).into());
+    }
+
+    add_staking_account_candidate {
+        let member_id = 0;
+
+        let (account_id, member_id) = member_funded_account::<T>("member", member_id);
+    }: _(RawOrigin::Signed(account_id.clone()), member_id)
+
+    verify {
+
+        // Ensure staking account candidate is successfully added
+        let staking_account_member_binding = StakingAccountMemberBinding {
+            member_id,
+            confirmed: false,
+        };
+
+        assert_eq!(Module::<T>::staking_account_id_member_status(account_id.clone()), staking_account_member_binding);
+
+        assert_last_event::<T>(RawEvent::StakingAccountAdded(account_id, member_id).into());
+    }
+
+    confirm_staking_account {
+        let member_id = 0;
+
+        let (account_id, member_id) = member_funded_account::<T>("member", member_id);
+        Module::<T>::add_staking_account_candidate(
+            RawOrigin::Signed(account_id.clone()).into(),
+            member_id.clone(),
+        ).unwrap();
+
+    }: _(RawOrigin::Signed(account_id.clone()), member_id, account_id.clone())
+
+    verify {
+
+        // Ensure staking account candidate is successfully confirmed
+        let staking_account_member_binding = StakingAccountMemberBinding {
+            member_id,
+            confirmed: true,
+        };
+
+        assert_eq!(Module::<T>::staking_account_id_member_status(account_id.clone()), staking_account_member_binding);
+
+        assert_last_event::<T>(RawEvent::StakingAccountConfirmed(account_id, member_id).into());
+    }
+
+    remove_staking_account {
+        let member_id = 0;
+
+        let (account_id, member_id) = member_funded_account::<T>("member", member_id);
+        Module::<T>::add_staking_account_candidate(
+            RawOrigin::Signed(account_id.clone()).into(),
+            member_id.clone(),
+        ).unwrap();
+
+    }: _(RawOrigin::Signed(account_id.clone()), member_id)
+
+    verify {
+
+        // Ensure staking account candidate is successfully removed
+        assert!(!StakingAccountIdMemberStatus::<T>::contains_key(account_id.clone()));
+
+        assert_last_event::<T>(RawEvent::StakingAccountRemoved(account_id, member_id).into());
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::tests::*;
+    use frame_support::assert_ok;
+
+    #[test]
+    fn buy_membership_with_referrer() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_buy_membership_with_referrer::<Test>());
+        });
+    }
+
+    #[test]
+    fn buy_membership_without_referrer() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_buy_membership_without_referrer::<Test>());
+        });
+    }
+
+    #[test]
+    fn update_profile() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_update_profile::<Test>());
+        });
+    }
+
+    #[test]
+    fn update_accounts_none() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_update_accounts_none::<Test>());
+        });
+    }
+
+    #[test]
+    fn update_accounts_root() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_update_accounts_root::<Test>());
+        });
+    }
+
+    #[test]
+    fn update_accounts_controller() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_update_accounts_controller::<Test>());
+        });
+    }
+
+    #[test]
+    fn update_accounts_both() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_update_accounts_both::<Test>());
+        });
+    }
+
+    #[test]
+    fn set_referral_cut() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_set_referral_cut::<Test>());
+        });
+    }
+
+    #[test]
+    fn transfer_invites() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_transfer_invites::<Test>());
+        });
+    }
+
+    #[test]
+    fn set_membership_price() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_set_membership_price::<Test>());
+        });
+    }
+
+    #[test]
+    fn set_leader_invitation_quota() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_set_leader_invitation_quota::<Test>());
+        });
+    }
+
+    #[test]
+    fn invite_member() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_invite_member::<Test>());
+        });
+    }
+
+    #[test]
+    fn set_initial_invitation_balance() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_set_initial_invitation_balance::<Test>());
+        });
+    }
+
+    #[test]
+    fn set_initial_invitation_count() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_set_initial_invitation_count::<Test>());
+        });
+    }
+
+    #[test]
+    fn add_staking_account_candidate() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_add_staking_account_candidate::<Test>());
+        });
+    }
+
+    #[test]
+    fn confirm_staking_account() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_confirm_staking_account::<Test>());
+        });
+    }
+
+    #[test]
+    fn remove_staking_account() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_remove_staking_account::<Test>());
+        });
+    }
+
+    #[test]
+    fn update_profile_verification() {
+        build_test_externalities().execute_with(|| {
+            assert_ok!(test_benchmark_update_profile_verification::<Test>());
+        });
+    }
+}

+ 211 - 16
runtime-modules/membership/src/lib.rs

@@ -43,25 +43,57 @@
 // Ensure we're `no_std` when compiling for Wasm.
 #![cfg_attr(not(feature = "std"), no_std)]
 
+pub mod benchmarking;
+
 pub mod genesis;
 mod tests;
 
 use codec::{Decode, Encode};
 use frame_support::dispatch::DispatchError;
 use frame_support::traits::{Currency, Get, WithdrawReason, WithdrawReasons};
+pub use frame_support::weights::Weight;
 use frame_support::{decl_error, decl_event, decl_module, decl_storage, ensure};
 use frame_system::{ensure_root, ensure_signed};
 use sp_arithmetic::traits::{One, Zero};
 use sp_runtime::traits::{Hash, Saturating};
+use sp_runtime::SaturatedConversion;
 use sp_std::vec::Vec;
 
 use common::origin::MemberOriginValidator;
 use common::working_group::{WorkingGroupAuthenticator, WorkingGroupBudgetHandler};
 use staking_handler::StakingHandler;
 
+#[cfg(feature = "runtime-benchmarks")]
+pub use benchmarking::MembershipWorkingGroupHelper;
+
 // Balance type alias
 type BalanceOf<T> = <T as balances::Trait>::Balance;
 
+type WeightInfoMembership<T> = <T as Trait>::WeightInfo;
+
+/// pallet_forum WeightInfo.
+/// Note: This was auto generated through the benchmark CLI using the `--weight-trait` flag
+pub trait WeightInfo {
+    fn buy_membership_without_referrer(i: u32) -> Weight;
+    fn buy_membership_with_referrer(i: u32) -> Weight;
+    fn update_profile(i: u32) -> Weight;
+    fn update_accounts_none() -> Weight;
+    fn update_accounts_root() -> Weight;
+    fn update_accounts_controller() -> Weight;
+    fn update_accounts_both() -> Weight;
+    fn set_referral_cut() -> Weight;
+    fn transfer_invites() -> Weight;
+    fn invite_member(i: u32) -> Weight;
+    fn set_membership_price() -> Weight;
+    fn update_profile_verification() -> Weight;
+    fn set_leader_invitation_quota() -> Weight;
+    fn set_initial_invitation_balance() -> Weight;
+    fn set_initial_invitation_count() -> Weight;
+    fn add_staking_account_candidate() -> Weight;
+    fn confirm_staking_account() -> Weight;
+    fn remove_staking_account() -> Weight;
+}
+
 pub trait Trait:
     frame_system::Trait + balances::Trait + pallet_timestamp::Trait + common::Trait
 {
@@ -84,6 +116,9 @@ pub trait Trait:
         BalanceOf<Self>,
         Self::MemberId,
     >;
+
+    /// Weight information for extrinsics in this pallet.
+    type WeightInfo: WeightInfo;
 }
 
 pub(crate) const DEFAULT_MEMBER_INVITES_COUNT: u32 = 5;
@@ -91,7 +126,7 @@ pub(crate) const DEFAULT_MEMBER_INVITES_COUNT: u32 = 5;
 /// Public membership profile alias.
 pub type Membership<T> = MembershipObject<<T as frame_system::Trait>::AccountId>;
 
-#[derive(Encode, Decode, Default)]
+#[derive(Encode, PartialEq, Decode, Debug, Default)]
 /// Stored information about a registered user.
 pub struct MembershipObject<AccountId: Ord> {
     /// The hash of the handle chosen by member.
@@ -117,7 +152,7 @@ pub struct MembershipObject<AccountId: Ord> {
 }
 
 // Contain staking account to member binding and its confirmation.
-#[derive(Encode, Decode, Default)]
+#[derive(Encode, Decode, Default, Debug, PartialEq)]
 pub struct StakingAccountMemberBinding<MemberId> {
     /// Member id that we bind account to.
     pub member_id: MemberId,
@@ -313,7 +348,16 @@ decl_module! {
         fn deposit_event() = default;
 
         /// Non-members can buy membership.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (W)` where:
+        /// - `W` is the handle length
+        /// - DB:
+        ///    - O(W)
+        /// # </weight>
+        #[weight = Module::<T>::calculate_weight_for_buy_membership(params)]
         pub fn buy_membership(
             origin,
             params: BuyMembershipParameters<T::AccountId, T::MemberId>
@@ -371,7 +415,20 @@ decl_module! {
 
         /// Update member's all or some of name, handle, avatar and about text.
         /// No effect if no changed fields.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (W)` where:
+        /// - `W` is the handle length
+        /// - DB:
+        ///    - O(W)
+        /// # </weight>
+        #[weight = WeightInfoMembership::<T>::update_profile(
+            handle.as_ref()
+                .map(|handle| handle.len().saturated_into())
+                .unwrap_or_default())
+        ]
         pub fn update_profile(
             origin,
             member_id: T::MemberId,
@@ -412,7 +469,17 @@ decl_module! {
         }
 
         /// Updates member root or controller accounts. No effect if both new accounts are empty.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (1)`
+        /// - DB:
+        ///    - O(1) doesn't depend on the state or parameters
+        /// # </weight>
+        #[weight = Module::<T>::calculate_weight_for_update_account(new_root_account, new_controller_account)]
         pub fn update_accounts(
             origin,
             member_id: T::MemberId,
@@ -446,7 +513,15 @@ decl_module! {
         }
 
         /// Updates member profile verification status. Requires working group member origin.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (1)`
+        /// - DB:
+        ///    - O(1) doesn't depend on the state or parameters
+        /// # </weight>
+        #[weight = WeightInfoMembership::<T>::update_profile_verification()]
         pub fn update_profile_verification(
             origin,
             worker_id: T::ActorId,
@@ -471,7 +546,15 @@ decl_module! {
         }
 
         /// Updates membership referral cut. Requires root origin.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (1)`
+        /// - DB:
+        ///    - O(1) doesn't depend on the state or parameters
+        /// # </weight>
+        #[weight = WeightInfoMembership::<T>::set_referral_cut()]
         pub fn set_referral_cut(origin, value: BalanceOf<T>) {
             ensure_root(origin)?;
 
@@ -485,7 +568,15 @@ decl_module! {
         }
 
         /// Transfers invites from one member to another.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (1)`
+        /// - DB:
+        ///    - O(1) doesn't depend on the state or parameters
+        /// # </weight>
+        #[weight = WeightInfoMembership::<T>::transfer_invites()]
         pub fn transfer_invites(
             origin,
             source_member_id: T::MemberId,
@@ -524,7 +615,21 @@ decl_module! {
         }
 
         /// Invite a new member.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (W)` where:
+        /// - `W` is the handle length
+        /// - DB:
+        ///    - O(W)
+        /// # </weight>
+        #[weight = WeightInfoMembership::<T>::invite_member(
+            params.handle.as_ref()
+                .map(|handle| handle.len().saturated_into())
+                .unwrap_or_default()
+            )
+        ]
         pub fn invite_member(
             origin,
             params: InviteMembershipParameters<T::AccountId, T::MemberId>
@@ -586,7 +691,15 @@ decl_module! {
         }
 
         /// Updates membership price. Requires root origin.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (1)`
+        /// - DB:
+        ///    - O(1) doesn't depend on the state or parameters
+        /// # </weight>
+        #[weight = WeightInfoMembership::<T>::set_membership_price()]
         pub fn set_membership_price(origin, new_price: BalanceOf<T>) {
             ensure_root(origin)?;
 
@@ -600,7 +713,15 @@ decl_module! {
         }
 
         /// Updates leader invitation quota. Requires root origin.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (1)`
+        /// - DB:
+        ///    - O(1) doesn't depend on the state or parameters
+        /// # </weight>
+        #[weight = WeightInfoMembership::<T>::set_leader_invitation_quota()]
         pub fn set_leader_invitation_quota(origin, invitation_quota: u32) {
             ensure_root(origin)?;
 
@@ -626,7 +747,15 @@ decl_module! {
         }
 
         /// Updates initial invitation balance for a invited member. Requires root origin.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (1)`
+        /// - DB:
+        ///    - O(1) doesn't depend on the state or parameters
+        /// # </weight>
+        #[weight = WeightInfoMembership::<T>::set_initial_invitation_balance()]
         pub fn set_initial_invitation_balance(origin, new_initial_balance: BalanceOf<T>) {
             ensure_root(origin)?;
 
@@ -640,7 +769,15 @@ decl_module! {
         }
 
         /// Updates initial invitation count for a member. Requires root origin.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (1)`
+        /// - DB:
+        ///    - O(1) doesn't depend on the state or parameters
+        /// # </weight>
+        #[weight = WeightInfoMembership::<T>::set_initial_invitation_count()]
         pub fn set_initial_invitation_count(origin, new_invitation_count: u32) {
             ensure_root(origin)?;
 
@@ -655,7 +792,15 @@ decl_module! {
 
         /// Add staking account candidate for a member.
         /// The membership must be confirmed before usage.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (1)`
+        /// - DB:
+        ///    - O(1) doesn't depend on the state or parameters
+        /// # </weight>
+        #[weight = WeightInfoMembership::<T>::add_staking_account_candidate()]
         pub fn add_staking_account_candidate(origin, member_id: T::MemberId) {
             let staking_account_id = ensure_signed(origin)?;
 
@@ -682,7 +827,15 @@ decl_module! {
         }
 
         /// Remove staking account for a member.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (1)`
+        /// - DB:
+        ///    - O(1) doesn't depend on the state or parameters
+        /// # </weight>
+        #[weight = WeightInfoMembership::<T>::remove_staking_account()]
         pub fn remove_staking_account(origin, member_id: T::MemberId) {
             let staking_account_id = ensure_signed(origin)?;
 
@@ -703,7 +856,15 @@ decl_module! {
         }
 
         /// Confirm staking account candidate for a member.
-        #[weight = 10_000_000] // TODO: adjust weight
+        ///
+        /// <weight>
+        ///
+        /// ## Weight
+        /// `O (1)`
+        /// - DB:
+        ///    - O(1) doesn't depend on the state or parameters
+        /// # </weight>
+        #[weight = WeightInfoMembership::<T>::confirm_staking_account()]
         pub fn confirm_staking_account(
             origin,
             member_id: T::MemberId,
@@ -739,6 +900,40 @@ decl_module! {
 }
 
 impl<T: Trait> Module<T> {
+    pub fn calculate_weight_for_update_account(
+        new_root_account: &Option<T::AccountId>,
+        new_controller_account: &Option<T::AccountId>,
+    ) -> Weight {
+        match (new_root_account.is_some(), new_controller_account.is_some()) {
+            (true, true) => WeightInfoMembership::<T>::update_accounts_both(),
+            (false, true) => WeightInfoMembership::<T>::update_accounts_root(),
+            (true, false) => WeightInfoMembership::<T>::update_accounts_controller(),
+            _ => WeightInfoMembership::<T>::update_accounts_both(),
+        }
+    }
+
+    pub fn calculate_weight_for_buy_membership(
+        params: &BuyMembershipParameters<T::AccountId, T::MemberId>,
+    ) -> Weight {
+        if params.referrer_id.is_some() {
+            WeightInfoMembership::<T>::buy_membership_with_referrer(
+                params
+                    .handle
+                    .as_ref()
+                    .map(|handle| handle.len().saturated_into())
+                    .unwrap_or_default(),
+            )
+        } else {
+            WeightInfoMembership::<T>::buy_membership_without_referrer(
+                params
+                    .handle
+                    .as_ref()
+                    .map(|handle| handle.len().saturated_into())
+                    .unwrap_or_default(),
+            )
+        }
+    }
+
     /// Provided that the member_id exists return its membership. Returns error otherwise.
     fn ensure_membership(member_id: T::MemberId) -> Result<Membership<T>, Error<T>> {
         Self::ensure_membership_with_error(member_id, Error::<T>::MemberProfileNotFound)

+ 78 - 4
runtime-modules/membership/src/tests/mock.rs

@@ -1,12 +1,11 @@
 #![cfg(test)]
 
-pub use crate::{GenesisConfig, Trait};
-
-use staking_handler::LockComparator;
+pub use crate::{GenesisConfig, Trait, Weight, WeightInfo};
 
 pub use frame_support::traits::{Currency, LockIdentifier};
 use frame_support::{impl_outer_event, impl_outer_origin, parameter_types};
 use sp_std::cell::RefCell;
+use staking_handler::LockComparator;
 
 use crate::tests::fixtures::ALICE_MEMBER_ID;
 pub use frame_system;
@@ -226,6 +225,63 @@ impl working_group::WeightInfo for Weights {
     }
 }
 
+impl WeightInfo for () {
+    fn buy_membership_without_referrer(_: u32) -> Weight {
+        0
+    }
+    fn buy_membership_with_referrer(_: u32) -> Weight {
+        0
+    }
+    fn update_profile(_: u32) -> Weight {
+        0
+    }
+    fn update_accounts_none() -> Weight {
+        0
+    }
+    fn update_accounts_root() -> Weight {
+        0
+    }
+    fn update_accounts_controller() -> Weight {
+        0
+    }
+    fn update_accounts_both() -> Weight {
+        0
+    }
+    fn set_referral_cut() -> Weight {
+        0
+    }
+    fn transfer_invites() -> Weight {
+        0
+    }
+    fn invite_member(_: u32) -> Weight {
+        0
+    }
+    fn set_membership_price() -> Weight {
+        0
+    }
+    fn update_profile_verification() -> Weight {
+        0
+    }
+    fn set_leader_invitation_quota() -> Weight {
+        0
+    }
+    fn set_initial_invitation_balance() -> Weight {
+        0
+    }
+    fn set_initial_invitation_count() -> Weight {
+        0
+    }
+    fn add_staking_account_candidate() -> Weight {
+        0
+    }
+    fn confirm_staking_account() -> Weight {
+        0
+    }
+    fn remove_staking_account() -> Weight {
+        0
+    }
+}
+
 impl common::origin::MemberOriginValidator<Origin, u64, u64> for () {
     fn ensure_member_controller_account_origin(
         origin: Origin,
@@ -247,6 +303,7 @@ impl Trait for Test {
     type WorkingGroup = ();
     type DefaultInitialInvitationBalance = DefaultInitialInvitationBalance;
     type InvitedMemberStakingHandler = staking_handler::StakingManager<Self, InvitedMemberLockId>;
+    type WeightInfo = ();
 }
 
 pub const WORKING_GROUP_BUDGET: u64 = 100;
@@ -276,7 +333,7 @@ impl common::working_group::WorkingGroupAuthenticator<Test> for () {
             origin.into();
 
         if let RawOrigin::Signed(_) = raw_origin.unwrap() {
-            if *worker_id == 1 {
+            if *worker_id == 1 || *worker_id == 0 {
                 Ok(())
             } else {
                 Err(working_group::Error::<Test, MembershipWorkingGroupInstance>::WorkerDoesNotExist.into())
@@ -306,6 +363,23 @@ impl common::working_group::WorkingGroupAuthenticator<Test> for () {
     }
 }
 
+#[cfg(feature = "runtime-benchmarks")]
+impl
+    crate::MembershipWorkingGroupHelper<
+        <Test as frame_system::Trait>::AccountId,
+        <Test as common::Trait>::MemberId,
+        <Test as common::Trait>::ActorId,
+    > for Test
+{
+    fn insert_a_lead(
+        _opening_id: u32,
+        _caller_id: &<Test as frame_system::Trait>::AccountId,
+        _member_id: <Test as common::Trait>::MemberId,
+    ) -> <Test as common::Trait>::ActorId {
+        ALICE_MEMBER_ID
+    }
+}
+
 pub struct TestExternalitiesBuilder<T: Trait> {
     system_config: Option<frame_system::GenesisConfig>,
     membership_config: Option<GenesisConfig<T>>,

+ 2 - 2
runtime-modules/membership/src/tests/mod.rs

@@ -4,8 +4,8 @@ pub(crate) mod fixtures;
 pub(crate) mod mock;
 
 use crate::{Error, Event};
-use fixtures::*;
-use mock::*;
+pub use fixtures::*;
+pub use mock::*;
 
 use common::origin::MemberOriginValidator;
 use common::working_group::WorkingGroupBudgetHandler;

+ 60 - 0
runtime-modules/proposals/codex/src/tests/mock.rs

@@ -51,10 +51,70 @@ impl common::Trait for Test {
     type ActorId = u64;
 }
 
+// Weights info stub
+pub struct Weights;
+impl membership::WeightInfo for Weights {
+    fn buy_membership_without_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn buy_membership_with_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_profile(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_none() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_root() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_controller() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_both() -> Weight {
+        unimplemented!()
+    }
+    fn set_referral_cut() -> Weight {
+        unimplemented!()
+    }
+    fn transfer_invites() -> Weight {
+        unimplemented!()
+    }
+    fn invite_member(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn set_membership_price() -> Weight {
+        unimplemented!()
+    }
+    fn update_profile_verification() -> Weight {
+        unimplemented!()
+    }
+    fn set_leader_invitation_quota() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_balance() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_count() -> Weight {
+        unimplemented!()
+    }
+    fn add_staking_account_candidate() -> Weight {
+        unimplemented!()
+    }
+    fn confirm_staking_account() -> Weight {
+        unimplemented!()
+    }
+    fn remove_staking_account() -> Weight {
+        unimplemented!()
+    }
+}
+
 impl membership::Trait for Test {
     type Event = ();
     type DefaultMembershipPrice = DefaultMembershipPrice;
     type WorkingGroup = ();
+    type WeightInfo = Weights;
     type DefaultInitialInvitationBalance = ();
     type InvitedMemberStakingHandler = staking_handler::StakingManager<Self, InvitedMemberLockId>;
 }

+ 60 - 0
runtime-modules/proposals/discussion/src/tests/mock.rs

@@ -77,6 +77,65 @@ parameter_types! {
     pub const InvitedMemberLockId: [u8; 8] = [2; 8];
 }
 
+// Weights info stub
+pub struct Weights;
+impl membership::WeightInfo for Weights {
+    fn buy_membership_without_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn buy_membership_with_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_profile(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_none() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_root() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_controller() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_both() -> Weight {
+        unimplemented!()
+    }
+    fn set_referral_cut() -> Weight {
+        unimplemented!()
+    }
+    fn transfer_invites() -> Weight {
+        unimplemented!()
+    }
+    fn invite_member(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn set_membership_price() -> Weight {
+        unimplemented!()
+    }
+    fn update_profile_verification() -> Weight {
+        unimplemented!()
+    }
+    fn set_leader_invitation_quota() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_balance() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_count() -> Weight {
+        unimplemented!()
+    }
+    fn add_staking_account_candidate() -> Weight {
+        unimplemented!()
+    }
+    fn confirm_staking_account() -> Weight {
+        unimplemented!()
+    }
+    fn remove_staking_account() -> Weight {
+        unimplemented!()
+    }
+}
+
 impl balances::Trait for Test {
     type Balance = u64;
     type DustRemoval = ();
@@ -96,6 +155,7 @@ impl membership::Trait for Test {
     type Event = TestEvent;
     type DefaultMembershipPrice = DefaultMembershipPrice;
     type WorkingGroup = ();
+    type WeightInfo = Weights;
     type DefaultInitialInvitationBalance = ();
     type InvitedMemberStakingHandler = staking_handler::StakingManager<Self, InvitedMemberLockId>;
 }

+ 60 - 0
runtime-modules/proposals/engine/src/tests/mock/mod.rs

@@ -188,10 +188,70 @@ impl common::Trait for Test {
     type ActorId = u64;
 }
 
+// Weights info stub
+pub struct Weights;
+impl membership::WeightInfo for Weights {
+    fn buy_membership_without_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn buy_membership_with_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_profile(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_none() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_root() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_controller() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_both() -> Weight {
+        unimplemented!()
+    }
+    fn set_referral_cut() -> Weight {
+        unimplemented!()
+    }
+    fn transfer_invites() -> Weight {
+        unimplemented!()
+    }
+    fn invite_member(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn set_membership_price() -> Weight {
+        unimplemented!()
+    }
+    fn update_profile_verification() -> Weight {
+        unimplemented!()
+    }
+    fn set_leader_invitation_quota() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_balance() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_count() -> Weight {
+        unimplemented!()
+    }
+    fn add_staking_account_candidate() -> Weight {
+        unimplemented!()
+    }
+    fn confirm_staking_account() -> Weight {
+        unimplemented!()
+    }
+    fn remove_staking_account() -> Weight {
+        unimplemented!()
+    }
+}
+
 impl membership::Trait for Test {
     type Event = TestEvent;
     type DefaultMembershipPrice = DefaultMembershipPrice;
     type WorkingGroup = ();
+    type WeightInfo = Weights;
     type DefaultInitialInvitationBalance = ();
     type InvitedMemberStakingHandler = staking_handler::StakingManager<Self, InvitedMemberLockId>;
 }

+ 60 - 0
runtime-modules/referendum/src/mock.rs

@@ -171,6 +171,65 @@ impl WeightInfo for () {
     }
 }
 
+// Weights info stub
+pub struct Weights;
+impl membership::WeightInfo for Weights {
+    fn buy_membership_without_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn buy_membership_with_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_profile(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_none() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_root() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_controller() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_both() -> Weight {
+        unimplemented!()
+    }
+    fn set_referral_cut() -> Weight {
+        unimplemented!()
+    }
+    fn transfer_invites() -> Weight {
+        unimplemented!()
+    }
+    fn invite_member(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn set_membership_price() -> Weight {
+        unimplemented!()
+    }
+    fn update_profile_verification() -> Weight {
+        unimplemented!()
+    }
+    fn set_leader_invitation_quota() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_balance() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_count() -> Weight {
+        unimplemented!()
+    }
+    fn add_staking_account_candidate() -> Weight {
+        unimplemented!()
+    }
+    fn confirm_staking_account() -> Weight {
+        unimplemented!()
+    }
+    fn remove_staking_account() -> Weight {
+        unimplemented!()
+    }
+}
+
 parameter_types! {
     pub const DefaultMembershipPrice: u64 = 100;
     pub const DefaultInitialInvitationBalance: u64 = 100;
@@ -181,6 +240,7 @@ impl membership::Trait for Runtime {
     type Event = TestEvent;
     type DefaultMembershipPrice = DefaultMembershipPrice;
     type WorkingGroup = ();
+    type WeightInfo = Weights;
     type DefaultInitialInvitationBalance = DefaultInitialInvitationBalance;
     type InvitedMemberStakingHandler = staking_handler::StakingManager<Self, InvitedMemberLockId>;
 }

+ 60 - 0
runtime-modules/service-discovery/src/mock.rs

@@ -93,10 +93,70 @@ impl common::Trait for Test {
     type ActorId = u64;
 }
 
+// Weights info stub
+pub struct Weights;
+impl membership::WeightInfo for Weights {
+    fn buy_membership_without_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn buy_membership_with_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_profile(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_none() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_root() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_controller() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_both() -> Weight {
+        unimplemented!()
+    }
+    fn set_referral_cut() -> Weight {
+        unimplemented!()
+    }
+    fn transfer_invites() -> Weight {
+        unimplemented!()
+    }
+    fn invite_member(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn set_membership_price() -> Weight {
+        unimplemented!()
+    }
+    fn update_profile_verification() -> Weight {
+        unimplemented!()
+    }
+    fn set_leader_invitation_quota() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_balance() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_count() -> Weight {
+        unimplemented!()
+    }
+    fn add_staking_account_candidate() -> Weight {
+        unimplemented!()
+    }
+    fn confirm_staking_account() -> Weight {
+        unimplemented!()
+    }
+    fn remove_staking_account() -> Weight {
+        unimplemented!()
+    }
+}
+
 impl membership::Trait for Test {
     type Event = MetaEvent;
     type DefaultMembershipPrice = DefaultMembershipPrice;
     type WorkingGroup = ();
+    type WeightInfo = Weights;
     type DefaultInitialInvitationBalance = ();
     type InvitedMemberStakingHandler = staking_handler::StakingManager<Self, InvitedMemberLockId>;
 }

+ 60 - 0
runtime-modules/storage/src/tests/mock.rs

@@ -243,6 +243,65 @@ impl working_group::WeightInfo for WorkingGroupWeightInfo {
     }
 }
 
+// Weights info stub
+pub struct Weights;
+impl membership::WeightInfo for Weights {
+    fn buy_membership_without_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn buy_membership_with_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_profile(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_none() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_root() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_controller() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_both() -> Weight {
+        unimplemented!()
+    }
+    fn set_referral_cut() -> Weight {
+        unimplemented!()
+    }
+    fn transfer_invites() -> Weight {
+        unimplemented!()
+    }
+    fn invite_member(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn set_membership_price() -> Weight {
+        unimplemented!()
+    }
+    fn update_profile_verification() -> Weight {
+        unimplemented!()
+    }
+    fn set_leader_invitation_quota() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_balance() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_count() -> Weight {
+        unimplemented!()
+    }
+    fn add_staking_account_candidate() -> Weight {
+        unimplemented!()
+    }
+    fn confirm_staking_account() -> Weight {
+        unimplemented!()
+    }
+    fn remove_staking_account() -> Weight {
+        unimplemented!()
+    }
+}
+
 impl common::origin::MemberOriginValidator<Origin, u64, u64> for () {
     fn ensure_member_controller_account_origin(
         origin: Origin,
@@ -294,6 +353,7 @@ impl membership::Trait for Test {
     type Event = MetaEvent;
     type DefaultMembershipPrice = DefaultMembershipPrice;
     type WorkingGroup = ();
+    type WeightInfo = Weights;
     type DefaultInitialInvitationBalance = ();
     type InvitedMemberStakingHandler = staking_handler::StakingManager<Self, InvitedMemberLockId>;
 }

+ 26 - 6
runtime-modules/working-group/src/benchmarking.rs

@@ -18,7 +18,7 @@ use membership::Module as Membership;
 const SEED: u32 = 0;
 const MAX_BYTES: u32 = 16384;
 
-enum StakingRole {
+pub enum StakingRole {
     WithStakes,
     WithoutStakes,
 }
@@ -219,7 +219,7 @@ fn force_missed_reward<T: Trait<I>, I: Instance>() {
     WorkingGroup::<T, _>::on_initialize(curr_block_number);
 }
 
-fn insert_a_worker<T: Trait<I> + membership::Trait, I: Instance>(
+pub fn insert_a_worker<T: Trait<I> + membership::Trait, I: Instance>(
     staking_role: StakingRole,
     job_opening_type: OpeningType,
     id: u32,
@@ -228,18 +228,38 @@ fn insert_a_worker<T: Trait<I> + membership::Trait, I: Instance>(
 where
     WorkingGroup<T, I>: OnInitialize<T::BlockNumber>,
 {
+    let (caller_id, member_id) = member_funded_account::<T, I>("member", id);
+
+    let worker_id = complete_opening::<T, I>(
+        staking_role,
+        job_opening_type,
+        id,
+        lead_id,
+        &caller_id,
+        member_id,
+    );
+
+    (caller_id, worker_id)
+}
+
+pub fn complete_opening<T: Trait<I> + membership::Trait, I: Instance>(
+    staking_role: StakingRole,
+    job_opening_type: OpeningType,
+    id: u32,
+    lead_id: Option<T::AccountId>,
+    caller_id: &T::AccountId,
+    member_id: T::MemberId,
+) -> WorkerId<T> {
     let add_worker_origin = match job_opening_type {
         OpeningType::Leader => RawOrigin::Root,
         OpeningType::Regular => RawOrigin::Signed(lead_id.clone().unwrap()),
     };
 
-    let (caller_id, member_id) = member_funded_account::<T, I>("member", id);
-
     let (opening_id, application_id) = add_and_apply_opening::<T, I>(
         id,
         &T::Origin::from(add_worker_origin.clone()),
         &staking_role,
-        &caller_id,
+        caller_id,
         &member_id,
         &job_opening_type,
     );
@@ -261,7 +281,7 @@ where
 
     assert!(WorkerById::<T, I>::contains_key(worker_id));
 
-    (caller_id, worker_id)
+    worker_id
 }
 
 benchmarks_instance! {

+ 60 - 0
runtime-modules/working-group/src/tests/mock.rs

@@ -97,10 +97,70 @@ impl common::Trait for Test {
     type ActorId = u64;
 }
 
+// Weights info stub
+pub struct Weights;
+impl membership::WeightInfo for Weights {
+    fn buy_membership_without_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn buy_membership_with_referrer(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_profile(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_none() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_root() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_controller() -> Weight {
+        unimplemented!()
+    }
+    fn update_accounts_both() -> Weight {
+        unimplemented!()
+    }
+    fn set_referral_cut() -> Weight {
+        unimplemented!()
+    }
+    fn transfer_invites() -> Weight {
+        unimplemented!()
+    }
+    fn invite_member(_: u32) -> Weight {
+        unimplemented!()
+    }
+    fn set_membership_price() -> Weight {
+        unimplemented!()
+    }
+    fn update_profile_verification() -> Weight {
+        unimplemented!()
+    }
+    fn set_leader_invitation_quota() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_balance() -> Weight {
+        unimplemented!()
+    }
+    fn set_initial_invitation_count() -> Weight {
+        unimplemented!()
+    }
+    fn add_staking_account_candidate() -> Weight {
+        unimplemented!()
+    }
+    fn confirm_staking_account() -> Weight {
+        unimplemented!()
+    }
+    fn remove_staking_account() -> Weight {
+        unimplemented!()
+    }
+}
+
 impl membership::Trait for Test {
     type Event = TestEvent;
     type DefaultMembershipPrice = DefaultMembershipPrice;
     type WorkingGroup = Module<Test>;
+    type WeightInfo = Weights;
     type DefaultInitialInvitationBalance = ();
     type InvitedMemberStakingHandler = staking_handler::StakingManager<Self, InvitedMemberLockId>;
 }

+ 1 - 0
runtime/Cargo.toml

@@ -170,6 +170,7 @@ runtime-benchmarks = [
     "pallet_constitution/runtime-benchmarks",
     "working-group/runtime-benchmarks",
     "forum/runtime-benchmarks",
+    "membership/runtime-benchmarks",
     "council/runtime-benchmarks",
     "referendum/runtime-benchmarks",
     "hex-literal",

+ 3 - 1
runtime/src/lib.rs

@@ -72,6 +72,7 @@ pub use content_directory::{
 pub use council;
 pub use forum;
 pub use membership;
+
 #[cfg(any(feature = "std", test))]
 pub use pallet_balances::Call as BalancesCall;
 pub use pallet_staking::StakerStatus;
@@ -634,9 +635,10 @@ impl common::Trait for Runtime {
 impl membership::Trait for Runtime {
     type Event = Event;
     type DefaultMembershipPrice = DefaultMembershipPrice;
-    type WorkingGroup = MembershipWorkingGroup;
     type DefaultInitialInvitationBalance = DefaultInitialInvitationBalance;
     type InvitedMemberStakingHandler = InvitedMemberStakingManager;
+    type WorkingGroup = MembershipWorkingGroup;
+    type WeightInfo = weights::membership::WeightInfo;
 }
 
 parameter_types! {

+ 24 - 0
runtime/src/runtime_api.rs

@@ -287,6 +287,7 @@ impl_runtime_apis! {
             use crate::ProposalsCodex;
             use crate::Constitution;
             use crate::Forum;
+            use crate::Members;
             use crate::ContentDirectoryWorkingGroup;
             use crate::Utility;
             use crate::Timestamp;
@@ -316,6 +317,28 @@ impl_runtime_apis! {
                 }
             }
 
+            impl membership::MembershipWorkingGroupHelper<
+                <Runtime as frame_system::Trait>::AccountId,
+                <Runtime as common::Trait>::MemberId,
+                <Runtime as common::Trait>::ActorId,
+                    > for Runtime
+            {
+                fn insert_a_lead(
+                    opening_id: u32,
+                    caller_id: &<Runtime as frame_system::Trait>::AccountId,
+                    member_id: <Runtime as common::Trait>::MemberId,
+                ) -> <Runtime as common::Trait>::ActorId {
+                    working_group::benchmarking::complete_opening::<Runtime, crate::MembershipWorkingGroupInstance>(
+                        working_group::benchmarking::StakingRole::WithStakes,
+                        working_group::OpeningType::Leader,
+                        opening_id,
+                        None,
+                        &caller_id,
+                        member_id,
+                    )
+                }
+            }
+
             let whitelist: Vec<TrackedStorageKey> = vec![
                 // Block Number
                 hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),
@@ -354,6 +377,7 @@ impl_runtime_apis! {
             add_benchmark!(params, batches, proposals_discussion, ProposalsDiscussion);
             add_benchmark!(params, batches, proposals_codex, ProposalsCodex);
             add_benchmark!(params, batches, proposals_engine, ProposalsEngine);
+            add_benchmark!(params, batches, membership, Members);
             add_benchmark!(params, batches, forum, Forum);
             add_benchmark!(params, batches, pallet_constitution, Constitution);
             add_benchmark!(params, batches, working_group, ContentDirectoryWorkingGroup);

+ 94 - 0
runtime/src/weights/membership.rs

@@ -0,0 +1,94 @@
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0
+
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::weights::{constants::RocksDbWeight as DbWeight, Weight};
+
+pub struct WeightInfo;
+impl membership::WeightInfo for WeightInfo {
+    fn buy_membership_without_referrer(i: u32) -> Weight {
+        (353_184_000 as Weight)
+            .saturating_add((2_000 as Weight).saturating_mul(i as Weight))
+            .saturating_add(DbWeight::get().reads(5 as Weight))
+            .saturating_add(DbWeight::get().writes(4 as Weight))
+    }
+    fn buy_membership_with_referrer(i: u32) -> Weight {
+        (554_008_000 as Weight)
+            .saturating_add((2_000 as Weight).saturating_mul(i as Weight))
+            .saturating_add(DbWeight::get().reads(7 as Weight))
+            .saturating_add(DbWeight::get().writes(4 as Weight))
+    }
+    fn update_profile(i: u32) -> Weight {
+        (446_195_000 as Weight)
+            .saturating_add((72_000 as Weight).saturating_mul(i as Weight))
+            .saturating_add(DbWeight::get().reads(2 as Weight))
+            .saturating_add(DbWeight::get().writes(3 as Weight))
+    }
+    fn update_accounts_none() -> Weight {
+        (11_101_000 as Weight)
+    }
+    fn update_accounts_root() -> Weight {
+        (224_926_000 as Weight)
+            .saturating_add(DbWeight::get().reads(1 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn update_accounts_controller() -> Weight {
+        (224_476_000 as Weight)
+            .saturating_add(DbWeight::get().reads(1 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn update_accounts_both() -> Weight {
+        (224_616_000 as Weight)
+            .saturating_add(DbWeight::get().reads(1 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn set_referral_cut() -> Weight {
+        (78_995_000 as Weight).saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn transfer_invites() -> Weight {
+        (507_472_000 as Weight)
+            .saturating_add(DbWeight::get().reads(2 as Weight))
+            .saturating_add(DbWeight::get().writes(2 as Weight))
+    }
+    fn invite_member(i: u32) -> Weight {
+        (657_622_000 as Weight)
+            .saturating_add((2_000 as Weight).saturating_mul(i as Weight))
+            .saturating_add(DbWeight::get().reads(6 as Weight))
+            .saturating_add(DbWeight::get().writes(6 as Weight))
+    }
+    fn set_membership_price() -> Weight {
+        (78_998_000 as Weight).saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn update_profile_verification() -> Weight {
+        (382_380_000 as Weight)
+            .saturating_add(DbWeight::get().reads(2 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn set_leader_invitation_quota() -> Weight {
+        (352_240_000 as Weight)
+            .saturating_add(DbWeight::get().reads(3 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn set_initial_invitation_balance() -> Weight {
+        (76_451_000 as Weight).saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn set_initial_invitation_count() -> Weight {
+        (70_621_000 as Weight).saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn add_staking_account_candidate() -> Weight {
+        (214_287_000 as Weight)
+            .saturating_add(DbWeight::get().reads(2 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn confirm_staking_account() -> Weight {
+        (324_026_000 as Weight)
+            .saturating_add(DbWeight::get().reads(2 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn remove_staking_account() -> Weight {
+        (247_835_000 as Weight)
+            .saturating_add(DbWeight::get().reads(2 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+}

+ 1 - 0
runtime/src/weights/mod.rs

@@ -26,6 +26,7 @@ pub mod pallet_utility;
 // Joystream pallets
 pub mod council;
 pub mod forum;
+pub mod membership;
 pub mod pallet_constitution;
 pub mod proposals_codex;
 pub mod proposals_discussion;

+ 2 - 0
scripts/generate-weights.sh

@@ -52,3 +52,5 @@ benchmark pallet_constitution
 benchmark working_group
 benchmark council
 benchmark referendum
+benchmark forum
+benchmark membership