diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs
index 369281ccd8ee4fa6d43964f5bd795ea4750acdfd..84b4cda15347a5072ce46cc0c3f0ea9be0d9931c 100644
--- a/cumulus/pallets/parachain-system/src/lib.rs
+++ b/cumulus/pallets/parachain-system/src/lib.rs
@@ -39,7 +39,6 @@ use frame_support::{
 	dispatch::{DispatchResult, Pays, PostDispatchInfo},
 	ensure,
 	inherent::{InherentData, InherentIdentifier, ProvideInherent},
-	storage,
 	traits::Get,
 	weights::Weight,
 };
@@ -598,7 +597,7 @@ pub mod pallet {
 					);
 					let validation_code = <PendingValidationCode<T>>::take();
 
-					Self::put_parachain_code(&validation_code);
+					frame_system::Pallet::<T>::update_code_in_storage(&validation_code);
 					<T::OnSystemEvent as OnSystemEvent>::on_validation_code_applied();
 					Self::deposit_event(Event::ValidationFunctionApplied {
 						relay_chain_block_num: vfp.relay_parent_number,
@@ -1399,12 +1398,6 @@ impl<T: Config> Pallet<T> {
 		<DidSetValidationCode<T>>::put(true);
 	}
 
-	/// Put a new validation function into a particular location where this
-	/// parachain will execute it on subsequent blocks.
-	fn put_parachain_code(code: &[u8]) {
-		storage::unhashed::put_raw(sp_core::storage::well_known_keys::CODE, code);
-	}
-
 	/// The maximum code size permitted, in bytes.
 	///
 	/// Returns `None` if the relay chain parachain host configuration hasn't been submitted yet.
diff --git a/cumulus/pallets/parachain-system/src/tests.rs b/cumulus/pallets/parachain-system/src/tests.rs
index 3f5b4f649e3231035d4e2d031ed6b574bb443f38..7db6a966ec91be1d5a581d407505f6084cf4ef62 100755
--- a/cumulus/pallets/parachain-system/src/tests.rs
+++ b/cumulus/pallets/parachain-system/src/tests.rs
@@ -869,7 +869,7 @@ fn hrmp_outbound_respects_used_bandwidth() {
 }
 
 #[test]
-fn events() {
+fn runtime_upgrade_events() {
 	BlockTests::new()
 		.with_relay_sproof_builder(|_, block_number, builder| {
 			if block_number > 123 {
@@ -894,12 +894,20 @@ fn events() {
 			|| {},
 			|| {
 				let events = System::events();
+
+				assert_eq!(events[0].event, RuntimeEvent::System(frame_system::Event::CodeUpdated));
+
 				assert_eq!(
-					events[0].event,
+					events[1].event,
 					RuntimeEvent::ParachainSystem(crate::Event::ValidationFunctionApplied {
 						relay_chain_block_num: 1234
 					})
 				);
+
+				assert!(System::digest()
+					.logs()
+					.iter()
+					.any(|d| *d == sp_runtime::generic::DigestItem::RuntimeEnvironmentUpdated));
 			},
 		);
 }
diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs
index eca20f5a0a9f963e52e67cf72ea88dd3700e1a93..dfdacc9a8eb9645619fde5c0f5b841f7619086f2 100644
--- a/substrate/frame/system/src/lib.rs
+++ b/substrate/frame/system/src/lib.rs
@@ -163,7 +163,7 @@ pub trait SetCode<T: Config> {
 
 impl<T: Config> SetCode<T> for () {
 	fn set_code(code: Vec<u8>) -> DispatchResult {
-		<Pallet<T>>::update_code_in_storage(&code)?;
+		<Pallet<T>>::update_code_in_storage(&code);
 		Ok(())
 	}
 }
@@ -1106,11 +1106,10 @@ impl<T: Config> Pallet<T> {
 	/// Note this function almost never should be used directly. It is exposed
 	/// for `OnSetCode` implementations that defer actual code being written to
 	/// the storage (for instance in case of parachains).
-	pub fn update_code_in_storage(code: &[u8]) -> DispatchResult {
+	pub fn update_code_in_storage(code: &[u8]) {
 		storage::unhashed::put_raw(well_known_keys::CODE, code);
 		Self::deposit_log(generic::DigestItem::RuntimeEnvironmentUpdated);
 		Self::deposit_event(Event::CodeUpdated);
-		Ok(())
 	}
 
 	/// Increment the reference counter on an account.