diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock
index 82fabb30cf33519dca3a3deb36d5b1d083f49001..69f0f3906bf69dd555e9a59b3349b4adf2fd20f5 100644
--- a/substrate/Cargo.lock
+++ b/substrate/Cargo.lock
@@ -4077,6 +4077,7 @@ dependencies = [
  "pallet-contracts-primitives",
  "pallet-randomness-collective-flip",
  "pallet-timestamp",
+ "pallet-transaction-payment",
  "parity-scale-codec",
  "parity-wasm 0.41.0",
  "pwasm-utils",
diff --git a/substrate/bin/node/cli/src/chain_spec.rs b/substrate/bin/node/cli/src/chain_spec.rs
index 6d67c61381270ef5923ab9955ec5ee9bc3cf3be9..461474038b8b839f227a1356f29bec69d0a6beb3 100644
--- a/substrate/bin/node/cli/src/chain_spec.rs
+++ b/substrate/bin/node/cli/src/chain_spec.rs
@@ -292,7 +292,6 @@ pub fn testnet_genesis(
 				enable_println, // this should only be enabled on development chains
 				..Default::default()
 			},
-			gas_price: 1 * MILLICENTS,
 		}),
 		pallet_sudo: Some(SudoConfig {
 			key: root_key,
diff --git a/substrate/bin/node/cli/src/factory_impl.rs b/substrate/bin/node/cli/src/factory_impl.rs
index 1d1eabe29cbfb12ca43663be00b0969e852a30d9..bc7653538247f05c33381516be2a756463dc3c2a 100644
--- a/substrate/bin/node/cli/src/factory_impl.rs
+++ b/substrate/bin/node/cli/src/factory_impl.rs
@@ -57,7 +57,6 @@ impl<Number> FactoryState<Number> {
 			frame_system::CheckNonce::from(index),
 			frame_system::CheckWeight::new(),
 			pallet_transaction_payment::ChargeTransactionPayment::from(0),
-			Default::default(),
 		)
 	}
 }
@@ -122,7 +121,7 @@ impl RuntimeAdapter for FactoryState<Number> {
 					(*amount).into()
 				)
 			)
-		}, key, (version, genesis_hash.clone(), prior_block_hash.clone(), (), (), (), ()))
+		}, key, (version, genesis_hash.clone(), prior_block_hash.clone(), (), (), ()))
 	}
 
 	fn inherent_extrinsics(&self) -> InherentData {
diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs
index 0acd553ea0127ff849eb47f3841929c1941eccaa..1ccc6e5ec48506ad107b0cdeb17f38cb99a046b2 100644
--- a/substrate/bin/node/cli/src/service.rs
+++ b/substrate/bin/node/cli/src/service.rs
@@ -633,12 +633,11 @@ mod tests {
 					check_nonce,
 					check_weight,
 					payment,
-					Default::default(),
 				);
 				let raw_payload = SignedPayload::from_raw(
 					function,
 					extra,
-					(version, genesis_hash, genesis_hash, (), (), (), ())
+					(version, genesis_hash, genesis_hash, (), (), ())
 				);
 				let signature = raw_payload.using_encoded(|payload|	{
 					signer.sign(payload)
diff --git a/substrate/bin/node/executor/tests/basic.rs b/substrate/bin/node/executor/tests/basic.rs
index 151b7c54f67e276f3404dd75af8299eab9a81961..387a7e9200dd511b98028ee39693e776687a4aed 100644
--- a/substrate/bin/node/executor/tests/basic.rs
+++ b/substrate/bin/node/executor/tests/basic.rs
@@ -606,13 +606,18 @@ fn deploying_wasm_contract_should_work() {
 			CheckedExtrinsic {
 				signed: Some((charlie(), signed_extra(0, 0))),
 				function: Call::Contracts(
-					pallet_contracts::Call::put_code::<Runtime>(10_000, transfer_code)
+					pallet_contracts::Call::put_code::<Runtime>(transfer_code)
 				),
 			},
 			CheckedExtrinsic {
 				signed: Some((charlie(), signed_extra(1, 0))),
 				function: Call::Contracts(
-					pallet_contracts::Call::instantiate::<Runtime>(1 * DOLLARS, 10_000, transfer_ch, Vec::new())
+					pallet_contracts::Call::instantiate::<Runtime>(
+						1 * DOLLARS,
+						500_000_000,
+						transfer_ch,
+						Vec::new()
+					)
 				),
 			},
 			CheckedExtrinsic {
@@ -621,7 +626,7 @@ fn deploying_wasm_contract_should_work() {
 					pallet_contracts::Call::call::<Runtime>(
 						pallet_indices::address::Address::Id(addr.clone()),
 						10,
-						10_000,
+						500_000_000,
 						vec![0x00, 0x01, 0x02, 0x03]
 					)
 				),
diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index d225d3e478033556ec22ac49899ada657fe39b8c..7c39c72bd4a65878127260d405148328401801e9 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -73,7 +73,6 @@ use constants::{time::*, currency::*};
 #[cfg(feature = "std")]
 include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
 
-
 /// Runtime version.
 pub const VERSION: RuntimeVersion = RuntimeVersion {
 	spec_name: create_runtime_str!("node"),
@@ -460,9 +459,6 @@ impl pallet_treasury::Trait for Runtime {
 }
 
 parameter_types! {
-	pub const ContractTransactionBaseFee: Balance = 1 * CENTS;
-	pub const ContractTransactionByteFee: Balance = 10 * MILLICENTS;
-	pub const ContractFee: Balance = 1 * CENTS;
 	pub const TombstoneDeposit: Balance = 1 * DOLLARS;
 	pub const RentByteFee: Balance = 1 * DOLLARS;
 	pub const RentDepositOffset: Balance = 1000 * DOLLARS;
@@ -470,15 +466,12 @@ parameter_types! {
 }
 
 impl pallet_contracts::Trait for Runtime {
-	type Currency = Balances;
 	type Time = Timestamp;
 	type Randomness = RandomnessCollectiveFlip;
 	type Call = Call;
 	type Event = Event;
 	type DetermineContractAddress = pallet_contracts::SimpleAddressDeterminer<Runtime>;
-	type ComputeDispatchFee = pallet_contracts::DefaultDispatchFeeComputor<Runtime>;
 	type TrieIdGenerator = pallet_contracts::TrieIdFromParentCounter<Runtime>;
-	type GasPayment = ();
 	type RentPayment = ();
 	type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap;
 	type TombstoneDeposit = TombstoneDeposit;
@@ -486,14 +479,8 @@ impl pallet_contracts::Trait for Runtime {
 	type RentByteFee = RentByteFee;
 	type RentDepositOffset = RentDepositOffset;
 	type SurchargeReward = SurchargeReward;
-	type TransactionBaseFee = ContractTransactionBaseFee;
-	type TransactionByteFee = ContractTransactionByteFee;
-	type ContractFee = ContractFee;
-	type CallBaseFee = pallet_contracts::DefaultCallBaseFee;
-	type InstantiateBaseFee = pallet_contracts::DefaultInstantiateBaseFee;
 	type MaxDepth = pallet_contracts::DefaultMaxDepth;
 	type MaxValueSize = pallet_contracts::DefaultMaxValueSize;
-	type BlockGasLimit = pallet_contracts::DefaultBlockGasLimit;
 }
 
 impl pallet_sudo::Trait for Runtime {
@@ -536,7 +523,6 @@ impl<LocalCall> frame_system::offchain::CreateSignedTransaction<LocalCall> for R
 			frame_system::CheckNonce::<Runtime>::from(nonce),
 			frame_system::CheckWeight::<Runtime>::new(),
 			pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
-			Default::default(),
 		);
 		let raw_payload = SignedPayload::new(call, extra).map_err(|e| {
 			debug::warn!("Unable to create signed payload: {:?}", e);
@@ -692,7 +678,7 @@ construct_runtime!(
 		FinalityTracker: pallet_finality_tracker::{Module, Call, Inherent},
 		Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event},
 		Treasury: pallet_treasury::{Module, Call, Storage, Config, Event<T>},
-		Contracts: pallet_contracts::{Module, Call, Config<T>, Storage, Event<T>},
+		Contracts: pallet_contracts::{Module, Call, Config, Storage, Event<T>},
 		Sudo: pallet_sudo::{Module, Call, Config<T>, Storage, Event<T>},
 		ImOnline: pallet_im_online::{Module, Call, Storage, Event<T>, ValidateUnsigned, Config<T>},
 		AuthorityDiscovery: pallet_authority_discovery::{Module, Call, Config},
@@ -724,7 +710,6 @@ pub type SignedExtra = (
 	frame_system::CheckNonce<Runtime>,
 	frame_system::CheckWeight<Runtime>,
 	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
-	pallet_contracts::CheckBlockGasLimit<Runtime>,
 );
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
diff --git a/substrate/bin/node/testing/src/genesis.rs b/substrate/bin/node/testing/src/genesis.rs
index 8a57010770f3dedf9795e0da462455943fb6f74d..0f72d2c5471bd835be225a9d046d02867ca6fbc4 100644
--- a/substrate/bin/node/testing/src/genesis.rs
+++ b/substrate/bin/node/testing/src/genesis.rs
@@ -97,7 +97,6 @@ pub fn config_endowed(
 		}),
 		pallet_contracts: Some(ContractsConfig {
 			current_schedule: Default::default(),
-			gas_price: 1 * MILLICENTS,
 		}),
 		pallet_babe: Some(Default::default()),
 		pallet_grandpa: Some(GrandpaConfig {
diff --git a/substrate/bin/node/testing/src/keyring.rs b/substrate/bin/node/testing/src/keyring.rs
index 6b0d06875d6924a0715f74334390193736009bd0..5eebc09f4b7af4a3c7be434f53b2baa3586d705a 100644
--- a/substrate/bin/node/testing/src/keyring.rs
+++ b/substrate/bin/node/testing/src/keyring.rs
@@ -74,7 +74,6 @@ pub fn signed_extra(nonce: Index, extra_fee: Balance) -> SignedExtra {
 		frame_system::CheckNonce::from(nonce),
 		frame_system::CheckWeight::new(),
 		pallet_transaction_payment::ChargeTransactionPayment::from(extra_fee),
-		Default::default(),
 	)
 }
 
diff --git a/substrate/bin/utils/subkey/src/main.rs b/substrate/bin/utils/subkey/src/main.rs
index 2d9302bf8c72e233e7b232fce22640bf4dca71e5..22706ebd822daea88f34693e5ed475bad8ecda27 100644
--- a/substrate/bin/utils/subkey/src/main.rs
+++ b/substrate/bin/utils/subkey/src/main.rs
@@ -708,7 +708,6 @@ fn create_extrinsic<C: Crypto>(
 			frame_system::CheckNonce::<Runtime>::from(i),
 			frame_system::CheckWeight::<Runtime>::new(),
 			pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(f),
-			Default::default(),
 		)
 	};
 	let raw_payload = SignedPayload::from_raw(
@@ -721,7 +720,6 @@ fn create_extrinsic<C: Crypto>(
 			(),
 			(),
 			(),
-			(),
 		),
 	);
 	let signature = raw_payload.using_encoded(|payload| signer.sign(payload)).into_runtime();
diff --git a/substrate/frame/contracts/Cargo.toml b/substrate/frame/contracts/Cargo.toml
index 42dba7299de0fa7805a65bae6450fc09a0bc7f6a..e26efe5b690f1be4c83327b637dfb47c281b8107 100644
--- a/substrate/frame/contracts/Cargo.toml
+++ b/substrate/frame/contracts/Cargo.toml
@@ -25,6 +25,7 @@ sp-sandbox = { version = "0.8.0-dev", default-features = false, path = "../../pr
 frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" }
 pallet-contracts-primitives = { version = "2.0.0-dev", default-features = false, path = "common" }
+pallet-transaction-payment = { version = "2.0.0-dev", default-features = false, path = "../transaction-payment" }
 
 [dev-dependencies]
 wabt = "0.9.2"
diff --git a/substrate/frame/contracts/rpc/src/lib.rs b/substrate/frame/contracts/rpc/src/lib.rs
index 52dddb177bbc74538f869419d20beebd1cc2b916..53e8d938703c866de09d1234e2a34ebb51122e09 100644
--- a/substrate/frame/contracts/rpc/src/lib.rs
+++ b/substrate/frame/contracts/rpc/src/lib.rs
@@ -46,9 +46,10 @@ const CONTRACT_IS_A_TOMBSTONE: i64 = 3;
 /// This value is used to set the upper bound for maximal contract calls to
 /// prevent blocking the RPC for too long.
 ///
-/// Based on W3F research spreadsheet:
-/// https://docs.google.com/spreadsheets/d/1h0RqncdqiWI4KgxO0z9JIpZEJESXjX_ZCK6LFX6veDo/view
-const GAS_PER_SECOND: u64 = 1_000_000_000;
+/// As 1 gas is equal to 1 weight we base this on the conducted benchmarks which
+/// determined runtime weights:
+/// https://github.com/paritytech/substrate/pull/5446
+const GAS_PER_SECOND: u64 = 1_000_000_000_000;
 
 /// A private newtype for converting `ContractAccessError` into an RPC error.
 struct ContractAccessError(pallet_contracts_primitives::ContractAccessError);
diff --git a/substrate/frame/contracts/src/exec.rs b/substrate/frame/contracts/src/exec.rs
index 402622331d0ecc33ae66a8920b0568aaad099dd2..9cc1c50260db9fed6581217e08107a61d4aafe6c 100644
--- a/substrate/frame/contracts/src/exec.rs
+++ b/substrate/frame/contracts/src/exec.rs
@@ -17,7 +17,7 @@
 use super::{CodeHash, Config, ContractAddressFor, Event, RawEvent, Trait,
 	TrieId, BalanceOf, ContractInfo};
 use crate::account_db::{AccountDb, DirectAccountDb, OverlayAccountDb};
-use crate::gas::{Gas, GasMeter, Token, approx_gas_for_balance};
+use crate::gas::{Gas, GasMeter, Token};
 use crate::rent;
 
 use sp_std::prelude::*;
@@ -203,6 +203,9 @@ pub trait Ext {
 	///
 	/// Returns `None` if the value doesn't exist.
 	fn get_runtime_storage(&self, key: &[u8]) -> Option<Vec<u8>>;
+
+	/// Returns the price of one weight unit.
+	fn get_weight_price(&self) -> BalanceOf<Self::T>;
 }
 
 /// Loader is a companion of the `Vm` trait. It loads an appropriate abstract
@@ -605,21 +608,19 @@ pub enum TransferFeeKind {
 
 #[cfg_attr(test, derive(Debug, PartialEq, Eq))]
 #[derive(Copy, Clone)]
-pub struct TransferFeeToken<Balance> {
+pub struct TransferFeeToken {
 	kind: TransferFeeKind,
-	gas_price: Balance,
 }
 
-impl<T: Trait> Token<T> for TransferFeeToken<BalanceOf<T>> {
+impl<T: Trait> Token<T> for TransferFeeToken {
 	type Metadata = Config<T>;
 
 	#[inline]
 	fn calculate_amount(&self, metadata: &Config<T>) -> Gas {
-		let balance_fee = match self.kind {
-			TransferFeeKind::ContractInstantiate => metadata.contract_account_instantiate_fee,
-			TransferFeeKind::Transfer => return metadata.schedule.transfer_cost,
-		};
-		approx_gas_for_balance(self.gas_price, balance_fee)
+		match self.kind {
+			TransferFeeKind::ContractInstantiate => metadata.schedule.instantiate_cost,
+			TransferFeeKind::Transfer => metadata.schedule.transfer_cost,
+		}
 	}
 }
 
@@ -668,7 +669,6 @@ fn transfer<'a, T: Trait, V: Vm<T>, L: Loader<T>>(
 		};
 		TransferFeeToken {
 			kind,
-			gas_price: gas_meter.gas_price(),
 		}
 	};
 
@@ -868,6 +868,13 @@ where
 	fn get_runtime_storage(&self, key: &[u8]) -> Option<Vec<u8>> {
 		unhashed::get_raw(&key)
 	}
+
+	fn get_weight_price(&self) -> BalanceOf<Self::T> {
+		use pallet_transaction_payment::Module as Payment;
+		use sp_runtime::SaturatedConversion;
+		let price = Payment::<T>::weight_to_fee_with_adjustment::<u128>(1);
+		price.saturated_into()
+	}
 }
 
 /// These tests exercise the executive layer.
@@ -889,6 +896,7 @@ mod tests {
 	use crate::{
 		account_db::AccountDb, gas::GasMeter, tests::{ExtBuilder, Test},
 		exec::{ExecReturnValue, ExecError, STATUS_SUCCESS}, CodeHash, Config,
+		gas::Gas,
 	};
 	use std::{cell::RefCell, rc::Rc, collections::HashMap, marker::PhantomData};
 	use assert_matches::assert_matches;
@@ -898,6 +906,8 @@ mod tests {
 	const BOB: u64 = 2;
 	const CHARLIE: u64 = 3;
 
+	const GAS_LIMIT: Gas = 10_000_000_000;
+
 	impl<'a, T, V, L> ExecutionContext<'a, T, V, L>
 		where T: crate::Trait
 	{
@@ -1003,7 +1013,7 @@ mod tests {
 	#[test]
 	fn it_works() {
 		let value = Default::default();
-		let mut gas_meter = GasMeter::<Test>::with_limit(10000, 1);
+		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
 		let data = vec![];
 
 		let vm = MockVm::new();
@@ -1044,7 +1054,7 @@ mod tests {
 			ctx.overlay.set_balance(&origin, 100);
 			ctx.overlay.set_balance(&dest, 0);
 
-			let mut gas_meter = GasMeter::<Test>::with_limit(1000, 1);
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
 
 			let result = ctx.call(dest, 0, &mut gas_meter, vec![]);
 			assert_matches!(result, Ok(_));
@@ -1064,7 +1074,7 @@ mod tests {
 
 			ctx.overlay.set_balance(&origin, 100);
 
-			let mut gas_meter = GasMeter::<Test>::with_limit(1000, 1);
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
 
 			let result = ctx.instantiate(1, &mut gas_meter, &code, vec![]);
 			assert_matches!(result, Ok(_));
@@ -1093,7 +1103,7 @@ mod tests {
 			let output = ctx.call(
 				dest,
 				55,
-				&mut GasMeter::<Test>::with_limit(1000, 1),
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				vec![],
 			).unwrap();
 
@@ -1126,7 +1136,7 @@ mod tests {
 			let output = ctx.call(
 				dest,
 				55,
-				&mut GasMeter::<Test>::with_limit(1000, 1),
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				vec![],
 			).unwrap();
 
@@ -1152,7 +1162,7 @@ mod tests {
 			ctx.overlay.set_balance(&origin, 100);
 			ctx.overlay.set_balance(&dest, 0);
 
-			let mut gas_meter = GasMeter::<Test>::with_limit(1000, 1);
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
 
 			let result = ctx.call(dest, 50, &mut gas_meter, vec![]);
 			assert_matches!(result, Ok(_));
@@ -1163,7 +1173,6 @@ mod tests {
 				ExecFeeToken::Call,
 				TransferFeeToken {
 					kind: TransferFeeKind::Transfer,
-					gas_price: 1u64
 				},
 			);
 		});
@@ -1178,7 +1187,7 @@ mod tests {
 			ctx.overlay.set_balance(&origin, 100);
 			ctx.overlay.set_balance(&dest, 15);
 
-			let mut gas_meter = GasMeter::<Test>::with_limit(1000, 1);
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
 
 			let result = ctx.call(dest, 50, &mut gas_meter, vec![]);
 			assert_matches!(result, Ok(_));
@@ -1189,7 +1198,6 @@ mod tests {
 				ExecFeeToken::Call,
 				TransferFeeToken {
 					kind: TransferFeeKind::Transfer,
-					gas_price: 1u64
 				},
 			);
 		});
@@ -1207,7 +1215,7 @@ mod tests {
 			ctx.overlay.set_balance(&origin, 100);
 			ctx.overlay.set_balance(&dest, 15);
 
-			let mut gas_meter = GasMeter::<Test>::with_limit(1000, 1);
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
 
 			let result = ctx.instantiate(50, &mut gas_meter, &code, vec![]);
 			assert_matches!(result, Ok(_));
@@ -1218,7 +1226,6 @@ mod tests {
 				ExecFeeToken::Instantiate,
 				TransferFeeToken {
 					kind: TransferFeeKind::ContractInstantiate,
-					gas_price: 1u64
 				},
 			);
 		});
@@ -1242,7 +1249,7 @@ mod tests {
 			let result = ctx.call(
 				dest,
 				100,
-				&mut GasMeter::<Test>::with_limit(1000, 1),
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				vec![],
 			);
 
@@ -1279,7 +1286,7 @@ mod tests {
 			let result = ctx.call(
 				dest,
 				0,
-				&mut GasMeter::<Test>::with_limit(1000, 1),
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				vec![],
 			);
 
@@ -1310,7 +1317,7 @@ mod tests {
 			let result = ctx.call(
 				dest,
 				0,
-				&mut GasMeter::<Test>::with_limit(1000, 1),
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				vec![],
 			);
 
@@ -1338,7 +1345,7 @@ mod tests {
 			let result = ctx.call(
 				BOB,
 				0,
-				&mut GasMeter::<Test>::with_limit(10000, 1),
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				vec![1, 2, 3, 4],
 			);
 			assert_matches!(result, Ok(_));
@@ -1363,7 +1370,7 @@ mod tests {
 
 			let result = ctx.instantiate(
 				1,
-				&mut GasMeter::<Test>::with_limit(10000, 1),
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&input_data_ch,
 				vec![1, 2, 3, 4],
 			);
@@ -1413,7 +1420,7 @@ mod tests {
 			let result = ctx.call(
 				BOB,
 				value,
-				&mut GasMeter::<Test>::with_limit(100000, 1),
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				vec![],
 			);
 
@@ -1459,7 +1466,7 @@ mod tests {
 			let result = ctx.call(
 				dest,
 				0,
-				&mut GasMeter::<Test>::with_limit(10000, 1),
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				vec![],
 			);
 
@@ -1500,7 +1507,7 @@ mod tests {
 			let result = ctx.call(
 				BOB,
 				0,
-				&mut GasMeter::<Test>::with_limit(10000, 1),
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				vec![],
 			);
 
@@ -1522,7 +1529,7 @@ mod tests {
 			assert_matches!(
 				ctx.instantiate(
 					0, // <- zero endowment
-					&mut GasMeter::<Test>::with_limit(10000, 1),
+					&mut GasMeter::<Test>::new(GAS_LIMIT),
 					&dummy_ch,
 					vec![],
 				),
@@ -1548,7 +1555,7 @@ mod tests {
 			let instantiated_contract_address = assert_matches!(
 				ctx.instantiate(
 					100,
-					&mut GasMeter::<Test>::with_limit(10000, 1),
+					&mut GasMeter::<Test>::new(GAS_LIMIT),
 					&dummy_ch,
 					vec![],
 				),
@@ -1588,7 +1595,7 @@ mod tests {
 			let instantiated_contract_address = assert_matches!(
 				ctx.instantiate(
 					100,
-					&mut GasMeter::<Test>::with_limit(10000, 1),
+					&mut GasMeter::<Test>::new(GAS_LIMIT),
 					&dummy_ch,
 					vec![],
 				),
@@ -1633,7 +1640,7 @@ mod tests {
 			ctx.overlay.instantiate_contract(&BOB, instantiator_ch).unwrap();
 
 			assert_matches!(
-				ctx.call(BOB, 20, &mut GasMeter::<Test>::with_limit(1000, 1), vec![]),
+				ctx.call(BOB, 20, &mut GasMeter::<Test>::new(GAS_LIMIT), vec![]),
 				Ok(_)
 			);
 
@@ -1693,7 +1700,7 @@ mod tests {
 			ctx.overlay.instantiate_contract(&BOB, instantiator_ch).unwrap();
 
 			assert_matches!(
-				ctx.call(BOB, 20, &mut GasMeter::<Test>::with_limit(1000, 1), vec![]),
+				ctx.call(BOB, 20, &mut GasMeter::<Test>::new(GAS_LIMIT), vec![]),
 				Ok(_)
 			);
 
@@ -1730,7 +1737,7 @@ mod tests {
 				assert_matches!(
 					ctx.instantiate(
 						100,
-						&mut GasMeter::<Test>::with_limit(10000, 1),
+						&mut GasMeter::<Test>::new(GAS_LIMIT),
 						&terminate_ch,
 						vec![],
 					),
@@ -1766,7 +1773,7 @@ mod tests {
 
 			let result = ctx.instantiate(
 				1,
-				&mut GasMeter::<Test>::with_limit(10000, 1),
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
 				&rent_allowance_ch,
 				vec![],
 			);
diff --git a/substrate/frame/contracts/src/gas.rs b/substrate/frame/contracts/src/gas.rs
index 362f15f3aae795ef44b346285de79cd557291a23..38f231c008f8b635c10d67102ecd0c2bf3e703c4 100644
--- a/substrate/frame/contracts/src/gas.rs
+++ b/substrate/frame/contracts/src/gas.rs
@@ -14,22 +14,18 @@
 // You should have received a copy of the GNU General Public License
 // along with Substrate. If not, see <http://www.gnu.org/licenses/>.
 
-use crate::{GasSpent, Module, Trait, BalanceOf, NegativeImbalanceOf};
-use sp_std::convert::TryFrom;
-use sp_runtime::traits::{
-	CheckedMul, Zero, SaturatedConversion, AtLeast32Bit, UniqueSaturatedInto,
-};
-use frame_support::{
-	traits::{Currency, ExistenceRequirement, Imbalance, OnUnbalanced, WithdrawReason}, StorageValue,
-	dispatch::DispatchError,
+use crate::Trait;
+use sp_std::marker::PhantomData;
+use sp_runtime::traits::Zero;
+use frame_support::dispatch::{
+	DispatchError, DispatchResultWithPostInfo, PostDispatchInfo, DispatchErrorWithPostInfo,
 };
 
 #[cfg(test)]
 use std::{any::Any, fmt::Debug};
 
-// Gas units are chosen to be represented by u64 so that gas metering instructions can operate on
-// them efficiently.
-pub type Gas = u64;
+// Gas is essentially the same as weight. It is a 1 to 1 correspondence.
+pub type Gas = frame_support::weights::Weight;
 
 #[must_use]
 #[derive(Debug, PartialEq, Eq)]
@@ -88,20 +84,19 @@ pub struct ErasedToken {
 }
 
 pub struct GasMeter<T: Trait> {
-	limit: Gas,
+	gas_limit: Gas,
 	/// Amount of gas left from initial gas limit. Can reach zero.
 	gas_left: Gas,
-	gas_price: BalanceOf<T>,
-
+	_phantom: PhantomData<T>,
 	#[cfg(test)]
 	tokens: Vec<ErasedToken>,
 }
 impl<T: Trait> GasMeter<T> {
-	pub fn with_limit(gas_limit: Gas, gas_price: BalanceOf<T>) -> GasMeter<T> {
+	pub fn new(gas_limit: Gas) -> Self {
 		GasMeter {
-			limit: gas_limit,
+			gas_limit,
 			gas_left: gas_limit,
-			gas_price,
+			_phantom: PhantomData,
 			#[cfg(test)]
 			tokens: Vec::new(),
 		}
@@ -147,6 +142,14 @@ impl<T: Trait> GasMeter<T> {
 		}
 	}
 
+	// Account for not fully used gas.
+	//
+	// This can be used after dispatching a runtime call to refund gas that was not
+	// used by the dispatchable.
+	pub fn refund(&mut self, gas: Gas) {
+		self.gas_left = self.gas_left.saturating_add(gas).max(self.gas_limit);
+	}
+
 	/// Allocate some amount of gas and perform some work with
 	/// a newly created nested gas meter.
 	///
@@ -165,7 +168,7 @@ impl<T: Trait> GasMeter<T> {
 			f(None)
 		} else {
 			self.gas_left = self.gas_left - amount;
-			let mut nested = GasMeter::with_limit(amount, self.gas_price);
+			let mut nested = GasMeter::new(amount);
 
 			let r = f(Some(&mut nested));
 
@@ -175,8 +178,9 @@ impl<T: Trait> GasMeter<T> {
 		}
 	}
 
-	pub fn gas_price(&self) -> BalanceOf<T> {
-		self.gas_price
+	/// Returns how much gas left from the initial budget.
+	fn gas_spent(&self) -> Gas {
+		self.gas_limit - self.gas_left
 	}
 
 	/// Returns how much gas left from the initial budget.
@@ -184,9 +188,17 @@ impl<T: Trait> GasMeter<T> {
 		self.gas_left
 	}
 
-	/// Returns how much gas was spent.
-	fn spent(&self) -> Gas {
-		self.limit - self.gas_left
+	/// Turn this GasMeter into a DispatchResult that contains the actually used gas.
+	pub fn into_dispatch_result<R, E>(self, result: Result<R, E>) -> DispatchResultWithPostInfo where
+		E: Into<DispatchError>,
+	{
+		let post_info = PostDispatchInfo {
+			actual_weight: Some(self.gas_spent()),
+		};
+
+		result
+			.map(|_| post_info)
+			.map_err(|e| DispatchErrorWithPostInfo { post_info, error: e.into() })
 	}
 
 	#[cfg(test)]
@@ -195,68 +207,6 @@ impl<T: Trait> GasMeter<T> {
 	}
 }
 
-/// Buy the given amount of gas.
-///
-/// Cost is calculated by multiplying the gas cost (taken from the storage) by the `gas_limit`.
-/// The funds are deducted from `transactor`.
-pub fn buy_gas<T: Trait>(
-	transactor: &T::AccountId,
-	gas_limit: Gas,
-) -> Result<(GasMeter<T>, NegativeImbalanceOf<T>), DispatchError> {
-	// Buy the specified amount of gas.
-	let gas_price = <Module<T>>::gas_price();
-	let cost = if gas_price.is_zero() {
-		<BalanceOf<T>>::zero()
-	} else {
-		<BalanceOf<T> as TryFrom<Gas>>::try_from(gas_limit).ok()
-			.and_then(|gas_limit| gas_price.checked_mul(&gas_limit))
-			.ok_or("overflow multiplying gas limit by price")?
-	};
-
-	let imbalance = T::Currency::withdraw(
-		transactor,
-		cost,
-		WithdrawReason::Fee.into(),
-		ExistenceRequirement::KeepAlive
-	)?;
-
-	Ok((GasMeter::with_limit(gas_limit, gas_price), imbalance))
-}
-
-/// Refund the unused gas.
-pub fn refund_unused_gas<T: Trait>(
-	transactor: &T::AccountId,
-	gas_meter: GasMeter<T>,
-	imbalance: NegativeImbalanceOf<T>,
-) {
-	let gas_spent = gas_meter.spent();
-	let gas_left = gas_meter.gas_left();
-
-	// Increase total spent gas.
-	// This cannot overflow, since `gas_spent` is never greater than `block_gas_limit`, which
-	// also has Gas type.
-	GasSpent::mutate(|block_gas_spent| *block_gas_spent += gas_spent);
-
-	// Refund gas left by the price it was bought at.
-	let refund = gas_meter.gas_price * gas_left.unique_saturated_into();
-	let refund_imbalance = T::Currency::deposit_creating(transactor, refund);
-	if let Ok(imbalance) = imbalance.offset(refund_imbalance) {
-		T::GasPayment::on_unbalanced(imbalance);
-	}
-}
-
-/// A little handy utility for converting a value in balance units into approximate value in gas units
-/// at the given gas price.
-pub fn approx_gas_for_balance<Balance>(gas_price: Balance, balance: Balance) -> Gas
-	where Balance: AtLeast32Bit
-{
-	if gas_price.is_zero() {
-		Zero::zero()
-	} else {
-		(balance / gas_price).saturated_into::<Gas>()
-	}
-}
-
 /// A simple utility macro that helps to match against a
 /// list of tokens.
 #[macro_export]
@@ -298,7 +248,7 @@ macro_rules! match_tokens {
 #[cfg(test)]
 mod tests {
 	use super::{GasMeter, Token};
-	use crate::{tests::Test, gas::approx_gas_for_balance};
+	use crate::tests::Test;
 
 	/// A trivial token that charges the specified number of gas units.
 	#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -326,26 +276,24 @@ mod tests {
 
 	#[test]
 	fn it_works() {
-		let gas_meter = GasMeter::<Test>::with_limit(50000, 10);
+		let gas_meter = GasMeter::<Test>::new(50000);
 		assert_eq!(gas_meter.gas_left(), 50000);
 	}
 
 	#[test]
 	fn simple() {
-		let mut gas_meter = GasMeter::<Test>::with_limit(50000, 10);
+		let mut gas_meter = GasMeter::<Test>::new(50000);
 
 		let result = gas_meter
 			.charge(&MultiplierTokenMetadata { multiplier: 3 }, MultiplierToken(10));
 		assert!(!result.is_out_of_gas());
 
 		assert_eq!(gas_meter.gas_left(), 49_970);
-		assert_eq!(gas_meter.spent(), 30);
-		assert_eq!(gas_meter.gas_price(), 10);
 	}
 
 	#[test]
 	fn tracing() {
-		let mut gas_meter = GasMeter::<Test>::with_limit(50000, 10);
+		let mut gas_meter = GasMeter::<Test>::new(50000);
 		assert!(!gas_meter.charge(&(), SimpleToken(1)).is_out_of_gas());
 		assert!(!gas_meter
 			.charge(&MultiplierTokenMetadata { multiplier: 3 }, MultiplierToken(10))
@@ -358,7 +306,7 @@ mod tests {
 	// This test makes sure that nothing can be executed if there is no gas.
 	#[test]
 	fn refuse_to_execute_anything_if_zero() {
-		let mut gas_meter = GasMeter::<Test>::with_limit(0, 10);
+		let mut gas_meter = GasMeter::<Test>::new(0);
 		assert!(gas_meter.charge(&(), SimpleToken(1)).is_out_of_gas());
 	}
 
@@ -369,7 +317,7 @@ mod tests {
 	// if the gas meter runs out of gas. However, this is just a nice property to have.
 	#[test]
 	fn overcharge_is_unrecoverable() {
-		let mut gas_meter = GasMeter::<Test>::with_limit(200, 10);
+		let mut gas_meter = GasMeter::<Test>::new(200);
 
 		// The first charge is should lead to OOG.
 		assert!(gas_meter.charge(&(), SimpleToken(300)).is_out_of_gas());
@@ -383,25 +331,7 @@ mod tests {
 	// possible.
 	#[test]
 	fn charge_exact_amount() {
-		let mut gas_meter = GasMeter::<Test>::with_limit(25, 10);
+		let mut gas_meter = GasMeter::<Test>::new(25);
 		assert!(!gas_meter.charge(&(), SimpleToken(25)).is_out_of_gas());
 	}
-
-	// A unit test for `fn approx_gas_for_balance()`, and makes
-	// sure setting gas_price 0 does not cause `div by zero` error.
-	#[test]
-	fn approx_gas_for_balance_works() {
-		let tests = vec![
-			(approx_gas_for_balance(0_u64, 123), 0),
-			(approx_gas_for_balance(0_u64, 456), 0),
-			(approx_gas_for_balance(1_u64, 123), 123),
-			(approx_gas_for_balance(1_u64, 456), 456),
-			(approx_gas_for_balance(100_u64, 900), 9),
-			(approx_gas_for_balance(123_u64, 900), 7),
-		];
-
-		for (lhs, rhs) in tests {
-			assert_eq!(lhs, rhs);
-		}
-	}
 }
diff --git a/substrate/frame/contracts/src/lib.rs b/substrate/frame/contracts/src/lib.rs
index 2513f2fb618e2d4f814bbcd429c98d2d3bbc1b1e..8a17ada6fc324ddd032e5ec5eb6dde844f7e1b54 100644
--- a/substrate/frame/contracts/src/lib.rs
+++ b/substrate/frame/contracts/src/lib.rs
@@ -64,15 +64,6 @@
 //! initialize the contract.
 //! * `call` - Makes a call to an account, optionally transferring some balance.
 //!
-//! ### Signed Extensions
-//!
-//! The contracts module defines the following extension:
-//!
-//!   - [`CheckBlockGasLimit`]: Ensures that the transaction does not exceeds the block gas limit.
-//!
-//! The signed extension needs to be added as signed extra to the transaction type to be used in the
-//! runtime.
-//!
 //! ## Usage
 //!
 //! The Contract module is a work in progress. The following examples show how this Contract module
@@ -114,21 +105,20 @@ use codec::{Codec, Encode, Decode};
 use sp_io::hashing::blake2_256;
 use sp_runtime::{
 	traits::{
-		Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member, SignedExtension,
-		DispatchInfoOf,
-	},
-	transaction_validity::{
-		ValidTransaction, InvalidTransaction, TransactionValidity, TransactionValidityError,
+		Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member,
 	},
 	RuntimeDebug,
 };
-use frame_support::dispatch::{DispatchResult, Dispatchable};
+use frame_support::dispatch::{
+	PostDispatchInfo, DispatchResult, Dispatchable, DispatchResultWithPostInfo
+};
 use frame_support::weights::MINIMUM_WEIGHT;
 use frame_support::{
 	Parameter, decl_module, decl_event, decl_storage, decl_error,
 	parameter_types, IsSubType, storage::child::{self, ChildInfo},
 };
 use frame_support::traits::{OnUnbalanced, Currency, Get, Time, Randomness};
+use frame_support::weights::{FunctionOf, DispatchClass, Weight, GetDispatchInfo, Pays};
 use frame_system::{self as system, ensure_signed, RawOrigin, ensure_root};
 use pallet_contracts_primitives::{RentProjection, ContractAccessError};
 
@@ -295,9 +285,9 @@ where
 	}
 }
 
-pub type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::Balance;
+pub type BalanceOf<T> = <<T as pallet_transaction_payment::Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::Balance;
 pub type NegativeImbalanceOf<T> =
-	<<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::NegativeImbalance;
+	<<T as pallet_transaction_payment::Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::NegativeImbalance;
 
 parameter_types! {
 	/// A reasonable default value for [`Trait::SignedClaimedHandicap`].
@@ -312,35 +302,21 @@ parameter_types! {
 	pub const DefaultRentDepositOffset: u32 = 1000;
 	/// A reasonable default value for [`Trait::SurchargeReward`].
 	pub const DefaultSurchargeReward: u32 = 150;
-	/// A reasonable default value for [`Trait::TransferFee`].
-	pub const DefaultTransferFee: u32 = 0;
-	/// A reasonable default value for [`Trait::InstantiationFee`].
-	pub const DefaultInstantiationFee: u32 = 0;
-	/// A reasonable default value for [`Trait::TransactionBaseFee`].
-	pub const DefaultTransactionBaseFee: u32 = 0;
-	/// A reasonable default value for [`Trait::TransactionByteFee`].
-	pub const DefaultTransactionByteFee: u32 = 0;
-	/// A reasonable default value for [`Trait::ContractFee`].
-	pub const DefaultContractFee: u32 = 21;
-	/// A reasonable default value for [`Trait::CallBaseFee`].
-	pub const DefaultCallBaseFee: u32 = 1000;
-	/// A reasonable default value for [`Trait::InstantiateBaseFee`].
-	pub const DefaultInstantiateBaseFee: u32 = 1000;
 	/// A reasonable default value for [`Trait::MaxDepth`].
 	pub const DefaultMaxDepth: u32 = 32;
 	/// A reasonable default value for [`Trait::MaxValueSize`].
 	pub const DefaultMaxValueSize: u32 = 16_384;
-	/// A reasonable default value for [`Trait::BlockGasLimit`].
-	pub const DefaultBlockGasLimit: u32 = 10_000_000;
 }
 
-pub trait Trait: frame_system::Trait {
-	type Currency: Currency<Self::AccountId>;
+pub trait Trait: frame_system::Trait + pallet_transaction_payment::Trait {
 	type Time: Time;
 	type Randomness: Randomness<Self::Hash>;
 
 	/// The outer call dispatch type.
-	type Call: Parameter + Dispatchable<Origin=<Self as frame_system::Trait>::Origin> + IsSubType<Module<Self>, Self>;
+	type Call:
+		Parameter +
+		Dispatchable<PostInfo=PostDispatchInfo, Origin=<Self as frame_system::Trait>::Origin> +
+		IsSubType<Module<Self>, Self> + GetDispatchInfo;
 
 	/// The overarching event type.
 	type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
@@ -348,18 +324,9 @@ pub trait Trait: frame_system::Trait {
 	/// A function type to get the contract address given the instantiator.
 	type DetermineContractAddress: ContractAddressFor<CodeHash<Self>, Self::AccountId>;
 
-	/// A function type that computes the fee for dispatching the given `Call`.
-	///
-	/// It is recommended (though not required) for this function to return a fee that would be
-	/// taken by the Executive module for regular dispatch.
-	type ComputeDispatchFee: ComputeDispatchFee<<Self as Trait>::Call, BalanceOf<Self>>;
-
 	/// trie id generator
 	type TrieIdGenerator: TrieIdGenerator<Self::AccountId>;
 
-	/// Handler for the unbalanced reduction when making a gas payment.
-	type GasPayment: OnUnbalanced<NegativeImbalanceOf<Self>>;
-
 	/// Handler for rent payments.
 	type RentPayment: OnUnbalanced<NegativeImbalanceOf<Self>>;
 
@@ -392,29 +359,11 @@ pub trait Trait: frame_system::Trait {
 	/// to removal of a contract.
 	type SurchargeReward: Get<BalanceOf<Self>>;
 
-	/// The fee to be paid for making a transaction; the base.
-	type TransactionBaseFee: Get<BalanceOf<Self>>;
-
-	/// The fee to be paid for making a transaction; the per-byte portion.
-	type TransactionByteFee: Get<BalanceOf<Self>>;
-
-	/// The fee required to instantiate a contract instance.
-	type ContractFee: Get<BalanceOf<Self>>;
-
-	/// The base fee charged for calling into a contract.
-	type CallBaseFee: Get<Gas>;
-
-	/// The base fee charged for instantiating a contract.
-	type InstantiateBaseFee: Get<Gas>;
-
 	/// The maximum nesting level of a call/instantiate stack.
 	type MaxDepth: Get<u32>;
 
 	/// The maximum size of a storage value in bytes.
 	type MaxValueSize: Get<u32>;
-
-	/// The maximum amount of gas that could be expended per block.
-	type BlockGasLimit: Get<Gas>;
 }
 
 /// Simple contract address determiner.
@@ -440,19 +389,6 @@ where
 	}
 }
 
-/// The default dispatch fee computor computes the fee in the same way that
-/// the implementation of `ChargeTransactionPayment` for the Balances module does. Note that this only takes a fixed
-/// fee based on size. Unlike the balances module, weight-fee is applied.
-pub struct DefaultDispatchFeeComputor<T: Trait>(PhantomData<T>);
-impl<T: Trait> ComputeDispatchFee<<T as Trait>::Call, BalanceOf<T>> for DefaultDispatchFeeComputor<T> {
-	fn compute_dispatch_fee(call: &<T as Trait>::Call) -> BalanceOf<T> {
-		let encoded_len = call.using_encoded(|encoded| encoded.len() as u32);
-		let base_fee = T::TransactionBaseFee::get();
-		let byte_fee = T::TransactionByteFee::get();
-		base_fee + byte_fee * encoded_len.into()
-	}
-}
-
 decl_error! {
 	/// Error for the contracts module.
 	pub enum Error for Module<T: Trait> {
@@ -505,24 +441,6 @@ decl_module! {
 		/// to removal of a contract.
 		const SurchargeReward: BalanceOf<T> = T::SurchargeReward::get();
 
-		/// The fee to be paid for making a transaction; the base.
-		const TransactionBaseFee: BalanceOf<T> = T::TransactionBaseFee::get();
-
-		/// The fee to be paid for making a transaction; the per-byte portion.
-		const TransactionByteFee: BalanceOf<T> = T::TransactionByteFee::get();
-
-		/// The fee required to instantiate a contract instance. A reasonable default value
-		/// is 21.
-		const ContractFee: BalanceOf<T> = T::ContractFee::get();
-
-		/// The base fee charged for calling into a contract. A reasonable default
-		/// value is 135.
-		const CallBaseFee: Gas = T::CallBaseFee::get();
-
-		/// The base fee charged for instantiating a contract. A reasonable default value
-		/// is 175.
-		const InstantiateBaseFee: Gas = T::InstantiateBaseFee::get();
-
 		/// The maximum nesting level of a call/instantiate stack. A reasonable default
 		/// value is 100.
 		const MaxDepth: u32 = T::MaxDepth::get();
@@ -530,10 +448,6 @@ decl_module! {
 		/// The maximum size of a storage value in bytes. A reasonable default is 16 KiB.
 		const MaxValueSize: u32 = T::MaxValueSize::get();
 
-		/// The maximum amount of gas that could be expended per block. A reasonable
-		/// default value is 10_000_000.
-		const BlockGasLimit: Gas = T::BlockGasLimit::get();
-
 		fn deposit_event() = default;
 
 		/// Updates the schedule for metering contracts.
@@ -554,24 +468,21 @@ decl_module! {
 
 		/// Stores the given binary Wasm code into the chain's storage and returns its `codehash`.
 		/// You can instantiate contracts only with stored code.
-		#[weight = MINIMUM_WEIGHT]
+		#[weight = FunctionOf(
+			|args: (&Vec<u8>,)| Module::<T>::calc_code_put_costs(args.0) + MINIMUM_WEIGHT,
+			DispatchClass::Normal,
+			Pays::Yes
+		)]
 		pub fn put_code(
 			origin,
-			#[compact] gas_limit: Gas,
 			code: Vec<u8>
 		) -> DispatchResult {
-			let origin = ensure_signed(origin)?;
-
-			let (mut gas_meter, imbalance) = gas::buy_gas::<T>(&origin, gas_limit)?;
-
+			ensure_signed(origin)?;
 			let schedule = <Module<T>>::current_schedule();
-			let result = wasm::save_code::<T>(code, &mut gas_meter, &schedule);
+			let result = wasm::save_code::<T>(code, &schedule);
 			if let Ok(code_hash) = result {
 				Self::deposit_event(RawEvent::CodeStored(code_hash));
 			}
-
-			gas::refund_unused_gas::<T>(&origin, gas_meter, imbalance);
-
 			result.map(|_| ()).map_err(Into::into)
 		}
 
@@ -582,20 +493,27 @@ decl_module! {
 		/// * If the account is a regular account, any value will be transferred.
 		/// * If no account exists and the call value is not less than `existential_deposit`,
 		/// a regular account will be created and any value will be transferred.
-		#[weight = MINIMUM_WEIGHT]
+		#[weight = FunctionOf(
+			|args: (&<T::Lookup as StaticLookup>::Source, &BalanceOf<T>, &Weight, &Vec<u8>)|
+				args.2 + MINIMUM_WEIGHT,
+			DispatchClass::Normal,
+			Pays::Yes
+		)]
 		pub fn call(
 			origin,
 			dest: <T::Lookup as StaticLookup>::Source,
 			#[compact] value: BalanceOf<T>,
 			#[compact] gas_limit: Gas,
 			data: Vec<u8>
-		) -> DispatchResult {
+		) -> DispatchResultWithPostInfo {
 			let origin = ensure_signed(origin)?;
 			let dest = T::Lookup::lookup(dest)?;
+			let mut gas_meter = GasMeter::new(gas_limit);
 
-			Self::bare_call(origin, dest, value, gas_limit, data)
-				.map(|_| ())
-				.map_err(|e| e.reason.into())
+			let result = Self::execute_wasm(origin, &mut gas_meter, |ctx, gas_meter| {
+				ctx.call(dest, value, gas_meter, data)
+			});
+			gas_meter.into_dispatch_result(result.map_err(|e| e.reason))
 		}
 
 		/// Instantiates a new contract from the `codehash` generated by `put_code`, optionally transferring some balance.
@@ -608,22 +526,26 @@ decl_module! {
 		///   after the execution is saved as the `code` of the account. That code will be invoked
 		///   upon any call received by this account.
 		/// - The contract is initialized.
-		#[weight = MINIMUM_WEIGHT]
+		#[weight = FunctionOf(
+			|args: (&BalanceOf<T>, &Weight, &CodeHash<T>, &Vec<u8>)| args.1 + MINIMUM_WEIGHT,
+			DispatchClass::Normal,
+			Pays::Yes
+		)]
 		pub fn instantiate(
 			origin,
 			#[compact] endowment: BalanceOf<T>,
 			#[compact] gas_limit: Gas,
 			code_hash: CodeHash<T>,
 			data: Vec<u8>
-		) -> DispatchResult {
+		) -> DispatchResultWithPostInfo {
 			let origin = ensure_signed(origin)?;
+			let mut gas_meter = GasMeter::new(gas_limit);
 
-			Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| {
+			let result = Self::execute_wasm(origin, &mut gas_meter, |ctx, gas_meter| {
 				ctx.instantiate(endowment, gas_meter, &code_hash, data)
 					.map(|(_address, output)| output)
-			})
-			.map(|_| ())
-			.map_err(|e| e.reason.into())
+			});
+			gas_meter.into_dispatch_result(result.map_err(|e| e.reason))
 		}
 
 		/// Allows block producers to claim a small reward for evicting a contract. If a block producer
@@ -658,10 +580,6 @@ decl_module! {
 				T::Currency::deposit_into_existing(&rewarded, T::SurchargeReward::get())?;
 			}
 		}
-
-		fn on_finalize() {
-			GasSpent::kill();
-		}
 	}
 }
 
@@ -678,7 +596,8 @@ impl<T: Trait> Module<T> {
 		gas_limit: Gas,
 		input_data: Vec<u8>,
 	) -> ExecResult {
-		Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| {
+		let mut gas_meter = GasMeter::new(gas_limit);
+		Self::execute_wasm(origin, &mut gas_meter, |ctx, gas_meter| {
 			ctx.call(dest, value, gas_meter, input_data)
 		})
 	}
@@ -710,40 +629,27 @@ impl<T: Trait> Module<T> {
 }
 
 impl<T: Trait> Module<T> {
+	fn calc_code_put_costs(code: &Vec<u8>) -> Gas {
+		<Module<T>>::current_schedule().put_code_per_byte_cost.saturating_mul(code.len() as Gas)
+	}
+
 	fn execute_wasm(
 		origin: T::AccountId,
-		gas_limit: Gas,
+		gas_meter: &mut GasMeter<T>,
 		func: impl FnOnce(&mut ExecutionContext<T, WasmVm, WasmLoader>, &mut GasMeter<T>) -> ExecResult
 	) -> ExecResult {
-		// Pay for the gas upfront.
-		//
-		// NOTE: it is very important to avoid any state changes before
-		// paying for the gas.
-		let (mut gas_meter, imbalance) =
-			try_or_exec_error!(
-				gas::buy_gas::<T>(&origin, gas_limit),
-				// We don't have a spare buffer here in the first place, so create a new empty one.
-				Vec::new()
-			);
-
 		let cfg = Config::preload();
 		let vm = WasmVm::new(&cfg.schedule);
 		let loader = WasmLoader::new(&cfg.schedule);
 		let mut ctx = ExecutionContext::top_level(origin.clone(), &cfg, &vm, &loader);
 
-		let result = func(&mut ctx, &mut gas_meter);
+		let result = func(&mut ctx, gas_meter);
 
 		if result.as_ref().map(|output| output.is_success()).unwrap_or(false) {
 			// Commit all changes that made it thus far into the persistent storage.
 			DirectAccountDb.commit(ctx.overlay.into_change_set());
 		}
 
-		// Refund cost of the unused gas.
-		//
-		// NOTE: This should go after the commit to the storage, since the storage changes
-		// can alter the balance of the caller.
-		gas::refund_unused_gas::<T>(&origin, gas_meter, imbalance);
-
 		// Execute deferred actions.
 		ctx.deferred.into_iter().for_each(|deferred| {
 			use self::exec::DeferredAction::*;
@@ -759,7 +665,13 @@ impl<T: Trait> Module<T> {
 					origin: who,
 					call,
 				} => {
+					let info = call.get_dispatch_info();
 					let result = call.dispatch(RawOrigin::Signed(who.clone()).into());
+					let post_info = match result {
+						Ok(post_info) => post_info,
+						Err(err) => err.post_info,
+					};
+					gas_meter.refund(post_info.calc_unspent(&info));
 					Self::deposit_event(RawEvent::Dispatched(who, result.is_ok()));
 				}
 				RestoreTo {
@@ -917,8 +829,6 @@ decl_event! {
 
 decl_storage! {
 	trait Store for Module<T: Trait> as Contracts {
-		/// Gas spent so far in this block.
-		GasSpent get(fn gas_spent): Gas;
 		/// Current cost schedule for contracts.
 		CurrentSchedule get(fn current_schedule) config(): Schedule = Schedule::default();
 		/// A mapping from an original code hash to the original code, untouched by instrumentation.
@@ -929,8 +839,6 @@ decl_storage! {
 		pub AccountCounter: u64 = 0;
 		/// The code associated with a given account.
 		pub ContractInfoOf: map hasher(twox_64_concat) T::AccountId => Option<ContractInfo<T>>;
-		/// The price of one unit of gas.
-		GasPrice get(fn gas_price) config(): BalanceOf<T> = 1.into();
 	}
 }
 
@@ -944,7 +852,6 @@ pub struct Config<T: Trait> {
 	pub tombstone_deposit: BalanceOf<T>,
 	pub max_depth: u32,
 	pub max_value_size: u32,
-	pub contract_account_instantiate_fee: BalanceOf<T>,
 }
 
 impl<T: Trait> Config<T> {
@@ -955,7 +862,6 @@ impl<T: Trait> Config<T> {
 			tombstone_deposit: T::TombstoneDeposit::get(),
 			max_depth: T::MaxDepth::get(),
 			max_value_size: T::MaxValueSize::get(),
-			contract_account_instantiate_fee: T::ContractFee::get(),
 		}
 	}
 }
@@ -994,6 +900,9 @@ pub struct Schedule {
 	/// Base gas cost to instantiate a contract.
 	pub instantiate_base_cost: Gas,
 
+	/// Base gas cost to dispatch a runtime call.
+	pub dispatch_base_cost: Gas,
+
 	/// Gas cost per one byte read from the sandbox memory.
 	pub sandbox_data_read_cost: Gas,
 
@@ -1003,6 +912,9 @@ pub struct Schedule {
 	/// Cost for a simple balance transfer.
 	pub transfer_cost: Gas,
 
+	/// Cost for instantiating a new contract.
+	pub instantiate_cost: Gas,
+
 	/// The maximum number of topics supported by an event.
 	pub max_event_topics: u32,
 
@@ -1026,22 +938,29 @@ pub struct Schedule {
 	pub max_subject_len: u32,
 }
 
+// 500 (2 instructions per nano second on 2GHZ) * 1000x slowdown through wasmi
+// This is a wild guess and should be viewed as a rough estimation.
+// Proper benchmarks are needed before this value and its derivatives can be used in production.
+const WASM_INSTRUCTION_COST: Gas = 500_000;
+
 impl Default for Schedule {
 	fn default() -> Schedule {
 		Schedule {
 			version: 0,
-			put_code_per_byte_cost: 1,
-			grow_mem_cost: 1,
-			regular_op_cost: 1,
-			return_data_per_byte_cost: 1,
-			event_data_per_byte_cost: 1,
-			event_per_topic_cost: 1,
-			event_base_cost: 1,
-			call_base_cost: 135,
-			instantiate_base_cost: 175,
-			sandbox_data_read_cost: 1,
-			sandbox_data_write_cost: 1,
-			transfer_cost: 100,
+			put_code_per_byte_cost: WASM_INSTRUCTION_COST,
+			grow_mem_cost: WASM_INSTRUCTION_COST,
+			regular_op_cost: WASM_INSTRUCTION_COST,
+			return_data_per_byte_cost: WASM_INSTRUCTION_COST,
+			event_data_per_byte_cost: WASM_INSTRUCTION_COST,
+			event_per_topic_cost: WASM_INSTRUCTION_COST,
+			event_base_cost: WASM_INSTRUCTION_COST,
+			call_base_cost: 135 * WASM_INSTRUCTION_COST,
+			dispatch_base_cost: 135 * WASM_INSTRUCTION_COST,
+			instantiate_base_cost: 175 * WASM_INSTRUCTION_COST,
+			sandbox_data_read_cost: WASM_INSTRUCTION_COST,
+			sandbox_data_write_cost: WASM_INSTRUCTION_COST,
+			transfer_cost: 100 * WASM_INSTRUCTION_COST,
+			instantiate_cost: 200 * WASM_INSTRUCTION_COST,
 			max_event_topics: 4,
 			max_stack_height: 64 * 1024,
 			max_memory_pages: 16,
@@ -1052,67 +971,3 @@ impl Default for Schedule {
 	}
 }
 
-/// `SignedExtension` that checks if a transaction would exhausts the block gas limit.
-#[derive(Encode, Decode, Clone, Eq, PartialEq)]
-pub struct CheckBlockGasLimit<T: Trait + Send + Sync>(PhantomData<T>);
-
-impl<T: Trait + Send + Sync> Default for CheckBlockGasLimit<T> {
-	fn default() -> Self {
-		Self(PhantomData)
-	}
-}
-
-impl<T: Trait + Send + Sync> sp_std::fmt::Debug for CheckBlockGasLimit<T> {
-	#[cfg(feature = "std")]
-	fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
-		write!(f, "CheckBlockGasLimit")
-	}
-
-	#[cfg(not(feature = "std"))]
-	fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
-		Ok(())
-	}
-}
-
-impl<T: Trait + Send + Sync> SignedExtension for CheckBlockGasLimit<T> {
-	const IDENTIFIER: &'static str = "CheckBlockGasLimit";
-	type AccountId = T::AccountId;
-	type Call = <T as Trait>::Call;
-	type AdditionalSigned = ();
-	type Pre = ();
-
-	fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }
-
-	fn validate(
-		&self,
-		_: &Self::AccountId,
-		call: &Self::Call,
-		_: &DispatchInfoOf<Self::Call>,
-		_: usize,
-	) -> TransactionValidity {
-		let call = match call.is_sub_type() {
-			Some(call) => call,
-			None => return Ok(ValidTransaction::default()),
-		};
-
-		match call {
-			Call::claim_surcharge(_, _) | Call::update_schedule(_) =>
-				Ok(ValidTransaction::default()),
-			Call::put_code(gas_limit, _)
-				| Call::call(_, _, gas_limit, _)
-				| Call::instantiate(_, gas_limit, _, _)
-			=> {
-				// Check if the specified amount of gas is available in the current block.
-				// This cannot underflow since `gas_spent` is never greater than `T::BlockGasLimit`.
-				let gas_available = T::BlockGasLimit::get() - <Module<T>>::gas_spent();
-				if *gas_limit > gas_available {
-					// gas limit reached, revert the transaction and retry again in the future
-					InvalidTransaction::ExhaustsResources.into()
-				} else {
-					Ok(ValidTransaction::default())
-				}
-			},
-			Call::__PhantomItem(_, _)  => unreachable!("Variant is never constructed"),
-		}
-	}
-}
diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs
index 452a4517dbe6838aeedb8e03904887ffde5b7703..dd228b0644d2b8aac4bcf3de45ddc2edf3e0acb6 100644
--- a/substrate/frame/contracts/src/tests.rs
+++ b/substrate/frame/contracts/src/tests.rs
@@ -22,20 +22,22 @@
 use crate::{
 	BalanceOf, ComputeDispatchFee, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig,
 	Module, RawAliveContractInfo, RawEvent, Trait, TrieId, TrieIdFromParentCounter, Schedule,
-	TrieIdGenerator, CheckBlockGasLimit, account_db::{AccountDb, DirectAccountDb, OverlayAccountDb},
+	TrieIdGenerator, account_db::{AccountDb, DirectAccountDb, OverlayAccountDb},
+	gas::Gas,
 };
 use assert_matches::assert_matches;
 use hex_literal::*;
 use codec::{Decode, Encode, KeyedVec};
 use sp_runtime::{
 	Perbill, BuildStorage, transaction_validity::{InvalidTransaction, ValidTransaction},
-	traits::{BlakeTwo256, Hash, IdentityLookup, SignedExtension},
+	traits::{BlakeTwo256, Hash, IdentityLookup, SignedExtension, Convert},
 	testing::{Digest, DigestItem, Header, UintAuthorityId, H256},
 };
 use frame_support::{
-	assert_ok, assert_err, impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types,
+	assert_ok, assert_err, assert_err_ignore_postinfo, impl_outer_dispatch, impl_outer_event,
+	impl_outer_origin, parameter_types,
 	storage::child, StorageMap, StorageValue, traits::{Currency, Get},
-	weights::{DispatchInfo, DispatchClass, Weight, Pays},
+	weights::{DispatchInfo, DispatchClass, Weight, PostDispatchInfo, Pays},
 };
 use std::{cell::RefCell, sync::atomic::{AtomicUsize, Ordering}};
 use sp_core::storage::well_known_keys;
@@ -70,9 +72,6 @@ impl_outer_dispatch! {
 
 thread_local! {
 	static EXISTENTIAL_DEPOSIT: RefCell<u64> = RefCell::new(0);
-	static TRANSFER_FEE: RefCell<u64> = RefCell::new(0);
-	static INSTANTIATION_FEE: RefCell<u64> = RefCell::new(0);
-	static BLOCK_GAS_LIMIT: RefCell<u64> = RefCell::new(0);
 }
 
 pub struct ExistentialDeposit;
@@ -80,16 +79,6 @@ impl Get<u64> for ExistentialDeposit {
 	fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) }
 }
 
-pub struct TransferFee;
-impl Get<u64> for TransferFee {
-	fn get() -> u64 { TRANSFER_FEE.with(|v| *v.borrow()) }
-}
-
-pub struct BlockGasLimit;
-impl Get<u64> for BlockGasLimit {
-	fn get() -> u64 { BLOCK_GAS_LIMIT.with(|v| *v.borrow()) }
-}
-
 #[derive(Clone, Eq, PartialEq, Debug)]
 pub struct Test;
 parameter_types! {
@@ -142,24 +131,37 @@ parameter_types! {
 	pub const RentByteFee: u64 = 4;
 	pub const RentDepositOffset: u64 = 10_000;
 	pub const SurchargeReward: u64 = 150;
-	pub const TransactionBaseFee: u64 = 2;
-	pub const TransactionByteFee: u64 = 6;
-	pub const ContractFee: u64 = 21;
-	pub const CallBaseFee: u64 = 135;
-	pub const InstantiateBaseFee: u64 = 175;
 	pub const MaxDepth: u32 = 100;
 	pub const MaxValueSize: u32 = 16_384;
 }
-impl Trait for Test {
+
+parameter_types! {
+	pub const TransactionBaseFee: u64 = 0;
+	pub const TransactionByteFee: u64 = 0;
+}
+
+impl Convert<Weight, BalanceOf<Self>> for Test {
+	fn convert(w: Weight) -> BalanceOf<Self> {
+		w
+	}
+}
+
+impl pallet_transaction_payment::Trait for Test {
 	type Currency = Balances;
+	type OnTransactionPayment = ();
+	type TransactionBaseFee = TransactionBaseFee;
+	type TransactionByteFee = TransactionByteFee;
+	type WeightToFee = Test;
+	type FeeMultiplierUpdate = ();
+}
+
+impl Trait for Test {
 	type Time = Timestamp;
 	type Randomness = Randomness;
 	type Call = Call;
 	type DetermineContractAddress = DummyContractAddressFor;
 	type Event = MetaEvent;
-	type ComputeDispatchFee = DummyComputeDispatchFee;
 	type TrieIdGenerator = DummyTrieIdGenerator;
-	type GasPayment = ();
 	type RentPayment = ();
 	type SignedClaimHandicap = SignedClaimHandicap;
 	type TombstoneDeposit = TombstoneDeposit;
@@ -167,14 +169,8 @@ impl Trait for Test {
 	type RentByteFee = RentByteFee;
 	type RentDepositOffset = RentDepositOffset;
 	type SurchargeReward = SurchargeReward;
-	type TransactionBaseFee = TransactionBaseFee;
-	type TransactionByteFee = TransactionByteFee;
-	type ContractFee = ContractFee;
-	type CallBaseFee = CallBaseFee;
-	type InstantiateBaseFee = InstantiateBaseFee;
 	type MaxDepth = MaxDepth;
 	type MaxValueSize = MaxValueSize;
-	type BlockGasLimit = BlockGasLimit;
 }
 
 type Balances = pallet_balances::Module<Test>;
@@ -219,21 +215,15 @@ const BOB: u64 = 2;
 const CHARLIE: u64 = 3;
 const DJANGO: u64 = 4;
 
+const GAS_LIMIT: Gas = 10_000_000_000;
+
 pub struct ExtBuilder {
 	existential_deposit: u64,
-	gas_price: u64,
-	block_gas_limit: u64,
-	transfer_fee: u64,
-	instantiation_fee: u64,
 }
 impl Default for ExtBuilder {
 	fn default() -> Self {
 		Self {
 			existential_deposit: 1,
-			gas_price: 2,
-			block_gas_limit: 100_000_000,
-			transfer_fee: 0,
-			instantiation_fee: 0,
 		}
 	}
 }
@@ -242,27 +232,8 @@ impl ExtBuilder {
 		self.existential_deposit = existential_deposit;
 		self
 	}
-	pub fn gas_price(mut self, gas_price: u64) -> Self {
-		self.gas_price = gas_price;
-		self
-	}
-	pub fn block_gas_limit(mut self, block_gas_limit: u64) -> Self {
-		self.block_gas_limit = block_gas_limit;
-		self
-	}
-	pub fn transfer_fee(mut self, transfer_fee: u64) -> Self {
-		self.transfer_fee = transfer_fee;
-		self
-	}
-	pub fn instantiation_fee(mut self, instantiation_fee: u64) -> Self {
-		self.instantiation_fee = instantiation_fee;
-		self
-	}
 	pub fn set_associated_consts(&self) {
 		EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit);
-		TRANSFER_FEE.with(|v| *v.borrow_mut() = self.transfer_fee);
-		INSTANTIATION_FEE.with(|v| *v.borrow_mut() = self.instantiation_fee);
-		BLOCK_GAS_LIMIT.with(|v| *v.borrow_mut() = self.block_gas_limit);
 	}
 	pub fn build(self) -> sp_io::TestExternalities {
 		self.set_associated_consts();
@@ -270,12 +241,11 @@ impl ExtBuilder {
 		pallet_balances::GenesisConfig::<Test> {
 			balances: vec![],
 		}.assimilate_storage(&mut t).unwrap();
-		GenesisConfig::<Test> {
+		GenesisConfig {
 			current_schedule: Schedule {
 				enable_println: true,
 				..Default::default()
 			},
-			gas_price: self.gas_price,
 		}.assimilate_storage(&mut t).unwrap();
 		let mut ext = sp_io::TestExternalities::new(t);
 		ext.execute_with(|| System::set_block_number(1));
@@ -293,17 +263,21 @@ fn compile_module<T>(wabt_module: &str)
 	Ok((wasm, code_hash))
 }
 
-// Perform a simple transfer to a non-existent account supplying way more gas than needed.
-// Then we check that the all unused gas is refunded.
+// Perform a simple transfer to a non-existent account.
+// Then we check that only the base costs are returned as actual costs.
 #[test]
-fn refunds_unused_gas() {
-	ExtBuilder::default().gas_price(2).build().execute_with(|| {
+fn returns_base_call_cost() {
+	ExtBuilder::default().build().execute_with(|| {
 		Balances::deposit_creating(&ALICE, 100_000_000);
 
-		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, Vec::new()));
-
-		// 2 * 135 - gas price multiplied by the call base fee.
-		assert_eq!(Balances::free_balance(ALICE), 100_000_000 - (2 * 135));
+		assert_eq!(
+			Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, Vec::new()),
+			Ok(
+				PostDispatchInfo {
+					actual_weight: Some(67500000),
+				}
+			)
+		);
 	});
 }
 
@@ -388,13 +362,13 @@ fn instantiate_and_call_and_deposit_event() {
 	ExtBuilder::default().existential_deposit(100).build().execute_with(|| {
 		Balances::deposit_creating(&ALICE, 1_000_000);
 
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 
 		// Check at the end to get hash on error easily
 		let creation = Contracts::instantiate(
 			Origin::signed(ALICE),
 			100,
-			100_000,
+			GAS_LIMIT,
 			code_hash.into(),
 			vec![],
 		);
@@ -462,7 +436,7 @@ fn dispatch_call() {
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		Balances::deposit_creating(&ALICE, 1_000_000);
 
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 
 		// Let's keep this assert even though it's redundant. If you ever need to update the
 		// wasm source this test will fail and will show you the actual hash.
@@ -487,7 +461,7 @@ fn dispatch_call() {
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			100,
-			100_000,
+			GAS_LIMIT,
 			code_hash.into(),
 			vec![],
 		));
@@ -496,7 +470,7 @@ fn dispatch_call() {
 			Origin::signed(ALICE),
 			BOB, // newly created account
 			0,
-			100_000,
+			GAS_LIMIT,
 			vec![],
 		));
 
@@ -583,7 +557,7 @@ fn dispatch_call_not_dispatched_after_top_level_transaction_failure() {
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		Balances::deposit_creating(&ALICE, 1_000_000);
 
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 
 		// Let's keep this assert even though it's redundant. If you ever need to update the
 		// wasm source this test will fail and will show you the actual hash.
@@ -608,19 +582,19 @@ fn dispatch_call_not_dispatched_after_top_level_transaction_failure() {
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			100,
-			100_000,
+			GAS_LIMIT,
 			code_hash.into(),
 			vec![],
 		));
 
 		// Call the newly instantiated contract. The contract is expected to dispatch a call
 		// and then trap.
-		assert_err!(
+		assert_err_ignore_postinfo!(
 			Contracts::call(
 				Origin::signed(ALICE),
 				BOB, // newly created account
 				0,
-				100_000,
+				GAS_LIMIT,
 				vec![],
 			),
 			"contract trapped during execution"
@@ -679,24 +653,24 @@ fn run_out_of_gas() {
 		.execute_with(|| {
 			Balances::deposit_creating(&ALICE, 1_000_000);
 
-			assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+			assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 
 			assert_ok!(Contracts::instantiate(
 				Origin::signed(ALICE),
 				100,
-				100_000,
+				GAS_LIMIT,
 				code_hash.into(),
 				vec![],
 			));
 
 			// Call the contract with a fixed gas limit. It must run out of gas because it just
 			// loops forever.
-			assert_err!(
+			assert_err_ignore_postinfo!(
 				Contracts::call(
 					Origin::signed(ALICE),
 					BOB, // newly created account
 					0,
-					1000,
+					67_500_000,
 					vec![],
 				),
 				"ran out of gas during contract execution"
@@ -725,7 +699,7 @@ fn test_set_rent_code_and_hash() {
 
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 
 		// If you ever need to update the wasm source this test will fail
 		// and will show you the actual hash.
@@ -757,21 +731,21 @@ fn storage_size() {
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		// Create
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			30_000,
-			100_000, code_hash.into(),
+			GAS_LIMIT, code_hash.into(),
 			<Test as pallet_balances::Trait>::Balance::from(1_000u32).encode() // rent allowance
 		));
 		let bob_contract = ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap();
 		assert_eq!(bob_contract.storage_size, <Test as Trait>::StorageSizeOffset::get() + 4);
 
-		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::set_storage_4_byte()));
+		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::set_storage_4_byte()));
 		let bob_contract = ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap();
 		assert_eq!(bob_contract.storage_size, <Test as Trait>::StorageSizeOffset::get() + 4 + 4);
 
-		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::remove_storage_4_byte()));
+		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::remove_storage_4_byte()));
 		let bob_contract = ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap();
 		assert_eq!(bob_contract.storage_size, <Test as Trait>::StorageSizeOffset::get() + 4);
 	});
@@ -794,11 +768,11 @@ fn deduct_blocks() {
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		// Create
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			30_000,
-			100_000, code_hash.into(),
+			GAS_LIMIT, code_hash.into(),
 			<Test as pallet_balances::Trait>::Balance::from(1_000u32).encode() // rent allowance
 		));
 
@@ -810,7 +784,7 @@ fn deduct_blocks() {
 		initialize_block(5);
 
 		// Trigger rent through call
-		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()));
+		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
 
 		// Check result
 		let rent = (8 + 4 - 3) // storage size = size_offset + deploy_set_storage - deposit_offset
@@ -825,7 +799,7 @@ fn deduct_blocks() {
 		initialize_block(12);
 
 		// Trigger rent through call
-		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()));
+		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
 
 		// Check result
 		let rent_2 = (8 + 4 - 2) // storage size = size_offset + deploy_set_storage - deposit_offset
@@ -837,7 +811,7 @@ fn deduct_blocks() {
 		assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2);
 
 		// Second call on same block should have no effect on rent
-		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()));
+		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
 
 		let bob_contract = ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap();
 		assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2);
@@ -850,7 +824,7 @@ fn deduct_blocks() {
 fn call_contract_removals() {
 	removals(|| {
 		// Call on already-removed account might fail, and this is fine.
-		Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null());
+		Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null());
 		true
 	});
 }
@@ -888,11 +862,11 @@ fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool)
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		// Create
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			100,
-			100_000, code_hash.into(),
+			GAS_LIMIT, code_hash.into(),
 			<Test as pallet_balances::Trait>::Balance::from(1_000u32).encode() // rent allowance
 		));
 
@@ -921,11 +895,11 @@ fn removals(trigger_call: impl Fn() -> bool) {
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		// Create
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm.clone()));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			100,
-			100_000, code_hash.into(),
+			GAS_LIMIT, code_hash.into(),
 			<Test as pallet_balances::Trait>::Balance::from(1_000u32).encode() // rent allowance
 		));
 
@@ -957,11 +931,11 @@ fn removals(trigger_call: impl Fn() -> bool) {
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		// Create
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm.clone()));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			1_000,
-			100_000, code_hash.into(),
+			GAS_LIMIT, code_hash.into(),
 			<Test as pallet_balances::Trait>::Balance::from(100u32).encode() // rent allowance
 		));
 
@@ -992,11 +966,11 @@ fn removals(trigger_call: impl Fn() -> bool) {
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		// Create
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm.clone()));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			50+Balances::minimum_balance(),
-			100_000, code_hash.into(),
+			GAS_LIMIT, code_hash.into(),
 			<Test as pallet_balances::Trait>::Balance::from(1_000u32).encode() // rent allowance
 		));
 
@@ -1006,7 +980,7 @@ fn removals(trigger_call: impl Fn() -> bool) {
 		assert_eq!(Balances::free_balance(BOB), 50 + Balances::minimum_balance());
 
 		// Transfer funds
-		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::transfer()));
+		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::transfer()));
 		assert_eq!(ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000);
 		assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance());
 
@@ -1036,23 +1010,23 @@ fn call_removed_contract() {
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		// Create
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm.clone()));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			100,
-			100_000, code_hash.into(),
+			GAS_LIMIT, code_hash.into(),
 			<Test as pallet_balances::Trait>::Balance::from(1_000u32).encode() // rent allowance
 		));
 
 		// Calling contract should succeed.
-		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()));
+		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
 
 		// Advance blocks
 		initialize_block(10);
 
 		// Calling contract should remove contract and fail.
-		assert_err!(
-			Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()),
+		assert_err_ignore_postinfo!(
+			Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()),
 			"contract has been evicted"
 		);
 		// Calling a contract that is about to evict shall emit an event.
@@ -1065,8 +1039,8 @@ fn call_removed_contract() {
 		]);
 
 		// Subsequent contract calls should also fail.
-		assert_err!(
-			Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()),
+		assert_err_ignore_postinfo!(
+			Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()),
 			"contract has been evicted"
 		);
 	})
@@ -1080,11 +1054,11 @@ fn default_rent_allowance_on_instantiate() {
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		// Create
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			30_000,
-			100_000,
+			GAS_LIMIT,
 			code_hash.into(),
 			vec![],
 		));
@@ -1097,7 +1071,7 @@ fn default_rent_allowance_on_instantiate() {
 		initialize_block(5);
 
 		// Trigger rent through call
-		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()));
+		assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
 
 		// Check contract is still alive
 		let bob_contract = ContractInfoOf::<Test>::get(BOB).unwrap().get_alive();
@@ -1133,8 +1107,8 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:
 
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, restoration_wasm));
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, set_rent_wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), restoration_wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), set_rent_wasm));
 
 		// If you ever need to update the wasm source this test will fail
 		// and will show you the actual hash.
@@ -1166,7 +1140,7 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			30_000,
-			100_000,
+			GAS_LIMIT,
 			set_rent_code_hash.into(),
 			<Test as pallet_balances::Trait>::Balance::from(0u32).encode()
 		));
@@ -1179,7 +1153,7 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:
 		if test_different_storage {
 			assert_ok!(Contracts::call(
 				Origin::signed(ALICE),
-				BOB, 0, 100_000,
+				BOB, 0, GAS_LIMIT,
 				call::set_storage_4_byte())
 			);
 		}
@@ -1192,8 +1166,8 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:
 			.get_alive().unwrap().code_hash;
 		// Call `BOB`, which makes it pay rent. Since the rent allowance is set to 0
 		// we expect that it will get removed leaving tombstone.
-		assert_err!(
-			Contracts::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()),
+		assert_err_ignore_postinfo!(
+			Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()),
 			"contract has been evicted"
 		);
 		assert!(ContractInfoOf::<Test>::get(BOB).unwrap().get_tombstone().is_some());
@@ -1215,7 +1189,7 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(CHARLIE),
 			30_000,
-			100_000,
+			GAS_LIMIT,
 			restoration_code_hash.into(),
 			<Test as pallet_balances::Trait>::Balance::from(0u32).encode()
 		));
@@ -1235,7 +1209,7 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:
 			Origin::signed(ALICE),
 			DJANGO,
 			0,
-			100_000,
+			GAS_LIMIT,
 			vec![],
 		));
 
@@ -1349,11 +1323,11 @@ fn storage_max_value_limit() {
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		// Create
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			30_000,
-			100_000,
+			GAS_LIMIT,
 			code_hash.into(),
 			vec![],
 		));
@@ -1367,17 +1341,17 @@ fn storage_max_value_limit() {
 			Origin::signed(ALICE),
 			BOB,
 			0,
-			100_000,
+			GAS_LIMIT,
 			Encode::encode(&self::MaxValueSize::get()),
 		));
 
 		// Call contract with too large a storage value.
-		assert_err!(
+		assert_err_ignore_postinfo!(
 			Contracts::call(
 				Origin::signed(ALICE),
 				BOB,
 				0,
-				100_000,
+				GAS_LIMIT,
 				Encode::encode(&(self::MaxValueSize::get() + 1)),
 			),
 			"contract trapped during execution"
@@ -1395,13 +1369,13 @@ fn deploy_and_call_other_contract() {
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		// Create
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, callee_wasm));
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, caller_wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm));
 
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			100_000,
-			100_000,
+			GAS_LIMIT,
 			caller_code_hash.into(),
 			vec![],
 		));
@@ -1412,41 +1386,24 @@ fn deploy_and_call_other_contract() {
 			Origin::signed(ALICE),
 			BOB,
 			0,
-			200_000,
+			GAS_LIMIT,
 			callee_code_hash.as_ref().to_vec(),
 		));
 	});
 }
 
-#[test]
-fn deploy_works_without_gas_price() {
-	let (wasm, code_hash) = compile_module::<Test>(&load_wasm("get_runtime_storage.wat"))
-		.unwrap();
-	ExtBuilder::default().existential_deposit(50).gas_price(0).build().execute_with(|| {
-		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
-		assert_ok!(Contracts::instantiate(
-			Origin::signed(ALICE),
-			100,
-			100_000,
-			code_hash.into(),
-			vec![],
-		));
-	});
-}
-
 #[test]
 fn cannot_self_destruct_through_draning() {
 	let (wasm, code_hash) = compile_module::<Test>(&load_wasm("drain.wat")).unwrap();
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 
 		// Instantiate the BOB contract.
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			100_000,
-			100_000,
+			GAS_LIMIT,
 			code_hash.into(),
 			vec![],
 		));
@@ -1459,12 +1416,12 @@ fn cannot_self_destruct_through_draning() {
 
 		// Call BOB with no input data, forcing it to run until out-of-balance
 		// and eventually trapping because below existential deposit.
-		assert_err!(
+		assert_err_ignore_postinfo!(
 			Contracts::call(
 				Origin::signed(ALICE),
 				BOB,
 				0,
-				100_000,
+				GAS_LIMIT,
 				vec![],
 			),
 			"contract trapped during execution"
@@ -1478,13 +1435,13 @@ fn cannot_self_destruct_while_live() {
 		.unwrap();
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 
 		// Instantiate the BOB contract.
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			100_000,
-			100_000,
+			GAS_LIMIT,
 			code_hash.into(),
 			vec![],
 		));
@@ -1497,12 +1454,12 @@ fn cannot_self_destruct_while_live() {
 
 		// Call BOB with input data, forcing it make a recursive call to itself to
 		// self-destruct, resulting in a trap.
-		assert_err!(
+		assert_err_ignore_postinfo!(
 			Contracts::call(
 				Origin::signed(ALICE),
 				BOB,
 				0,
-				100_000,
+				GAS_LIMIT,
 				vec![0],
 			),
 			"contract trapped during execution"
@@ -1522,13 +1479,13 @@ fn self_destruct_works() {
 		.unwrap();
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 
 		// Instantiate the BOB contract.
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			100_000,
-			100_000,
+			GAS_LIMIT,
 			code_hash.into(),
 			vec![],
 		));
@@ -1545,10 +1502,10 @@ fn self_destruct_works() {
 				Origin::signed(ALICE),
 				BOB,
 				0,
-				100_000,
+				GAS_LIMIT,
 				vec![],
 			),
-			Ok(())
+			Ok(_)
 		);
 
 		// Check that account is gone
@@ -1571,15 +1528,15 @@ fn destroy_contract_and_transfer_funds() {
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		// Create
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, callee_wasm));
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, caller_wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm));
 
 		// This deploys the BOB contract, which in turn deploys the CHARLIE contract during
 		// construction.
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			200_000,
-			100_000,
+			GAS_LIMIT,
 			caller_code_hash.into(),
 			callee_code_hash.as_ref().to_vec(),
 		));
@@ -1595,7 +1552,7 @@ fn destroy_contract_and_transfer_funds() {
 			Origin::signed(ALICE),
 			BOB,
 			0,
-			100_000,
+			GAS_LIMIT,
 			CHARLIE.encode(),
 		));
 
@@ -1610,15 +1567,15 @@ fn cannot_self_destruct_in_constructor() {
 		compile_module::<Test>(&load_wasm("self_destructing_constructor.wat")).unwrap();
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 
 		// Fail to instantiate the BOB because the call that is issued in the deploy
 		// function exhausts all balances which puts it below the existential deposit.
-		assert_err!(
+		assert_err_ignore_postinfo!(
 			Contracts::instantiate(
 				Origin::signed(ALICE),
 				100_000,
-				100_000,
+				GAS_LIMIT,
 				code_hash.into(),
 				vec![],
 			),
@@ -1627,23 +1584,6 @@ fn cannot_self_destruct_in_constructor() {
 	});
 }
 
-#[test]
-fn check_block_gas_limit_works() {
-	ExtBuilder::default().block_gas_limit(50).build().execute_with(|| {
-		let info = DispatchInfo { weight: 100, class: DispatchClass::Normal, pays_fee: Pays::Yes };
-		let check = CheckBlockGasLimit::<Test>(Default::default());
-		let call: Call = crate::Call::put_code(1000, vec![]).into();
-
-		assert_eq!(
-			check.validate(&0, &call, &info, 0), InvalidTransaction::ExhaustsResources.into(),
-		);
-
-		let call: Call = crate::Call::update_schedule(Default::default()).into();
-		assert_eq!(check.validate(&0, &call, &info, 0), Ok(Default::default()));
-	});
-}
-
-#[test]
 fn get_runtime_storage() {
 	let (wasm, code_hash) = compile_module::<Test>(&load_wasm("get_runtime_storage.wat"))
 		.unwrap();
@@ -1655,11 +1595,11 @@ fn get_runtime_storage() {
 			0x14144020u32.to_le_bytes().to_vec().as_ref()
 		);
 
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			100,
-			100_000,
+			GAS_LIMIT,
 			code_hash.into(),
 			vec![],
 		));
@@ -1667,7 +1607,7 @@ fn get_runtime_storage() {
 			Origin::signed(ALICE),
 			BOB,
 			0,
-			100_000,
+			GAS_LIMIT,
 			vec![],
 		));
 	});
@@ -1679,13 +1619,13 @@ fn crypto_hashes() {
 
 	ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
 		Balances::deposit_creating(&ALICE, 1_000_000);
-		assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm));
+		assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 
 		// Instantiate the CRYPTO_HASHES contract.
 		assert_ok!(Contracts::instantiate(
 			Origin::signed(ALICE),
 			100_000,
-			100_000,
+			GAS_LIMIT,
 			code_hash.into(),
 			vec![],
 		));
@@ -1714,7 +1654,7 @@ fn crypto_hashes() {
 				ALICE,
 				BOB,
 				0,
-				100_000,
+				GAS_LIMIT,
 				params,
 			).unwrap();
 			assert_eq!(result.status, 0);
diff --git a/substrate/frame/contracts/src/wasm/code_cache.rs b/substrate/frame/contracts/src/wasm/code_cache.rs
index cb942a25892cd1553b381ab8f856329c395e188a..ba7a02356d2826c649afd8ae6dcd5b8bfb62ab27 100644
--- a/substrate/frame/contracts/src/wasm/code_cache.rs
+++ b/substrate/frame/contracts/src/wasm/code_cache.rs
@@ -26,49 +26,20 @@
 //! this guarantees that every instrumented contract code in cache cannot have the version equal to the current one.
 //! Thus, before executing a contract it should be reinstrument with new schedule.
 
-use crate::gas::{Gas, GasMeter, Token};
 use crate::wasm::{prepare, runtime::Env, PrefabWasmModule};
 use crate::{CodeHash, CodeStorage, PristineCode, Schedule, Trait};
 use sp_std::prelude::*;
-use sp_runtime::traits::{Hash, Bounded};
+use sp_runtime::traits::Hash;
 use frame_support::StorageMap;
 
-/// Gas metering token that used for charging storing code into the code storage.
-///
-/// Specifies the code length in bytes.
-#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
-#[derive(Copy, Clone)]
-pub struct PutCodeToken(u32);
-
-impl<T: Trait> Token<T> for PutCodeToken {
-	type Metadata = Schedule;
-
-	fn calculate_amount(&self, metadata: &Schedule) -> Gas {
-		metadata
-			.put_code_per_byte_cost
-			.checked_mul(self.0.into())
-			.unwrap_or_else(|| Bounded::max_value())
-	}
-}
-
 /// Put code in the storage. The hash of code is used as a key and is returned
 /// as a result of this function.
 ///
 /// This function instruments the given code and caches it in the storage.
 pub fn save<T: Trait>(
 	original_code: Vec<u8>,
-	gas_meter: &mut GasMeter<T>,
 	schedule: &Schedule,
 ) -> Result<CodeHash<T>, &'static str> {
-	// The first time instrumentation is on the user. However, consequent reinstrumentation
-	// due to the schedule changes is on governance system.
-	if gas_meter
-		.charge(schedule, PutCodeToken(original_code.len() as u32))
-		.is_out_of_gas()
-	{
-		return Err("there is not enough gas for storing the code");
-	}
-
 	let prefab_module = prepare::prepare_contract::<Env>(&original_code, schedule)?;
 	let code_hash = T::Hashing::hash(&original_code);
 
diff --git a/substrate/frame/contracts/src/wasm/mod.rs b/substrate/frame/contracts/src/wasm/mod.rs
index 8911fb72b6130c66fa1cf7d88d6fcc86b062b5dd..cb69cd689b2657fa159eec447f1ed569cfc4a434 100644
--- a/substrate/frame/contracts/src/wasm/mod.rs
+++ b/substrate/frame/contracts/src/wasm/mod.rs
@@ -157,12 +157,14 @@ mod tests {
 	use crate::gas::{Gas, GasMeter};
 	use crate::tests::{Test, Call};
 	use crate::wasm::prepare::prepare_contract;
-	use crate::CodeHash;
+	use crate::{CodeHash, BalanceOf};
 	use wabt;
 	use hex_literal::hex;
 	use assert_matches::assert_matches;
 	use sp_runtime::DispatchError;
 
+	const GAS_LIMIT: Gas = 10_000_000_000;
+
 	#[derive(Debug, PartialEq, Eq)]
 	struct DispatchEntry(Call);
 
@@ -373,6 +375,9 @@ mod tests {
 				)
 			)
 		}
+		fn get_weight_price(&self) -> BalanceOf<Self::T> {
+			1312_u32.into()
+		}
 	}
 
 	impl Ext for &mut MockExt {
@@ -478,6 +483,9 @@ mod tests {
 		fn get_runtime_storage(&self, key: &[u8]) -> Option<Vec<u8>> {
 			(**self).get_runtime_storage(key)
 		}
+		fn get_weight_price(&self) -> BalanceOf<Self::T> {
+			(**self).get_weight_price()
+		}
 	}
 
 	fn execute<E: Ext>(
@@ -544,7 +552,7 @@ mod tests {
 			CODE_TRANSFER,
 			vec![],
 			&mut mock_ext,
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 
 		assert_eq!(
@@ -553,7 +561,7 @@ mod tests {
 				to: 7,
 				value: 153,
 				data: Vec::new(),
-				gas_left: 49978,
+				gas_left: 9989000000,
 			}]
 		);
 	}
@@ -604,7 +612,7 @@ mod tests {
 			CODE_CALL,
 			vec![],
 			&mut mock_ext,
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 
 		assert_eq!(
@@ -613,7 +621,7 @@ mod tests {
 				to: 9,
 				value: 6,
 				data: vec![1, 2, 3, 4],
-				gas_left: 49971,
+				gas_left: 9985500000,
 			}]
 		);
 	}
@@ -666,7 +674,7 @@ mod tests {
 			CODE_INSTANTIATE,
 			vec![],
 			&mut mock_ext,
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 
 		assert_eq!(
@@ -675,7 +683,7 @@ mod tests {
 				code_hash: [0x11; 32].into(),
 				endowment: 3,
 				data: vec![1, 2, 3, 4],
-				gas_left: 49947,
+				gas_left: 9973500000,
 			}]
 		);
 	}
@@ -709,14 +717,14 @@ mod tests {
 			CODE_TERMINATE,
 			vec![],
 			&mut mock_ext,
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 
 		assert_eq!(
 			&mock_ext.terminations,
 			&[TerminationEntry {
 				beneficiary: 0x09,
-				gas_left: 49989,
+				gas_left: 9994500000,
 			}]
 		);
 	}
@@ -767,7 +775,7 @@ mod tests {
 			&CODE_TRANSFER_LIMITED_GAS,
 			vec![],
 			&mut mock_ext,
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 
 		assert_eq!(
@@ -860,7 +868,7 @@ mod tests {
 			CODE_GET_STORAGE,
 			vec![],
 			mock_ext,
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 
 		assert_eq!(output, ExecReturnValue { status: STATUS_SUCCESS, data: [0x22; 32].to_vec() });
@@ -924,7 +932,7 @@ mod tests {
 			CODE_CALLER,
 			vec![],
 			MockExt::default(),
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 	}
 
@@ -986,7 +994,7 @@ mod tests {
 			CODE_ADDRESS,
 			vec![],
 			MockExt::default(),
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 	}
 
@@ -1041,7 +1049,7 @@ mod tests {
 
 	#[test]
 	fn balance() {
-		let mut gas_meter = GasMeter::with_limit(50_000, 1);
+		let mut gas_meter = GasMeter::new(GAS_LIMIT);
 		let _ = execute(
 			CODE_BALANCE,
 			vec![],
@@ -1101,7 +1109,7 @@ mod tests {
 
 	#[test]
 	fn gas_price() {
-		let mut gas_meter = GasMeter::with_limit(50_000, 1312);
+		let mut gas_meter = GasMeter::new(GAS_LIMIT);
 		let _ = execute(
 			CODE_GAS_PRICE,
 			vec![],
@@ -1159,7 +1167,7 @@ mod tests {
 
 	#[test]
 	fn gas_left() {
-		let mut gas_meter = GasMeter::with_limit(50_000, 1312);
+		let mut gas_meter = GasMeter::new(GAS_LIMIT);
 
 		let output = execute(
 			CODE_GAS_LEFT,
@@ -1169,7 +1177,7 @@ mod tests {
 		).unwrap();
 
 		let gas_left = Gas::decode(&mut output.data.as_slice()).unwrap();
-		assert!(gas_left < 50_000, "gas_left must be less than initial");
+		assert!(gas_left < GAS_LIMIT, "gas_left must be less than initial");
 		assert!(gas_left > gas_meter.gas_left(), "gas_left must be greater than final");
 	}
 
@@ -1224,7 +1232,7 @@ mod tests {
 
 	#[test]
 	fn value_transferred() {
-		let mut gas_meter = GasMeter::with_limit(50_000, 1);
+		let mut gas_meter = GasMeter::new(GAS_LIMIT);
 		let _ = execute(
 			CODE_VALUE_TRANSFERRED,
 			vec![],
@@ -1260,7 +1268,7 @@ mod tests {
 			CODE_DISPATCH_CALL,
 			vec![],
 			&mut mock_ext,
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 
 		assert_eq!(
@@ -1300,7 +1308,7 @@ mod tests {
 			CODE_RETURN_FROM_START_FN,
 			vec![],
 			MockExt::default(),
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 
 		assert_eq!(output, ExecReturnValue { status: STATUS_SUCCESS, data: vec![1, 2, 3, 4] });
@@ -1357,7 +1365,7 @@ mod tests {
 
 	#[test]
 	fn now() {
-		let mut gas_meter = GasMeter::with_limit(50_000, 1);
+		let mut gas_meter = GasMeter::new(GAS_LIMIT);
 		let _ = execute(
 			CODE_TIMESTAMP_NOW,
 			vec![],
@@ -1416,7 +1424,7 @@ mod tests {
 
 	#[test]
 	fn minimum_balance() {
-		let mut gas_meter = GasMeter::with_limit(50_000, 1);
+		let mut gas_meter = GasMeter::new(GAS_LIMIT);
 		let _ = execute(
 			CODE_MINIMUM_BALANCE,
 			vec![],
@@ -1475,7 +1483,7 @@ mod tests {
 
 	#[test]
 	fn tombstone_deposit() {
-		let mut gas_meter = GasMeter::with_limit(50_000, 1);
+		let mut gas_meter = GasMeter::new(GAS_LIMIT);
 		let _ = execute(
 			CODE_TOMBSTONE_DEPOSIT,
 			vec![],
@@ -1543,7 +1551,7 @@ mod tests {
 
 	#[test]
 	fn random() {
-		let mut gas_meter = GasMeter::with_limit(50_000, 1);
+		let mut gas_meter = GasMeter::new(GAS_LIMIT);
 
 		let output = execute(
 			CODE_RANDOM,
@@ -1588,7 +1596,7 @@ mod tests {
 	#[test]
 	fn deposit_event() {
 		let mut mock_ext = MockExt::default();
-		let mut gas_meter = GasMeter::with_limit(50_000, 1);
+		let mut gas_meter = GasMeter::new(GAS_LIMIT);
 		let _ = execute(
 			CODE_DEPOSIT_EVENT,
 			vec![],
@@ -1601,7 +1609,7 @@ mod tests {
 			vec![0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00])
 		]);
 
-		assert_eq!(gas_meter.gas_left(), 49934);
+		assert_eq!(gas_meter.gas_left(), 9967000000);
 	}
 
 	const CODE_DEPOSIT_EVENT_MAX_TOPICS: &str = r#"
@@ -1634,7 +1642,7 @@ mod tests {
 	#[test]
 	fn deposit_event_max_topics() {
 		// Checks that the runtime traps if there are more than `max_topic_events` topics.
-		let mut gas_meter = GasMeter::with_limit(50_000, 1);
+		let mut gas_meter = GasMeter::new(GAS_LIMIT);
 
 		assert_matches!(
 			execute(
@@ -1678,7 +1686,7 @@ mod tests {
 	#[test]
 	fn deposit_event_duplicates() {
 		// Checks that the runtime traps if there are duplicates.
-		let mut gas_meter = GasMeter::with_limit(50_000, 1);
+		let mut gas_meter = GasMeter::new(GAS_LIMIT);
 
 		assert_matches!(
 			execute(
@@ -1749,7 +1757,7 @@ mod tests {
 			CODE_BLOCK_NUMBER,
 			vec![],
 			MockExt::default(),
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 	}
 
@@ -1789,7 +1797,7 @@ mod tests {
 			CODE_SIMPLE_ASSERT,
 			input_data,
 			MockExt::default(),
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 
 		assert_eq!(output.data.len(), 0);
@@ -1805,7 +1813,7 @@ mod tests {
 			CODE_SIMPLE_ASSERT,
 			input_data,
 			MockExt::default(),
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).err().unwrap();
 
 		assert_eq!(error.buffer.capacity(), 1_234);
@@ -1859,7 +1867,7 @@ mod tests {
 			CODE_RETURN_WITH_DATA,
 			hex!("00112233445566778899").to_vec(),
 			MockExt::default(),
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 
 		assert_eq!(output, ExecReturnValue { status: 0, data: hex!("445566778899").to_vec() });
@@ -1872,7 +1880,7 @@ mod tests {
 			CODE_RETURN_WITH_DATA,
 			hex!("112233445566778899").to_vec(),
 			MockExt::default(),
-			&mut GasMeter::with_limit(50_000, 1),
+			&mut GasMeter::new(GAS_LIMIT),
 		).unwrap();
 
 		assert_eq!(output, ExecReturnValue { status: 17, data: hex!("5566778899").to_vec() });
@@ -1958,7 +1966,7 @@ mod tests {
 
 	#[test]
 	fn get_runtime_storage() {
-		let mut gas_meter = GasMeter::with_limit(50_000, 1);
+		let mut gas_meter = GasMeter::new(GAS_LIMIT);
 		let mock_ext = MockExt::default();
 
 		// "\01\02\03\04" - Some(0x14144020)
diff --git a/substrate/frame/contracts/src/wasm/runtime.rs b/substrate/frame/contracts/src/wasm/runtime.rs
index 7cede5542fc6f8bde389f6b99fc960b7b3512e24..f87f5d1ef53cc962ee88cad097b6e524259d6f54 100644
--- a/substrate/frame/contracts/src/wasm/runtime.rs
+++ b/substrate/frame/contracts/src/wasm/runtime.rs
@@ -16,11 +16,11 @@
 
 //! Environment definition of the wasm smart-contract runtime.
 
-use crate::{Schedule, Trait, CodeHash, ComputeDispatchFee, BalanceOf};
+use crate::{Schedule, Trait, CodeHash, BalanceOf};
 use crate::exec::{
 	Ext, ExecResult, ExecError, ExecReturnValue, StorageKey, TopicOf, STATUS_SUCCESS,
 };
-use crate::gas::{Gas, GasMeter, Token, GasMeterResult, approx_gas_for_balance};
+use crate::gas::{Gas, GasMeter, Token, GasMeterResult};
 use sp_sandbox;
 use frame_system;
 use sp_std::{prelude::*, mem, convert::TryInto};
@@ -32,6 +32,7 @@ use sp_io::hashing::{
 	blake2_128,
 	sha2_256,
 };
+use frame_support::weights::GetDispatchInfo;
 
 /// The value returned from ext_call and ext_instantiate contract external functions if the call or
 /// instantiation traps. This value is chosen as if the execution does not trap, the return value
@@ -153,8 +154,8 @@ pub enum RuntimeToken {
 	/// The given number of bytes is read from the sandbox memory and
 	/// is returned as the return data buffer of the call.
 	ReturnData(u32),
-	/// Dispatch fee calculated by `T::ComputeDispatchFee`.
-	ComputedDispatchFee(Gas),
+	/// Dispatched a call with the given weight.
+	DispatchWithWeight(Gas),
 	/// (topic_count, data_bytes): A buffer of the given size is posted as an event indexed with the
 	/// given number of topics.
 	DepositEvent(u32, u32),
@@ -195,7 +196,7 @@ impl<T: Trait> Token<T> for RuntimeToken {
 						data_and_topics_cost.checked_add(metadata.event_base_cost)
 					)
 			},
-			ComputedDispatchFee(gas) => Some(gas),
+			DispatchWithWeight(gas) => gas.checked_add(metadata.dispatch_base_cost),
 		};
 
 		value.unwrap_or_else(|| Bounded::max_value())
@@ -692,7 +693,7 @@ define_env!(Env, <E: Ext>,
 	// The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten.
 	ext_gas_price(ctx) => {
 		ctx.scratch_buf.clear();
-		ctx.gas_meter.gas_price().encode_to(&mut ctx.scratch_buf);
+		ctx.ext.get_weight_price().encode_to(&mut ctx.scratch_buf);
 		Ok(())
 	},
 
@@ -783,16 +784,14 @@ define_env!(Env, <E: Ext>,
 		let call: <<E as Ext>::T as Trait>::Call =
 			read_sandbox_memory_as(ctx, call_ptr, call_len)?;
 
-		// Charge gas for dispatching this call.
-		let fee = {
-			let balance_fee = <<E as Ext>::T as Trait>::ComputeDispatchFee::compute_dispatch_fee(&call);
-			approx_gas_for_balance(ctx.gas_meter.gas_price(), balance_fee)
-		};
+		// We already deducted the len costs when reading from the sandbox.
+		// Bill on the actual weight of the dispatched call.
+		let info = call.get_dispatch_info();
 		charge_gas(
 			&mut ctx.gas_meter,
 			ctx.schedule,
 			&mut ctx.special_trap,
-			RuntimeToken::ComputedDispatchFee(fee)
+			RuntimeToken::DispatchWithWeight(info.weight)
 		)?;
 
 		ctx.ext.note_dispatch_call(call);
diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs
index df987e0b0bac6e360a2b571f2ac52507dbd24cdb..b0e7395e9ff2f36ea03f32b3fdb27f233fb031e4 100644
--- a/substrate/frame/support/src/lib.rs
+++ b/substrate/frame/support/src/lib.rs
@@ -193,10 +193,6 @@ macro_rules! assert_noop {
 	}
 }
 
-/// Panic if an expression doesn't evaluate to an `Err`.
-///
-/// Used as `assert_err!(expression_to_assert, expected_err_expression)`.
-
 /// Assert an expression returns an error specified.
 ///
 /// Used as `assert_err!(expression_to_assert, expected_error_expression)`
@@ -208,6 +204,18 @@ macro_rules! assert_err {
 	}
 }
 
+/// Assert an expression returns an error specified.
+///
+/// This can be used on`DispatchResultWithPostInfo` when the post info should
+/// be ignored.
+#[macro_export]
+#[cfg(feature = "std")]
+macro_rules! assert_err_ignore_postinfo {
+	( $x:expr , $y:expr $(,)? ) => {
+		assert_err!($x.map(|_| ()).map_err(|e| e.error), $y);
+	}
+}
+
 /// Panic if an expression doesn't evaluate to `Ok`.
 ///
 /// Used as `assert_ok!(expression_to_assert, expected_ok_expression)`,
diff --git a/substrate/frame/transaction-payment/src/lib.rs b/substrate/frame/transaction-payment/src/lib.rs
index 95845990b8e43b017d4aa680908025ef836a6394..6caca4c23ba36f9917799f4208215e95feb621d0 100644
--- a/substrate/frame/transaction-payment/src/lib.rs
+++ b/substrate/frame/transaction-payment/src/lib.rs
@@ -47,7 +47,7 @@ use sp_runtime::{
 	},
 	traits::{
 		Zero, Saturating, SignedExtension, SaturatedConversion, Convert, Dispatchable,
-		DispatchInfoOf, PostDispatchInfoOf,
+		DispatchInfoOf, PostDispatchInfoOf, UniqueSaturatedFrom, UniqueSaturatedInto,
 	},
 };
 use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
@@ -116,9 +116,7 @@ decl_module! {
 	}
 }
 
-impl<T: Trait> Module<T> where
-	T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo>,
-{
+impl<T: Trait> Module<T> {
 	/// Query the data that we know about the fee of a given `call`.
 	///
 	/// As this module is not and cannot be aware of the internals of a signed extension, it only
@@ -133,6 +131,7 @@ impl<T: Trait> Module<T> where
 	where
 		T: Send + Sync,
 		BalanceOf<T>: Send + Sync,
+		T::Call: Dispatchable<Info=DispatchInfo>,
 	{
 		// NOTE: we can actually make it understand `ChargeTransactionPayment`, but would be some
 		// hassle for sure. We have to make it aware of the index of `ChargeTransactionPayment` in
@@ -165,7 +164,9 @@ impl<T: Trait> Module<T> where
 		len: u32,
 		info: &DispatchInfoOf<T::Call>,
 		tip: BalanceOf<T>,
-	) -> BalanceOf<T> {
+	) -> BalanceOf<T> where
+		T::Call: Dispatchable<Info=DispatchInfo>,
+	{
 		if info.pays_fee == Pays::Yes {
 			let len = <BalanceOf<T>>::from(len);
 			let per_byte = T::TransactionByteFee::get();
@@ -188,11 +189,12 @@ impl<T: Trait> Module<T> where
 	///
 	/// This fee is already adjusted by the per block fee adjustment factor and is therefore
 	/// the share that the weight contributes to the overall fee of a transaction.
-	pub fn weight_to_fee_with_adjustment(weight: Weight) -> BalanceOf<T> where
-		BalanceOf<T>: From<u64>
+	pub fn weight_to_fee_with_adjustment<Balance>(weight: Weight) -> Balance where
+		Balance: UniqueSaturatedFrom<u128>
 	{
-		NextFeeMultiplier::get().saturated_multiply_accumulate(
-			Self::weight_to_fee(weight)
+		let fee = UniqueSaturatedInto::<u128>::unique_saturated_into(Self::weight_to_fee(weight));
+		UniqueSaturatedFrom::unique_saturated_from(
+			NextFeeMultiplier::get().saturated_multiply_accumulate(fee)
 		)
 	}