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(dev_mode)]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;3233 #[pallet::config]34 pub trait Config: frame_system::Config {35 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;3637 38 type RuntimeCall: Parameter39 + Dispatchable<40 RuntimeOrigin = <Self as frame_system::Config>::RuntimeOrigin,41 PostInfo = PostDispatchInfo,42 > + GetDispatchInfo43 + From<frame_system::Call<Self>>44 + UnfilteredDispatchable<RuntimeOrigin = <Self as frame_system::Config>::RuntimeOrigin>45 + IsSubType<Call<Self>>46 + IsType<<Self as frame_system::Config>::RuntimeCall>;47 }4849 #[pallet::event]50 #[pallet::generate_deposit(pub(super) fn deposit_event)]51 pub enum Event<T: Config> {52 ValueIsSet,53 ShouldRollback,54 BatchCompleted,55 }5657 #[pallet::pallet]58 pub struct Pallet<T>(_);5960 #[pallet::storage]61 #[pallet::getter(fn is_enabled)]62 pub type Enabled<T> = StorageValue<_, bool, ValueQuery>;6364 #[pallet::storage]65 #[pallet::getter(fn test_value)]66 pub type TestValue<T> = StorageValue<_, u32, ValueQuery>;6768 #[pallet::error]69 pub enum Error<T> {70 TestPalletDisabled,71 TriggerRollback,72 }7374 #[pallet::call]75 impl<T: Config> Pallet<T> {76 #[pallet::call_index(0)]77 #[pallet::weight(10_000)]78 pub fn enable(origin: OriginFor<T>) -> DispatchResult {79 ensure_root(origin)?;80 <Enabled<T>>::set(true);8182 Ok(())83 }8485 #[pallet::call_index(1)]86 #[pallet::weight(10_000)]87 pub fn set_test_value(origin: OriginFor<T>, value: u32) -> DispatchResult {88 Self::ensure_origin_and_enabled(origin)?;8990 <TestValue<T>>::put(value);9192 Self::deposit_event(Event::ValueIsSet);9394 Ok(())95 }9697 #[pallet::call_index(2)]98 #[pallet::weight(10_000)]99 pub fn set_test_value_and_rollback(origin: OriginFor<T>, value: u32) -> DispatchResult {100 Self::set_test_value(origin, value)?;101102 Self::deposit_event(Event::ShouldRollback);103104 Err(<Error<T>>::TriggerRollback.into())105 }106107 #[pallet::call_index(3)]108 #[pallet::weight(10_000)]109 pub fn inc_test_value(origin: OriginFor<T>) -> DispatchResult {110 Self::set_test_value(origin, <TestValue<T>>::get() + 1)111 }112113 114 115 116 117 118 119 120 121122 123 124 125126 127 128129 #[pallet::call_index(4)]130 #[pallet::weight(100_000_000)]131 pub fn just_take_fee(origin: OriginFor<T>) -> DispatchResult {132 Self::ensure_origin_and_enabled(origin)?;133 Ok(())134 }135136 #[pallet::call_index(5)]137 #[pallet::weight(10_000)]138 pub fn batch_all(139 origin: OriginFor<T>,140 calls: Vec<<T as Config>::RuntimeCall>,141 ) -> DispatchResultWithPostInfo {142 Self::ensure_origin_and_enabled(origin.clone())?;143144 let is_root = ensure_root(origin.clone()).is_ok();145146 for call in calls {147 if is_root {148 call.dispatch_bypass_filter(origin.clone())?;149 } else {150 let mut filtered_origin = origin.clone();151 152 filtered_origin.add_filter(153 move |c: &<T as frame_system::Config>::RuntimeCall| {154 let c = <T as Config>::RuntimeCall::from_ref(c);155 !matches!(c.is_sub_type(), Some(Call::batch_all { .. }))156 },157 );158 call.dispatch(filtered_origin)?;159 }160 }161162 Self::deposit_event(Event::BatchCompleted);163 Ok(None::<Weight>.into())164 }165 }166}167168impl<T: Config> Pallet<T> {169 fn ensure_origin_and_enabled(origin: OriginFor<T>) -> DispatchResult {170 ensure_signed(origin)?;171 <Enabled<T>>::get()172 .then_some(())173 .ok_or(<Error<T>>::TestPalletDisabled.into())174 }175}