Browse Source

Merge: blog module into olympia

conectado 4 years ago
parent
commit
1e24dd0748

+ 5 - 0
analyses/fee-analysis/.gitignore

@@ -0,0 +1,5 @@
+.ipynb_checkpoints/
+.vim/
+__pycache__/
+.venv/
+*.csv

+ 35 - 0
analyses/fee-analysis/README.md

@@ -0,0 +1,35 @@
+# Fee analysis
+
+This directory has a CLI to output the analysis of weights into a `CSV` and a more interactive notebook
+
+
+
+## Requirements
+
+* python3
+* (virtualenv)[https://pypi.org/project/virtualenv/]
+
+## Steps to run
+* `virtualenv .venv`
+* `source .venv/bin/activate`
+* `pip install -r requirements.txt`
+* `jupyter notebook`
+* a browser tab should launch with the files in this directory
+
+## To run the CLI
+* `python analysis_cli --help` will output the help
+
+You will need to provide a path to a directory containing the weight files or the path to a single
+weight file.
+
+For the CSV to include an analysis pass the parameter `-p` (Meaning the calculated price in tokens and prices)
+
+The `config.json` file in the `analysis_cli` there is configuration for said analysis. Such as specializing the
+parametrs and length for a given extrinsics, the coefficients, issuance and marke caps.
+
+**Note:** The output csv file already sums the `EXTRINSIC_BASE_WEIGHT` to the weight column
+
+## To run the notebook
+
+* open `main_notebook.ipynb`
+* The notebook has the information on how to proceed

+ 61 - 0
analyses/fee-analysis/analysis_cli/__main__.py

@@ -0,0 +1,61 @@
+from parser import parse_weights
+from pathlib import Path
+import pathlib
+import argparse
+from os import listdir
+import os
+from analysis import get_weight_info
+import json
+
+
+def main():
+    arg_parser = argparse.ArgumentParser(description="Fee analysis")
+    arg_parser.add_argument(
+        'weight_path', type=str, help='Path to weight files or directory with weights'
+    )
+    arg_parser.add_argument('-o', '--output', type=str,
+                            help='Path for csv file defaults to output.csv', default="output.csv")
+    arg_parser.add_argument('-c', '--config', type=str,
+                            help='Path of a config file', default=Path(__file__).parent / "config.json")
+    arg_parser.add_argument('-p', '--process-data', action='store_true',
+                            help='Process data given a config if not used only weights will be dumped into the csv output')
+
+    args = arg_parser.parse_args()
+    weight_path = args.weight_path
+    output_file = args.output
+    config_file = args.config
+    process_data = args.process_data
+
+    with open(config_file) as f:
+        config = json.load(f)
+
+    weight_coeff = config.get("weight_coefficient", 0)
+    issuance = config.get("issuance", 0)
+    length_coeff = config.get("length_coefficient", 0)
+    min_market_cap = config.get("min_market_cap", 0)
+    max_market_cap = config.get("max_market_cap", 0)
+    lengths = config.get("lengths", {})
+    params = config.get("params", {})
+
+    w = {}
+
+    if os.path.isdir(weight_path):
+        for f in listdir(weight_path):
+            path = weight_path + f
+            if os.path.isfile(path):
+                w |= parse_weights(weight_path + f)
+    elif os.path.isfile(weight_path):
+        w = parse_weights(weight_path)
+    else:
+        print("Error: ", weight_path, " is not a valid directory or file")
+
+    df = get_weight_info(w, weight_coeff, issuance,
+                         length_coeff, min_market_cap, max_market_cap, params, lengths)
+    if process_data:
+        df.to_csv(output_file, index=False, )
+    else:
+        df.to_csv(output_file, index=False, columns=["Extrinsic", "Weight"])
+
+
+if __name__ == '__main__':
+    main()

+ 172 - 0
analyses/fee-analysis/analysis_cli/analysis.py

@@ -0,0 +1,172 @@
+import pandas as pd
+from constants import *
+
+
+def weight_to_fee(weight, coeff):
+    return coeff * weight
+
+
+def length_to_fee(length, coeff):
+    return coeff * length
+
+
+def token_to_price(token, market_cap, issuance):
+    return (market_cap / issuance) * token
+
+
+def price_weight_function(x, weight_coefficient, market_cap, issuance):
+    return token_to_price(weight_to_fee(x, weight_coefficient), market_cap, issuance)
+
+
+def price_length_function(x, length_coefficient, market_cap, issuance):
+    return token_to_price(length_to_fee(x, length_coefficient), market_cap, issuance)
+
+
+def print_var_err(var, extrn):
+    print("WARNING: the parameter {} isn't defined in the calculation for extrinsic: {}".format(
+        var[0], extrn))
+
+
+def calc_vars_weight(weight, extrinsic, params):
+    total = 0
+    if extrinsic in params:
+        for var in weight[VARS]:
+            if var[0] in params[extrinsic]:
+                total += params[extrinsic][var[0]] * var[1]
+            else:
+                print_var_err(var, extrinsic)
+        for var in weight[DB_READS][DB_VARS]:
+            if var[0] in params[extrinsic]:
+                total += params[extrinsic][var[0]] * var[1] * READ_WEIGHT
+            else:
+                print_var_err(var, extrinsic)
+        for var in weight[DB_WRITES][DB_VARS]:
+            if var[0] in params[extrinsic]:
+                total += params[extrinsic][var] * WRITE_WEIGHT
+            else:
+                print_var_err(var, extrinsic)
+    return total
+
+
+def calc_weight(weight, extrinsic, params):
+    vars_weight = calc_vars_weight(weight, extrinsic, params)
+    return vars_weight + \
+        weight[BASE_WEIGHT] + \
+        weight[DB_READS][BASE_DB] * READ_WEIGHT + \
+        weight[DB_WRITES][BASE_DB] * WRITE_WEIGHT + EXTRINSIC_BASE_WEIGHT
+
+
+def calc_total_price_given_params(extrinsic, weight_coeff, market_cap, issuance, length_coeff, params, lengths, weights):
+    return price_weight_function(calc_weight(weights[extrinsic], extrinsic, params), weight_coeff, market_cap, issuance) + \
+        price_length_function(lengths.get(extrinsic, 0),
+                              length_coeff, market_cap, issuance)
+
+
+def calc_total_fee(extrinsic, weight_coeff, length_coeff, params, lengths, weights):
+    return weight_to_fee(calc_weight(weights[extrinsic], extrinsic, params) + EXTRINSIC_BASE_WEIGHT, weight_coeff) + \
+        length_to_fee(lengths.get(extrinsic, 0), length_coeff)
+
+
+def get_computed_values(
+    extrinsic,
+    weight_model,
+    weight_coeff,
+    min_market_cap,
+    max_market_cap,
+    issuance,
+    length_coeff,
+    params,
+    lengths,
+    weights
+):
+    weight = calc_weight(weight_model, extrinsic, params)
+    tokens = calc_total_fee(extrinsic, weight_coeff,
+                            length_coeff, params, lengths, weights)
+    min_price = calc_total_price_given_params(
+        extrinsic,
+        weight_coeff,
+        min_market_cap,
+        issuance,
+        length_coeff,
+        params,
+        lengths,
+        weights
+    )
+    max_price = calc_total_price_given_params(
+        extrinsic,
+        weight_coeff,
+        max_market_cap,
+        issuance,
+        length_coeff,
+        params,
+        lengths,
+        weights
+    )
+    return weight, tokens, min_price, max_price
+
+
+def calc_all_price(weight_coeff, issuance, length_coeff, min_market_cap, max_market_cap, weights, params, lengths):
+    names = []
+    computed_weights = []
+    computed_tokens = []
+    min_prices = []
+    max_prices = []
+    for (key, val) in weights.items():
+        weight, tokens, min_price, max_price = get_computed_values(
+            key,
+            val,
+            weight_coeff,
+            min_market_cap,
+            max_market_cap,
+            issuance,
+            length_coeff,
+            params,
+            lengths,
+            weights
+        )
+        names.append(key)
+        computed_weights.append(weight)
+        min_prices.append(min_price)
+        max_prices.append(max_price)
+        computed_tokens.append(tokens)
+
+    weight_table = {
+        "Extrinsic": names,
+        "Weight": computed_weights,
+        "Tokens(JOY)": computed_tokens,
+        "Min Price(¢)": min_prices,
+        "Max Price(¢)": max_prices
+    }
+    df = pd.DataFrame(weight_table)
+
+    return df, min_prices, max_prices
+
+
+def get_weight_info(weights, weight_coeff=1, issuance=1, length_coeff=1, min_market_cap=1, max_market_cap=1, params={},
+                    lengths={}):
+    weights[RUNTIME_UPGRADE] = {
+        BASE_WEIGHT: MAX_BLOCK_WEIGHT,
+        DB_READS: {
+            BASE_DB: 0,
+            DB_VARS: []
+        },
+        DB_WRITES: {
+            BASE_DB: 0,
+            DB_VARS: []
+        },
+        VARS: []
+
+    }
+
+    df, _, _ = calc_all_price(
+        weight_coeff,
+        issuance,
+        length_coeff,
+        min_market_cap,
+        max_market_cap,
+        weights,
+        params,
+        lengths,
+    )
+
+    return df

+ 15 - 0
analyses/fee-analysis/analysis_cli/config.json

@@ -0,0 +1,15 @@
+{
+    "weight_coefficient": 2,
+    "issuance": 250000000,
+    "length_coefficient": 1,
+    "min_market_cap": 1250000,
+    "max_market_cap": 100000000000,
+    "lengths": {
+        "runtime_upgrade": 0
+    },
+    "params": {
+        "proposals_discussion::add_post": {
+            "i": 0
+        }
+    }
+}

+ 14 - 0
analyses/fee-analysis/analysis_cli/constants.py

@@ -0,0 +1,14 @@
+RUNTIME_UPGRADE = "proposal_codex::runtime_upgrade"
+BASE_WEIGHT = "base_weight"
+DB_READS = "db_reads"
+DB_WRITES = "db_writes"
+BASE_DB = "base"
+DB_VARS = "vars"
+VARS = "vars"
+WRITE_WEIGHT = 100 * 1_000_000
+READ_WEIGHT = 25 * 1_000_000
+WEIGHT_PER_SECOND = 1_000_000_000_000
+WEIGHT_PER_MILLIS = WEIGHT_PER_SECOND / 1000  # 1_000_000_000
+WEIGHT_PER_MICROS = WEIGHT_PER_MILLIS / 1000  # 1_000_000
+MAX_BLOCK_WEIGHT = 2 * 1_000_000_000_000
+EXTRINSIC_BASE_WEIGHT = 125 * WEIGHT_PER_MICROS

+ 96 - 0
analyses/fee-analysis/analysis_cli/parser.py

@@ -0,0 +1,96 @@
+import re
+from constants import *
+
+
+match_parenthesis = r'\(.*'
+match_base_weight = r'\(((\d+_{0,1})+)'
+re_match_base_weight = re.compile(match_base_weight)
+match_db_ops_reads = r'DbWeight::get\(\).reads\((\d+) as Weight\)'
+match_db_ops_writes = r'DbWeight::get\(\).writes\((\d+) as Weight\)'
+re_match_db_ops_reads = re.compile(match_db_ops_reads)
+re_match_db_ops_writes = re.compile(match_db_ops_writes)
+match_scaling_var = r'\((\D) as Weight\)'
+re_match_scaling_var = re.compile(match_scaling_var)
+
+
+def parse_weights(weight_file):
+    weights = {}
+    with open(weight_file) as f:
+        start_reading = False
+        reading_func = False
+        function_name = ""
+        weight = 0
+        db_reads_base = 0
+        db_reads = []
+        db_writes_base = 0
+        db_writes = []
+        variables = []
+        pallet_name = ""
+        for line in f:
+            words = line.strip().split(" ")
+            if words[0] == "impl":
+                start_reading = True
+                pallet_name = words[1].split("::")[0]
+
+            if reading_func:
+                if reading_func and "}" in words:
+                    reading_func = False
+                    weights[function_name] = {
+                        BASE_WEIGHT: weight,
+                        DB_READS: {
+                            BASE_DB: db_reads_base,
+                            DB_VARS: db_reads
+                        },
+                        DB_WRITES: {
+                            BASE_DB: db_writes_base,
+                            DB_VARS: db_writes,
+                        },
+                        VARS: variables
+                    }
+                    weight = 0
+                    db_reads_base = 0
+                    db_writes_base = 0
+                    variables = []
+                    db_reads = []
+                    db_writes = []
+
+                if "DbWeight::get()" in line:
+                    if "reads" in line:
+                        if re.search(re_match_scaling_var, line):
+                            var = re.search(
+                                re_match_scaling_var, line).group(1)
+                            weight_factor = re.search(
+                                re_match_base_weight, line).group(1)
+                            db_reads.append((var, int(weight_factor)))
+                        else:
+                            db_reads_base = int(
+                                re.search(re_match_db_ops_reads, line).group(1))
+
+                    if "writes" in line:
+                        if re.search(re_match_scaling_var, line):
+                            var = re.search(
+                                re_match_scaling_var, line).group(1)
+                            weight_factor = re.search(
+                                re_match_base_weight, line).group(1)
+                            db_writes.append((var, int(weight_factor)))
+                        else:
+                            db_writes_base = int(
+                                re.search(re_match_db_ops_writes, line).group(1))
+                else:
+                    if re.match(re_match_base_weight, words[0]) is not None:
+                        match = re.match(re_match_base_weight, words[0])
+                        weight = int(match.group(1))
+
+                    if re.search(re_match_scaling_var, line):
+                        var = re.search(
+                            re_match_scaling_var, line).group(1)
+                        weight_factor = re.search(
+                            re_match_base_weight, line).group(1)
+                        variables.append((var, int(weight_factor)))
+
+            if start_reading and words[0] == "fn":
+                reading_func = True
+                function_name = re.sub(match_parenthesis, '', words[1])
+                function_name = pallet_name + "::" + function_name
+
+    return weights

File diff suppressed because it is too large
+ 2294 - 0
analyses/fee-analysis/main_notebook.ipynb


+ 73 - 0
analyses/fee-analysis/requirements.txt

@@ -0,0 +1,73 @@
+argon2-cffi==20.1.0
+astroid==2.4.2
+async-generator==1.10
+attrs==20.3.0
+autopep8==1.5.4
+backcall==0.2.0
+bleach==3.2.2
+cffi==1.14.4
+cycler==0.10.0
+decorator==4.4.2
+defusedxml==0.6.0
+entrypoints==0.3
+ipykernel==5.4.3
+ipympl==0.6.3
+ipython==7.19.0
+ipython-genutils==0.2.0
+ipywidgets==7.6.3
+isort==5.7.0
+jedi==0.18.0
+Jinja2==2.11.2
+jsonschema==3.2.0
+jupyter==1.0.0
+jupyter-client==6.1.11
+jupyter-console==6.2.0
+jupyter-core==4.7.0
+jupyterlab-pygments==0.1.2
+jupyterlab-widgets==1.0.0
+kiwisolver==1.3.1
+lazy-object-proxy==1.4.3
+MarkupSafe==1.1.1
+matplotlib==3.3.3
+mccabe==0.6.1
+mistune==0.8.4
+nbclient==0.5.1
+nbconvert==6.0.7
+nbformat==5.1.2
+nest-asyncio==1.4.3
+notebook==6.2.0
+numpy==1.19.5
+packaging==20.8
+pandas==1.2.1
+pandocfilters==1.4.3
+parso==0.8.1
+pexpect==4.8.0
+pickleshare==0.7.5
+Pillow==8.1.0
+prometheus-client==0.9.0
+prompt-toolkit==3.0.14
+ptyprocess==0.7.0
+pycodestyle==2.6.0
+pycparser==2.20
+Pygments==2.7.4
+pylint==2.6.0
+pyparsing==2.4.7
+pyrsistent==0.17.3
+python-dateutil==2.8.1
+pytz==2020.5
+pyzmq==21.0.2
+qtconsole==5.0.2
+QtPy==1.9.0
+rope==0.18.0
+scipy==1.6.0
+Send2Trash==1.5.0
+six==1.15.0
+terminado==0.9.2
+testpath==0.4.4
+toml==0.10.2
+tornado==6.1
+traitlets==5.0.5
+wcwidth==0.2.5
+webencodings==0.5.1
+widgetsnbextension==3.5.1
+wrapt==1.12.1

+ 1 - 1
runtime-modules/common/src/lib.rs

@@ -62,7 +62,7 @@ pub struct BlockAndTime<BlockNumber, Moment> {
 
 /// Parameters for the 'Funding Request' proposal.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Encode, Decode, Clone, PartialEq, Debug)]
+#[derive(Encode, Decode, Clone, PartialEq, Debug, Eq)]
 pub struct FundingRequestParameters<Balance, AccountId> {
     /// Single reciever account of funding request
     pub account: AccountId,

+ 9 - 6
runtime-modules/membership/src/benchmarking.rs

@@ -152,7 +152,7 @@ benchmarks! {
 
         assert_eq!(MembershipById::<T>::get(member_id), membership);
 
-        assert_last_event::<T>(RawEvent::MemberRegistered(member_id).into());
+        assert_last_event::<T>(RawEvent::MembershipBought(member_id).into());
     }
 
     buy_membership_with_referrer{
@@ -232,7 +232,7 @@ benchmarks! {
 
         assert_eq!(MembershipById::<T>::get(second_member_id), membership);
 
-        assert_last_event::<T>(RawEvent::MemberRegistered(second_member_id).into());
+        assert_last_event::<T>(RawEvent::MembershipBought(second_member_id).into());
     }
 
     update_profile{
@@ -503,7 +503,7 @@ benchmarks! {
 
         assert_eq!(MembershipById::<T>::get(invited_member_id), invited_membership);
 
-        assert_last_event::<T>(RawEvent::MemberRegistered(invited_member_id).into());
+        assert_last_event::<T>(RawEvent::MemberInvited(invited_member_id).into());
 
     }
 
@@ -760,9 +760,12 @@ mod tests {
 
     #[test]
     fn set_leader_invitation_quota() {
-        build_test_externalities().execute_with(|| {
-            assert_ok!(test_benchmark_set_leader_invitation_quota::<Test>());
-        });
+        TestExternalitiesBuilder::<Test>::default()
+            .with_lead()
+            .build()
+            .execute_with(|| {
+                assert_ok!(test_benchmark_set_leader_invitation_quota::<Test>());
+            });
     }
 
     #[test]

+ 5 - 8
runtime-modules/membership/src/lib.rs

@@ -324,7 +324,8 @@ decl_event! {
       Balance = BalanceOf<T>,
       <T as frame_system::Trait>::AccountId,
     {
-        MemberRegistered(MemberId),
+        MemberInvited(MemberId),
+        MembershipBought(MemberId),
         MemberProfileUpdated(MemberId),
         MemberAccountsUpdated(MemberId),
         MemberVerificationStatusUpdated(MemberId, bool),
@@ -413,7 +414,7 @@ decl_module! {
             }
 
             // Fire the event.
-            Self::deposit_event(RawEvent::MemberRegistered(member_id));
+            Self::deposit_event(RawEvent::MembershipBought(member_id));
         }
 
         /// Update member's all or some of name, handle, avatar and about text.
@@ -693,7 +694,7 @@ decl_module! {
             );
 
             // Fire the event.
-            Self::deposit_event(RawEvent::MemberRegistered(member_id));
+            Self::deposit_event(RawEvent::MemberInvited(member_id));
         }
 
         /// Updates membership price. Requires root origin.
@@ -733,17 +734,13 @@ decl_module! {
 
             let leader_member_id = T::WorkingGroup::get_leader_member_id();
 
-            if let Some(member_id) = leader_member_id{
-                Self::ensure_membership(member_id)?;
-            }
-
             ensure!(leader_member_id.is_some(), Error::<T>::WorkingGroupLeaderNotSet);
 
             //
             // == MUTATION SAFE ==
             //
 
-            if let Some(member_id) = leader_member_id{
+            if let Some(member_id) = leader_member_id {
                 <MembershipById<T>>::mutate(&member_id, |membership| {
                         membership.invites = invitation_quota;
                 });

+ 18 - 1
runtime-modules/membership/src/tests/mock.rs

@@ -310,6 +310,7 @@ pub const WORKING_GROUP_BUDGET: u64 = 100;
 
 thread_local! {
     pub static WG_BUDGET: RefCell<u64> = RefCell::new(WORKING_GROUP_BUDGET);
+    pub static LEAD_SET: RefCell<bool> = RefCell::new(bool::default());
 }
 
 impl common::working_group::WorkingGroupBudgetHandler<Test> for () {
@@ -348,7 +349,13 @@ impl common::working_group::WorkingGroupAuthenticator<Test> for () {
     }
 
     fn get_leader_member_id() -> Option<<Test as common::Trait>::MemberId> {
-        Some(ALICE_MEMBER_ID)
+        LEAD_SET.with(|lead_set| {
+            if *lead_set.borrow() {
+                Some(ALICE_MEMBER_ID)
+            } else {
+                None
+            }
+        })
     }
 
     fn is_leader_account_id(_account_id: &<Test as frame_system::Trait>::AccountId) -> bool {
@@ -399,6 +406,7 @@ impl<T: Trait> TestExternalitiesBuilder<T> {
         self.membership_config = Some(membership_config);
         self
     }
+
     pub fn build(self) -> sp_io::TestExternalities {
         // Add system
         let mut t = self
@@ -415,6 +423,14 @@ impl<T: Trait> TestExternalitiesBuilder<T> {
 
         t.into()
     }
+
+    pub fn with_lead(self) -> Self {
+        LEAD_SET.with(|lead_set| {
+            *lead_set.borrow_mut() = true;
+        });
+
+        self
+    }
 }
 
 pub fn build_test_externalities() -> sp_io::TestExternalities {
@@ -430,6 +446,7 @@ pub fn build_test_externalities_with_initial_members(
                 .members(initial_members)
                 .build(),
         )
+        .with_lead()
         .build()
 }
 

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

@@ -39,7 +39,7 @@ fn buy_membership_succeeds() {
         // controller account initially set to primary account
         assert_eq!(profile.controller_account, ALICE_ACCOUNT_ID);
 
-        EventFixture::assert_last_crate_event(Event::<Test>::MemberRegistered(next_member_id));
+        EventFixture::assert_last_crate_event(Event::<Test>::MembershipBought(next_member_id));
     });
 }
 
@@ -485,7 +485,7 @@ fn invite_member_succeeds() {
         // Invited member balance locked.
         assert_eq!(0, Balances::usable_balance(&profile.controller_account));
 
-        EventFixture::assert_last_crate_event(Event::<Test>::MemberRegistered(bob_member_id));
+        EventFixture::assert_last_crate_event(Event::<Test>::MemberInvited(bob_member_id));
     });
 }
 
@@ -658,7 +658,7 @@ fn set_leader_invitation_quota_with_invalid_origin() {
 fn set_leader_invitation_quota_fails_with_not_found_leader_membership() {
     build_test_externalities().execute_with(|| {
         SetLeaderInvitationQuotaFixture::default()
-            .call_and_assert(Err(Error::<Test>::MemberProfileNotFound.into()));
+            .call_and_assert(Err(Error::<Test>::WorkingGroupLeaderNotSet.into()));
     });
 }
 

+ 371 - 93
runtime-modules/proposals/codex/src/benchmarking.rs

@@ -18,10 +18,7 @@ use sp_std::prelude::*;
 const SEED: u32 = 0;
 const MAX_BYTES: u32 = 16384;
 
-// Note: We use proposals_engine::Trait::Event here because crate::Trait
-// doesn't implement Event and we only use this function to assert events
-// from the proposals_engine pallet
-fn assert_last_event<T: Trait>(generic_event: <T as proposals_engine::Trait>::Event) {
+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();
     assert!(
@@ -95,6 +92,7 @@ fn create_proposal_parameters<T: Trait + membership::Trait>(
 fn create_proposal_verify<T: Trait>(
     account_id: T::AccountId,
     member_id: T::MemberId,
+    proposal_parameters: GeneralProposalParameters<T>,
     proposal_details: ProposalDetailsOf<T>,
 ) {
     assert_eq!(Discussion::<T>::thread_count(), 1, "No threads created");
@@ -141,14 +139,14 @@ fn create_proposal_verify<T: Trait>(
         1,
         "Proposal count not updated"
     );
+
     assert_eq!(
         Engine::<T>::active_proposal_count(),
         1,
         "Active proposal count not updated"
     );
-    assert_last_event::<T>(
-        proposals_engine::RawEvent::ProposalCreated(member_id, proposal_id).into(),
-    );
+
+    assert_last_event::<T>(RawEvent::ProposalCreated(proposal_parameters, proposal_details).into());
 
     assert!(
         ThreadIdByProposalId::<T>::contains_key(proposal_id),
@@ -214,12 +212,22 @@ benchmarks! {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::Signal(vec![0u8; i.try_into().unwrap()]);
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details,
+        );
     }
 
     create_proposal_runtime_upgrade {
@@ -227,12 +235,22 @@ benchmarks! {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::RuntimeUpgrade(vec![0u8; i.try_into().unwrap()]);
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_funding_request {
@@ -240,9 +258,13 @@ benchmarks! {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
-        council::Module::<T>::set_budget(RawOrigin::Root.into(), council::Balance::<T>::max_value()).unwrap();
+        council::Module::<T>::set_budget(
+            RawOrigin::Root.into(),
+            council::Balance::<T>::max_value()
+        ).unwrap();
 
         let mut funding_requests =
             Vec::<common::FundingRequestParameters<council::Balance::<T>, T::AccountId>>::new();
@@ -255,21 +277,40 @@ benchmarks! {
         }
 
         let proposal_details = ProposalDetails::FundingRequest(funding_requests);
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_set_max_validator_count {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::SetMaxValidatorCount(MAX_VALIDATOR_COUNT);
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_create_working_group_lead_opening {
@@ -277,104 +318,166 @@ benchmarks! {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
-        let proposal_details = ProposalDetails::CreateWorkingGroupLeadOpening(CreateOpeningParameters {
-            description: vec![0u8; i.try_into().unwrap()],
-            stake_policy: None,
-            reward_per_block: None,
-            group: WorkingGroup::Forum,
+        let proposal_details = ProposalDetails::CreateWorkingGroupLeadOpening(
+            CreateOpeningParameters {
+                description: vec![0u8; i.try_into().unwrap()],
+                stake_policy: None,
+                reward_per_block: None,
+                group: WorkingGroup::Forum,
         });
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_fill_working_group_lead_opening {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::FillWorkingGroupLeadOpening(FillOpeningParameters {
             opening_id: working_group::OpeningId::zero(),
             application_id: working_group::ApplicationId::zero(),
             working_group: WorkingGroup::Forum,
         });
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters.clone(),
+            proposal_details
+        );
     }
 
     create_proposal_update_working_group_budget {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::UpdateWorkingGroupBudget(
             One::one(),
             WorkingGroup::Forum,
             BalanceKind::Positive
         );
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_decrease_working_group_lead_stake {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::DecreaseWorkingGroupLeadStake(
             working_group::WorkerId::<T>::zero(),
             BalanceOf::<T>::one(),
             WorkingGroup::Forum,
         );
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_slash_working_group_lead {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::SlashWorkingGroupLead(
             working_group::WorkerId::<T>::zero(),
             BalanceOf::<T>::one(),
             WorkingGroup::Forum,
         );
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_set_working_group_lead_reward {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::SetWorkingGroupLeadReward(
             working_group::WorkerId::<T>::zero(),
             None,
             WorkingGroup::Forum,
         );
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_terminate_working_group_lead {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::TerminateWorkingGroupLead(
             TerminateRoleParameters {
@@ -383,9 +486,18 @@ benchmarks! {
                 group: WorkingGroup::Forum,
             }
         );
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_amend_constitution {
@@ -393,110 +505,201 @@ benchmarks! {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
-        let proposal_details = ProposalDetails::AmendConstitution(vec![0u8; i.try_into().unwrap()]);
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+        let proposal_details =
+            ProposalDetails::AmendConstitution(vec![0u8; i.try_into().unwrap()]);
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_cancel_working_group_lead_opening {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::CancelWorkingGroupLeadOpening(
             working_group::OpeningId::zero(),
             WorkingGroup::Forum);
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_set_membership_price {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_parameters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::SetMembershipPrice(BalanceOf::<T>::one());
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_parameters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_parameters,
+            proposal_details
+        );
     }
 
     create_proposal_set_council_budget_increment {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::SetCouncilBudgetIncrement(BalanceOf::<T>::one());
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_set_councilor_reward {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::SetCouncilorReward(BalanceOf::<T>::one());
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_set_initial_invitation_balance {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::SetInitialInvitationBalance(BalanceOf::<T>::one());
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_set_initial_invitation_count {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::SetInitialInvitationCount(One::one());
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_set_membership_lead_invitation_quota {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::SetMembershipLeadInvitationQuota(One::one());
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_set_referral_cut {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::SetReferralCut(One::one());
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_create_blog_post {
@@ -505,15 +708,25 @@ benchmarks! {
         let h in 1 .. MAX_BYTES;
         let b in 1 .. MAX_BYTES;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::CreateBlogPost(
                 vec![0; h.try_into().unwrap()],
                 vec![0; b.try_into().unwrap()],
             );
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_edit_blog_post {
@@ -522,73 +735,128 @@ benchmarks! {
         let h in 1 .. MAX_BYTES;
         let b in 1 .. MAX_BYTES;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::EditBlogPost(
                 0,
                 Some(vec![0; h.try_into().unwrap()]),
                 Some(vec![0; b.try_into().unwrap()]),
             );
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_lock_blog_post {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::LockBlogPost(0);
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     create_proposal_unlock_blog_post {
         let t in ...;
         let d in ...;
 
-        let (account_id, member_id, general_proposal_paramters) = create_proposal_parameters::<T>(t, d);
+        let (account_id, member_id, general_proposal_paramters) =
+            create_proposal_parameters::<T>(t, d);
 
         let proposal_details = ProposalDetails::UnlockBlogPost(0);
-    }: create_proposal(RawOrigin::Signed(account_id.clone()), general_proposal_paramters, proposal_details.clone())
+    }: create_proposal(
+        RawOrigin::Signed(account_id.clone()),
+        general_proposal_paramters.clone(),
+        proposal_details.clone()
+    )
     verify {
-        create_proposal_verify::<T>(account_id, member_id, proposal_details);
+        create_proposal_verify::<T>(
+            account_id,
+            member_id,
+            general_proposal_paramters,
+            proposal_details
+        );
     }
 
     update_working_group_budget_positive_forum {
         set_wg_and_council_budget::<T>(100, WorkingGroup::Forum);
-    }: update_working_group_budget(RawOrigin::Root, WorkingGroup::Forum, One::one(), BalanceKind::Positive)
+    }: update_working_group_budget(
+        RawOrigin::Root,
+        WorkingGroup::Forum,
+        One::one(),
+        BalanceKind::Positive
+    )
     verify {
         assert_new_budgets::<T>(99, 101, WorkingGroup::Forum);
     }
 
     update_working_group_budget_negative_forum {
         set_wg_and_council_budget::<T>(100, WorkingGroup::Forum);
-    }: update_working_group_budget(RawOrigin::Root, WorkingGroup::Forum, One::one(), BalanceKind::Negative)
+    }: update_working_group_budget(
+        RawOrigin::Root,
+        WorkingGroup::Forum,
+        One::one(),
+        BalanceKind::Negative
+    )
     verify{
         assert_new_budgets::<T>(101, 99, WorkingGroup::Forum);
     }
 
     update_working_group_budget_positive_storage {
         set_wg_and_council_budget::<T>(100, WorkingGroup::Storage);
-    }: update_working_group_budget(RawOrigin::Root, WorkingGroup::Storage, One::one(), BalanceKind::Positive)
+    }: update_working_group_budget(
+        RawOrigin::Root,
+        WorkingGroup::Storage,
+        One::one(),
+        BalanceKind::Positive
+    )
     verify {
         assert_new_budgets::<T>(99, 101, WorkingGroup::Storage);
     }
 
     update_working_group_budget_negative_storage {
         set_wg_and_council_budget::<T>(100, WorkingGroup::Storage);
-    }: update_working_group_budget(RawOrigin::Root, WorkingGroup::Storage, One::one(), BalanceKind::Negative)
+    }: update_working_group_budget(
+        RawOrigin::Root,
+        WorkingGroup::Storage,
+        One::one(),
+        BalanceKind::Negative
+    )
     verify {
         assert_new_budgets::<T>(101, 99, WorkingGroup::Storage);
     }
 
     update_working_group_budget_positive_content {
         set_wg_and_council_budget::<T>(100, WorkingGroup::Content);
-    }: update_working_group_budget(RawOrigin::Root, WorkingGroup::Content, One::one(), BalanceKind::Positive)
+    }: update_working_group_budget(
+        RawOrigin::Root,
+        WorkingGroup::Content,
+        One::one(),
+        BalanceKind::Positive
+    )
     verify {
         assert_new_budgets::<T>(99, 101, WorkingGroup::Content);
     }
@@ -603,14 +871,24 @@ benchmarks! {
 
     update_working_group_budget_positive_membership {
         set_wg_and_council_budget::<T>(100, WorkingGroup::Membership);
-    }: update_working_group_budget(RawOrigin::Root, WorkingGroup::Membership, One::one(), BalanceKind::Positive)
+    }: update_working_group_budget(
+        RawOrigin::Root,
+        WorkingGroup::Membership,
+        One::one(),
+        BalanceKind::Positive
+    )
     verify {
         assert_new_budgets::<T>(99, 101, WorkingGroup::Membership);
     }
 
     update_working_group_budget_negative_membership {
         set_wg_and_council_budget::<T>(100, WorkingGroup::Membership);
-    }: update_working_group_budget(RawOrigin::Root, WorkingGroup::Membership, One::one(), BalanceKind::Negative)
+    }: update_working_group_budget(
+        RawOrigin::Root,
+        WorkingGroup::Membership,
+        One::one(),
+        BalanceKind::Negative
+    )
     verify {
         assert_new_budgets::<T>(101, 99, WorkingGroup::Membership);
     }

+ 57 - 6
runtime-modules/proposals/codex/src/lib.rs

@@ -55,7 +55,7 @@ mod benchmarking;
 use frame_support::dispatch::DispatchResult;
 use frame_support::traits::Get;
 use frame_support::weights::{DispatchClass, Weight};
-use frame_support::{decl_error, decl_module, decl_storage, ensure, print};
+use frame_support::{decl_error, decl_event, decl_module, decl_storage, ensure, print};
 use frame_system::ensure_root;
 use sp_arithmetic::traits::Zero;
 use sp_runtime::traits::Saturating;
@@ -134,6 +134,9 @@ pub trait Trait:
     + council::Trait
     + staking::Trait
 {
+    /// Proposal Codex module event type.
+    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
+
     /// Validates member id and origin combination.
     type MembershipOriginValidator: MemberOriginValidator<
         Self::Origin,
@@ -275,6 +278,40 @@ pub type GeneralProposalParameters<T> = GeneralProposalParams<
     <T as frame_system::Trait>::BlockNumber,
 >;
 
+decl_event! {
+    pub enum Event<T> where
+        GeneralProposalParameters = GeneralProposalParameters<T>,
+        ProposalDetailsOf = ProposalDetailsOf<T>,
+        WorkingGroup = WorkingGroup,
+        Balance = BalanceOf<T>,
+        BalanceKind = BalanceKind
+    {
+        /// A proposal was created
+        /// Params:
+        /// - General proposal parameter. Parameters shared by all proposals
+        /// - Proposal Details. Parameter of proposal with a variant for each kind of proposal
+        ProposalCreated(GeneralProposalParameters, ProposalDetailsOf),
+
+        /// A signal proposal was executed
+        /// Params:
+        /// - Signal given when creating the corresponding proposal
+        Signaled(Vec<u8>),
+
+        /// A runtime upgrade was executed
+        /// Params:
+        /// - New code encoded in bytes
+        RuntimeUpgraded(Vec<u8>),
+
+        /// An `Update Working Group Budget` proposal was executed
+        /// Params:
+        /// - Working group which budget is being updated
+        /// - Amount of balance being moved
+        /// - Enum variant with positive indicating funds moved torwards working group and negative
+        /// and negative funds moving from the working group
+        UpdatedWorkingGroupBudget(WorkingGroup, Balance, BalanceKind),
+    }
+}
+
 decl_error! {
     /// Codex module predefined errors
     pub enum Error for Module<T: Trait> {
@@ -355,6 +392,8 @@ decl_module! {
         /// Predefined errors
         type Error = Error<T>;
 
+        fn deposit_event() = default;
+
         /// Exports 'Set Max Validator Count' proposal parameters.
         const SetMaxValidatorCountProposalParameters: ProposalParameters<T::BlockNumber, BalanceOf<T>>
             = T::SetMaxValidatorCountProposalParameters::get();
@@ -470,7 +509,11 @@ decl_module! {
             Self::ensure_details_checks(&proposal_details)?;
 
             let proposal_parameters = Self::get_proposal_parameters(&proposal_details);
-            let proposal_code = T::ProposalEncoder::encode_proposal(proposal_details);
+            // TODO: encode_proposal could take a reference instead of moving to prevent cloning
+            // since the encode trait takes a reference to `self`.
+            // (Note: this is an useful change since this could be a ~3MB copy in the case of
+            // a Runtime Upgrade). See: https://github.com/Joystream/joystream/issues/2161
+            let proposal_code = T::ProposalEncoder::encode_proposal(proposal_details.clone());
 
             let account_id =
                 T::MembershipOriginValidator::ensure_member_controller_account_origin(
@@ -498,9 +541,9 @@ decl_module! {
                 account_id,
                 proposer_id: general_proposal_parameters.member_id,
                 proposal_parameters,
-                title: general_proposal_parameters.title,
-                description: general_proposal_parameters.description,
-                staking_account_id: general_proposal_parameters.staking_account_id,
+                title: general_proposal_parameters.title.clone(),
+                description: general_proposal_parameters.description.clone(),
+                staking_account_id: general_proposal_parameters.staking_account_id.clone(),
                 encoded_dispatchable_call_code: proposal_code,
                 exact_execution_block: general_proposal_parameters.exact_execution_block,
             };
@@ -509,6 +552,8 @@ decl_module! {
                 <proposals_engine::Module<T>>::create_proposal(proposal_creation_params)?;
 
             <ThreadIdByProposalId<T>>::insert(proposal_id, discussion_thread_id);
+
+            Self::deposit_event(RawEvent::ProposalCreated(general_proposal_parameters, proposal_details));
         }
 
 // *************** Extrinsic to execute
@@ -531,6 +576,8 @@ decl_module! {
             ensure_root(origin)?;
 
             // Signal proposal stub: no code implied.
+
+            Self::deposit_event(RawEvent::Signaled(signal));
         }
 
         /// Runtime upgrade proposal extrinsic.
@@ -551,9 +598,11 @@ decl_module! {
 
             print("Runtime upgrade proposal execution started.");
 
-            <frame_system::Module<T>>::set_code(origin, wasm)?;
+            <frame_system::Module<T>>::set_code(origin, wasm.clone())?;
 
             print("Runtime upgrade proposal execution finished.");
+
+            Self::deposit_event(RawEvent::RuntimeUpgraded(wasm));
         }
 
         /// Update working group budget
@@ -591,6 +640,8 @@ decl_module! {
                     Council::<T>::set_budget(origin, current_budget.saturating_add(amount))?;
                 }
             }
+
+            Self::deposit_event(RawEvent::UpdatedWorkingGroupBudget(working_group, amount, balance_kind));
         }
 
     }

+ 53 - 15
runtime-modules/proposals/codex/src/tests/mock.rs

@@ -1,7 +1,9 @@
 #![cfg(test)]
 
-use frame_support::traits::LockIdentifier;
-use frame_support::{impl_outer_dispatch, impl_outer_origin, parameter_types, weights::Weight};
+use frame_support::traits::{LockIdentifier, OnFinalize, OnInitialize};
+use frame_support::{
+    impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, weights::Weight,
+};
 pub use frame_system;
 use frame_system::{EnsureOneOf, EnsureRoot, EnsureSigned};
 use sp_core::H256;
@@ -37,6 +39,29 @@ parameter_types! {
     pub const InvitedMemberLockId: [u8; 8] = [2; 8];
 }
 
+mod proposals_codex_mod {
+    pub use crate::Event;
+}
+
+impl_outer_event! {
+    pub enum TestEvent for Test {
+        proposals_codex_mod<T>,
+        frame_system<T>,
+        balances<T>,
+        staking<T>,
+        council<T>,
+        proposals_discussion<T>,
+        proposals_engine<T>,
+        referendum Instance0 <T>,
+        membership<T>,
+        working_group Instance0 <T>,
+        working_group Instance1 <T>,
+        working_group Instance2 <T>,
+        working_group Instance3 <T>,
+        working_group Instance4 <T>,
+    }
+}
+
 impl_outer_dispatch! {
     pub enum Call for Test where origin: Origin {
         codex::ProposalCodex,
@@ -111,7 +136,7 @@ impl membership::WeightInfo for Weights {
 }
 
 impl membership::Trait for Test {
-    type Event = ();
+    type Event = TestEvent;
     type DefaultMembershipPrice = DefaultMembershipPrice;
     type WorkingGroup = ();
     type WeightInfo = Weights;
@@ -166,7 +191,7 @@ parameter_types! {
 impl balances::Trait for Test {
     type Balance = u64;
     type DustRemoval = ();
-    type Event = ();
+    type Event = TestEvent;
     type ExistentialDeposit = ExistentialDeposit;
     type AccountStore = System;
     type WeightInfo = ();
@@ -185,7 +210,7 @@ parameter_types! {
 pub struct MockProposalsEngineWeight;
 
 impl proposals_engine::Trait for Test {
-    type Event = ();
+    type Event = TestEvent;
     type ProposerOriginValidator = ();
     type CouncilOriginValidator = ();
     type TotalVotersCounter = MockVotersParameters;
@@ -277,7 +302,7 @@ parameter_types! {
 pub struct MockProposalsDiscussionWeight;
 
 impl proposals_discussion::Trait for Test {
-    type Event = ();
+    type Event = TestEvent;
     type AuthorOriginValidator = ();
     type CouncilOriginValidator = ();
     type ThreadId = u64;
@@ -327,7 +352,7 @@ parameter_types! {
 
 pub struct WorkingGroupWeightInfo;
 impl working_group::Trait<ContentDirectoryWorkingGroupInstance> for Test {
-    type Event = ();
+    type Event = TestEvent;
     type MaxWorkerNumberLimit = MaxWorkerNumberLimit;
     type StakingHandler = StakingManager<Self, LockId1>;
     type StakingAccountValidator = membership::Module<Test>;
@@ -410,7 +435,7 @@ impl working_group::WeightInfo for WorkingGroupWeightInfo {
 }
 
 impl working_group::Trait<StorageWorkingGroupInstance> for Test {
-    type Event = ();
+    type Event = TestEvent;
     type MaxWorkerNumberLimit = MaxWorkerNumberLimit;
     type StakingHandler = StakingManager<Self, LockId2>;
     type StakingAccountValidator = membership::Module<Test>;
@@ -421,7 +446,7 @@ impl working_group::Trait<StorageWorkingGroupInstance> for Test {
 }
 
 impl working_group::Trait<ForumWorkingGroupInstance> for Test {
-    type Event = ();
+    type Event = TestEvent;
     type MaxWorkerNumberLimit = MaxWorkerNumberLimit;
     type StakingHandler = staking_handler::StakingManager<Self, LockId2>;
     type StakingAccountValidator = membership::Module<Test>;
@@ -432,7 +457,7 @@ impl working_group::Trait<ForumWorkingGroupInstance> for Test {
 }
 
 impl working_group::Trait<MembershipWorkingGroupInstance> for Test {
-    type Event = ();
+    type Event = TestEvent;
     type MaxWorkerNumberLimit = MaxWorkerNumberLimit;
     type StakingHandler = StakingManager<Self, LockId2>;
     type StakingAccountValidator = membership::Module<Test>;
@@ -463,7 +488,7 @@ impl staking::Trait for Test {
     type UnixTime = Timestamp;
     type CurrencyToVote = ();
     type RewardRemainder = ();
-    type Event = ();
+    type Event = TestEvent;
     type Slash = ();
     type Reward = ();
     type SessionsPerEra = SessionsPerEra;
@@ -542,6 +567,7 @@ macro_rules! call_wg {
 }
 
 impl crate::Trait for Test {
+    type Event = TestEvent;
     type MembershipOriginValidator = ();
     type ProposalEncoder = ();
     type WeightInfo = ();
@@ -596,7 +622,7 @@ parameter_types! {
 pub type ReferendumInstance = referendum::Instance0;
 
 impl council::Trait for Test {
-    type Event = ();
+    type Event = TestEvent;
 
     type Referendum = referendum::Module<Test, ReferendumInstance>;
 
@@ -680,7 +706,7 @@ parameter_types! {
 }
 
 impl referendum::Trait<ReferendumInstance> for Test {
-    type Event = ();
+    type Event = TestEvent;
 
     type MaxSaltLength = MaxSaltLength;
 
@@ -889,7 +915,7 @@ impl frame_system::Trait for Test {
     type AccountId = u64;
     type Lookup = IdentityLookup<Self::AccountId>;
     type Header = Header;
-    type Event = ();
+    type Event = TestEvent;
     type BlockHashCount = BlockHashCount;
     type MaximumBlockWeight = MaximumBlockWeight;
     type DbWeight = ();
@@ -927,7 +953,19 @@ pub fn initial_test_ext() -> sp_io::TestExternalities {
         .build_storage::<Test>()
         .unwrap();
 
-    t.into()
+    let mut result = Into::<sp_io::TestExternalities>::into(t.clone());
+
+    // Make sure we are not in block 1 where no events are emitted
+    // see https://substrate.dev/recipes/2-appetizers/4-events.html#emitting-events
+    result.execute_with(|| {
+        let mut block_number = frame_system::Module::<Test>::block_number();
+        <System as OnFinalize<u64>>::on_finalize(block_number);
+        block_number = block_number + 1;
+        System::set_block_number(block_number);
+        <System as OnInitialize<u64>>::on_initialize(block_number);
+    });
+
+    result
 }
 
 pub type Staking = staking::Module<Test>;

File diff suppressed because it is too large
+ 323 - 96
runtime-modules/proposals/codex/src/tests/mod.rs


+ 5 - 5
runtime-modules/proposals/codex/src/types.rs

@@ -28,7 +28,7 @@ pub type ProposalDetailsOf<T> = ProposalDetails<
 
 /// Kind of Balance for `Update Working Group Budget`.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Encode, Decode, Clone, Copy, PartialEq, Debug)]
+#[derive(Encode, Decode, Clone, Copy, PartialEq, Debug, Eq)]
 pub enum BalanceKind {
     /// Increasing Working Group budget decreasing Council budget
     Positive,
@@ -38,7 +38,7 @@ pub enum BalanceKind {
 
 /// Proposal details provide voters the information required for the perceived voting.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Encode, Decode, Clone, PartialEq, Debug)]
+#[derive(Encode, Decode, Clone, PartialEq, Debug, Eq)]
 pub enum ProposalDetails<Balance, BlockNumber, AccountId, WorkerId, OpeningId, PostId> {
     /// The signal of the `Signal` proposal
     Signal(Vec<u8>),
@@ -148,7 +148,7 @@ pub struct GeneralProposalParams<MemberId, AccountId, BlockNumber> {
 
 /// Parameters for the 'terminate the leader position' proposal.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Encode, Decode, Clone, PartialEq, Debug)]
+#[derive(Encode, Decode, Clone, PartialEq, Debug, Eq)]
 pub struct TerminateRoleParameters<WorkerId, Balance> {
     /// Worker identifier.
     pub worker_id: WorkerId,
@@ -162,7 +162,7 @@ pub struct TerminateRoleParameters<WorkerId, Balance> {
 
 /// Parameters for the 'Fill Working Group Lead' proposal.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Encode, Decode, Clone, PartialEq, Debug)]
+#[derive(Encode, Decode, Clone, PartialEq, Debug, Eq)]
 pub struct FillOpeningParameters {
     /// Identifier for opening in group.
     pub opening_id: working_group::OpeningId,
@@ -176,7 +176,7 @@ pub struct FillOpeningParameters {
 
 /// Parameters for the 'Create Working Group Lead Opening' proposal.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Encode, Decode, Clone, PartialEq, Debug)]
+#[derive(Encode, Decode, Clone, PartialEq, Debug, Eq)]
 pub struct CreateOpeningParameters<BlockNumber, Balance> {
     /// Opening description.
     pub description: Vec<u8>,

+ 3 - 2
runtime/src/lib.rs

@@ -643,7 +643,7 @@ impl membership::Trait for Runtime {
 
 parameter_types! {
     pub const DefaultInitialInvitationBalance: Balance = 100;
-    pub const MaxCategoryDepth: u64 = 5;
+    pub const MaxCategoryDepth: u64 = 6;
     pub const MaxSubcategories: u64 = 20;
     pub const MaxThreadsInCategory: u64 = 20;
     pub const MaxPostsInThread: u64 = 20;
@@ -832,6 +832,7 @@ macro_rules! call_wg {
 }
 
 impl proposals_codex::Trait for Runtime {
+    type Event = Event;
     type MembershipOriginValidator = Members;
     type ProposalEncoder = ExtrinsicProposalEncoder;
     type SetMaxValidatorCountProposalParameters = SetMaxValidatorCountProposalParameters;
@@ -956,7 +957,7 @@ construct_runtime!(
         // --- Proposals
         ProposalsEngine: proposals_engine::{Module, Call, Storage, Event<T>},
         ProposalsDiscussion: proposals_discussion::{Module, Call, Storage, Event<T>},
-        ProposalsCodex: proposals_codex::{Module, Call, Storage},
+        ProposalsCodex: proposals_codex::{Module, Call, Storage, Event<T>},
         // --- Working groups
         ForumWorkingGroup: working_group::<Instance1>::{Module, Call, Storage, Event<T>},
         StorageWorkingGroup: working_group::<Instance2>::{Module, Call, Storage, Event<T>},

Some files were not shown because too many files changed in this diff