diff --git a/prdoc/pr_5556.prdoc b/prdoc/pr_5556.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..4865ec1e338d652af4c37f9f271c5f1869871212
--- /dev/null
+++ b/prdoc/pr_5556.prdoc
@@ -0,0 +1,11 @@
+title: Make salt optional
+
+doc:
+  - audience: Runtime Dev
+    description: |
+     By making salt optional we allow clients to use CREATE1 semantics
+     when deploying a new contract.
+
+crates:
+  - name: pallet-revive
+    bump: major
diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index 7ef0779dd9b842de7b2b39a508f3d76f7dcdaa82..31584427b3b65980eb64b64e56d3e60e97400373 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -3017,7 +3017,7 @@ impl_runtime_apis! {
 			storage_deposit_limit: Option<Balance>,
 			code: pallet_revive::Code,
 			data: Vec<u8>,
-			salt: [u8; 32],
+			salt: Option<[u8; 32]>,
 		) -> pallet_revive::ContractInstantiateResult<Balance, EventRecord>
 		{
 			Revive::bare_instantiate(
diff --git a/substrate/frame/revive/src/address.rs b/substrate/frame/revive/src/address.rs
index f1bd36dcbba862055e6df616a8982dc980b26732..c51940ba771e6ba81cb8fadb27a23a4eed655bd7 100644
--- a/substrate/frame/revive/src/address.rs
+++ b/substrate/frame/revive/src/address.rs
@@ -76,7 +76,6 @@ impl AddressMapper<AccountId32> for DefaultAddressMapper {
 }
 
 /// Determine the address of a contract using CREATE semantics.
-#[allow(dead_code)]
 pub fn create1(deployer: &H160, nonce: u64) -> H160 {
 	let mut list = rlp::RlpStream::new_list(2);
 	list.append(&deployer.as_bytes());
diff --git a/substrate/frame/revive/src/benchmarking/mod.rs b/substrate/frame/revive/src/benchmarking/mod.rs
index 409d53b8a0627d79ce0422e99da1c79314103e3e..3ffd53e3561cc1f9e42789834fdb8ccf6f84f1fd 100644
--- a/substrate/frame/revive/src/benchmarking/mod.rs
+++ b/substrate/frame/revive/src/benchmarking/mod.rs
@@ -94,7 +94,7 @@ where
 		data: Vec<u8>,
 	) -> Result<Contract<T>, &'static str> {
 		T::Currency::set_balance(&caller, caller_funding::<T>());
-		let salt = [0xffu8; 32];
+		let salt = Some([0xffu8; 32]);
 
 		let outcome = Contracts::<T>::bare_instantiate(
 			RawOrigin::Signed(caller.clone()).into(),
@@ -344,7 +344,6 @@ mod benchmarks {
 
 	// `c`: Size of the code in bytes.
 	// `i`: Size of the input in bytes.
-	// `s`: Size of the salt in bytes.
 	#[benchmark(pov_mode = Measured)]
 	fn instantiate_with_code(
 		c: Linear<0, { T::MaxCodeLen::get() }>,
@@ -362,7 +361,7 @@ mod benchmarks {
 		let account_id = T::AddressMapper::to_account_id_contract(&addr);
 		let storage_deposit = default_deposit_limit::<T>();
 		#[extrinsic_call]
-		_(origin, value, Weight::MAX, storage_deposit, code, input, salt);
+		_(origin, value, Weight::MAX, storage_deposit, code, input, Some(salt));
 
 		let deposit =
 			T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &account_id);
@@ -378,7 +377,7 @@ mod benchmarks {
 	}
 
 	// `i`: Size of the input in bytes.
-	// `s`: Size of the salt in bytes.
+	// `s`: Size of e salt in bytes.
 	#[benchmark(pov_mode = Measured)]
 	fn instantiate(i: Linear<0, { limits::MEMORY_BYTES }>) -> Result<(), BenchmarkError> {
 		let input = vec![42u8; i as usize];
@@ -403,7 +402,7 @@ mod benchmarks {
 			storage_deposit,
 			hash,
 			input,
-			salt,
+			Some(salt),
 		);
 
 		let deposit =
@@ -1529,7 +1528,6 @@ mod benchmarks {
 
 	// t: value to transfer
 	// i: size of input in bytes
-	// s: size of salt in bytes
 	#[benchmark(pov_mode = Measured)]
 	fn seal_instantiate(i: Linear<0, { limits::MEMORY_BYTES }>) -> Result<(), BenchmarkError> {
 		let code = WasmModule::dummy();
diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs
index 54019a6ba9928a23784c5d4c3b9b9a783c3e6240..649479f7790f36a495412a36609600e4e508d65b 100644
--- a/substrate/frame/revive/src/exec.rs
+++ b/substrate/frame/revive/src/exec.rs
@@ -54,7 +54,7 @@ use sp_core::{
 use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256};
 use sp_runtime::{
 	traits::{BadOrigin, Convert, Dispatchable, Zero},
-	DispatchError,
+	DispatchError, SaturatedConversion,
 };
 
 pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
@@ -213,7 +213,7 @@ pub trait Ext: sealing::Sealed {
 		code: H256,
 		value: BalanceOf<Self::T>,
 		input_data: Vec<u8>,
-		salt: &[u8; 32],
+		salt: Option<&[u8; 32]>,
 	) -> Result<(H160, ExecReturnValue), ExecError>;
 
 	/// Transfer all funds to `beneficiary` and delete the contract.
@@ -573,7 +573,7 @@ enum FrameArgs<'a, T: Config, E> {
 		/// The executable whose `deploy` function is run.
 		executable: E,
 		/// A salt used in the contract address derivation of the new contract.
-		salt: &'a [u8; 32],
+		salt: Option<&'a [u8; 32]>,
 		/// The input data is used in the contract address derivation of the new contract.
 		input_data: &'a [u8],
 	},
@@ -750,7 +750,7 @@ where
 		storage_meter: &'a mut storage::meter::Meter<T>,
 		value: BalanceOf<T>,
 		input_data: Vec<u8>,
-		salt: &[u8; 32],
+		salt: Option<&[u8; 32]>,
 		debug_message: Option<&'a mut DebugBuffer>,
 	) -> Result<(H160, ExecReturnValue), ExecError> {
 		let (mut stack, executable) = Self::new(
@@ -863,7 +863,12 @@ where
 			},
 			FrameArgs::Instantiate { sender, executable, salt, input_data } => {
 				let deployer = T::AddressMapper::to_address(&sender);
-				let address = address::create2(&deployer, executable.code(), input_data, salt);
+				let account_nonce = <System<T>>::account_nonce(&sender);
+				let address = if let Some(salt) = salt {
+					address::create2(&deployer, executable.code(), input_data, salt)
+				} else {
+					address::create1(&deployer, account_nonce.saturated_into())
+				};
 				let contract = ContractInfo::new(
 					&address,
 					<System<T>>::account_nonce(&sender),
@@ -1321,7 +1326,7 @@ where
 		code_hash: H256,
 		value: BalanceOf<T>,
 		input_data: Vec<u8>,
-		salt: &[u8; 32],
+		salt: Option<&[u8; 32]>,
 	) -> Result<(H160, ExecReturnValue), ExecError> {
 		let executable = E::from_storage(code_hash, self.gas_meter_mut())?;
 		let sender = &self.top_frame().account_id;
@@ -2088,7 +2093,7 @@ mod tests {
 					&mut storage_meter,
 					min_balance,
 					vec![1, 2, 3, 4],
-					&[0; 32],
+					Some(&[0; 32]),
 					None,
 				);
 				assert_matches!(result, Ok(_));
@@ -2497,7 +2502,7 @@ mod tests {
 					&mut storage_meter,
 					0, // <- zero value
 					vec![],
-					&[0; 32],
+					Some(&[0; 32]),
 					None,
 				),
 				Err(_)
@@ -2533,7 +2538,7 @@ mod tests {
 
 						min_balance,
 						vec![],
-						&[0;32],
+						Some(&[0 ;32]),
 						None,
 					),
 					Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address
@@ -2587,7 +2592,7 @@ mod tests {
 
 						min_balance,
 						vec![],
-						&[0;32],
+						Some(&[0; 32]),
 						None,
 					),
 					Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address
@@ -2620,7 +2625,7 @@ mod tests {
 						dummy_ch,
 						<Test as Config>::Currency::minimum_balance(),
 						vec![],
-						&[48; 32],
+						Some(&[48; 32]),
 					)
 					.unwrap();
 
@@ -2698,7 +2703,7 @@ mod tests {
 						dummy_ch,
 						<Test as Config>::Currency::minimum_balance(),
 						vec![],
-						&[0; 32],
+						Some(&[0; 32]),
 					),
 					Err(ExecError {
 						error: DispatchError::Other("It's a trap!"),
@@ -2771,7 +2776,7 @@ mod tests {
 						&mut storage_meter,
 						100,
 						vec![],
-						&[0; 32],
+						Some(&[0; 32]),
 						None,
 					),
 					Err(Error::<Test>::TerminatedInConstructor.into())
@@ -2882,7 +2887,7 @@ mod tests {
 					&mut storage_meter,
 					min_balance,
 					vec![],
-					&[0; 32],
+					Some(&[0; 32]),
 					None,
 				);
 				assert_matches!(result, Ok(_));
@@ -3250,7 +3255,7 @@ mod tests {
 					fail_code,
 					ctx.ext.minimum_balance() * 100,
 					vec![],
-					&[0; 32],
+					Some(&[0; 32]),
 				)
 				.ok();
 			exec_success()
@@ -3267,7 +3272,7 @@ mod tests {
 					success_code,
 					ctx.ext.minimum_balance() * 100,
 					vec![],
-					&[0; 32],
+					Some(&[0; 32]),
 				)
 				.unwrap();
 
@@ -3318,7 +3323,7 @@ mod tests {
 					&mut storage_meter,
 					min_balance * 100,
 					vec![],
-					&[0; 32],
+					Some(&[0; 32]),
 					None,
 				)
 				.ok();
@@ -3331,7 +3336,7 @@ mod tests {
 					&mut storage_meter,
 					min_balance * 100,
 					vec![],
-					&[0; 32],
+					Some(&[0; 32]),
 					None,
 				));
 				assert_eq!(System::account_nonce(&ALICE), 1);
@@ -3343,7 +3348,7 @@ mod tests {
 					&mut storage_meter,
 					min_balance * 200,
 					vec![],
-					&[0; 32],
+					Some(&[0; 32]),
 					None,
 				));
 				assert_eq!(System::account_nonce(&ALICE), 2);
@@ -3355,7 +3360,7 @@ mod tests {
 					&mut storage_meter,
 					min_balance * 200,
 					vec![],
-					&[0; 32],
+					Some(&[0; 32]),
 					None,
 				));
 				assert_eq!(System::account_nonce(&ALICE), 3);
diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs
index 359434b9abd61b03681c5554231d0789e500c21c..9a99b01776c138527c9d8a47258aaff699461320 100644
--- a/substrate/frame/revive/src/lib.rs
+++ b/substrate/frame/revive/src/lib.rs
@@ -824,7 +824,7 @@ pub mod pallet {
 		/// must be supplied.
 		#[pallet::call_index(1)]
 		#[pallet::weight(
-			T::WeightInfo::instantiate(data.len() as u32, salt.len() as u32).saturating_add(*gas_limit)
+			T::WeightInfo::instantiate(data.len() as u32, 32).saturating_add(*gas_limit)
 		)]
 		pub fn instantiate(
 			origin: OriginFor<T>,
@@ -833,10 +833,9 @@ pub mod pallet {
 			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
 			code_hash: sp_core::H256,
 			data: Vec<u8>,
-			salt: [u8; 32],
+			salt: Option<[u8; 32]>,
 		) -> DispatchResultWithPostInfo {
 			let data_len = data.len() as u32;
-			let salt_len = salt.len() as u32;
 			let mut output = Self::bare_instantiate(
 				origin,
 				value,
@@ -856,7 +855,7 @@ pub mod pallet {
 			dispatch_result(
 				output.result.map(|result| result.result),
 				output.gas_consumed,
-				T::WeightInfo::instantiate(data_len, salt_len),
+				T::WeightInfo::instantiate(data_len, 32),
 			)
 		}
 
@@ -875,7 +874,9 @@ pub mod pallet {
 		///   from the caller to pay for the storage consumed.
 		/// * `code`: The contract code to deploy in raw bytes.
 		/// * `data`: The input data to pass to the contract constructor.
-		/// * `salt`: Used for the address derivation. See [`crate::address::create2`].
+		/// * `salt`: Used for the address derivation. If `Some` is supplied then `CREATE2`
+		/// 	semantics are used. If `None` then `CRATE1` is used.
+		///
 		///
 		/// Instantiation is executed as follows:
 		///
@@ -887,7 +888,7 @@ pub mod pallet {
 		/// - The `deploy` function is executed in the context of the newly-created account.
 		#[pallet::call_index(2)]
 		#[pallet::weight(
-			T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32, salt.len() as u32)
+			T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32, 32)
 			.saturating_add(*gas_limit)
 		)]
 		pub fn instantiate_with_code(
@@ -897,11 +898,10 @@ pub mod pallet {
 			#[pallet::compact] storage_deposit_limit: BalanceOf<T>,
 			code: Vec<u8>,
 			data: Vec<u8>,
-			salt: [u8; 32],
+			salt: Option<[u8; 32]>,
 		) -> DispatchResultWithPostInfo {
 			let code_len = code.len() as u32;
 			let data_len = data.len() as u32;
-			let salt_len = salt.len() as u32;
 			let mut output = Self::bare_instantiate(
 				origin,
 				value,
@@ -921,7 +921,7 @@ pub mod pallet {
 			dispatch_result(
 				output.result.map(|result| result.result),
 				output.gas_consumed,
-				T::WeightInfo::instantiate_with_code(code_len, data_len, salt_len),
+				T::WeightInfo::instantiate_with_code(code_len, data_len, 32),
 			)
 		}
 
@@ -1122,7 +1122,7 @@ impl<T: Config> Pallet<T> {
 		mut storage_deposit_limit: BalanceOf<T>,
 		code: Code,
 		data: Vec<u8>,
-		salt: [u8; 32],
+		salt: Option<[u8; 32]>,
 		debug: DebugInfo,
 		collect_events: CollectEvents,
 	) -> ContractInstantiateResult<BalanceOf<T>, EventRecordOf<T>> {
@@ -1158,7 +1158,7 @@ impl<T: Config> Pallet<T> {
 				&mut storage_meter,
 				value,
 				data,
-				&salt,
+				salt.as_ref(),
 				debug_message.as_mut(),
 			);
 			storage_deposit = storage_meter
@@ -1298,7 +1298,7 @@ sp_api::decl_runtime_apis! {
 			storage_deposit_limit: Option<Balance>,
 			code: Code,
 			data: Vec<u8>,
-			salt: [u8; 32],
+			salt: Option<[u8; 32]>,
 		) -> ContractInstantiateResult<Balance, EventRecord>;
 
 		/// Upload new code without instantiating a contract from it.
diff --git a/substrate/frame/revive/src/test_utils/builder.rs b/substrate/frame/revive/src/test_utils/builder.rs
index 76b4c98d4cb063a2044510d0e005bf5fabb08b51..b17067769c05d529f22af6c4c8b4376a1bc83d4f 100644
--- a/substrate/frame/revive/src/test_utils/builder.rs
+++ b/substrate/frame/revive/src/test_utils/builder.rs
@@ -88,7 +88,7 @@ builder!(
 		storage_deposit_limit: BalanceOf<T>,
 		code: Vec<u8>,
 		data: Vec<u8>,
-		salt: [u8; 32],
+		salt: Option<[u8; 32]>,
 	) -> DispatchResultWithPostInfo;
 
 	/// Create an [`InstantiateWithCodeBuilder`] with default values.
@@ -100,7 +100,7 @@ builder!(
 			storage_deposit_limit: deposit_limit::<T>(),
 			code,
 			data: vec![],
-			salt: [0; 32],
+			salt: Some([0; 32]),
 		}
 	}
 );
@@ -113,7 +113,7 @@ builder!(
 		storage_deposit_limit: BalanceOf<T>,
 		code_hash: sp_core::H256,
 		data: Vec<u8>,
-		salt: [u8; 32],
+		salt: Option<[u8; 32]>,
 	) -> DispatchResultWithPostInfo;
 
 	/// Create an [`InstantiateBuilder`] with default values.
@@ -125,7 +125,7 @@ builder!(
 			storage_deposit_limit: deposit_limit::<T>(),
 			code_hash,
 			data: vec![],
-			salt: [0; 32],
+			salt: Some([0; 32]),
 		}
 	}
 );
@@ -138,7 +138,7 @@ builder!(
 		storage_deposit_limit: BalanceOf<T>,
 		code: Code,
 		data: Vec<u8>,
-		salt: [u8; 32],
+		salt: Option<[u8; 32]>,
 		debug: DebugInfo,
 		collect_events: CollectEvents,
 	) -> ContractInstantiateResult<BalanceOf<T>, EventRecordOf<T>>;
@@ -164,7 +164,7 @@ builder!(
 			storage_deposit_limit: deposit_limit::<T>(),
 			code,
 			data: vec![],
-			salt: [0; 32],
+			salt: Some([0; 32]),
 			debug: DebugInfo::UnsafeDebug,
 			collect_events: CollectEvents::Skip,
 		}
diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs
index a37e9842a2cb6394208837b19a0cb033d43e1baa..447d55f0dd8d0089574f767c51785787e45914c7 100644
--- a/substrate/frame/revive/src/tests.rs
+++ b/substrate/frame/revive/src/tests.rs
@@ -26,7 +26,7 @@ use self::{
 };
 use crate::{
 	self as pallet_revive,
-	address::AddressMapper,
+	address::{create1, create2, AddressMapper},
 	chain_extension::{
 		ChainExtension, Environment, Ext, RegisteredChainExtension, Result as ExtensionResult,
 		RetVal, ReturnFlags,
@@ -771,6 +771,47 @@ mod run_tests {
 		});
 	}
 
+	#[test]
+	fn create1_address_from_extrinsic() {
+		let (wasm, code_hash) = compile_module("dummy").unwrap();
+
+		ExtBuilder::default().existential_deposit(1).build().execute_with(|| {
+			let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000);
+
+			assert_ok!(Contracts::upload_code(
+				RuntimeOrigin::signed(ALICE),
+				wasm.clone(),
+				deposit_limit::<Test>(),
+			));
+
+			assert_eq!(System::account_nonce(&ALICE), 0);
+
+			for nonce in 0..3 {
+				let Contract { addr, .. } = builder::bare_instantiate(Code::Existing(code_hash))
+					.salt(None)
+					.build_and_unwrap_contract();
+				assert!(ContractInfoOf::<Test>::contains_key(&addr));
+				assert_eq!(
+					addr,
+					create1(&<Test as Config>::AddressMapper::to_address(&ALICE), nonce)
+				);
+			}
+			assert_eq!(System::account_nonce(&ALICE), 3);
+
+			for nonce in 3..6 {
+				let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm.clone()))
+					.salt(None)
+					.build_and_unwrap_contract();
+				assert!(ContractInfoOf::<Test>::contains_key(&addr));
+				assert_eq!(
+					addr,
+					create1(&<Test as Config>::AddressMapper::to_address(&ALICE), nonce)
+				);
+			}
+			assert_eq!(System::account_nonce(&ALICE), 6);
+		});
+	}
+
 	#[test]
 	fn deposit_event_max_value_limit() {
 		let (wasm, _code_hash) = compile_module("event_size").unwrap();
@@ -1023,7 +1064,7 @@ mod run_tests {
 					.value(100_000)
 					.build_and_unwrap_contract();
 
-			let callee_addr = crate::address::create2(
+			let callee_addr = create2(
 				&caller_addr,
 				&callee_wasm,
 				&[0, 1, 34, 51, 68, 85, 102, 119], // hard coded in wasm
@@ -1410,7 +1451,7 @@ mod run_tests {
 
 			// Check that the CHARLIE contract has been instantiated.
 			let salt = [47; 32]; // hard coded in fixture.
-			let addr_charlie = crate::address::create2(&addr_bob, &callee_wasm, &[], &salt);
+			let addr_charlie = create2(&addr_bob, &callee_wasm, &[], &salt);
 			get_contract(&addr_charlie);
 
 			// Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct.
@@ -1759,7 +1800,7 @@ mod run_tests {
 			for i in 0..3u8 {
 				let contract = builder::bare_instantiate(Code::Upload(code.clone()))
 					.value(min_balance * 100)
-					.salt([i; 32])
+					.salt(Some([i; 32]))
 					.build_and_unwrap_contract();
 
 				let info = get_contract(&contract.addr);
@@ -2000,7 +2041,7 @@ mod run_tests {
 			for i in 0..3u8 {
 				let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(code.clone()))
 					.value(min_balance * 100)
-					.salt([i; 32])
+					.salt(Some([i; 32]))
 					.build_and_unwrap_contract();
 
 				let info = get_contract(&addr);
@@ -2042,19 +2083,19 @@ mod run_tests {
 			let Contract { addr: addr0, .. } =
 				builder::bare_instantiate(Code::Upload(wasm.clone()))
 					.value(min_balance * 100)
-					.salt([0; 32])
+					.salt(Some([0; 32]))
 					.build_and_unwrap_contract();
 			let Contract { addr: addr1, .. } =
 				builder::bare_instantiate(Code::Upload(wasm.clone()))
 					.value(min_balance * 100)
-					.salt([1; 32])
+					.salt(Some([1; 32]))
 					.build_and_unwrap_contract();
 			assert_refcount!(code_hash, 2);
 
 			// Sharing should also work with the usual instantiate call
 			let Contract { addr: addr2, .. } = builder::bare_instantiate(Code::Existing(code_hash))
 				.value(min_balance * 100)
-				.salt([2; 32])
+				.salt(Some([2; 32]))
 				.build_and_unwrap_contract();
 			assert_refcount!(code_hash, 3);
 
@@ -2241,7 +2282,7 @@ mod run_tests {
 			let Contract { addr: addr_caller, .. } =
 				builder::bare_instantiate(Code::Upload(caller_code))
 					.value(min_balance * 100)
-					.salt([0; 32])
+					.salt(Some([0; 32]))
 					.build_and_unwrap_contract();
 
 			// Call something trivial with a huge gas limit so that we can observe the effects
@@ -2279,13 +2320,13 @@ mod run_tests {
 			let Contract { addr: addr_caller, .. } =
 				builder::bare_instantiate(Code::Upload(caller_code))
 					.value(min_balance * 100)
-					.salt([0; 32])
+					.salt(Some([0; 32]))
 					.build_and_unwrap_contract();
 
 			let Contract { addr: addr_callee, .. } =
 				builder::bare_instantiate(Code::Upload(callee_code))
 					.value(min_balance * 100)
-					.salt([1; 32])
+					.salt(Some([1; 32]))
 					.build_and_unwrap_contract();
 
 			// Call pallet_revive call() dispatchable
diff --git a/substrate/frame/revive/src/tests/test_debug.rs b/substrate/frame/revive/src/tests/test_debug.rs
index e3571b7f21eb9dc397b9c44e4ebe0d1179afd1af..7885d681e482346929bd10f10d8d37f45a8b8746 100644
--- a/substrate/frame/revive/src/tests/test_debug.rs
+++ b/substrate/frame/revive/src/tests/test_debug.rs
@@ -122,7 +122,7 @@ mod run_tests {
 				deposit_limit::<Test>(),
 				Code::Upload(wasm),
 				vec![],
-				[0u8; 32],
+				Some([0u8; 32]),
 				DebugInfo::Skip,
 				CollectEvents::Skip,
 			)
@@ -207,7 +207,7 @@ mod run_tests {
 				Code::Upload(wasm),
 				vec![],
 				// some salt to ensure that the address of this contract is unique among all tests
-				[0x41; 32],
+				Some([0x41; 32]),
 				DebugInfo::Skip,
 				CollectEvents::Skip,
 			)
diff --git a/substrate/frame/revive/src/wasm/runtime.rs b/substrate/frame/revive/src/wasm/runtime.rs
index 70d405da9897492548d9433e340b73b1e76d1946..533baf8d2c8293b998cc78fc93a1a0038ed3a269 100644
--- a/substrate/frame/revive/src/wasm/runtime.rs
+++ b/substrate/frame/revive/src/wasm/runtime.rs
@@ -327,8 +327,8 @@ pub enum RuntimeCosts {
 	CallTransferSurcharge,
 	/// Weight per byte that is cloned by supplying the `CLONE_INPUT` flag.
 	CallInputCloned(u32),
-	/// Weight of calling `seal_instantiate` for the given input length and salt.
-	Instantiate { input_data_len: u32, salt_len: u32 },
+	/// Weight of calling `seal_instantiate` for the given input lenth.
+	Instantiate { input_data_len: u32 },
 	/// Weight of calling `seal_hash_sha_256` for the given input size.
 	HashSha256(u32),
 	/// Weight of calling `seal_hash_keccak_256` for the given input size.
@@ -453,8 +453,7 @@ impl<T: Config> Token<T> for RuntimeCosts {
 			DelegateCallBase => T::WeightInfo::seal_delegate_call(),
 			CallTransferSurcharge => cost_args!(seal_call, 1, 0),
 			CallInputCloned(len) => cost_args!(seal_call, 0, len),
-			Instantiate { input_data_len, salt_len } =>
-				T::WeightInfo::seal_instantiate(input_data_len, salt_len),
+			Instantiate { input_data_len } => T::WeightInfo::seal_instantiate(input_data_len, 32),
 			HashSha256(len) => T::WeightInfo::seal_hash_sha2_256(len),
 			HashKeccak256(len) => T::WeightInfo::seal_hash_keccak_256(len),
 			HashBlake256(len) => T::WeightInfo::seal_hash_blake2_256(len),
@@ -1015,9 +1014,8 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> {
 		output_ptr: u32,
 		output_len_ptr: u32,
 		salt_ptr: u32,
-		salt_len: u32,
 	) -> Result<ReturnErrorCode, TrapReason> {
-		self.charge_gas(RuntimeCosts::Instantiate { input_data_len, salt_len })?;
+		self.charge_gas(RuntimeCosts::Instantiate { input_data_len })?;
 		let deposit_limit: BalanceOf<<E as Ext>::T> = if deposit_ptr == SENTINEL {
 			BalanceOf::<<E as Ext>::T>::zero()
 		} else {
@@ -1026,10 +1024,21 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> {
 		let value: BalanceOf<<E as Ext>::T> = memory.read_as(value_ptr)?;
 		let code_hash: H256 = memory.read_as(code_hash_ptr)?;
 		let input_data = memory.read(input_data_ptr, input_data_len)?;
-		let mut salt = [0u8; 32];
-		memory.read_into_buf(salt_ptr, salt.as_mut_slice())?;
-		let instantiate_outcome =
-			self.ext.instantiate(weight, deposit_limit, code_hash, value, input_data, &salt);
+		let salt = if salt_ptr == SENTINEL {
+			None
+		} else {
+			let mut salt = [0u8; 32];
+			memory.read_into_buf(salt_ptr, salt.as_mut_slice())?;
+			Some(salt)
+		};
+		let instantiate_outcome = self.ext.instantiate(
+			weight,
+			deposit_limit,
+			code_hash,
+			value,
+			input_data,
+			salt.as_ref(),
+		);
 		if let Ok((address, output)) = &instantiate_outcome {
 			if !output.flags.contains(ReturnFlags::REVERT) {
 				self.write_sandbox_output(
@@ -1253,7 +1262,7 @@ pub mod env {
 		output_ptr: u32,
 		output_len_ptr: u32,
 		salt_ptr: u32,
-		salt_len: u32,
+		_salt_len: u32,
 	) -> Result<ReturnErrorCode, TrapReason> {
 		self.instantiate(
 			memory,
@@ -1268,7 +1277,6 @@ pub mod env {
 			output_ptr,
 			output_len_ptr,
 			salt_ptr,
-			salt_len,
 		)
 	}