diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs
index 9fce1762c6ea7..13d03562cce49 100644
--- a/frame/collective/src/lib.rs
+++ b/frame/collective/src/lib.rs
@@ -996,11 +996,11 @@ impl<
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> O {
+	fn try_successful_origin() -> Result<O, ()> {
 		let zero_account_id =
 			AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes())
 				.expect("infinite length input; no invalid inputs for type; qed");
-		O::from(RawOrigin::Member(zero_account_id))
+		Ok(O::from(RawOrigin::Member(zero_account_id)))
 	}
 }
 
@@ -1021,8 +1021,8 @@ impl<
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> O {
-		O::from(RawOrigin::Members(N, N))
+	fn try_successful_origin() -> Result<O, ()> {
+		Ok(O::from(RawOrigin::Members(N, N)))
 	}
 }
 
@@ -1046,8 +1046,8 @@ impl<
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> O {
-		O::from(RawOrigin::Members(1u32, 0u32))
+	fn try_successful_origin() -> Result<O, ()> {
+		Ok(O::from(RawOrigin::Members(1u32, 0u32)))
 	}
 }
 
@@ -1071,7 +1071,7 @@ impl<
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> O {
-		O::from(RawOrigin::Members(0u32, 0u32))
+	fn try_successful_origin() -> Result<O, ()> {
+		Ok(O::from(RawOrigin::Members(0u32, 0u32)))
 	}
 }
diff --git a/frame/society/src/lib.rs b/frame/society/src/lib.rs
index 5a993f72f32d2..2a6428e754b9d 100644
--- a/frame/society/src/lib.rs
+++ b/frame/society/src/lib.rs
@@ -1272,9 +1272,9 @@ impl<T: Config> EnsureOrigin<T::Origin> for EnsureFounder<T> {
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> T::Origin {
-		let founder = Founder::<T>::get().expect("society founder should exist");
-		T::Origin::from(frame_system::RawOrigin::Signed(founder))
+	fn try_successful_origin() -> Result<T::Origin, ()> {
+		let founder = Founder::<T>::get().ok_or(())?;
+		Ok(T::Origin::from(frame_system::RawOrigin::Signed(founder)))
 	}
 }
 
diff --git a/frame/support/src/traits/dispatch.rs b/frame/support/src/traits/dispatch.rs
index b1bd52ca960da..e06373348e499 100644
--- a/frame/support/src/traits/dispatch.rs
+++ b/frame/support/src/traits/dispatch.rs
@@ -18,10 +18,14 @@
 //! Traits for dealing with dispatching calls and the origin from which they are dispatched.
 
 use crate::dispatch::{DispatchResultWithPostInfo, Parameter, RawOrigin};
+use sp_arithmetic::traits::{CheckedSub, Zero};
 use sp_runtime::{
-	traits::{BadOrigin, Member},
+	traits::{BadOrigin, Member, Morph, TryMorph},
 	Either,
 };
+use sp_std::marker::PhantomData;
+
+use super::TypedGet;
 
 /// Some sort of check on the origin is performed by this object.
 pub trait EnsureOrigin<OuterOrigin> {
@@ -38,9 +42,23 @@ pub trait EnsureOrigin<OuterOrigin> {
 
 	/// Returns an outer origin capable of passing `try_origin` check.
 	///
+	/// NOTE: This should generally *NOT* be reimplemented. Instead implement
+	/// `try_successful_origin`.
+	///
 	/// ** Should be used for benchmarking only!!! **
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> OuterOrigin;
+	fn successful_origin() -> OuterOrigin {
+		Self::try_successful_origin().expect("No origin exists which can satisfy the guard")
+	}
+
+	/// Attept to get an outer origin capable of passing `try_origin` check. May return `Err` if it
+	/// is impossible. Default implementation just uses `successful_origin()`.
+	///
+	/// ** Should be used for benchmarking only!!! **
+	#[cfg(feature = "runtime-benchmarks")]
+	fn try_successful_origin() -> Result<OuterOrigin, ()> {
+		Ok(Self::successful_origin())
+	}
 }
 
 /// `EnsureOrigin` implementation that always fails.
@@ -51,8 +69,8 @@ impl<OO, Success> EnsureOrigin<OO> for NeverEnsureOrigin<Success> {
 		Err(o)
 	}
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> OO {
-		panic!("No `successful_origin` possible for `NeverEnsureOrigin`")
+	fn try_successful_origin() -> Result<OO, ()> {
+		Err(())
 	}
 }
 
@@ -71,9 +89,23 @@ pub trait EnsureOriginWithArg<OuterOrigin, Argument> {
 
 	/// Returns an outer origin capable of passing `try_origin` check.
 	///
+	/// NOTE: This should generally *NOT* be reimplemented. Instead implement
+	/// `try_successful_origin`.
+	///
 	/// ** Should be used for benchmarking only!!! **
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin(a: &Argument) -> OuterOrigin;
+	fn successful_origin(a: &Argument) -> OuterOrigin {
+		Self::try_successful_origin(a).expect("No origin exists which can satisfy the guard")
+	}
+
+	/// Attept to get an outer origin capable of passing `try_origin` check. May return `Err` if it
+	/// is impossible. Default implementation just uses `successful_origin()`.
+	///
+	/// ** Should be used for benchmarking only!!! **
+	#[cfg(feature = "runtime-benchmarks")]
+	fn try_successful_origin(a: &Argument) -> Result<OuterOrigin, ()> {
+		Ok(Self::successful_origin(a))
+	}
 }
 
 pub struct AsEnsureOriginWithArg<EO>(sp_std::marker::PhantomData<EO>);
@@ -97,8 +129,121 @@ impl<OuterOrigin, Argument, EO: EnsureOrigin<OuterOrigin>>
 	///
 	/// ** Should be used for benchmarking only!!! **
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin(_: &Argument) -> OuterOrigin {
-		EO::successful_origin()
+	fn try_successful_origin(_: &Argument) -> Result<OuterOrigin, ()> {
+		EO::try_successful_origin()
+	}
+}
+
+/// A derivative `EnsureOrigin` implementation. It mutates the `Success` result of an `Original`
+/// implementation with a given `Mutator`.
+pub struct MapSuccess<Original, Mutator>(PhantomData<(Original, Mutator)>);
+impl<O, Original: EnsureOrigin<O>, Mutator: Morph<Original::Success>> EnsureOrigin<O>
+	for MapSuccess<Original, Mutator>
+{
+	type Success = Mutator::Outcome;
+	fn try_origin(o: O) -> Result<Mutator::Outcome, O> {
+		Ok(Mutator::morph(Original::try_origin(o)?))
+	}
+	#[cfg(feature = "runtime-benchmarks")]
+	fn try_successful_origin() -> Result<O, ()> {
+		Original::try_successful_origin()
+	}
+}
+
+/// A derivative `EnsureOrigin` implementation. It mutates the `Success` result of an `Original`
+/// implementation with a given `Mutator`, allowing the possibility of an error to be returned
+/// from the mutator.
+///
+/// NOTE: This is strictly worse performance than `MapSuccess` since it clones the original origin
+/// value. If possible, use `MapSuccess` instead.
+pub struct TryMapSuccess<Orig, Mutator>(PhantomData<(Orig, Mutator)>);
+impl<O: Clone, Original: EnsureOrigin<O>, Mutator: TryMorph<Original::Success>> EnsureOrigin<O>
+	for TryMapSuccess<Original, Mutator>
+{
+	type Success = Mutator::Outcome;
+	fn try_origin(o: O) -> Result<Mutator::Outcome, O> {
+		let orig = o.clone();
+		Mutator::try_morph(Original::try_origin(o)?).map_err(|()| orig)
+	}
+	#[cfg(feature = "runtime-benchmarks")]
+	fn try_successful_origin() -> Result<O, ()> {
+		Original::try_successful_origin()
+	}
+}
+
+/// "OR gate" implementation of `EnsureOrigin` allowing for different `Success` types for `L`
+/// and `R`, with them combined using an `Either` type.
+///
+/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
+///
+/// Successful origin is derived from the left side.
+pub struct EitherOfDiverse<L, R>(sp_std::marker::PhantomData<(L, R)>);
+impl<OuterOrigin, L: EnsureOrigin<OuterOrigin>, R: EnsureOrigin<OuterOrigin>>
+	EnsureOrigin<OuterOrigin> for EitherOfDiverse<L, R>
+{
+	type Success = Either<L::Success, R::Success>;
+	fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin> {
+		L::try_origin(o)
+			.map_or_else(|o| R::try_origin(o).map(Either::Right), |o| Ok(Either::Left(o)))
+	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn try_successful_origin() -> Result<OuterOrigin, ()> {
+		L::try_successful_origin().or_else(|()| R::try_successful_origin())
+	}
+}
+
+/// "OR gate" implementation of `EnsureOrigin` allowing for different `Success` types for `L`
+/// and `R`, with them combined using an `Either` type.
+///
+/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
+///
+/// Successful origin is derived from the left side.
+#[deprecated = "Use `EitherOfDiverse` instead"]
+pub type EnsureOneOf<L, R> = EitherOfDiverse<L, R>;
+
+/// "OR gate" implementation of `EnsureOrigin`, `Success` type for both `L` and `R` must
+/// be equal.
+///
+/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
+///
+/// Successful origin is derived from the left side.
+pub struct EitherOf<L, R>(sp_std::marker::PhantomData<(L, R)>);
+impl<
+		OuterOrigin,
+		L: EnsureOrigin<OuterOrigin>,
+		R: EnsureOrigin<OuterOrigin, Success = L::Success>,
+	> EnsureOrigin<OuterOrigin> for EitherOf<L, R>
+{
+	type Success = L::Success;
+	fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin> {
+		L::try_origin(o).or_else(|o| R::try_origin(o))
+	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn try_successful_origin() -> Result<OuterOrigin, ()> {
+		L::try_successful_origin().or_else(|()| R::try_successful_origin())
+	}
+}
+
+/// Mutator which reduces a scalar by a particular amount.
+pub struct ReduceBy<N>(PhantomData<N>);
+impl<N: TypedGet> TryMorph<N::Type> for ReduceBy<N>
+where
+	N::Type: CheckedSub,
+{
+	type Outcome = N::Type;
+	fn try_morph(r: N::Type) -> Result<N::Type, ()> {
+		r.checked_sub(&N::get()).ok_or(())
+	}
+}
+impl<N: TypedGet> Morph<N::Type> for ReduceBy<N>
+where
+	N::Type: CheckedSub + Zero,
+{
+	type Outcome = N::Type;
+	fn morph(r: N::Type) -> N::Type {
+		r.checked_sub(&N::get()).unwrap_or(Zero::zero())
 	}
 }
 
@@ -176,63 +321,6 @@ pub trait OriginTrait: Sized {
 	fn signed(by: Self::AccountId) -> Self;
 }
 
-/// "OR gate" implementation of `EnsureOrigin` allowing for different `Success` types for `L`
-/// and `R`, with them combined using an `Either` type.
-///
-/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
-///
-/// Successful origin is derived from the left side.
-pub struct EitherOfDiverse<L, R>(sp_std::marker::PhantomData<(L, R)>);
-
-impl<OuterOrigin, L: EnsureOrigin<OuterOrigin>, R: EnsureOrigin<OuterOrigin>>
-	EnsureOrigin<OuterOrigin> for EitherOfDiverse<L, R>
-{
-	type Success = Either<L::Success, R::Success>;
-	fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin> {
-		L::try_origin(o)
-			.map_or_else(|o| R::try_origin(o).map(Either::Right), |o| Ok(Either::Left(o)))
-	}
-
-	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> OuterOrigin {
-		L::successful_origin()
-	}
-}
-
-/// "OR gate" implementation of `EnsureOrigin` allowing for different `Success` types for `L`
-/// and `R`, with them combined using an `Either` type.
-///
-/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
-///
-/// Successful origin is derived from the left side.
-#[deprecated = "Use `EitherOfDiverse` instead"]
-pub type EnsureOneOf<L, R> = EitherOfDiverse<L, R>;
-
-/// "OR gate" implementation of `EnsureOrigin`, `Success` type for both `L` and `R` must
-/// be equal.
-///
-/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
-///
-/// Successful origin is derived from the left side.
-pub struct EitherOf<L, R>(sp_std::marker::PhantomData<(L, R)>);
-
-impl<
-		OuterOrigin,
-		L: EnsureOrigin<OuterOrigin>,
-		R: EnsureOrigin<OuterOrigin, Success = L::Success>,
-	> EnsureOrigin<OuterOrigin> for EitherOf<L, R>
-{
-	type Success = L::Success;
-	fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin> {
-		L::try_origin(o).or_else(|o| R::try_origin(o))
-	}
-
-	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> OuterOrigin {
-		L::successful_origin()
-	}
-}
-
 #[cfg(test)]
 mod tests {
 	use super::*;
@@ -248,8 +336,8 @@ mod tests {
 			Ok(V::get())
 		}
 		#[cfg(feature = "runtime-benchmarks")]
-		fn successful_origin() -> () {
-			()
+		fn try_successful_origin() -> Result<(), ()> {
+			Ok(())
 		}
 	}
 
@@ -259,8 +347,8 @@ mod tests {
 			Err(())
 		}
 		#[cfg(feature = "runtime-benchmarks")]
-		fn successful_origin() -> () {
-			()
+		fn try_successful_origin() -> Result<(), ()> {
+			Err(())
 		}
 	}
 
diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs
index bc28cc7e8118e..370a802665918 100644
--- a/frame/system/src/lib.rs
+++ b/frame/system/src/lib.rs
@@ -66,6 +66,8 @@
 
 #[cfg(feature = "std")]
 use serde::Serialize;
+#[cfg(feature = "runtime-benchmarks")]
+use sp_runtime::traits::TrailingZeroInput;
 use sp_runtime::{
 	generic,
 	traits::{
@@ -782,8 +784,8 @@ impl<O: Into<Result<RawOrigin<AccountId>, O>> + From<RawOrigin<AccountId>>, Acco
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> O {
-		O::from(RawOrigin::Root)
+	fn try_successful_origin() -> Result<O, ()> {
+		Ok(O::from(RawOrigin::Root))
 	}
 }
 
@@ -805,8 +807,8 @@ impl<
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> O {
-		O::from(RawOrigin::Root)
+	fn try_successful_origin() -> Result<O, ()> {
+		Ok(O::from(RawOrigin::Root))
 	}
 }
 
@@ -823,11 +825,10 @@ impl<O: Into<Result<RawOrigin<AccountId>, O>> + From<RawOrigin<AccountId>>, Acco
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> O {
+	fn try_successful_origin() -> Result<O, ()> {
 		let zero_account_id =
-			AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes())
-				.expect("infinite length input; no invalid inputs for type; qed");
-		O::from(RawOrigin::Signed(zero_account_id))
+			AccountId::decode(&mut TrailingZeroInput::zeroes()).map_err(|_| ())?;
+		Ok(O::from(RawOrigin::Signed(zero_account_id)))
 	}
 }
 
@@ -847,16 +848,15 @@ impl<
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> O {
+	fn try_successful_origin() -> Result<O, ()> {
 		let zero_account_id =
-			AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes())
-				.expect("infinite length input; no invalid inputs for type; qed");
+			AccountId::decode(&mut TrailingZeroInput::zeroes()).map_err(|_| ())?;
 		let members = Who::sorted_members();
 		let first_member = match members.get(0) {
 			Some(account) => account.clone(),
 			None => zero_account_id,
 		};
-		O::from(RawOrigin::Signed(first_member))
+		Ok(O::from(RawOrigin::Signed(first_member)))
 	}
 }
 
@@ -873,8 +873,8 @@ impl<O: Into<Result<RawOrigin<AccountId>, O>> + From<RawOrigin<AccountId>>, Acco
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> O {
-		O::from(RawOrigin::None)
+	fn try_successful_origin() -> Result<O, ()> {
+		Ok(O::from(RawOrigin::None))
 	}
 }
 
@@ -886,8 +886,8 @@ impl<O, T> EnsureOrigin<O> for EnsureNever<T> {
 	}
 
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> O {
-		unimplemented!()
+	fn try_successful_origin() -> Result<O, ()> {
+		Err(())
 	}
 }
 
diff --git a/frame/treasury/src/tests.rs b/frame/treasury/src/tests.rs
index a21296d1b39ec..61eafb652427b 100644
--- a/frame/treasury/src/tests.rs
+++ b/frame/treasury/src/tests.rs
@@ -116,8 +116,8 @@ impl frame_support::traits::EnsureOrigin<Origin> for TestSpendOrigin {
 		})
 	}
 	#[cfg(feature = "runtime-benchmarks")]
-	fn successful_origin() -> Origin {
-		Origin::root()
+	fn try_successful_origin() -> Result<Origin, ()> {
+		Ok(Origin::root())
 	}
 }
 
diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs
index 1b21e7c65ddf7..ee6a526e95e1e 100644
--- a/primitives/runtime/src/traits.rs
+++ b/primitives/runtime/src/traits.rs
@@ -274,6 +274,42 @@ where
 	}
 }
 
+/// Extensible conversion trait. Generic over only source type, with destination type being
+/// associated.
+pub trait Morph<A> {
+	/// The type into which `A` is mutated.
+	type Outcome;
+
+	/// Make conversion.
+	fn morph(a: A) -> Self::Outcome;
+}
+
+/// A structure that performs identity conversion.
+impl<T> Morph<T> for Identity {
+	type Outcome = T;
+	fn morph(a: T) -> T {
+		a
+	}
+}
+
+/// Extensible conversion trait. Generic over only source type, with destination type being
+/// associated.
+pub trait TryMorph<A> {
+	/// The type into which `A` is mutated.
+	type Outcome;
+
+	/// Make conversion.
+	fn try_morph(a: A) -> Result<Self::Outcome, ()>;
+}
+
+/// A structure that performs identity conversion.
+impl<T> TryMorph<T> for Identity {
+	type Outcome = T;
+	fn try_morph(a: T) -> Result<T, ()> {
+		Ok(a)
+	}
+}
+
 /// Extensible conversion trait. Generic over both source and destination types.
 pub trait Convert<A, B> {
 	/// Make conversion.