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,243 @@
|
||||
// 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(feature = "runtime-benchmarks")]
|
||||
|
||||
use super::{Pallet as SafeMode, *};
|
||||
use frame::benchmarking::prelude::*;
|
||||
|
||||
#[benchmarks(where T::Currency: fungible::Mutate<T::AccountId>)]
|
||||
mod benchmarks {
|
||||
use super::*;
|
||||
|
||||
/// `on_initialize` doing nothing.
|
||||
#[benchmark]
|
||||
fn on_initialize_noop() {
|
||||
#[block]
|
||||
{
|
||||
SafeMode::<T>::on_initialize(1u32.into());
|
||||
}
|
||||
}
|
||||
|
||||
/// `on_initialize` exiting since the until block is in the past.
|
||||
#[benchmark]
|
||||
fn on_initialize_exit() {
|
||||
EnteredUntil::<T>::put(&BlockNumberFor::<T>::zero());
|
||||
assert!(SafeMode::<T>::is_entered());
|
||||
|
||||
#[block]
|
||||
{
|
||||
SafeMode::<T>::on_initialize(1u32.into());
|
||||
}
|
||||
|
||||
assert!(!SafeMode::<T>::is_entered());
|
||||
}
|
||||
|
||||
/// Permissionless enter - if configured.
|
||||
#[benchmark]
|
||||
fn enter() -> Result<(), BenchmarkError> {
|
||||
T::EnterDepositAmount::get().ok_or_else(|| BenchmarkError::Weightless)?;
|
||||
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
let origin = RawOrigin::Signed(caller.clone());
|
||||
<T::Currency as fungible::Mutate<_>>::set_balance(&caller, init_bal::<T>());
|
||||
|
||||
#[extrinsic_call]
|
||||
_(origin);
|
||||
|
||||
assert_eq!(
|
||||
EnteredUntil::<T>::get().unwrap(),
|
||||
pezframe_system::Pallet::<T>::block_number() + T::EnterDuration::get()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Forceful enter - if configured.
|
||||
#[benchmark]
|
||||
fn force_enter() -> Result<(), BenchmarkError> {
|
||||
let force_origin =
|
||||
T::ForceEnterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
|
||||
let duration = T::ForceEnterOrigin::ensure_origin(force_origin.clone()).unwrap();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(force_origin as T::RuntimeOrigin);
|
||||
|
||||
assert_eq!(
|
||||
EnteredUntil::<T>::get().unwrap(),
|
||||
pezframe_system::Pallet::<T>::block_number() + duration
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Permissionless extend - if configured.
|
||||
#[benchmark]
|
||||
fn extend() -> Result<(), BenchmarkError> {
|
||||
T::ExtendDepositAmount::get().ok_or_else(|| BenchmarkError::Weightless)?;
|
||||
|
||||
let alice: T::AccountId = whitelisted_caller();
|
||||
<T::Currency as fungible::Mutate<_>>::set_balance(&alice, init_bal::<T>());
|
||||
|
||||
pezframe_system::Pallet::<T>::set_block_number(1u32.into());
|
||||
assert!(SafeMode::<T>::do_enter(None, 1u32.into()).is_ok());
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(alice));
|
||||
|
||||
assert_eq!(
|
||||
EnteredUntil::<T>::get().unwrap(),
|
||||
pezframe_system::Pallet::<T>::block_number() + 1u32.into() + T::ExtendDuration::get()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Forceful extend - if configured.
|
||||
#[benchmark]
|
||||
fn force_extend() -> Result<(), BenchmarkError> {
|
||||
let force_origin = T::ForceExtendOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
|
||||
pezframe_system::Pallet::<T>::set_block_number(1u32.into());
|
||||
assert!(SafeMode::<T>::do_enter(None, 1u32.into()).is_ok());
|
||||
|
||||
let duration = T::ForceExtendOrigin::ensure_origin(force_origin.clone()).unwrap();
|
||||
let call = Call::<T>::force_extend {};
|
||||
|
||||
#[block]
|
||||
{
|
||||
call.dispatch_bypass_filter(force_origin)?;
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
EnteredUntil::<T>::get().unwrap(),
|
||||
pezframe_system::Pallet::<T>::block_number() + 1u32.into() + duration
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Forceful exit - if configured.
|
||||
#[benchmark]
|
||||
fn force_exit() -> Result<(), BenchmarkError> {
|
||||
let force_origin =
|
||||
T::ForceExitOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
assert!(SafeMode::<T>::do_enter(None, 1u32.into()).is_ok());
|
||||
|
||||
#[extrinsic_call]
|
||||
_(force_origin as T::RuntimeOrigin);
|
||||
|
||||
assert_eq!(EnteredUntil::<T>::get(), None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Permissionless release of a deposit - if configured.
|
||||
#[benchmark]
|
||||
fn release_deposit() -> Result<(), BenchmarkError> {
|
||||
let delay = T::ReleaseDelay::get().ok_or_else(|| BenchmarkError::Weightless)?;
|
||||
|
||||
let alice: T::AccountId = whitelisted_caller();
|
||||
let origin = RawOrigin::Signed(alice.clone());
|
||||
|
||||
<T::Currency as fungible::Mutate<_>>::set_balance(&alice, init_bal::<T>());
|
||||
// Mock the storage. This is needed in case the `EnterDepositAmount` is zero.
|
||||
let block: BlockNumberFor<T> = 1u32.into();
|
||||
let bal: BalanceOf<T> = 1u32.into();
|
||||
Deposits::<T>::insert(&alice, &block, &bal);
|
||||
T::Currency::hold(&HoldReason::EnterOrExtend.into(), &alice, bal)?;
|
||||
EnteredUntil::<T>::put(&block);
|
||||
assert!(SafeMode::<T>::do_exit(ExitReason::Force).is_ok());
|
||||
|
||||
pezframe_system::Pallet::<T>::set_block_number(delay + One::one() + 2u32.into());
|
||||
pezframe_system::Pallet::<T>::on_initialize(pezframe_system::Pallet::<T>::block_number());
|
||||
SafeMode::<T>::on_initialize(pezframe_system::Pallet::<T>::block_number());
|
||||
|
||||
#[extrinsic_call]
|
||||
_(origin, alice.clone(), 1u32.into());
|
||||
|
||||
assert!(!Deposits::<T>::contains_key(&alice, &block));
|
||||
assert_eq!(<T::Currency as fungible::Inspect<_>>::balance(&alice), init_bal::<T>());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Forceful release of a deposit - if configured.
|
||||
#[benchmark]
|
||||
fn force_release_deposit() -> Result<(), BenchmarkError> {
|
||||
let force_origin = T::ForceDepositOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
|
||||
let alice: T::AccountId = whitelisted_caller();
|
||||
<T::Currency as fungible::Mutate<_>>::set_balance(&alice, init_bal::<T>());
|
||||
|
||||
// Mock the storage. This is needed in case the `EnterDepositAmount` is zero.
|
||||
let block: BlockNumberFor<T> = 1u32.into();
|
||||
let bal: BalanceOf<T> = 1u32.into();
|
||||
Deposits::<T>::insert(&alice, &block, &bal);
|
||||
T::Currency::hold(&&HoldReason::EnterOrExtend.into(), &alice, bal)?;
|
||||
EnteredUntil::<T>::put(&block);
|
||||
|
||||
assert_eq!(
|
||||
<T::Currency as fungible::Inspect<_>>::balance(&alice),
|
||||
init_bal::<T>() - 1u32.into()
|
||||
);
|
||||
assert!(SafeMode::<T>::do_exit(ExitReason::Force).is_ok());
|
||||
|
||||
pezframe_system::Pallet::<T>::set_block_number(
|
||||
pezframe_system::Pallet::<T>::block_number() + One::one(),
|
||||
);
|
||||
pezframe_system::Pallet::<T>::on_initialize(pezframe_system::Pallet::<T>::block_number());
|
||||
SafeMode::<T>::on_initialize(pezframe_system::Pallet::<T>::block_number());
|
||||
|
||||
#[extrinsic_call]
|
||||
_(force_origin as T::RuntimeOrigin, alice.clone(), block);
|
||||
|
||||
assert!(!Deposits::<T>::contains_key(&alice, block));
|
||||
assert_eq!(<T::Currency as fungible::Inspect<_>>::balance(&alice), init_bal::<T>());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn force_slash_deposit() -> Result<(), BenchmarkError> {
|
||||
let force_origin = T::ForceDepositOrigin::try_successful_origin()
|
||||
.map_err(|_| BenchmarkError::Weightless)?;
|
||||
|
||||
let alice: T::AccountId = whitelisted_caller();
|
||||
<T::Currency as fungible::Mutate<_>>::set_balance(&alice, init_bal::<T>());
|
||||
|
||||
// Mock the storage. This is needed in case the `EnterDepositAmount` is zero.
|
||||
let block: BlockNumberFor<T> = 1u32.into();
|
||||
let bal: BalanceOf<T> = 1u32.into();
|
||||
Deposits::<T>::insert(&alice, &block, &bal);
|
||||
T::Currency::hold(&&HoldReason::EnterOrExtend.into(), &alice, bal)?;
|
||||
EnteredUntil::<T>::put(&block);
|
||||
assert!(SafeMode::<T>::do_exit(ExitReason::Force).is_ok());
|
||||
|
||||
#[extrinsic_call]
|
||||
_(force_origin as T::RuntimeOrigin, alice.clone(), block);
|
||||
|
||||
assert!(!Deposits::<T>::contains_key(&alice, block));
|
||||
assert_eq!(
|
||||
<T::Currency as fungible::Inspect<_>>::balance(&alice),
|
||||
init_bal::<T>() - 1u32.into()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init_bal<T: Config>() -> BalanceOf<T> {
|
||||
BalanceOf::<T>::max_value() / 10u32.into()
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(SafeMode, crate::mock::new_test_ext(), crate::mock::Test);
|
||||
}
|
||||
@@ -0,0 +1,649 @@
|
||||
// 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.
|
||||
|
||||
//! # Safe Mode
|
||||
//!
|
||||
//! Trigger for stopping all extrinsics outside of a specific whitelist.
|
||||
//!
|
||||
//! ## Pallet API
|
||||
//!
|
||||
//! See the [`pallet`] module for more information about the interfaces this pallet exposes,
|
||||
//! including its configuration trait, dispatchables, storage items, events, and errors.
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! Safe mode is entered via two paths (deposit or forced) until a set block number.
|
||||
//! The mode is exited when the block number is reached or a call to one of the exit extrinsics is
|
||||
//! made. A `WhitelistedCalls` configuration item contains all calls that can be executed while in
|
||||
//! safe mode.
|
||||
//!
|
||||
//! ### Primary Features
|
||||
//!
|
||||
//! - Entering safe mode can be via privileged origin or anyone who places a deposit.
|
||||
//! - Origin configuration items are separated for privileged entering and exiting safe mode.
|
||||
//! - A configurable duration sets the number of blocks after which the system will exit safe mode.
|
||||
//! - Safe mode may be extended beyond the configured exit by additional calls.
|
||||
//!
|
||||
//! ### Example
|
||||
//!
|
||||
//! Configuration of call filters:
|
||||
//!
|
||||
//! ```ignore
|
||||
//! impl pezframe_system::Config for Runtime {
|
||||
//! // …
|
||||
//! type BaseCallFilter = InsideBoth<DefaultFilter, SafeMode>;
|
||||
//! // …
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Entering safe mode with deposit:
|
||||
#![doc = docify::embed!("src/tests.rs", can_activate)]
|
||||
//!
|
||||
//! Entering safe mode via privileged origin:
|
||||
#![doc = docify::embed!("src/tests.rs", can_force_activate_with_config_origin)]
|
||||
//!
|
||||
//! Exiting safe mode via privileged origin:
|
||||
#![doc = docify::embed!("src/tests.rs", can_force_deactivate_with_config_origin)]
|
||||
//!
|
||||
//! ## Low Level / Implementation Details
|
||||
//!
|
||||
//! ### Use Cost
|
||||
//!
|
||||
//! A storage value (`EnteredUntil`) is used to store the block safe mode will be exited on.
|
||||
//! Using the call filter will require a db read of that storage on the first extrinsic.
|
||||
//! The storage will be added to the overlay and incur low cost for all additional calls.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
|
||||
mod benchmarking;
|
||||
pub mod mock;
|
||||
mod tests;
|
||||
pub mod weights;
|
||||
|
||||
use frame::{
|
||||
prelude::{
|
||||
fungible::hold::{Inspect, Mutate},
|
||||
*,
|
||||
},
|
||||
traits::{fungible, CallMetadata, GetCallMetadata, SafeModeNotify},
|
||||
};
|
||||
|
||||
pub use pallet::*;
|
||||
pub use weights::*;
|
||||
|
||||
type BalanceOf<T> =
|
||||
<<T as Config>::Currency as fungible::Inspect<<T as pezframe_system::Config>::AccountId>>::Balance;
|
||||
|
||||
#[frame::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(PhantomData<T>);
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: pezframe_system::Config {
|
||||
/// The overarching event type.
|
||||
#[allow(deprecated)]
|
||||
type RuntimeEvent: From<Event<Self>> + IsType<<Self as pezframe_system::Config>::RuntimeEvent>;
|
||||
|
||||
/// Currency type for this pallet, used for Deposits.
|
||||
type Currency: Inspect<Self::AccountId>
|
||||
+ Mutate<Self::AccountId, Reason = Self::RuntimeHoldReason>;
|
||||
|
||||
/// The hold reason when reserving funds for entering or extending the safe-mode.
|
||||
type RuntimeHoldReason: From<HoldReason>;
|
||||
|
||||
/// Contains all runtime calls in any pallet that can be dispatched even while the safe-mode
|
||||
/// is entered.
|
||||
///
|
||||
/// The safe-mode pallet cannot disable it's own calls, and does not need to be explicitly
|
||||
/// added here.
|
||||
type WhitelistedCalls: Contains<Self::RuntimeCall>;
|
||||
|
||||
/// For how many blocks the safe-mode will be entered by [`Pallet::enter`].
|
||||
#[pallet::constant]
|
||||
type EnterDuration: Get<BlockNumberFor<Self>>;
|
||||
|
||||
/// For how many blocks the safe-mode can be extended by each [`Pallet::extend`] call.
|
||||
///
|
||||
/// This does not impose a hard limit as the safe-mode can be extended multiple times.
|
||||
#[pallet::constant]
|
||||
type ExtendDuration: Get<BlockNumberFor<Self>>;
|
||||
|
||||
/// The amount that will be reserved upon calling [`Pallet::enter`].
|
||||
///
|
||||
/// `None` disallows permissionlessly enabling the safe-mode and is a sane default.
|
||||
#[pallet::constant]
|
||||
type EnterDepositAmount: Get<Option<BalanceOf<Self>>>;
|
||||
|
||||
/// The amount that will be reserved upon calling [`Pallet::extend`].
|
||||
///
|
||||
/// `None` disallows permissionlessly extending the safe-mode and is a sane default.
|
||||
#[pallet::constant]
|
||||
type ExtendDepositAmount: Get<Option<BalanceOf<Self>>>;
|
||||
|
||||
/// The origin that may call [`Pallet::force_enter`].
|
||||
///
|
||||
/// The `Success` value is the number of blocks that this origin can enter safe-mode for.
|
||||
type ForceEnterOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = BlockNumberFor<Self>>;
|
||||
|
||||
/// The origin that may call [`Pallet::force_extend`].
|
||||
///
|
||||
/// The `Success` value is the number of blocks that this origin can extend the safe-mode.
|
||||
type ForceExtendOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = BlockNumberFor<Self>>;
|
||||
|
||||
/// The origin that may call [`Pallet::force_enter`].
|
||||
type ForceExitOrigin: EnsureOrigin<Self::RuntimeOrigin>;
|
||||
|
||||
/// The only origin that can force to release or slash a deposit.
|
||||
type ForceDepositOrigin: EnsureOrigin<Self::RuntimeOrigin>;
|
||||
|
||||
/// Notifies external logic when the safe-mode is being entered or exited.
|
||||
type Notify: SafeModeNotify;
|
||||
|
||||
/// The minimal duration a deposit will remain reserved after safe-mode is entered or
|
||||
/// extended, unless [`Pallet::force_release_deposit`] is successfully called sooner.
|
||||
///
|
||||
/// Every deposit is tied to a specific activation or extension, thus each deposit can be
|
||||
/// released independently after the delay for it has passed.
|
||||
///
|
||||
/// `None` disallows permissionlessly releasing the safe-mode deposits and is a sane
|
||||
/// default.
|
||||
#[pallet::constant]
|
||||
type ReleaseDelay: Get<Option<BlockNumberFor<Self>>>;
|
||||
|
||||
// Weight information for extrinsics in this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
/// The safe-mode is (already or still) entered.
|
||||
Entered,
|
||||
|
||||
/// The safe-mode is (already or still) exited.
|
||||
Exited,
|
||||
|
||||
/// This functionality of the pallet is disabled by the configuration.
|
||||
NotConfigured,
|
||||
|
||||
/// There is no balance reserved.
|
||||
NoDeposit,
|
||||
|
||||
/// The account already has a deposit reserved and can therefore not enter or extend again.
|
||||
AlreadyDeposited,
|
||||
|
||||
/// This deposit cannot be released yet.
|
||||
CannotReleaseYet,
|
||||
|
||||
/// An error from the underlying `Currency`.
|
||||
CurrencyError,
|
||||
}
|
||||
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config> {
|
||||
/// The safe-mode was entered until inclusively this block.
|
||||
Entered { until: BlockNumberFor<T> },
|
||||
|
||||
/// The safe-mode was extended until inclusively this block.
|
||||
Extended { until: BlockNumberFor<T> },
|
||||
|
||||
/// Exited the safe-mode for a specific reason.
|
||||
Exited { reason: ExitReason },
|
||||
|
||||
/// An account reserved funds for either entering or extending the safe-mode.
|
||||
DepositPlaced { account: T::AccountId, amount: BalanceOf<T> },
|
||||
|
||||
/// An account had a reserve released that was reserved.
|
||||
DepositReleased { account: T::AccountId, amount: BalanceOf<T> },
|
||||
|
||||
/// An account had reserve slashed that was reserved.
|
||||
DepositSlashed { account: T::AccountId, amount: BalanceOf<T> },
|
||||
|
||||
/// Could not hold funds for entering or extending the safe-mode.
|
||||
///
|
||||
/// This error comes from the underlying `Currency`.
|
||||
CannotDeposit,
|
||||
|
||||
/// Could not release funds for entering or extending the safe-mode.
|
||||
///
|
||||
/// This error comes from the underlying `Currency`.
|
||||
CannotRelease,
|
||||
}
|
||||
|
||||
/// The reason why the safe-mode was deactivated.
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
RuntimeDebug,
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
TypeInfo,
|
||||
MaxEncodedLen,
|
||||
)]
|
||||
pub enum ExitReason {
|
||||
/// The safe-mode was automatically deactivated after it's duration ran out.
|
||||
Timeout,
|
||||
|
||||
/// The safe-mode was forcefully deactivated by [`Pallet::force_exit`].
|
||||
Force,
|
||||
}
|
||||
|
||||
/// Contains the last block number that the safe-mode will remain entered in.
|
||||
///
|
||||
/// Set to `None` when safe-mode is exited.
|
||||
///
|
||||
/// Safe-mode is automatically exited when the current block number exceeds this value.
|
||||
#[pallet::storage]
|
||||
pub type EnteredUntil<T: Config> = StorageValue<_, BlockNumberFor<T>, OptionQuery>;
|
||||
|
||||
/// Holds the reserve that was taken from an account at a specific block number.
|
||||
///
|
||||
/// This helps governance to have an overview of outstanding deposits that should be returned or
|
||||
/// slashed.
|
||||
#[pallet::storage]
|
||||
pub type Deposits<T: Config> = StorageDoubleMap<
|
||||
_,
|
||||
Twox64Concat,
|
||||
T::AccountId,
|
||||
Twox64Concat,
|
||||
BlockNumberFor<T>,
|
||||
BalanceOf<T>,
|
||||
OptionQuery,
|
||||
>;
|
||||
|
||||
/// Configure the initial state of this pallet in the genesis block.
|
||||
#[pallet::genesis_config]
|
||||
#[derive(DefaultNoBound)]
|
||||
pub struct GenesisConfig<T: Config> {
|
||||
pub entered_until: Option<BlockNumberFor<T>>,
|
||||
}
|
||||
|
||||
#[pallet::genesis_build]
|
||||
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
|
||||
fn build(&self) {
|
||||
if let Some(block) = self.entered_until {
|
||||
EnteredUntil::<T>::put(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A reason for the pallet placing a hold on funds.
|
||||
#[pallet::composite_enum]
|
||||
pub enum HoldReason {
|
||||
/// Funds are held for entering or extending the safe-mode.
|
||||
#[codec(index = 0)]
|
||||
EnterOrExtend,
|
||||
}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Enter safe-mode permissionlessly for [`Config::EnterDuration`] blocks.
|
||||
///
|
||||
/// Reserves [`Config::EnterDepositAmount`] from the caller's account.
|
||||
/// Emits an [`Event::Entered`] event on success.
|
||||
/// Errors with [`Error::Entered`] if the safe-mode is already entered.
|
||||
/// Errors with [`Error::NotConfigured`] if the deposit amount is `None`.
|
||||
#[pallet::call_index(0)]
|
||||
#[pallet::weight(T::WeightInfo::enter())]
|
||||
pub fn enter(origin: OriginFor<T>) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
|
||||
Self::do_enter(Some(who), T::EnterDuration::get()).map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Enter safe-mode by force for a per-origin configured number of blocks.
|
||||
///
|
||||
/// Emits an [`Event::Entered`] event on success.
|
||||
/// Errors with [`Error::Entered`] if the safe-mode is already entered.
|
||||
///
|
||||
/// Can only be called by the [`Config::ForceEnterOrigin`] origin.
|
||||
#[pallet::call_index(1)]
|
||||
#[pallet::weight(T::WeightInfo::force_enter())]
|
||||
pub fn force_enter(origin: OriginFor<T>) -> DispatchResult {
|
||||
let duration = T::ForceEnterOrigin::ensure_origin(origin)?;
|
||||
|
||||
Self::do_enter(None, duration).map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Extend the safe-mode permissionlessly for [`Config::ExtendDuration`] blocks.
|
||||
///
|
||||
/// This accumulates on top of the current remaining duration.
|
||||
/// Reserves [`Config::ExtendDepositAmount`] from the caller's account.
|
||||
/// Emits an [`Event::Extended`] event on success.
|
||||
/// Errors with [`Error::Exited`] if the safe-mode is entered.
|
||||
/// Errors with [`Error::NotConfigured`] if the deposit amount is `None`.
|
||||
///
|
||||
/// This may be called by any signed origin with [`Config::ExtendDepositAmount`] free
|
||||
/// currency to reserve. This call can be disabled for all origins by configuring
|
||||
/// [`Config::ExtendDepositAmount`] to `None`.
|
||||
#[pallet::call_index(2)]
|
||||
#[pallet::weight(T::WeightInfo::extend())]
|
||||
pub fn extend(origin: OriginFor<T>) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
|
||||
Self::do_extend(Some(who), T::ExtendDuration::get()).map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Extend the safe-mode by force for a per-origin configured number of blocks.
|
||||
///
|
||||
/// Emits an [`Event::Extended`] event on success.
|
||||
/// Errors with [`Error::Exited`] if the safe-mode is inactive.
|
||||
///
|
||||
/// Can only be called by the [`Config::ForceExtendOrigin`] origin.
|
||||
#[pallet::call_index(3)]
|
||||
#[pallet::weight(T::WeightInfo::force_extend())]
|
||||
pub fn force_extend(origin: OriginFor<T>) -> DispatchResult {
|
||||
let duration = T::ForceExtendOrigin::ensure_origin(origin)?;
|
||||
|
||||
Self::do_extend(None, duration).map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Exit safe-mode by force.
|
||||
///
|
||||
/// Emits an [`Event::Exited`] with [`ExitReason::Force`] event on success.
|
||||
/// Errors with [`Error::Exited`] if the safe-mode is inactive.
|
||||
///
|
||||
/// Note: `safe-mode` will be automatically deactivated by [`Pallet::on_initialize`] hook
|
||||
/// after the block height is greater than the [`EnteredUntil`] storage item.
|
||||
/// Emits an [`Event::Exited`] with [`ExitReason::Timeout`] event when deactivated in the
|
||||
/// hook.
|
||||
#[pallet::call_index(4)]
|
||||
#[pallet::weight(T::WeightInfo::force_exit())]
|
||||
pub fn force_exit(origin: OriginFor<T>) -> DispatchResult {
|
||||
T::ForceExitOrigin::ensure_origin(origin)?;
|
||||
|
||||
Self::do_exit(ExitReason::Force).map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Slash a deposit for an account that entered or extended safe-mode at a given
|
||||
/// historical block.
|
||||
///
|
||||
/// This can only be called while safe-mode is entered.
|
||||
///
|
||||
/// Emits a [`Event::DepositSlashed`] event on success.
|
||||
/// Errors with [`Error::Entered`] if safe-mode is entered.
|
||||
///
|
||||
/// Can only be called by the [`Config::ForceDepositOrigin`] origin.
|
||||
#[pallet::call_index(5)]
|
||||
#[pallet::weight(T::WeightInfo::force_slash_deposit())]
|
||||
pub fn force_slash_deposit(
|
||||
origin: OriginFor<T>,
|
||||
account: T::AccountId,
|
||||
block: BlockNumberFor<T>,
|
||||
) -> DispatchResult {
|
||||
T::ForceDepositOrigin::ensure_origin(origin)?;
|
||||
|
||||
Self::do_force_deposit(account, block).map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Permissionlessly release a deposit for an account that entered safe-mode at a
|
||||
/// given historical block.
|
||||
///
|
||||
/// The call can be completely disabled by setting [`Config::ReleaseDelay`] to `None`.
|
||||
/// This cannot be called while safe-mode is entered and not until
|
||||
/// [`Config::ReleaseDelay`] blocks have passed since safe-mode was entered.
|
||||
///
|
||||
/// Emits a [`Event::DepositReleased`] event on success.
|
||||
/// Errors with [`Error::Entered`] if the safe-mode is entered.
|
||||
/// Errors with [`Error::CannotReleaseYet`] if [`Config::ReleaseDelay`] block have not
|
||||
/// passed since safe-mode was entered. Errors with [`Error::NoDeposit`] if the payee has no
|
||||
/// reserved currency at the block specified.
|
||||
#[pallet::call_index(6)]
|
||||
#[pallet::weight(T::WeightInfo::release_deposit())]
|
||||
pub fn release_deposit(
|
||||
origin: OriginFor<T>,
|
||||
account: T::AccountId,
|
||||
block: BlockNumberFor<T>,
|
||||
) -> DispatchResult {
|
||||
ensure_signed(origin)?;
|
||||
|
||||
Self::do_release(false, account, block).map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Force to release a deposit for an account that entered safe-mode at a given
|
||||
/// historical block.
|
||||
///
|
||||
/// This can be called while safe-mode is still entered.
|
||||
///
|
||||
/// Emits a [`Event::DepositReleased`] event on success.
|
||||
/// Errors with [`Error::Entered`] if safe-mode is entered.
|
||||
/// Errors with [`Error::NoDeposit`] if the payee has no reserved currency at the
|
||||
/// specified block.
|
||||
///
|
||||
/// Can only be called by the [`Config::ForceDepositOrigin`] origin.
|
||||
#[pallet::call_index(7)]
|
||||
#[pallet::weight(T::WeightInfo::force_release_deposit())]
|
||||
pub fn force_release_deposit(
|
||||
origin: OriginFor<T>,
|
||||
account: T::AccountId,
|
||||
block: BlockNumberFor<T>,
|
||||
) -> DispatchResult {
|
||||
T::ForceDepositOrigin::ensure_origin(origin)?;
|
||||
|
||||
Self::do_release(true, account, block).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||
/// Automatically exits safe-mode when the current block number is greater than
|
||||
/// [`EnteredUntil`].
|
||||
fn on_initialize(current: BlockNumberFor<T>) -> Weight {
|
||||
let Some(limit) = EnteredUntil::<T>::get() else {
|
||||
return T::WeightInfo::on_initialize_noop();
|
||||
};
|
||||
|
||||
if current > limit {
|
||||
let _ = Self::do_exit(ExitReason::Timeout).defensive_proof("Only Errors if safe-mode is not entered. Safe-mode has already been checked to be entered; qed");
|
||||
T::WeightInfo::on_initialize_exit()
|
||||
} else {
|
||||
T::WeightInfo::on_initialize_noop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Logic for the [`crate::Pallet::enter`] and [`crate::Pallet::force_enter`] calls.
|
||||
pub(crate) fn do_enter(
|
||||
who: Option<T::AccountId>,
|
||||
duration: BlockNumberFor<T>,
|
||||
) -> Result<(), Error<T>> {
|
||||
ensure!(!Self::is_entered(), Error::<T>::Entered);
|
||||
|
||||
if let Some(who) = who {
|
||||
let amount = T::EnterDepositAmount::get().ok_or(Error::<T>::NotConfigured)?;
|
||||
Self::hold(who, amount)?;
|
||||
}
|
||||
|
||||
let until = <pezframe_system::Pallet<T>>::block_number().saturating_add(duration);
|
||||
EnteredUntil::<T>::put(until);
|
||||
Self::deposit_event(Event::Entered { until });
|
||||
T::Notify::entered();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Logic for the [`crate::Pallet::extend`] and [`crate::Pallet::force_extend`] calls.
|
||||
pub(crate) fn do_extend(
|
||||
who: Option<T::AccountId>,
|
||||
duration: BlockNumberFor<T>,
|
||||
) -> Result<(), Error<T>> {
|
||||
let mut until = EnteredUntil::<T>::get().ok_or(Error::<T>::Exited)?;
|
||||
|
||||
if let Some(who) = who {
|
||||
let amount = T::ExtendDepositAmount::get().ok_or(Error::<T>::NotConfigured)?;
|
||||
Self::hold(who, amount)?;
|
||||
}
|
||||
|
||||
until.saturating_accrue(duration);
|
||||
EnteredUntil::<T>::put(until);
|
||||
Self::deposit_event(Event::<T>::Extended { until });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Logic for the [`crate::Pallet::force_exit`] call.
|
||||
///
|
||||
/// Errors if safe-mode is already exited.
|
||||
pub(crate) fn do_exit(reason: ExitReason) -> Result<(), Error<T>> {
|
||||
let _until = EnteredUntil::<T>::take().ok_or(Error::<T>::Exited)?;
|
||||
Self::deposit_event(Event::Exited { reason });
|
||||
T::Notify::exited();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Logic for the [`crate::Pallet::release_deposit`] and
|
||||
/// [`crate::Pallet::force_release_deposit`] calls.
|
||||
pub(crate) fn do_release(
|
||||
force: bool,
|
||||
account: T::AccountId,
|
||||
block: BlockNumberFor<T>,
|
||||
) -> Result<(), Error<T>> {
|
||||
let amount = Deposits::<T>::take(&account, &block).ok_or(Error::<T>::NoDeposit)?;
|
||||
|
||||
if !force {
|
||||
ensure!(!Self::is_entered(), Error::<T>::Entered);
|
||||
|
||||
let delay = T::ReleaseDelay::get().ok_or(Error::<T>::NotConfigured)?;
|
||||
let now = <pezframe_system::Pallet<T>>::block_number();
|
||||
ensure!(now > block.saturating_add(delay), Error::<T>::CannotReleaseYet);
|
||||
}
|
||||
|
||||
let amount = T::Currency::release(
|
||||
&&HoldReason::EnterOrExtend.into(),
|
||||
&account,
|
||||
amount,
|
||||
Precision::BestEffort,
|
||||
)
|
||||
.map_err(|_| Error::<T>::CurrencyError)?;
|
||||
Self::deposit_event(Event::<T>::DepositReleased { account, amount });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Logic for the [`crate::Pallet::slash_deposit`] call.
|
||||
pub(crate) fn do_force_deposit(
|
||||
account: T::AccountId,
|
||||
block: BlockNumberFor<T>,
|
||||
) -> Result<(), Error<T>> {
|
||||
let amount = Deposits::<T>::take(&account, block).ok_or(Error::<T>::NoDeposit)?;
|
||||
|
||||
let burned = T::Currency::burn_held(
|
||||
&&HoldReason::EnterOrExtend.into(),
|
||||
&account,
|
||||
amount,
|
||||
Precision::BestEffort,
|
||||
Fortitude::Force,
|
||||
)
|
||||
.map_err(|_| Error::<T>::CurrencyError)?;
|
||||
defensive_assert!(burned == amount, "Could not burn the full held amount");
|
||||
Self::deposit_event(Event::<T>::DepositSlashed { account, amount });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Place a hold for exactly `amount` and store it in `Deposits`.
|
||||
///
|
||||
/// Errors if the account already has a hold for the same reason.
|
||||
fn hold(who: T::AccountId, amount: BalanceOf<T>) -> Result<(), Error<T>> {
|
||||
let block = <pezframe_system::Pallet<T>>::block_number();
|
||||
if !T::Currency::balance_on_hold(&HoldReason::EnterOrExtend.into(), &who).is_zero() {
|
||||
return Err(Error::<T>::AlreadyDeposited.into());
|
||||
}
|
||||
|
||||
T::Currency::hold(&HoldReason::EnterOrExtend.into(), &who, amount)
|
||||
.map_err(|_| Error::<T>::CurrencyError)?;
|
||||
Deposits::<T>::insert(&who, block, amount);
|
||||
Self::deposit_event(Event::<T>::DepositPlaced { account: who, amount });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Return whether `safe-mode` is entered.
|
||||
pub fn is_entered() -> bool {
|
||||
EnteredUntil::<T>::exists()
|
||||
}
|
||||
|
||||
/// Return whether the given call is allowed to be dispatched.
|
||||
pub fn is_allowed(call: &T::RuntimeCall) -> bool
|
||||
where
|
||||
T::RuntimeCall: GetCallMetadata,
|
||||
{
|
||||
let CallMetadata { pezpallet_name, .. } = call.get_call_metadata();
|
||||
// SAFETY: The `SafeMode` pallet is always allowed.
|
||||
if pezpallet_name == <Pallet<T> as PalletInfoAccess>::name() {
|
||||
return true;
|
||||
}
|
||||
|
||||
if Self::is_entered() {
|
||||
T::WhitelistedCalls::contains(call)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Contains<T::RuntimeCall> for Pallet<T>
|
||||
where
|
||||
T::RuntimeCall: GetCallMetadata,
|
||||
{
|
||||
/// Return whether the given call is allowed to be dispatched.
|
||||
fn contains(call: &T::RuntimeCall) -> bool {
|
||||
Pallet::<T>::is_allowed(call)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> frame::traits::SafeMode for Pallet<T> {
|
||||
type BlockNumber = BlockNumberFor<T>;
|
||||
|
||||
fn is_entered() -> bool {
|
||||
Self::is_entered()
|
||||
}
|
||||
|
||||
fn remaining() -> Option<BlockNumberFor<T>> {
|
||||
EnteredUntil::<T>::get().map(|until| {
|
||||
let now = <pezframe_system::Pallet<T>>::block_number();
|
||||
until.saturating_sub(now)
|
||||
})
|
||||
}
|
||||
|
||||
fn enter(duration: BlockNumberFor<T>) -> Result<(), frame::traits::SafeModeError> {
|
||||
Self::do_enter(None, duration).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn extend(duration: BlockNumberFor<T>) -> Result<(), frame::traits::SafeModeError> {
|
||||
Self::do_extend(None, duration).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn exit() -> Result<(), frame::traits::SafeModeError> {
|
||||
Self::do_exit(ExitReason::Force).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> From<Error<T>> for frame::traits::SafeModeError {
|
||||
fn from(err: Error<T>) -> Self {
|
||||
match err {
|
||||
Error::<T>::Entered => Self::AlreadyEntered,
|
||||
Error::<T>::Exited => Self::AlreadyExited,
|
||||
_ => Self::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
// 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.
|
||||
|
||||
//! Tests and test utilities for safe mode pallet.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use super::*;
|
||||
use crate as pezpallet_safe_mode;
|
||||
|
||||
use frame::{
|
||||
testing_prelude::*,
|
||||
traits::{InsideBoth, InstanceFilter, IsInVec},
|
||||
};
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for Test {
|
||||
type BaseCallFilter = InsideBoth<Everything, SafeMode>;
|
||||
type BlockWeights = ();
|
||||
type BlockLength = ();
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type Nonce = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type AccountId = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Block = Block;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type DbWeight = ();
|
||||
type Version = ();
|
||||
type PalletInfo = PalletInfo;
|
||||
type AccountData = pezpallet_balances::AccountData<u64>;
|
||||
type OnNewAccount = ();
|
||||
type OnKilledAccount = ();
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = ConstU32<16>;
|
||||
}
|
||||
|
||||
/// Identifies a hold on an account's balance.
|
||||
#[derive(
|
||||
Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, MaxEncodedLen, Debug, TypeInfo,
|
||||
)]
|
||||
pub enum HoldReason {
|
||||
/// The safe-mode pallet holds funds since an account either entered or extended the safe-mode.
|
||||
SafeMode,
|
||||
}
|
||||
|
||||
#[derive_impl(pezpallet_balances::config_preludes::TestDefaultConfig)]
|
||||
impl pezpallet_balances::Config for Test {
|
||||
type ExistentialDeposit = ConstU64<2>;
|
||||
type AccountStore = System;
|
||||
}
|
||||
|
||||
impl pezpallet_utility::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type PalletsOrigin = OriginCaller;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
/// Mocked proxies to check that the safe-mode also works with the proxy pallet.
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Ord,
|
||||
PartialOrd,
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
RuntimeDebug,
|
||||
MaxEncodedLen,
|
||||
scale_info::TypeInfo,
|
||||
)]
|
||||
pub enum ProxyType {
|
||||
Any,
|
||||
JustTransfer,
|
||||
JustUtility,
|
||||
}
|
||||
|
||||
impl Default for ProxyType {
|
||||
fn default() -> Self {
|
||||
Self::Any
|
||||
}
|
||||
}
|
||||
|
||||
impl InstanceFilter<RuntimeCall> for ProxyType {
|
||||
fn filter(&self, c: &RuntimeCall) -> bool {
|
||||
match self {
|
||||
ProxyType::Any => true,
|
||||
ProxyType::JustTransfer => {
|
||||
matches!(
|
||||
c,
|
||||
RuntimeCall::Balances(pezpallet_balances::Call::transfer_allow_death { .. })
|
||||
)
|
||||
},
|
||||
ProxyType::JustUtility => matches!(c, RuntimeCall::Utility { .. }),
|
||||
}
|
||||
}
|
||||
fn is_superset(&self, o: &Self) -> bool {
|
||||
self == &ProxyType::Any || self == o
|
||||
}
|
||||
}
|
||||
|
||||
impl pezpallet_proxy::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type Currency = Balances;
|
||||
type ProxyType = ProxyType;
|
||||
type ProxyDepositBase = ConstU64<1>;
|
||||
type ProxyDepositFactor = ConstU64<1>;
|
||||
type MaxProxies = ConstU32<4>;
|
||||
type WeightInfo = ();
|
||||
type CallHasher = BlakeTwo256;
|
||||
type MaxPending = ConstU32<2>;
|
||||
type AnnouncementDepositBase = ConstU64<1>;
|
||||
type AnnouncementDepositFactor = ConstU64<1>;
|
||||
type BlockNumberProvider = pezframe_system::Pallet<Test>;
|
||||
}
|
||||
|
||||
/// The calls that can always bypass safe-mode.
|
||||
pub struct WhitelistedCalls;
|
||||
impl Contains<RuntimeCall> for WhitelistedCalls {
|
||||
fn contains(call: &RuntimeCall) -> bool {
|
||||
match call {
|
||||
RuntimeCall::Balances(_) => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const EnterDuration: u64 = 7;
|
||||
pub const ExtendDuration: u64 = 10;
|
||||
pub const EnterDepositAmount: u64 = 100;
|
||||
pub const ExtendDepositAmount: u64 = 100;
|
||||
pub const ReleaseDelay: u64 = 20;
|
||||
pub const SafeModeHoldReason: HoldReason = HoldReason::SafeMode;
|
||||
|
||||
pub const ForceEnterWeak: u64 = 3;
|
||||
pub const ForceEnterStrong: u64 = 5;
|
||||
|
||||
pub const ForceExtendWeak: u64 = 11;
|
||||
pub const ForceExtendStrong: u64 = 15;
|
||||
|
||||
// NOTE: The account ID maps to the duration. Easy for testing.
|
||||
pub ForceEnterOrigins: Vec<u64> = vec![ForceEnterWeak::get(), ForceEnterStrong::get()];
|
||||
pub ForceExtendOrigins: Vec<u64> = vec![ForceExtendWeak::get(), ForceExtendStrong::get()];
|
||||
|
||||
pub storage Notifications: Vec<(u64, bool)> = vec![];
|
||||
}
|
||||
|
||||
pub struct MockedNotify;
|
||||
impl SafeModeNotify for MockedNotify {
|
||||
fn entered() {
|
||||
let mut ns = Notifications::get();
|
||||
ns.push((<pezframe_system::Pallet<Test>>::block_number(), true));
|
||||
Notifications::set(&ns);
|
||||
}
|
||||
|
||||
fn exited() {
|
||||
let mut ns = Notifications::get();
|
||||
ns.push((<pezframe_system::Pallet<Test>>::block_number(), false));
|
||||
Notifications::set(&ns);
|
||||
}
|
||||
}
|
||||
|
||||
ord_parameter_types! {
|
||||
pub const ForceExitOrigin: u64 = 100;
|
||||
pub const ForceDepositOrigin: u64 = 200;
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Currency = Balances;
|
||||
type RuntimeHoldReason = RuntimeHoldReason;
|
||||
type WhitelistedCalls = WhitelistedCalls;
|
||||
type EnterDuration = EnterDuration;
|
||||
type EnterDepositAmount = EnterDepositAmount;
|
||||
type ExtendDuration = ExtendDuration;
|
||||
type ExtendDepositAmount = ExtendDepositAmount;
|
||||
type ForceEnterOrigin = EnsureSignedBy<IsInVec<ForceEnterOrigins>, u64>;
|
||||
type ForceExtendOrigin = EnsureSignedBy<IsInVec<ForceExtendOrigins>, u64>;
|
||||
type ForceExitOrigin = EnsureSignedBy<ForceExitOrigin, Self::AccountId>;
|
||||
type ForceDepositOrigin = EnsureSignedBy<ForceDepositOrigin, Self::AccountId>;
|
||||
type ReleaseDelay = ReleaseDelay;
|
||||
type Notify = MockedNotify;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
type Block = pezframe_system::mocking::MockBlock<Test>;
|
||||
|
||||
construct_runtime!(
|
||||
pub enum Test
|
||||
{
|
||||
System: pezframe_system,
|
||||
Balances: pezpallet_balances,
|
||||
Utility: pezpallet_utility,
|
||||
Proxy: pezpallet_proxy,
|
||||
SafeMode: pezpallet_safe_mode,
|
||||
}
|
||||
);
|
||||
|
||||
pub const BAL_ACC0: u64 = 1234;
|
||||
pub const BAL_ACC1: u64 = 5678;
|
||||
|
||||
pub fn new_test_ext() -> TestExternalities {
|
||||
let mut t = pezframe_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
|
||||
pezpallet_balances::GenesisConfig::<Test> {
|
||||
// The 0 account is NOT a special origin, the rest may be.
|
||||
balances: vec![(0, BAL_ACC0), (1, BAL_ACC1), (2, 5678), (3, 5678), (4, 5678)],
|
||||
..Default::default()
|
||||
}
|
||||
.assimilate_storage(&mut t)
|
||||
.unwrap();
|
||||
pezpallet_safe_mode::GenesisConfig::<Test> { entered_until: None }
|
||||
.assimilate_storage(&mut t)
|
||||
.unwrap();
|
||||
|
||||
let mut ext = TestExternalities::new(t);
|
||||
ext.execute_with(|| {
|
||||
System::set_block_number(1);
|
||||
});
|
||||
ext
|
||||
}
|
||||
|
||||
pub fn next_block() {
|
||||
SafeMode::on_finalize(System::block_number());
|
||||
Balances::on_finalize(System::block_number());
|
||||
System::on_finalize(System::block_number());
|
||||
System::set_block_number(System::block_number() + 1);
|
||||
System::on_initialize(System::block_number());
|
||||
Balances::on_initialize(System::block_number());
|
||||
SafeMode::on_initialize(System::block_number());
|
||||
}
|
||||
|
||||
pub fn run_to(n: u64) {
|
||||
while System::block_number() < n {
|
||||
next_block();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,591 @@
|
||||
// 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.
|
||||
|
||||
//! Test utilities for the safe mode pallet.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use super::*;
|
||||
use crate::mock::{RuntimeCall, *};
|
||||
|
||||
use frame::{testing_prelude::*, traits::Currency};
|
||||
|
||||
#[test]
|
||||
fn fails_to_filter_calls_to_safe_mode_pallet() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
let activated_at_block = System::block_number();
|
||||
|
||||
assert_err!(
|
||||
call_transfer().dispatch(RuntimeOrigin::signed(0)),
|
||||
pezframe_system::Error::<Test>::CallFiltered
|
||||
);
|
||||
|
||||
next_block();
|
||||
assert_ok!(SafeMode::extend(RuntimeOrigin::signed(1)));
|
||||
assert_ok!(SafeMode::force_extend(signed(ForceExtendStrong::get())));
|
||||
assert_err!(
|
||||
call_transfer().dispatch(RuntimeOrigin::signed(0)),
|
||||
pezframe_system::Error::<Test>::CallFiltered
|
||||
);
|
||||
assert_ok!(SafeMode::force_exit(RuntimeOrigin::signed(mock::ForceExitOrigin::get())));
|
||||
assert_ok!(SafeMode::force_release_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
activated_at_block
|
||||
));
|
||||
|
||||
next_block();
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
assert_err!(
|
||||
call_transfer().dispatch(RuntimeOrigin::signed(0)),
|
||||
pezframe_system::Error::<Test>::CallFiltered
|
||||
);
|
||||
assert_ok!(SafeMode::force_exit(RuntimeOrigin::signed(mock::ForceExitOrigin::get())));
|
||||
assert_ok!(SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
activated_at_block + 2
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fails_to_activate_if_activated() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
assert_noop!(SafeMode::enter(RuntimeOrigin::signed(2)), Error::<Test>::Entered);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fails_to_extend_if_not_activated() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(EnteredUntil::<Test>::get(), None);
|
||||
assert_noop!(SafeMode::extend(RuntimeOrigin::signed(2)), Error::<Test>::Exited);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fails_to_force_release_deposits_with_wrong_block() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let activated_at_block = System::block_number();
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
run_to(mock::EnterDuration::get() + activated_at_block + 1);
|
||||
|
||||
assert_err!(
|
||||
SafeMode::force_release_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
activated_at_block + 1
|
||||
),
|
||||
Error::<Test>::NoDeposit
|
||||
);
|
||||
|
||||
assert_err!(
|
||||
SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
activated_at_block + 1
|
||||
),
|
||||
Error::<Test>::NoDeposit
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fails_to_release_deposits_too_early() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let activated_at_block = System::block_number();
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
assert_ok!(SafeMode::force_exit(RuntimeOrigin::signed(mock::ForceExitOrigin::get())));
|
||||
assert_err!(
|
||||
SafeMode::release_deposit(RuntimeOrigin::signed(2), 0, activated_at_block),
|
||||
Error::<Test>::CannotReleaseYet
|
||||
);
|
||||
run_to(activated_at_block + mock::ReleaseDelay::get() + 1);
|
||||
assert_ok!(SafeMode::release_deposit(RuntimeOrigin::signed(2), 0, activated_at_block));
|
||||
});
|
||||
}
|
||||
|
||||
// GENERAL SUCCESS/POSITIVE TESTS ---------------------
|
||||
|
||||
#[test]
|
||||
fn can_automatically_deactivate_after_timeout() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let activated_at_block = System::block_number();
|
||||
assert_ok!(SafeMode::force_enter(signed(ForceEnterWeak::get())));
|
||||
run_to(1 + activated_at_block + ForceEnterWeak::get());
|
||||
|
||||
assert_eq!(EnteredUntil::<Test>::get(), None);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_filter_balance_calls_when_activated() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(call_transfer().dispatch(RuntimeOrigin::signed(0)));
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
assert_err!(
|
||||
call_transfer().dispatch(RuntimeOrigin::signed(0)),
|
||||
pezframe_system::Error::<Test>::CallFiltered
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_filter_balance_in_batch_when_activated() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let batch_call =
|
||||
RuntimeCall::Utility(pezpallet_utility::Call::batch { calls: vec![call_transfer()] });
|
||||
|
||||
assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0)));
|
||||
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
|
||||
assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0)));
|
||||
System::assert_last_event(
|
||||
pezpallet_utility::Event::BatchInterrupted {
|
||||
index: 0,
|
||||
error: pezframe_system::Error::<Test>::CallFiltered.into(),
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_filter_balance_in_proxy_when_activated() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::JustTransfer, 0));
|
||||
|
||||
assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, Box::new(call_transfer())));
|
||||
System::assert_last_event(pezpallet_proxy::Event::ProxyExecuted { result: Ok(()) }.into());
|
||||
|
||||
assert_ok!(SafeMode::force_enter(signed(ForceEnterWeak::get())));
|
||||
|
||||
assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, Box::new(call_transfer())));
|
||||
System::assert_last_event(
|
||||
pezpallet_proxy::Event::ProxyExecuted {
|
||||
result: DispatchError::from(pezframe_system::Error::<Test>::CallFiltered).into(),
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[docify::export]
|
||||
#[test]
|
||||
fn can_activate() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
assert_eq!(
|
||||
EnteredUntil::<Test>::get().unwrap(),
|
||||
System::block_number() + mock::EnterDuration::get()
|
||||
);
|
||||
assert_eq!(Balances::reserved_balance(0), mock::EnterDepositAmount::get());
|
||||
assert_eq!(Notifications::get(), vec![(1, true)]);
|
||||
assert_noop!(SafeMode::enter(RuntimeOrigin::signed(0)), Error::<Test>::Entered);
|
||||
assert_eq!(Notifications::get(), vec![(1, true)]);
|
||||
// Assert the deposit.
|
||||
assert_eq!(Deposits::<Test>::get(0, 1), Some(mock::EnterDepositAmount::get()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn notify_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
assert_eq!(Notifications::get(), vec![(1, true)]);
|
||||
run_to(10);
|
||||
assert_eq!(Notifications::get(), vec![(1, true), (9, false)]);
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(1)));
|
||||
assert_ok!(SafeMode::extend(RuntimeOrigin::signed(2)));
|
||||
run_to(30);
|
||||
assert_eq!(Notifications::get(), vec![(1, true), (9, false), (10, true), (28, false)]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cannot_extend() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
assert_err!(SafeMode::extend(RuntimeOrigin::signed(0)), Error::<Test>::AlreadyDeposited);
|
||||
assert_eq!(
|
||||
EnteredUntil::<Test>::get().unwrap(),
|
||||
System::block_number() + mock::EnterDuration::get()
|
||||
);
|
||||
assert_eq!(Balances::reserved_balance(0), mock::EnterDepositAmount::get());
|
||||
assert_eq!(Notifications::get(), vec![(1, true)]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fails_signed_origin_when_explicit_origin_required() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(EnteredUntil::<Test>::get(), None);
|
||||
let activated_at_block = System::block_number();
|
||||
|
||||
assert_err!(SafeMode::force_enter(RuntimeOrigin::signed(0)), DispatchError::BadOrigin);
|
||||
assert_err!(SafeMode::force_extend(RuntimeOrigin::signed(0)), DispatchError::BadOrigin);
|
||||
assert_err!(SafeMode::force_exit(RuntimeOrigin::signed(0)), DispatchError::BadOrigin);
|
||||
assert_err!(
|
||||
SafeMode::force_slash_deposit(RuntimeOrigin::signed(0), 0, activated_at_block),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_err!(
|
||||
SafeMode::force_release_deposit(RuntimeOrigin::signed(0), 0, activated_at_block),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// CONFIGURED ORIGIN CALL TESTS ---------------------
|
||||
|
||||
#[test]
|
||||
fn fails_force_deactivate_if_not_activated() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_noop!(
|
||||
SafeMode::force_exit(RuntimeOrigin::signed(mock::ForceExitOrigin::get())),
|
||||
Error::<Test>::Exited
|
||||
);
|
||||
assert_noop!(
|
||||
SafeMode::force_exit(RuntimeOrigin::signed(mock::ForceExitOrigin::get())),
|
||||
Error::<Test>::Exited
|
||||
);
|
||||
assert!(Notifications::get().is_empty());
|
||||
});
|
||||
}
|
||||
|
||||
#[docify::export]
|
||||
#[test]
|
||||
fn can_force_activate_with_config_origin() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(SafeMode::force_enter(signed(ForceEnterStrong::get())));
|
||||
assert_eq!(Notifications::get(), vec![(1, true)]);
|
||||
assert_eq!(
|
||||
EnteredUntil::<Test>::get().unwrap(),
|
||||
System::block_number() + ForceEnterStrong::get()
|
||||
);
|
||||
assert_noop!(
|
||||
SafeMode::force_enter(signed(ForceEnterStrong::get())),
|
||||
Error::<Test>::Entered
|
||||
);
|
||||
assert_eq!(Notifications::get(), vec![(1, true)]);
|
||||
});
|
||||
}
|
||||
|
||||
#[docify::export]
|
||||
#[test]
|
||||
fn can_force_deactivate_with_config_origin() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(EnteredUntil::<Test>::get(), None);
|
||||
assert_err!(
|
||||
SafeMode::force_exit(RuntimeOrigin::signed(ForceExitOrigin::get())),
|
||||
Error::<Test>::Exited
|
||||
);
|
||||
assert_ok!(SafeMode::force_enter(signed(ForceEnterWeak::get())));
|
||||
assert_ok!(SafeMode::force_exit(RuntimeOrigin::signed(ForceExitOrigin::get())));
|
||||
assert_eq!(Notifications::get(), vec![(1, true), (1, false)]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_force_extend_with_config_origin() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Activated by `Weak` and extended by `Medium`.
|
||||
assert_ok!(SafeMode::force_enter(signed(ForceEnterWeak::get())));
|
||||
assert_eq!(
|
||||
EnteredUntil::<Test>::get().unwrap(),
|
||||
System::block_number() + ForceEnterWeak::get()
|
||||
);
|
||||
assert_ok!(SafeMode::force_extend(signed(ForceExtendWeak::get())));
|
||||
assert_eq!(
|
||||
EnteredUntil::<Test>::get().unwrap(),
|
||||
System::block_number() + ForceEnterWeak::get() + ForceExtendWeak::get()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_force_release_deposit_with_config_origin() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let activated_at_block = System::block_number();
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
hypothetically_ok!(SafeMode::force_release_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
activated_at_block
|
||||
),);
|
||||
run_to(mock::EnterDuration::get() + activated_at_block + 1);
|
||||
|
||||
assert_ok!(SafeMode::force_release_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
activated_at_block
|
||||
));
|
||||
assert_eq!(Balances::free_balance(&0), BAL_ACC0); // accounts set in mock genesis
|
||||
|
||||
Balances::make_free_balance_be(&0, BAL_ACC0);
|
||||
let activated_and_extended_at_block = System::block_number();
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
assert_ok!(SafeMode::extend(RuntimeOrigin::signed(1)));
|
||||
run_to(
|
||||
mock::EnterDuration::get() +
|
||||
mock::ExtendDuration::get() +
|
||||
activated_and_extended_at_block +
|
||||
1,
|
||||
);
|
||||
|
||||
assert_ok!(SafeMode::force_release_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
activated_and_extended_at_block
|
||||
));
|
||||
assert_eq!(Balances::free_balance(&0), BAL_ACC0); // accounts set in mock genesis
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_release_deposit_while_entered() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
assert!(SafeMode::is_entered());
|
||||
|
||||
assert_eq!(Balances::free_balance(&0), BAL_ACC0 - mock::EnterDepositAmount::get());
|
||||
|
||||
// We could slash in the same block or any later.
|
||||
for i in 0..mock::EnterDuration::get() + 10 {
|
||||
run_to(i);
|
||||
hypothetically_ok!(SafeMode::force_release_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
1
|
||||
));
|
||||
}
|
||||
// Now once we slash once
|
||||
assert_ok!(SafeMode::force_release_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
1
|
||||
),);
|
||||
assert_eq!(Balances::free_balance(&0), BAL_ACC0);
|
||||
// ... it wont work ever again.
|
||||
assert_err!(
|
||||
SafeMode::force_release_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
1
|
||||
),
|
||||
Error::<Test>::NoDeposit
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_slash_deposit_while_entered() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
assert!(SafeMode::is_entered());
|
||||
|
||||
// We could slash in the same block or any later.
|
||||
for i in 0..mock::EnterDuration::get() + 10 {
|
||||
run_to(i);
|
||||
hypothetically_ok!(SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
1
|
||||
));
|
||||
}
|
||||
// Now once we slash once
|
||||
assert_ok!(SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
1
|
||||
),);
|
||||
// ... it wont work ever again.
|
||||
assert_err!(
|
||||
SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
1
|
||||
),
|
||||
Error::<Test>::NoDeposit
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_slash_deposit_from_extend_block() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
assert_ok!(SafeMode::extend(RuntimeOrigin::signed(1)));
|
||||
assert_eq!(Balances::free_balance(&0), BAL_ACC0 - mock::EnterDepositAmount::get());
|
||||
assert_eq!(Balances::free_balance(&1), BAL_ACC1 - mock::ExtendDepositAmount::get());
|
||||
|
||||
assert_ok!(SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
1
|
||||
),);
|
||||
assert_eq!(Balances::free_balance(&0), BAL_ACC0 - mock::EnterDepositAmount::get());
|
||||
|
||||
assert_ok!(SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
1,
|
||||
1
|
||||
),);
|
||||
assert_eq!(Balances::free_balance(&1), BAL_ACC1 - mock::ExtendDepositAmount::get());
|
||||
|
||||
// But never again.
|
||||
assert_err!(
|
||||
SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
1
|
||||
),
|
||||
Error::<Test>::NoDeposit
|
||||
);
|
||||
assert_err!(
|
||||
SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
1,
|
||||
1
|
||||
),
|
||||
Error::<Test>::NoDeposit
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_slash_deposit_with_config_origin() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let activated_at_block = System::block_number();
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
hypothetically_ok!(SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
activated_at_block
|
||||
),);
|
||||
run_to(mock::EnterDuration::get() + activated_at_block + 1);
|
||||
|
||||
assert_ok!(SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
activated_at_block
|
||||
));
|
||||
// accounts set in mock genesis
|
||||
assert_eq!(Balances::free_balance(&0), BAL_ACC0 - mock::EnterDepositAmount::get());
|
||||
|
||||
Balances::make_free_balance_be(&0, BAL_ACC0);
|
||||
let activated_and_extended_at_block = System::block_number();
|
||||
assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0)));
|
||||
assert_ok!(SafeMode::extend(RuntimeOrigin::signed(1)));
|
||||
run_to(
|
||||
mock::EnterDuration::get() +
|
||||
mock::ExtendDuration::get() +
|
||||
activated_and_extended_at_block +
|
||||
1,
|
||||
);
|
||||
|
||||
assert_ok!(SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceDepositOrigin::get()),
|
||||
0,
|
||||
activated_and_extended_at_block
|
||||
));
|
||||
// accounts set in mock genesis
|
||||
assert_eq!(Balances::free_balance(&0), BAL_ACC0 - mock::EnterDepositAmount::get());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fails_when_explicit_origin_required() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(EnteredUntil::<Test>::get(), None);
|
||||
let activated_at_block = System::block_number();
|
||||
|
||||
assert_err!(SafeMode::force_extend(signed(1)), DispatchError::BadOrigin);
|
||||
assert_err!(SafeMode::force_exit(signed(1)), DispatchError::BadOrigin);
|
||||
assert_err!(
|
||||
SafeMode::force_slash_deposit(signed(1), 0, activated_at_block),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_err!(
|
||||
SafeMode::force_release_deposit(signed(1), 0, activated_at_block),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
|
||||
assert_err!(SafeMode::force_enter(signed(1)), DispatchError::BadOrigin);
|
||||
assert_err!(SafeMode::force_exit(signed(1)), DispatchError::BadOrigin);
|
||||
assert_err!(
|
||||
SafeMode::force_slash_deposit(signed(1), 0, activated_at_block),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_err!(
|
||||
SafeMode::force_release_deposit(signed(1), 0, activated_at_block),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
|
||||
assert_err!(
|
||||
SafeMode::force_enter(RuntimeOrigin::signed(mock::ForceExitOrigin::get())),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_err!(
|
||||
SafeMode::force_extend(RuntimeOrigin::signed(mock::ForceExitOrigin::get())),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_err!(
|
||||
SafeMode::force_slash_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceExitOrigin::get()),
|
||||
0,
|
||||
activated_at_block
|
||||
),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_err!(
|
||||
SafeMode::force_release_deposit(
|
||||
RuntimeOrigin::signed(mock::ForceExitOrigin::get()),
|
||||
0,
|
||||
activated_at_block
|
||||
),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
|
||||
assert_err!(
|
||||
SafeMode::force_enter(RuntimeOrigin::signed(mock::ForceDepositOrigin::get())),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_err!(
|
||||
SafeMode::force_extend(RuntimeOrigin::signed(mock::ForceDepositOrigin::get())),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_err!(
|
||||
SafeMode::force_exit(RuntimeOrigin::signed(mock::ForceDepositOrigin::get())),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn call_transfer() -> RuntimeCall {
|
||||
RuntimeCall::Balances(pezpallet_balances::Call::transfer_allow_death { dest: 1, value: 1 })
|
||||
}
|
||||
|
||||
fn signed(who: u64) -> RuntimeOrigin {
|
||||
RuntimeOrigin::signed(who)
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
// 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_safe_mode`
|
||||
//!
|
||||
//! 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_safe_mode
|
||||
// --header=/__w/pezkuwi-sdk/pezkuwi-sdk/bizinikiwi/HEADER-APACHE2
|
||||
// --output=/__w/pezkuwi-sdk/pezkuwi-sdk/bizinikiwi/pezframe/safe-mode/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 frame::weights_prelude::*;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// Weight functions needed for `pezpallet_safe_mode`.
|
||||
pub trait WeightInfo {
|
||||
fn on_initialize_noop() -> Weight;
|
||||
fn on_initialize_exit() -> Weight;
|
||||
fn enter() -> Weight;
|
||||
fn force_enter() -> Weight;
|
||||
fn extend() -> Weight;
|
||||
fn force_extend() -> Weight;
|
||||
fn force_exit() -> Weight;
|
||||
fn release_deposit() -> Weight;
|
||||
fn force_release_deposit() -> Weight;
|
||||
fn force_slash_deposit() -> Weight;
|
||||
}
|
||||
|
||||
/// Weights for `pezpallet_safe_mode` using the Bizinikiwi node and recommended hardware.
|
||||
pub struct BizinikiwiWeight<T>(PhantomData<T>);
|
||||
impl<T: pezframe_system::Config> WeightInfo for BizinikiwiWeight<T> {
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:0)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn on_initialize_noop() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `1489`
|
||||
// Minimum execution time: 684_000 picoseconds.
|
||||
Weight::from_parts(733_000, 1489)
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:1)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn on_initialize_exit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `8`
|
||||
// Estimated: `1489`
|
||||
// Minimum execution time: 4_624_000 picoseconds.
|
||||
Weight::from_parts(4_926_000, 1489)
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:1)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::Holds` (r:1 w:1)
|
||||
/// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `MaxEncodedLen`)
|
||||
/// Storage: `SafeMode::Deposits` (r:0 w:1)
|
||||
/// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
|
||||
fn enter() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `3892`
|
||||
// Minimum execution time: 43_918_000 picoseconds.
|
||||
Weight::from_parts(44_471_000, 3892)
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:1)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn force_enter() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `1489`
|
||||
// Minimum execution time: 5_020_000 picoseconds.
|
||||
Weight::from_parts(5_200_000, 1489)
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:1)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::Holds` (r:1 w:1)
|
||||
/// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `MaxEncodedLen`)
|
||||
/// Storage: `SafeMode::Deposits` (r:0 w:1)
|
||||
/// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
|
||||
fn extend() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `8`
|
||||
// Estimated: `3892`
|
||||
// Minimum execution time: 44_860_000 picoseconds.
|
||||
Weight::from_parts(46_411_000, 3892)
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:1)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn force_extend() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `8`
|
||||
// Estimated: `1489`
|
||||
// Minimum execution time: 6_777_000 picoseconds.
|
||||
Weight::from_parts(7_011_000, 1489)
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:1)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn force_exit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `8`
|
||||
// Estimated: `1489`
|
||||
// Minimum execution time: 5_960_000 picoseconds.
|
||||
Weight::from_parts(6_180_000, 1489)
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::Deposits` (r:1 w:1)
|
||||
/// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:0)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::Holds` (r:1 w:1)
|
||||
/// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `MaxEncodedLen`)
|
||||
fn release_deposit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `129`
|
||||
// Estimated: `3892`
|
||||
// Minimum execution time: 36_814_000 picoseconds.
|
||||
Weight::from_parts(37_735_000, 3892)
|
||||
.saturating_add(T::DbWeight::get().reads(3_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::Deposits` (r:1 w:1)
|
||||
/// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::Holds` (r:1 w:1)
|
||||
/// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `MaxEncodedLen`)
|
||||
fn force_release_deposit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `129`
|
||||
// Estimated: `3892`
|
||||
// Minimum execution time: 35_691_000 picoseconds.
|
||||
Weight::from_parts(36_454_000, 3892)
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::Deposits` (r:1 w:1)
|
||||
/// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::Holds` (r:1 w:1)
|
||||
/// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `MaxEncodedLen`)
|
||||
fn force_slash_deposit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `129`
|
||||
// Estimated: `3892`
|
||||
// Minimum execution time: 28_256_000 picoseconds.
|
||||
Weight::from_parts(28_905_000, 3892)
|
||||
.saturating_add(T::DbWeight::get().reads(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests.
|
||||
impl WeightInfo for () {
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:0)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn on_initialize_noop() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `1489`
|
||||
// Minimum execution time: 684_000 picoseconds.
|
||||
Weight::from_parts(733_000, 1489)
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:1)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn on_initialize_exit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `8`
|
||||
// Estimated: `1489`
|
||||
// Minimum execution time: 4_624_000 picoseconds.
|
||||
Weight::from_parts(4_926_000, 1489)
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:1)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::Holds` (r:1 w:1)
|
||||
/// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `MaxEncodedLen`)
|
||||
/// Storage: `SafeMode::Deposits` (r:0 w:1)
|
||||
/// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
|
||||
fn enter() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `3892`
|
||||
// Minimum execution time: 43_918_000 picoseconds.
|
||||
Weight::from_parts(44_471_000, 3892)
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:1)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn force_enter() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `1489`
|
||||
// Minimum execution time: 5_020_000 picoseconds.
|
||||
Weight::from_parts(5_200_000, 1489)
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:1)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::Holds` (r:1 w:1)
|
||||
/// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `MaxEncodedLen`)
|
||||
/// Storage: `SafeMode::Deposits` (r:0 w:1)
|
||||
/// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
|
||||
fn extend() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `8`
|
||||
// Estimated: `3892`
|
||||
// Minimum execution time: 44_860_000 picoseconds.
|
||||
Weight::from_parts(46_411_000, 3892)
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:1)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn force_extend() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `8`
|
||||
// Estimated: `1489`
|
||||
// Minimum execution time: 6_777_000 picoseconds.
|
||||
Weight::from_parts(7_011_000, 1489)
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:1)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
fn force_exit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `8`
|
||||
// Estimated: `1489`
|
||||
// Minimum execution time: 5_960_000 picoseconds.
|
||||
Weight::from_parts(6_180_000, 1489)
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::Deposits` (r:1 w:1)
|
||||
/// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
|
||||
/// Storage: `SafeMode::EnteredUntil` (r:1 w:0)
|
||||
/// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::Holds` (r:1 w:1)
|
||||
/// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `MaxEncodedLen`)
|
||||
fn release_deposit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `129`
|
||||
// Estimated: `3892`
|
||||
// Minimum execution time: 36_814_000 picoseconds.
|
||||
Weight::from_parts(37_735_000, 3892)
|
||||
.saturating_add(RocksDbWeight::get().reads(3_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::Deposits` (r:1 w:1)
|
||||
/// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::Holds` (r:1 w:1)
|
||||
/// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `MaxEncodedLen`)
|
||||
fn force_release_deposit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `129`
|
||||
// Estimated: `3892`
|
||||
// Minimum execution time: 35_691_000 picoseconds.
|
||||
Weight::from_parts(36_454_000, 3892)
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64))
|
||||
}
|
||||
/// Storage: `SafeMode::Deposits` (r:1 w:1)
|
||||
/// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::Holds` (r:1 w:1)
|
||||
/// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(427), added: 2902, mode: `MaxEncodedLen`)
|
||||
fn force_slash_deposit() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `129`
|
||||
// Estimated: `3892`
|
||||
// Minimum execution time: 28_256_000 picoseconds.
|
||||
Weight::from_parts(28_905_000, 3892)
|
||||
.saturating_add(RocksDbWeight::get().reads(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user