diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs
index e17e0085f0365647af1789b83248ee9b8bd92be5..e80d5fa83ab381278c83756b2e4a45b7781694d4 100644
--- a/substrate/node/runtime/src/lib.rs
+++ b/substrate/node/runtime/src/lib.rs
@@ -80,8 +80,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
 	// and set impl_version to equal spec_version. If only runtime
 	// implementation changes and behavior does not, then leave spec_version as
 	// is and increment impl_version.
-	spec_version: 148,
-	impl_version: 148,
+	spec_version: 149,
+	impl_version: 149,
 	apis: RUNTIME_API_VERSIONS,
 };
 
diff --git a/substrate/srml/contracts/src/account_db.rs b/substrate/srml/contracts/src/account_db.rs
index 5cfd0d3a65fa8dc77c5584cefdcbd730cc401092..9f8b29e0bd897594007b004878da5cdc36ba7007 100644
--- a/substrate/srml/contracts/src/account_db.rs
+++ b/substrate/srml/contracts/src/account_db.rs
@@ -34,11 +34,57 @@ use system;
 // the trie_id in the overlay, thus we provide an overlay on the fields
 // specifically.
 pub struct ChangeEntry<T: Trait> {
+	/// If Some(_), then the account balance is modified to the value. If None and `reset` is false,
+	/// the balance unmodified. If None and `reset` is true, the balance is reset to 0.
 	balance: Option<BalanceOf<T>>,
-	/// If None, the code_hash remains untouched.
+	/// If Some(_), then a contract is created with the code hash. If None and `reset` is false,
+	/// then the contract code is unmodified. If None and `reset` is true, the contract is deleted.
 	code_hash: Option<CodeHash<T>>,
+	/// If Some(_), then the rent allowance is set to the value. If None and `reset` is false, then
+	/// the rent allowance is unmodified. If None and `reset` is true, the contract is deleted.
 	rent_allowance: Option<BalanceOf<T>>,
 	storage: BTreeMap<StorageKey, Option<Vec<u8>>>,
+	/// If true, indicates that the existing contract and all its storage entries should be removed
+	/// and replaced with the fields on this change entry. Otherwise, the fields on this change
+	/// entry are updates merged into the existing contract info and storage.
+	reset: bool,
+}
+
+impl<T: Trait> ChangeEntry<T> {
+	fn balance(&self) -> Option<BalanceOf<T>> {
+		self.balance.or_else(|| {
+			if self.reset {
+				Some(<BalanceOf<T>>::zero())
+			} else {
+				None
+			}
+		})
+	}
+
+	fn code_hash(&self) -> Option<Option<CodeHash<T>>> {
+		if self.reset {
+			Some(self.code_hash)
+		} else {
+			self.code_hash.map(Some)
+		}
+	}
+
+	fn rent_allowance(&self) -> Option<Option<BalanceOf<T>>> {
+		if self.reset {
+			Some(self.rent_allowance)
+		} else {
+			self.rent_allowance.map(Some)
+		}
+	}
+
+	fn storage(&self, location: &StorageKey) -> Option<Option<Vec<u8>>> {
+		let value = self.storage.get(location).cloned();
+		if self.reset {
+			Some(value.unwrap_or(None))
+		} else {
+			value
+		}
+	}
 }
 
 // Cannot derive(Default) since it erroneously bounds T by Default.
@@ -49,6 +95,7 @@ impl<T: Trait> Default for ChangeEntry<T> {
 			balance: Default::default(),
 			code_hash: Default::default(),
 			storage: Default::default(),
+			reset: false,
 		}
 	}
 }
@@ -98,7 +145,7 @@ impl<T: Trait> AccountDb<T> for DirectAccountDb {
 	fn commit(&mut self, s: ChangeSet<T>) {
 		let mut total_imbalance = SignedImbalance::zero();
 		for (address, changed) in s.into_iter() {
-			if let Some(balance) = changed.balance {
+			if let Some(balance) = changed.balance() {
 				let (imbalance, outcome) = T::Currency::make_free_balance_be(&address, balance);
 				total_imbalance = total_imbalance.merge(imbalance);
 				if let UpdateBalanceOutcome::AccountKilled = outcome {
@@ -109,9 +156,10 @@ impl<T: Trait> AccountDb<T> for DirectAccountDb {
 				}
 			}
 
-			if changed.code_hash.is_some()
-				|| changed.rent_allowance.is_some()
+			if changed.code_hash().is_some()
+				|| changed.rent_allowance().is_some()
 				|| !changed.storage.is_empty()
+				|| changed.reset
 			{
 				let old_info = match <ContractInfoOf<T>>::get(&address) {
 					Some(ContractInfo::Alive(alive)) => Some(alive),
@@ -120,20 +168,40 @@ impl<T: Trait> AccountDb<T> for DirectAccountDb {
 					Some(ContractInfo::Tombstone(_)) => continue,
 				};
 
-				let mut new_info = if let Some(info) = old_info.clone() {
-					info
-				} else if let Some(code_hash) = changed.code_hash {
-					AliveContractInfo::<T> {
-						code_hash,
-						storage_size: T::StorageSizeOffset::get(),
-						trie_id: <T as Trait>::TrieIdGenerator::trie_id(&address),
-						deduct_block: <system::Module<T>>::block_number(),
-						rent_allowance: <BalanceOf<T>>::max_value(),
-						last_write: None,
+				let mut new_info = match (changed.reset, old_info.clone(), changed.code_hash) {
+					// Existing contract is being modified.
+					(false, Some(info), _) => info,
+					// Existing contract is being removed.
+					(true, Some(info), None) => {
+						child::kill_storage(&info.trie_id);
+						<ContractInfoOf<T>>::remove(&address);
+						continue;
 					}
-				} else {
-					// No contract exist and no code_hash provided
-					continue;
+					// Existing contract is being replaced by a new one.
+					(true, Some(info), Some(code_hash)) => {
+						child::kill_storage(&info.trie_id);
+						AliveContractInfo::<T> {
+							code_hash,
+							storage_size: T::StorageSizeOffset::get(),
+							trie_id: <T as Trait>::TrieIdGenerator::trie_id(&address),
+							deduct_block: <system::Module<T>>::block_number(),
+							rent_allowance: <BalanceOf<T>>::max_value(),
+							last_write: None,
+						}
+					}
+					// New contract is being created.
+					(_, None, Some(code_hash)) => {
+						AliveContractInfo::<T> {
+							code_hash,
+							storage_size: T::StorageSizeOffset::get(),
+							trie_id: <T as Trait>::TrieIdGenerator::trie_id(&address),
+							deduct_block: <system::Module<T>>::block_number(),
+							rent_allowance: <BalanceOf<T>>::max_value(),
+							last_write: None,
+						}
+					}
+					// There is no existing at the address nor a new one to be created.
+					(_, None, None) => continue,
 				};
 
 				if let Some(rent_allowance) = changed.rent_allowance {
@@ -227,6 +295,19 @@ impl<'a, T: Trait> OverlayAccountDb<'a, T> {
 
 		Ok(())
 	}
+
+	/// Mark a contract as deleted.
+	pub fn destroy_contract(&mut self, account: &T::AccountId) {
+		let mut local = self.local.borrow_mut();
+		local.insert(
+			account.clone(),
+			ChangeEntry {
+				reset: true,
+				..Default::default()
+			}
+		);
+	}
+
 	/// Assume contract exists
 	pub fn set_rent_allowance(&mut self, account: &T::AccountId, rent_allowance: BalanceOf<T>) {
 		self.local
@@ -254,36 +335,35 @@ impl<'a, T: Trait> AccountDb<T> for OverlayAccountDb<'a, T> {
 		self.local
 			.borrow()
 			.get(account)
-			.and_then(|a| a.storage.get(location))
-			.cloned()
+			.and_then(|changes| changes.storage(location))
 			.unwrap_or_else(|| self.underlying.get_storage(account, trie_id, location))
 	}
 	fn get_code_hash(&self, account: &T::AccountId) -> Option<CodeHash<T>> {
 		self.local
 			.borrow()
 			.get(account)
-			.and_then(|changes| changes.code_hash)
-			.or_else(|| self.underlying.get_code_hash(account))
+			.and_then(|changes| changes.code_hash())
+			.unwrap_or_else(|| self.underlying.get_code_hash(account))
 	}
 	fn get_rent_allowance(&self, account: &T::AccountId) -> Option<BalanceOf<T>> {
 		self.local
 			.borrow()
 			.get(account)
-			.and_then(|changes| changes.rent_allowance)
-			.or_else(|| self.underlying.get_rent_allowance(account))
+			.and_then(|changes| changes.rent_allowance())
+			.unwrap_or_else(|| self.underlying.get_rent_allowance(account))
 	}
 	fn contract_exists(&self, account: &T::AccountId) -> bool {
 		self.local
 			.borrow()
 			.get(account)
-			.map(|a| a.code_hash.is_some())
+			.and_then(|changes| changes.code_hash().map(|code_hash| code_hash.is_some()))
 			.unwrap_or_else(|| self.underlying.contract_exists(account))
 	}
 	fn get_balance(&self, account: &T::AccountId) -> BalanceOf<T> {
 		self.local
 			.borrow()
 			.get(account)
-			.and_then(|a| a.balance)
+			.and_then(|changes| changes.balance())
 			.unwrap_or_else(|| self.underlying.get_balance(account))
 	}
 	fn commit(&mut self, s: ChangeSet<T>) {
@@ -293,10 +373,14 @@ impl<'a, T: Trait> AccountDb<T> for OverlayAccountDb<'a, T> {
 			match local.entry(address) {
 				Entry::Occupied(e) => {
 					let mut value = e.into_mut();
-					value.balance = changed.balance.or(value.balance);
-					value.code_hash = changed.code_hash.or(value.code_hash);
-					value.rent_allowance = changed.rent_allowance.or(value.rent_allowance);
-					value.storage.extend(changed.storage.into_iter());
+					if changed.reset {
+						*value = changed;
+					} else {
+						value.balance = changed.balance.or(value.balance);
+						value.code_hash = changed.code_hash.or(value.code_hash);
+						value.rent_allowance = changed.rent_allowance.or(value.rent_allowance);
+						value.storage.extend(changed.storage.into_iter());
+					}
 				}
 				Entry::Vacant(e) => {
 					e.insert(changed);
diff --git a/substrate/srml/contracts/src/exec.rs b/substrate/srml/contracts/src/exec.rs
index 5ba02d43a0ffe68d1d99bdf4e260a4b35a043b47..818a689f99d9080ced3fc298c8e975bb98dfd049 100644
--- a/substrate/srml/contracts/src/exec.rs
+++ b/substrate/srml/contracts/src/exec.rs
@@ -267,6 +267,7 @@ pub enum DeferredAction<T: Trait> {
 }
 
 pub struct ExecutionContext<'a, T: Trait + 'a, V, L> {
+	pub parent: Option<&'a ExecutionContext<'a, T, V, L>>,
 	pub self_account: T::AccountId,
 	pub self_trie_id: Option<TrieId>,
 	pub overlay: OverlayAccountDb<'a, T>,
@@ -291,6 +292,7 @@ where
 	/// account (not a contract).
 	pub fn top_level(origin: T::AccountId, cfg: &'a Config<T>, vm: &'a V, loader: &'a L) -> Self {
 		ExecutionContext {
+			parent: None,
 			self_trie_id: None,
 			self_account: origin,
 			overlay: OverlayAccountDb::<T>::new(&DirectAccountDb),
@@ -308,6 +310,7 @@ where
 		-> ExecutionContext<'b, T, V, L>
 	{
 		ExecutionContext {
+			parent: Some(self),
 			self_trie_id: trie_id,
 			self_account: dest,
 			overlay: OverlayAccountDb::new(&self.overlay),
@@ -385,13 +388,29 @@ where
 						nested.loader.load_main(&dest_code_hash),
 						input_data
 					);
-					nested.vm
+					let output = nested.vm
 						.execute(
 							&executable,
 							nested.new_call_context(caller, value),
 							input_data,
 							gas_meter,
-						)
+						)?;
+
+					// Destroy contract if insufficient remaining balance.
+					if nested.overlay.get_balance(&dest) < nested.config.existential_deposit {
+						let parent = nested.parent
+							.expect("a nested execution context must have a parent; qed");
+						if parent.is_live(&dest) {
+							return Err(ExecError {
+								reason: "contract cannot be destroyed during recursive execution",
+								buffer: output.data,
+							});
+						}
+
+						nested.overlay.destroy_contract(&dest);
+					}
+
+					Ok(output)
 				}
 				None => Ok(ExecReturnValue { status: STATUS_SUCCESS, data: Vec::new() }),
 			}
@@ -464,6 +483,14 @@ where
 					gas_meter,
 				)?;
 
+			// Error out if insufficient remaining balance.
+			if nested.overlay.get_balance(&dest) < nested.config.existential_deposit {
+				return Err(ExecError {
+					reason: "insufficient remaining balance",
+					buffer: output.data,
+				});
+			}
+
 			// Deposit an instantiation event.
 			nested.deferred.push(DeferredAction::DepositEvent {
 				event: RawEvent::Instantiated(caller.clone(), dest.clone()),
@@ -507,6 +534,13 @@ where
 
 		Ok(output)
 	}
+
+	/// Returns whether a contract, identified by address, is currently live in the execution
+	/// stack, meaning it is in the middle of an execution.
+	fn is_live(&self, account: &T::AccountId) -> bool {
+		&self.self_account == account ||
+			self.parent.map_or(false, |parent| parent.is_live(account))
+	}
 }
 
 #[cfg_attr(test, derive(Debug, PartialEq, Eq))]
diff --git a/substrate/srml/contracts/src/tests.rs b/substrate/srml/contracts/src/tests.rs
index 5c5910c1571e798b69fc07e53054cd48458049d3..6ac1a50764f3f44a0f3181f2ece031deb0e0c85a 100644
--- a/substrate/srml/contracts/src/tests.rs
+++ b/substrate/srml/contracts/src/tests.rs
@@ -1602,7 +1602,7 @@ const CODE_RETURN_WITH_DATA: &str = r#"
 
 		;; Copy all but the first 4 bytes of the input data as the output data.
 		(call $ext_scratch_write
-			(i32.const 4)		;; Offset from the start of the scratch buffer.
+			(i32.const 4)	;; Pointer to the data to return.
 			(i32.sub		;; Count of bytes to copy.
 				(get_local $buf_size)
 				(i32.const 4)
@@ -1926,3 +1926,467 @@ fn deploy_and_call_other_contract() {
 		}
 	);
 }
+
+const CODE_SELF_DESTRUCT: &str = r#"
+(module
+	(import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))
+	(import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32)))
+	(import "env" "ext_address" (func $ext_address))
+	(import "env" "ext_balance" (func $ext_balance))
+	(import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32)))
+	(import "env" "memory" (memory 1 1))
+
+	(func $assert (param i32)
+		(block $ok
+			(br_if $ok
+				(get_local 0)
+			)
+			(unreachable)
+		)
+	)
+
+	(func (export "deploy"))
+
+	(func (export "call")
+		;; If the input data is not empty, then recursively call self with empty input data.
+		;; This should trap instead of self-destructing since a contract cannot be removed live in
+		;; the execution stack cannot be removed. If the recursive call traps, then trap here as
+		;; well.
+		(if (call $ext_scratch_size)
+			(then
+				(call $ext_address)
+
+				;; Expect address to be 8 bytes.
+				(call $assert
+					(i32.eq
+						(call $ext_scratch_size)
+						(i32.const 8)
+					)
+				)
+
+				;; Read own address into memory.
+				(call $ext_scratch_read
+					(i32.const 16)	;; Pointer to write address to
+					(i32.const 0)	;; Offset into scrach buffer
+					(i32.const 8)	;; Length of encoded address
+				)
+
+				;; Recursively call self with empty imput data.
+				(call $assert
+					(i32.eq
+						(call $ext_call
+							(i32.const 16)	;; Pointer to own address
+							(i32.const 8)	;; Length of own address
+							(i64.const 0)	;; How much gas to devote for the execution. 0 = all.
+							(i32.const 8)	;; Pointer to the buffer with value to transfer
+							(i32.const 8)	;; Length of the buffer with value to transfer
+							(i32.const 0)	;; Pointer to input data buffer address
+							(i32.const 0)	;; Length of input data buffer
+						)
+						(i32.const 0)
+					)
+				)
+			)
+		)
+
+		;; Send entire remaining balance to the 0 address.
+		(call $ext_balance)
+
+		;; Balance should be encoded as a u64.
+		(call $assert
+			(i32.eq
+				(call $ext_scratch_size)
+				(i32.const 8)
+			)
+		)
+
+		;; Read balance into memory.
+		(call $ext_scratch_read
+			(i32.const 8)	;; Pointer to write balance to
+			(i32.const 0)	;; Offset into scrach buffer
+			(i32.const 8)	;; Length of encoded balance
+		)
+
+		;; Self-destruct by sending full balance to the 0 address.
+		(call $assert
+			(i32.eq
+				(call $ext_call
+					(i32.const 0)	;; Pointer to destination address
+					(i32.const 8)	;; Length of destination address
+					(i64.const 0)	;; How much gas to devote for the execution. 0 = all.
+					(i32.const 8)	;; Pointer to the buffer with value to transfer
+					(i32.const 8)	;; Length of the buffer with value to transfer
+					(i32.const 0)	;; Pointer to input data buffer address
+					(i32.const 0)	;; Length of input data buffer
+				)
+				(i32.const 0)
+			)
+		)
+	)
+)
+"#;
+
+#[test]
+fn self_destruct_by_draining_balance() {
+	let (wasm, code_hash) = compile_module::<Test>(CODE_SELF_DESTRUCT).unwrap();
+	with_externalities(
+		&mut ExtBuilder::default().existential_deposit(50).build(),
+		|| {
+			Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm));
+
+			// Instantiate the BOB contract.
+			assert_ok!(Contract::create(
+				Origin::signed(ALICE),
+				100_000,
+				100_000,
+				code_hash.into(),
+				vec![],
+			));
+
+			// Check that the BOB contract has been instantiated.
+			assert_matches!(
+				ContractInfoOf::<Test>::get(BOB),
+				Some(ContractInfo::Alive(_))
+			);
+
+			// Call BOB with no input data, forcing it to self-destruct.
+			assert_ok!(Contract::call(
+				Origin::signed(ALICE),
+				BOB,
+				0,
+				100_000,
+				vec![],
+			));
+
+			// Check that BOB is now dead.
+			assert!(ContractInfoOf::<Test>::get(BOB).is_none());
+		}
+	);
+}
+
+#[test]
+fn cannot_self_destruct_while_live() {
+	let (wasm, code_hash) = compile_module::<Test>(CODE_SELF_DESTRUCT).unwrap();
+	with_externalities(
+		&mut ExtBuilder::default().existential_deposit(50).build(),
+		|| {
+			Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm));
+
+			// Instantiate the BOB contract.
+			assert_ok!(Contract::create(
+				Origin::signed(ALICE),
+				100_000,
+				100_000,
+				code_hash.into(),
+				vec![],
+			));
+
+			// Check that the BOB contract has been instantiated.
+			assert_matches!(
+				ContractInfoOf::<Test>::get(BOB),
+				Some(ContractInfo::Alive(_))
+			);
+
+			// Call BOB with input data, forcing it make a recursive call to itself to
+			// self-destruct, resulting in a trap.
+			assert_err!(
+				Contract::call(
+					Origin::signed(ALICE),
+					BOB,
+					0,
+					100_000,
+					vec![0],
+				),
+				"during execution"
+			);
+
+			// Check that BOB is still alive.
+			assert_matches!(
+				ContractInfoOf::<Test>::get(BOB),
+				Some(ContractInfo::Alive(_))
+			);
+		}
+	);
+}
+
+const CODE_DESTROY_AND_TRANSFER: &str = r#"
+(module
+	(import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))
+	(import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32)))
+	(import "env" "ext_get_storage" (func $ext_get_storage (param i32) (result i32)))
+	(import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32 i32)))
+	(import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32)))
+	(import "env" "ext_create" (func $ext_create (param i32 i32 i64 i32 i32 i32 i32) (result i32)))
+	(import "env" "memory" (memory 1 1))
+
+	(func $assert (param i32)
+		(block $ok
+			(br_if $ok
+				(get_local 0)
+			)
+			(unreachable)
+		)
+	)
+
+	(func (export "deploy")
+		;; Input data is the code hash of the contract to be deployed.
+		(call $assert
+			(i32.eq
+				(call $ext_scratch_size)
+				(i32.const 32)
+			)
+		)
+
+		;; Copy code hash from scratch buffer into this contract's memory.
+		(call $ext_scratch_read
+			(i32.const 48)		;; The pointer where to store the scratch buffer contents,
+			(i32.const 0)		;; Offset from the start of the scratch buffer.
+			(i32.const 32)		;; Count of bytes to copy.
+		)
+
+		;; Deploy the contract with the provided code hash.
+		(call $assert
+			(i32.eq
+				(call $ext_create
+					(i32.const 48)	;; Pointer to the code hash.
+					(i32.const 32)	;; Length of the code hash.
+					(i64.const 0)	;; How much gas to devote for the execution. 0 = all.
+					(i32.const 0)	;; Pointer to the buffer with value to transfer
+					(i32.const 8)	;; Length of the buffer with value to transfer.
+					(i32.const 0)	;; Pointer to input data buffer address
+					(i32.const 0)	;; Length of input data buffer
+				)
+				(i32.const 0)
+			)
+		)
+
+		;; Read the address of the instantiated contract into memory.
+		(call $assert
+			(i32.eq
+				(call $ext_scratch_size)
+				(i32.const 8)
+			)
+		)
+		(call $ext_scratch_read
+			(i32.const 80)		;; The pointer where to store the scratch buffer contents,
+			(i32.const 0)		;; Offset from the start of the scratch buffer.
+			(i32.const 8)		;; Count of bytes to copy.
+		)
+
+		;; Store the return address.
+		(call $ext_set_storage
+			(i32.const 16)	;; Pointer to the key
+			(i32.const 1)	;; Value is not null
+			(i32.const 80)	;; Pointer to the value
+			(i32.const 8)	;; Length of the value
+		)
+	)
+
+	(func (export "call")
+		;; Read address of destination contract from storage.
+		(call $assert
+			(i32.eq
+				(call $ext_get_storage
+					(i32.const 16)	;; Pointer to the key
+				)
+				(i32.const 0)
+			)
+		)
+		(call $assert
+			(i32.eq
+				(call $ext_scratch_size)
+				(i32.const 8)
+			)
+		)
+		(call $ext_scratch_read
+			(i32.const 80)		;; The pointer where to store the contract address.
+			(i32.const 0)		;; Offset from the start of the scratch buffer.
+			(i32.const 8)		;; Count of bytes to copy.
+		)
+
+		;; Calling the destination contract with non-empty input data should fail.
+		(call $assert
+			(i32.eq
+				(call $ext_call
+					(i32.const 80)	;; Pointer to destination address
+					(i32.const 8)	;; Length of destination address
+					(i64.const 0)	;; How much gas to devote for the execution. 0 = all.
+					(i32.const 0)	;; Pointer to the buffer with value to transfer
+					(i32.const 8)	;; Length of the buffer with value to transfer
+					(i32.const 0)	;; Pointer to input data buffer address
+					(i32.const 1)	;; Length of input data buffer
+				)
+				(i32.const 0x0100)
+			)
+		)
+
+		;; Call the destination contract regularly, forcing it to self-destruct.
+		(call $assert
+			(i32.eq
+				(call $ext_call
+					(i32.const 80)	;; Pointer to destination address
+					(i32.const 8)	;; Length of destination address
+					(i64.const 0)	;; How much gas to devote for the execution. 0 = all.
+					(i32.const 8)	;; Pointer to the buffer with value to transfer
+					(i32.const 8)	;; Length of the buffer with value to transfer
+					(i32.const 0)	;; Pointer to input data buffer address
+					(i32.const 0)	;; Length of input data buffer
+				)
+				(i32.const 0)
+			)
+		)
+
+		;; Calling the destination address with non-empty input data should now work since the
+		;; contract has been removed. Also transfer a balance to the address so we can ensure this
+		;; does not keep the contract alive.
+		(call $assert
+			(i32.eq
+				(call $ext_call
+					(i32.const 80)	;; Pointer to destination address
+					(i32.const 8)	;; Length of destination address
+					(i64.const 0)	;; How much gas to devote for the execution. 0 = all.
+					(i32.const 0)	;; Pointer to the buffer with value to transfer
+					(i32.const 8)	;; Length of the buffer with value to transfer
+					(i32.const 0)	;; Pointer to input data buffer address
+					(i32.const 1)	;; Length of input data buffer
+				)
+				(i32.const 0)
+			)
+		)
+	)
+
+	(data (i32.const 0) "\00\00\01")		;; Endowment to send when creating contract.
+	(data (i32.const 8) "")		;; Value to send when calling contract.
+	(data (i32.const 16) "")	;; The key to store the contract address under.
+)
+"#;
+
+// This tests that one contract cannot prevent another from self-destructing by sending it
+// additional funds after it has been drained.
+#[test]
+fn destroy_contract_and_transfer_funds() {
+	let (callee_wasm, callee_code_hash) = compile_module::<Test>(CODE_SELF_DESTRUCT).unwrap();
+	let (caller_wasm, caller_code_hash) = compile_module::<Test>(CODE_DESTROY_AND_TRANSFER).unwrap();
+
+	with_externalities(
+		&mut ExtBuilder::default().existential_deposit(50).build(),
+		|| {
+			// Create
+			Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, callee_wasm));
+			assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, caller_wasm));
+
+			// This deploys the BOB contract, which in turn deploys the CHARLIE contract during
+			// construction.
+			assert_ok!(Contract::create(
+				Origin::signed(ALICE),
+				200_000,
+				100_000,
+				caller_code_hash.into(),
+				callee_code_hash.as_ref().to_vec(),
+			));
+
+			// Check that the CHARLIE contract has been instantiated.
+			assert_matches!(
+				ContractInfoOf::<Test>::get(CHARLIE),
+				Some(ContractInfo::Alive(_))
+			);
+
+			// Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct.
+			assert_ok!(Contract::call(
+				Origin::signed(ALICE),
+				BOB,
+				0,
+				100_000,
+				CHARLIE.encode(),
+			));
+
+			// Check that CHARLIE has moved on to the great beyond (ie. died).
+			assert!(ContractInfoOf::<Test>::get(CHARLIE).is_none());
+		}
+	);
+}
+
+const CODE_SELF_DESTRUCTING_CONSTRUCTOR: &str = r#"
+(module
+	(import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))
+	(import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32)))
+	(import "env" "ext_balance" (func $ext_balance))
+	(import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32)))
+	(import "env" "memory" (memory 1 1))
+
+	(func $assert (param i32)
+		(block $ok
+			(br_if $ok
+				(get_local 0)
+			)
+			(unreachable)
+		)
+	)
+
+	(func (export "deploy")
+		;; Send entire remaining balance to the 0 address.
+		(call $ext_balance)
+
+		;; Balance should be encoded as a u64.
+		(call $assert
+			(i32.eq
+				(call $ext_scratch_size)
+				(i32.const 8)
+			)
+		)
+
+		;; Read balance into memory.
+		(call $ext_scratch_read
+			(i32.const 8)	;; Pointer to write balance to
+			(i32.const 0)	;; Offset into scrach buffer
+			(i32.const 8)	;; Length of encoded balance
+		)
+
+		;; Self-destruct by sending full balance to the 0 address.
+		(call $assert
+			(i32.eq
+				(call $ext_call
+					(i32.const 0)	;; Pointer to destination address
+					(i32.const 8)	;; Length of destination address
+					(i64.const 0)	;; How much gas to devote for the execution. 0 = all.
+					(i32.const 8)	;; Pointer to the buffer with value to transfer
+					(i32.const 8)	;; Length of the buffer with value to transfer
+					(i32.const 0)	;; Pointer to input data buffer address
+					(i32.const 0)	;; Length of input data buffer
+				)
+				(i32.const 0)
+			)
+		)
+	)
+
+	(func (export "call"))
+)
+"#;
+
+#[test]
+fn cannot_self_destruct_in_constructor() {
+	let (wasm, code_hash) = compile_module::<Test>(CODE_SELF_DESTRUCTING_CONSTRUCTOR).unwrap();
+	with_externalities(
+		&mut ExtBuilder::default().existential_deposit(50).build(),
+		|| {
+			Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm));
+
+			// Fail to instantiate the BOB contract since its final balance is below existential
+			// deposit.
+			assert_err!(
+				Contract::create(
+					Origin::signed(ALICE),
+					100_000,
+					100_000,
+					code_hash.into(),
+					vec![],
+				),
+				"insufficient remaining balance"
+			);
+		}
+	);
+}
diff --git a/substrate/srml/contracts/src/wasm/runtime.rs b/substrate/srml/contracts/src/wasm/runtime.rs
index ecc4dfc7fb592f40ae5504d654405af65cc9865e..c6ef1bb3f561aea37d5527da9021b485a4ee4ed5 100644
--- a/substrate/srml/contracts/src/wasm/runtime.rs
+++ b/substrate/srml/contracts/src/wasm/runtime.rs
@@ -70,10 +70,6 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> {
 			special_trap: None,
 		}
 	}
-
-	fn memory(&self) -> &sandbox::Memory {
-		&self.memory
-	}
 }
 
 pub(crate) fn to_execution_result<E: Ext>(