1234567891011121314151617#![cfg_attr(not(feature = "std"), no_std)]1819pub use pallet::*;20use frame_support::pallet_prelude::*;21use frame_system::pallet_prelude::*;2223#[frame_support::pallet]24pub mod pallet {25 use frame_support::{26 pallet_prelude::*,27 dispatch::{Dispatchable, GetDispatchInfo, PostDispatchInfo},28 traits::{UnfilteredDispatchable, IsSubType, OriginTrait},29 };30 use frame_system::pallet_prelude::*;31 use sp_std::vec::Vec;32 3334 #[pallet::config]35 pub trait Config: frame_system::Config {36 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;3738 39 type RuntimeCall: Parameter40 + Dispatchable<41 RuntimeOrigin = <Self as frame_system::Config>::RuntimeOrigin,42 PostInfo = PostDispatchInfo,43 > + GetDispatchInfo44 + From<frame_system::Call<Self>>45 + UnfilteredDispatchable<RuntimeOrigin = <Self as frame_system::Config>::RuntimeOrigin>46 + IsSubType<Call<Self>>47 + IsType<<Self as frame_system::Config>::RuntimeCall>;48 }4950 #[pallet::event]51 #[pallet::generate_deposit(pub(super) fn deposit_event)]52 pub enum Event<T: Config> {53 ValueIsSet,54 ShouldRollback,55 BatchCompleted,56 }5758 #[pallet::pallet]59 #[pallet::generate_store(pub(super) trait Store)]60 pub struct Pallet<T>(_);6162 #[pallet::storage]63 #[pallet::getter(fn is_enabled)]64 pub type Enabled<T> = StorageValue<_, bool, ValueQuery>;6566 #[pallet::storage]67 #[pallet::getter(fn test_value)]68 pub type TestValue<T> = StorageValue<_, u32, ValueQuery>;6970 #[pallet::error]71 pub enum Error<T> {72 TestPalletDisabled,73 TriggerRollback,74 }7576 #[pallet::call]77 impl<T: Config> Pallet<T> {78 #[pallet::call_index(0)]79 #[pallet::weight(10_000)]80 pub fn enable(origin: OriginFor<T>) -> DispatchResult {81 ensure_root(origin)?;82 <Enabled<T>>::set(true);8384 Ok(())85 }8687 #[pallet::call_index(1)]88 #[pallet::weight(10_000)]89 pub fn set_test_value(origin: OriginFor<T>, value: u32) -> DispatchResult {90 Self::ensure_origin_and_enabled(origin)?;9192 <TestValue<T>>::put(value);9394 Self::deposit_event(Event::ValueIsSet);9596 Ok(())97 }9899 #[pallet::call_index(2)]100 #[pallet::weight(10_000)]101 pub fn set_test_value_and_rollback(origin: OriginFor<T>, value: u32) -> DispatchResult {102 Self::set_test_value(origin, value)?;103104 Self::deposit_event(Event::ShouldRollback);105106 Err(<Error<T>>::TriggerRollback.into())107 }108109 #[pallet::call_index(3)]110 #[pallet::weight(10_000)]111 pub fn inc_test_value(origin: OriginFor<T>) -> DispatchResult {112 Self::set_test_value(origin, <TestValue<T>>::get() + 1)113 }114115 116 117 118 119 120 121 122 123124 125 126 127128 129 130131 #[pallet::call_index(4)]132 #[pallet::weight(100_000_000)]133 pub fn just_take_fee(origin: OriginFor<T>) -> DispatchResult {134 Self::ensure_origin_and_enabled(origin)?;135 Ok(())136 }137138 #[pallet::call_index(5)]139 #[pallet::weight(10_000)]140 pub fn batch_all(141 origin: OriginFor<T>,142 calls: Vec<<T as Config>::RuntimeCall>,143 ) -> DispatchResultWithPostInfo {144 Self::ensure_origin_and_enabled(origin.clone())?;145146 let is_root = ensure_root(origin.clone()).is_ok();147148 for call in calls {149 if is_root {150 call.dispatch_bypass_filter(origin.clone())?;151 } else {152 let mut filtered_origin = origin.clone();153 154 filtered_origin.add_filter(155 move |c: &<T as frame_system::Config>::RuntimeCall| {156 let c = <T as Config>::RuntimeCall::from_ref(c);157 !matches!(c.is_sub_type(), Some(Call::batch_all { .. }))158 },159 );160 call.dispatch(filtered_origin)?;161 }162 }163164 Self::deposit_event(Event::BatchCompleted);165 Ok(None::<Weight>.into())166 }167 }168}169170impl<T: Config> Pallet<T> {171 fn ensure_origin_and_enabled(origin: OriginFor<T>) -> DispatchResult {172 ensure_signed(origin)?;173 <Enabled<T>>::get()174 .then(|| ())175 .ok_or(<Error<T>>::TestPalletDisabled.into())176 }177}