diff --git a/substrate/frame/contracts/src/exec.rs b/substrate/frame/contracts/src/exec.rs
index 05eaf52c1bc9b2eaf2c1e3faa6afaf88ec956087..c2ad48ca981ab03ac85d0e8db01a71d34d7ebdef 100644
--- a/substrate/frame/contracts/src/exec.rs
+++ b/substrate/frame/contracts/src/exec.rs
@@ -582,6 +582,7 @@ where
 		)?;
 		if let Some(ContractInfo::Alive(info)) = ContractInfoOf::<T>::take(&self_id) {
 			Storage::<T>::queue_trie_for_deletion(&info)?;
+			Contracts::<T>::deposit_event(RawEvent::Terminated(self_id, beneficiary.clone()));
 			Ok(())
 		} else {
 			panic!(
@@ -671,7 +672,7 @@ where
 	fn deposit_event(&mut self, topics: Vec<T::Hash>, data: Vec<u8>) {
 		deposit_event::<Self::T>(
 			topics,
-			RawEvent::ContractExecution(self.ctx.self_account.clone(), data)
+			RawEvent::ContractEmitted(self.ctx.self_account.clone(), data)
 		);
 	}
 
diff --git a/substrate/frame/contracts/src/lib.rs b/substrate/frame/contracts/src/lib.rs
index 43566bc547c409a7bfd12e35bf565e493fb6eef8..9c810faad9655cb4b38cb49bb30a88db1c26e932 100644
--- a/substrate/frame/contracts/src/lib.rs
+++ b/substrate/frame/contracts/src/lib.rs
@@ -756,39 +756,57 @@ decl_event! {
 		<T as frame_system::Config>::AccountId,
 		<T as frame_system::Config>::Hash
 	{
-		/// Contract deployed by address at the specified address. \[owner, contract\]
+		/// Contract deployed by address at the specified address. \[deployer, contract\]
 		Instantiated(AccountId, AccountId),
 
-		/// Contract has been evicted and is now in tombstone state.
-		/// \[contract, tombstone\]
+		/// Contract has been evicted and is now in tombstone state. \[contract\]
+		Evicted(AccountId),
+
+		/// Contract has been terminated without leaving a tombstone.
+		/// \[contract, beneficiary\]
 		///
 		/// # Params
 		///
-		/// - `contract`: `AccountId`: The account ID of the evicted contract.
-		/// - `tombstone`: `bool`: True if the evicted contract left behind a tombstone.
-		Evicted(AccountId, bool),
+		/// - `contract`: The contract that was terminated.
+		/// - `beneficiary`: The account that received the contracts remaining balance.
+		///
+		/// # Note
+		///
+		/// The only way for a contract to be removed without a tombstone and emitting
+		/// this event is by calling `seal_terminate`.
+		Terminated(AccountId, AccountId),
 
-		/// Restoration for a contract has been successful.
-		/// \[donor, dest, code_hash, rent_allowance\]
+		/// Restoration of a contract has been successful.
+		/// \[restorer, dest, code_hash, rent_allowance\]
 		///
 		/// # Params
 		///
-		/// - `donor`: `AccountId`: Account ID of the restoring contract
-		/// - `dest`: `AccountId`: Account ID of the restored contract
-		/// - `code_hash`: `Hash`: Code hash of the restored contract
-		/// - `rent_allowance: `Balance`: Rent allowance of the restored contract
+		/// - `restorer`: Account ID of the restoring contract.
+		/// - `dest`: Account ID of the restored contract.
+		/// - `code_hash`: Code hash of the restored contract.
+		/// - `rent_allowance`: Rent allowance of the restored contract.
 		Restored(AccountId, AccountId, Hash, Balance),
 
-		/// Code with the specified hash has been stored.
-		/// \[code_hash\]
+		/// Code with the specified hash has been stored. \[code_hash\]
 		CodeStored(Hash),
 
-		/// Triggered when the current \[schedule\] is updated.
+		/// Triggered when the current schedule is updated.
+		/// \[version\]
+		///
+		/// # Params
+		///
+		/// - `version`: The version of the newly set schedule.
 		ScheduleUpdated(u32),
 
-		/// An event deposited upon execution of a contract from the account.
-		/// \[account, data\]
-		ContractExecution(AccountId, Vec<u8>),
+		/// A custom event emitted by the contract.
+		/// \[contract, data\]
+		///
+		/// # Params
+		///
+		/// - `contract`: The contract that emitted the event.
+		/// - `data`: Data supplied by the contract. Metadata generated during contract
+		///           compilation is needed to decode it.
+		ContractEmitted(AccountId, Vec<u8>),
 	}
 }
 
diff --git a/substrate/frame/contracts/src/rent.rs b/substrate/frame/contracts/src/rent.rs
index 0bf229d49469650f62921e07503e97349f8c373d..2075f6f757de2ef3d3e87fadcc884b288adabd00 100644
--- a/substrate/frame/contracts/src/rent.rs
+++ b/substrate/frame/contracts/src/rent.rs
@@ -261,7 +261,7 @@ where
 				);
 				let tombstone_info = ContractInfo::Tombstone(tombstone);
 				<ContractInfoOf<T>>::insert(account, &tombstone_info);
-				<Module<T>>::deposit_event(RawEvent::Evicted(account.clone(), true));
+				<Module<T>>::deposit_event(RawEvent::Evicted(account.clone()));
 				Ok(Some(tombstone_info))
 			}
 			Verdict::Charge { amount } => {
diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs
index a2916ff833b4ee0d5618f61dba55c64d4c5f0922..a8bf80213a176f95bae0ec75f84708c307d1f217 100644
--- a/substrate/frame/contracts/src/tests.rs
+++ b/substrate/frame/contracts/src/tests.rs
@@ -512,7 +512,7 @@ fn instantiate_and_call_and_deposit_event() {
 				EventRecord {
 					phase: Phase::Initialization,
 					event: MetaEvent::contracts(
-						RawEvent::ContractExecution(addr.clone(), vec![1, 2, 3, 4])
+						RawEvent::ContractEmitted(addr.clone(), vec![1, 2, 3, 4])
 					),
 					topics: vec![],
 				},
@@ -1300,7 +1300,7 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:
 				EventRecord {
 					phase: Phase::Initialization,
 					event: MetaEvent::contracts(
-						RawEvent::Evicted(addr_bob.clone(), true)
+						RawEvent::Evicted(addr_bob.clone())
 					),
 					topics: vec![],
 				},
@@ -1385,7 +1385,7 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:
 						pretty_assertions::assert_eq!(System::events(), vec![
 							EventRecord {
 								phase: Phase::Initialization,
-								event: MetaEvent::contracts(RawEvent::Evicted(addr_bob, true)),
+								event: MetaEvent::contracts(RawEvent::Evicted(addr_bob)),
 								topics: vec![],
 							},
 							EventRecord {
@@ -1633,6 +1633,7 @@ fn self_destruct_works() {
 		.build()
 		.execute_with(|| {
 			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			let _ = Balances::deposit_creating(&DJANGO, 1_000_000);
 			assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
 
 			// Instantiate the BOB contract.
@@ -1652,6 +1653,9 @@ fn self_destruct_works() {
 				Some(ContractInfo::Alive(_))
 			);
 
+			// Drop all previous events
+			initialize_block(2);
+
 			// Call BOB without input data which triggers termination.
 			assert_matches!(
 				Contracts::call(
@@ -1664,11 +1668,35 @@ fn self_destruct_works() {
 				Ok(_)
 			);
 
+			pretty_assertions::assert_eq!(System::events(), vec![
+				EventRecord {
+					phase: Phase::Initialization,
+					event: MetaEvent::system(
+						frame_system::Event::KilledAccount(addr.clone())
+					),
+					topics: vec![],
+				},
+				EventRecord {
+					phase: Phase::Initialization,
+					event: MetaEvent::balances(
+						pallet_balances::RawEvent::Transfer(addr.clone(), DJANGO, 100_000)
+					),
+					topics: vec![],
+				},
+				EventRecord {
+					phase: Phase::Initialization,
+					event: MetaEvent::contracts(
+						RawEvent::Terminated(addr.clone(), DJANGO)
+					),
+					topics: vec![],
+				},
+			]);
+
 			// Check that account is gone
 			assert!(ContractInfoOf::<Test>::get(&addr).is_none());
 
 			// check that the beneficiary (django) got remaining balance
-			assert_eq!(Balances::free_balance(DJANGO), 100_000);
+			assert_eq!(Balances::free_balance(DJANGO), 1_100_000);
 		});
 }