diff --git a/polkadot/runtime/common/src/integration_tests.rs b/polkadot/runtime/common/src/integration_tests.rs
index c1c4eaa153e485e8e7cc4c2fe906438759864d8b..9b82255c3e6444cefe6a00f11adeab8d003b37a2 100644
--- a/polkadot/runtime/common/src/integration_tests.rs
+++ b/polkadot/runtime/common/src/integration_tests.rs
@@ -1074,6 +1074,13 @@ fn parachain_swap_works() {
 			ParaId::from(2001),
 			ParaId::from(2000)
 		));
+		assert!(contains_event(
+			paras_registrar::Event::<Test>::Swapped {
+				para_id: ParaId::from(2001),
+				other_id: ParaId::from(2000)
+			}
+			.into()
+		));
 
 		// Crowdloan Swapped
 		let fund_2000 = Crowdloan::funds(ParaId::from(2000)).unwrap();
diff --git a/polkadot/runtime/common/src/paras_registrar.rs b/polkadot/runtime/common/src/paras_registrar.rs
index 6ad37e63cc7e8bcb55c13c14b2efab3ee4d213e4..585f7c1ab17a0f2972b55c621e95544fce586ee4 100644
--- a/polkadot/runtime/common/src/paras_registrar.rs
+++ b/polkadot/runtime/common/src/paras_registrar.rs
@@ -138,6 +138,7 @@ pub mod pallet {
 		Registered { para_id: ParaId, manager: T::AccountId },
 		Deregistered { para_id: ParaId },
 		Reserved { para_id: ParaId, who: T::AccountId },
+		Swapped { para_id: ParaId, other_id: ParaId },
 	}
 
 	#[pallet::error]
@@ -319,6 +320,7 @@ pub mod pallet {
 				} else {
 					return Err(Error::<T>::CannotSwap.into())
 				}
+				Self::deposit_event(Event::<T>::Swapped { para_id: id, other_id: other });
 				PendingSwap::<T>::remove(other);
 			} else {
 				PendingSwap::<T>::insert(id, other);
@@ -806,9 +808,11 @@ mod tests {
 		)
 		.unwrap();
 
-		pallet_balances::GenesisConfig::<Test> { balances: vec![(1, 10_000_000), (2, 10_000_000)] }
-			.assimilate_storage(&mut t)
-			.unwrap();
+		pallet_balances::GenesisConfig::<Test> {
+			balances: vec![(1, 10_000_000), (2, 10_000_000), (3, 10_000_000)],
+		}
+		.assimilate_storage(&mut t)
+		.unwrap();
 
 		t.into()
 	}
@@ -1120,8 +1124,13 @@ mod tests {
 			assert!(Parachains::is_parathread(para_2));
 
 			// Both paras initiate a swap
+			// Swap between parachain and parathread
 			assert_ok!(Registrar::swap(para_origin(para_1), para_1, para_2,));
 			assert_ok!(Registrar::swap(para_origin(para_2), para_2, para_1,));
+			System::assert_last_event(RuntimeEvent::Registrar(paras_registrar::Event::Swapped {
+				para_id: para_2,
+				other_id: para_1,
+			}));
 
 			run_to_session(6);
 
@@ -1134,6 +1143,60 @@ mod tests {
 			// Data is swapped
 			assert_eq!(SwapData::get().get(&para_1).unwrap(), &1337);
 			assert_eq!(SwapData::get().get(&para_2).unwrap(), &69);
+
+			// Both paras initiate a swap
+			// Swap between parathread and parachain
+			assert_ok!(Registrar::swap(para_origin(para_1), para_1, para_2,));
+			assert_ok!(Registrar::swap(para_origin(para_2), para_2, para_1,));
+			System::assert_last_event(RuntimeEvent::Registrar(paras_registrar::Event::Swapped {
+				para_id: para_2,
+				other_id: para_1,
+			}));
+
+			// Data is swapped
+			assert_eq!(SwapData::get().get(&para_1).unwrap(), &69);
+			assert_eq!(SwapData::get().get(&para_2).unwrap(), &1337);
+
+			// Parachain to parachain swap
+			let para_3 = LOWEST_PUBLIC_ID + 2;
+			assert_ok!(Registrar::reserve(RuntimeOrigin::signed(3)));
+			assert_ok!(Registrar::register(
+				RuntimeOrigin::signed(3),
+				para_3,
+				test_genesis_head(max_head_size() as usize),
+				test_validation_code(max_code_size() as usize),
+			));
+
+			run_to_session(8);
+
+			// Upgrade para 3 into a parachain
+			assert_ok!(Registrar::make_parachain(para_3));
+
+			// Set some mock swap data.
+			let mut swap_data = SwapData::get();
+			swap_data.insert(para_3, 777);
+			SwapData::set(swap_data);
+
+			run_to_session(10);
+
+			// Both are parachains
+			assert!(Parachains::is_parachain(para_3));
+			assert!(!Parachains::is_parathread(para_3));
+			assert!(Parachains::is_parachain(para_1));
+			assert!(!Parachains::is_parathread(para_1));
+
+			// Both paras initiate a swap
+			// Swap between parachain and parachain
+			assert_ok!(Registrar::swap(para_origin(para_1), para_1, para_3,));
+			assert_ok!(Registrar::swap(para_origin(para_3), para_3, para_1,));
+			System::assert_last_event(RuntimeEvent::Registrar(paras_registrar::Event::Swapped {
+				para_id: para_3,
+				other_id: para_1,
+			}));
+
+			// Data is swapped
+			assert_eq!(SwapData::get().get(&para_3).unwrap(), &69);
+			assert_eq!(SwapData::get().get(&para_1).unwrap(), &777);
 		});
 	}
 
@@ -1248,6 +1311,10 @@ mod tests {
 			// Swap works here.
 			assert_ok!(Registrar::swap(RuntimeOrigin::root(), para_1, para_2));
 			assert_ok!(Registrar::swap(RuntimeOrigin::root(), para_2, para_1));
+			assert!(System::events().iter().any(|r| matches!(
+				r.event,
+				RuntimeEvent::Registrar(paras_registrar::Event::Swapped { .. })
+			)));
 
 			run_to_session(5);
 
@@ -1263,6 +1330,10 @@ mod tests {
 			// Swap worked!
 			assert!(Parachains::is_parachain(para_2));
 			assert!(Parachains::is_parathread(para_1));
+			assert!(System::events().iter().any(|r| matches!(
+				r.event,
+				RuntimeEvent::Registrar(paras_registrar::Event::Swapped { .. })
+			)));
 
 			// Something starts to downgrade a para
 			assert_ok!(Registrar::make_parathread(para_2));