mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-29 09:07:57 +00:00
Allow pallet error enum variants to contain fields (#10242)
* Allow pallet errors to contain at most one field * Update docs on pallet::error * Reword documentation * cargo fmt * Introduce CompactPalletError trait and require #[pallet::error] fields to implement them * cargo fmt * Do not assume tuple variants * Add CompactPalletError derive macro * Check for error type compactness in construct_runtime * cargo fmt * Derive CompactPalletError instead of implementing it directly during macro expansion * Implement CompactPalletError on OptionBool instead of Option<bool> * Check for type idents instead of variant ident * Add doc comments for ErrorCompactnessTest * Add an trait implementation of ErrorCompactnessTest for () * Convert the error field of DispatchError to a 4-element byte array * Add static check for pallet error size * Rename to MAX_PALLET_ERROR_ENCODED_SIZE * Remove ErrorCompactnessTest trait * Remove check_compactness * Return only the most significant byte when constructing a custom InvalidTransaction * Rename CompactPalletError to PalletError * Use counter to generate unique idents for assert macros * Make declarative pallet macros compile with pallet error size checks * Remove unused doc comment * Try and fix build errors * Fix build errors * Add macro_use for some test modules * Test fix * Fix compilation errors * Remove unneeded #[macro_use] * Resolve import ambiguity * Make path to pallet Error enum more specific * Fix test expectation * Disambiguate imports * Fix test expectations * Revert appending pallet module name to path * Rename bags_list::list::Error to BagError * Fixes * Fixes * Fixes * Fix test expectations * Fix test expectation * Add more implementations for PalletError * Lift the 1-field requirement for nested pallet errors * Fix UI test expectation * Remove PalletError impl for OptionBool * Use saturating operations * cargo fmt * Delete obsolete test * Fix test expectation * Try and use assert macro in const context * Pull out the pallet error size check macro * Fix UI test for const assertion * cargo fmt * Apply clippy suggestion * Fix doc comment * Docs for create_tt_return_macro * Ensure TryInto is imported in earlier Rust editions * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Fix up comments and names * Implement PalletError for Never * cargo fmt * Don't compile example code * Bump API version for block builder * Factor in codec attributes while derving PalletError * Rename module and fix unit test * Add missing attribute * Check API version and convert ApplyExtrinsicResult accordingly * Rename BagError to ListError Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Use codec crate re-exported from frame support * Add links to types mentioned in doc comments Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * cargo fmt * cargo fmt * Re-add attribute for hidden docs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
This commit is contained in:
@@ -271,139 +271,95 @@ pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<u32, Call, Signature, ()>;
|
||||
|
||||
mod origin_test {
|
||||
use super::{module3, nested, system, Block, UncheckedExtrinsic};
|
||||
use frame_support::traits::{Contains, OriginTrait};
|
||||
|
||||
impl nested::module3::Config for RuntimeOriginTest {}
|
||||
impl module3::Config for RuntimeOriginTest {}
|
||||
|
||||
pub struct BaseCallFilter;
|
||||
impl Contains<Call> for BaseCallFilter {
|
||||
fn contains(c: &Call) -> bool {
|
||||
match c {
|
||||
Call::NestedModule3(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl system::Config for RuntimeOriginTest {
|
||||
type BaseCallFilter = BaseCallFilter;
|
||||
type Hash = super::H256;
|
||||
type Origin = Origin;
|
||||
type BlockNumber = super::BlockNumber;
|
||||
type AccountId = u32;
|
||||
type Event = Event;
|
||||
type PalletInfo = PalletInfo;
|
||||
type Call = Call;
|
||||
type DbWeight = ();
|
||||
}
|
||||
|
||||
frame_support::construct_runtime!(
|
||||
pub enum RuntimeOriginTest where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: system::{Pallet, Event<T>, Origin<T>},
|
||||
NestedModule3: nested::module3::{Pallet, Origin, Call},
|
||||
Module3: module3::{Pallet, Origin<T>, Call},
|
||||
}
|
||||
);
|
||||
|
||||
#[test]
|
||||
fn origin_default_filter() {
|
||||
let accepted_call = nested::module3::Call::fail {}.into();
|
||||
let rejected_call = module3::Call::fail {}.into();
|
||||
|
||||
assert_eq!(Origin::root().filter_call(&accepted_call), true);
|
||||
assert_eq!(Origin::root().filter_call(&rejected_call), true);
|
||||
assert_eq!(Origin::none().filter_call(&accepted_call), true);
|
||||
assert_eq!(Origin::none().filter_call(&rejected_call), false);
|
||||
assert_eq!(Origin::signed(0).filter_call(&accepted_call), true);
|
||||
assert_eq!(Origin::signed(0).filter_call(&rejected_call), false);
|
||||
assert_eq!(Origin::from(Some(0)).filter_call(&accepted_call), true);
|
||||
assert_eq!(Origin::from(Some(0)).filter_call(&rejected_call), false);
|
||||
assert_eq!(Origin::from(None).filter_call(&accepted_call), true);
|
||||
assert_eq!(Origin::from(None).filter_call(&rejected_call), false);
|
||||
assert_eq!(Origin::from(super::nested::module3::Origin).filter_call(&accepted_call), true);
|
||||
assert_eq!(Origin::from(super::nested::module3::Origin).filter_call(&rejected_call), false);
|
||||
|
||||
let mut origin = Origin::from(Some(0));
|
||||
origin.add_filter(|c| matches!(c, Call::Module3(_)));
|
||||
assert_eq!(origin.filter_call(&accepted_call), false);
|
||||
assert_eq!(origin.filter_call(&rejected_call), false);
|
||||
|
||||
// Now test for root origin and filters:
|
||||
let mut origin = Origin::from(Some(0));
|
||||
origin.set_caller_from(Origin::root());
|
||||
assert!(matches!(origin.caller, OriginCaller::system(super::system::RawOrigin::Root)));
|
||||
|
||||
// Root origin bypass all filter.
|
||||
assert_eq!(origin.filter_call(&accepted_call), true);
|
||||
assert_eq!(origin.filter_call(&rejected_call), true);
|
||||
|
||||
origin.set_caller_from(Origin::from(Some(0)));
|
||||
|
||||
// Back to another signed origin, the filtered are now effective again
|
||||
assert_eq!(origin.filter_call(&accepted_call), true);
|
||||
assert_eq!(origin.filter_call(&rejected_call), false);
|
||||
|
||||
origin.set_caller_from(Origin::root());
|
||||
origin.reset_filter();
|
||||
|
||||
// Root origin bypass all filter, even when they are reset.
|
||||
assert_eq!(origin.filter_call(&accepted_call), true);
|
||||
assert_eq!(origin.filter_call(&rejected_call), true);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_modules_error_type() {
|
||||
assert_eq!(
|
||||
Module1_1::fail(system::Origin::<Runtime>::Root.into()),
|
||||
Err(DispatchError::Module(ModuleError { index: 31, error: 0, message: Some("Something") })),
|
||||
Err(DispatchError::Module(ModuleError {
|
||||
index: 31,
|
||||
error: [0; 4],
|
||||
message: Some("Something")
|
||||
})),
|
||||
);
|
||||
assert_eq!(
|
||||
Module2::fail(system::Origin::<Runtime>::Root.into()),
|
||||
Err(DispatchError::Module(ModuleError { index: 32, error: 0, message: Some("Something") })),
|
||||
Err(DispatchError::Module(ModuleError {
|
||||
index: 32,
|
||||
error: [0; 4],
|
||||
message: Some("Something")
|
||||
})),
|
||||
);
|
||||
assert_eq!(
|
||||
Module1_2::fail(system::Origin::<Runtime>::Root.into()),
|
||||
Err(DispatchError::Module(ModuleError { index: 33, error: 0, message: Some("Something") })),
|
||||
Err(DispatchError::Module(ModuleError {
|
||||
index: 33,
|
||||
error: [0; 4],
|
||||
message: Some("Something")
|
||||
})),
|
||||
);
|
||||
assert_eq!(
|
||||
NestedModule3::fail(system::Origin::<Runtime>::Root.into()),
|
||||
Err(DispatchError::Module(ModuleError { index: 34, error: 0, message: Some("Something") })),
|
||||
Err(DispatchError::Module(ModuleError {
|
||||
index: 34,
|
||||
error: [0; 4],
|
||||
message: Some("Something")
|
||||
})),
|
||||
);
|
||||
assert_eq!(
|
||||
Module1_3::fail(system::Origin::<Runtime>::Root.into()),
|
||||
Err(DispatchError::Module(ModuleError { index: 6, error: 0, message: Some("Something") })),
|
||||
Err(DispatchError::Module(ModuleError {
|
||||
index: 6,
|
||||
error: [0; 4],
|
||||
message: Some("Something")
|
||||
})),
|
||||
);
|
||||
assert_eq!(
|
||||
Module1_4::fail(system::Origin::<Runtime>::Root.into()),
|
||||
Err(DispatchError::Module(ModuleError { index: 3, error: 0, message: Some("Something") })),
|
||||
Err(DispatchError::Module(ModuleError {
|
||||
index: 3,
|
||||
error: [0; 4],
|
||||
message: Some("Something")
|
||||
})),
|
||||
);
|
||||
assert_eq!(
|
||||
Module1_5::fail(system::Origin::<Runtime>::Root.into()),
|
||||
Err(DispatchError::Module(ModuleError { index: 4, error: 0, message: Some("Something") })),
|
||||
Err(DispatchError::Module(ModuleError {
|
||||
index: 4,
|
||||
error: [0; 4],
|
||||
message: Some("Something")
|
||||
})),
|
||||
);
|
||||
assert_eq!(
|
||||
Module1_6::fail(system::Origin::<Runtime>::Root.into()),
|
||||
Err(DispatchError::Module(ModuleError { index: 1, error: 0, message: Some("Something") })),
|
||||
Err(DispatchError::Module(ModuleError {
|
||||
index: 1,
|
||||
error: [0; 4],
|
||||
message: Some("Something")
|
||||
})),
|
||||
);
|
||||
assert_eq!(
|
||||
Module1_7::fail(system::Origin::<Runtime>::Root.into()),
|
||||
Err(DispatchError::Module(ModuleError { index: 2, error: 0, message: Some("Something") })),
|
||||
Err(DispatchError::Module(ModuleError {
|
||||
index: 2,
|
||||
error: [0; 4],
|
||||
message: Some("Something")
|
||||
})),
|
||||
);
|
||||
assert_eq!(
|
||||
Module1_8::fail(system::Origin::<Runtime>::Root.into()),
|
||||
Err(DispatchError::Module(ModuleError { index: 12, error: 0, message: Some("Something") })),
|
||||
Err(DispatchError::Module(ModuleError {
|
||||
index: 12,
|
||||
error: [0; 4],
|
||||
message: Some("Something")
|
||||
})),
|
||||
);
|
||||
assert_eq!(
|
||||
Module1_9::fail(system::Origin::<Runtime>::Root.into()),
|
||||
Err(DispatchError::Module(ModuleError { index: 13, error: 0, message: Some("Something") })),
|
||||
Err(DispatchError::Module(ModuleError {
|
||||
index: 13,
|
||||
error: [0; 4],
|
||||
message: Some("Something")
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
use frame_support::construct_runtime;
|
||||
use sp_runtime::{generic, traits::BlakeTwo256};
|
||||
use sp_core::sr25519;
|
||||
|
||||
#[frame_support::pallet]
|
||||
mod pallet {
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config {}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(core::marker::PhantomData<T>);
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
MyError(crate::Nested1),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(scale_info::TypeInfo, frame_support::PalletError, codec::Encode, codec::Decode)]
|
||||
pub enum Nested1 {
|
||||
Nested2(Nested2)
|
||||
}
|
||||
|
||||
#[derive(scale_info::TypeInfo, frame_support::PalletError, codec::Encode, codec::Decode)]
|
||||
pub enum Nested2 {
|
||||
Nested3(Nested3)
|
||||
}
|
||||
|
||||
#[derive(scale_info::TypeInfo, frame_support::PalletError, codec::Encode, codec::Decode)]
|
||||
pub enum Nested3 {
|
||||
Nested4(Nested4)
|
||||
}
|
||||
|
||||
#[derive(scale_info::TypeInfo, frame_support::PalletError, codec::Encode, codec::Decode)]
|
||||
pub enum Nested4 {
|
||||
Num(u8)
|
||||
}
|
||||
|
||||
pub type Signature = sr25519::Signature;
|
||||
pub type BlockNumber = u32;
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<u32, Call, Signature, ()>;
|
||||
|
||||
impl pallet::Config for Runtime {}
|
||||
|
||||
impl frame_system::Config for Runtime {
|
||||
type BaseCallFilter = frame_support::traits::Everything;
|
||||
type Origin = Origin;
|
||||
type Index = u64;
|
||||
type BlockNumber = u32;
|
||||
type Call = Call;
|
||||
type Hash = sp_runtime::testing::H256;
|
||||
type Hashing = sp_runtime::traits::BlakeTwo256;
|
||||
type AccountId = u64;
|
||||
type Lookup = sp_runtime::traits::IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = Event;
|
||||
type BlockHashCount = frame_support::traits::ConstU32<250>;
|
||||
type BlockWeights = ();
|
||||
type BlockLength = ();
|
||||
type DbWeight = ();
|
||||
type Version = ();
|
||||
type PalletInfo = PalletInfo;
|
||||
type AccountData = ();
|
||||
type OnNewAccount = ();
|
||||
type OnKilledAccount = ();
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
construct_runtime! {
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: frame_system::{Pallet, Call, Storage, Config, Event<T>},
|
||||
Pallet: pallet::{Pallet},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,13 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> tests/construct_runtime_ui/pallet_error_too_large.rs:74:1
|
||||
|
|
||||
74 | / construct_runtime! {
|
||||
75 | | pub enum Runtime where
|
||||
76 | | Block = Block,
|
||||
77 | | NodeBlock = Block,
|
||||
... |
|
||||
82 | | }
|
||||
83 | | }
|
||||
| |_^ the evaluated program panicked at 'The maximum encoded size of the error type in the `Pallet` pallet exceeds `MAX_MODULE_ERROR_ENCODED_SIZE`', $DIR/tests/construct_runtime_ui/pallet_error_too_large.rs:74:1
|
||||
|
|
||||
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
@@ -0,0 +1,214 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2021 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.
|
||||
|
||||
//! Origin tests for construct_runtime macro
|
||||
|
||||
#![recursion_limit = "128"]
|
||||
|
||||
use frame_support::traits::{Contains, OriginTrait};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_core::{sr25519, H256};
|
||||
use sp_runtime::{generic, traits::BlakeTwo256};
|
||||
|
||||
mod system;
|
||||
|
||||
mod nested {
|
||||
use super::*;
|
||||
|
||||
pub mod module {
|
||||
use super::*;
|
||||
|
||||
pub trait Config: system::Config {}
|
||||
|
||||
frame_support::decl_module! {
|
||||
pub struct Module<T: Config> for enum Call
|
||||
where origin: <T as system::Config>::Origin, system=system
|
||||
{
|
||||
#[weight = 0]
|
||||
pub fn fail(_origin) -> frame_support::dispatch::DispatchResult {
|
||||
Err(Error::<T>::Something.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, codec::Encode, codec::Decode, TypeInfo)]
|
||||
pub struct Origin;
|
||||
|
||||
frame_support::decl_event! {
|
||||
pub enum Event {
|
||||
A,
|
||||
}
|
||||
}
|
||||
|
||||
frame_support::decl_error! {
|
||||
pub enum Error for Module<T: Config> {
|
||||
Something
|
||||
}
|
||||
}
|
||||
|
||||
frame_support::decl_storage! {
|
||||
trait Store for Module<T: Config> as Module {}
|
||||
add_extra_genesis {
|
||||
build(|_config| {})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod module {
|
||||
use super::*;
|
||||
|
||||
pub trait Config: system::Config {}
|
||||
|
||||
frame_support::decl_module! {
|
||||
pub struct Module<T: Config> for enum Call
|
||||
where origin: <T as system::Config>::Origin, system=system
|
||||
{
|
||||
#[weight = 0]
|
||||
pub fn fail(_origin) -> frame_support::dispatch::DispatchResult {
|
||||
Err(Error::<T>::Something.into())
|
||||
}
|
||||
#[weight = 0]
|
||||
pub fn aux_1(_origin, #[compact] _data: u32) -> frame_support::dispatch::DispatchResult {
|
||||
unreachable!()
|
||||
}
|
||||
#[weight = 0]
|
||||
pub fn aux_2(_origin, _data: i32, #[compact] _data2: u32) -> frame_support::dispatch::DispatchResult {
|
||||
unreachable!()
|
||||
}
|
||||
#[weight = 0]
|
||||
fn aux_3(_origin, _data: i32, _data2: String) -> frame_support::dispatch::DispatchResult {
|
||||
unreachable!()
|
||||
}
|
||||
#[weight = 3]
|
||||
fn aux_4(_origin) -> frame_support::dispatch::DispatchResult { unreachable!() }
|
||||
#[weight = (5, frame_support::weights::DispatchClass::Operational)]
|
||||
fn operational(_origin) { unreachable!() }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, codec::Encode, codec::Decode, TypeInfo)]
|
||||
pub struct Origin<T>(pub core::marker::PhantomData<T>);
|
||||
|
||||
frame_support::decl_event! {
|
||||
pub enum Event {
|
||||
A,
|
||||
}
|
||||
}
|
||||
|
||||
frame_support::decl_error! {
|
||||
pub enum Error for Module<T: Config> {
|
||||
Something
|
||||
}
|
||||
}
|
||||
|
||||
frame_support::decl_storage! {
|
||||
trait Store for Module<T: Config> as Module {}
|
||||
add_extra_genesis {
|
||||
build(|_config| {})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl nested::module::Config for RuntimeOriginTest {}
|
||||
impl module::Config for RuntimeOriginTest {}
|
||||
|
||||
pub struct BaseCallFilter;
|
||||
impl Contains<Call> for BaseCallFilter {
|
||||
fn contains(c: &Call) -> bool {
|
||||
match c {
|
||||
Call::NestedModule(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl system::Config for RuntimeOriginTest {
|
||||
type BaseCallFilter = BaseCallFilter;
|
||||
type Hash = H256;
|
||||
type Origin = Origin;
|
||||
type BlockNumber = BlockNumber;
|
||||
type AccountId = u32;
|
||||
type Event = Event;
|
||||
type PalletInfo = PalletInfo;
|
||||
type Call = Call;
|
||||
type DbWeight = ();
|
||||
}
|
||||
|
||||
frame_support::construct_runtime!(
|
||||
pub enum RuntimeOriginTest where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: system::{Pallet, Event<T>, Origin<T>},
|
||||
NestedModule: nested::module::{Pallet, Origin, Call},
|
||||
Module: module::{Pallet, Origin<T>, Call},
|
||||
}
|
||||
);
|
||||
|
||||
pub type Signature = sr25519::Signature;
|
||||
pub type BlockNumber = u64;
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<u32, Call, Signature, ()>;
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
|
||||
#[test]
|
||||
fn origin_default_filter() {
|
||||
let accepted_call = nested::module::Call::fail {}.into();
|
||||
let rejected_call = module::Call::fail {}.into();
|
||||
|
||||
assert_eq!(Origin::root().filter_call(&accepted_call), true);
|
||||
assert_eq!(Origin::root().filter_call(&rejected_call), true);
|
||||
assert_eq!(Origin::none().filter_call(&accepted_call), true);
|
||||
assert_eq!(Origin::none().filter_call(&rejected_call), false);
|
||||
assert_eq!(Origin::signed(0).filter_call(&accepted_call), true);
|
||||
assert_eq!(Origin::signed(0).filter_call(&rejected_call), false);
|
||||
assert_eq!(Origin::from(Some(0)).filter_call(&accepted_call), true);
|
||||
assert_eq!(Origin::from(Some(0)).filter_call(&rejected_call), false);
|
||||
assert_eq!(Origin::from(None).filter_call(&accepted_call), true);
|
||||
assert_eq!(Origin::from(None).filter_call(&rejected_call), false);
|
||||
assert_eq!(Origin::from(nested::module::Origin).filter_call(&accepted_call), true);
|
||||
assert_eq!(Origin::from(nested::module::Origin).filter_call(&rejected_call), false);
|
||||
|
||||
let mut origin = Origin::from(Some(0));
|
||||
origin.add_filter(|c| matches!(c, Call::Module(_)));
|
||||
assert_eq!(origin.filter_call(&accepted_call), false);
|
||||
assert_eq!(origin.filter_call(&rejected_call), false);
|
||||
|
||||
// Now test for root origin and filters:
|
||||
let mut origin = Origin::from(Some(0));
|
||||
origin.set_caller_from(Origin::root());
|
||||
assert!(matches!(origin.caller, OriginCaller::system(system::RawOrigin::Root)));
|
||||
|
||||
// Root origin bypass all filter.
|
||||
assert_eq!(origin.filter_call(&accepted_call), true);
|
||||
assert_eq!(origin.filter_call(&rejected_call), true);
|
||||
|
||||
origin.set_caller_from(Origin::from(Some(0)));
|
||||
|
||||
// Back to another signed origin, the filtered are now effective again
|
||||
assert_eq!(origin.filter_call(&accepted_call), true);
|
||||
assert_eq!(origin.filter_call(&rejected_call), false);
|
||||
|
||||
origin.set_caller_from(Origin::root());
|
||||
origin.reset_filter();
|
||||
|
||||
// Root origin bypass all filter, even when they are reset.
|
||||
assert_eq!(origin.filter_call(&accepted_call), true);
|
||||
assert_eq!(origin.filter_call(&rejected_call), true);
|
||||
}
|
||||
@@ -20,7 +20,7 @@ use frame_support::{
|
||||
storage::unhashed,
|
||||
traits::{
|
||||
ConstU32, GetCallName, GetStorageVersion, OnFinalize, OnGenesis, OnInitialize,
|
||||
OnRuntimeUpgrade, PalletInfoAccess, StorageVersion,
|
||||
OnRuntimeUpgrade, PalletError, PalletInfoAccess, StorageVersion,
|
||||
},
|
||||
weights::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays, RuntimeDbWeight},
|
||||
};
|
||||
@@ -229,9 +229,14 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum Error<T> {
|
||||
/// doc comment put into metadata
|
||||
InsufficientProposersBalance,
|
||||
Code(u8),
|
||||
#[codec(skip)]
|
||||
Skipped(u128),
|
||||
CompactU8(#[codec(compact)] u8),
|
||||
}
|
||||
|
||||
#[pallet::event]
|
||||
@@ -656,10 +661,11 @@ fn error_expand() {
|
||||
DispatchError::from(pallet::Error::<Runtime>::InsufficientProposersBalance),
|
||||
DispatchError::Module(ModuleError {
|
||||
index: 1,
|
||||
error: 0,
|
||||
error: [0, 0, 0, 0],
|
||||
message: Some("InsufficientProposersBalance")
|
||||
}),
|
||||
);
|
||||
assert_eq!(<pallet::Error::<Runtime> as PalletError>::MAX_ENCODED_SIZE, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -343,7 +343,7 @@ fn error_expand() {
|
||||
DispatchError::from(pallet::Error::<Runtime>::InsufficientProposersBalance),
|
||||
DispatchError::Module(ModuleError {
|
||||
index: 1,
|
||||
error: 0,
|
||||
error: [0; 4],
|
||||
message: Some("InsufficientProposersBalance")
|
||||
}),
|
||||
);
|
||||
@@ -364,7 +364,7 @@ fn error_expand() {
|
||||
),
|
||||
DispatchError::Module(ModuleError {
|
||||
index: 2,
|
||||
error: 0,
|
||||
error: [0; 4],
|
||||
message: Some("InsufficientProposersBalance")
|
||||
}),
|
||||
);
|
||||
|
||||
+4
-10
@@ -1,25 +1,19 @@
|
||||
#[frame_support::pallet]
|
||||
mod pallet {
|
||||
use frame_support::pallet_prelude::Hooks;
|
||||
use frame_system::pallet_prelude::BlockNumberFor;
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config {}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(core::marker::PhantomData<T>);
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {}
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
U8(u8),
|
||||
CustomError(crate::MyError),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(scale_info::TypeInfo, codec::Encode, codec::Decode)]
|
||||
enum MyError {}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
error[E0277]: the trait bound `MyError: PalletError` is not satisfied
|
||||
--> tests/pallet_ui/error_does_not_derive_pallet_error.rs:1:1
|
||||
|
|
||||
1 | #[frame_support::pallet]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `PalletError` is not implemented for `MyError`
|
||||
|
|
||||
note: required by `MAX_ENCODED_SIZE`
|
||||
--> $WORKSPACE/frame/support/src/traits/error.rs
|
||||
|
|
||||
| const MAX_ENCODED_SIZE: usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the derive macro `frame_support::PalletError` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
@@ -1,5 +0,0 @@
|
||||
error: Invalid pallet::error, unexpected fields, must be `Unit`
|
||||
--> $DIR/error_no_fieldless.rs:20:5
|
||||
|
|
||||
20 | U8(u8),
|
||||
| ^^^^
|
||||
@@ -0,0 +1,41 @@
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::PalletError;
|
||||
|
||||
#[frame_support::pallet]
|
||||
mod pallet {
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config {}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(core::marker::PhantomData<T>);
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
CustomError(crate::MyError),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, PalletError, scale_info::TypeInfo)]
|
||||
pub enum MyError {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz(NestedError),
|
||||
Struct(MyStruct),
|
||||
Wrapper(Wrapper),
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, PalletError, scale_info::TypeInfo)]
|
||||
pub enum NestedError {
|
||||
Quux
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, PalletError, scale_info::TypeInfo)]
|
||||
pub struct MyStruct {
|
||||
field: u8,
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, PalletError, scale_info::TypeInfo)]
|
||||
pub struct Wrapper(bool);
|
||||
|
||||
fn main() {
|
||||
}
|
||||
Reference in New Issue
Block a user