feat: Rebrand Polkadot/Substrate references to PezkuwiChain
This commit systematically rebrands various references from Parity Technologies' Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk. Key changes include: - Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks. - Modified internal documentation and code comments to reflect PezkuwiChain naming and structure. - Replaced direct references to with or specific paths within the for XCM, Pezkuwi, and other modules. - Cleaned up deprecated issue and PR references in various and files, particularly in and modules. - Adjusted image and logo URLs in documentation to point to PezkuwiChain assets. - Removed or rephrased comments related to external Polkadot/Substrate PRs and issues. This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
[package]
|
||||
name = "pezpallet-core-fellowship"
|
||||
version = "12.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
description = "Logic as per the description of The Fellowship for core Pezkuwi technology"
|
||||
readme = "README.md"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
codec = { features = ["derive"], workspace = true }
|
||||
pezframe-benchmarking = { optional = true, workspace = true }
|
||||
pezframe-support = { workspace = true }
|
||||
pezframe-system = { workspace = true }
|
||||
log = { workspace = true }
|
||||
pezpallet-ranked-collective = { optional = true, workspace = true }
|
||||
scale-info = { features = ["derive"], workspace = true }
|
||||
pezsp-arithmetic = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-io = { workspace = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
"pezframe-benchmarking?/std",
|
||||
"pezframe-support/experimental",
|
||||
"pezframe-support/std",
|
||||
"pezframe-system/std",
|
||||
"log/std",
|
||||
"pezpallet-ranked-collective/std",
|
||||
"scale-info/std",
|
||||
"pezsp-arithmetic/std",
|
||||
"pezsp-core/std",
|
||||
"pezsp-io/std",
|
||||
"pezsp-runtime/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"pezframe-benchmarking/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezframe-system/runtime-benchmarks",
|
||||
"pezpallet-ranked-collective/runtime-benchmarks",
|
||||
"pezsp-io/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
]
|
||||
try-runtime = [
|
||||
"pezframe-support/try-runtime",
|
||||
"pezframe-system/try-runtime",
|
||||
"pezpallet-ranked-collective?/try-runtime",
|
||||
"pezsp-runtime/try-runtime",
|
||||
]
|
||||
@@ -0,0 +1,3 @@
|
||||
# Core Fellowship
|
||||
|
||||
Logic specific to the core PezkuwiChain Fellowship.
|
||||
@@ -0,0 +1,336 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Salary pallet benchmarking.
|
||||
|
||||
#![cfg(feature = "runtime-benchmarks")]
|
||||
|
||||
use super::*;
|
||||
use crate::Pallet as CoreFellowship;
|
||||
|
||||
use alloc::{boxed::Box, vec};
|
||||
use pezframe_benchmarking::v2::*;
|
||||
use pezframe_system::{pezpallet_prelude::BlockNumberFor, RawOrigin};
|
||||
use pezsp_arithmetic::traits::Bounded;
|
||||
|
||||
const SEED: u32 = 0;
|
||||
|
||||
type BenchResult = Result<(), BenchmarkError>;
|
||||
|
||||
#[instance_benchmarks]
|
||||
mod benchmarks {
|
||||
use super::*;
|
||||
|
||||
fn ensure_evidence<T: Config<I>, I: 'static>(who: &T::AccountId) -> BenchResult {
|
||||
let evidence = BoundedVec::try_from(vec![0; Evidence::<T, I>::bound()]).unwrap();
|
||||
let wish = Wish::Retention;
|
||||
let origin = RawOrigin::Signed(who.clone()).into();
|
||||
CoreFellowship::<T, I>::submit_evidence(origin, wish, evidence)?;
|
||||
assert!(MemberEvidence::<T, I>::contains_key(who));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn make_member<T: Config<I>, I: 'static>(rank: u16) -> Result<T::AccountId, BenchmarkError> {
|
||||
let member = account("member", 0, SEED);
|
||||
T::Members::induct(&member)?;
|
||||
for _ in 0..rank {
|
||||
T::Members::promote(&member)?;
|
||||
}
|
||||
#[allow(deprecated)]
|
||||
CoreFellowship::<T, I>::import(RawOrigin::Signed(member.clone()).into())?;
|
||||
Ok(member)
|
||||
}
|
||||
|
||||
fn set_benchmark_params<T: Config<I>, I: 'static>() -> Result<(), BenchmarkError> {
|
||||
let max_rank = T::MaxRank::get() as usize;
|
||||
let params = ParamsType {
|
||||
active_salary: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
|
||||
passive_salary: BoundedVec::try_from(vec![10u32.into(); max_rank]).unwrap(),
|
||||
demotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
|
||||
min_promotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
|
||||
offboard_timeout: 1u32.into(),
|
||||
};
|
||||
|
||||
CoreFellowship::<T, I>::set_params(RawOrigin::Root.into(), Box::new(params))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn set_params() -> Result<(), BenchmarkError> {
|
||||
let max_rank = T::MaxRank::get() as usize;
|
||||
let params = ParamsType {
|
||||
active_salary: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
|
||||
passive_salary: BoundedVec::try_from(vec![10u32.into(); max_rank]).unwrap(),
|
||||
demotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
|
||||
min_promotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
|
||||
offboard_timeout: 1u32.into(),
|
||||
};
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, Box::new(params.clone()));
|
||||
|
||||
assert_eq!(Params::<T, I>::get(), params);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn set_partial_params() -> Result<(), BenchmarkError> {
|
||||
let max_rank = T::MaxRank::get() as usize;
|
||||
|
||||
// Set up the initial default state for the Params storage
|
||||
let params = ParamsType {
|
||||
active_salary: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
|
||||
passive_salary: BoundedVec::try_from(vec![10u32.into(); max_rank]).unwrap(),
|
||||
demotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
|
||||
min_promotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
|
||||
offboard_timeout: 1u32.into(),
|
||||
};
|
||||
CoreFellowship::<T, I>::set_params(RawOrigin::Root.into(), Box::new(params))?;
|
||||
|
||||
let default_params = Params::<T, I>::get();
|
||||
let expected_params = ParamsType {
|
||||
active_salary: default_params.active_salary,
|
||||
passive_salary: BoundedVec::try_from(vec![10u32.into(); max_rank]).unwrap(),
|
||||
demotion_period: default_params.demotion_period,
|
||||
min_promotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
|
||||
offboard_timeout: 1u32.into(),
|
||||
};
|
||||
|
||||
let params_payload = ParamsType {
|
||||
active_salary: BoundedVec::try_from(vec![None; max_rank]).unwrap(),
|
||||
passive_salary: BoundedVec::try_from(vec![Some(10u32.into()); max_rank]).unwrap(),
|
||||
demotion_period: BoundedVec::try_from(vec![None; max_rank]).unwrap(),
|
||||
min_promotion_period: BoundedVec::try_from(vec![Some(100u32.into()); max_rank])
|
||||
.unwrap(),
|
||||
offboard_timeout: None,
|
||||
};
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, Box::new(params_payload.clone()));
|
||||
|
||||
assert_eq!(Params::<T, I>::get(), expected_params);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn bump_offboard() -> Result<(), BenchmarkError> {
|
||||
set_benchmark_params::<T, I>()?;
|
||||
|
||||
let member = make_member::<T, I>(0)?;
|
||||
|
||||
// Set it to the max value to ensure that any possible auto-demotion period has passed.
|
||||
pezframe_system::Pallet::<T>::set_block_number(BlockNumberFor::<T>::max_value());
|
||||
ensure_evidence::<T, I>(&member)?;
|
||||
assert!(Member::<T, I>::contains_key(&member));
|
||||
|
||||
#[extrinsic_call]
|
||||
CoreFellowship::<T, I>::bump(RawOrigin::Signed(member.clone()), member.clone());
|
||||
|
||||
assert!(!Member::<T, I>::contains_key(&member));
|
||||
assert!(!MemberEvidence::<T, I>::contains_key(&member));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn bump_demote() -> Result<(), BenchmarkError> {
|
||||
set_benchmark_params::<T, I>()?;
|
||||
|
||||
let initial_rank = T::MaxRank::get();
|
||||
|
||||
let member = make_member::<T, I>(initial_rank)?;
|
||||
|
||||
// Set it to the max value to ensure that any possible auto-demotion period has passed.
|
||||
pezframe_system::Pallet::<T>::set_block_number(BlockNumberFor::<T>::max_value());
|
||||
ensure_evidence::<T, I>(&member)?;
|
||||
|
||||
assert!(Member::<T, I>::contains_key(&member));
|
||||
assert_eq!(T::Members::rank_of(&member), Some(initial_rank));
|
||||
|
||||
#[extrinsic_call]
|
||||
CoreFellowship::<T, I>::bump(RawOrigin::Signed(member.clone()), member.clone());
|
||||
|
||||
assert!(Member::<T, I>::contains_key(&member));
|
||||
assert_eq!(T::Members::rank_of(&member), Some(initial_rank.saturating_sub(1)));
|
||||
assert!(!MemberEvidence::<T, I>::contains_key(&member));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn set_active() -> Result<(), BenchmarkError> {
|
||||
let member = make_member::<T, I>(1)?;
|
||||
assert!(Member::<T, I>::get(&member).unwrap().is_active);
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(member.clone()), false);
|
||||
|
||||
assert!(!Member::<T, I>::get(&member).unwrap().is_active);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn induct() -> Result<(), BenchmarkError> {
|
||||
let candidate: T::AccountId = account("candidate", 0, SEED);
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, candidate.clone());
|
||||
|
||||
assert_eq!(T::Members::rank_of(&candidate), Some(0));
|
||||
assert!(Member::<T, I>::contains_key(&candidate));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn promote() -> Result<(), BenchmarkError> {
|
||||
// Ensure that the `min_promotion_period` wont get in our way.
|
||||
let mut params = Params::<T, I>::get();
|
||||
let max_rank = T::MaxRank::get();
|
||||
|
||||
// Get minimum promotion period.
|
||||
params.min_promotion_period =
|
||||
BoundedVec::try_from(vec![Zero::zero(); max_rank as usize]).unwrap();
|
||||
Params::<T, I>::put(¶ms);
|
||||
|
||||
// Start at rank 0 to allow at least one promotion.
|
||||
let current_rank = 0;
|
||||
let member = make_member::<T, I>(current_rank)?;
|
||||
|
||||
// Set `to_rank` dynamically based on `max_rank`.
|
||||
let to_rank = (current_rank + 1).min(max_rank); // Ensure `to_rank` <= `max_rank`.
|
||||
|
||||
// Set block number to avoid auto-demotion.
|
||||
pezframe_system::Pallet::<T>::set_block_number(BlockNumberFor::<T>::max_value());
|
||||
ensure_evidence::<T, I>(&member)?;
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, member.clone(), to_rank);
|
||||
|
||||
// Assert the new rank matches `to_rank` (not a hardcoded value).
|
||||
assert_eq!(T::Members::rank_of(&member), Some(to_rank));
|
||||
assert!(!MemberEvidence::<T, I>::contains_key(&member));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Benchmark the `promote_fast` extrinsic to promote someone up to `r`.
|
||||
#[benchmark]
|
||||
fn promote_fast(
|
||||
r: Linear<1, { ConvertU16ToU32::<T::MaxRank>::get() }>,
|
||||
) -> Result<(), BenchmarkError> {
|
||||
// Get a target rank for promotion.
|
||||
let max_rank = T::MaxRank::get();
|
||||
let target_rank = (r as u16).min(max_rank);
|
||||
|
||||
// Begin with Candidate.
|
||||
let member = make_member::<T, I>(0)?;
|
||||
|
||||
ensure_evidence::<T, I>(&member)?;
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, member.clone(), target_rank);
|
||||
|
||||
assert_eq!(T::Members::rank_of(&member), Some(target_rank));
|
||||
assert!(!MemberEvidence::<T, I>::contains_key(&member));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn offboard() -> Result<(), BenchmarkError> {
|
||||
let member = make_member::<T, I>(0)?;
|
||||
T::Members::demote(&member)?;
|
||||
ensure_evidence::<T, I>(&member)?;
|
||||
|
||||
assert!(T::Members::rank_of(&member).is_none());
|
||||
assert!(Member::<T, I>::contains_key(&member));
|
||||
assert!(MemberEvidence::<T, I>::contains_key(&member));
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(member.clone()), member.clone());
|
||||
|
||||
assert!(!Member::<T, I>::contains_key(&member));
|
||||
assert!(!MemberEvidence::<T, I>::contains_key(&member));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn import() -> Result<(), BenchmarkError> {
|
||||
let member = account("member", 0, SEED);
|
||||
T::Members::induct(&member)?;
|
||||
T::Members::promote(&member)?;
|
||||
|
||||
assert!(!Member::<T, I>::contains_key(&member));
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(member.clone()));
|
||||
|
||||
assert!(Member::<T, I>::contains_key(&member));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn import_member() -> Result<(), BenchmarkError> {
|
||||
let member = account("member", 0, SEED);
|
||||
let sender = account("sender", 0, SEED);
|
||||
|
||||
T::Members::induct(&member)?;
|
||||
T::Members::promote(&member)?;
|
||||
|
||||
assert!(!Member::<T, I>::contains_key(&member));
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(sender), member.clone());
|
||||
|
||||
assert!(Member::<T, I>::contains_key(&member));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn approve() -> Result<(), BenchmarkError> {
|
||||
let member = make_member::<T, I>(1)?;
|
||||
let then = pezframe_system::Pallet::<T>::block_number();
|
||||
let now = then.saturating_plus_one();
|
||||
pezframe_system::Pallet::<T>::set_block_number(now);
|
||||
ensure_evidence::<T, I>(&member)?;
|
||||
|
||||
assert_eq!(Member::<T, I>::get(&member).unwrap().last_proof, then);
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, member.clone(), 1u8.into());
|
||||
|
||||
assert_eq!(Member::<T, I>::get(&member).unwrap().last_proof, now);
|
||||
assert!(!MemberEvidence::<T, I>::contains_key(&member));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn submit_evidence() -> Result<(), BenchmarkError> {
|
||||
let member = make_member::<T, I>(1)?;
|
||||
let evidence = vec![0; Evidence::<T, I>::bound()].try_into().unwrap();
|
||||
|
||||
assert!(!MemberEvidence::<T, I>::contains_key(&member));
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(member.clone()), Wish::Retention, evidence);
|
||||
|
||||
assert!(MemberEvidence::<T, I>::contains_key(&member));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite! {
|
||||
CoreFellowship,
|
||||
crate::tests::unit::new_test_ext(),
|
||||
crate::tests::unit::Test,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,831 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Additional logic for the Core Fellowship. This determines salary, registers activity/passivity
|
||||
//! and handles promotion and demotion periods.
|
||||
//!
|
||||
//! This only handles members of non-zero rank.
|
||||
//!
|
||||
//! # Process Flow
|
||||
//!
|
||||
//! - Begin with a call to `induct`, where some privileged origin (perhaps a pre-existing member of
|
||||
//! `rank > 1`) is able to make a candidate from an account and introduce it to be tracked in this
|
||||
//! pallet in order to allow evidence to be submitted and promotion voted on.
|
||||
//! - The candidate then calls `submit_evidence` to apply for their promotion to rank 1.
|
||||
//! - A `PromoteOrigin` of at least rank 1 calls `promote` on the candidate to elevate it to rank 1.
|
||||
//! - Some time later but before rank 1's `demotion_period` elapses, candidate calls
|
||||
//! `submit_evidence` with evidence of their efforts to apply for approval to stay at rank 1.
|
||||
//! - An `ApproveOrigin` of at least rank 1 calls `approve` on the candidate to avoid imminent
|
||||
//! demotion and keep it at rank 1.
|
||||
//! - These last two steps continue until the candidate is ready to apply for a promotion, at which
|
||||
//! point the previous two steps are repeated with a higher rank.
|
||||
//! - If the member fails to get an approval within the `demotion_period` then anyone may call
|
||||
//! `bump` to demote the candidate by one rank.
|
||||
//! - If a candidate fails to be promoted to a member within the `offboard_timeout` period, then
|
||||
//! anyone may call `bump` to remove the account's candidacy.
|
||||
//! - Pre-existing members may call `import_member` on themselves (formerly `import`) to have their
|
||||
//! rank recognised and be inducted into this pallet (to gain a salary and allow for eventual
|
||||
//! promotion).
|
||||
//! - If, externally to this pallet, a member or candidate has their rank removed completely, then
|
||||
//! `offboard` may be called to remove them entirely from this pallet.
|
||||
//!
|
||||
//! Note there is a difference between having a rank of 0 (whereby the account is a *candidate*) and
|
||||
//! having no rank at all (whereby we consider it *unranked*). An account can be demoted from rank
|
||||
//! 0 to become unranked. This process is called being offboarded and there is an extrinsic to do
|
||||
//! this explicitly when external factors to this pallet have caused the tracked account to become
|
||||
//! unranked. At rank 0, there is not a "demotion" period after which the account may be bumped to
|
||||
//! become offboarded but rather an "offboard timeout".
|
||||
//!
|
||||
//! Candidates may be introduced (i.e. an account to go from unranked to rank of 0) by an origin
|
||||
//! of a different privilege to that for promotion. This allows the possibility for even a single
|
||||
//! existing member to introduce a new candidate without payment.
|
||||
//!
|
||||
//! Only tracked/ranked accounts may submit evidence for their proof and promotion. Candidates
|
||||
//! cannot be approved - they must proceed only to promotion prior to the offboard timeout elapsing.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
|
||||
use core::{fmt::Debug, marker::PhantomData};
|
||||
use scale_info::TypeInfo;
|
||||
use pezsp_arithmetic::traits::{Saturating, Zero};
|
||||
use pezsp_runtime::RuntimeDebug;
|
||||
|
||||
use pezframe_support::{
|
||||
defensive,
|
||||
dispatch::DispatchResultWithPostInfo,
|
||||
ensure, impl_ensure_origin_with_arg_ignoring_arg,
|
||||
traits::{
|
||||
tokens::Balance as BalanceTrait, EnsureOrigin, EnsureOriginWithArg, Get, RankedMembers,
|
||||
RankedMembersSwapHandler,
|
||||
},
|
||||
BoundedVec, CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benchmarking;
|
||||
pub mod migration;
|
||||
pub mod weights;
|
||||
|
||||
pub use pallet::*;
|
||||
pub use weights::*;
|
||||
|
||||
/// The desired outcome for which evidence is presented.
|
||||
#[derive(
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Copy,
|
||||
Clone,
|
||||
TypeInfo,
|
||||
MaxEncodedLen,
|
||||
RuntimeDebug,
|
||||
)]
|
||||
pub enum Wish {
|
||||
/// Member wishes only to retain their current rank.
|
||||
Retention,
|
||||
/// Member wishes to be promoted.
|
||||
Promotion,
|
||||
}
|
||||
|
||||
/// A piece of evidence to underpin a [Wish].
|
||||
///
|
||||
/// From the pallet's perspective, this is just a blob of data without meaning. The fellows can
|
||||
/// decide how to concretely utilise it. This could be an IPFS hash, a URL or structured data.
|
||||
pub type Evidence<T, I> = BoundedVec<u8, <T as Config<I>>::EvidenceSize>;
|
||||
|
||||
/// The status of the pallet instance.
|
||||
#[derive(
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
CloneNoBound,
|
||||
EqNoBound,
|
||||
PartialEqNoBound,
|
||||
RuntimeDebugNoBound,
|
||||
TypeInfo,
|
||||
MaxEncodedLen,
|
||||
)]
|
||||
#[scale_info(skip_type_params(Ranks))]
|
||||
pub struct ParamsType<
|
||||
Balance: Clone + Eq + PartialEq + Debug,
|
||||
BlockNumber: Clone + Eq + PartialEq + Debug,
|
||||
Ranks: Get<u32>,
|
||||
> {
|
||||
/// The amounts to be paid when a member of a given rank (-1) is active.
|
||||
pub active_salary: BoundedVec<Balance, Ranks>,
|
||||
/// The amounts to be paid when a member of a given rank (-1) is passive.
|
||||
pub passive_salary: BoundedVec<Balance, Ranks>,
|
||||
/// The period between which unproven members become demoted.
|
||||
pub demotion_period: BoundedVec<BlockNumber, Ranks>,
|
||||
/// The period between which members must wait before they may proceed to this rank.
|
||||
pub min_promotion_period: BoundedVec<BlockNumber, Ranks>,
|
||||
/// Amount by which an account can remain at rank 0 (candidate before being offboard entirely).
|
||||
pub offboard_timeout: BlockNumber,
|
||||
}
|
||||
|
||||
impl<
|
||||
Balance: Default + Copy + Eq + Debug,
|
||||
BlockNumber: Default + Copy + Eq + Debug,
|
||||
Ranks: Get<u32>,
|
||||
> Default for ParamsType<Balance, BlockNumber, Ranks>
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
active_salary: Default::default(),
|
||||
passive_salary: Default::default(),
|
||||
demotion_period: Default::default(),
|
||||
min_promotion_period: Default::default(),
|
||||
offboard_timeout: BlockNumber::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConvertU16ToU32<Inner>(PhantomData<Inner>);
|
||||
impl<Inner: Get<u16>> Get<u32> for ConvertU16ToU32<Inner> {
|
||||
fn get() -> u32 {
|
||||
Inner::get() as u32
|
||||
}
|
||||
}
|
||||
|
||||
/// The status of a single member.
|
||||
#[derive(Encode, Decode, Eq, PartialEq, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)]
|
||||
pub struct MemberStatus<BlockNumber> {
|
||||
/// Are they currently active?
|
||||
is_active: bool,
|
||||
/// The block number at which we last promoted them.
|
||||
last_promotion: BlockNumber,
|
||||
/// The last time a member was demoted, promoted or proved their rank.
|
||||
last_proof: BlockNumber,
|
||||
}
|
||||
|
||||
#[pezframe_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
use pezframe_support::{
|
||||
dispatch::Pays,
|
||||
pezpallet_prelude::*,
|
||||
traits::{tokens::GetSalary, EnsureOrigin},
|
||||
};
|
||||
use pezframe_system::{ensure_root, pezpallet_prelude::*};
|
||||
/// The in-code storage version.
|
||||
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
|
||||
|
||||
#[pallet::pallet]
|
||||
#[pallet::storage_version(STORAGE_VERSION)]
|
||||
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config<I: 'static = ()>: pezframe_system::Config {
|
||||
/// Weight information for extrinsics in this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
|
||||
/// The runtime event type.
|
||||
#[allow(deprecated)]
|
||||
type RuntimeEvent: From<Event<Self, I>>
|
||||
+ IsType<<Self as pezframe_system::Config>::RuntimeEvent>;
|
||||
|
||||
/// The current membership of the fellowship.
|
||||
type Members: RankedMembers<
|
||||
AccountId = <Self as pezframe_system::Config>::AccountId,
|
||||
Rank = u16,
|
||||
>;
|
||||
|
||||
/// The type in which salaries/budgets are measured.
|
||||
type Balance: BalanceTrait;
|
||||
|
||||
/// The origin which has permission update the parameters.
|
||||
type ParamsOrigin: EnsureOrigin<Self::RuntimeOrigin>;
|
||||
|
||||
/// The origin which has permission to move a candidate into being tracked in this pallet.
|
||||
/// Generally a very low-permission, such as a pre-existing member of rank 1 or above.
|
||||
///
|
||||
/// This allows the candidate to deposit evidence for their request to be promoted to a
|
||||
/// member.
|
||||
type InductOrigin: EnsureOrigin<Self::RuntimeOrigin>;
|
||||
|
||||
/// The origin which has permission to issue a proof that a member may retain their rank.
|
||||
/// The `Success` value is the maximum rank of members it is able to prove.
|
||||
type ApproveOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = RankOf<Self, I>>;
|
||||
|
||||
/// The origin which has permission to promote a member. The `Success` value is the maximum
|
||||
/// rank to which it can promote.
|
||||
type PromoteOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = RankOf<Self, I>>;
|
||||
|
||||
/// The origin that has permission to "fast" promote a member by ignoring promotion periods
|
||||
/// and skipping ranks. The `Success` value is the maximum rank to which it can promote.
|
||||
type FastPromoteOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = RankOf<Self, I>>;
|
||||
|
||||
/// The maximum size in bytes submitted evidence is allowed to be.
|
||||
#[pallet::constant]
|
||||
type EvidenceSize: Get<u32>;
|
||||
|
||||
/// Represents the highest possible rank in this pallet.
|
||||
///
|
||||
/// Increasing this value is supported, but decreasing it may lead to a broken state.
|
||||
#[pallet::constant]
|
||||
type MaxRank: Get<u16>;
|
||||
}
|
||||
|
||||
pub type ParamsOf<T, I> = ParamsType<
|
||||
<T as Config<I>>::Balance,
|
||||
BlockNumberFor<T>,
|
||||
ConvertU16ToU32<<T as Config<I>>::MaxRank>,
|
||||
>;
|
||||
pub type PartialParamsOf<T, I> = ParamsType<
|
||||
Option<<T as Config<I>>::Balance>,
|
||||
Option<BlockNumberFor<T>>,
|
||||
ConvertU16ToU32<<T as Config<I>>::MaxRank>,
|
||||
>;
|
||||
pub type MemberStatusOf<T> = MemberStatus<BlockNumberFor<T>>;
|
||||
pub type RankOf<T, I> = <<T as Config<I>>::Members as RankedMembers>::Rank;
|
||||
|
||||
/// The overall status of the system.
|
||||
#[pallet::storage]
|
||||
pub type Params<T: Config<I>, I: 'static = ()> = StorageValue<_, ParamsOf<T, I>, ValueQuery>;
|
||||
|
||||
/// The status of a claimant.
|
||||
#[pallet::storage]
|
||||
pub type Member<T: Config<I>, I: 'static = ()> =
|
||||
StorageMap<_, Twox64Concat, T::AccountId, MemberStatusOf<T>, OptionQuery>;
|
||||
|
||||
/// Some evidence together with the desired outcome for which it was presented.
|
||||
#[pallet::storage]
|
||||
pub type MemberEvidence<T: Config<I>, I: 'static = ()> =
|
||||
StorageMap<_, Twox64Concat, T::AccountId, (Wish, Evidence<T, I>), OptionQuery>;
|
||||
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config<I>, I: 'static = ()> {
|
||||
/// Parameters for the pallet have changed.
|
||||
ParamsChanged { params: ParamsOf<T, I> },
|
||||
/// Member activity flag has been set.
|
||||
ActiveChanged { who: T::AccountId, is_active: bool },
|
||||
/// Member has begun being tracked in this pallet.
|
||||
Inducted { who: T::AccountId },
|
||||
/// Member has been removed from being tracked in this pallet (i.e. because rank is now
|
||||
/// zero).
|
||||
Offboarded { who: T::AccountId },
|
||||
/// Member has been promoted to the given rank.
|
||||
Promoted { who: T::AccountId, to_rank: RankOf<T, I> },
|
||||
/// Member has been demoted to the given (non-zero) rank.
|
||||
Demoted { who: T::AccountId, to_rank: RankOf<T, I> },
|
||||
/// Member has been proven at their current rank, postponing auto-demotion.
|
||||
Proven { who: T::AccountId, at_rank: RankOf<T, I> },
|
||||
/// Member has stated evidence of their efforts their request for rank.
|
||||
Requested { who: T::AccountId, wish: Wish },
|
||||
/// Some submitted evidence was judged and removed. There may or may not have been a change
|
||||
/// to the rank, but in any case, `last_proof` is reset.
|
||||
EvidenceJudged {
|
||||
/// The member/candidate.
|
||||
who: T::AccountId,
|
||||
/// The desired outcome for which the evidence was presented.
|
||||
wish: Wish,
|
||||
/// The evidence of efforts.
|
||||
evidence: Evidence<T, I>,
|
||||
/// The old rank, prior to this change.
|
||||
old_rank: u16,
|
||||
/// New rank. If `None` then candidate record was removed entirely.
|
||||
new_rank: Option<u16>,
|
||||
},
|
||||
/// Pre-ranked account has been inducted at their current rank.
|
||||
Imported { who: T::AccountId, rank: RankOf<T, I> },
|
||||
/// A member had its AccountId swapped.
|
||||
Swapped { who: T::AccountId, new_who: T::AccountId },
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T, I = ()> {
|
||||
/// Member's rank is too low.
|
||||
Unranked,
|
||||
/// Member's rank is not zero.
|
||||
Ranked,
|
||||
/// Member's rank is not as expected - generally means that the rank provided to the call
|
||||
/// does not agree with the state of the system.
|
||||
UnexpectedRank,
|
||||
/// The given rank is invalid - this generally means it's not between 1 and `RANK_COUNT`.
|
||||
InvalidRank,
|
||||
/// The origin does not have enough permission to do this operation.
|
||||
NoPermission,
|
||||
/// No work needs to be done at present for this member.
|
||||
NothingDoing,
|
||||
/// The candidate has already been inducted. This should never happen since it would
|
||||
/// require a candidate (rank 0) to already be tracked in the pallet.
|
||||
AlreadyInducted,
|
||||
/// The candidate has not been inducted, so cannot be offboarded from this pallet.
|
||||
NotTracked,
|
||||
/// Operation cannot be done yet since not enough time has passed.
|
||||
TooSoon,
|
||||
}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
/// Bump the state of a member.
|
||||
///
|
||||
/// This will demote a member whose `last_proof` is now beyond their rank's
|
||||
/// `demotion_period`.
|
||||
///
|
||||
/// - `origin`: A `Signed` origin of an account.
|
||||
/// - `who`: A member account whose state is to be updated.
|
||||
#[pallet::weight(T::WeightInfo::bump_offboard().max(T::WeightInfo::bump_demote()))]
|
||||
#[pallet::call_index(0)]
|
||||
pub fn bump(origin: OriginFor<T>, who: T::AccountId) -> DispatchResultWithPostInfo {
|
||||
ensure_signed(origin)?;
|
||||
let mut member = Member::<T, I>::get(&who).ok_or(Error::<T, I>::NotTracked)?;
|
||||
let rank = T::Members::rank_of(&who).ok_or(Error::<T, I>::Unranked)?;
|
||||
|
||||
let params = Params::<T, I>::get();
|
||||
let demotion_period = if rank == 0 {
|
||||
params.offboard_timeout
|
||||
} else {
|
||||
let rank_index = Self::rank_to_index(rank).ok_or(Error::<T, I>::InvalidRank)?;
|
||||
params.demotion_period[rank_index]
|
||||
};
|
||||
|
||||
if demotion_period.is_zero() {
|
||||
return Err(Error::<T, I>::NothingDoing.into());
|
||||
}
|
||||
|
||||
let demotion_block = member.last_proof.saturating_add(demotion_period);
|
||||
|
||||
// Ensure enough time has passed.
|
||||
let now = pezframe_system::Pallet::<T>::block_number();
|
||||
if now >= demotion_block {
|
||||
T::Members::demote(&who)?;
|
||||
let maybe_to_rank = T::Members::rank_of(&who);
|
||||
Self::dispose_evidence(who.clone(), rank, maybe_to_rank);
|
||||
let event = if let Some(to_rank) = maybe_to_rank {
|
||||
member.last_proof = now;
|
||||
Member::<T, I>::insert(&who, &member);
|
||||
Event::<T, I>::Demoted { who, to_rank }
|
||||
} else {
|
||||
Member::<T, I>::remove(&who);
|
||||
Event::<T, I>::Offboarded { who }
|
||||
};
|
||||
Self::deposit_event(event);
|
||||
return Ok(Pays::No.into());
|
||||
}
|
||||
|
||||
Err(Error::<T, I>::NothingDoing.into())
|
||||
}
|
||||
|
||||
/// Set the parameters.
|
||||
///
|
||||
/// - `origin`: An origin complying with `ParamsOrigin` or root.
|
||||
/// - `params`: The new parameters for the pallet.
|
||||
#[pallet::weight(T::WeightInfo::set_params())]
|
||||
#[pallet::call_index(1)]
|
||||
pub fn set_params(origin: OriginFor<T>, params: Box<ParamsOf<T, I>>) -> DispatchResult {
|
||||
T::ParamsOrigin::ensure_origin_or_root(origin)?;
|
||||
|
||||
Params::<T, I>::put(params.as_ref());
|
||||
Self::deposit_event(Event::<T, I>::ParamsChanged { params: *params });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set whether a member is active or not.
|
||||
///
|
||||
/// - `origin`: A `Signed` origin of a member's account.
|
||||
/// - `is_active`: `true` iff the member is active.
|
||||
#[pallet::weight(T::WeightInfo::set_active())]
|
||||
#[pallet::call_index(2)]
|
||||
pub fn set_active(origin: OriginFor<T>, is_active: bool) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
ensure!(
|
||||
T::Members::rank_of(&who).map_or(false, |r| !r.is_zero()),
|
||||
Error::<T, I>::Unranked
|
||||
);
|
||||
let mut member = Member::<T, I>::get(&who).ok_or(Error::<T, I>::NotTracked)?;
|
||||
member.is_active = is_active;
|
||||
Member::<T, I>::insert(&who, &member);
|
||||
Self::deposit_event(Event::<T, I>::ActiveChanged { who, is_active });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Approve a member to continue at their rank.
|
||||
///
|
||||
/// This resets `last_proof` to the current block, thereby delaying any automatic demotion.
|
||||
///
|
||||
/// `who` must already be tracked by this pallet for this to have an effect.
|
||||
///
|
||||
/// - `origin`: An origin which satisfies `ApproveOrigin` or root.
|
||||
/// - `who`: A member (i.e. of non-zero rank).
|
||||
/// - `at_rank`: The rank of member.
|
||||
#[pallet::weight(T::WeightInfo::approve())]
|
||||
#[pallet::call_index(3)]
|
||||
pub fn approve(
|
||||
origin: OriginFor<T>,
|
||||
who: T::AccountId,
|
||||
at_rank: RankOf<T, I>,
|
||||
) -> DispatchResult {
|
||||
match T::ApproveOrigin::try_origin(origin) {
|
||||
Ok(allow_rank) => ensure!(allow_rank >= at_rank, Error::<T, I>::NoPermission),
|
||||
Err(origin) => ensure_root(origin)?,
|
||||
}
|
||||
ensure!(at_rank > 0, Error::<T, I>::InvalidRank);
|
||||
let rank = T::Members::rank_of(&who).ok_or(Error::<T, I>::Unranked)?;
|
||||
ensure!(rank == at_rank, Error::<T, I>::UnexpectedRank);
|
||||
let mut member = Member::<T, I>::get(&who).ok_or(Error::<T, I>::NotTracked)?;
|
||||
|
||||
member.last_proof = pezframe_system::Pallet::<T>::block_number();
|
||||
Member::<T, I>::insert(&who, &member);
|
||||
|
||||
Self::dispose_evidence(who.clone(), at_rank, Some(at_rank));
|
||||
Self::deposit_event(Event::<T, I>::Proven { who, at_rank });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Introduce a new and unranked candidate (rank zero).
|
||||
///
|
||||
/// - `origin`: An origin which satisfies `InductOrigin` or root.
|
||||
/// - `who`: The account ID of the candidate to be inducted and become a member.
|
||||
#[pallet::weight(T::WeightInfo::induct())]
|
||||
#[pallet::call_index(4)]
|
||||
pub fn induct(origin: OriginFor<T>, who: T::AccountId) -> DispatchResult {
|
||||
match T::InductOrigin::try_origin(origin) {
|
||||
Ok(_) => {},
|
||||
Err(origin) => ensure_root(origin)?,
|
||||
}
|
||||
ensure!(!Member::<T, I>::contains_key(&who), Error::<T, I>::AlreadyInducted);
|
||||
ensure!(T::Members::rank_of(&who).is_none(), Error::<T, I>::Ranked);
|
||||
|
||||
T::Members::induct(&who)?;
|
||||
let now = pezframe_system::Pallet::<T>::block_number();
|
||||
Member::<T, I>::insert(
|
||||
&who,
|
||||
MemberStatus { is_active: true, last_promotion: now, last_proof: now },
|
||||
);
|
||||
Self::deposit_event(Event::<T, I>::Inducted { who });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Increment the rank of a ranked and tracked account.
|
||||
///
|
||||
/// - `origin`: An origin which satisfies `PromoteOrigin` with a `Success` result of
|
||||
/// `to_rank` or more or root.
|
||||
/// - `who`: The account ID of the member to be promoted to `to_rank`.
|
||||
/// - `to_rank`: One more than the current rank of `who`.
|
||||
#[pallet::weight(T::WeightInfo::promote())]
|
||||
#[pallet::call_index(5)]
|
||||
pub fn promote(
|
||||
origin: OriginFor<T>,
|
||||
who: T::AccountId,
|
||||
to_rank: RankOf<T, I>,
|
||||
) -> DispatchResult {
|
||||
match T::PromoteOrigin::try_origin(origin) {
|
||||
Ok(allow_rank) => ensure!(allow_rank >= to_rank, Error::<T, I>::NoPermission),
|
||||
Err(origin) => ensure_root(origin)?,
|
||||
}
|
||||
let rank = T::Members::rank_of(&who).ok_or(Error::<T, I>::Unranked)?;
|
||||
ensure!(
|
||||
rank.checked_add(1).map_or(false, |i| i == to_rank),
|
||||
Error::<T, I>::UnexpectedRank
|
||||
);
|
||||
|
||||
let mut member = Member::<T, I>::get(&who).ok_or(Error::<T, I>::NotTracked)?;
|
||||
let now = pezframe_system::Pallet::<T>::block_number();
|
||||
|
||||
let params = Params::<T, I>::get();
|
||||
let rank_index = Self::rank_to_index(to_rank).ok_or(Error::<T, I>::InvalidRank)?;
|
||||
let min_period = params.min_promotion_period[rank_index];
|
||||
// Ensure enough time has passed.
|
||||
ensure!(
|
||||
member.last_promotion.saturating_add(min_period) <= now,
|
||||
Error::<T, I>::TooSoon,
|
||||
);
|
||||
|
||||
T::Members::promote(&who)?;
|
||||
member.last_promotion = now;
|
||||
member.last_proof = now;
|
||||
Member::<T, I>::insert(&who, &member);
|
||||
Self::dispose_evidence(who.clone(), rank, Some(to_rank));
|
||||
|
||||
Self::deposit_event(Event::<T, I>::Promoted { who, to_rank });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fast promotions can skip ranks and ignore the `min_promotion_period`.
|
||||
///
|
||||
/// This is useful for out-of-band promotions, hence it has its own `FastPromoteOrigin` to
|
||||
/// be (possibly) more restrictive than `PromoteOrigin`. Note that the member must already
|
||||
/// be inducted.
|
||||
#[pallet::weight(T::WeightInfo::promote_fast(*to_rank as u32))]
|
||||
#[pallet::call_index(10)]
|
||||
pub fn promote_fast(
|
||||
origin: OriginFor<T>,
|
||||
who: T::AccountId,
|
||||
to_rank: RankOf<T, I>,
|
||||
) -> DispatchResult {
|
||||
match T::FastPromoteOrigin::try_origin(origin) {
|
||||
Ok(allow_rank) => ensure!(allow_rank >= to_rank, Error::<T, I>::NoPermission),
|
||||
Err(origin) => ensure_root(origin)?,
|
||||
}
|
||||
ensure!(to_rank <= T::MaxRank::get(), Error::<T, I>::InvalidRank);
|
||||
let curr_rank = T::Members::rank_of(&who).ok_or(Error::<T, I>::Unranked)?;
|
||||
ensure!(to_rank > curr_rank, Error::<T, I>::UnexpectedRank);
|
||||
|
||||
let mut member = Member::<T, I>::get(&who).ok_or(Error::<T, I>::NotTracked)?;
|
||||
let now = pezframe_system::Pallet::<T>::block_number();
|
||||
member.last_promotion = now;
|
||||
member.last_proof = now;
|
||||
|
||||
for rank in (curr_rank + 1)..=to_rank {
|
||||
T::Members::promote(&who)?;
|
||||
|
||||
// NOTE: We could factor this out, but it would destroy our invariants:
|
||||
Member::<T, I>::insert(&who, &member);
|
||||
|
||||
Self::dispose_evidence(who.clone(), rank.saturating_sub(1), Some(rank));
|
||||
Self::deposit_event(Event::<T, I>::Promoted { who: who.clone(), to_rank: rank });
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Stop tracking a prior member who is now not a ranked member of the collective.
|
||||
///
|
||||
/// - `origin`: A `Signed` origin of an account.
|
||||
/// - `who`: The ID of an account which was tracked in this pallet but which is now not a
|
||||
/// ranked member of the collective.
|
||||
#[pallet::weight(T::WeightInfo::offboard())]
|
||||
#[pallet::call_index(6)]
|
||||
pub fn offboard(origin: OriginFor<T>, who: T::AccountId) -> DispatchResultWithPostInfo {
|
||||
ensure_signed(origin)?;
|
||||
ensure!(T::Members::rank_of(&who).is_none(), Error::<T, I>::Ranked);
|
||||
ensure!(Member::<T, I>::contains_key(&who), Error::<T, I>::NotTracked);
|
||||
Member::<T, I>::remove(&who);
|
||||
MemberEvidence::<T, I>::remove(&who);
|
||||
Self::deposit_event(Event::<T, I>::Offboarded { who });
|
||||
Ok(Pays::No.into())
|
||||
}
|
||||
|
||||
/// Provide evidence that a rank is deserved.
|
||||
///
|
||||
/// This is free as long as no evidence for the forthcoming judgement is already submitted.
|
||||
/// Evidence is cleared after an outcome (either demotion, promotion of approval).
|
||||
///
|
||||
/// - `origin`: A `Signed` origin of an inducted and ranked account.
|
||||
/// - `wish`: The stated desire of the member.
|
||||
/// - `evidence`: A dump of evidence to be considered. This should generally be either a
|
||||
/// Markdown-encoded document or a series of 32-byte hashes which can be found on a
|
||||
/// decentralised content-based-indexing system such as IPFS.
|
||||
#[pallet::weight(T::WeightInfo::submit_evidence())]
|
||||
#[pallet::call_index(7)]
|
||||
pub fn submit_evidence(
|
||||
origin: OriginFor<T>,
|
||||
wish: Wish,
|
||||
evidence: Evidence<T, I>,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let who = ensure_signed(origin)?;
|
||||
ensure!(Member::<T, I>::contains_key(&who), Error::<T, I>::NotTracked);
|
||||
let replaced = MemberEvidence::<T, I>::contains_key(&who);
|
||||
MemberEvidence::<T, I>::insert(&who, (wish, evidence));
|
||||
Self::deposit_event(Event::<T, I>::Requested { who, wish });
|
||||
Ok(if replaced { Pays::Yes } else { Pays::No }.into())
|
||||
}
|
||||
|
||||
/// Introduce an already-ranked individual of the collective into this pallet.
|
||||
///
|
||||
/// The rank may still be zero. This resets `last_proof` to the current block and
|
||||
/// `last_promotion` will be set to zero, thereby delaying any automatic demotion but
|
||||
/// allowing immediate promotion.
|
||||
///
|
||||
/// - `origin`: A signed origin of a ranked, but not tracked, account.
|
||||
#[pallet::weight(T::WeightInfo::import())]
|
||||
#[pallet::call_index(8)]
|
||||
#[deprecated = "Use `import_member` instead"]
|
||||
#[allow(deprecated)] // Otherwise FRAME will complain about using something deprecated.
|
||||
pub fn import(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
|
||||
let who = ensure_signed(origin)?;
|
||||
Self::do_import(who)?;
|
||||
|
||||
Ok(Pays::No.into()) // Successful imports are free
|
||||
}
|
||||
|
||||
/// Introduce an already-ranked individual of the collective into this pallet.
|
||||
///
|
||||
/// The rank may still be zero. Can be called by anyone on any collective member - including
|
||||
/// the sender.
|
||||
///
|
||||
/// This resets `last_proof` to the current block and `last_promotion` will be set to zero,
|
||||
/// thereby delaying any automatic demotion but allowing immediate promotion.
|
||||
///
|
||||
/// - `origin`: A signed origin of a ranked, but not tracked, account.
|
||||
/// - `who`: The account ID of the collective member to be inducted.
|
||||
#[pallet::weight(T::WeightInfo::set_partial_params())]
|
||||
#[pallet::call_index(11)]
|
||||
pub fn import_member(
|
||||
origin: OriginFor<T>,
|
||||
who: T::AccountId,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
ensure_signed(origin)?;
|
||||
Self::do_import(who)?;
|
||||
|
||||
Ok(Pays::No.into()) // Successful imports are free
|
||||
}
|
||||
|
||||
/// Set the parameters partially.
|
||||
///
|
||||
/// - `origin`: An origin complying with `ParamsOrigin` or root.
|
||||
/// - `partial_params`: The new parameters for the pallet.
|
||||
///
|
||||
/// This update config with multiple arguments without duplicating
|
||||
/// the fields that does not need to update (set to None).
|
||||
#[pallet::weight(T::WeightInfo::set_partial_params())]
|
||||
#[pallet::call_index(9)]
|
||||
pub fn set_partial_params(
|
||||
origin: OriginFor<T>,
|
||||
partial_params: Box<PartialParamsOf<T, I>>,
|
||||
) -> DispatchResult {
|
||||
T::ParamsOrigin::ensure_origin_or_root(origin)?;
|
||||
let params = Params::<T, I>::mutate(|p| {
|
||||
Self::set_partial_params_slice(&mut p.active_salary, partial_params.active_salary);
|
||||
Self::set_partial_params_slice(
|
||||
&mut p.passive_salary,
|
||||
partial_params.passive_salary,
|
||||
);
|
||||
Self::set_partial_params_slice(
|
||||
&mut p.demotion_period,
|
||||
partial_params.demotion_period,
|
||||
);
|
||||
Self::set_partial_params_slice(
|
||||
&mut p.min_promotion_period,
|
||||
partial_params.min_promotion_period,
|
||||
);
|
||||
if let Some(new_offboard_timeout) = partial_params.offboard_timeout {
|
||||
p.offboard_timeout = new_offboard_timeout;
|
||||
}
|
||||
p.clone()
|
||||
});
|
||||
Self::deposit_event(Event::<T, I>::ParamsChanged { params });
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
/// Partially update the base slice with a new slice
|
||||
///
|
||||
/// Only elements in the base slice which has a new value in the new slice will be updated.
|
||||
pub(crate) fn set_partial_params_slice<S>(
|
||||
base_slice: &mut BoundedVec<S, ConvertU16ToU32<T::MaxRank>>,
|
||||
new_slice: BoundedVec<Option<S>, ConvertU16ToU32<T::MaxRank>>,
|
||||
) {
|
||||
for (base_element, new_element) in base_slice.iter_mut().zip(new_slice) {
|
||||
if let Some(element) = new_element {
|
||||
*base_element = element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Import `who` into the core-fellowship pallet.
|
||||
///
|
||||
/// `who` must be a member of the collective but *not* already imported.
|
||||
pub(crate) fn do_import(who: T::AccountId) -> DispatchResult {
|
||||
ensure!(!Member::<T, I>::contains_key(&who), Error::<T, I>::AlreadyInducted);
|
||||
let rank = T::Members::rank_of(&who).ok_or(Error::<T, I>::Unranked)?;
|
||||
|
||||
let now = pezframe_system::Pallet::<T>::block_number();
|
||||
Member::<T, I>::insert(
|
||||
&who,
|
||||
MemberStatus { is_active: true, last_promotion: 0u32.into(), last_proof: now },
|
||||
);
|
||||
Self::deposit_event(Event::<T, I>::Imported { who, rank });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convert a rank into a `0..RANK_COUNT` index suitable for the arrays in Params.
|
||||
///
|
||||
/// Rank 1 becomes index 0, rank `RANK_COUNT` becomes index `RANK_COUNT - 1`. Any rank not
|
||||
/// in the range `1..=RANK_COUNT` is `None`.
|
||||
pub(crate) fn rank_to_index(rank: RankOf<T, I>) -> Option<usize> {
|
||||
if rank == 0 || rank > T::MaxRank::get() {
|
||||
None
|
||||
} else {
|
||||
Some((rank - 1) as usize)
|
||||
}
|
||||
}
|
||||
|
||||
fn dispose_evidence(who: T::AccountId, old_rank: u16, new_rank: Option<u16>) {
|
||||
if let Some((wish, evidence)) = MemberEvidence::<T, I>::take(&who) {
|
||||
let e = Event::<T, I>::EvidenceJudged { who, wish, evidence, old_rank, new_rank };
|
||||
Self::deposit_event(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> GetSalary<RankOf<T, I>, T::AccountId, T::Balance> for Pallet<T, I> {
|
||||
fn get_salary(rank: RankOf<T, I>, who: &T::AccountId) -> T::Balance {
|
||||
let index = match Self::rank_to_index(rank) {
|
||||
Some(i) => i,
|
||||
None => return Zero::zero(),
|
||||
};
|
||||
let member = match Member::<T, I>::get(who) {
|
||||
Some(m) => m,
|
||||
None => return Zero::zero(),
|
||||
};
|
||||
let params = Params::<T, I>::get();
|
||||
let salary =
|
||||
if member.is_active { params.active_salary } else { params.passive_salary };
|
||||
salary[index]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Guard to ensure that the given origin is inducted into this pallet with a given minimum rank.
|
||||
/// The account ID of the member is the `Success` value.
|
||||
pub struct EnsureInducted<T, I, const MIN_RANK: u16>(PhantomData<(T, I)>);
|
||||
impl<T: Config<I>, I: 'static, const MIN_RANK: u16> EnsureOrigin<T::RuntimeOrigin>
|
||||
for EnsureInducted<T, I, MIN_RANK>
|
||||
{
|
||||
type Success = T::AccountId;
|
||||
|
||||
fn try_origin(o: T::RuntimeOrigin) -> Result<Self::Success, T::RuntimeOrigin> {
|
||||
let who = <pezframe_system::EnsureSigned<_> as EnsureOrigin<_>>::try_origin(o)?;
|
||||
match T::Members::rank_of(&who) {
|
||||
Some(rank) if rank >= MIN_RANK && Member::<T, I>::contains_key(&who) => Ok(who),
|
||||
_ => Err(pezframe_system::RawOrigin::Signed(who).into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn try_successful_origin() -> Result<T::RuntimeOrigin, ()> {
|
||||
let who = pezframe_benchmarking::account::<T::AccountId>("successful_origin", 0, 0);
|
||||
if T::Members::rank_of(&who).is_none() {
|
||||
T::Members::induct(&who).map_err(|_| ())?;
|
||||
}
|
||||
for _ in 0..MIN_RANK {
|
||||
if T::Members::rank_of(&who).ok_or(())? < MIN_RANK {
|
||||
T::Members::promote(&who).map_err(|_| ())?;
|
||||
}
|
||||
}
|
||||
Ok(pezframe_system::RawOrigin::Signed(who).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl_ensure_origin_with_arg_ignoring_arg! {
|
||||
impl< { T: Config<I>, I: 'static, const MIN_RANK: u16, A } >
|
||||
EnsureOriginWithArg<T::RuntimeOrigin, A> for EnsureInducted<T, I, MIN_RANK>
|
||||
{}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> RankedMembersSwapHandler<T::AccountId, u16> for Pallet<T, I> {
|
||||
fn swapped(old: &T::AccountId, new: &T::AccountId, _rank: u16) {
|
||||
if old == new {
|
||||
defensive!("Should not try to swap with self");
|
||||
return;
|
||||
}
|
||||
if !Member::<T, I>::contains_key(old) {
|
||||
defensive!("Should not try to swap non-member");
|
||||
return;
|
||||
}
|
||||
if Member::<T, I>::contains_key(new) {
|
||||
defensive!("Should not try to overwrite existing member");
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(member) = Member::<T, I>::take(old) {
|
||||
Member::<T, I>::insert(new, member);
|
||||
}
|
||||
if let Some(we) = MemberEvidence::<T, I>::take(old) {
|
||||
MemberEvidence::<T, I>::insert(new, we);
|
||||
}
|
||||
|
||||
Self::deposit_event(Event::<T, I>::Swapped { who: old.clone(), new_who: new.clone() });
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
impl<T: Config<I>, I: 'static>
|
||||
pezpallet_ranked_collective::BenchmarkSetup<<T as pezframe_system::Config>::AccountId> for Pallet<T, I>
|
||||
{
|
||||
fn ensure_member(who: &<T as pezframe_system::Config>::AccountId) {
|
||||
#[allow(deprecated)]
|
||||
Self::import(pezframe_system::RawOrigin::Signed(who.clone()).into()).unwrap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Storage migrations for the core-fellowship pallet.
|
||||
use super::*;
|
||||
use pezframe_support::{
|
||||
pezpallet_prelude::*,
|
||||
storage_alias,
|
||||
traits::{DefensiveTruncateFrom, UncheckedOnRuntimeUpgrade},
|
||||
BoundedVec,
|
||||
};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use alloc::vec::Vec;
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use pezsp_runtime::TryRuntimeError;
|
||||
|
||||
mod v0 {
|
||||
use pezframe_system::pezpallet_prelude::BlockNumberFor;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Encode, Decode, Eq, PartialEq, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)]
|
||||
pub struct ParamsType<Balance, BlockNumber, const RANKS: usize> {
|
||||
pub active_salary: [Balance; RANKS],
|
||||
pub passive_salary: [Balance; RANKS],
|
||||
pub demotion_period: [BlockNumber; RANKS],
|
||||
pub min_promotion_period: [BlockNumber; RANKS],
|
||||
pub offboard_timeout: BlockNumber,
|
||||
}
|
||||
|
||||
impl<Balance: Default + Copy, BlockNumber: Default + Copy, const RANKS: usize> Default
|
||||
for ParamsType<Balance, BlockNumber, RANKS>
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
active_salary: [Balance::default(); RANKS],
|
||||
passive_salary: [Balance::default(); RANKS],
|
||||
demotion_period: [BlockNumber::default(); RANKS],
|
||||
min_promotion_period: [BlockNumber::default(); RANKS],
|
||||
offboard_timeout: BlockNumber::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Number of available ranks from old version.
|
||||
pub(crate) const RANK_COUNT: usize = 9;
|
||||
|
||||
pub type ParamsOf<T, I> = ParamsType<<T as Config<I>>::Balance, BlockNumberFor<T>, RANK_COUNT>;
|
||||
|
||||
/// V0 type for [`crate::Params`].
|
||||
#[storage_alias]
|
||||
pub type Params<T: Config<I>, I: 'static> =
|
||||
StorageValue<Pallet<T, I>, ParamsOf<T, I>, ValueQuery>;
|
||||
}
|
||||
|
||||
pub struct MigrateToV1<T, I = ()>(PhantomData<(T, I)>);
|
||||
impl<T: Config<I>, I: 'static> UncheckedOnRuntimeUpgrade for MigrateToV1<T, I> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
|
||||
ensure!(
|
||||
T::MaxRank::get() as usize >= v0::RANK_COUNT,
|
||||
"pezpallet-core-fellowship: new bound should not truncate"
|
||||
);
|
||||
Ok(Default::default())
|
||||
}
|
||||
|
||||
fn on_runtime_upgrade() -> pezframe_support::weights::Weight {
|
||||
// Read the old value from storage
|
||||
let old_value = v0::Params::<T, I>::take();
|
||||
// Write the new value to storage
|
||||
let new = crate::ParamsType {
|
||||
active_salary: BoundedVec::defensive_truncate_from(old_value.active_salary.to_vec()),
|
||||
passive_salary: BoundedVec::defensive_truncate_from(old_value.passive_salary.to_vec()),
|
||||
demotion_period: BoundedVec::defensive_truncate_from(
|
||||
old_value.demotion_period.to_vec(),
|
||||
),
|
||||
min_promotion_period: BoundedVec::defensive_truncate_from(
|
||||
old_value.min_promotion_period.to_vec(),
|
||||
),
|
||||
offboard_timeout: old_value.offboard_timeout,
|
||||
};
|
||||
crate::Params::<T, I>::put(new);
|
||||
T::DbWeight::get().reads_writes(1, 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// [`UncheckedOnRuntimeUpgrade`] implementation [`MigrateToV1`] wrapped in a
|
||||
/// [`VersionedMigration`](pezframe_support::migrations::VersionedMigration), which ensures that:
|
||||
/// - The migration only runs once when the on-chain storage version is 0
|
||||
/// - The on-chain storage version is updated to `1` after the migration executes
|
||||
/// - Reads/Writes from checking/settings the on-chain storage version are accounted for
|
||||
pub type MigrateV0ToV1<T, I> = pezframe_support::migrations::VersionedMigration<
|
||||
0, // The migration will only execute when the on-chain storage version is 0
|
||||
1, // The on-chain storage version will be set to 1 after the migration is complete
|
||||
MigrateToV1<T, I>,
|
||||
crate::pallet::Pallet<T, I>,
|
||||
<T as pezframe_system::Config>::DbWeight,
|
||||
>;
|
||||
@@ -0,0 +1,281 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Integration test together with the ranked-collective pallet.
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use pezframe_support::{
|
||||
assert_noop, assert_ok, derive_impl, hypothetically, hypothetically_ok, ord_parameter_types,
|
||||
pezpallet_prelude::Weight,
|
||||
parameter_types,
|
||||
traits::{ConstU16, EitherOf, IsInVec, MapSuccess, NoOpPoll, TryMapSuccess},
|
||||
};
|
||||
use pezframe_system::{pezpallet_prelude::BlockNumberFor, EnsureSignedBy};
|
||||
use pezpallet_ranked_collective::{EnsureRanked, Geometric, Rank};
|
||||
use pezsp_core::Get;
|
||||
use pezsp_runtime::{
|
||||
bounded_vec,
|
||||
traits::{Convert, ReduceBy, ReplaceWithDefault, TryMorphInto},
|
||||
BuildStorage,
|
||||
};
|
||||
type Class = Rank;
|
||||
|
||||
use crate as pezpallet_core_fellowship;
|
||||
use crate::*;
|
||||
|
||||
type Block = pezframe_system::mocking::MockBlock<Test>;
|
||||
|
||||
pezframe_support::construct_runtime!(
|
||||
pub enum Test
|
||||
{
|
||||
System: pezframe_system,
|
||||
CoreFellowship: pezpallet_core_fellowship,
|
||||
Club: pezpallet_ranked_collective,
|
||||
}
|
||||
);
|
||||
|
||||
parameter_types! {
|
||||
pub BlockWeights: pezframe_system::limits::BlockWeights =
|
||||
pezframe_system::limits::BlockWeights::simple_max(Weight::from_parts(1_000_000, u64::max_value()));
|
||||
}
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for Test {
|
||||
type Block = Block;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub static MinRankOfClassDelta: Rank = 0;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub ZeroToNine: Vec<u64> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
pub EvidenceSize: u32 = 1024;
|
||||
}
|
||||
ord_parameter_types! {
|
||||
pub const One: u64 = 1;
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
type WeightInfo = ();
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Members = Club;
|
||||
type Balance = u64;
|
||||
type ParamsOrigin = EnsureSignedBy<One, u64>;
|
||||
type InductOrigin = EnsureInducted<Test, (), 1>;
|
||||
type ApproveOrigin = TryMapSuccess<EnsureSignedBy<IsInVec<ZeroToNine>, u64>, TryMorphInto<u16>>;
|
||||
type PromoteOrigin = TryMapSuccess<EnsureSignedBy<IsInVec<ZeroToNine>, u64>, TryMorphInto<u16>>;
|
||||
type FastPromoteOrigin = Self::PromoteOrigin;
|
||||
type EvidenceSize = EvidenceSize;
|
||||
type MaxRank = ConstU16<9>;
|
||||
}
|
||||
|
||||
/// Convert the tally class into the minimum rank required to vote on the poll.
|
||||
/// MinRank(Class) = Class - Delta
|
||||
pub struct MinRankOfClass<Delta>(PhantomData<Delta>);
|
||||
impl<Delta: Get<Rank>> Convert<Class, Rank> for MinRankOfClass<Delta> {
|
||||
fn convert(a: Class) -> Rank {
|
||||
a.saturating_sub(Delta::get())
|
||||
}
|
||||
}
|
||||
|
||||
impl pezpallet_ranked_collective::Config for Test {
|
||||
type WeightInfo = ();
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type PromoteOrigin = EitherOf<
|
||||
// Root can promote arbitrarily.
|
||||
pezframe_system::EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>,
|
||||
// Members can promote up to the rank of 2 below them.
|
||||
MapSuccess<EnsureRanked<Test, (), 2>, ReduceBy<ConstU16<2>>>,
|
||||
>;
|
||||
type AddOrigin = MapSuccess<Self::PromoteOrigin, ReplaceWithDefault<()>>;
|
||||
type DemoteOrigin = EitherOf<
|
||||
// Root can demote arbitrarily.
|
||||
pezframe_system::EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>,
|
||||
// Members can demote up to the rank of 3 below them.
|
||||
MapSuccess<EnsureRanked<Test, (), 3>, ReduceBy<ConstU16<3>>>,
|
||||
>;
|
||||
type RemoveOrigin = Self::DemoteOrigin;
|
||||
type ExchangeOrigin = EitherOf<
|
||||
// Root can exchange arbitrarily.
|
||||
pezframe_system::EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>,
|
||||
// Members can exchange up to the rank of 2 below them.
|
||||
MapSuccess<EnsureRanked<Test, (), 2>, ReduceBy<ConstU16<2>>>,
|
||||
>;
|
||||
type Polls = NoOpPoll<BlockNumberFor<Test>>;
|
||||
type MinRankOfClass = MinRankOfClass<MinRankOfClassDelta>;
|
||||
type MemberSwappedHandler = CoreFellowship;
|
||||
type VoteWeight = Geometric;
|
||||
type MaxMemberCount = ();
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type BenchmarkSetup = CoreFellowship;
|
||||
}
|
||||
|
||||
pub fn new_test_ext() -> pezsp_io::TestExternalities {
|
||||
let t = pezframe_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
let mut ext = pezsp_io::TestExternalities::new(t);
|
||||
ext.execute_with(|| {
|
||||
assert_ok!(Club::add_member(RuntimeOrigin::root(), 100));
|
||||
promote_n_times(100, 9);
|
||||
let params = ParamsType {
|
||||
active_salary: bounded_vec![10, 20, 30, 40, 50, 60, 70, 80, 90],
|
||||
passive_salary: bounded_vec![1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
demotion_period: bounded_vec![2, 4, 6, 8, 10, 12, 14, 16, 18],
|
||||
min_promotion_period: bounded_vec![3, 6, 9, 12, 15, 18, 21, 24, 27],
|
||||
offboard_timeout: 1,
|
||||
};
|
||||
assert_ok!(CoreFellowship::set_params(signed(1), Box::new(params)));
|
||||
System::set_block_number(1);
|
||||
});
|
||||
ext
|
||||
}
|
||||
|
||||
fn promote_n_times(acc: u64, r: u16) {
|
||||
for _ in 0..r {
|
||||
assert_ok!(Club::promote_member(RuntimeOrigin::root(), acc));
|
||||
}
|
||||
}
|
||||
|
||||
fn signed(who: u64) -> RuntimeOrigin {
|
||||
RuntimeOrigin::signed(who)
|
||||
}
|
||||
|
||||
fn assert_last_event(generic_event: <Test as Config>::RuntimeEvent) {
|
||||
let events = pezframe_system::Pallet::<Test>::events();
|
||||
let system_event: <Test as pezframe_system::Config>::RuntimeEvent = generic_event.into();
|
||||
let pezframe_system::EventRecord { event, .. } = events.last().expect("Event expected");
|
||||
assert_eq!(event, &system_event.into());
|
||||
}
|
||||
|
||||
fn evidence(e: u32) -> Evidence<Test, ()> {
|
||||
e.encode()
|
||||
.into_iter()
|
||||
.cycle()
|
||||
.take(1024)
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.expect("Static length matches")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn import_simple_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
for i in 0u16..9 {
|
||||
let acc = i as u64;
|
||||
|
||||
// Does not work yet
|
||||
assert_noop!(CoreFellowship::import(signed(acc)), Error::<Test>::Unranked);
|
||||
assert_noop!(
|
||||
CoreFellowship::import_member(signed(acc + 1), acc),
|
||||
Error::<Test>::Unranked
|
||||
);
|
||||
|
||||
assert_ok!(Club::add_member(RuntimeOrigin::root(), acc));
|
||||
promote_n_times(acc, i);
|
||||
|
||||
hypothetically_ok!(CoreFellowship::import(signed(acc)));
|
||||
hypothetically_ok!(CoreFellowship::import_member(signed(acc), acc));
|
||||
// Works from other accounts
|
||||
assert_ok!(CoreFellowship::import_member(signed(acc + 1), acc));
|
||||
|
||||
// Does not work again
|
||||
assert_noop!(CoreFellowship::import(signed(acc)), Error::<Test>::AlreadyInducted);
|
||||
assert_noop!(
|
||||
CoreFellowship::import_member(signed(acc + 1), acc),
|
||||
Error::<Test>::AlreadyInducted
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn swap_simple_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
for i in 0u16..9 {
|
||||
let acc = i as u64;
|
||||
|
||||
assert_ok!(Club::add_member(RuntimeOrigin::root(), acc));
|
||||
promote_n_times(acc, i);
|
||||
hypothetically_ok!(CoreFellowship::import(signed(acc)));
|
||||
assert_ok!(CoreFellowship::import_member(signed(acc), acc));
|
||||
|
||||
// Swapping normally works:
|
||||
assert_ok!(Club::exchange_member(RuntimeOrigin::root(), acc, acc + 10));
|
||||
assert_last_event(Event::Swapped { who: acc, new_who: acc + 10 }.into());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Exhaustively test that adding member `1` is equivalent to adding member `0` and then swapping.
|
||||
///
|
||||
/// The member also submits evidence before the swap.
|
||||
#[test]
|
||||
fn swap_exhaustive_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let root_add = hypothetically!({
|
||||
assert_ok!(Club::add_member(RuntimeOrigin::root(), 1));
|
||||
promote_n_times(1, 4);
|
||||
assert_ok!(CoreFellowship::import(signed(1)));
|
||||
assert_ok!(CoreFellowship::submit_evidence(signed(1), Wish::Retention, evidence(1)));
|
||||
|
||||
// The events mess up the storage root:
|
||||
System::reset_events();
|
||||
pezsp_io::storage::root(pezsp_runtime::StateVersion::V1)
|
||||
});
|
||||
|
||||
let root_swap = hypothetically!({
|
||||
assert_ok!(Club::add_member(RuntimeOrigin::root(), 0));
|
||||
promote_n_times(0, 4);
|
||||
assert_ok!(CoreFellowship::import(signed(0)));
|
||||
assert_ok!(CoreFellowship::submit_evidence(signed(0), Wish::Retention, evidence(1)));
|
||||
|
||||
// Now we swap:
|
||||
assert_ok!(Club::exchange_member(RuntimeOrigin::root(), 0, 1));
|
||||
|
||||
System::reset_events();
|
||||
pezsp_io::storage::root(pezsp_runtime::StateVersion::V1)
|
||||
});
|
||||
|
||||
assert_eq!(root_add, root_swap);
|
||||
// Ensure that we don't compare trivial stuff like `()` from a type error above.
|
||||
assert_eq!(root_add.len(), 32);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn swap_bad_noops() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Club::add_member(RuntimeOrigin::root(), 0));
|
||||
promote_n_times(0, 0);
|
||||
assert_ok!(CoreFellowship::import(signed(0)));
|
||||
assert_ok!(Club::add_member(RuntimeOrigin::root(), 1));
|
||||
promote_n_times(1, 1);
|
||||
assert_ok!(CoreFellowship::import(signed(1)));
|
||||
|
||||
// Swapping for another member is a noop:
|
||||
assert_noop!(
|
||||
Club::exchange_member(RuntimeOrigin::root(), 0, 1),
|
||||
pezpallet_ranked_collective::Error::<Test>::AlreadyMember
|
||||
);
|
||||
// Swapping for the same member is a noop:
|
||||
assert_noop!(
|
||||
Club::exchange_member(RuntimeOrigin::root(), 0, 0),
|
||||
pezpallet_ranked_collective::Error::<Test>::SameMember
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
//! Tests for this crate.
|
||||
|
||||
pub(crate) mod integration;
|
||||
pub(crate) mod unit;
|
||||
@@ -0,0 +1,547 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! The crate's tests.
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use core::cell::RefCell;
|
||||
use pezframe_support::{
|
||||
assert_noop, assert_ok, derive_impl, hypothetically, ord_parameter_types,
|
||||
pezpallet_prelude::Weight,
|
||||
parameter_types,
|
||||
traits::{tokens::GetSalary, ConstU16, ConstU32, IsInVec, TryMapSuccess},
|
||||
};
|
||||
use pezframe_system::EnsureSignedBy;
|
||||
use pezsp_runtime::{bounded_vec, traits::TryMorphInto, BuildStorage, DispatchError, DispatchResult};
|
||||
|
||||
use crate as pezpallet_core_fellowship;
|
||||
use crate::*;
|
||||
|
||||
type Block = pezframe_system::mocking::MockBlock<Test>;
|
||||
|
||||
pezframe_support::construct_runtime!(
|
||||
pub enum Test
|
||||
{
|
||||
System: pezframe_system,
|
||||
CoreFellowship: pezpallet_core_fellowship,
|
||||
}
|
||||
);
|
||||
|
||||
parameter_types! {
|
||||
pub BlockWeights: pezframe_system::limits::BlockWeights =
|
||||
pezframe_system::limits::BlockWeights::simple_max(Weight::from_parts(1_000_000, u64::max_value()));
|
||||
}
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for Test {
|
||||
type Block = Block;
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
pub static CLUB: RefCell<BTreeMap<u64, u16>> = RefCell::new(BTreeMap::new());
|
||||
}
|
||||
|
||||
pub struct TestClub;
|
||||
impl RankedMembers for TestClub {
|
||||
type AccountId = u64;
|
||||
type Rank = u16;
|
||||
fn min_rank() -> Self::Rank {
|
||||
0
|
||||
}
|
||||
fn rank_of(who: &Self::AccountId) -> Option<Self::Rank> {
|
||||
CLUB.with(|club| club.borrow().get(who).cloned())
|
||||
}
|
||||
fn induct(who: &Self::AccountId) -> DispatchResult {
|
||||
CLUB.with(|club| club.borrow_mut().insert(*who, 0));
|
||||
Ok(())
|
||||
}
|
||||
fn promote(who: &Self::AccountId) -> DispatchResult {
|
||||
CLUB.with(|club| {
|
||||
club.borrow_mut().entry(*who).and_modify(|r| *r += 1);
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
fn demote(who: &Self::AccountId) -> DispatchResult {
|
||||
CLUB.with(|club| match Self::rank_of(who) {
|
||||
None => Err(pezsp_runtime::DispatchError::Unavailable),
|
||||
Some(0) => {
|
||||
club.borrow_mut().remove(&who);
|
||||
Ok(())
|
||||
},
|
||||
Some(_) => {
|
||||
club.borrow_mut().entry(*who).and_modify(|x| *x -= 1);
|
||||
Ok(())
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn set_rank(who: u64, rank: u16) {
|
||||
CLUB.with(|club| club.borrow_mut().insert(who, rank));
|
||||
}
|
||||
|
||||
fn unrank(who: u64) {
|
||||
CLUB.with(|club| club.borrow_mut().remove(&who));
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub ZeroToNine: Vec<u64> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
}
|
||||
ord_parameter_types! {
|
||||
pub const One: u64 = 1;
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
type WeightInfo = ();
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Members = TestClub;
|
||||
type Balance = u64;
|
||||
type ParamsOrigin = EnsureSignedBy<One, u64>;
|
||||
type InductOrigin = EnsureInducted<Test, (), 1>;
|
||||
type ApproveOrigin = TryMapSuccess<EnsureSignedBy<IsInVec<ZeroToNine>, u64>, TryMorphInto<u16>>;
|
||||
type PromoteOrigin = TryMapSuccess<EnsureSignedBy<IsInVec<ZeroToNine>, u64>, TryMorphInto<u16>>;
|
||||
type FastPromoteOrigin = Self::PromoteOrigin;
|
||||
type EvidenceSize = ConstU32<1024>;
|
||||
type MaxRank = ConstU16<9>;
|
||||
}
|
||||
|
||||
pub fn new_test_ext() -> pezsp_io::TestExternalities {
|
||||
let t = pezframe_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
let mut ext = pezsp_io::TestExternalities::new(t);
|
||||
ext.execute_with(|| {
|
||||
set_rank(100, 9);
|
||||
let params = ParamsType {
|
||||
active_salary: bounded_vec![10, 20, 30, 40, 50, 60, 70, 80, 90],
|
||||
passive_salary: bounded_vec![1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
demotion_period: bounded_vec![2, 4, 6, 8, 10, 12, 14, 16, 18],
|
||||
min_promotion_period: bounded_vec![3, 6, 9, 12, 15, 18, 21, 24, 27],
|
||||
offboard_timeout: 1,
|
||||
};
|
||||
|
||||
assert_ok!(CoreFellowship::set_params(signed(1), Box::new(params)));
|
||||
System::set_block_number(1);
|
||||
});
|
||||
ext
|
||||
}
|
||||
|
||||
fn next_block() {
|
||||
System::set_block_number(System::block_number() + 1);
|
||||
}
|
||||
|
||||
fn run_to(n: u64) {
|
||||
while System::block_number() < n {
|
||||
next_block();
|
||||
}
|
||||
}
|
||||
|
||||
fn signed(who: u64) -> RuntimeOrigin {
|
||||
RuntimeOrigin::signed(who)
|
||||
}
|
||||
|
||||
fn next_demotion(who: u64) -> u64 {
|
||||
let member = Member::<Test>::get(who).unwrap();
|
||||
let demotion_period = Params::<Test>::get().demotion_period;
|
||||
member.last_proof + demotion_period[TestClub::rank_of(&who).unwrap() as usize - 1]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_stuff() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(CoreFellowship::rank_to_index(0), None);
|
||||
assert_eq!(CoreFellowship::rank_to_index(1), Some(0));
|
||||
assert_eq!(CoreFellowship::rank_to_index(9), Some(8));
|
||||
assert_eq!(CoreFellowship::rank_to_index(10), None);
|
||||
assert_eq!(CoreFellowship::get_salary(0, &1), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_params_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let params = ParamsType {
|
||||
active_salary: bounded_vec![10, 20, 30, 40, 50, 60, 70, 80, 90],
|
||||
passive_salary: bounded_vec![1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
demotion_period: bounded_vec![1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
min_promotion_period: bounded_vec![1, 2, 3, 4, 5, 10, 15, 20, 30],
|
||||
offboard_timeout: 1,
|
||||
};
|
||||
assert_noop!(
|
||||
CoreFellowship::set_params(signed(2), Box::new(params.clone())),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_ok!(CoreFellowship::set_params(signed(1), Box::new(params)));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_partial_params_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let params = ParamsType {
|
||||
active_salary: bounded_vec![None; 9],
|
||||
passive_salary: bounded_vec![None; 9],
|
||||
demotion_period: bounded_vec![None, Some(10), None, None, None, None, None, None, None],
|
||||
min_promotion_period: bounded_vec![None; 9],
|
||||
offboard_timeout: Some(2),
|
||||
};
|
||||
assert_noop!(
|
||||
CoreFellowship::set_partial_params(signed(2), Box::new(params.clone())),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_ok!(CoreFellowship::set_partial_params(signed(1), Box::new(params)));
|
||||
|
||||
// Update params from the base params value declared in `new_test_ext`
|
||||
let raw_updated_params = ParamsType {
|
||||
active_salary: bounded_vec![10, 20, 30, 40, 50, 60, 70, 80, 90],
|
||||
passive_salary: bounded_vec![1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
demotion_period: bounded_vec![2, 10, 6, 8, 10, 12, 14, 16, 18],
|
||||
min_promotion_period: bounded_vec![3, 6, 9, 12, 15, 18, 21, 24, 27],
|
||||
offboard_timeout: 2,
|
||||
};
|
||||
// Updated params stored in Params storage value
|
||||
let updated_params = Params::<Test>::get();
|
||||
assert_eq!(raw_updated_params, updated_params);
|
||||
|
||||
System::assert_last_event(
|
||||
Event::<Test, _>::ParamsChanged { params: updated_params }.into(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn import_member_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_noop!(CoreFellowship::import_member(signed(0), 0), Error::<Test>::Unranked);
|
||||
assert_noop!(CoreFellowship::import(signed(0)), Error::<Test>::Unranked);
|
||||
|
||||
// Make induction work:
|
||||
set_rank(0, 1);
|
||||
assert!(!Member::<Test>::contains_key(0), "not yet imported");
|
||||
|
||||
// `import_member` can be used to induct ourselves:
|
||||
hypothetically!({
|
||||
assert_ok!(CoreFellowship::import_member(signed(0), 0));
|
||||
assert!(Member::<Test>::contains_key(0), "got imported");
|
||||
|
||||
// Twice does not work:
|
||||
assert_noop!(
|
||||
CoreFellowship::import_member(signed(0), 0),
|
||||
Error::<Test>::AlreadyInducted
|
||||
);
|
||||
assert_noop!(CoreFellowship::import(signed(0)), Error::<Test>::AlreadyInducted);
|
||||
});
|
||||
|
||||
// But we could have also used `import`:
|
||||
hypothetically!({
|
||||
assert_ok!(CoreFellowship::import(signed(0)));
|
||||
assert!(Member::<Test>::contains_key(0), "got imported");
|
||||
|
||||
// Twice does not work:
|
||||
assert_noop!(
|
||||
CoreFellowship::import_member(signed(0), 0),
|
||||
Error::<Test>::AlreadyInducted
|
||||
);
|
||||
assert_noop!(CoreFellowship::import(signed(0)), Error::<Test>::AlreadyInducted);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn import_member_same_as_import() {
|
||||
new_test_ext().execute_with(|| {
|
||||
for rank in 0..=9 {
|
||||
set_rank(0, rank);
|
||||
|
||||
let import_root = hypothetically!({
|
||||
assert_ok!(CoreFellowship::import(signed(0)));
|
||||
pezsp_io::storage::root(pezsp_runtime::StateVersion::V1)
|
||||
});
|
||||
|
||||
let import_member_root = hypothetically!({
|
||||
assert_ok!(CoreFellowship::import_member(signed(1), 0));
|
||||
pezsp_io::storage::root(pezsp_runtime::StateVersion::V1)
|
||||
});
|
||||
|
||||
// `import` and `import_member` do exactly the same thing.
|
||||
assert_eq!(import_root, import_member_root);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn induct_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
set_rank(0, 0);
|
||||
assert_ok!(CoreFellowship::import(signed(0)));
|
||||
set_rank(1, 1);
|
||||
assert_ok!(CoreFellowship::import(signed(1)));
|
||||
|
||||
assert_noop!(CoreFellowship::induct(signed(10), 10), DispatchError::BadOrigin);
|
||||
assert_noop!(CoreFellowship::induct(signed(0), 10), DispatchError::BadOrigin);
|
||||
assert_ok!(CoreFellowship::induct(signed(1), 10));
|
||||
assert_noop!(CoreFellowship::induct(signed(1), 10), Error::<Test>::AlreadyInducted);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn promote_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
set_rank(1, 1);
|
||||
assert_ok!(CoreFellowship::import(signed(1)));
|
||||
assert_noop!(CoreFellowship::promote(signed(1), 10, 1), Error::<Test>::Unranked);
|
||||
|
||||
assert_ok!(CoreFellowship::induct(signed(1), 10));
|
||||
assert_noop!(CoreFellowship::promote(signed(10), 10, 1), DispatchError::BadOrigin);
|
||||
assert_noop!(CoreFellowship::promote(signed(0), 10, 1), Error::<Test>::NoPermission);
|
||||
assert_noop!(CoreFellowship::promote(signed(3), 10, 2), Error::<Test>::UnexpectedRank);
|
||||
run_to(3);
|
||||
assert_noop!(CoreFellowship::promote(signed(1), 10, 1), Error::<Test>::TooSoon);
|
||||
run_to(4);
|
||||
assert_ok!(CoreFellowship::promote(signed(1), 10, 1));
|
||||
set_rank(11, 0);
|
||||
assert_noop!(CoreFellowship::promote(signed(1), 11, 1), Error::<Test>::NotTracked);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn promote_fast_works() {
|
||||
let alice = 1;
|
||||
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_noop!(
|
||||
CoreFellowship::promote_fast(signed(alice), alice, 1),
|
||||
Error::<Test>::Unranked
|
||||
);
|
||||
set_rank(alice, 0);
|
||||
assert_noop!(
|
||||
CoreFellowship::promote_fast(signed(alice), alice, 1),
|
||||
Error::<Test>::NotTracked
|
||||
);
|
||||
assert_ok!(CoreFellowship::import(signed(alice)));
|
||||
|
||||
// Cannot fast promote to the same rank:
|
||||
assert_noop!(
|
||||
CoreFellowship::promote_fast(signed(alice), alice, 0),
|
||||
Error::<Test>::UnexpectedRank
|
||||
);
|
||||
assert_ok!(CoreFellowship::promote_fast(signed(alice), alice, 1));
|
||||
assert_eq!(TestClub::rank_of(&alice), Some(1));
|
||||
|
||||
// Cannot promote normally because of the period:
|
||||
assert_noop!(CoreFellowship::promote(signed(2), alice, 2), Error::<Test>::TooSoon);
|
||||
// But can fast promote:
|
||||
assert_ok!(CoreFellowship::promote_fast(signed(2), alice, 2));
|
||||
assert_eq!(TestClub::rank_of(&alice), Some(2));
|
||||
|
||||
// Cannot promote to lower rank:
|
||||
assert_noop!(
|
||||
CoreFellowship::promote_fast(signed(alice), alice, 0),
|
||||
Error::<Test>::UnexpectedRank
|
||||
);
|
||||
assert_noop!(
|
||||
CoreFellowship::promote_fast(signed(alice), alice, 1),
|
||||
Error::<Test>::UnexpectedRank
|
||||
);
|
||||
// Permission is checked:
|
||||
assert_noop!(
|
||||
CoreFellowship::promote_fast(signed(alice), alice, 2),
|
||||
Error::<Test>::NoPermission
|
||||
);
|
||||
|
||||
// Can fast promote up to the maximum:
|
||||
assert_ok!(CoreFellowship::promote_fast(signed(9), alice, 9));
|
||||
// But not past the maximum:
|
||||
assert_noop!(
|
||||
CoreFellowship::promote_fast(RuntimeOrigin::root(), alice, 10),
|
||||
Error::<Test>::InvalidRank
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Compare the storage root hashes of a normal promote and a fast promote.
|
||||
#[test]
|
||||
fn promote_fast_identical_to_promote() {
|
||||
let alice = 1;
|
||||
|
||||
new_test_ext().execute_with(|| {
|
||||
set_rank(alice, 0);
|
||||
assert_eq!(TestClub::rank_of(&alice), Some(0));
|
||||
assert_ok!(CoreFellowship::import(signed(alice)));
|
||||
run_to(3);
|
||||
assert_eq!(TestClub::rank_of(&alice), Some(0));
|
||||
assert_ok!(CoreFellowship::submit_evidence(
|
||||
signed(alice),
|
||||
Wish::Promotion,
|
||||
bounded_vec![0; 1024]
|
||||
));
|
||||
|
||||
let root_promote = hypothetically!({
|
||||
assert_ok!(CoreFellowship::promote(signed(alice), alice, 1));
|
||||
// Don't clean the events since they should emit the same events:
|
||||
pezsp_io::storage::root(pezsp_runtime::StateVersion::V1)
|
||||
});
|
||||
|
||||
// This is using thread locals instead of storage...
|
||||
TestClub::demote(&alice).unwrap();
|
||||
|
||||
let root_promote_fast = hypothetically!({
|
||||
assert_ok!(CoreFellowship::promote_fast(signed(alice), alice, 1));
|
||||
|
||||
pezsp_io::storage::root(pezsp_runtime::StateVersion::V1)
|
||||
});
|
||||
|
||||
assert_eq!(root_promote, root_promote_fast);
|
||||
// Ensure that we don't compare trivial stuff like `()` from a type error above.
|
||||
assert_eq!(root_promote.len(), 32);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
set_rank(10, 5);
|
||||
assert_noop!(CoreFellowship::approve(signed(4), 10, 5), Error::<Test>::NoPermission);
|
||||
assert_noop!(CoreFellowship::approve(signed(6), 10, 6), Error::<Test>::UnexpectedRank);
|
||||
assert_ok!(CoreFellowship::import(signed(10)));
|
||||
assert!(Member::<Test>::contains_key(10));
|
||||
assert_eq!(next_demotion(10), 11);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auto_demote_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
set_rank(10, 5);
|
||||
assert_ok!(CoreFellowship::import(signed(10)));
|
||||
|
||||
run_to(10);
|
||||
assert_noop!(CoreFellowship::bump(signed(0), 10), Error::<Test>::NothingDoing);
|
||||
run_to(11);
|
||||
assert_ok!(CoreFellowship::bump(signed(0), 10));
|
||||
assert_eq!(TestClub::rank_of(&10), Some(4));
|
||||
assert_noop!(CoreFellowship::bump(signed(0), 10), Error::<Test>::NothingDoing);
|
||||
assert_eq!(next_demotion(10), 19);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auto_demote_offboard_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
set_rank(10, 1);
|
||||
assert_ok!(CoreFellowship::import(signed(10)));
|
||||
|
||||
run_to(3);
|
||||
assert_ok!(CoreFellowship::bump(signed(0), 10));
|
||||
assert_eq!(TestClub::rank_of(&10), Some(0));
|
||||
assert_noop!(CoreFellowship::bump(signed(0), 10), Error::<Test>::NothingDoing);
|
||||
run_to(4);
|
||||
assert_ok!(CoreFellowship::bump(signed(0), 10));
|
||||
assert_noop!(CoreFellowship::bump(signed(0), 10), Error::<Test>::NotTracked);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn offboard_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_noop!(CoreFellowship::offboard(signed(0), 10), Error::<Test>::NotTracked);
|
||||
set_rank(10, 0);
|
||||
assert_noop!(CoreFellowship::offboard(signed(0), 10), Error::<Test>::Ranked);
|
||||
|
||||
assert_ok!(CoreFellowship::import(signed(10)));
|
||||
assert_noop!(CoreFellowship::offboard(signed(0), 10), Error::<Test>::Ranked);
|
||||
|
||||
unrank(10);
|
||||
assert_ok!(CoreFellowship::offboard(signed(0), 10));
|
||||
assert_noop!(CoreFellowship::offboard(signed(0), 10), Error::<Test>::NotTracked);
|
||||
assert_noop!(CoreFellowship::bump(signed(0), 10), Error::<Test>::NotTracked);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infinite_demotion_period_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let params = ParamsType {
|
||||
active_salary: bounded_vec![10, 10, 10, 10, 10, 10, 10, 10, 10],
|
||||
passive_salary: bounded_vec![10, 10, 10, 10, 10, 10, 10, 10, 10],
|
||||
min_promotion_period: bounded_vec![10, 10, 10, 10, 10, 10, 10, 10, 10],
|
||||
demotion_period: bounded_vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
offboard_timeout: 0,
|
||||
};
|
||||
assert_ok!(CoreFellowship::set_params(signed(1), Box::new(params)));
|
||||
|
||||
set_rank(0, 0);
|
||||
assert_ok!(CoreFellowship::import(signed(0)));
|
||||
set_rank(1, 1);
|
||||
assert_ok!(CoreFellowship::import(signed(1)));
|
||||
|
||||
assert_noop!(CoreFellowship::bump(signed(0), 0), Error::<Test>::NothingDoing);
|
||||
assert_noop!(CoreFellowship::bump(signed(0), 1), Error::<Test>::NothingDoing);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn proof_postpones_auto_demote() {
|
||||
new_test_ext().execute_with(|| {
|
||||
set_rank(10, 5);
|
||||
assert_ok!(CoreFellowship::import(signed(10)));
|
||||
|
||||
run_to(11);
|
||||
assert_ok!(CoreFellowship::approve(signed(5), 10, 5));
|
||||
assert_eq!(next_demotion(10), 21);
|
||||
assert_noop!(CoreFellowship::bump(signed(0), 10), Error::<Test>::NothingDoing);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn promote_postpones_auto_demote() {
|
||||
new_test_ext().execute_with(|| {
|
||||
set_rank(10, 5);
|
||||
assert_ok!(CoreFellowship::import(signed(10)));
|
||||
|
||||
run_to(19);
|
||||
assert_ok!(CoreFellowship::promote(signed(6), 10, 6));
|
||||
assert_eq!(next_demotion(10), 31);
|
||||
assert_noop!(CoreFellowship::bump(signed(0), 10), Error::<Test>::NothingDoing);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_salary_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
for i in 1..=9u64 {
|
||||
set_rank(10 + i, i as u16);
|
||||
assert_ok!(CoreFellowship::import(signed(10 + i)));
|
||||
assert_eq!(CoreFellowship::get_salary(i as u16, &(10 + i)), i * 10);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn active_changing_get_salary_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
for i in 1..=9u64 {
|
||||
set_rank(10 + i, i as u16);
|
||||
assert_ok!(CoreFellowship::import(signed(10 + i)));
|
||||
assert_ok!(CoreFellowship::set_active(signed(10 + i), false));
|
||||
assert_eq!(CoreFellowship::get_salary(i as u16, &(10 + i)), i);
|
||||
assert_ok!(CoreFellowship::set_active(signed(10 + i), true));
|
||||
assert_eq!(CoreFellowship::get_salary(i as u16, &(10 + i)), i * 10);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,533 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Autogenerated weights for `pezpallet_core_fellowship`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE BIZINIKIWI BENCHMARK CLI VERSION 32.0.0
|
||||
//! DATE: 2025-02-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `4563561839a5`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
|
||||
//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024`
|
||||
|
||||
// Executed Command:
|
||||
// frame-omni-bencher
|
||||
// v1
|
||||
// benchmark
|
||||
// pallet
|
||||
// --extrinsic=*
|
||||
// --runtime=target/production/wbuild/kitchensink-runtime/kitchensink_runtime.wasm
|
||||
// --pallet=pezpallet_core_fellowship
|
||||
// --header=/__w/pezkuwi-sdk/pezkuwi-sdk/bizinikiwi/HEADER-APACHE2
|
||||
// --output=/__w/pezkuwi-sdk/pezkuwi-sdk/bizinikiwi/pezframe/core-fellowship/src/weights.rs
|
||||
// --wasm-execution=compiled
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --heap-pages=4096
|
||||
// --template=bizinikiwi/.maintain/frame-weight-template.hbs
|
||||
// --no-storage-info
|
||||
// --no-min-squares
|
||||
// --no-median-slopes
|
||||
// --genesis-builder-policy=none
|
||||
// --exclude-pallets=pezpallet_xcm,pezpallet_xcm_benchmarks::fungible,pezpallet_xcm_benchmarks::generic,pezpallet_nomination_pools,pezpallet_remark,pezpallet_transaction_storage,pezpallet_election_provider_multi_block,pezpallet_election_provider_multi_block::signed,pezpallet_election_provider_multi_block::unsigned,pezpallet_election_provider_multi_block::verifier
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use pezframe_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// Weight functions needed for `pezpallet_core_fellowship`.
|
||||
pub trait WeightInfo {
|
||||
fn set_params() -> Weight;
|
||||
fn set_partial_params() -> Weight;
|
||||
fn bump_offboard() -> Weight;
|
||||
fn bump_demote() -> Weight;
|
||||
fn set_active() -> Weight;
|
||||
fn induct() -> Weight;
|
||||
fn promote() -> Weight;
|
||||
fn promote_fast(r: u32, ) -> Weight;
|
||||
fn offboard() -> Weight;
|
||||
fn import() -> Weight;
|
||||
fn import_member() -> Weight;
|
||||
fn approve() -> Weight;
|
||||
fn submit_evidence() -> Weight;
|
||||
}
|
||||
|
||||
/// Weights for `pezpallet_core_fellowship` using the Bizinikiwi node and recommended hardware.
|
||||
pub struct BizinikiwiWeight<T>(PhantomData<T>);
|
||||
impl<T: pezframe_system::Config> WeightInfo for BizinikiwiWeight<T> {
|
||||
/// Storage: `CoreFellowship::Params` (r:0 w:1)
|
||||
/// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`)
|
||||
fn set_params() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 5_918_000 picoseconds.
|
||||
Weight::from_parts(6_267_000, 0)
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Params` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`)
|
||||
fn set_partial_params() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `373`
|
||||
// Estimated: `1853`
|
||||
// Minimum execution time: 9_660_000 picoseconds.
|
||||
Weight::from_parts(10_193_000, 1853)
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Params` (r:1 w:0)
|
||||
/// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::MemberCount` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IdToIndex` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IndexToId` (r:0 w:1)
|
||||
/// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
fn bump_offboard() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `17098`
|
||||
// Estimated: `19894`
|
||||
// Minimum execution time: 56_571_000 picoseconds.
|
||||
Weight::from_parts(66_034_000, 19894)
|
||||
.saturating_add(T::DbWeight::get().reads(6_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(6_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Params` (r:1 w:0)
|
||||
/// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::MemberCount` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IdToIndex` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IndexToId` (r:0 w:1)
|
||||
/// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
fn bump_demote() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `17208`
|
||||
// Estimated: `19894`
|
||||
// Minimum execution time: 58_374_000 picoseconds.
|
||||
Weight::from_parts(60_954_000, 19894)
|
||||
.saturating_add(T::DbWeight::get().reads(6_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(6_u64))
|
||||
}
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:0)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
fn set_active() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `204`
|
||||
// Estimated: `3514`
|
||||
// Minimum execution time: 14_336_000 picoseconds.
|
||||
Weight::from_parts(14_873_000, 3514)
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::MemberCount` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IndexToId` (r:0 w:1)
|
||||
/// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IdToIndex` (r:0 w:1)
|
||||
/// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
fn induct() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `3514`
|
||||
// Minimum execution time: 19_369_000 picoseconds.
|
||||
Weight::from_parts(19_919_000, 3514)
|
||||
.saturating_add(T::DbWeight::get().reads(3_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(5_u64))
|
||||
}
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Params` (r:1 w:0)
|
||||
/// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::MemberCount` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IndexToId` (r:0 w:1)
|
||||
/// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IdToIndex` (r:0 w:1)
|
||||
/// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
fn promote() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `16752`
|
||||
// Estimated: `19894`
|
||||
// Minimum execution time: 51_794_000 picoseconds.
|
||||
Weight::from_parts(52_807_000, 19894)
|
||||
.saturating_add(T::DbWeight::get().reads(5_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(6_u64))
|
||||
}
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::MemberCount` (r:9 w:9)
|
||||
/// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IndexToId` (r:0 w:9)
|
||||
/// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IdToIndex` (r:0 w:9)
|
||||
/// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// The range of component `r` is `[1, 9]`.
|
||||
fn promote_fast(r: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `16665`
|
||||
// Estimated: `19894 + r * (2489 ±0)`
|
||||
// Minimum execution time: 45_726_000 picoseconds.
|
||||
Weight::from_parts(33_520_659, 19894)
|
||||
// Standard Error: 25_104
|
||||
.saturating_add(Weight::from_parts(14_350_763, 0).saturating_mul(r.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(3_u64))
|
||||
.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into())))
|
||||
.saturating_add(T::DbWeight::get().writes(3_u64))
|
||||
.saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(r.into())))
|
||||
.saturating_add(Weight::from_parts(0, 2489).saturating_mul(r.into()))
|
||||
}
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:0)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:0 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
fn offboard() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `109`
|
||||
// Estimated: `3514`
|
||||
// Minimum execution time: 14_819_000 picoseconds.
|
||||
Weight::from_parts(15_310_000, 3514)
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:0)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
fn import() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `151`
|
||||
// Estimated: `3514`
|
||||
// Minimum execution time: 13_302_000 picoseconds.
|
||||
Weight::from_parts(13_671_000, 3514)
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:0)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
fn import_member() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `151`
|
||||
// Estimated: `3514`
|
||||
// Minimum execution time: 13_235_000 picoseconds.
|
||||
Weight::from_parts(13_505_000, 3514)
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:0)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
fn approve() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `16664`
|
||||
// Estimated: `19894`
|
||||
// Minimum execution time: 34_543_000 picoseconds.
|
||||
Weight::from_parts(35_450_000, 19894)
|
||||
.saturating_add(T::DbWeight::get().reads(3_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:0)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
fn submit_evidence() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `53`
|
||||
// Estimated: `19894`
|
||||
// Minimum execution time: 21_572_000 picoseconds.
|
||||
Weight::from_parts(22_081_000, 19894)
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests.
|
||||
impl WeightInfo for () {
|
||||
/// Storage: `CoreFellowship::Params` (r:0 w:1)
|
||||
/// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`)
|
||||
fn set_params() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 5_918_000 picoseconds.
|
||||
Weight::from_parts(6_267_000, 0)
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Params` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`)
|
||||
fn set_partial_params() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `373`
|
||||
// Estimated: `1853`
|
||||
// Minimum execution time: 9_660_000 picoseconds.
|
||||
Weight::from_parts(10_193_000, 1853)
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Params` (r:1 w:0)
|
||||
/// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::MemberCount` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IdToIndex` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IndexToId` (r:0 w:1)
|
||||
/// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
fn bump_offboard() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `17098`
|
||||
// Estimated: `19894`
|
||||
// Minimum execution time: 56_571_000 picoseconds.
|
||||
Weight::from_parts(66_034_000, 19894)
|
||||
.saturating_add(RocksDbWeight::get().reads(6_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Params` (r:1 w:0)
|
||||
/// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::MemberCount` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IdToIndex` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IndexToId` (r:0 w:1)
|
||||
/// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
fn bump_demote() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `17208`
|
||||
// Estimated: `19894`
|
||||
// Minimum execution time: 58_374_000 picoseconds.
|
||||
Weight::from_parts(60_954_000, 19894)
|
||||
.saturating_add(RocksDbWeight::get().reads(6_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
||||
}
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:0)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
fn set_active() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `204`
|
||||
// Estimated: `3514`
|
||||
// Minimum execution time: 14_336_000 picoseconds.
|
||||
Weight::from_parts(14_873_000, 3514)
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::MemberCount` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IndexToId` (r:0 w:1)
|
||||
/// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IdToIndex` (r:0 w:1)
|
||||
/// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
fn induct() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `3514`
|
||||
// Minimum execution time: 19_369_000 picoseconds.
|
||||
Weight::from_parts(19_919_000, 3514)
|
||||
.saturating_add(RocksDbWeight::get().reads(3_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(5_u64))
|
||||
}
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Params` (r:1 w:0)
|
||||
/// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(368), added: 863, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::MemberCount` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IndexToId` (r:0 w:1)
|
||||
/// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IdToIndex` (r:0 w:1)
|
||||
/// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
fn promote() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `16752`
|
||||
// Estimated: `19894`
|
||||
// Minimum execution time: 51_794_000 picoseconds.
|
||||
Weight::from_parts(52_807_000, 19894)
|
||||
.saturating_add(RocksDbWeight::get().reads(5_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
||||
}
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:1)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::MemberCount` (r:9 w:9)
|
||||
/// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IndexToId` (r:0 w:9)
|
||||
/// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::IdToIndex` (r:0 w:9)
|
||||
/// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
|
||||
/// The range of component `r` is `[1, 9]`.
|
||||
fn promote_fast(r: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `16665`
|
||||
// Estimated: `19894 + r * (2489 ±0)`
|
||||
// Minimum execution time: 45_726_000 picoseconds.
|
||||
Weight::from_parts(33_520_659, 19894)
|
||||
// Standard Error: 25_104
|
||||
.saturating_add(Weight::from_parts(14_350_763, 0).saturating_mul(r.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(3_u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into())))
|
||||
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(r.into())))
|
||||
.saturating_add(Weight::from_parts(0, 2489).saturating_mul(r.into()))
|
||||
}
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:0)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:0 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
fn offboard() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `109`
|
||||
// Estimated: `3514`
|
||||
// Minimum execution time: 14_819_000 picoseconds.
|
||||
Weight::from_parts(15_310_000, 3514)
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:0)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
fn import() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `151`
|
||||
// Estimated: `3514`
|
||||
// Minimum execution time: 13_302_000 picoseconds.
|
||||
Weight::from_parts(13_671_000, 3514)
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:0)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
fn import_member() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `151`
|
||||
// Estimated: `3514`
|
||||
// Minimum execution time: 13_235_000 picoseconds.
|
||||
Weight::from_parts(13_505_000, 3514)
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `RankedCollective::Members` (r:1 w:0)
|
||||
/// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
fn approve() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `16664`
|
||||
// Estimated: `19894`
|
||||
// Minimum execution time: 34_543_000 picoseconds.
|
||||
Weight::from_parts(35_450_000, 19894)
|
||||
.saturating_add(RocksDbWeight::get().reads(3_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64))
|
||||
}
|
||||
/// Storage: `CoreFellowship::Member` (r:1 w:0)
|
||||
/// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
|
||||
/// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1)
|
||||
/// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`)
|
||||
fn submit_evidence() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `53`
|
||||
// Estimated: `19894`
|
||||
// Minimum execution time: 21_572_000 picoseconds.
|
||||
Weight::from_parts(22_081_000, 19894)
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user