Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #219 #7407

Merged
merged 14 commits into from
Feb 18, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,7 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
// Standard Error: 1_745
.saturating_add(Weight::from_parts(6_562_902, 0).saturating_mul(c.into()))
}
fn dispatch_as_checked() -> Weight {
0.into()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,7 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
// Standard Error: 3_765
.saturating_add(Weight::from_parts(6_028_416, 0).saturating_mul(c.into()))
}
fn dispatch_as_checked() -> Weight {
0.into()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,7 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
// Standard Error: 1_601
.saturating_add(Weight::from_parts(5_138_293, 0).saturating_mul(c.into()))
}
fn dispatch_as_checked() -> Weight {
0.into()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,7 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
// Standard Error: 1_601
.saturating_add(Weight::from_parts(5_138_293, 0).saturating_mul(c.into()))
}
fn dispatch_as_checked() -> Weight {
0.into()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,7 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
// Standard Error: 1_395
.saturating_add(Weight::from_parts(5_000_971, 0).saturating_mul(c.into()))
}
fn dispatch_as_checked() -> Weight {
0.into()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,7 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
// Standard Error: 1_621
.saturating_add(Weight::from_parts(3_312_302, 0).saturating_mul(c.into()))
}
fn dispatch_as_checked() -> Weight {
0.into()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,7 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
// Standard Error: 740
.saturating_add(Weight::from_parts(2_800_888, 0).saturating_mul(c.into()))
}
fn dispatch_as_checked() -> Weight {
0.into()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,7 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
// Standard Error: 3_915
.saturating_add(Weight::from_parts(4_372_646, 0).saturating_mul(c.into()))
}
fn dispatch_as_checked() -> Weight {
0.into()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,7 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
// Standard Error: 7_605
.saturating_add(Weight::from_parts(4_306_193, 0).saturating_mul(c.into()))
}
fn dispatch_as_checked() -> Weight {
0.into()
}
}
3 changes: 3 additions & 0 deletions polkadot/runtime/rococo/src/weights/pallet_utility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,7 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
// Standard Error: 460
.saturating_add(Weight::from_parts(3_173_577, 0).saturating_mul(c.into()))
}
fn dispatch_as_checked() -> Weight {
0.into()
}
}
3 changes: 3 additions & 0 deletions polkadot/runtime/westend/src/weights/pallet_utility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,7 @@ impl<T: frame_system::Config> pallet_utility::WeightInfo for WeightInfo<T> {
// Standard Error: 2_817
.saturating_add(Weight::from_parts(5_113_539, 0).saturating_mul(c.into()))
}
fn dispatch_as_checked() -> Weight {
0.into()
}
}
12 changes: 12 additions & 0 deletions substrate/frame/utility/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@ mod benchmark {
assert_last_event::<T>(Event::BatchCompleted.into());
}

#[benchmark]
fn dispatch_as_checked() {
let caller = account("caller", SEED, SEED);
let call = Box::new(frame_system::Call::remark { remark: vec![] }.into());
let origin: T::RuntimeOrigin = RawOrigin::Signed(caller).into();
let pallets_origin = origin.caller().clone();
let pallets_origin = T::PalletsOrigin::from(pallets_origin);

#[extrinsic_call]
_(RawOrigin::Root, Box::new(pallets_origin), call);
}

impl_benchmark_test_suite! {
Pallet,
tests::new_test_ext(),
Expand Down
30 changes: 30 additions & 0 deletions substrate/frame/utility/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,36 @@ pub mod pallet {
let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into());
res.map(|_| ()).map_err(|e| e.error)
}

/// Dispatches a function call with a provided origin.
/// Almost the same as [`Pallet::dispatch_as`] but check the result of the call.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can be more explicit and say it will return an error if the call returns an error.
I find the verb "check" a bit vague here.

///
/// The dispatch origin for this call must be _Root_.
///
/// ## Complexity
/// - O(1).
#[pallet::call_index(6)]
#[pallet::weight({
let dispatch_info = call.get_dispatch_info();
(
T::WeightInfo::dispatch_as_checked()
.saturating_add(dispatch_info.call_weight),
dispatch_info.class,
)
})]
pub fn dispatch_as_checked(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn dispatch_as_checked(
pub fn dispatch_as_fallible(

Maybe that sounds better?

origin: OriginFor<T>,
as_origin: Box<T::PalletsOrigin>,
call: Box<<T as Config>::RuntimeCall>,
) -> DispatchResult {
ensure_root(origin)?;

call.dispatch_bypass_filter((*as_origin).into()).map_err(|e| e.error)?;

Self::deposit_event(Event::DispatchedAs { result: Ok(()) });

Ok(())
}
}

impl<T: Config> Pallet<T> {
Expand Down
60 changes: 60 additions & 0 deletions substrate/frame/utility/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,14 @@ fn call_foobar(err: bool, start_weight: Weight, end_weight: Option<Weight>) -> R
RuntimeCall::Example(ExampleCall::foobar { err, start_weight, end_weight })
}

fn utility_events() -> Vec<Event> {
System::events()
.into_iter()
.map(|r| r.event)
.filter_map(|e| if let RuntimeEvent::Utility(inner) = e { Some(inner) } else { None })
.collect()
}

#[test]
fn as_derivative_works() {
new_test_ext().execute_with(|| {
Expand Down Expand Up @@ -915,3 +923,55 @@ fn with_weight_works() {
);
})
}

#[test]
fn dispatch_as_works() {
new_test_ext().execute_with(|| {
Balances::force_set_balance(RuntimeOrigin::root(), 666, 100).unwrap();
assert_eq!(Balances::free_balance(666), 100);
assert_eq!(Balances::free_balance(777), 0);
assert_ok!(Utility::dispatch_as(
RuntimeOrigin::root(),
Box::new(OriginCaller::system(frame_system::RawOrigin::Signed(666))),
Box::new(call_transfer(777, 100))
));
assert_eq!(Balances::free_balance(666), 0);
assert_eq!(Balances::free_balance(777), 100);

System::reset_events();
assert_ok!(Utility::dispatch_as(
RuntimeOrigin::root(),
Box::new(OriginCaller::system(frame_system::RawOrigin::Signed(777))),
Box::new(RuntimeCall::Timestamp(TimestampCall::set { now: 0 }))
));
assert_eq!(
utility_events(),
vec![Event::DispatchedAs { result: Err(DispatchError::BadOrigin) }]
);
})
}

#[test]
fn dispatch_as_checked_works() {
new_test_ext().execute_with(|| {
Balances::force_set_balance(RuntimeOrigin::root(), 666, 100).unwrap();
assert_eq!(Balances::free_balance(666), 100);
assert_eq!(Balances::free_balance(777), 0);
assert_ok!(Utility::dispatch_as_checked(
RuntimeOrigin::root(),
Box::new(OriginCaller::system(frame_system::RawOrigin::Signed(666))),
Box::new(call_transfer(777, 100))
));
assert_eq!(Balances::free_balance(666), 0);
assert_eq!(Balances::free_balance(777), 100);

assert_noop!(
Utility::dispatch_as_checked(
RuntimeOrigin::root(),
Box::new(OriginCaller::system(frame_system::RawOrigin::Signed(777))),
Box::new(RuntimeCall::Timestamp(TimestampCall::set { now: 0 }))
),
DispatchError::BadOrigin,
);
});
}
7 changes: 7 additions & 0 deletions substrate/frame/utility/src/weights.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading