diff --git a/substrate/bin/node-template/runtime/src/lib.rs b/substrate/bin/node-template/runtime/src/lib.rs
index 153d9cf49dcc0ab62b527cf352448039cf8db5ea..a9944199b8209d34f2db5cd567960d06cdeb3258 100644
--- a/substrate/bin/node-template/runtime/src/lib.rs
+++ b/substrate/bin/node-template/runtime/src/lib.rs
@@ -235,7 +235,7 @@ impl transaction_payment::Trait for Runtime {
 
 impl sudo::Trait for Runtime {
 	type Event = Event;
-	type Proposal = Call;
+	type Call = Call;
 }
 
 /// Used for the module template in `./template.rs`
diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index d80986c0df8ce6854c668ab6f6919bab89ac145c..1807952af6171924b193e0153e5070ae6b735eb0 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -82,8 +82,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
 	// and set impl_version to 0. If only runtime
 	// implementation changes and behavior does not, then leave spec_version as
 	// is and increment impl_version.
-	spec_version: 219,
-	impl_version: 1,
+	spec_version: 220,
+	impl_version: 0,
 	apis: RUNTIME_API_VERSIONS,
 };
 
@@ -442,7 +442,7 @@ impl pallet_contracts::Trait for Runtime {
 
 impl pallet_sudo::Trait for Runtime {
 	type Event = Event;
-	type Proposal = Call;
+	type Call = Call;
 }
 
 /// A runtime transaction submitter.
diff --git a/substrate/frame/sudo/src/lib.rs b/substrate/frame/sudo/src/lib.rs
index e69840e1586670d26e543468876b41524d38c288..8ee09ba223ab1a393fadb9ff41056dbac21c756b 100644
--- a/substrate/frame/sudo/src/lib.rs
+++ b/substrate/frame/sudo/src/lib.rs
@@ -90,8 +90,8 @@ use sp_runtime::{traits::{StaticLookup, Dispatchable}, DispatchError};
 
 use frame_support::{
 	Parameter, decl_module, decl_event, decl_storage, decl_error, ensure,
-	weights::SimpleDispatchInfo,
 };
+use frame_support::weights::{GetDispatchInfo, FunctionOf};
 use frame_system::{self as system, ensure_signed};
 
 pub trait Trait: frame_system::Trait {
@@ -99,7 +99,7 @@ pub trait Trait: frame_system::Trait {
 	type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
 
 	/// A sudo-able call.
-	type Proposal: Parameter + Dispatchable<Origin=Self::Origin>;
+	type Call: Parameter + Dispatchable<Origin=Self::Origin> + GetDispatchInfo;
 }
 
 decl_module! {
@@ -117,15 +117,19 @@ decl_module! {
 		/// - O(1).
 		/// - Limited storage reads.
 		/// - One DB write (event).
-		/// - Unknown weight of derivative `proposal` execution.
+		/// - Weight of derivative `call` execution + 10,000.
 		/// # </weight>
-		#[weight = SimpleDispatchInfo::FixedNormal(50_000)]
-		fn sudo(origin, proposal: Box<T::Proposal>) {
+		#[weight = FunctionOf(
+			|args: (&Box<<T as Trait>::Call>,)| args.0.get_dispatch_info().weight + 10_000, 
+			|args: (&Box<<T as Trait>::Call>,)| args.0.get_dispatch_info().class,
+			true
+		)]
+		fn sudo(origin, call: Box<<T as Trait>::Call>) {
 			// This is a public call, so we ensure that the origin is some signed account.
 			let sender = ensure_signed(origin)?;
 			ensure!(sender == Self::key(), Error::<T>::RequireSudo);
 
-			let res = match proposal.dispatch(frame_system::RawOrigin::Root.into()) {
+			let res = match call.dispatch(frame_system::RawOrigin::Root.into()) {
 				Ok(_) => true,
 				Err(e) => {
 					let e: DispatchError = e.into();
@@ -165,17 +169,25 @@ decl_module! {
 		/// - O(1).
 		/// - Limited storage reads.
 		/// - One DB write (event).
-		/// - Unknown weight of derivative `proposal` execution.
+		/// - Weight of derivative `call` execution + 10,000.
 		/// # </weight>
-		#[weight = SimpleDispatchInfo::FixedOperational(0)]
-		fn sudo_as(origin, who: <T::Lookup as StaticLookup>::Source, proposal: Box<T::Proposal>) {
+		#[weight = FunctionOf(
+			|args: (&<T::Lookup as StaticLookup>::Source, &Box<<T as Trait>::Call>,)| {
+				args.1.get_dispatch_info().weight + 10_000
+			}, 
+			|args: (&<T::Lookup as StaticLookup>::Source, &Box<<T as Trait>::Call>,)| {
+				args.1.get_dispatch_info().class
+			},
+			true
+		)]
+		fn sudo_as(origin, who: <T::Lookup as StaticLookup>::Source, call: Box<<T as Trait>::Call>) {
 			// This is a public call, so we ensure that the origin is some signed account.
 			let sender = ensure_signed(origin)?;
 			ensure!(sender == Self::key(), Error::<T>::RequireSudo);
 
 			let who = T::Lookup::lookup(who)?;
 
-			let res = match proposal.dispatch(frame_system::RawOrigin::Signed(who).into()) {
+			let res = match call.dispatch(frame_system::RawOrigin::Signed(who).into()) {
 				Ok(_) => true,
 				Err(e) => {
 					let e: DispatchError = e.into();
diff --git a/substrate/frame/support/src/weights.rs b/substrate/frame/support/src/weights.rs
index 60f0d4a8b2b64b91edb4658295f1760993b5887d..c46cca683ba934172c08a3b5437d1a7e9457d077 100644
--- a/substrate/frame/support/src/weights.rs
+++ b/substrate/frame/support/src/weights.rs
@@ -234,32 +234,61 @@ impl SimpleDispatchInfo {
 /// A struct to represent a weight which is a function of the input arguments. The given items have
 /// the following types:
 ///
-/// - `F`: a closure with the same argument list as the dispatched, wrapped in a tuple.
-/// - `DispatchClass`: class of the dispatch.
-/// - `bool`: whether this dispatch pays fee or not.
-pub struct FunctionOf<F>(pub F, pub DispatchClass, pub bool);
+/// - `WD`: a raw `Weight` value or a closure that returns a `Weight` with the same
+///   argument list as the dispatched, wrapped in a tuple.
+/// - `CD`: a raw `DispatchClass` value or a closure that returns a `DispatchClass`
+///   with the same argument list as the dispatched, wrapped in a tuple.
+/// - `PF`: a `bool` for whether this dispatch pays fee or not or a closure that
+///   returns a bool with the same argument list as the dispatched, wrapped in a tuple.
+pub struct FunctionOf<WD, CD, PF>(pub WD, pub CD, pub PF);
+
+// `WeighData` as a raw value
+impl<Args, CD, PF> WeighData<Args> for FunctionOf<Weight, CD, PF> {
+	fn weigh_data(&self, _: Args) -> Weight {
+		self.0
+	}
+}
 
-impl<Args, F> WeighData<Args> for FunctionOf<F>
-where
-	F : Fn(Args) -> Weight
+// `WeighData` as a closure
+impl<Args, WD, CD, PF> WeighData<Args> for FunctionOf<WD, CD, PF> where
+	WD : Fn(Args) -> Weight
 {
 	fn weigh_data(&self, args: Args) -> Weight {
 		(self.0)(args)
 	}
 }
 
-impl<Args, F> ClassifyDispatch<Args> for FunctionOf<F> {
+// `ClassifyDispatch` as a raw value
+impl<Args, WD, PF> ClassifyDispatch<Args> for FunctionOf<WD, DispatchClass, PF> {
 	fn classify_dispatch(&self, _: Args) -> DispatchClass {
-		self.1.clone()
+		self.1
 	}
 }
 
-impl<T, F> PaysFee<T> for FunctionOf<F> {
-	fn pays_fee(&self, _: T) -> bool {
+// `ClassifyDispatch` as a raw value
+impl<Args, WD, CD, PF> ClassifyDispatch<Args> for FunctionOf<WD, CD, PF> where
+	CD : Fn(Args) -> DispatchClass
+{
+	fn classify_dispatch(&self, args: Args) -> DispatchClass {
+		(self.1)(args)
+	}
+}
+
+// `PaysFee` as a raw value
+impl<Args, WD, CD> PaysFee<Args> for FunctionOf<WD, CD, bool> {
+	fn pays_fee(&self, _: Args) -> bool {
 		self.2
 	}
 }
 
+// `PaysFee` as a closure
+impl<Args, WD, CD, PF> PaysFee<Args> for FunctionOf<WD, CD, PF> where
+	PF : Fn(Args) -> bool
+{
+	fn pays_fee(&self, args: Args) -> bool {
+		(self.2)(args)
+	}
+}
 
 /// Implementation for unchecked extrinsic.
 impl<Address, Call, Signature, Extra> GetDispatchInfo