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