pallet_domain_sudo/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
19
20#[cfg(not(feature = "std"))]
21extern crate alloc;
22
23pub use pallet::*;
24
25#[frame_support::pallet]
26mod pallet {
27 #[cfg(not(feature = "std"))]
28 use alloc::boxed::Box;
29 use frame_support::dispatch::{GetDispatchInfo, RawOrigin};
30 use frame_support::pallet_prelude::*;
31 use frame_support::traits::UnfilteredDispatchable;
32 use frame_system::ensure_none;
33 use frame_system::pallet_prelude::OriginFor;
34 use sp_domain_sudo::{INHERENT_IDENTIFIER, InherentError, InherentType, IntoRuntimeCall};
35
36 #[pallet::config]
37 pub trait Config: frame_system::Config<RuntimeEvent: From<Event<Self>>> {
38 type RuntimeCall: Parameter
39 + UnfilteredDispatchable<RuntimeOrigin = Self::RuntimeOrigin>
40 + GetDispatchInfo;
41 type IntoRuntimeCall: IntoRuntimeCall<<Self as Config>::RuntimeCall>;
42 }
43
44 #[pallet::event]
45 #[pallet::generate_deposit(pub (super) fn deposit_event)]
46 pub enum Event<T: Config> {
47 Sudid {
49 sudo_result: DispatchResult,
51 },
52 }
53
54 #[pallet::pallet]
56 #[pallet::without_storage_info]
57 pub struct Pallet<T>(_);
58
59 #[pallet::call]
60 impl<T: Config> Pallet<T> {
61 #[pallet::call_index(0)]
63 #[pallet::weight({
64 let dispatch_info = call.get_dispatch_info();
65 (dispatch_info.call_weight.saturating_add(dispatch_info.extension_weight), DispatchClass::Mandatory)
66 })]
67 pub fn sudo(origin: OriginFor<T>, call: Box<<T as Config>::RuntimeCall>) -> DispatchResult {
68 ensure_none(origin)?;
69
70 let res = call.dispatch_bypass_filter(RawOrigin::Root.into());
71 Self::deposit_event(Event::Sudid {
72 sudo_result: res.map(|_| ()).map_err(|e| e.error),
73 });
74
75 Ok(())
76 }
77 }
78
79 #[pallet::inherent]
80 impl<T: Config> ProvideInherent for Pallet<T> {
81 type Call = Call<T>;
82 type Error = InherentError;
83 const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
84
85 fn create_inherent(data: &InherentData) -> Option<Self::Call> {
86 let inherent_data = data
87 .get_data::<InherentType>(&INHERENT_IDENTIFIER)
88 .expect("Domain sudo inherent data not correctly encoded")
89 .expect("Domain sudo inherent data must be provided");
90
91 if let Some(encoded_call) = inherent_data.maybe_call {
92 let call = Box::new(T::IntoRuntimeCall::runtime_call(encoded_call));
93 Some(Call::sudo { call })
94 } else {
95 None
96 }
97 }
98
99 fn is_inherent_required(data: &InherentData) -> Result<Option<Self::Error>, Self::Error> {
100 let inherent_data = data
101 .get_data::<InherentType>(&INHERENT_IDENTIFIER)
102 .expect("Domain sudo inherent data not correctly encoded")
103 .expect("Domain sudo inherent data must be provided");
104
105 Ok(if inherent_data.maybe_call.is_none() {
106 None
107 } else {
108 Some(InherentError::MissingRuntimeCall)
109 })
110 }
111
112 fn check_inherent(call: &Self::Call, data: &InherentData) -> Result<(), Self::Error> {
113 let inherent_data = data
114 .get_data::<InherentType>(&INHERENT_IDENTIFIER)
115 .expect("Domain sudo inherent data not correctly encoded")
116 .expect("Domain sudo inherent data must be provided");
117
118 if let Some(encoded_call) = inherent_data.maybe_call {
119 let runtime_call = Box::new(T::IntoRuntimeCall::runtime_call(encoded_call));
120 if let Call::sudo { call } = call
121 && call != &runtime_call
122 {
123 return Err(InherentError::IncorrectRuntimeCall);
124 }
125 } else {
126 return Err(InherentError::MissingRuntimeCall);
127 }
128
129 Ok(())
130 }
131
132 fn is_inherent(call: &Self::Call) -> bool {
133 matches!(call, Call::sudo { .. })
134 }
135 }
136}