Files
pezkuwi-subxt/substrate/frame/safe-mode/src/tests.rs
T
Oliver Tale-Yazdi 3710edfedc [FRAME Core] New pallets: safe-mode and tx-pause (#12092)
* Add safe-mode

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Update pallet

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add to kitchensink-runtime

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Spelling

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Rename to tx-pause

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add SafeMode pallet

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* fmt

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Automatically disable safe-mode in on_init…

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add permissionless enable+extend

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add repay+slash stake methods

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add docs

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix stakes storage

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Genesis config for safe-mode pallet

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Genesis config for safe-mode pallet

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Rename ExtrinsicName to FunctionName

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Origin variable duration

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Rename FunctionName -> CallName

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Rename and docs

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Pallet safe mode tests (#12148)

* Add safe-mode mock runtime
* Add safe-mode tests
* Add ForceEnable- and ForceExtendOrigin
* Start dummy benchmarks
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Tests for `pallet-tx-pause` (#12259)

* mock added
* tests added
* dummy benchmarks started

* rename to active/inactive
tests broken, in progress

* Runtime types, fix tests

* WIP safe mode and tx pause {continued} (#12371)

* test coverage on safe mode and tx pause
* benchmarks & tests
* tests passing, use FullNameOf to check tx-pause unfilterables
* naming updates

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Set block number

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* dummy weights generated, safe mode

* add repay_reservation call with RepaymentDelay per #10033 feature requirements

* make call name optional to allow pausing pallets, handle `Contains` correctly for this throughout, doc comments started

* move to full_name notation for all interfaces, last commit introduced 1 more storage read.

* refactor is_paused

* safe math on safe mode

* Make stuff compile

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Compile

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Cleanup & renames

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Cleanup TxPause pallet

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix benches

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* fmt

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Refactor to fungibles::* and rename stuf

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Make compile

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix node config

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Typos

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Remove CausalHoldReason

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Refactor benchmarks and runtime configs

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add traits

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Remove old code

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Cleanup safe-mode benches

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Update frame/safe-mode/Cargo.toml

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/safe-mode/Cargo.toml

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Docs

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Remove getters

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Update Cargo.lock

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Remove phantom

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix test

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Remove phantom

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Apply suggestions from code review

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Use new as Origin benchmarking syntax

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Docs

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix node

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix tx-pause benches

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Renames

* Remove duplicate test

* Add docs

* docs

* Apply suggestions from code review

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com>
Co-authored-by: Gonçalo Pestana <g6pestana@gmail.com>

* Cleanup tests

* docs

* Cleanup GenesisConfigs

* Doc traits

* Remove PauseTooLongNames

* docs

* Use V2 benchmarking

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Use RuntimeHoldReason

* Fix kitchensink runtime

* Fix CI

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix CI

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Review

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Rename Stake to Deposit

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add docs

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add Notify and test it

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix kitchensink

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Update frame/safe-mode/src/tests.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/safe-mode/src/tests.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/tx_pause.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/tx-pause/src/lib.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/tx-pause/src/lib.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/tx-pause/src/mock.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Simplify code

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Fixup merge

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Make stuff compile

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Make tx-pause compile again

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix features

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix more features

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=dev --target_dir=substrate --pallet=pallet_safe_mode

* Update weights

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

---------

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Dan Shields <35669742+NukeManDan@users.noreply.github.com>
Co-authored-by: Dan Shields <nukemandan@protonmail.com>
Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com>
Co-authored-by: Gonçalo Pestana <g6pestana@gmail.com>
Co-authored-by: command-bot <>
2023-08-25 00:56:00 +00:00

614 lines
18 KiB
Rust

// This file is part of Substrate.
// 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_support::{assert_err, assert_noop, assert_ok, dispatch::Dispatchable, traits::Currency};
use sp_runtime::TransactionOutcome;
/// Do something hypothetically by rolling back any changes afterwards.
///
/// Returns the original result of the closure.
macro_rules! hypothetically {
( $e:expr ) => {
frame_support::storage::transactional::with_transaction(
|| -> TransactionOutcome<Result<_, sp_runtime::DispatchError>> {
sp_runtime::TransactionOutcome::Rollback(Ok($e))
},
)
.expect("Always returning Ok; qed")
};
}
/// Assert something to be [*hypothetically*] `Ok` without actually committing it.
///
/// Reverts any storage changes made by the closure.
macro_rules! hypothetically_ok {
($e:expr $(, $args:expr)* $(,)?) => {
let result = hypothetically!($e);
assert_ok!(result $(, $args)*);
};
}
#[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)),
frame_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)),
frame_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)),
frame_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)),
frame_system::Error::<Test>::CallFiltered
);
});
}
#[test]
fn can_filter_balance_in_batch_when_activated() {
new_test_ext().execute_with(|| {
let batch_call =
RuntimeCall::Utility(pallet_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(
pallet_utility::Event::BatchInterrupted {
index: 0,
error: frame_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(pallet_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(
pallet_proxy::Event::ProxyExecuted {
result: DispatchError::from(frame_system::Error::<Test>::CallFiltered).into(),
}
.into(),
);
});
}
#[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());
});
}
#[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)]);
});
}
#[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(pallet_balances::Call::transfer { dest: 1, value: 1 })
}
fn signed(who: u64) -> RuntimeOrigin {
RuntimeOrigin::signed(who)
}