git.delta.rocks / unique-network / refs/commits / e8fdadb89923

difftreelog

Code style update

str-mv2021-07-29parent: #1e0a302.patch.diff
in: master

58 files changed

addedpallets/contracts/CHANGELOG.mddiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/CHANGELOG.md
@@ -0,0 +1,93 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+The semantic versioning guarantees cover the interface to the substrate runtime which
+includes this pallet as a dependency. This module will also add storage migrations whenever
+changes require it. Stability with regard to offchain tooling is explicitly excluded from
+this guarantee: For example adding a new field to an in-storage data structure will require
+changes to frontends to properly display it. However, those changes will still be regarded
+as a minor version bump.
+
+The interface provided to smart contracts will adhere to semver with one exception: Even
+major version bumps will be backwards compatible with regard to already deployed contracts.
+In other words: Upgrading this pallet will not break pre-existing contracts.
+
+## [Unreleased]
+
+### Added
+
+- Add new `instantiate` RPC that allows clients to dry-run contract instantiation.
+
+- Make storage and fields of `Schedule` private to the crate.
+[1](https://github.com/paritytech/substrate/pull/8359)
+
+- Add new version of `seal_random` which exposes additional information.
+[1](https://github.com/paritytech/substrate/pull/8329)
+
+- Add `seal_rent_params` contract callable function.
+[1](https://github.com/paritytech/substrate/pull/8231)
+
+## [v3.0.0] 2021-02-25
+
+This version constitutes the first release that brings any stability guarantees (see above).
+
+### Added
+
+- Emit an event when a contract terminates (self-destructs).
+[1](https://github.com/paritytech/substrate/pull/8014)
+
+- Charge rent for code stored on the chain in addition to the already existing
+rent that is payed for data storage.
+[1](https://github.com/paritytech/substrate/pull/7935)
+
+- Allow the runtime to configure per storage item costs in addition
+to the already existing per byte costs.
+[1](https://github.com/paritytech/substrate/pull/7819)
+
+- Contracts are now deleted lazily so that the user who removes a contract
+does not need to pay for the deletion of the contract storage.
+[1](https://github.com/paritytech/substrate/pull/7740)
+
+- Allow runtime authors to define chain extensions in order to provide custom
+functionality to contracts.
+[1](https://github.com/paritytech/substrate/pull/7548)
+[2](https://github.com/paritytech/substrate/pull/8003)
+
+- Proper weights which are fully automated by benchmarking.
+[1](https://github.com/paritytech/substrate/pull/6715)
+[2](https://github.com/paritytech/substrate/pull/7017)
+[3](https://github.com/paritytech/substrate/pull/7361)
+
+### Changes
+
+- Collect the rent for one block during instantiation.
+[1](https://github.com/paritytech/substrate/pull/7847)
+
+- Instantiation takes a `salt` argument to allow for easier instantion of the
+same code by the same sender.
+[1](https://github.com/paritytech/substrate/pull/7482)
+
+- Improve the information returned by the `contracts_call` RPC.
+[1](https://github.com/paritytech/substrate/pull/7468)
+
+- Simplify the node configuration necessary to add this module.
+[1](https://github.com/paritytech/substrate/pull/7409)
+
+### Fixed
+
+- Consider the code size of a contract in the weight that is charged for
+loading a contract from storage.
+[1](https://github.com/paritytech/substrate/pull/8086)
+
+- Fix possible overflow in storage size calculation
+[1](https://github.com/paritytech/substrate/pull/7885)
+
+- Cap the surcharge reward that can be claimed.
+[1](https://github.com/paritytech/substrate/pull/7870)
+
+- Fix a possible DoS vector where contracts could allocate too large buffers.
+[1](https://github.com/paritytech/substrate/pull/7818)
addedpallets/contracts/COMPLEXITY.mddiffbeforeafterboth

no changes

addedpallets/contracts/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/Cargo.toml
@@ -0,0 +1,75 @@
+[package]
+name = "pallet-contracts"
+version = "3.0.0"
+authors = ["Parity Technologies <admin@parity.io>"]
+edition = "2018"
+license = "Apache-2.0"
+homepage = "https://substrate.dev"
+repository = "https://github.com/paritytech/substrate/"
+description = "FRAME pallet for WASM contracts"
+readme = "README.md"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[dependencies]
+codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+log = { version = "0.4", default-features = false }
+parity-wasm = { version = "0.42", default-features = false }
+pwasm-utils = { version = "0.17", default-features = false }
+serde = { version = "1", optional = true, features = ["derive"] }
+wasmi-validation = { version = "0.4", default-features = false }
+
+# Only used in benchmarking to generate random contract code
+rand = { version = "0.8", optional = true, default-features = false }
+rand_pcg = { version = "0.3", optional = true }
+
+# Substrate Dependencies
+frame-benchmarking = { version = "3.1.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3', optional = true }
+frame-support = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+frame-system = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+pallet-contracts-primitives = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+pallet-contracts-proc-macro = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-core = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-io = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-runtime = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-sandbox = { version = "0.9.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-std = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+
+[dev-dependencies]
+assert_matches = "1"
+hex-literal = "0.3"
+paste = "1"
+pretty_assertions = "0.7"
+wat = "1"
+
+# Substrate Dependencies
+pallet-balances = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+pallet-timestamp = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+pallet-randomness-collective-flip = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+
+[features]
+default = ["std"]
+std = [
+	"serde",
+	"codec/std",
+	"sp-core/std",
+	"sp-runtime/std",
+	"sp-io/std",
+	"sp-std/std",
+	"sp-sandbox/std",
+	"frame-support/std",
+	"frame-system/std",
+	"parity-wasm/std",
+	"pwasm-utils/std",
+	"wasmi-validation/std",
+	"pallet-contracts-primitives/std",
+	"pallet-contracts-proc-macro/full",
+	"log/std",
+]
+runtime-benchmarks = [
+	"frame-benchmarking",
+	"rand",
+	"rand_pcg",
+]
+
addedpallets/contracts/README.mddiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/README.md
@@ -0,0 +1,75 @@
+# Contract Module
+
+The Contract module provides functionality for the runtime to deploy and execute WebAssembly smart-contracts.
+
+- [`Call`](https://docs.rs/pallet-contracts/latest/pallet_contracts/enum.Call.html)
+- [`Config`](https://docs.rs/pallet-contracts/latest/pallet_contracts/trait.Config.html)
+- [`Error`](https://docs.rs/pallet-contracts/latest/pallet_contracts/enum.Error.html)
+- [`Event`](https://docs.rs/pallet-contracts/latest/pallet_contracts/enum.Event.html)
+
+## Overview
+
+This module extends accounts based on the `Currency` trait to have smart-contract functionality. It can
+be used with other modules that implement accounts based on `Currency`. These "smart-contract accounts"
+have the ability to instantiate smart-contracts and make calls to other contract and non-contract accounts.
+
+The smart-contract code is stored once in a `code_cache`, and later retrievable via its `code_hash`.
+This means that multiple smart-contracts can be instantiated from the same `code_cache`, without replicating
+the code each time.
+
+When a smart-contract is called, its associated code is retrieved via the code hash and gets executed.
+This call can alter the storage entries of the smart-contract account, instantiate new smart-contracts,
+or call other smart-contracts.
+
+Finally, when an account is reaped, its associated code and storage of the smart-contract account
+will also be deleted.
+
+### Gas
+
+Senders must specify a gas limit with every call, as all instructions invoked by the smart-contract require gas.
+Unused gas is refunded after the call, regardless of the execution outcome.
+
+If the gas limit is reached, then all calls and state changes (including balance transfers) are only
+reverted at the current call's contract level. For example, if contract A calls B and B runs out of gas mid-call,
+then all of B's calls are reverted. Assuming correct error handling by contract A, A's other calls and state
+changes still persist.
+
+One gas is equivalent to one [weight](https://substrate.dev/docs/en/knowledgebase/learn-substrate/weight)
+which is defined as one picosecond of execution time on the runtime's reference machine.
+
+### Notable Scenarios
+
+Contract call failures are not always cascading. When failures occur in a sub-call, they do not "bubble up",
+and the call will only revert at the specific contract level. For example, if contract A calls contract B, and B
+fails, A can decide how to handle that failure, either proceeding or reverting A's changes.
+
+## Interface
+
+### Dispatchable functions
+
+Those are documented in the [reference documentation](https://docs.rs/pallet-contracts/latest/pallet_contracts/#dispatchable-functions).
+
+## Usage
+
+This module executes WebAssembly smart contracts. These can potentially be written in any language
+that compiles to web assembly. However, using a language that specifically targets this module
+will make things a lot easier. One such language is [`ink`](https://github.com/paritytech/ink)
+which is an [`eDSL`](https://wiki.haskell.org/Embedded_domain_specific_language) that enables
+writing WebAssembly based smart contracts in the Rust programming language.
+
+## Debugging
+
+Contracts can emit messages to the node console when run on a development chain through the
+`seal_println` API. This is exposed in ink! via
+[`ink_env::debug_println()`](https://docs.rs/ink_env/latest/ink_env/fn.debug_println.html).
+
+In order to see these messages the log level for the `runtime::contracts` target needs to be raised
+to at least the `info` level which is the default. However, those messages are easy to overlook
+because of the noise generated by block production. A good starting point for contract debugging
+could be:
+
+```bash
+cargo run --release -- --dev --tmp -lerror,runtime::contracts
+```
+
+License: Apache-2.0
addedpallets/contracts/common/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/common/Cargo.toml
@@ -0,0 +1,33 @@
+[package]
+name = "pallet-contracts-primitives"
+version = "3.0.0"
+authors = ["Parity Technologies <admin@parity.io>"]
+edition = "2018"
+license = "Apache-2.0"
+homepage = "https://substrate.dev"
+repository = "https://github.com/paritytech/substrate/"
+description = "A crate that hosts a common definitions that are relevant for the pallet-contracts."
+readme = "README.md"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[dependencies]
+bitflags = "1.0"
+codec = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
+serde = { version = "1", features = ["derive"], optional = true }
+
+# Substrate Dependencies (This crate should not rely on frame)
+sp-core = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3', default-features = false }
+sp-std = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-runtime = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+
+[features]
+default = ["std"]
+std = [
+	"codec/std",
+	"sp-core/std",
+	"sp-runtime/std",
+	"sp-std/std",
+	"serde",
+]
addedpallets/contracts/common/README.mddiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/common/README.md
@@ -0,0 +1,3 @@
+A crate that hosts a common definitions that are relevant for the pallet-contracts.
+
+License: Apache-2.0
\ No newline at end of file
addedpallets/contracts/common/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/common/src/lib.rs
@@ -0,0 +1,148 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! A crate that hosts a common definitions that are relevant for the pallet-contracts.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+use bitflags::bitflags;
+use codec::{Decode, Encode};
+use sp_core::Bytes;
+use sp_runtime::{DispatchError, RuntimeDebug};
+use sp_std::prelude::*;
+
+#[cfg(feature = "std")]
+use serde::{Serialize, Deserialize};
+
+/// Result type of a `bare_call` or `bare_instantiate` call.
+///
+/// It contains the execution result together with some auxiliary information.
+#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
+pub struct ContractResult<T> {
+	/// How much gas was consumed during execution.
+	pub gas_consumed: u64,
+	/// An optional debug message. This message is only non-empty when explicitly requested
+	/// by the code that calls into the contract.
+	///
+	/// The contained bytes are valid UTF-8. This is not declared as `String` because
+	/// this type is not allowed within the runtime. A client should decode them in order
+	/// to present the message to its users.
+	///
+	/// # Note
+	///
+	/// The debug message is never generated during on-chain execution. It is reserved for
+	/// RPC calls.
+	pub debug_message: Bytes,
+	/// The execution result of the wasm code.
+	pub result: T,
+}
+
+/// Result type of a `bare_call` call.
+pub type ContractExecResult = ContractResult<Result<ExecReturnValue, DispatchError>>;
+
+/// Result type of a `bare_instantiate` call.
+pub type ContractInstantiateResult<AccountId, BlockNumber> =
+	ContractResult<Result<InstantiateReturnValue<AccountId, BlockNumber>, DispatchError>>;
+
+/// Result type of a `get_storage` call.
+pub type GetStorageResult = Result<Option<Vec<u8>>, ContractAccessError>;
+
+/// Result type of a `rent_projection` call.
+pub type RentProjectionResult<BlockNumber> =
+	Result<RentProjection<BlockNumber>, ContractAccessError>;
+
+/// The possible errors that can happen querying the storage of a contract.
+#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)]
+pub enum ContractAccessError {
+	/// The given address doesn't point to a contract.
+	DoesntExist,
+	/// The specified contract is a tombstone and thus cannot have any storage.
+	IsTombstone,
+}
+
+#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
+pub enum RentProjection<BlockNumber> {
+	/// Eviction is projected to happen at the specified block number.
+	EvictionAt(BlockNumber),
+	/// No eviction is scheduled.
+	///
+	/// E.g. Contract accumulated enough funds to offset the rent storage costs.
+	NoEviction,
+}
+
+bitflags! {
+	/// Flags used by a contract to customize exit behaviour.
+	#[derive(Encode, Decode)]
+	#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+	#[cfg_attr(feature = "std", serde(rename_all = "camelCase", transparent))]
+	pub struct ReturnFlags: u32 {
+		/// If this bit is set all changes made by the contract execution are rolled back.
+		const REVERT = 0x0000_0001;
+	}
+}
+
+/// Output of a contract call or instantiation which ran to completion.
+#[derive(PartialEq, Eq, Encode, Decode, RuntimeDebug)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
+pub struct ExecReturnValue {
+	/// Flags passed along by `seal_return`. Empty when `seal_return` was never called.
+	pub flags: ReturnFlags,
+	/// Buffer passed along by `seal_return`. Empty when `seal_return` was never called.
+	pub data: Bytes,
+}
+
+impl ExecReturnValue {
+	/// We understand the absense of a revert flag as success.
+	pub fn is_success(&self) -> bool {
+		!self.flags.contains(ReturnFlags::REVERT)
+	}
+}
+
+/// The result of a successful contract instantiation.
+#[derive(PartialEq, Eq, Encode, Decode, RuntimeDebug)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
+pub struct InstantiateReturnValue<AccountId, BlockNumber> {
+	/// The output of the called constructor.
+	pub result: ExecReturnValue,
+	/// The account id of the new contract.
+	pub account_id: AccountId,
+	/// Information about when and if the new project will be evicted.
+	///
+	/// # Note
+	///
+	/// `None` if `bare_instantiate` was called with
+	/// `compute_projection` set to false. From the perspective of an RPC this means that
+	/// the runtime API did not request this value and this feature is therefore unsupported.
+	pub rent_projection: Option<RentProjection<BlockNumber>>,
+}
+
+/// Reference to an existing code hash or a new wasm module.
+#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
+pub enum Code<Hash> {
+	/// A wasm module as raw bytes.
+	Upload(Bytes),
+	/// The code hash of an on-chain wasm blob.
+	Existing(Hash),
+}
addedpallets/contracts/fixtures/call_return_code.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/call_return_code.wat
@@ -0,0 +1,42 @@
+;; This calls the supplied dest and transfers 100 balance during this call and copies
+;; the return code of this call to the output buffer.
+;; It also forwards its input to the callee.
+(module
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
+	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
+	(import "env" "memory" (memory 1 1))
+
+	;; [0, 8) 100 balance
+	(data (i32.const 0) "\64\00\00\00\00\00\00\00")
+
+	;; [8, 12) here we store the return code of the transfer
+
+	;; [12, 16) size of the input data
+	(data (i32.const 12) "\24")
+
+	;; [16, inf) here we store the input data
+	;; 32 byte dest + 4 byte forward
+
+	(func (export "deploy"))
+
+	(func (export "call")
+		(call $seal_input (i32.const 16) (i32.const 12))
+		(i32.store
+			(i32.const 8)
+			(call $seal_call
+				(i32.const 16) ;; Pointer to "callee" address.
+				(i32.const 32) ;; Length of "callee" 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 48) ;; Pointer to input data buffer address
+				(i32.const 4) ;; Length of input data buffer
+				(i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output
+				(i32.const 0) ;; Ptr to output buffer len
+			)
+		)
+		;; exit with success and take transfer return code to the output buffer
+		(call $seal_return (i32.const 0) (i32.const 8) (i32.const 4))
+	)
+)
addedpallets/contracts/fixtures/caller_contract.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/caller_contract.wat
@@ -0,0 +1,293 @@
+(module
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "seal0" "seal_balance" (func $seal_balance (param i32 i32)))
+	(import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
+	(import "seal0" "seal_instantiate" (func $seal_instantiate
+		(param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)
+	))
+	(import "seal0" "seal_println" (func $seal_println (param i32 i32)))
+	(import "env" "memory" (memory 1 1))
+
+	(func $assert (param i32)
+		(block $ok
+			(br_if $ok
+				(get_local 0)
+			)
+			(unreachable)
+		)
+	)
+
+	(func $current_balance (param $sp i32) (result i64)
+		(i32.store
+			(i32.sub (get_local $sp) (i32.const 16))
+			(i32.const 8)
+		)
+		(call $seal_balance
+			(i32.sub (get_local $sp) (i32.const 8))
+			(i32.sub (get_local $sp) (i32.const 16))
+		)
+		(call $assert
+			(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 16))) (i32.const 8))
+		)
+		(i64.load (i32.sub (get_local $sp) (i32.const 8)))
+	)
+
+	(func (export "deploy"))
+
+	(func (export "call")
+		(local $sp i32)
+		(local $exit_code i32)
+		(local $balance i64)
+
+		;; Length of the buffer
+		(i32.store (i32.const 20) (i32.const 32))
+
+		;; Copy input to this contracts memory
+		(call $seal_input (i32.const 24) (i32.const 20))
+
+		;; Input data is the code hash of the contract to be deployed.
+		(call $assert
+			(i32.eq
+				(i32.load (i32.const 20))
+				(i32.const 32)
+			)
+		)
+
+		;; Read current balance into local variable.
+		(set_local $sp (i32.const 1024))
+		(set_local $balance
+			(call $current_balance (get_local $sp))
+		)
+
+		;; Fail to deploy the contract since it returns a non-zero exit status.
+		(set_local $exit_code
+			(call $seal_instantiate
+				(i32.const 24)	;; 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 9)	;; Pointer to input data buffer address
+				(i32.const 7)	;; Length of input data buffer
+				(i32.const 4294967295) ;; u32 max sentinel value: do not copy address
+				(i32.const 0) ;; Length is ignored in this case
+				(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
+				(i32.const 0) ;; Length is ignored in this case
+				(i32.const 0) ;; salt_ptr
+				(i32.const 0) ;; salt_le
+			)
+		)
+
+		;; Check non-zero exit status.
+		(call $assert
+			(i32.eq (get_local $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted
+		)
+
+		;; Check that balance has not changed.
+		(call $assert
+			(i64.eq (get_local $balance) (call $current_balance (get_local $sp)))
+		)
+
+		;; Fail to deploy the contract due to insufficient gas.
+		(set_local $exit_code
+			(call $seal_instantiate
+				(i32.const 24)	;; Pointer to the code hash.
+				(i32.const 32)	;; Length of the code hash.
+				(i64.const 1) ;; Supply too little gas
+				(i32.const 0)	;; Pointer to the buffer with value to transfer
+				(i32.const 8)	;; Length of the buffer with value to transfer.
+				(i32.const 8)	;; Pointer to input data buffer address
+				(i32.const 8)	;; Length of input data buffer
+				(i32.const 4294967295) ;; u32 max sentinel value: do not copy address
+				(i32.const 0) ;; Length is ignored in this case
+				(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
+				(i32.const 0) ;; Length is ignored in this case
+				(i32.const 0) ;; salt_ptr
+				(i32.const 0) ;; salt_le
+
+			)
+		)
+
+		;; Check for special trap exit status.
+		(call $assert
+			(i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped
+		)
+
+		;; Check that balance has not changed.
+		(call $assert
+			(i64.eq (get_local $balance) (call $current_balance (get_local $sp)))
+		)
+
+		;; Length of the output buffer
+		(i32.store
+			(i32.sub (get_local $sp) (i32.const 4))
+			(i32.const 256)
+		)
+
+		;; Deploy the contract successfully.
+		(set_local $exit_code
+			(call $seal_instantiate
+				(i32.const 24)	;; 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 8)	;; Pointer to input data buffer address
+				(i32.const 8)	;; Length of input data buffer
+				(i32.const 16) ;; Pointer to the address output buffer
+				(i32.sub (get_local $sp) (i32.const 4)) ;; Pointer to the address buffer length
+				(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
+				(i32.const 0) ;; Length is ignored in this case
+				(i32.const 0) ;; salt_ptr
+				(i32.const 0) ;; salt_le
+
+			)
+		)
+
+		;; Check for success exit status.
+		(call $assert
+			(i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success
+		)
+
+		;; Check that address has the expected length
+		(call $assert
+			(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 4))) (i32.const 32))
+		)
+
+		;; Check that balance has been deducted.
+		(set_local $balance
+			(i64.sub (get_local $balance) (i64.load (i32.const 0)))
+		)
+		(call $assert
+			(i64.eq (get_local $balance) (call $current_balance (get_local $sp)))
+		)
+
+		;; Zero out destination buffer of output
+		(i32.store
+			(i32.sub (get_local $sp) (i32.const 4))
+			(i32.const 0)
+		)
+
+		;; Length of the output buffer
+		(i32.store
+			(i32.sub (get_local $sp) (i32.const 8))
+			(i32.const 4)
+		)
+
+		;; Call the new contract and expect it to return failing exit code.
+		(set_local $exit_code
+			(call $seal_call
+				(i32.const 16)	;; Pointer to "callee" address.
+				(i32.const 32)	;; Length of "callee" 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 9)	;; Pointer to input data buffer address
+				(i32.const 7)	;; Length of input data buffer
+				(i32.sub (get_local $sp) (i32.const 4)) ;; Ptr to output buffer
+				(i32.sub (get_local $sp) (i32.const 8)) ;; Ptr to output buffer len
+			)
+		)
+
+		;; Check non-zero exit status.
+		(call $assert
+			(i32.eq (get_local $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted
+		)
+
+		;; Check that output buffer contains the expected return data.
+		(call $assert
+			(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 8))) (i32.const 3))
+		)
+		(call $assert
+			(i32.eq
+				(i32.load (i32.sub (get_local $sp) (i32.const 4)))
+				(i32.const 0x00776655)
+			)
+		)
+
+		;; Check that balance has not changed.
+		(call $assert
+			(i64.eq (get_local $balance) (call $current_balance (get_local $sp)))
+		)
+
+		;; Fail to call the contract due to insufficient gas.
+		(set_local $exit_code
+			(call $seal_call
+				(i32.const 16)	;; Pointer to "callee" address.
+				(i32.const 32)	;; Length of "callee" address.
+				(i64.const 1) ;; Supply too little gas
+				(i32.const 0)	;; Pointer to the buffer with value to transfer
+				(i32.const 8)	;; Length of the buffer with value to transfer.
+				(i32.const 8)	;; Pointer to input data buffer address
+				(i32.const 8)	;; Length of input data buffer
+				(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
+				(i32.const 0) ;; Length is ignored in this cas
+			)
+		)
+
+		;; Check for special trap exit status.
+		(call $assert
+			(i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped
+		)
+
+		;; Check that balance has not changed.
+		(call $assert
+			(i64.eq (get_local $balance) (call $current_balance (get_local $sp)))
+		)
+
+		;; Zero out destination buffer of output
+		(i32.store
+			(i32.sub (get_local $sp) (i32.const 4))
+			(i32.const 0)
+		)
+
+		;; Length of the output buffer
+		(i32.store
+			(i32.sub (get_local $sp) (i32.const 8))
+			(i32.const 4)
+		)
+
+		;; Call the contract successfully.
+		(set_local $exit_code
+			(call $seal_call
+				(i32.const 16)	;; Pointer to "callee" address.
+				(i32.const 32)	;; Length of "callee" 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 8)	;; Pointer to input data buffer address
+				(i32.const 8)	;; Length of input data buffer
+				(i32.sub (get_local $sp) (i32.const 4)) ;; Ptr to output buffer
+				(i32.sub (get_local $sp) (i32.const 8)) ;; Ptr to output buffer len
+			)
+		)
+
+		;; Check for success exit status.
+		(call $assert
+			(i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success
+		)
+
+		;; Check that the output buffer contains the expected return data.
+		(call $assert
+			(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 8))) (i32.const 4))
+		)
+		(call $assert
+			(i32.eq
+				(i32.load (i32.sub (get_local $sp) (i32.const 4)))
+				(i32.const 0x77665544)
+			)
+		)
+
+		;; Check that balance has been deducted.
+		(set_local $balance
+			(i64.sub (get_local $balance) (i64.load (i32.const 0)))
+		)
+		(call $assert
+			(i64.eq (get_local $balance) (call $current_balance (get_local $sp)))
+		)
+	)
+
+	(data (i32.const 0) "\00\80")		;; The value to transfer on instantiation and calls.
+										;; Chosen to be greater than existential deposit.
+	(data (i32.const 8) "\00\01\22\33\44\55\66\77")		;; The input data to instantiations and calls.
+)
addedpallets/contracts/fixtures/chain_extension.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/chain_extension.wat
@@ -0,0 +1,46 @@
+;; Call chain extension by passing through input and output of this contract
+(module
+	(import "seal0" "seal_call_chain_extension"
+		(func $seal_call_chain_extension (param i32 i32 i32 i32 i32) (result i32))
+	)
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
+	(import "env" "memory" (memory 16 16))
+
+	(func $assert (param i32)
+		(block $ok
+			(br_if $ok (get_local 0))
+			(unreachable)
+		)
+	)
+
+	;; [0, 4) len of input output
+	(data (i32.const 0) "\02")
+
+	;; [4, 12) buffer for input
+
+	;; [12, 16) len of output buffer
+	(data (i32.const 12) "\02")
+
+	;; [16, inf) buffer for output
+
+	(func (export "deploy"))
+
+	(func (export "call")
+		(call $seal_input (i32.const 4) (i32.const 0))
+
+		;; the chain extension passes through the input and returns it as output
+		(call $seal_call_chain_extension
+			(i32.load8_u (i32.const 4))	;; func_id
+			(i32.const 4)				;; input_ptr
+			(i32.load (i32.const 0))	;; input_len
+			(i32.const 16)				;; output_ptr
+			(i32.const 12)				;; output_len_ptr
+		)
+
+		;; the chain extension passes through the func_id
+		(call $assert (i32.eq (i32.load8_u (i32.const 4))))
+
+		(call $seal_return (i32.const 0) (i32.const 16) (i32.load (i32.const 12)))
+	)
+)
addedpallets/contracts/fixtures/check_default_rent_allowance.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/check_default_rent_allowance.wat
@@ -0,0 +1,43 @@
+(module
+	(import "seal0" "seal_rent_allowance" (func $seal_rent_allowance (param i32 i32)))
+	(import "env" "memory" (memory 1 1))
+
+	;; [0, 8) reserved for $seal_rent_allowance output
+
+	;; [8, 16) length of the buffer
+	(data (i32.const 8) "\08")
+
+	;; [16, inf) zero initialized
+
+	(func $assert (param i32)
+		(block $ok
+			(br_if $ok
+				(get_local 0)
+			)
+			(unreachable)
+		)
+	)
+
+	(func (export "call"))
+
+	(func (export "deploy")
+		;; fill the buffer with the rent allowance.
+		(call $seal_rent_allowance (i32.const 0) (i32.const 8))
+
+		;; assert len == 8
+		(call $assert
+			(i32.eq
+				(i32.load (i32.const 8))
+				(i32.const 8)
+			)
+		)
+
+		;; assert that contents of the buffer is equal to <BalanceOf<T>>::max_value().
+		(call $assert
+			(i64.eq
+				(i64.load (i32.const 0))
+				(i64.const 0xFFFFFFFFFFFFFFFF)
+			)
+		)
+	)
+)
addedpallets/contracts/fixtures/crypto_hashes.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/crypto_hashes.wat
@@ -0,0 +1,81 @@
+(module
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
+
+	(import "seal0" "seal_hash_sha2_256" (func $seal_hash_sha2_256 (param i32 i32 i32)))
+	(import "seal0" "seal_hash_keccak_256" (func $seal_hash_keccak_256 (param i32 i32 i32)))
+	(import "seal0" "seal_hash_blake2_256" (func $seal_hash_blake2_256 (param i32 i32 i32)))
+	(import "seal0" "seal_hash_blake2_128" (func $seal_hash_blake2_128 (param i32 i32 i32)))
+
+	(import "env" "memory" (memory 1 1))
+
+	(type $hash_fn_sig (func (param i32 i32 i32)))
+	(table 8 funcref)
+	(elem (i32.const 1)
+		$seal_hash_sha2_256
+		$seal_hash_keccak_256
+		$seal_hash_blake2_256
+		$seal_hash_blake2_128
+	)
+	(data (i32.const 1) "20202010201008") ;; Output sizes of the hashes in order in hex.
+
+	;; Not in use by the tests besides instantiating the contract.
+	(func (export "deploy"))
+
+	;; Called by the tests.
+	;;
+	;; The `call` function expects data in a certain format in the input buffer.
+	;;
+	;; 1. The first byte encodes an identifier for the crypto hash function
+	;;    under test. (*)
+	;; 2. The rest encodes the input data that is directly fed into the
+	;;    crypto hash function chosen in 1.
+	;;
+	;; The `deploy` function then computes the chosen crypto hash function
+	;; given the input and puts the result into the output buffer.
+	;; After contract execution the test driver then asserts that the returned
+	;; values are equal to the expected bytes for the input and chosen hash
+	;; function.
+	;;
+	;; (*) The possible value for the crypto hash identifiers can be found below:
+	;;
+	;; | value | Algorithm | Bit Width |
+	;; |-------|-----------|-----------|
+	;; |     0 |      SHA2 |       256 |
+	;; |     1 |    KECCAK |       256 |
+	;; |     2 |    BLAKE2 |       256 |
+	;; |     3 |    BLAKE2 |       128 |
+	;; ---------------------------------
+	(func (export "call")
+		(local $chosen_hash_fn i32)
+		(local $input_len_ptr i32)
+		(local $input_ptr i32)
+		(local $input_len i32)
+		(local $output_ptr i32)
+		(local $output_len i32)
+		(local.set $input_len_ptr (i32.const 256))
+		(local.set $input_ptr (i32.const 10))
+		(i32.store (local.get $input_len_ptr) (i32.const 246))
+		(call $seal_input (local.get $input_ptr) (local.get $input_len_ptr))
+		(local.set $chosen_hash_fn (i32.load8_u (local.get $input_ptr)))
+		(if (i32.gt_u (local.get $chosen_hash_fn) (i32.const 7))
+			;; We check that the chosen hash fn  identifier is within bounds: [0,7]
+			(unreachable)
+		)
+		(local.set $input_ptr (i32.add (local.get $input_ptr) (i32.const 1)))
+		(local.set $input_len (i32.sub (i32.load (local.get $input_len_ptr)) (i32.const 1)))
+		(local.set $output_len (i32.load8_u (local.get $chosen_hash_fn)))
+		(call_indirect (type $hash_fn_sig)
+			(local.get $input_ptr)
+			(local.get $input_len)
+			(local.get $input_ptr)
+			(local.get $chosen_hash_fn) ;; Which crypto hash function to execute.
+		)
+		(call $seal_return
+			(i32.const 0)
+			(local.get $input_ptr) ;; Linear memory location of the output buffer.
+			(local.get $output_len) ;; Number of output buffer bytes.
+		)
+		(unreachable)
+	)
+)
addedpallets/contracts/fixtures/destroy_and_transfer.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/destroy_and_transfer.wat
@@ -0,0 +1,161 @@
+(module
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32)))
+	(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
+	(import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
+	(import "seal0" "seal_transfer" (func $seal_transfer (param i32 i32 i32 i32) (result i32)))
+	(import "seal0" "seal_instantiate"  (func $seal_instantiate
+		(param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)
+	))
+	(import "env" "memory" (memory 1 1))
+
+	;; [0, 8) Endowment to send when creating contract.
+	(data (i32.const 0) "\00\00\01")
+
+	;; [8, 16) Value to send when calling contract.
+
+	;; [16, 48) The key to store the contract address under.
+
+	;; [48, 80) Buffer where to store the input to the contract
+
+	;; [88, 96) Size of the buffer
+	(data (i32.const 88) "\FF")
+
+	;; [96, 100) Size of the input buffer
+	(data (i32.const 96) "\20")
+
+	;; [100, 132) Buffer where to store the address of the instantiated contract
+
+	;; [132, 134) Salt
+	(data (i32.const 132) "\47\11")
+
+
+	(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 $seal_input (i32.const 48) (i32.const 96))
+		(call $assert
+			(i32.eq
+				(i32.load (i32.const 96))
+				(i32.const 32)
+			)
+		)
+
+		;; Deploy the contract with the provided code hash.
+		(call $assert
+			(i32.eq
+				(call $seal_instantiate
+					(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 100)	;; Buffer where to store address of new contract
+					(i32.const 88)	;; Pointer to the length of the buffer
+					(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
+					(i32.const 0) ;; Length is ignored in this case
+					(i32.const 132) ;; salt_ptr
+					(i32.const 2) ;; salt_len
+				)
+				(i32.const 0)
+			)
+		)
+
+		;; Check that address has expected length
+		(call $assert
+			(i32.eq
+				(i32.load (i32.const 88))
+				(i32.const 32)
+			)
+		)
+
+		;; Store the return address.
+		(call $seal_set_storage
+			(i32.const 16)	;; Pointer to the key
+			(i32.const 100)	;; Pointer to the value
+			(i32.const 32)	;; Length of the value
+		)
+	)
+
+	(func (export "call")
+		;; Read address of destination contract from storage.
+		(call $assert
+			(i32.eq
+				(call $seal_get_storage
+					(i32.const 16)	;; Pointer to the key
+					(i32.const 100)	;; Pointer to the value
+					(i32.const 88)	;; Pointer to the len of the value
+				)
+				(i32.const 0)
+			)
+		)
+		(call $assert
+			(i32.eq
+				(i32.load (i32.const 88))
+				(i32.const 32)
+			)
+		)
+
+		;; Calling the destination contract with non-empty input data should fail.
+		(call $assert
+			(i32.eq
+				(call $seal_call
+					(i32.const 100)	;; Pointer to destination address
+					(i32.const 32)	;; 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 4294967295) ;; u32 max sentinel value: do not copy output
+					(i32.const 0) ;; Length is ignored in this case
+
+				)
+				(i32.const 0x1)
+			)
+		)
+
+		;; Call the destination contract regularly, forcing it to self-destruct.
+		(call $assert
+			(i32.eq
+				(call $seal_call
+					(i32.const 100)	;; Pointer to destination address
+					(i32.const 32)	;; 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 4294967295) ;; u32 max sentinel value: do not copy output
+					(i32.const 0) ;; Length is ignored in this case
+				)
+				(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 $seal_transfer
+					(i32.const 100)	;; Pointer to destination address
+					(i32.const 32)	;; Length of destination address
+					(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)
+			)
+		)
+	)
+)
addedpallets/contracts/fixtures/drain.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/drain.wat
@@ -0,0 +1,49 @@
+(module
+	(import "seal0" "seal_balance" (func $seal_balance (param i32 i32)))
+	(import "seal0" "seal_transfer" (func $seal_transfer (param i32 i32 i32 i32) (result i32)))
+	(import "env" "memory" (memory 1 1))
+
+	;; [0, 8) reserved for $seal_balance output
+
+	;; [8, 16) length of the buffer
+	(data (i32.const 8) "\08")
+
+	;; [16, inf) zero initialized
+
+	(func $assert (param i32)
+		(block $ok
+			(br_if $ok
+				(get_local 0)
+			)
+			(unreachable)
+		)
+	)
+
+	(func (export "deploy"))
+
+	(func (export "call")
+		;; Send entire remaining balance to the 0 address.
+		(call $seal_balance (i32.const 0) (i32.const 8))
+
+		;; Balance should be encoded as a u64.
+		(call $assert
+			(i32.eq
+				(i32.load (i32.const 8))
+				(i32.const 8)
+			)
+		)
+
+		;; Self-destruct by sending full balance to the 0 address.
+		(call $assert
+			(i32.eq
+				(call $seal_transfer
+					(i32.const 16)	;; Pointer to destination address
+					(i32.const 32)	;; Length of destination address
+					(i32.const 0)	;; Pointer to the buffer with value to transfer
+					(i32.const 8)	;; Length of the buffer with value to transfer
+				)
+				(i32.const 4) ;; ReturnCode::BelowSubsistenceThreshold
+			)
+		)
+	)
+)
addedpallets/contracts/fixtures/event_size.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/event_size.wat
@@ -0,0 +1,39 @@
+(module
+	(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "env" "memory" (memory 16 16))
+
+	;; [0, 4) size of the input buffer
+	(data (i32.const 0) "\04")
+
+	(func $assert (param i32)
+		(block $ok
+			(br_if $ok
+				(get_local 0)
+			)
+			(unreachable)
+		)
+	)
+
+	(func (export "call")
+		(call $seal_input (i32.const 4) (i32.const 0))
+
+		;; assert input size == 4
+		(call $assert
+			(i32.eq
+				(i32.load (i32.const 0))
+				(i32.const 4)
+			)
+		)
+
+		;; place a garbage value in storage, the size of which is specified by the call input.
+		(call $seal_deposit_event
+			(i32.const 0) ;; topics_ptr
+			(i32.const 0) ;; topics_len
+			(i32.const 0) ;; data_ptr
+			(i32.load (i32.const 4)) ;; data_len
+		)
+	)
+
+	(func (export "deploy"))
+)
addedpallets/contracts/fixtures/instantiate_return_code.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/instantiate_return_code.wat
@@ -0,0 +1,49 @@
+;; This instantiats a contract and transfers 100 balance during this call and copies the return code
+;; of this call to the output buffer.
+;; The first 32 byte of input is the code hash to instantiate
+;; The rest of the input is forwarded to the constructor of the callee
+(module
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "seal0" "seal_instantiate" (func $seal_instantiate
+		(param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)
+	))
+	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
+	(import "env" "memory" (memory 1 1))
+
+	;; [0, 8) 10_000 balance
+	(data (i32.const 0) "\10\27\00\00\00\00\00\00")
+
+	;; [8, 12) here we store the return code of the transfer
+
+	;; [12, 16) size of the input buffer
+	(data (i32.const 12) "\24")
+
+	;; [16, inf) input buffer
+	;; 32 bye code hash + 4 byte forward
+
+	(func (export "deploy"))
+
+	(func (export "call")
+		(call $seal_input (i32.const 16) (i32.const 12))
+		(i32.store
+			(i32.const 8)
+			(call $seal_instantiate
+				(i32.const 16) ;; 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 48) ;; Pointer to input data buffer address
+				(i32.const 4) ;; Length of input data buffer
+				(i32.const 0xffffffff) ;; u32 max sentinel value: do not copy address
+				(i32.const 0) ;; Length is ignored in this case
+				(i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output
+				(i32.const 0) ;; Length is ignored in this case
+				(i32.const 0) ;; salt_ptr
+				(i32.const 0) ;; salt_len
+			)
+		)
+		;; exit with success and take transfer return code to the output buffer
+		(call $seal_return (i32.const 0) (i32.const 8) (i32.const 4))
+	)
+)
addedpallets/contracts/fixtures/ok_trap_revert.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/ok_trap_revert.wat
@@ -0,0 +1,35 @@
+(module
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
+	(import "env" "memory" (memory 1 1))
+
+    (func (export "deploy")
+        (call $ok_trap_revert)
+    )
+
+    (func (export "call")
+        (call $ok_trap_revert)
+    )
+
+    (func $ok_trap_revert
+        (i32.store (i32.const 4) (i32.const 4))
+        (call $seal_input (i32.const 0) (i32.const 4))
+        (block $IF_2
+            (block $IF_1
+                (block $IF_0
+                    (br_table $IF_0 $IF_1 $IF_2
+                        (i32.load8_u (i32.const 0))
+                    )
+                    (unreachable)
+                )
+                ;; 0 = return with success
+                return
+            )
+            ;; 1 = revert
+            (call $seal_return (i32.const 1) (i32.const 0) (i32.const 0))
+            (unreachable)
+        )
+        ;; 2 = trap
+        (unreachable)
+    )
+)
\ No newline at end of file
addedpallets/contracts/fixtures/restoration.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/restoration.wat
@@ -0,0 +1,75 @@
+(module
+	(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "seal0" "seal_restore_to"
+		(func $seal_restore_to
+			(param i32 i32 i32 i32 i32 i32 i32 i32)
+		)
+	)
+	(import "env" "memory" (memory 1 1))
+
+	(func $assert (param i32)
+		(block $ok
+			(br_if $ok
+				(get_local 0)
+			)
+			(unreachable)
+		)
+	)
+
+	(func (export "call")
+		;; copy code hash to contract memory
+		(call $seal_input (i32.const 308) (i32.const 304))
+		(call $assert
+			(i32.eq
+				(i32.load (i32.const 304))
+				(i32.const 64)
+			)
+		)
+		(call $seal_restore_to
+			;; Pointer and length of the encoded dest buffer.
+			(i32.const 340)
+			(i32.const 32)
+			;; Pointer and length of the encoded code hash buffer
+			(i32.const 308)
+			(i32.const 32)
+			;; Pointer and length of the encoded rent_allowance buffer
+			(i32.const 296)
+			(i32.const 8)
+			;; Pointer and number of items in the delta buffer.
+			;; This buffer specifies multiple keys for removal before restoration.
+			(i32.const 100)
+			(i32.const 1)
+		)
+	)
+	(func (export "deploy")
+		;; Data to restore
+		(call $seal_set_storage
+			(i32.const 0)
+			(i32.const 0)
+			(i32.const 4)
+		)
+
+		;; ACL
+		(call $seal_set_storage
+			(i32.const 100)
+			(i32.const 0)
+			(i32.const 4)
+		)
+	)
+
+	;; Data to restore
+	(data (i32.const 0) "\28")
+
+	;; Buffer that has ACL storage keys.
+	(data (i32.const 100) "\01")
+
+	;; [296, 304) Rent allowance
+	(data (i32.const 296) "\32\00\00\00\00\00\00\00")
+
+	;; [304, 308) Size of the buffer that holds code_hash + addr
+	(data (i32.const 304) "\40")
+
+	;; [308, 340) code hash of bob (copied by seal_input)
+	;; [340, 372) addr of bob (copied by seal_input)
+)
addedpallets/contracts/fixtures/return_from_start_fn.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/return_from_start_fn.wat
@@ -0,0 +1,28 @@
+(module
+	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
+	(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
+	(import "env" "memory" (memory 1 1))
+
+	(start $start)
+	(func $start
+		(call $seal_deposit_event
+			(i32.const 0) ;; The topics buffer
+			(i32.const 0) ;; The topics buffer's length
+			(i32.const 8) ;; The data buffer
+			(i32.const 4) ;; The data buffer's length
+		)
+		(call $seal_return
+			(i32.const 0)
+			(i32.const 8)
+			(i32.const 4)
+		)
+		(unreachable)
+	)
+
+	(func (export "call")
+		(unreachable)
+	)
+	(func (export "deploy"))
+
+	(data (i32.const 8) "\01\02\03\04")
+)
addedpallets/contracts/fixtures/return_with_data.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/return_with_data.wat
@@ -0,0 +1,33 @@
+(module
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
+	(import "env" "memory" (memory 1 1))
+
+	;; [0, 128) buffer where input is copied
+
+	;; [128, 132) length of the input buffer
+	(data (i32.const 128) "\80")
+
+	;; Deploy routine is the same as call.
+	(func (export "deploy")
+		(call $call)
+	)
+
+	;; Call reads the first 4 bytes (LE) as the exit status and returns the rest as output data.
+	(func $call (export "call")
+		;; Copy input into this contracts memory.
+		(call $seal_input (i32.const 0) (i32.const 128))
+
+		;; Copy all but the first 4 bytes of the input data as the output data.
+		;; Use the first byte as exit status
+		(call $seal_return
+			(i32.load8_u (i32.const 0))	;; Exit status
+			(i32.const 4)	;; Pointer to the data to return.
+			(i32.sub		;; Count of bytes to copy.
+				(i32.load (i32.const 128))
+				(i32.const 4)
+			)
+		)
+		(unreachable)
+	)
+)
addedpallets/contracts/fixtures/run_out_of_gas.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/run_out_of_gas.wat
@@ -0,0 +1,7 @@
+(module
+	(func (export "call")
+		(loop $inf (br $inf)) ;; just run out of gas
+		(unreachable)
+	)
+	(func (export "deploy"))
+)
addedpallets/contracts/fixtures/self_destruct.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/self_destruct.wat
@@ -0,0 +1,83 @@
+(module
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "seal0" "seal_address" (func $seal_address (param i32 i32)))
+	(import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
+	(import "seal0" "seal_terminate" (func $seal_terminate (param i32 i32)))
+	(import "env" "memory" (memory 1 1))
+
+	;; [0, 32) reserved for $seal_address output
+
+	;; [32, 36) length of the buffer
+	(data (i32.const 32) "\20")
+
+	;; [36, 68) Address of django
+	(data (i32.const 36)
+		"\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04"
+		"\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04"
+	)
+
+	;; [68, 72) reserved for output of $seal_input
+
+	;; [72, 76) length of the buffer
+	(data (i32.const 72) "\04")
+
+	;; [76, inf) zero initialized
+
+	(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.
+		(call $seal_input (i32.const 68) (i32.const 72))
+		(if (i32.load (i32.const 72))
+			(then
+				(call $seal_address (i32.const 0) (i32.const 32))
+
+				;; Expect address to be 8 bytes.
+				(call $assert
+					(i32.eq
+						(i32.load (i32.const 32))
+						(i32.const 32)
+					)
+				)
+
+				;; Recursively call self with empty input data.
+				(call $assert
+					(i32.eq
+						(call $seal_call
+							(i32.const 0)	;; Pointer to own address
+							(i32.const 32)	;; Length of own address
+							(i64.const 0)	;; How much gas to devote for the execution. 0 = all.
+							(i32.const 76)	;; 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 4294967295) ;; u32 max sentinel value: do not copy output
+							(i32.const 0) ;; Length is ignored in this case
+						)
+						(i32.const 0)
+					)
+				)
+			)
+			(else
+				;; Try to terminate and give balance to django.
+				(call $seal_terminate
+					(i32.const 36)	;; Pointer to beneficiary address
+					(i32.const 32)	;; Length of beneficiary address
+				)
+				(unreachable) ;; seal_terminate never returns
+			)
+		)
+	)
+)
addedpallets/contracts/fixtures/self_destructing_constructor.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/self_destructing_constructor.wat
@@ -0,0 +1,23 @@
+(module
+	(import "seal0" "seal_terminate" (func $seal_terminate (param i32 i32)))
+	(import "env" "memory" (memory 1 1))
+
+	(func $assert (param i32)
+		(block $ok
+			(br_if $ok
+				(get_local 0)
+			)
+			(unreachable)
+		)
+	)
+
+	(func (export "deploy")
+		;; Self-destruct by sending full balance to the 0 address.
+		(call $seal_terminate
+			(i32.const 0)	;; Pointer to destination address
+			(i32.const 32)	;; Length of destination address
+		)
+	)
+
+	(func (export "call"))
+)
addedpallets/contracts/fixtures/set_empty_storage.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/set_empty_storage.wat
@@ -0,0 +1,15 @@
+;; This module stores a KV pair into the storage
+(module
+	(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
+	(import "env" "memory" (memory 16 16))
+
+	(func (export "call")
+	)
+	(func (export "deploy")
+		(call $seal_set_storage
+			(i32.const 0)				;; Pointer to storage key
+			(i32.const 0)				;; Pointer to value
+			(i32.load (i32.const 0))	;; Size of value
+		)
+	)
+)
addedpallets/contracts/fixtures/set_rent.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/set_rent.wat
@@ -0,0 +1,105 @@
+(module
+	(import "seal0" "seal_transfer" (func $seal_transfer (param i32 i32 i32 i32) (result i32)))
+	(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
+	(import "seal0" "seal_clear_storage" (func $seal_clear_storage (param i32)))
+	(import "seal0" "seal_set_rent_allowance" (func $seal_set_rent_allowance (param i32 i32)))
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "env" "memory" (memory 1 1))
+
+	;; insert a value of 4 bytes into storage
+	(func $call_0
+		(call $seal_set_storage
+			(i32.const 1)
+			(i32.const 0)
+			(i32.const 4)
+		)
+	)
+
+	;; remove the value inserted by call_1
+	(func $call_1
+		(call $seal_clear_storage
+			(i32.const 1)
+		)
+	)
+
+	;; transfer 50 to CHARLIE
+	(func $call_2
+		(call $assert
+			(i32.eq
+				(call $seal_transfer (i32.const 136) (i32.const 32) (i32.const 100) (i32.const 8))
+				(i32.const 0)
+			)
+		)
+	)
+
+	;; do nothing
+	(func $call_else)
+
+	(func $assert (param i32)
+		(block $ok
+			(br_if $ok
+				(get_local 0)
+			)
+			(unreachable)
+		)
+	)
+
+	;; Dispatch the call according to input size
+	(func (export "call")
+		(local $input_size i32)
+		;; 4 byte i32 for br_table followed by 32 byte destination for transfer
+		(i32.store (i32.const 128) (i32.const 36))
+		(call $seal_input (i32.const 132) (i32.const 128))
+		(set_local $input_size
+			(i32.load (i32.const 132))
+		)
+		(block $IF_ELSE
+			(block $IF_2
+				(block $IF_1
+					(block $IF_0
+						(br_table $IF_0 $IF_1 $IF_2 $IF_ELSE
+							(get_local $input_size)
+						)
+						(unreachable)
+					)
+					(call $call_0)
+					return
+				)
+				(call $call_1)
+				return
+			)
+			(call $call_2)
+			return
+		)
+		(call $call_else)
+	)
+
+	;; Set into storage a 4 bytes value
+	;; Set call set_rent_allowance with input
+	(func (export "deploy")
+		(call $seal_set_storage
+			(i32.const 0)
+			(i32.const 0)
+			(i32.const 4)
+		)
+		(i32.store (i32.const 128) (i32.const 64))
+		(call $seal_input
+			(i32.const 132)
+			(i32.const 128)
+		)
+		(call $seal_set_rent_allowance
+			(i32.const 132)
+			(i32.load (i32.const 128))
+		)
+	)
+
+	;; Encoding of 10 in balance
+	(data (i32.const 0) "\28")
+
+	;; encoding of 50 balance
+	(data (i32.const 100) "\32")
+
+	;; [128, 132) size of seal input buffer
+
+	;; [132, inf) output buffer for seal input
+)
addedpallets/contracts/fixtures/storage_size.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/storage_size.wat
@@ -0,0 +1,68 @@
+(module
+	(import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32)))
+	(import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32)))
+	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
+	(import "env" "memory" (memory 16 16))
+
+	;; [0, 32) storage key
+	(data (i32.const 0) "\01")
+
+	;; [32, 36) buffer where input is copied (expected size of storage item)
+
+	;; [36, 40) size of the input buffer
+	(data (i32.const 36) "\04")
+
+	;; [40, 44) size of buffer for seal_get_storage set to max
+	(data (i32.const 40) "\FF\FF\FF\FF")
+
+	;; [44, inf) seal_get_storage buffer
+
+	(func $assert (param i32)
+		(block $ok
+			(br_if $ok
+				(get_local 0)
+			)
+			(unreachable)
+		)
+	)
+
+	(func (export "call")
+		(call $seal_input (i32.const 32) (i32.const 36))
+
+		;; assert input size == 4
+		(call $assert
+			(i32.eq
+				(i32.load (i32.const 36))
+				(i32.const 4)
+			)
+		)
+
+		;; place a garbage value in storage, the size of which is specified by the call input.
+		(call $seal_set_storage
+			(i32.const 0)		;; Pointer to storage key
+			(i32.const 0)		;; Pointer to value
+			(i32.load (i32.const 32))	;; Size of value
+		)
+
+		(call $assert
+			(i32.eq
+				(call $seal_get_storage
+					(i32.const 0)		;; Pointer to storage key
+					(i32.const 44)		;; buffer where to copy result
+					(i32.const 40)		;; pointer to size of buffer
+				)
+				(i32.const 0)
+			)
+		)
+
+		(call $assert
+			(i32.eq
+				(i32.load (i32.const 40))
+				(i32.load (i32.const 32))
+			)
+		)
+	)
+
+	(func (export "deploy"))
+
+)
addedpallets/contracts/fixtures/transfer_return_code.watdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/fixtures/transfer_return_code.wat
@@ -0,0 +1,34 @@
+;; This transfers 100 balance to the zero account and copies the return code
+;; of this transfer to the output buffer.
+(module
+	(import "seal0" "seal_transfer" (func $seal_transfer (param i32 i32 i32 i32) (result i32)))
+	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
+	(import "env" "memory" (memory 1 1))
+
+	;; [0, 32) zero-adress
+	(data (i32.const 0)
+		"\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"
+		"\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"
+	)
+
+	;; [32, 40) 100 balance
+	(data (i32.const 32) "\64\00\00\00\00\00\00\00")
+
+	;; [40, 44) here we store the return code of the transfer
+
+	(func (export "deploy"))
+
+	(func (export "call")
+		(i32.store
+			(i32.const 40)
+			(call $seal_transfer
+				(i32.const 0) ;; ptr to destination address
+				(i32.const 32) ;; length of destination address
+				(i32.const 32) ;; ptr to value to transfer
+				(i32.const 8) ;; length of value to transfer
+			)
+		)
+		;; exit with success and take transfer return code to the output buffer
+		(call $seal_return (i32.const 0) (i32.const 40) (i32.const 4))
+	)
+)
addedpallets/contracts/proc-macro/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/proc-macro/Cargo.toml
@@ -0,0 +1,26 @@
+[package]
+name = "pallet-contracts-proc-macro"
+version = "3.0.0"
+authors = ["Parity Technologies <admin@parity.io>"]
+edition = "2018"
+license = "Apache-2.0"
+homepage = "https://substrate.dev"
+repository = "https://github.com/paritytech/substrate/"
+description = "Procedural macros used in pallet_contracts"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[lib]
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "1"
+quote = "1"
+syn = "1"
+
+[dev-dependencies]
+
+[features]
+# If set the full output is generated. Do NOT set when generating for wasm runtime.
+full = []
addedpallets/contracts/proc-macro/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/proc-macro/src/lib.rs
@@ -0,0 +1,142 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Proc macros used in the contracts module.
+
+#![no_std]
+
+extern crate alloc;
+
+use proc_macro2::TokenStream;
+use quote::{quote, quote_spanned};
+use syn::spanned::Spanned;
+use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields, Ident};
+use alloc::string::ToString;
+
+/// This derives `Debug` for a struct where each field must be of some numeric type.
+/// It interprets each field as its represents some weight and formats it as times so that
+/// it is readable by humans.
+#[proc_macro_derive(WeightDebug)]
+pub fn derive_weight_debug(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+	derive_debug(input, format_weight)
+}
+
+/// This is basically identical to the std libs Debug derive but without adding any
+/// bounds to existing generics.
+#[proc_macro_derive(ScheduleDebug)]
+pub fn derive_schedule_debug(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+	derive_debug(input, format_default)
+}
+
+fn derive_debug(
+	input: proc_macro::TokenStream,
+	fmt: impl Fn(&Ident) -> TokenStream
+) -> proc_macro::TokenStream {
+	let input = parse_macro_input!(input as DeriveInput);
+	let name = &input.ident;
+	let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
+	let data = if let Data::Struct(data) = &input.data {
+		data
+	} else {
+		return quote_spanned! {
+			name.span() =>
+			compile_error!("WeightDebug is only supported for structs.");
+		}.into();
+	};
+
+	#[cfg(feature = "full")]
+	let fields = iterate_fields(data, fmt);
+
+	#[cfg(not(feature = "full"))]
+	let fields = {
+		drop(fmt);
+		drop(data);
+		TokenStream::new()
+	};
+
+	let tokens = quote! {
+		impl #impl_generics core::fmt::Debug for #name #ty_generics #where_clause {
+			fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+				use ::sp_runtime::{FixedPointNumber, FixedU128 as Fixed};
+				let mut formatter = formatter.debug_struct(stringify!(#name));
+				#fields
+				formatter.finish()
+			}
+		}
+	};
+
+	tokens.into()
+}
+
+/// This is only used then the `full` feature is activated.
+#[cfg(feature = "full")]
+fn iterate_fields(data: &DataStruct, fmt: impl Fn(&Ident) -> TokenStream) -> TokenStream {
+	match &data.fields {
+		Fields::Named(fields) => {
+			let recurse = fields.named
+			.iter()
+			.filter_map(|f| {
+				let name = f.ident.as_ref()?;
+				if name.to_string().starts_with('_') {
+					return None;
+				}
+				let value = fmt(name);
+				let ret = quote_spanned!{ f.span() =>
+					formatter.field(stringify!(#name), #value);
+				};
+				Some(ret)
+			});
+			quote!{
+				#( #recurse )*
+			}
+		}
+		Fields::Unnamed(fields) => quote_spanned!{
+			fields.span() =>
+			compile_error!("Unnamed fields are not supported")
+		},
+		Fields::Unit => quote!(),
+	}
+}
+
+fn format_weight(field: &Ident) -> TokenStream {
+	quote_spanned! { field.span() =>
+		&if self.#field > 1_000_000_000 {
+			format!(
+				"{:.1?} ms",
+				Fixed::saturating_from_rational(self.#field, 1_000_000_000).to_float()
+			)
+		} else if self.#field > 1_000_000 {
+			format!(
+				"{:.1?} µs",
+				Fixed::saturating_from_rational(self.#field, 1_000_000).to_float()
+			)
+		} else if self.#field > 1_000 {
+			format!(
+				"{:.1?} ns",
+				Fixed::saturating_from_rational(self.#field, 1_000).to_float()
+			)
+		} else {
+			format!("{} ps", self.#field)
+		}
+	}
+}
+
+fn format_default(field: &Ident) -> TokenStream {
+	quote_spanned! { field.span() =>
+		&self.#field
+	}
+}
addedpallets/contracts/rpc/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/rpc/Cargo.toml
@@ -0,0 +1,32 @@
+[package]
+name = "pallet-contracts-rpc"
+version = "3.0.0"
+authors = ["Parity Technologies <admin@parity.io>"]
+edition = "2018"
+license = "Apache-2.0"
+homepage = "https://substrate.dev"
+repository = "https://github.com/paritytech/substrate/"
+description = "Node-specific RPC methods for interaction with contracts."
+readme = "README.md"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[dependencies]
+codec = { package = "parity-scale-codec", version = "2" }
+jsonrpc-core = "15"
+jsonrpc-core-client = "15"
+jsonrpc-derive = "15"
+serde = { version = "1", features = ["derive"] }
+
+# Substrate Dependencies
+pallet-contracts-primitives = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+pallet-contracts-rpc-runtime-api = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-api = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-blockchain = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-core = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-rpc = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-runtime = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+
+[dev-dependencies]
+serde_json = "1"
addedpallets/contracts/rpc/README.mddiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/rpc/README.md
@@ -0,0 +1,3 @@
+Node-specific RPC methods for interaction with contracts.
+
+License: Apache-2.0
\ No newline at end of file
addedpallets/contracts/rpc/runtime-api/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/rpc/runtime-api/Cargo.toml
@@ -0,0 +1,32 @@
+[package]
+name = "pallet-contracts-rpc-runtime-api"
+version = "3.0.0"
+authors = ["Parity Technologies <admin@parity.io>"]
+edition = "2018"
+license = "Apache-2.0"
+homepage = "https://substrate.dev"
+repository = "https://github.com/paritytech/substrate/"
+description = "Runtime API definition required by Contracts RPC extensions."
+readme = "README.md"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[dependencies]
+codec = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
+
+# Substrate Dependencies
+pallet-contracts-primitives = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-api = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-runtime = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+sp-std = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.3' }
+
+[features]
+default = ["std"]
+std = [
+	"sp-api/std",
+	"codec/std",
+	"sp-std/std",
+	"sp-runtime/std",
+	"pallet-contracts-primitives/std",
+]
addedpallets/contracts/rpc/runtime-api/README.mddiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/rpc/runtime-api/README.md
@@ -0,0 +1,7 @@
+Runtime API definition required by Contracts RPC extensions.
+
+This API should be imported and implemented by the runtime,
+of a node that wants to use the custom RPC extension
+adding Contracts access methods.
+
+License: Apache-2.0
\ No newline at end of file
addedpallets/contracts/rpc/runtime-api/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/rpc/runtime-api/src/lib.rs
@@ -0,0 +1,82 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Runtime API definition required by Contracts RPC extensions.
+//!
+//! This API should be imported and implemented by the runtime,
+//! of a node that wants to use the custom RPC extension
+//! adding Contracts access methods.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+use codec::Codec;
+use sp_std::vec::Vec;
+use pallet_contracts_primitives::{
+	ContractExecResult, GetStorageResult, RentProjectionResult, Code, ContractInstantiateResult,
+};
+
+sp_api::decl_runtime_apis! {
+	/// The API to interact with contracts without using executive.
+	pub trait ContractsApi<AccountId, Balance, BlockNumber, Hash> where
+		AccountId: Codec,
+		Balance: Codec,
+		BlockNumber: Codec,
+		Hash: Codec,
+	{
+		/// Perform a call from a specified account to a given contract.
+		///
+		/// See [`pallet_contracts::Pallet::call`].
+		fn call(
+			origin: AccountId,
+			dest: AccountId,
+			value: Balance,
+			gas_limit: u64,
+			input_data: Vec<u8>,
+		) -> ContractExecResult;
+
+		/// Instantiate a new contract.
+		///
+		/// See [`pallet_contracts::Pallet::instantiate`].
+		fn instantiate(
+			origin: AccountId,
+			endowment: Balance,
+			gas_limit: u64,
+			code: Code<Hash>,
+			data: Vec<u8>,
+			salt: Vec<u8>,
+		) -> ContractInstantiateResult<AccountId, BlockNumber>;
+
+		/// Query a given storage key in a given contract.
+		///
+		/// Returns `Ok(Some(Vec<u8>))` if the storage value exists under the given key in the
+		/// specified account and `Ok(None)` if it doesn't. If the account specified by the address
+		/// doesn't exist, or doesn't have a contract or if the contract is a tombstone, then `Err`
+		/// is returned.
+		fn get_storage(
+			address: AccountId,
+			key: [u8; 32],
+		) -> GetStorageResult;
+
+		/// Returns the projected time a given contract will be able to sustain paying its rent.
+		///
+		/// The returned projection is relevant for the current block, i.e. it is as if the contract
+		/// was accessed at the current block.
+		///
+		/// Returns `Err` if the contract is in a tombstone state or doesn't exist.
+		fn rent_projection(address: AccountId) -> RentProjectionResult<BlockNumber>;
+	}
+}
addedpallets/contracts/rpc/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/rpc/src/lib.rs
@@ -0,0 +1,434 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Node-specific RPC methods for interaction with contracts.
+
+use std::sync::Arc;
+
+use codec::Codec;
+use jsonrpc_core::{Error, ErrorCode, Result};
+use jsonrpc_derive::rpc;
+use pallet_contracts_primitives::RentProjection;
+use serde::{Deserialize, Serialize};
+use sp_api::ProvideRuntimeApi;
+use sp_blockchain::HeaderBackend;
+use sp_core::{Bytes, H256};
+use sp_rpc::number::NumberOrHex;
+use sp_runtime::{
+	generic::BlockId,
+	traits::{Block as BlockT, Header as HeaderT},
+};
+use std::convert::{TryFrom, TryInto};
+use pallet_contracts_primitives::{Code, ContractExecResult, ContractInstantiateResult};
+
+pub use pallet_contracts_rpc_runtime_api::ContractsApi as ContractsRuntimeApi;
+
+const RUNTIME_ERROR: i64 = 1;
+const CONTRACT_DOESNT_EXIST: i64 = 2;
+const CONTRACT_IS_A_TOMBSTONE: i64 = 3;
+
+pub type Weight = u64;
+
+/// A rough estimate of how much gas a decent hardware consumes per second,
+/// using native execution.
+/// This value is used to set the upper bound for maximal contract calls to
+/// prevent blocking the RPC for too long.
+///
+/// As 1 gas is equal to 1 weight we base this on the conducted benchmarks which
+/// determined runtime weights:
+/// https://github.com/paritytech/substrate/pull/5446
+const GAS_PER_SECOND: Weight = 1_000_000_000_000;
+
+/// The maximum amount of weight that the call and instantiate rpcs are allowed to consume.
+/// This puts a ceiling on the weight limit that is supplied to the rpc as an argument.
+const GAS_LIMIT: Weight = 5 * GAS_PER_SECOND;
+
+/// A private newtype for converting `ContractAccessError` into an RPC error.
+struct ContractAccessError(pallet_contracts_primitives::ContractAccessError);
+impl From<ContractAccessError> for Error {
+	fn from(e: ContractAccessError) -> Error {
+		use pallet_contracts_primitives::ContractAccessError::*;
+		match e.0 {
+			DoesntExist => Error {
+				code: ErrorCode::ServerError(CONTRACT_DOESNT_EXIST),
+				message: "The specified contract doesn't exist.".into(),
+				data: None,
+			},
+			IsTombstone => Error {
+				code: ErrorCode::ServerError(CONTRACT_IS_A_TOMBSTONE),
+				message: "The contract is a tombstone and doesn't have any storage.".into(),
+				data: None,
+			},
+		}
+	}
+}
+
+/// A struct that encodes RPC parameters required for a call to a smart-contract.
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(deny_unknown_fields)]
+pub struct CallRequest<AccountId> {
+	origin: AccountId,
+	dest: AccountId,
+	value: NumberOrHex,
+	gas_limit: NumberOrHex,
+	input_data: Bytes,
+}
+
+/// A struct that encodes RPC parameters required to instantiate a new smart-contract.
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(deny_unknown_fields)]
+pub struct InstantiateRequest<AccountId, Hash> {
+	origin: AccountId,
+	endowment: NumberOrHex,
+	gas_limit: NumberOrHex,
+	code: Code<Hash>,
+	data: Bytes,
+	salt: Bytes,
+}
+
+/// Contracts RPC methods.
+#[rpc]
+pub trait ContractsApi<BlockHash, BlockNumber, AccountId, Balance, Hash> {
+	/// Executes a call to a contract.
+	///
+	/// This call is performed locally without submitting any transactions. Thus executing this
+	/// won't change any state. Nonetheless, the calling state-changing contracts is still possible.
+	///
+	/// This method is useful for calling getter-like methods on contracts.
+	#[rpc(name = "contracts_call")]
+	fn call(
+		&self,
+		call_request: CallRequest<AccountId>,
+		at: Option<BlockHash>,
+	) -> Result<ContractExecResult>;
+
+	/// Instantiate a new contract.
+	///
+	/// This call is performed locally without submitting any transactions. Thus the contract
+	/// is not actually created.
+	///
+	/// This method is useful for UIs to dry-run contract instantiations.
+	#[rpc(name = "contracts_instantiate")]
+	fn instantiate(
+		&self,
+		instantiate_request: InstantiateRequest<AccountId, Hash>,
+		at: Option<BlockHash>,
+	) -> Result<ContractInstantiateResult<AccountId, BlockNumber>>;
+
+	/// Returns the value under a specified storage `key` in a contract given by `address` param,
+	/// or `None` if it is not set.
+	#[rpc(name = "contracts_getStorage")]
+	fn get_storage(
+		&self,
+		address: AccountId,
+		key: H256,
+		at: Option<BlockHash>,
+	) -> Result<Option<Bytes>>;
+
+	/// Returns the projected time a given contract will be able to sustain paying its rent.
+	///
+	/// The returned projection is relevant for the given block, i.e. it is as if the contract was
+	/// accessed at the beginning of that block.
+	///
+	/// Returns `None` if the contract is exempted from rent.
+	#[rpc(name = "contracts_rentProjection")]
+	fn rent_projection(
+		&self,
+		address: AccountId,
+		at: Option<BlockHash>,
+	) -> Result<Option<BlockNumber>>;
+}
+
+/// An implementation of contract specific RPC methods.
+pub struct Contracts<C, B> {
+	client: Arc<C>,
+	_marker: std::marker::PhantomData<B>,
+}
+
+impl<C, B> Contracts<C, B> {
+	/// Create new `Contracts` with the given reference to the client.
+	pub fn new(client: Arc<C>) -> Self {
+		Contracts {
+			client,
+			_marker: Default::default(),
+		}
+	}
+}
+impl<C, Block, AccountId, Balance, Hash>
+	ContractsApi<
+		<Block as BlockT>::Hash,
+		<<Block as BlockT>::Header as HeaderT>::Number,
+		AccountId,
+		Balance,
+		Hash,
+	> for Contracts<C, Block>
+where
+	Block: BlockT,
+	C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
+	C::Api: ContractsRuntimeApi<
+		Block,
+		AccountId,
+		Balance,
+		<<Block as BlockT>::Header as HeaderT>::Number,
+		Hash,
+	>,
+	AccountId: Codec,
+	Balance: Codec + TryFrom<NumberOrHex>,
+	Hash: Codec,
+{
+	fn call(
+		&self,
+		call_request: CallRequest<AccountId>,
+		at: Option<<Block as BlockT>::Hash>,
+	) -> Result<ContractExecResult> {
+		let api = self.client.runtime_api();
+		let at = BlockId::hash(at.unwrap_or_else(||
+			// If the block hash is not supplied assume the best block.
+			self.client.info().best_hash));
+
+		let CallRequest {
+			origin,
+			dest,
+			value,
+			gas_limit,
+			input_data,
+		} = call_request;
+
+		let value: Balance = decode_hex(value, "balance")?;
+		let gas_limit: Weight = decode_hex(gas_limit, "weight")?;
+		limit_gas(gas_limit)?;
+
+		let exec_result = api
+			.call(&at, origin, dest, value, gas_limit, input_data.to_vec())
+			.map_err(runtime_error_into_rpc_err)?;
+
+		Ok(exec_result)
+	}
+
+	fn instantiate(
+		&self,
+		instantiate_request: InstantiateRequest<AccountId, Hash>,
+		at: Option<<Block as BlockT>::Hash>,
+	) -> Result<ContractInstantiateResult<AccountId, <<Block as BlockT>::Header as HeaderT>::Number>> {
+		let api = self.client.runtime_api();
+		let at = BlockId::hash(at.unwrap_or_else(||
+			// If the block hash is not supplied assume the best block.
+			self.client.info().best_hash));
+
+		let InstantiateRequest {
+			origin,
+			endowment,
+			gas_limit,
+			code,
+			data,
+			salt,
+		} = instantiate_request;
+
+		let endowment: Balance = decode_hex(endowment, "balance")?;
+		let gas_limit: Weight = decode_hex(gas_limit, "weight")?;
+		limit_gas(gas_limit)?;
+
+		let exec_result = api
+			.instantiate(&at, origin, endowment, gas_limit, code, data.to_vec(), salt.to_vec())
+			.map_err(runtime_error_into_rpc_err)?;
+
+		Ok(exec_result)
+	}
+
+	fn get_storage(
+		&self,
+		address: AccountId,
+		key: H256,
+		at: Option<<Block as BlockT>::Hash>,
+	) -> Result<Option<Bytes>> {
+		let api = self.client.runtime_api();
+		let at = BlockId::hash(at.unwrap_or_else(||
+			// If the block hash is not supplied assume the best block.
+			self.client.info().best_hash));
+
+		let result = api
+			.get_storage(&at, address, key.into())
+			.map_err(runtime_error_into_rpc_err)?
+			.map_err(ContractAccessError)?
+			.map(Bytes);
+
+		Ok(result)
+	}
+
+	fn rent_projection(
+		&self,
+		address: AccountId,
+		at: Option<<Block as BlockT>::Hash>,
+	) -> Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>> {
+		let api = self.client.runtime_api();
+		let at = BlockId::hash(at.unwrap_or_else(||
+			// If the block hash is not supplied assume the best block.
+			self.client.info().best_hash));
+
+		let result = api
+			.rent_projection(&at, address)
+			.map_err(runtime_error_into_rpc_err)?
+			.map_err(ContractAccessError)?;
+
+		Ok(match result {
+			RentProjection::NoEviction => None,
+			RentProjection::EvictionAt(block_num) => Some(block_num),
+		})
+	}
+}
+
+/// Converts a runtime trap into an RPC error.
+fn runtime_error_into_rpc_err(err: impl std::fmt::Debug) -> Error {
+	Error {
+		code: ErrorCode::ServerError(RUNTIME_ERROR),
+		message: "Runtime error".into(),
+		data: Some(format!("{:?}", err).into()),
+	}
+}
+
+fn decode_hex<H: std::fmt::Debug + Copy, T: TryFrom<H>>(from: H, name: &str) -> Result<T> {
+	from.try_into().map_err(|_| Error {
+		code: ErrorCode::InvalidParams,
+		message: format!("{:?} does not fit into the {} type", from, name),
+		data: None,
+	})
+}
+
+fn limit_gas(gas_limit: Weight) -> Result<()> {
+	if gas_limit > GAS_LIMIT {
+		Err(Error {
+			code: ErrorCode::InvalidParams,
+			message: format!(
+				"Requested gas limit is greater than maximum allowed: {} > {}",
+				gas_limit, GAS_LIMIT
+			),
+			data: None,
+		})
+	} else {
+		Ok(())
+	}
+}
+
+#[cfg(test)]
+mod tests {
+	use super::*;
+	use sp_core::U256;
+
+	fn trim(json: &str) -> String {
+		json.chars().filter(|c| !c.is_whitespace()).collect()
+	}
+
+	#[test]
+	fn call_request_should_serialize_deserialize_properly() {
+		type Req = CallRequest<String>;
+		let req: Req = serde_json::from_str(r#"
+		{
+			"origin": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL",
+			"dest": "5DRakbLVnjVrW6niwLfHGW24EeCEvDAFGEXrtaYS5M4ynoom",
+			"value": "0x112210f4B16c1cb1",
+			"gasLimit": 1000000000000,
+			"inputData": "0x8c97db39"
+		}
+		"#).unwrap();
+		assert_eq!(req.gas_limit.into_u256(), U256::from(0xe8d4a51000u64));
+		assert_eq!(req.value.into_u256(), U256::from(1234567890987654321u128));
+	}
+
+	#[test]
+	fn instantiate_request_should_serialize_deserialize_properly() {
+		type Req = InstantiateRequest<String, String>;
+		let req: Req = serde_json::from_str(r#"
+		{
+			"origin": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL",
+			"endowment": "0x88",
+			"gasLimit": 42,
+			"code": { "existing": "0x1122" },
+			"data": "0x4299",
+			"salt": "0x9988"
+		}
+		"#).unwrap();
+
+		assert_eq!(req.origin, "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL");
+		assert_eq!(req.endowment.into_u256(), 0x88.into());
+		assert_eq!(req.gas_limit.into_u256(), 42.into());
+		assert_eq!(&*req.data, [0x42, 0x99].as_ref());
+		assert_eq!(&*req.salt, [0x99, 0x88].as_ref());
+		let code = match req.code {
+			Code::Existing(hash) => hash,
+			_ => panic!("json encoded an existing hash"),
+		};
+		assert_eq!(&code, "0x1122");
+	}
+
+	#[test]
+	fn call_result_should_serialize_deserialize_properly() {
+		fn test(expected: &str) {
+			let res: ContractExecResult = serde_json::from_str(expected).unwrap();
+			let actual = serde_json::to_string(&res).unwrap();
+			assert_eq!(actual, trim(expected).as_str());
+		}
+		test(r#"{
+			"gasConsumed": 5000,
+			"debugMessage": "0x68656c704f6b",
+			"result": {
+			  "Ok": {
+				"flags": 5,
+				"data": "0x1234"
+			  }
+			}
+		}"#);
+		test(r#"{
+			"gasConsumed": 3400,
+			"debugMessage": "0x68656c70457272",
+			"result": {
+			  "Err": "BadOrigin"
+			}
+		}"#);
+	}
+
+	#[test]
+	fn instantiate_result_should_serialize_deserialize_properly() {
+		fn test(expected: &str) {
+			let res: ContractInstantiateResult<String, u64> = serde_json::from_str(expected).unwrap();
+			let actual = serde_json::to_string(&res).unwrap();
+			assert_eq!(actual, trim(expected).as_str());
+		}
+		test(r#"{
+			"gasConsumed": 5000,
+			"debugMessage": "0x68656c704f6b",
+			"result": {
+			   "Ok": {
+				  "result": {
+					 "flags": 5,
+					 "data": "0x1234"
+				  },
+				  "accountId": "5CiPP",
+				  "rentProjection": null
+			   }
+			}
+		}"#);
+		test(r#"{
+			"gasConsumed": 3400,
+			"debugMessage": "0x68656c70457272",
+			"result": {
+			  "Err": "BadOrigin"
+			}
+		}"#);
+	}
+}
addedpallets/contracts/src/benchmarking/code.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/benchmarking/code.rs
@@ -0,0 +1,526 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Functions to procedurally construct contract code used for benchmarking.
+//!
+//! In order to be able to benchmark events that are triggered by contract execution
+//! (API calls into seal, individual instructions), we need to generate contracts that
+//! perform those events. Because those contracts can get very big we cannot simply define
+//! them as text (.wat) as this will be too slow and consume too much memory. Therefore
+//! we define this simple definition of a contract that can be passed to `create_code` that
+//! compiles it down into a `WasmModule` that can be used as a contract's code.
+
+use crate::{Config, CurrentSchedule};
+use parity_wasm::elements::{
+	Instruction, Instructions, FuncBody, ValueType, BlockType, Section, CustomSection,
+};
+use pwasm_utils::stack_height::inject_limiter;
+use sp_core::crypto::UncheckedFrom;
+use sp_runtime::traits::Hash;
+use sp_sandbox::{EnvironmentDefinitionBuilder, Memory};
+use sp_std::{prelude::*, convert::TryFrom, borrow::ToOwned};
+
+/// Pass to `create_code` in order to create a compiled `WasmModule`.
+///
+/// This exists to have a more declarative way to describe a wasm module than to use
+/// parity-wasm directly. It is tailored to fit the structure of contracts that are
+/// needed for benchmarking.
+#[derive(Default)]
+pub struct ModuleDefinition {
+	/// Imported memory attached to the module. No memory is imported if `None`.
+	pub memory: Option<ImportedMemory>,
+	/// Initializers for the imported memory.
+	pub data_segments: Vec<DataSegment>,
+	/// Creates the supplied amount of i64 mutable globals initialized with random values.
+	pub num_globals: u32,
+	/// List of functions that the module should import. They start with index 0.
+	pub imported_functions: Vec<ImportedFunction>,
+	/// Function body of the exported `deploy` function. Body is empty if `None`.
+	/// Its index is `imported_functions.len()`.
+	pub deploy_body: Option<FuncBody>,
+	/// Function body of the exported `call` function. Body is empty if `None`.
+	/// Its index is `imported_functions.len() + 1`.
+	pub call_body: Option<FuncBody>,
+	/// Function body of a non-exported function with index `imported_functions.len() + 2`.
+	pub aux_body: Option<FuncBody>,
+	/// The amount of I64 arguments the aux function should have.
+	pub aux_arg_num: u32,
+	/// If set to true the stack height limiter is injected into the the module. This is
+	/// needed for instruction debugging because the cost of executing the stack height
+	/// instrumentation should be included in the costs for the individual instructions
+	/// that cause more metering code (only call).
+	pub inject_stack_metering: bool,
+	/// Create a table containing function pointers.
+	pub table: Option<TableSegment>,
+	/// Create a section named "dummy" of the specified size. This is useful in order to
+	/// benchmark the overhead of loading and storing codes of specified sizes. The dummy
+	/// section only contributes to the size of the contract but does not affect execution.
+	pub dummy_section: u32,
+}
+
+pub struct TableSegment {
+	/// How many elements should be created inside the table.
+	pub num_elements: u32,
+	/// The function index with which all table elements should be initialized.
+	pub function_index: u32,
+}
+
+pub struct DataSegment {
+	pub offset: u32,
+	pub value: Vec<u8>,
+}
+
+#[derive(Clone)]
+pub struct ImportedMemory {
+	pub min_pages: u32,
+	pub max_pages: u32,
+}
+
+impl ImportedMemory {
+	pub fn max<T: Config>() -> Self
+	where
+		T: Config,
+		T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+	{
+		let pages = max_pages::<T>();
+		Self {
+			min_pages: pages,
+			max_pages: pages,
+		}
+	}
+}
+
+pub struct ImportedFunction {
+	pub name: &'static str,
+	pub params: Vec<ValueType>,
+	pub return_type: Option<ValueType>,
+}
+
+/// A wasm module ready to be put on chain.
+#[derive(Clone)]
+pub struct WasmModule<T: Config> {
+	pub code: Vec<u8>,
+	pub hash: <T::Hashing as Hash>::Output,
+	memory: Option<ImportedMemory>,
+}
+
+impl<T: Config> From<ModuleDefinition> for WasmModule<T>
+where
+	T: Config,
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+{
+	fn from(def: ModuleDefinition) -> Self {
+		// internal functions start at that offset.
+		let func_offset = u32::try_from(def.imported_functions.len()).unwrap();
+
+		// Every contract must export "deploy" and "call" functions
+		let mut contract = parity_wasm::builder::module()
+			// deploy function (first internal function)
+			.function()
+			.signature()
+			.build()
+			.with_body(
+				def.deploy_body
+					.unwrap_or_else(|| FuncBody::new(Vec::new(), Instructions::empty())),
+			)
+			.build()
+			// call function (second internal function)
+			.function()
+			.signature()
+			.build()
+			.with_body(
+				def.call_body
+					.unwrap_or_else(|| FuncBody::new(Vec::new(), Instructions::empty())),
+			)
+			.build()
+			.export()
+			.field("deploy")
+			.internal()
+			.func(func_offset)
+			.build()
+			.export()
+			.field("call")
+			.internal()
+			.func(func_offset + 1)
+			.build();
+
+		// If specified we add an additional internal function
+		if let Some(body) = def.aux_body {
+			let mut signature = contract.function().signature();
+			for _ in 0..def.aux_arg_num {
+				signature = signature.with_param(ValueType::I64);
+			}
+			contract = signature.build().with_body(body).build();
+		}
+
+		// Grant access to linear memory.
+		if let Some(memory) = &def.memory {
+			contract = contract
+				.import()
+				.module("env")
+				.field("memory")
+				.external()
+				.memory(memory.min_pages, Some(memory.max_pages))
+				.build();
+		}
+
+		// Import supervisor functions. They start with idx 0.
+		for func in def.imported_functions {
+			let sig = parity_wasm::builder::signature()
+				.with_params(func.params)
+				.with_results(func.return_type.into_iter().collect())
+				.build_sig();
+			let sig = contract.push_signature(sig);
+			contract = contract
+				.import()
+				.module("seal0")
+				.field(func.name)
+				.with_external(parity_wasm::elements::External::Function(sig))
+				.build();
+		}
+
+		// Initialize memory
+		for data in def.data_segments {
+			contract = contract
+				.data()
+				.offset(Instruction::I32Const(data.offset as i32))
+				.value(data.value)
+				.build()
+		}
+
+		// Add global variables
+		if def.num_globals > 0 {
+			use rand::{prelude::*, distributions::Standard};
+			let rng = rand_pcg::Pcg32::seed_from_u64(3112244599778833558);
+			for val in rng.sample_iter(Standard).take(def.num_globals as usize) {
+				contract = contract
+					.global()
+					.value_type()
+					.i64()
+					.mutable()
+					.init_expr(Instruction::I64Const(val))
+					.build()
+			}
+		}
+
+		// Add function pointer table
+		if let Some(table) = def.table {
+			contract = contract
+				.table()
+				.with_min(table.num_elements)
+				.with_max(Some(table.num_elements))
+				.with_element(0, vec![table.function_index; table.num_elements as usize])
+				.build();
+		}
+
+		// Add the dummy section
+		if def.dummy_section > 0 {
+			contract = contract.with_section(Section::Custom(CustomSection::new(
+				"dummy".to_owned(),
+				vec![42; def.dummy_section as usize],
+			)));
+		}
+
+		let mut code = contract.build();
+
+		// Inject stack height metering
+		if def.inject_stack_metering {
+			code = inject_limiter(code, <CurrentSchedule<T>>::get().limits.stack_height).unwrap();
+		}
+
+		let code = code.to_bytes().unwrap();
+		let hash = T::Hashing::hash(&code);
+		Self {
+			code,
+			hash,
+			memory: def.memory,
+		}
+	}
+}
+
+impl<T: Config> WasmModule<T>
+where
+	T: Config,
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+{
+	/// Creates a wasm module with an empty `call` and `deploy` function and nothing else.
+	pub fn dummy() -> Self {
+		ModuleDefinition::default().into()
+	}
+
+	/// Same as `dummy` but with maximum sized linear memory and a dummy section of specified size.
+	pub fn dummy_with_bytes(dummy_bytes: u32) -> Self {
+		ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			dummy_section: dummy_bytes,
+			..Default::default()
+		}
+		.into()
+	}
+
+	/// Creates a wasm module of `target_bytes` size. Used to benchmark the performance of
+	/// `instantiate_with_code` for different sizes of wasm modules. The generated module maximizes
+	/// instrumentation runtime by nesting blocks as deeply as possible given the byte budget.
+	pub fn sized(target_bytes: u32) -> Self {
+		use parity_wasm::elements::Instruction::{If, I32Const, Return, End};
+		// Base size of a contract is 63 bytes and each expansion adds 6 bytes.
+		// We do one expansion less to account for the code section and function body
+		// size fields inside the binary wasm module representation which are leb128 encoded
+		// and therefore grow in size when the contract grows. We are not allowed to overshoot
+		// because of the maximum code size that is enforced by `instantiate_with_code`.
+		let expansions = (target_bytes.saturating_sub(63) / 6).saturating_sub(1);
+		const EXPANSION: [Instruction; 4] = [I32Const(0), If(BlockType::NoResult), Return, End];
+		ModuleDefinition {
+			call_body: Some(body::repeated(expansions, &EXPANSION)),
+			memory: Some(ImportedMemory::max::<T>()),
+			..Default::default()
+		}
+		.into()
+	}
+
+	/// Creates a wasm module that calls the imported function named `getter_name` `repeat`
+	/// times. The imported function is expected to have the "getter signature" of
+	/// (out_ptr: u32, len_ptr: u32) -> ().
+	pub fn getter(getter_name: &'static str, repeat: u32) -> Self {
+		let pages = max_pages::<T>();
+		ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: getter_name,
+				params: vec![ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			// Write the output buffer size. The output size will be overwritten by the
+			// supervisor with the real size when calling the getter. Since this size does not
+			// change between calls it suffices to start with an initial value and then just
+			// leave as whatever value was written there.
+			data_segments: vec![DataSegment {
+				offset: 0,
+				value: (pages * 64 * 1024 - 4).to_le_bytes().to_vec(),
+			}],
+			call_body: Some(body::repeated(
+				repeat,
+				&[
+					Instruction::I32Const(4), // ptr where to store output
+					Instruction::I32Const(0), // ptr to length
+					Instruction::Call(0),     // call the imported function
+				],
+			)),
+			..Default::default()
+		}
+		.into()
+	}
+
+	/// Creates a wasm module that calls the imported hash function named `name` `repeat` times
+	/// with an input of size `data_size`. Hash functions have the signature
+	/// (input_ptr: u32, input_len: u32, output_ptr: u32) -> ()
+	pub fn hasher(name: &'static str, repeat: u32, data_size: u32) -> Self {
+		ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name,
+				params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			call_body: Some(body::repeated(
+				repeat,
+				&[
+					Instruction::I32Const(0),                // input_ptr
+					Instruction::I32Const(data_size as i32), // input_len
+					Instruction::I32Const(0),                // output_ptr
+					Instruction::Call(0),
+				],
+			)),
+			..Default::default()
+		}
+		.into()
+	}
+
+	/// Creates a memory instance for use in a sandbox with dimensions declared in this module
+	/// and adds it to `env`. A reference to that memory is returned so that it can be used to
+	/// access the memory contents from the supervisor.
+	pub fn add_memory<S>(&self, env: &mut EnvironmentDefinitionBuilder<S>) -> Option<Memory> {
+		let memory = if let Some(memory) = &self.memory {
+			memory
+		} else {
+			return None;
+		};
+		let memory = Memory::new(memory.min_pages, Some(memory.max_pages)).unwrap();
+		env.add_memory("env", "memory", memory.clone());
+		Some(memory)
+	}
+
+	pub fn unary_instr(instr: Instruction, repeat: u32) -> Self {
+		use body::DynInstr::{RandomI64Repeated, Regular};
+		ModuleDefinition {
+			call_body: Some(body::repeated_dyn(
+				repeat,
+				vec![
+					RandomI64Repeated(1),
+					Regular(instr),
+					Regular(Instruction::Drop),
+				],
+			)),
+			..Default::default()
+		}
+		.into()
+	}
+
+	pub fn binary_instr(instr: Instruction, repeat: u32) -> Self {
+		use body::DynInstr::{RandomI64Repeated, Regular};
+		ModuleDefinition {
+			call_body: Some(body::repeated_dyn(
+				repeat,
+				vec![
+					RandomI64Repeated(2),
+					Regular(instr),
+					Regular(Instruction::Drop),
+				],
+			)),
+			..Default::default()
+		}
+		.into()
+	}
+}
+
+/// Mechanisms to generate a function body that can be used inside a `ModuleDefinition`.
+pub mod body {
+	use super::*;
+
+	/// When generating contract code by repeating a wasm sequence, it's sometimes necessary
+	/// to change those instructions on each repetition. The variants of this enum describe
+	/// various ways in which this can happen.
+	pub enum DynInstr {
+		/// Insert the associated instruction.
+		Regular(Instruction),
+		/// Insert a I32Const with incrementing value for each insertion.
+		/// (start_at, increment_by)
+		Counter(u32, u32),
+		/// Insert a I32Const with a random value in [low, high) not divisible by two.
+		/// (low, high)
+		RandomUnaligned(u32, u32),
+		/// Insert a I32Const with a random value in [low, high).
+		/// (low, high)
+		RandomI32(i32, i32),
+		/// Insert the specified amount of I32Const with a random value.
+		RandomI32Repeated(usize),
+		/// Insert the specified amount of I64Const with a random value.
+		RandomI64Repeated(usize),
+		/// Insert a GetLocal with a random offset in [low, high).
+		/// (low, high)
+		RandomGetLocal(u32, u32),
+		/// Insert a SetLocal with a random offset in [low, high).
+		/// (low, high)
+		RandomSetLocal(u32, u32),
+		/// Insert a TeeLocal with a random offset in [low, high).
+		/// (low, high)
+		RandomTeeLocal(u32, u32),
+		/// Insert a GetGlobal with a random offset in [low, high).
+		/// (low, high)
+		RandomGetGlobal(u32, u32),
+		/// Insert a SetGlobal with a random offset in [low, high).
+		/// (low, high)
+		RandomSetGlobal(u32, u32),
+	}
+
+	pub fn plain(instructions: Vec<Instruction>) -> FuncBody {
+		FuncBody::new(Vec::new(), Instructions::new(instructions))
+	}
+
+	pub fn repeated(repetitions: u32, instructions: &[Instruction]) -> FuncBody {
+		let instructions = Instructions::new(
+			instructions
+				.iter()
+				.cycle()
+				.take(instructions.len() * usize::try_from(repetitions).unwrap())
+				.cloned()
+				.chain(sp_std::iter::once(Instruction::End))
+				.collect(),
+		);
+		FuncBody::new(Vec::new(), instructions)
+	}
+
+	pub fn repeated_dyn(repetitions: u32, mut instructions: Vec<DynInstr>) -> FuncBody {
+		use rand::{prelude::*, distributions::Standard};
+
+		// We do not need to be secure here.
+		let mut rng = rand_pcg::Pcg32::seed_from_u64(8446744073709551615);
+
+		// We need to iterate over indices because we cannot cycle over mutable references
+		let body = (0..instructions.len())
+			.cycle()
+			.take(instructions.len() * usize::try_from(repetitions).unwrap())
+			.flat_map(|idx| match &mut instructions[idx] {
+				DynInstr::Regular(instruction) => vec![instruction.clone()],
+				DynInstr::Counter(offset, increment_by) => {
+					let current = *offset;
+					*offset += *increment_by;
+					vec![Instruction::I32Const(current as i32)]
+				}
+				DynInstr::RandomUnaligned(low, high) => {
+					let unaligned = rng.gen_range(*low..*high) | 1;
+					vec![Instruction::I32Const(unaligned as i32)]
+				}
+				DynInstr::RandomI32(low, high) => {
+					vec![Instruction::I32Const(rng.gen_range(*low..*high))]
+				}
+				DynInstr::RandomI32Repeated(num) => (&mut rng)
+					.sample_iter(Standard)
+					.take(*num)
+					.map(|val| Instruction::I32Const(val))
+					.collect(),
+				DynInstr::RandomI64Repeated(num) => (&mut rng)
+					.sample_iter(Standard)
+					.take(*num)
+					.map(|val| Instruction::I64Const(val))
+					.collect(),
+				DynInstr::RandomGetLocal(low, high) => {
+					vec![Instruction::GetLocal(rng.gen_range(*low..*high))]
+				}
+				DynInstr::RandomSetLocal(low, high) => {
+					vec![Instruction::SetLocal(rng.gen_range(*low..*high))]
+				}
+				DynInstr::RandomTeeLocal(low, high) => {
+					vec![Instruction::TeeLocal(rng.gen_range(*low..*high))]
+				}
+				DynInstr::RandomGetGlobal(low, high) => {
+					vec![Instruction::GetGlobal(rng.gen_range(*low..*high))]
+				}
+				DynInstr::RandomSetGlobal(low, high) => {
+					vec![Instruction::SetGlobal(rng.gen_range(*low..*high))]
+				}
+			})
+			.chain(sp_std::iter::once(Instruction::End))
+			.collect();
+		FuncBody::new(Vec::new(), Instructions::new(body))
+	}
+
+	/// Replace the locals of the supplied `body` with `num` i64 locals.
+	pub fn inject_locals(body: &mut FuncBody, num: u32) {
+		use parity_wasm::elements::Local;
+		*body.locals_mut() = (0..num).map(|i| Local::new(i, ValueType::I64)).collect()
+	}
+}
+
+/// The maximum amount of pages any contract is allowed to have according to the current `Schedule`.
+pub fn max_pages<T: Config>() -> u32
+where
+	T: Config,
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+{
+	<CurrentSchedule<T>>::get().limits.memory_pages
+}
addedpallets/contracts/src/benchmarking/mod.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/benchmarking/mod.rs
@@ -0,0 +1,2537 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Benchmarks for the contracts pallet
+
+#![cfg(feature = "runtime-benchmarks")]
+
+mod code;
+mod sandbox;
+
+use crate::{
+	*, Pallet as Contracts,
+	exec::StorageKey,
+	rent::Rent,
+	schedule::{API_BENCHMARK_BATCH_SIZE, INSTR_BENCHMARK_BATCH_SIZE},
+	storage::Storage,
+};
+use self::{
+	code::{
+		body::{self, DynInstr::*},
+		ModuleDefinition, DataSegment, ImportedMemory, ImportedFunction, WasmModule,
+	},
+	sandbox::Sandbox,
+};
+use codec::Encode;
+use frame_benchmarking::{benchmarks, account, whitelisted_caller, impl_benchmark_test_suite};
+use frame_system::{Pallet as System, RawOrigin};
+use parity_wasm::elements::{Instruction, ValueType, BlockType};
+use sp_runtime::traits::{Hash, Bounded, Zero};
+use sp_std::{
+	default::Default,
+	convert::{TryInto},
+	vec::Vec,
+	vec,
+};
+use pallet_contracts_primitives::RentProjection;
+use frame_support::weights::Weight;
+
+/// How many batches we do per API benchmark.
+const API_BENCHMARK_BATCHES: u32 = 20;
+
+/// How many batches we do per Instruction benchmark.
+const INSTR_BENCHMARK_BATCHES: u32 = 1;
+
+/// An instantiated and deployed contract.
+struct Contract<T: Config> {
+	caller: T::AccountId,
+	account_id: T::AccountId,
+	addr: <T::Lookup as StaticLookup>::Source,
+	endowment: BalanceOf<T>,
+	code_hash: <T::Hashing as Hash>::Output,
+}
+
+/// Describes how much balance should be transferred on instantiate from the caller.
+enum Endow {
+	/// Endow the contract with a maximum amount of balance. This value is described by
+	/// `Contract::max_endowment`.
+	Max,
+	/// Endow so that the amount of balance that is transferred is big but not so big
+	/// to offset the rent payment. This is needed in order to test rent collection.
+	CollectRent,
+}
+
+impl Endow {
+	/// The maximum amount of balance a caller can transfer without being brought below
+	/// the existential deposit. This assumes that every caller is funded with the amount
+	/// returned by `caller_funding`.
+	fn max<T: Config>() -> BalanceOf<T> {
+		caller_funding::<T>().saturating_sub(T::Currency::minimum_balance())
+	}
+}
+
+impl<T: Config> Contract<T>
+where
+	T: Config,
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+{
+	/// Create new contract and use a default account id as instantiator.
+	fn new(
+		module: WasmModule<T>,
+		data: Vec<u8>,
+		endowment: Endow,
+	) -> Result<Contract<T>, &'static str> {
+		Self::with_index(0, module, data, endowment)
+	}
+
+	/// Create new contract and use an account id derived from the supplied index as instantiator.
+	fn with_index(
+		index: u32,
+		module: WasmModule<T>,
+		data: Vec<u8>,
+		endowment: Endow,
+	) -> Result<Contract<T>, &'static str> {
+		Self::with_caller(account("instantiator", index, 0), module, data, endowment)
+	}
+
+	/// Create new contract and use the supplied `caller` as instantiator.
+	fn with_caller(
+		caller: T::AccountId,
+		module: WasmModule<T>,
+		data: Vec<u8>,
+		endowment: Endow,
+	) -> Result<Contract<T>, &'static str> {
+		let (storage_size, endowment) = match endowment {
+			Endow::CollectRent => {
+				// storage_size cannot be zero because otherwise a contract that is just above
+				// the subsistence threshold does not pay rent given a large enough subsistence
+				// threshold. But we need rent payments to occur in order to benchmark for worst cases.
+				let storage_size = u32::max_value() / 10;
+
+				// Endowment should be large but not as large to inhibit rent payments.
+				// Balance will only cover half the storage
+				let endowment = T::DepositPerStorageByte::get()
+					.saturating_mul(<BalanceOf<T>>::from(storage_size) / 2u32.into())
+					.saturating_add(T::DepositPerContract::get());
+
+				(storage_size, endowment)
+			}
+			Endow::Max => (0u32.into(), Endow::max::<T>()),
+		};
+		T::Currency::make_free_balance_be(&caller, caller_funding::<T>());
+		let salt = vec![0xff];
+		let addr = Contracts::<T>::contract_address(&caller, &module.hash, &salt);
+
+		// The default block number is zero. The benchmarking system bumps the block number
+		// to one for the benchmarking closure when it is set to zero. In order to prevent this
+		// undesired implicit bump (which messes with rent collection), we do the bump ourselves
+		// in the setup closure so that both the instantiate and subsequent call are run with the
+		// same block number.
+		System::<T>::set_block_number(1u32.into());
+
+		Contracts::<T>::store_code_raw(module.code)?;
+		Contracts::<T>::instantiate(
+			RawOrigin::Signed(caller.clone()).into(),
+			endowment,
+			Weight::max_value(),
+			module.hash,
+			data,
+			salt,
+		)?;
+
+		let result = Contract {
+			caller,
+			account_id: addr.clone(),
+			addr: T::Lookup::unlookup(addr),
+			endowment,
+			code_hash: module.hash.clone(),
+		};
+
+		let mut contract = result.alive_info()?;
+		contract.storage_size = storage_size;
+		ContractInfoOf::<T>::insert(&result.account_id, ContractInfo::Alive(contract));
+
+		Ok(result)
+	}
+
+	/// Store the supplied storage items into this contracts storage.
+	fn store(&self, items: &Vec<(StorageKey, Vec<u8>)>) -> Result<(), &'static str> {
+		let info = self.alive_info()?;
+		for item in items {
+			Storage::<T>::write(
+				&self.account_id,
+				&info.trie_id,
+				&item.0,
+				Some(item.1.clone()),
+			)
+			.map_err(|_| "Failed to write storage to restoration dest")?;
+		}
+		Ok(())
+	}
+
+	/// Get the `AliveContractInfo` of the `addr` or an error if it is no longer alive.
+	fn address_alive_info(addr: &T::AccountId) -> Result<AliveContractInfo<T>, &'static str> {
+		ContractInfoOf::<T>::get(addr)
+			.and_then(|c| c.get_alive())
+			.ok_or("Expected contract to be alive at this point.")
+	}
+
+	/// Get the `AliveContractInfo` of this contract or an error if it is no longer alive.
+	fn alive_info(&self) -> Result<AliveContractInfo<T>, &'static str> {
+		Self::address_alive_info(&self.account_id)
+	}
+
+	/// Return an error if this contract is no tombstone.
+	fn ensure_tombstone(&self) -> Result<(), &'static str> {
+		ContractInfoOf::<T>::get(&self.account_id)
+			.and_then(|c| c.get_tombstone())
+			.ok_or("Expected contract to be a tombstone at this point.")
+			.map(|_| ())
+	}
+
+	/// Get the block number when this contract will be evicted. Returns an error when
+	/// the rent collection won't happen because the contract has to much endowment.
+	fn eviction_at(&self) -> Result<T::BlockNumber, &'static str> {
+		let projection = Rent::<T, PrefabWasmModule<T>>::compute_projection(&self.account_id)
+			.map_err(|_| "Invalid acc for rent")?;
+		match projection {
+			RentProjection::EvictionAt(at) => Ok(at),
+			_ => Err("Account does not pay rent.")?,
+		}
+	}
+}
+
+/// A `Contract` that contains some storage items.
+///
+/// This is used to benchmark contract destruction and resurection. Those operations'
+/// weight depend on the amount of storage accumulated.
+struct ContractWithStorage<T: Config> {
+	/// The contract that was evicted.
+	contract: Contract<T>,
+	/// The storage the contract held when it was avicted.
+	storage: Vec<(StorageKey, Vec<u8>)>,
+}
+
+impl<T: Config> ContractWithStorage<T>
+where
+	T: Config,
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+{
+	/// Same as [`Self::with_code`] but with dummy contract code.
+	fn new(stor_num: u32, stor_size: u32) -> Result<Self, &'static str> {
+		Self::with_code(WasmModule::dummy(), stor_num, stor_size)
+	}
+
+	/// Create and evict a new contract with the supplied storage item count and size each.
+	fn with_code(code: WasmModule<T>, stor_num: u32, stor_size: u32) -> Result<Self, &'static str> {
+		let contract = Contract::<T>::new(code, vec![], Endow::CollectRent)?;
+		let storage_items = create_storage::<T>(stor_num, stor_size)?;
+		contract.store(&storage_items)?;
+		Ok(Self {
+			contract,
+			storage: storage_items,
+		})
+	}
+
+	/// Increase the system block number so that this contract is eligible for eviction.
+	fn set_block_num_for_eviction(&self) -> Result<(), &'static str> {
+		System::<T>::set_block_number(
+			self.contract.eviction_at()? + T::SignedClaimHandicap::get() + 5u32.into(),
+		);
+		Ok(())
+	}
+
+	/// Evict this contract.
+	fn evict(&mut self) -> Result<(), &'static str> {
+		self.set_block_num_for_eviction()?;
+		Rent::<T, PrefabWasmModule<T>>::try_eviction(&self.contract.account_id, Zero::zero())?;
+		self.contract.ensure_tombstone()
+	}
+}
+
+/// Generate `stor_num` storage items. Each has the size `stor_size`.
+fn create_storage<T: Config>(
+	stor_num: u32,
+	stor_size: u32,
+) -> Result<Vec<(StorageKey, Vec<u8>)>, &'static str> {
+	(0..stor_num)
+		.map(|i| {
+			let hash = T::Hashing::hash_of(&i)
+				.as_ref()
+				.try_into()
+				.map_err(|_| "Hash too big for storage key")?;
+			Ok((hash, vec![42u8; stor_size as usize]))
+		})
+		.collect::<Result<Vec<_>, &'static str>>()
+}
+
+/// The funding that each account that either calls or instantiates contracts is funded with.
+fn caller_funding<T: Config>() -> BalanceOf<T> {
+	BalanceOf::<T>::max_value() / 2u32.into()
+}
+
+benchmarks! {
+	where_clause { where
+		T::AccountId: UncheckedFrom<T::Hash>,
+		T::AccountId: AsRef<[u8]>,
+	}
+
+	// The base weight without any actual work performed apart from the setup costs.
+	on_initialize {}: {
+		Storage::<T>::process_deletion_queue_batch(Weight::max_value())
+	}
+
+	on_initialize_per_trie_key {
+		let k in 0..1024;
+		let instance = ContractWithStorage::<T>::new(k, T::MaxValueSize::get())?;
+		Storage::<T>::queue_trie_for_deletion(&instance.contract.alive_info()?)?;
+	}: {
+		Storage::<T>::process_deletion_queue_batch(Weight::max_value())
+	}
+
+	on_initialize_per_queue_item {
+		let q in 0..1024.min(T::DeletionQueueDepth::get());
+		for i in 0 .. q {
+			let instance = Contract::<T>::with_index(i, WasmModule::dummy(), vec![], Endow::Max)?;
+			Storage::<T>::queue_trie_for_deletion(&instance.alive_info()?)?;
+			ContractInfoOf::<T>::remove(instance.account_id);
+		}
+	}: {
+		Storage::<T>::process_deletion_queue_batch(Weight::max_value())
+	}
+
+	// This benchmarks the additional weight that is charged when a contract is executed the
+	// first time after a new schedule was deployed: For every new schedule a contract needs
+	// to re-run the instrumentation once.
+	instrument {
+		let c in 0 .. T::MaxCodeSize::get() / 1024;
+		let WasmModule { code, hash, .. } = WasmModule::<T>::sized(c * 1024);
+		Contracts::<T>::store_code_raw(code)?;
+		let mut module = PrefabWasmModule::from_storage_noinstr(hash)?;
+		let schedule = <CurrentSchedule<T>>::get();
+	}: {
+		Contracts::<T>::reinstrument_module(&mut module, &schedule)?;
+	}
+
+	// This extrinsic is pretty much constant as it is only a simple setter.
+	update_schedule {
+		let schedule = Schedule {
+			version: 1,
+			.. Default::default()
+		};
+	}: _(RawOrigin::Root, schedule)
+
+	// This constructs a contract that is maximal expensive to instrument.
+	// It creates a maximum number of metering blocks per byte.
+	// The size of the salt influences the runtime because is is hashed in order to
+	// determine the contract address.
+	// `c`: Size of the code in kilobytes.
+	// `s`: Size of the salt in kilobytes.
+	//
+	// # Note
+	//
+	// We cannot let `c` grow to the maximum code size because the code is not allowed
+	// to be larger than the maximum size **after instrumentation**.
+	instantiate_with_code {
+		let c in 0 .. Perbill::from_percent(50).mul_ceil(T::MaxCodeSize::get() / 1024);
+		let s in 0 .. code::max_pages::<T>() * 64;
+		let salt = vec![42u8; (s * 1024) as usize];
+		let endowment = caller_funding::<T>() / 3u32.into();
+		let caller = whitelisted_caller();
+		T::Currency::make_free_balance_be(&caller, caller_funding::<T>());
+		let WasmModule { code, hash, .. } = WasmModule::<T>::sized(c * 1024);
+		let origin = RawOrigin::Signed(caller.clone());
+		let addr = Contracts::<T>::contract_address(&caller, &hash, &salt);
+	}: _(origin, endowment, Weight::max_value(), code, vec![], salt)
+	verify {
+		// endowment was removed from the caller
+		assert_eq!(T::Currency::free_balance(&caller), caller_funding::<T>() - endowment);
+		// contract has the full endowment because no rent collection happended
+		assert_eq!(T::Currency::free_balance(&addr), endowment);
+		// instantiate should leave a alive contract
+		Contract::<T>::address_alive_info(&addr)?;
+	}
+
+	// Instantiate uses a dummy contract constructor to measure the overhead of the instantiate.
+	// `c`: Size of the code in kilobytes.
+	// `s`: Size of the salt in kilobytes.
+	instantiate {
+		let c in 0 .. T::MaxCodeSize::get() / 1024;
+		let s in 0 .. code::max_pages::<T>() * 64;
+		let salt = vec![42u8; (s * 1024) as usize];
+		let endowment = caller_funding::<T>() / 3u32.into();
+		let caller = whitelisted_caller();
+		T::Currency::make_free_balance_be(&caller, caller_funding::<T>());
+		let WasmModule { code, hash, .. } = WasmModule::<T>::dummy_with_bytes(c * 1024);
+		let origin = RawOrigin::Signed(caller.clone());
+		let addr = Contracts::<T>::contract_address(&caller, &hash, &salt);
+		Contracts::<T>::store_code_raw(code)?;
+	}: _(origin, endowment, Weight::max_value(), hash, vec![], salt)
+	verify {
+		// endowment was removed from the caller
+		assert_eq!(T::Currency::free_balance(&caller), caller_funding::<T>() - endowment);
+		// contract has the full endowment because no rent collection happended
+		assert_eq!(T::Currency::free_balance(&addr), endowment);
+		// instantiate should leave a alive contract
+		Contract::<T>::address_alive_info(&addr)?;
+	}
+
+	// We just call a dummy contract to measure to overhead of the call extrinsic.
+	// The size of the data has no influence on the costs of this extrinsic as long as the contract
+	// won't call `seal_input` in its constructor to copy the data to contract memory.
+	// The dummy contract used here does not do this. The costs for the data copy is billed as
+	// part of `seal_input`.
+	// `c`: Size of the code in kilobytes.
+	call {
+		let c in 0 .. T::MaxCodeSize::get() / 1024;
+		let data = vec![42u8; 1024];
+		let instance = Contract::<T>::with_caller(
+			whitelisted_caller(), WasmModule::dummy_with_bytes(c * 1024), vec![], Endow::CollectRent
+		)?;
+		let value = T::Currency::minimum_balance() * 100u32.into();
+		let origin = RawOrigin::Signed(instance.caller.clone());
+		let callee = instance.addr.clone();
+
+		// trigger rent collection for worst case performance of call
+		System::<T>::set_block_number(instance.eviction_at()? - 5u32.into());
+		let before = T::Currency::free_balance(&instance.account_id);
+	}: _(origin, callee, value, Weight::max_value(), data)
+	verify {
+		// endowment and value transfered via call should be removed from the caller
+		assert_eq!(
+			T::Currency::free_balance(&instance.caller),
+			caller_funding::<T>() - instance.endowment - value,
+		);
+		// rent should have lowered the amount of balance of the contract
+		assert!(T::Currency::free_balance(&instance.account_id) < before + value);
+		// but it should not have been evicted by the rent collection
+		instance.alive_info()?;
+	}
+
+	// We benchmark the costs for sucessfully evicting an empty contract.
+	// The actual costs are depending on how many storage items the evicted contract
+	// does have. However, those costs are not to be payed by the sender but
+	// will be distributed over multiple blocks using a scheduler. Otherwise there is
+	// no incentive to remove large contracts when the removal is more expensive than
+	// the reward for removing them.
+	// `c`: Size of the code of the contract that should be evicted.
+	claim_surcharge {
+		let c in 0 .. T::MaxCodeSize::get() / 1024;
+		let instance = Contract::<T>::with_caller(
+			whitelisted_caller(), WasmModule::dummy_with_bytes(c * 1024), vec![], Endow::CollectRent
+		)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+		let account_id = instance.account_id.clone();
+
+		// instantiate should leave us with an alive contract
+		instance.alive_info()?;
+
+		// generate enough rent so that the contract is evicted
+		System::<T>::set_block_number(
+			instance.eviction_at()? + T::SignedClaimHandicap::get() + 5u32.into()
+		);
+	}: _(origin, account_id, None)
+	verify {
+		// the claim surcharge should have evicted the contract
+		instance.ensure_tombstone()?;
+
+		// the caller should get the reward for being a good snitch
+		// this is capped by the maximum amount of rent payed. So we only now that it should
+		// have increased by at most the surcharge reward.
+		assert!(
+			T::Currency::free_balance(&instance.caller) >
+			caller_funding::<T>() - instance.endowment
+		);
+		assert!(
+			T::Currency::free_balance(&instance.caller) <=
+			caller_funding::<T>() - instance.endowment + <T as Config>::SurchargeReward::get(),
+		);
+	}
+
+	seal_caller {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::getter(
+			"seal_caller", r * API_BENCHMARK_BATCH_SIZE
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_address {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::getter(
+			"seal_address", r * API_BENCHMARK_BATCH_SIZE
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_gas_left {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::getter(
+			"seal_gas_left", r * API_BENCHMARK_BATCH_SIZE
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_balance {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::getter(
+			"seal_balance", r * API_BENCHMARK_BATCH_SIZE
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_value_transferred {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::getter(
+			"seal_value_transferred", r * API_BENCHMARK_BATCH_SIZE
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_minimum_balance {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::getter(
+			"seal_minimum_balance", r * API_BENCHMARK_BATCH_SIZE
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_tombstone_deposit {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::getter(
+			"seal_tombstone_deposit", r * API_BENCHMARK_BATCH_SIZE
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_rent_allowance {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::getter(
+			"seal_rent_allowance", r * API_BENCHMARK_BATCH_SIZE
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_block_number {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::getter(
+			"seal_block_number", r * API_BENCHMARK_BATCH_SIZE
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_now {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::getter(
+			"seal_now", r * API_BENCHMARK_BATCH_SIZE
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_rent_params {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::getter(
+			"seal_rent_params", r * API_BENCHMARK_BATCH_SIZE
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_weight_to_fee {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let pages = code::max_pages::<T>();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_weight_to_fee",
+				params: vec![ValueType::I64, ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			data_segments: vec![DataSegment {
+				offset: 0,
+				value: (pages * 64 * 1024 - 4).to_le_bytes().to_vec(),
+			}],
+			call_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &[
+				Instruction::I64Const(500_000),
+				Instruction::I32Const(4),
+				Instruction::I32Const(0),
+				Instruction::Call(0),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_gas {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			imported_functions: vec![ImportedFunction {
+				name: "gas",
+				params: vec![ValueType::I32],
+				return_type: None,
+			}],
+			call_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &[
+				Instruction::I32Const(42),
+				Instruction::Call(0),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// We cannot call seal_input multiple times. Therefore our weight determination is not
+	// as precise as with other APIs. Because this function can only be called once per
+	// contract it cannot be used for Dos.
+	seal_input {
+		let r in 0 .. 1;
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_input",
+				params: vec![ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: 0u32.to_le_bytes().to_vec(),
+				},
+			],
+			call_body: Some(body::repeated(r, &[
+				Instruction::I32Const(4), // ptr where to store output
+				Instruction::I32Const(0), // ptr to length
+				Instruction::Call(0),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_input_per_kb {
+		let n in 0 .. code::max_pages::<T>() * 64;
+		let pages = code::max_pages::<T>();
+		let buffer_size = pages * 64 * 1024 - 4;
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_input",
+				params: vec![ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: buffer_size.to_le_bytes().to_vec(),
+				},
+			],
+			call_body: Some(body::plain(vec![
+				Instruction::I32Const(4), // ptr where to store output
+				Instruction::I32Const(0), // ptr to length
+				Instruction::Call(0),
+				Instruction::End,
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let data = vec![42u8; (n * 1024).min(buffer_size) as usize];
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), data)
+
+	// The same argument as for `seal_input` is true here.
+	seal_return {
+		let r in 0 .. 1;
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_return",
+				params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			call_body: Some(body::repeated(r, &[
+				Instruction::I32Const(0), // flags
+				Instruction::I32Const(0), // data_ptr
+				Instruction::I32Const(0), // data_len
+				Instruction::Call(0),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_return_per_kb {
+		let n in 0 .. code::max_pages::<T>() * 64;
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_return",
+				params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			call_body: Some(body::plain(vec![
+				Instruction::I32Const(0), // flags
+				Instruction::I32Const(0), // data_ptr
+				Instruction::I32Const((n * 1024) as i32), // data_len
+				Instruction::Call(0),
+				Instruction::End,
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// The same argument as for `seal_input` is true here.
+	seal_terminate {
+		let r in 0 .. 1;
+		let beneficiary = account::<T::AccountId>("beneficiary", 0, 0);
+		let beneficiary_bytes = beneficiary.encode();
+		let beneficiary_len = beneficiary_bytes.len();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_terminate",
+				params: vec![ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: beneficiary_bytes,
+				},
+			],
+			call_body: Some(body::repeated(r, &[
+				Instruction::I32Const(0), // beneficiary_ptr
+				Instruction::I32Const(beneficiary_len as i32), // beneficiary_len
+				Instruction::Call(0),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+		assert_eq!(T::Currency::total_balance(&beneficiary), 0u32.into());
+		assert_eq!(T::Currency::total_balance(&instance.account_id), Endow::max::<T>());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+	verify {
+		if r > 0 {
+			assert_eq!(T::Currency::total_balance(&instance.account_id), 0u32.into());
+			assert_eq!(T::Currency::total_balance(&beneficiary), Endow::max::<T>());
+		}
+	}
+
+	seal_terminate_per_code_kb {
+		let c in 0 .. T::MaxCodeSize::get() / 1024;
+		let beneficiary = account::<T::AccountId>("beneficiary", 0, 0);
+		let beneficiary_bytes = beneficiary.encode();
+		let beneficiary_len = beneficiary_bytes.len();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_terminate",
+				params: vec![ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: beneficiary_bytes,
+				},
+			],
+			call_body: Some(body::repeated(1, &[
+				Instruction::I32Const(0), // beneficiary_ptr
+				Instruction::I32Const(beneficiary_len as i32), // beneficiary_len
+				Instruction::Call(0),
+			])),
+			dummy_section: c * 1024,
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+		assert_eq!(T::Currency::total_balance(&beneficiary), 0u32.into());
+		assert_eq!(T::Currency::total_balance(&instance.account_id), Endow::max::<T>());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+	verify {
+		assert_eq!(T::Currency::total_balance(&instance.account_id), 0u32.into());
+		assert_eq!(T::Currency::total_balance(&beneficiary), Endow::max::<T>());
+	}
+
+	seal_restore_to {
+		let r in 0 .. 1;
+
+		// Restore just moves the trie id from origin to destination and therefore
+		// does not depend on the size of the destination contract. However, to not
+		// trigger any edge case we won't use an empty contract as destination.
+		let mut tombstone = ContractWithStorage::<T>::new(10, T::MaxValueSize::get())?;
+		tombstone.evict()?;
+
+		let dest = tombstone.contract.account_id.encode();
+		let dest_len = dest.len();
+		let code_hash = tombstone.contract.code_hash.encode();
+		let code_hash_len = code_hash.len();
+		let rent_allowance = BalanceOf::<T>::max_value().encode();
+		let rent_allowance_len = rent_allowance.len();
+
+		let dest_offset = 0;
+		let code_hash_offset = dest_offset + dest_len;
+		let rent_allowance_offset = code_hash_offset + code_hash_len;
+
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_restore_to",
+				params: vec![
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+				],
+				return_type: None,
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: dest_offset as u32,
+					value: dest,
+				},
+				DataSegment {
+					offset: code_hash_offset as u32,
+					value: code_hash,
+				},
+				DataSegment {
+					offset: rent_allowance_offset as u32,
+					value: rent_allowance,
+				},
+			],
+			call_body: Some(body::repeated(r, &[
+				Instruction::I32Const(dest_offset as i32),
+				Instruction::I32Const(dest_len as i32),
+				Instruction::I32Const(code_hash_offset as i32),
+				Instruction::I32Const(code_hash_len as i32),
+				Instruction::I32Const(rent_allowance_offset as i32),
+				Instruction::I32Const(rent_allowance_len as i32),
+				Instruction::I32Const(0), // delta_ptr
+				Instruction::I32Const(0), // delta_count
+				Instruction::Call(0),
+			])),
+			.. Default::default()
+		});
+
+		let instance = Contract::<T>::with_caller(
+			account("origin", 0, 0), code, vec![], Endow::Max
+		)?;
+		instance.store(&tombstone.storage)?;
+		System::<T>::set_block_number(System::<T>::block_number() + 1u32.into());
+
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+	verify {
+		if r > 0 {
+			tombstone.contract.alive_info()?;
+		}
+	}
+
+	// `c`: Code size of caller contract
+	// `t`: Code size of tombstone contract
+	// `d`: Number of supplied delta keys
+	seal_restore_to_per_code_kb_delta {
+		let c in 0 .. T::MaxCodeSize::get() / 1024;
+		let t in 0 .. T::MaxCodeSize::get() / 1024;
+		let d in 0 .. API_BENCHMARK_BATCHES;
+		let mut tombstone = ContractWithStorage::<T>::with_code(
+			WasmModule::<T>::dummy_with_bytes(t * 1024), 0, 0
+		)?;
+		tombstone.evict()?;
+		let delta = create_storage::<T>(d * API_BENCHMARK_BATCH_SIZE, T::MaxValueSize::get())?;
+
+		let dest = tombstone.contract.account_id.encode();
+		let dest_len = dest.len();
+		let code_hash = tombstone.contract.code_hash.encode();
+		let code_hash_len = code_hash.len();
+		let rent_allowance = BalanceOf::<T>::max_value().encode();
+		let rent_allowance_len = rent_allowance.len();
+		let delta_keys = delta.iter().flat_map(|(key, _)| key).cloned().collect::<Vec<_>>();
+
+		let dest_offset = 0;
+		let code_hash_offset = dest_offset + dest_len;
+		let rent_allowance_offset = code_hash_offset + code_hash_len;
+		let delta_keys_offset = rent_allowance_offset + rent_allowance_len;
+
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_restore_to",
+				params: vec![
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+				],
+				return_type: None,
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: dest_offset as u32,
+					value: dest,
+				},
+				DataSegment {
+					offset: code_hash_offset as u32,
+					value: code_hash,
+				},
+				DataSegment {
+					offset: rent_allowance_offset as u32,
+					value: rent_allowance,
+				},
+				DataSegment {
+					offset: delta_keys_offset as u32,
+					value: delta_keys,
+				},
+			],
+			call_body: Some(body::plain(vec![
+				Instruction::I32Const(dest_offset as i32),
+				Instruction::I32Const(dest_len as i32),
+				Instruction::I32Const(code_hash_offset as i32),
+				Instruction::I32Const(code_hash_len as i32),
+				Instruction::I32Const(rent_allowance_offset as i32),
+				Instruction::I32Const(rent_allowance_len as i32),
+				Instruction::I32Const(delta_keys_offset as i32), // delta_ptr
+				Instruction::I32Const(delta.len() as i32), // delta_count
+				Instruction::Call(0),
+				Instruction::End,
+			])),
+			dummy_section: c * 1024,
+			.. Default::default()
+		});
+
+		let instance = Contract::<T>::with_caller(
+			account("origin", 0, 0), code, vec![], Endow::Max
+		)?;
+		instance.store(&tombstone.storage)?;
+		instance.store(&delta)?;
+		System::<T>::set_block_number(System::<T>::block_number() + 1u32.into());
+
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+	verify {
+		tombstone.contract.alive_info()?;
+	}
+
+	// We benchmark only for the maximum subject length. We assume that this is some lowish
+	// number (< 1 KB). Therefore we are not overcharging too much in case a smaller subject is
+	// used.
+	seal_random {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let pages = code::max_pages::<T>();
+		let subject_len = <CurrentSchedule<T>>::get().limits.subject_len;
+		assert!(subject_len < 1024);
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_random",
+				params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: (pages * 64 * 1024 - subject_len - 4).to_le_bytes().to_vec(),
+				},
+			],
+			call_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &[
+				Instruction::I32Const(4), // subject_ptr
+				Instruction::I32Const(subject_len as i32), // subject_len
+				Instruction::I32Const((subject_len + 4) as i32), // out_ptr
+				Instruction::I32Const(0),	// out_len_ptr
+				Instruction::Call(0),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// Overhead of calling the function without any topic.
+	// We benchmark for the worst case (largest event).
+	seal_deposit_event {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_deposit_event",
+				params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			call_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &[
+				Instruction::I32Const(0), // topics_ptr
+				Instruction::I32Const(0), // topics_len
+				Instruction::I32Const(0), // data_ptr
+				Instruction::I32Const(0), // data_len
+				Instruction::Call(0),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// Benchmark the overhead that topics generate.
+	// `t`: Number of topics
+	// `n`: Size of event payload in kb
+	seal_deposit_event_per_topic_and_kb {
+		let t in 0 .. <CurrentSchedule<T>>::get().limits.event_topics;
+		let n in 0 .. T::MaxValueSize::get() / 1024;
+		let mut topics = (0..API_BENCHMARK_BATCH_SIZE)
+			.map(|n| (n * t..n * t + t).map(|i| T::Hashing::hash_of(&i)).collect::<Vec<_>>().encode())
+			.peekable();
+		let topics_len = topics.peek().map(|i| i.len()).unwrap_or(0);
+		let topics = topics.flatten().collect();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_deposit_event",
+				params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: topics,
+				},
+			],
+			call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![
+				Counter(0, topics_len as u32), // topics_ptr
+				Regular(Instruction::I32Const(topics_len as i32)), // topics_len
+				Regular(Instruction::I32Const(0)), // data_ptr
+				Regular(Instruction::I32Const((n * 1024) as i32)), // data_len
+				Regular(Instruction::Call(0)),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_set_rent_allowance {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let allowance = caller_funding::<T>().encode();
+		let allowance_len = allowance.len();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory { min_pages: 1, max_pages: 1 }),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_set_rent_allowance",
+				params: vec![ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: allowance,
+				},
+			],
+			call_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &[
+				Instruction::I32Const(0), // value_ptr
+				Instruction::I32Const(allowance_len as i32), // value_len
+				Instruction::Call(0),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// Only the overhead of calling the function itself with minimal arguments.
+	// The contract is a bit more complex because I needs to use different keys in order
+	// to generate unique storage accesses. However, it is still dominated by the storage
+	// accesses.
+	seal_set_storage {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE)
+			.flat_map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
+			.collect::<Vec<_>>();
+		let key_len = sp_std::mem::size_of::<<T::Hashing as sp_runtime::traits::Hash>::Output>();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_set_storage",
+				params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: keys,
+				},
+			],
+			call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
+				Counter(0, key_len as u32), // key_ptr
+				Regular(Instruction::I32Const(0)), // value_ptr
+				Regular(Instruction::I32Const(0)), // value_len
+				Regular(Instruction::Call(0)),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_set_storage_per_kb {
+		let n in 0 .. T::MaxValueSize::get() / 1024;
+		let key = T::Hashing::hash_of(&1u32).as_ref().to_vec();
+		let key_len = key.len();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_set_storage",
+				params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
+				return_type: None,
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: key,
+				},
+			],
+			call_body: Some(body::repeated(API_BENCHMARK_BATCH_SIZE, &[
+				Instruction::I32Const(0), // key_ptr
+				Instruction::I32Const(0), // value_ptr
+				Instruction::I32Const((n * 1024) as i32), // value_len
+				Instruction::Call(0),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// Similar to seal_set_storage. However, we store all the keys that we are about to
+	// delete beforehand in order to prevent any optimizations that could occur when
+	// deleting a non existing key.
+	seal_clear_storage {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE)
+			.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
+			.collect::<Vec<_>>();
+		let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
+		let key_len = sp_std::mem::size_of::<<T::Hashing as sp_runtime::traits::Hash>::Output>();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_clear_storage",
+				params: vec![ValueType::I32],
+				return_type: None,
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: key_bytes,
+				},
+			],
+			call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
+				Counter(0, key_len as u32),
+				Regular(Instruction::Call(0)),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let trie_id = instance.alive_info()?.trie_id;
+		for key in keys {
+			Storage::<T>::write(
+				&instance.account_id,
+				&trie_id,
+				key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
+				Some(vec![42; T::MaxValueSize::get() as usize])
+			)
+			.map_err(|_| "Failed to write to storage during setup.")?;
+		}
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// We make sure that all storage accesses are to unique keys.
+	seal_get_storage {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE)
+			.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
+			.collect::<Vec<_>>();
+		let key_len = sp_std::mem::size_of::<<T::Hashing as sp_runtime::traits::Hash>::Output>();
+		let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
+		let key_bytes_len = key_bytes.len();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_get_storage",
+				params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
+				return_type: Some(ValueType::I32),
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: key_bytes,
+				},
+			],
+			call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
+				Counter(0, key_len as u32), // key_ptr
+				Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr
+				Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr
+				Regular(Instruction::Call(0)),
+				Regular(Instruction::Drop),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let trie_id = instance.alive_info()?.trie_id;
+		for key in keys {
+			Storage::<T>::write(
+				&instance.account_id,
+				&trie_id,
+				key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
+				Some(vec![])
+			)
+			.map_err(|_| "Failed to write to storage during setup.")?;
+		}
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_get_storage_per_kb {
+		let n in 0 .. T::MaxValueSize::get() / 1024;
+		let key = T::Hashing::hash_of(&1u32).as_ref().to_vec();
+		let key_len = key.len();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_get_storage",
+				params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
+				return_type: Some(ValueType::I32),
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: key.clone(),
+				},
+				DataSegment {
+					offset: key_len as u32,
+					value: T::MaxValueSize::get().to_le_bytes().into(),
+				},
+			],
+			call_body: Some(body::repeated(API_BENCHMARK_BATCH_SIZE, &[
+				// call at key_ptr
+				Instruction::I32Const(0), // key_ptr
+				Instruction::I32Const((key_len + 4) as i32), // out_ptr
+				Instruction::I32Const(key_len as i32), // out_len_ptr
+				Instruction::Call(0),
+				Instruction::Drop,
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let trie_id = instance.alive_info()?.trie_id;
+		Storage::<T>::write(
+			&instance.account_id,
+			&trie_id,
+			key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
+			Some(vec![42u8; (n * 1024) as usize])
+		)
+		.map_err(|_| "Failed to write to storage during setup.")?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// We transfer to unique accounts.
+	seal_transfer {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let accounts = (0..r * API_BENCHMARK_BATCH_SIZE)
+			.map(|i| account::<T::AccountId>("receiver", i, 0))
+			.collect::<Vec<_>>();
+		let account_len = accounts.get(0).map(|i| i.encode().len()).unwrap_or(0);
+		let account_bytes = accounts.iter().flat_map(|x| x.encode()).collect();
+		let value = Contracts::<T>::subsistence_threshold();
+		assert!(value > 0u32.into());
+		let value_bytes = value.encode();
+		let value_len = value_bytes.len();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_transfer",
+				params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
+				return_type: Some(ValueType::I32),
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: value_bytes,
+				},
+				DataSegment {
+					offset: value_len as u32,
+					value: account_bytes,
+				},
+			],
+			call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
+				Counter(value_len as u32, account_len as u32), // account_ptr
+				Regular(Instruction::I32Const(account_len as i32)), // account_len
+				Regular(Instruction::I32Const(0)), // value_ptr
+				Regular(Instruction::I32Const(value_len as i32)), // value_len
+				Regular(Instruction::Call(0)),
+				Regular(Instruction::Drop),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+		for account in &accounts {
+			assert_eq!(T::Currency::total_balance(account), 0u32.into());
+		}
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+	verify {
+		for account in &accounts {
+			assert_eq!(T::Currency::total_balance(account), value);
+		}
+	}
+
+	// We call unique accounts.
+	seal_call {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let dummy_code = WasmModule::<T>::dummy_with_bytes(0);
+		let callees = (0..r * API_BENCHMARK_BATCH_SIZE)
+			.map(|i| Contract::with_index(i + 1, dummy_code.clone(), vec![], Endow::Max))
+			.collect::<Result<Vec<_>, _>>()?;
+		let callee_len = callees.get(0).map(|i| i.account_id.encode().len()).unwrap_or(0);
+		let callee_bytes = callees.iter().flat_map(|x| x.account_id.encode()).collect();
+		let value: BalanceOf<T> = 0u32.into();
+		let value_bytes = value.encode();
+		let value_len = value_bytes.len();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_call",
+				params: vec![
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I64,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+				],
+				return_type: Some(ValueType::I32),
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: value_bytes,
+				},
+				DataSegment {
+					offset: value_len as u32,
+					value: callee_bytes,
+				},
+			],
+			call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
+				Counter(value_len as u32, callee_len as u32), // callee_ptr
+				Regular(Instruction::I32Const(callee_len as i32)), // callee_len
+				Regular(Instruction::I64Const(0)), // gas
+				Regular(Instruction::I32Const(0)), // value_ptr
+				Regular(Instruction::I32Const(value_len as i32)), // value_len
+				Regular(Instruction::I32Const(0)), // input_data_ptr
+				Regular(Instruction::I32Const(0)), // input_data_len
+				Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr
+				Regular(Instruction::I32Const(0)), // output_len_ptr
+				Regular(Instruction::Call(0)),
+				Regular(Instruction::Drop),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	seal_call_per_code_transfer_input_output_kb {
+		let c in 0 .. T::MaxCodeSize::get() / 1024;
+		let t in 0 .. 1;
+		let i in 0 .. code::max_pages::<T>() * 64;
+		let o in 0 .. (code::max_pages::<T>() - 1) * 64;
+		let callee_code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_return",
+				params: vec![
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+				],
+				return_type: None,
+			}],
+			call_body: Some(body::plain(vec![
+				Instruction::I32Const(0), // flags
+				Instruction::I32Const(0), // data_ptr
+				Instruction::I32Const((o * 1024) as i32), // data_len
+				Instruction::Call(0),
+				Instruction::End,
+			])),
+			dummy_section: c * 1024,
+			.. Default::default()
+		});
+		let callees = (0..API_BENCHMARK_BATCH_SIZE)
+			.map(|i| Contract::with_index(i + 1, callee_code.clone(), vec![], Endow::Max))
+			.collect::<Result<Vec<_>, _>>()?;
+		let callee_len = callees.get(0).map(|i| i.account_id.encode().len()).unwrap_or(0);
+		let callee_bytes = callees.iter().flat_map(|x| x.account_id.encode()).collect::<Vec<_>>();
+		let callees_len = callee_bytes.len();
+		let value: BalanceOf<T> = t.into();
+		let value_bytes = value.encode();
+		let value_len = value_bytes.len();
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_call",
+				params: vec![
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I64,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+				],
+				return_type: Some(ValueType::I32),
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: 0,
+					value: value_bytes,
+				},
+				DataSegment {
+					offset: value_len as u32,
+					value: callee_bytes,
+				},
+				DataSegment {
+					offset: (value_len + callees_len) as u32,
+					value: (o * 1024).to_le_bytes().into(),
+				},
+			],
+			call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![
+				Counter(value_len as u32, callee_len as u32), // callee_ptr
+				Regular(Instruction::I32Const(callee_len as i32)), // callee_len
+				Regular(Instruction::I64Const(0)), // gas
+				Regular(Instruction::I32Const(0)), // value_ptr
+				Regular(Instruction::I32Const(value_len as i32)), // value_len
+				Regular(Instruction::I32Const(0)), // input_data_ptr
+				Regular(Instruction::I32Const((i * 1024) as i32)), // input_data_len
+				Regular(Instruction::I32Const((value_len + callees_len + 4) as i32)), // output_ptr
+				Regular(Instruction::I32Const((value_len + callees_len) as i32)), // output_len_ptr
+				Regular(Instruction::Call(0)),
+				Regular(Instruction::Drop),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// We assume that every instantiate sends at least the subsistence amount.
+	seal_instantiate {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let hashes = (0..r * API_BENCHMARK_BATCH_SIZE)
+			.map(|i| {
+				let code = WasmModule::<T>::from(ModuleDefinition {
+					memory: Some(ImportedMemory::max::<T>()),
+					call_body: Some(body::plain(vec![
+						// we need to add this in order to make contracts unique
+						// so that they can be deployed from the same sender
+						Instruction::I32Const(i as i32),
+						Instruction::Drop,
+						Instruction::End,
+					])),
+					.. Default::default()
+				});
+				Contracts::<T>::store_code_raw(code.code)?;
+				Ok(code.hash)
+			})
+			.collect::<Result<Vec<_>, &'static str>>()?;
+		let hash_len = hashes.get(0).map(|x| x.encode().len()).unwrap_or(0);
+		let hashes_bytes = hashes.iter().flat_map(|x| x.encode()).collect::<Vec<_>>();
+		let hashes_len = hashes_bytes.len();
+		let value = Endow::max::<T>() / (r * API_BENCHMARK_BATCH_SIZE + 2).into();
+		assert!(value > 0u32.into());
+		let value_bytes = value.encode();
+		let value_len = value_bytes.len();
+		let addr_len = sp_std::mem::size_of::<T::AccountId>();
+
+		// offsets where to place static data in contract memory
+		let value_offset = 0;
+		let hashes_offset = value_offset + value_len;
+		let addr_len_offset = hashes_offset + hashes_len;
+		let addr_offset = addr_len_offset + addr_len;
+
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_instantiate",
+				params: vec![
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I64,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+				],
+				return_type: Some(ValueType::I32),
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: value_offset as u32,
+					value: value_bytes,
+				},
+				DataSegment {
+					offset: hashes_offset as u32,
+					value: hashes_bytes,
+				},
+				DataSegment {
+					offset: addr_len_offset as u32,
+					value: addr_len.to_le_bytes().into(),
+				},
+			],
+			call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
+				Counter(hashes_offset as u32, hash_len as u32), // code_hash_ptr
+				Regular(Instruction::I32Const(hash_len as i32)), // code_hash_len
+				Regular(Instruction::I64Const(0)), // gas
+				Regular(Instruction::I32Const(value_offset as i32)), // value_ptr
+				Regular(Instruction::I32Const(value_len as i32)), // value_len
+				Regular(Instruction::I32Const(0)), // input_data_ptr
+				Regular(Instruction::I32Const(0)), // input_data_len
+				Regular(Instruction::I32Const(addr_offset as i32)), // address_ptr
+				Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr
+				Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr
+				Regular(Instruction::I32Const(0)), // output_len_ptr
+				Regular(Instruction::I32Const(0)), // salt_ptr
+				Regular(Instruction::I32Const(0)), // salt_ptr_len
+				Regular(Instruction::Call(0)),
+				Regular(Instruction::Drop),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+		let callee = instance.addr.clone();
+		let addresses = hashes
+			.iter()
+			.map(|hash| Contracts::<T>::contract_address(
+				&instance.account_id, hash, &[],
+			))
+			.collect::<Vec<_>>();
+
+		for addr in &addresses {
+			if let Some(_) = ContractInfoOf::<T>::get(&addr) {
+				return Err("Expected that contract does not exist at this point.");
+			}
+		}
+	}: call(origin, callee, 0u32.into(), Weight::max_value(), vec![])
+	verify {
+		for addr in &addresses {
+			ContractInfoOf::<T>::get(&addr).and_then(|c| c.get_alive())
+				.ok_or_else(|| "Contract should have been instantiated")?;
+		}
+	}
+
+	seal_instantiate_per_code_input_output_salt_kb {
+		let c in 0 .. T::MaxCodeSize::get() / 1024;
+		let i in 0 .. (code::max_pages::<T>() - 1) * 64;
+		let o in 0 .. (code::max_pages::<T>() - 1) * 64;
+		let s in 0 .. (code::max_pages::<T>() - 1) * 64;
+		let callee_code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_return",
+				params: vec![
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+				],
+				return_type: None,
+			}],
+			deploy_body: Some(body::plain(vec![
+				Instruction::I32Const(0), // flags
+				Instruction::I32Const(0), // data_ptr
+				Instruction::I32Const((o * 1024) as i32), // data_len
+				Instruction::Call(0),
+				Instruction::End,
+			])),
+			dummy_section: c * 1024,
+			.. Default::default()
+		});
+		let hash = callee_code.hash.clone();
+		let hash_bytes = callee_code.hash.encode();
+		let hash_len = hash_bytes.len();
+		Contracts::<T>::store_code_raw(callee_code.code)?;
+		let inputs = (0..API_BENCHMARK_BATCH_SIZE).map(|x| x.encode()).collect::<Vec<_>>();
+		let input_len = inputs.get(0).map(|x| x.len()).unwrap_or(0);
+		let input_bytes = inputs.iter().cloned().flatten().collect::<Vec<_>>();
+		let inputs_len = input_bytes.len();
+		let value = Endow::max::<T>() / (API_BENCHMARK_BATCH_SIZE + 2).into();
+		assert!(value > 0u32.into());
+		let value_bytes = value.encode();
+		let value_len = value_bytes.len();
+		let addr_len = sp_std::mem::size_of::<T::AccountId>();
+
+		// offsets where to place static data in contract memory
+		let input_offset = 0;
+		let value_offset = inputs_len;
+		let hash_offset = value_offset + value_len;
+		let addr_len_offset = hash_offset + hash_len;
+		let output_len_offset = addr_len_offset + 4;
+		let output_offset = output_len_offset + 4;
+
+		let code = WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			imported_functions: vec![ImportedFunction {
+				name: "seal_instantiate",
+				params: vec![
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I64,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+					ValueType::I32,
+				],
+				return_type: Some(ValueType::I32),
+			}],
+			data_segments: vec![
+				DataSegment {
+					offset: input_offset as u32,
+					value: input_bytes,
+				},
+				DataSegment {
+					offset: value_offset as u32,
+					value: value_bytes,
+				},
+				DataSegment {
+					offset: hash_offset as u32,
+					value: hash_bytes,
+				},
+				DataSegment {
+					offset: addr_len_offset as u32,
+					value: (addr_len as u32).to_le_bytes().into(),
+				},
+				DataSegment {
+					offset: output_len_offset as u32,
+					value: (o * 1024).to_le_bytes().into(),
+				},
+			],
+			call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![
+				Regular(Instruction::I32Const(hash_offset as i32)), // code_hash_ptr
+				Regular(Instruction::I32Const(hash_len as i32)), // code_hash_len
+				Regular(Instruction::I64Const(0)), // gas
+				Regular(Instruction::I32Const(value_offset as i32)), // value_ptr
+				Regular(Instruction::I32Const(value_len as i32)), // value_len
+				Counter(input_offset as u32, input_len as u32), // input_data_ptr
+				Regular(Instruction::I32Const((i * 1024).max(input_len as u32) as i32)), // input_data_len
+				Regular(Instruction::I32Const((addr_len_offset + addr_len) as i32)), // address_ptr
+				Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr
+				Regular(Instruction::I32Const(output_offset as i32)), // output_ptr
+				Regular(Instruction::I32Const(output_len_offset as i32)), // output_len_ptr
+				Counter(input_offset as u32, input_len as u32), // salt_ptr
+				Regular(Instruction::I32Const((s * 1024).max(input_len as u32) as i32)), // salt_len
+				Regular(Instruction::Call(0)),
+				Regular(Instruction::I32Eqz),
+				Regular(Instruction::If(BlockType::NoResult)),
+				Regular(Instruction::Nop),
+				Regular(Instruction::Else),
+				Regular(Instruction::Unreachable),
+				Regular(Instruction::End),
+			])),
+			.. Default::default()
+		});
+		let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// Only the overhead of calling the function itself with minimal arguments.
+	seal_hash_sha2_256 {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::hasher(
+			"seal_hash_sha2_256", r * API_BENCHMARK_BATCH_SIZE, 0,
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// `n`: Input to hash in kilobytes
+	seal_hash_sha2_256_per_kb {
+		let n in 0 .. code::max_pages::<T>() * 64;
+		let instance = Contract::<T>::new(WasmModule::hasher(
+			"seal_hash_sha2_256", API_BENCHMARK_BATCH_SIZE, n * 1024,
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// Only the overhead of calling the function itself with minimal arguments.
+	seal_hash_keccak_256 {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::hasher(
+			"seal_hash_keccak_256", r * API_BENCHMARK_BATCH_SIZE, 0,
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// `n`: Input to hash in kilobytes
+	seal_hash_keccak_256_per_kb {
+		let n in 0 .. code::max_pages::<T>() * 64;
+		let instance = Contract::<T>::new(WasmModule::hasher(
+			"seal_hash_keccak_256", API_BENCHMARK_BATCH_SIZE, n * 1024,
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// Only the overhead of calling the function itself with minimal arguments.
+	seal_hash_blake2_256 {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::hasher(
+			"seal_hash_blake2_256", r * API_BENCHMARK_BATCH_SIZE, 0,
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// `n`: Input to hash in kilobytes
+	seal_hash_blake2_256_per_kb {
+		let n in 0 .. code::max_pages::<T>() * 64;
+		let instance = Contract::<T>::new(WasmModule::hasher(
+			"seal_hash_blake2_256", API_BENCHMARK_BATCH_SIZE, n * 1024,
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// Only the overhead of calling the function itself with minimal arguments.
+	seal_hash_blake2_128 {
+		let r in 0 .. API_BENCHMARK_BATCHES;
+		let instance = Contract::<T>::new(WasmModule::hasher(
+			"seal_hash_blake2_128", r * API_BENCHMARK_BATCH_SIZE, 0,
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// `n`: Input to hash in kilobytes
+	seal_hash_blake2_128_per_kb {
+		let n in 0 .. code::max_pages::<T>() * 64;
+		let instance = Contract::<T>::new(WasmModule::hasher(
+			"seal_hash_blake2_128", API_BENCHMARK_BATCH_SIZE, n * 1024,
+		), vec![], Endow::Max)?;
+		let origin = RawOrigin::Signed(instance.caller.clone());
+	}: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])
+
+	// We make the assumption that pushing a constant and dropping a value takes roughly
+	// the same amount of time. We follow that `t.load` and `drop` both have the weight
+	// of this benchmark / 2. We need to make this assumption because there is no way
+	// to measure them on their own using a valid wasm module. We need their individual
+	// values to derive the weight of individual instructions (by substraction) from
+	// benchmarks that include those for parameter pushing and return type dropping.
+	// We call the weight of `t.load` and `drop`: `w_param`.
+	// The weight that would result from the respective benchmark we call: `w_bench`.
+	//
+	// w_i{32,64}const = w_drop = w_bench / 2
+	instr_i64const {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_i{32,64}load = w_bench - 2 * w_param
+	instr_i64load {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				RandomUnaligned(0, code::max_pages::<T>() * 64 * 1024 - 8),
+				Regular(Instruction::I64Load(3, 0)),
+				Regular(Instruction::Drop),
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_i{32,64}store{...} = w_bench - 2 * w_param
+	instr_i64store {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				RandomUnaligned(0, code::max_pages::<T>() * 64 * 1024 - 8),
+				RandomI64Repeated(1),
+				Regular(Instruction::I64Store(3, 0)),
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_select = w_bench - 4 * w_param
+	instr_select {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				RandomI64Repeated(1),
+				RandomI64Repeated(1),
+				RandomI32(0, 2),
+				Regular(Instruction::Select),
+				Regular(Instruction::Drop),
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_if = w_bench - 3 * w_param
+	instr_if {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				RandomI32(0, 2),
+				Regular(Instruction::If(BlockType::Value(ValueType::I64))),
+				RandomI64Repeated(1),
+				Regular(Instruction::Else),
+				RandomI64Repeated(1),
+				Regular(Instruction::End),
+				Regular(Instruction::Drop),
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_br = w_bench - 2 * w_param
+	instr_br {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				Regular(Instruction::Block(BlockType::NoResult)),
+				Regular(Instruction::Block(BlockType::NoResult)),
+				Regular(Instruction::Block(BlockType::NoResult)),
+				Regular(Instruction::Br(1)),
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+				Regular(Instruction::End),
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+				Regular(Instruction::End),
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+				Regular(Instruction::End),
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_br_if = w_bench - 5 * w_param
+	// The two additional pushes + drop are only executed 50% of the time.
+	// Making it: 3 * w_param + (50% * 4 * w_param)
+	instr_br_if {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				Regular(Instruction::Block(BlockType::NoResult)),
+				Regular(Instruction::Block(BlockType::NoResult)),
+				Regular(Instruction::Block(BlockType::NoResult)),
+				RandomI32(0, 2),
+				Regular(Instruction::BrIf(1)),
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+				Regular(Instruction::End),
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+				Regular(Instruction::End),
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+				Regular(Instruction::End),
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_br_table = w_bench - 3 * w_param
+	// 1 * w_param + 0.5 * 2 * w_param + 0.25 * 4 * w_param
+	instr_br_table {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let table = Box::new(parity_wasm::elements::BrTableData {
+			table: Box::new([0, 1, 2]),
+			default: 1,
+		});
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				Regular(Instruction::Block(BlockType::NoResult)),
+				Regular(Instruction::Block(BlockType::NoResult)),
+				Regular(Instruction::Block(BlockType::NoResult)),
+				RandomI32(0, 4),
+				Regular(Instruction::BrTable(table)),
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+				Regular(Instruction::End),
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+				Regular(Instruction::End),
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+				Regular(Instruction::End),
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_br_table_per_entry = w_bench
+	instr_br_table_per_entry {
+		let e in 1 .. <CurrentSchedule<T>>::get().limits.br_table_size;
+		let entry: Vec<u32> = [0, 1].iter()
+			.cloned()
+			.cycle()
+			.take((e / 2) as usize).collect();
+		let table = Box::new(parity_wasm::elements::BrTableData {
+			table: entry.into_boxed_slice(),
+			default: 0,
+		});
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(body::repeated_dyn(INSTR_BENCHMARK_BATCH_SIZE, vec![
+				Regular(Instruction::Block(BlockType::NoResult)),
+				Regular(Instruction::Block(BlockType::NoResult)),
+				Regular(Instruction::Block(BlockType::NoResult)),
+				RandomI32(0, (e + 1) as i32), // Make sure the default entry is also used
+				Regular(Instruction::BrTable(table)),
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+				Regular(Instruction::End),
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+				Regular(Instruction::End),
+				RandomI64Repeated(1),
+				Regular(Instruction::Drop),
+				Regular(Instruction::End),
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_call = w_bench - 2 * w_param
+	instr_call {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			// We need to make use of the stack here in order to trigger stack height
+			// instrumentation.
+			aux_body: Some(body::plain(vec![
+				Instruction::I64Const(42),
+				Instruction::Drop,
+				Instruction::End,
+			])),
+			call_body: Some(body::repeated(r * INSTR_BENCHMARK_BATCH_SIZE, &[
+				Instruction::Call(2), // call aux
+			])),
+			inject_stack_metering: true,
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_call_indrect = w_bench - 3 * w_param
+	instr_call_indirect {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let num_elements = <CurrentSchedule<T>>::get().limits.table_size;
+		use self::code::TableSegment;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			// We need to make use of the stack here in order to trigger stack height
+			// instrumentation.
+			aux_body: Some(body::plain(vec![
+				Instruction::I64Const(42),
+				Instruction::Drop,
+				Instruction::End,
+			])),
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				RandomI32(0, num_elements as i32),
+				Regular(Instruction::CallIndirect(0, 0)), // we only have one sig: 0
+			])),
+			inject_stack_metering: true,
+			table: Some(TableSegment {
+				num_elements,
+				function_index: 2, // aux
+			}),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_instr_call_indirect_per_param = w_bench - 1 * w_param
+	// Calling a function indirectly causes it to go through a thunk function whose runtime
+	// linearly depend on the amount of parameters to this function.
+	// Please note that this is not necessary with a direct call.
+	instr_call_indirect_per_param {
+		let p in 0 .. <CurrentSchedule<T>>::get().limits.parameters;
+		let num_elements = <CurrentSchedule<T>>::get().limits.table_size;
+		use self::code::TableSegment;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			// We need to make use of the stack here in order to trigger stack height
+			// instrumentation.
+			aux_body: Some(body::plain(vec![
+				Instruction::I64Const(42),
+				Instruction::Drop,
+				Instruction::End,
+			])),
+			aux_arg_num: p,
+			call_body: Some(body::repeated_dyn(INSTR_BENCHMARK_BATCH_SIZE, vec![
+				RandomI64Repeated(p as usize),
+				RandomI32(0, num_elements as i32),
+				Regular(Instruction::CallIndirect(p.min(1), 0)), // aux signature: 1 or 0
+			])),
+			inject_stack_metering: true,
+			table: Some(TableSegment {
+				num_elements,
+				function_index: 2, // aux
+			}),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_local_get = w_bench - 1 * w_param
+	instr_local_get {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let max_locals = <CurrentSchedule<T>>::get().limits.stack_height;
+		let mut call_body = body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+			RandomGetLocal(0, max_locals),
+			Regular(Instruction::Drop),
+		]);
+		body::inject_locals(&mut call_body, max_locals);
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(call_body),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_local_set = w_bench - 1 * w_param
+	instr_local_set {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let max_locals = <CurrentSchedule<T>>::get().limits.stack_height;
+		let mut call_body = body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+			RandomI64Repeated(1),
+			RandomSetLocal(0, max_locals),
+		]);
+		body::inject_locals(&mut call_body, max_locals);
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(call_body),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_local_tee = w_bench - 2 * w_param
+	instr_local_tee {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let max_locals = <CurrentSchedule<T>>::get().limits.stack_height;
+		let mut call_body = body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+			RandomI64Repeated(1),
+			RandomTeeLocal(0, max_locals),
+			Regular(Instruction::Drop),
+		]);
+		body::inject_locals(&mut call_body, max_locals);
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(call_body),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_global_get = w_bench - 1 * w_param
+	instr_global_get {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let max_globals = <CurrentSchedule<T>>::get().limits.globals;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				RandomGetGlobal(0, max_globals),
+				Regular(Instruction::Drop),
+			])),
+			num_globals: max_globals,
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_global_set = w_bench - 1 * w_param
+	instr_global_set {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let max_globals = <CurrentSchedule<T>>::get().limits.globals;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				RandomI64Repeated(1),
+				RandomSetGlobal(0, max_globals),
+			])),
+			num_globals: max_globals,
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_memory_get = w_bench - 1 * w_param
+	instr_memory_current {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory::max::<T>()),
+			call_body: Some(body::repeated(r * INSTR_BENCHMARK_BATCH_SIZE, &[
+				Instruction::CurrentMemory(0),
+				Instruction::Drop
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// w_memory_grow = w_bench - 2 * w_param
+	// We can only allow allocate as much memory as it is allowed in a a contract.
+	// Therefore the repeat count is limited by the maximum memory any contract can have.
+	// Using a contract with more memory will skew the benchmark because the runtime of grow
+	// depends on how much memory is already allocated.
+	instr_memory_grow {
+		let r in 0 .. 1;
+		let max_pages = ImportedMemory::max::<T>().max_pages;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			memory: Some(ImportedMemory {
+				min_pages: 0,
+				max_pages,
+			}),
+			call_body: Some(body::repeated(r * max_pages, &[
+				Instruction::I32Const(1),
+				Instruction::GrowMemory(0),
+				Instruction::Drop,
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	// Unary numeric instructions.
+	// All use w = w_bench - 2 * w_param.
+
+	instr_i64clz {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::unary_instr(
+			Instruction::I64Clz,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64ctz {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::unary_instr(
+			Instruction::I64Ctz,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64popcnt {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::unary_instr(
+			Instruction::I64Popcnt,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64eqz {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::unary_instr(
+			Instruction::I64Eqz,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64extendsi32 {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				RandomI32Repeated(1),
+				Regular(Instruction::I64ExtendSI32),
+				Regular(Instruction::Drop),
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64extendui32 {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {
+			call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![
+				RandomI32Repeated(1),
+				Regular(Instruction::I64ExtendUI32),
+				Regular(Instruction::Drop),
+			])),
+			.. Default::default()
+		}));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i32wrapi64 {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::unary_instr(
+			Instruction::I32WrapI64,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	// Binary numeric instructions.
+	// All use w = w_bench - 3 * w_param.
+
+	instr_i64eq {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64Eq,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64ne {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64Ne,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64lts {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64LtS,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64ltu {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64LtU,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64gts {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64GtS,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64gtu {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64GtU,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64les {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64LeS,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64leu {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64LeU,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64ges {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64GeS,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64geu {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64GeU,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64add {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64Add,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64sub {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64Sub,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64mul {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64Mul,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64divs {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64DivS,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64divu {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64DivU,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64rems {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64RemS,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64remu {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64RemU,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64and {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64And,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64or {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64Or,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64xor {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64Xor,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64shl {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64Shl,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64shrs {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64ShrS,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64shru {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64ShrU,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64rotl {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64Rotl,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	instr_i64rotr {
+		let r in 0 .. INSTR_BENCHMARK_BATCHES;
+		let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(
+			Instruction::I64Rotr,
+			r * INSTR_BENCHMARK_BATCH_SIZE,
+		));
+	}: {
+		sbox.invoke();
+	}
+
+	// This is no benchmark. It merely exist to have an easy way to pretty print the curently
+	// configured `Schedule` during benchmark development.
+	// It can be outputed using the following command:
+	// cargo run --manifest-path=bin/node/cli/Cargo.toml --release \
+	//     --features runtime-benchmarks -- benchmark --dev --execution=native \
+	//     -p pallet_contracts -e print_schedule --no-median-slopes --no-min-squares
+	#[extra]
+	print_schedule {
+		#[cfg(feature = "std")]
+		{
+			let weight_per_key = T::WeightInfo::on_initialize_per_trie_key(1) -
+				T::WeightInfo::on_initialize_per_trie_key(0);
+			let weight_per_queue_item = T::WeightInfo::on_initialize_per_queue_item(1) -
+				T::WeightInfo::on_initialize_per_queue_item(0);
+			let weight_limit = T::DeletionWeightLimit::get();
+			let queue_depth: u64 = T::DeletionQueueDepth::get().into();
+			println!("{:#?}", Schedule::<T>::default());
+			println!("###############################################");
+			println!("Lazy deletion throughput per block (empty queue, full queue): {}, {}",
+				weight_limit / weight_per_key,
+				(weight_limit - weight_per_queue_item * queue_depth) / weight_per_key,
+			);
+		}
+		#[cfg(not(feature = "std"))]
+		return Err("Run this bench with a native runtime in order to see the schedule.");
+	}: {}
+}
+
+impl_benchmark_test_suite!(
+	Contracts,
+	crate::tests::ExtBuilder::default().build(),
+	crate::tests::Test,
+);
addedpallets/contracts/src/benchmarking/sandbox.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/benchmarking/sandbox.rs
@@ -0,0 +1,55 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+///! For instruction benchmarking we do no instantiate a full contract but merely the
+///! sandbox to execute the wasm code. This is because we do not need the full
+///! environment that provides the seal interface as imported functions.
+use super::{Config, code::WasmModule};
+use sp_core::crypto::UncheckedFrom;
+use sp_sandbox::{EnvironmentDefinitionBuilder, Instance, Memory};
+
+/// Minimal execution environment without any exported functions.
+pub struct Sandbox {
+	instance: Instance<()>,
+	_memory: Option<Memory>,
+}
+
+impl Sandbox {
+	/// Invoke the `call` function of a contract code and panic on any execution error.
+	pub fn invoke(&mut self) {
+		self.instance.invoke("call", &[], &mut ()).unwrap();
+	}
+}
+
+impl<T: Config> From<&WasmModule<T>> for Sandbox
+where
+	T: Config,
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+{
+	/// Creates an instance from the supplied module and supplies as much memory
+	/// to the instance as the module declares as imported.
+	fn from(module: &WasmModule<T>) -> Self {
+		let mut env_builder = EnvironmentDefinitionBuilder::new();
+		let memory = module.add_memory(&mut env_builder);
+		let instance = Instance::new(&module.code, &env_builder, &mut ())
+			.expect("Failed to create benchmarking Sandbox instance");
+		Self {
+			instance,
+			_memory: memory,
+		}
+	}
+}
addedpallets/contracts/src/chain_extension.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/chain_extension.rs
@@ -0,0 +1,400 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2020 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! A mechanism for runtime authors to augment the functionality of contracts.
+//!
+//! The runtime is able to call into any contract and retrieve the result using
+//! [`bare_call`](crate::Pallet::bare_call). This already allows customization of runtime
+//! behaviour by user generated code (contracts). However, often it is more straightforward
+//! to allow the reverse behaviour: The contract calls into the runtime. We call the latter
+//! one a "chain extension" because it allows the chain to extend the set of functions that are
+//! callable by a contract.
+//!
+//! In order to create a chain extension the runtime author implements the [`ChainExtension`]
+//! trait and declares it in this pallet's [configuration Trait](crate::Config). All types
+//! required for this endeavour are defined or re-exported in this module. There is an
+//! implementation on `()` which can be used to signal that no chain extension is available.
+//!
+//! # Security
+//!
+//! The chain author alone is responsible for the security of the chain extension.
+//! This includes avoiding the exposure of exploitable functions and charging the
+//! appropriate amount of weight. In order to do so benchmarks must be written and the
+//! [`charge_weight`](Environment::charge_weight) function must be called **before**
+//! carrying out any action that causes the consumption of the chargeable weight.
+//! It cannot be overstated how delicate of a process the creation of a chain extension
+//! is. Check whether using [`bare_call`](crate::Pallet::bare_call) suffices for the
+//! use case at hand.
+//!
+//! # Benchmarking
+//!
+//! The builtin contract callable functions that pallet-contracts provides all have
+//! benchmarks that determine the correct weight that an invocation of these functions
+//! induces. In order to be able to charge the correct weight for the functions defined
+//! by a chain extension benchmarks must be written, too. In the near future this crate
+//! will provide the means for easier creation of those specialized benchmarks.
+//!
+//! # Example
+//!
+//! The ink! repository maintains an
+//! [end-to-end example](https://github.com/paritytech/ink/tree/master/examples/rand-extension)
+//! on how to use a chain extension in order to provide new features to ink! contracts.
+
+use crate::{
+	Error,
+	wasm::{Runtime, RuntimeToken},
+};
+use codec::Decode;
+use frame_support::weights::Weight;
+use sp_runtime::DispatchError;
+use sp_std::{marker::PhantomData, vec::Vec};
+
+pub use frame_system::Config as SysConfig;
+pub use pallet_contracts_primitives::ReturnFlags;
+pub use sp_core::crypto::UncheckedFrom;
+pub use crate::{Config, exec::Ext};
+pub use state::Init as InitState;
+
+/// Result that returns a [`DispatchError`] on error.
+pub type Result<T> = sp_std::result::Result<T, DispatchError>;
+
+/// A trait used to extend the set of contract callable functions.
+///
+/// In order to create a custom chain extension this trait must be implemented and supplied
+/// to the pallet contracts configuration trait as the associated type of the same name.
+/// Consult the [module documentation](self) for a general explanation of chain extensions.
+pub trait ChainExtension<C: Config> {
+	/// Call the chain extension logic.
+	///
+	/// This is the only function that needs to be implemented in order to write a
+	/// chain extensions. It is called whenever a contract calls the `seal_call_chain_extension`
+	/// imported wasm function.
+	///
+	/// # Parameters
+	/// - `func_id`: The first argument to `seal_call_chain_extension`. Usually used to
+	///		determine which function to realize.
+	/// - `env`: Access to the remaining arguments and the execution environment.
+	///
+	/// # Return
+	///
+	/// In case of `Err` the contract execution is immediately suspended and the passed error
+	/// is returned to the caller. Otherwise the value of [`RetVal`] determines the exit
+	/// behaviour.
+	fn call<E>(func_id: u32, env: Environment<E, InitState>) -> Result<RetVal>
+	where
+		E: Ext<T = C>,
+		<E::T as SysConfig>::AccountId: UncheckedFrom<<E::T as SysConfig>::Hash> + AsRef<[u8]>;
+
+	/// Determines whether chain extensions are enabled for this chain.
+	///
+	/// The default implementation returns `true`. Therefore it is not necessary to overwrite
+	/// this function when implementing a chain extension. In case of `false` the deployment of
+	/// a contract that references `seal_call_chain_extension` will be denied and calling this
+	/// function will return [`NoChainExtension`](Error::NoChainExtension) without first calling
+	/// into [`call`](Self::call).
+	fn enabled() -> bool {
+		true
+	}
+}
+
+/// Implementation that indicates that no chain extension is available.
+impl<C: Config> ChainExtension<C> for () {
+	fn call<E>(_func_id: u32, mut _env: Environment<E, InitState>) -> Result<RetVal>
+	where
+		E: Ext<T = C>,
+		<E::T as SysConfig>::AccountId: UncheckedFrom<<E::T as SysConfig>::Hash> + AsRef<[u8]>,
+	{
+		// Never called since [`Self::enabled()`] is set to `false`. Because we want to
+		// avoid panics at all costs we supply a sensible error value here instead
+		// of an `unimplemented!`.
+		Err(Error::<E::T>::NoChainExtension.into())
+	}
+
+	fn enabled() -> bool {
+		false
+	}
+}
+
+/// Determines the exit behaviour and return value of a chain extension.
+pub enum RetVal {
+	/// The chain extensions returns the supplied value to its calling contract.
+	Converging(u32),
+	/// The control does **not** return to the calling contract.
+	///
+	/// Use this to stop the execution of the contract when the chain extension returns.
+	/// The semantic is the same as for calling `seal_return`: The control returns to
+	/// the caller of the currently executing contract yielding the supplied buffer and
+	/// flags.
+	Diverging { flags: ReturnFlags, data: Vec<u8> },
+}
+
+/// Grants the chain extension access to its parameters and execution environment.
+///
+/// It uses [typestate programming](https://docs.rust-embedded.org/book/static-guarantees/typestate-programming.html)
+/// to enforce the correct usage of the parameters passed to the chain extension.
+pub struct Environment<'a, 'b, E: Ext, S: state::State> {
+	/// The actual data of this type.
+	inner: Inner<'a, 'b, E>,
+	/// `S` is only used in the type system but never as value.
+	phantom: PhantomData<S>,
+}
+
+/// Functions that are available in every state of this type.
+impl<'a, 'b, E: Ext, S: state::State> Environment<'a, 'b, E, S>
+where
+	<E::T as SysConfig>::AccountId: UncheckedFrom<<E::T as SysConfig>::Hash> + AsRef<[u8]>,
+{
+	/// Charge the passed `amount` of weight from the overall limit.
+	///
+	/// It returns `Ok` when there the remaining weight budget is larger than the passed
+	/// `weight`. It returns `Err` otherwise. In this case the chain extension should
+	/// abort the execution and pass through the error.
+	///
+	/// # Note
+	///
+	/// Weight is synonymous with gas in substrate.
+	pub fn charge_weight(&mut self, amount: Weight) -> Result<()> {
+		self.inner
+			.runtime
+			.charge_gas(RuntimeToken::ChainExtension(amount))
+			.map(|_| ())
+	}
+
+	/// Grants access to the execution environment of the current contract call.
+	///
+	/// Consult the functions on the returned type before re-implementing those functions.
+	pub fn ext(&mut self) -> &mut E {
+		self.inner.runtime.ext()
+	}
+}
+
+/// Functions that are only available in the initial state of this type.
+///
+/// Those are the functions that determine how the arguments to the chain extensions
+/// should be consumed.
+impl<'a, 'b, E: Ext> Environment<'a, 'b, E, state::Init> {
+	/// Creates a new environment for consumption by a chain extension.
+	///
+	/// It is only available to this crate because only the wasm runtime module needs to
+	/// ever create this type. Chain extensions merely consume it.
+	pub(crate) fn new(
+		runtime: &'a mut Runtime<'b, E>,
+		input_ptr: u32,
+		input_len: u32,
+		output_ptr: u32,
+		output_len_ptr: u32,
+	) -> Self {
+		Environment {
+			inner: Inner {
+				runtime,
+				input_ptr,
+				input_len,
+				output_ptr,
+				output_len_ptr,
+			},
+			phantom: PhantomData,
+		}
+	}
+
+	/// Use all arguments as integer values.
+	pub fn only_in(self) -> Environment<'a, 'b, E, state::OnlyIn> {
+		Environment {
+			inner: self.inner,
+			phantom: PhantomData,
+		}
+	}
+
+	/// Use input arguments as integer and output arguments as pointer to a buffer.
+	pub fn prim_in_buf_out(self) -> Environment<'a, 'b, E, state::PrimInBufOut> {
+		Environment {
+			inner: self.inner,
+			phantom: PhantomData,
+		}
+	}
+
+	/// Use input and output arguments as pointers to a buffer.
+	pub fn buf_in_buf_out(self) -> Environment<'a, 'b, E, state::BufInBufOut> {
+		Environment {
+			inner: self.inner,
+			phantom: PhantomData,
+		}
+	}
+}
+
+/// Functions to use the input arguments as integers.
+impl<'a, 'b, E: Ext, S: state::PrimIn> Environment<'a, 'b, E, S> {
+	/// The `input_ptr` argument.
+	pub fn val0(&self) -> u32 {
+		self.inner.input_ptr
+	}
+
+	/// The `input_len` argument.
+	pub fn val1(&self) -> u32 {
+		self.inner.input_len
+	}
+}
+
+/// Functions to use the output arguments as integers.
+impl<'a, 'b, E: Ext, S: state::PrimOut> Environment<'a, 'b, E, S> {
+	/// The `output_ptr` argument.
+	pub fn val2(&self) -> u32 {
+		self.inner.output_ptr
+	}
+
+	/// The `output_len_ptr` argument.
+	pub fn val3(&self) -> u32 {
+		self.inner.output_len_ptr
+	}
+}
+
+/// Functions to use the input arguments as pointer to a buffer.
+impl<'a, 'b, E: Ext, S: state::BufIn> Environment<'a, 'b, E, S>
+where
+	<E::T as SysConfig>::AccountId: UncheckedFrom<<E::T as SysConfig>::Hash> + AsRef<[u8]>,
+{
+	/// Reads `min(max_len, in_len)` from contract memory.
+	///
+	/// This does **not** charge any weight. The caller must make sure that the an
+	/// appropriate amount of weight is charged **before** reading from contract memory.
+	/// The reason for that is that usually the costs for reading data and processing
+	/// said data cannot be separated in a benchmark. Therefore a chain extension would
+	/// charge the overall costs either using `max_len` (worst case approximation) or using
+	/// [`in_len()`](Self::in_len).
+	pub fn read(&self, max_len: u32) -> Result<Vec<u8>> {
+		self.inner
+			.runtime
+			.read_sandbox_memory(self.inner.input_ptr, self.inner.input_len.min(max_len))
+	}
+
+	/// Reads `min(buffer.len(), in_len) from contract memory.
+	///
+	/// This takes a mutable pointer to a buffer fills it with data and shrinks it to
+	/// the size of the actual data. Apart from supporting pre-allocated buffers it is
+	/// equivalent to to [`read()`](Self::read).
+	pub fn read_into(&self, buffer: &mut &mut [u8]) -> Result<()> {
+		let len = buffer.len();
+		let sliced = {
+			let buffer = core::mem::take(buffer);
+			&mut buffer[..len.min(self.inner.input_len as usize)]
+		};
+		self.inner
+			.runtime
+			.read_sandbox_memory_into_buf(self.inner.input_ptr, sliced)?;
+		*buffer = sliced;
+		Ok(())
+	}
+
+	/// Reads `in_len` from contract memory and scale decodes it.
+	///
+	/// This function is secure and recommended for all input types of fixed size
+	/// as long as the cost of reading the memory is included in the overall already charged
+	/// weight of the chain extension. This should usually be the case when fixed input types
+	/// are used. Non fixed size types (like everything using `Vec`) usually need to use
+	/// [`in_len()`](Self::in_len) in order to properly charge the necessary weight.
+	pub fn read_as<T: Decode>(&mut self) -> Result<T> {
+		self.inner
+			.runtime
+			.read_sandbox_memory_as(self.inner.input_ptr, self.inner.input_len)
+	}
+
+	/// The length of the input as passed in as `input_len`.
+	///
+	/// A chain extension would use this value to calculate the dynamic part of its
+	/// weight. For example a chain extension that calculates the hash of some passed in
+	/// bytes would use `in_len` to charge the costs of hashing that amount of bytes.
+	/// This also subsumes the act of copying those bytes as a benchmarks measures both.
+	pub fn in_len(&self) -> u32 {
+		self.inner.input_len
+	}
+}
+
+/// Functions to use the output arguments as pointer to a buffer.
+impl<'a, 'b, E: Ext, S: state::BufOut> Environment<'a, 'b, E, S>
+where
+	<E::T as SysConfig>::AccountId: UncheckedFrom<<E::T as SysConfig>::Hash> + AsRef<[u8]>,
+{
+	/// Write the supplied buffer to contract memory.
+	///
+	/// If the contract supplied buffer is smaller than the passed `buffer` an `Err` is returned.
+	/// If `allow_skip` is set to true the contract is allowed to skip the copying of the buffer
+	/// by supplying the guard value of `u32::max_value()` as `out_ptr`. The
+	/// `weight_per_byte` is only charged when the write actually happens and is not skipped or
+	/// failed due to a too small output buffer.
+	pub fn write(
+		&mut self,
+		buffer: &[u8],
+		allow_skip: bool,
+		weight_per_byte: Option<Weight>,
+	) -> Result<()> {
+		self.inner.runtime.write_sandbox_output(
+			self.inner.output_ptr,
+			self.inner.output_len_ptr,
+			buffer,
+			allow_skip,
+			|len| {
+				weight_per_byte.map(|w| RuntimeToken::ChainExtension(w.saturating_mul(len.into())))
+			},
+		)
+	}
+}
+
+/// The actual data of an `Environment`.
+///
+/// All data is put into this struct to easily pass it around as part of the typestate
+/// pattern. Also it creates the opportunity to box this struct in the future in case it
+/// gets too large.
+struct Inner<'a, 'b, E: Ext> {
+	/// The runtime contains all necessary functions to interact with the running contract.
+	runtime: &'a mut Runtime<'b, E>,
+	/// Verbatim argument passed to `seal_call_chain_extension`.
+	input_ptr: u32,
+	/// Verbatim argument passed to `seal_call_chain_extension`.
+	input_len: u32,
+	/// Verbatim argument passed to `seal_call_chain_extension`.
+	output_ptr: u32,
+	/// Verbatim argument passed to `seal_call_chain_extension`.
+	output_len_ptr: u32,
+}
+
+/// Private submodule with public types to prevent other modules from naming them.
+mod state {
+	pub trait State {}
+
+	pub trait PrimIn: State {}
+	pub trait PrimOut: State {}
+	pub trait BufIn: State {}
+	pub trait BufOut: State {}
+
+	/// The initial state of an [`Environment`](`super::Environment`).
+	/// See [typestate programming](https://docs.rust-embedded.org/book/static-guarantees/typestate-programming.html).
+	pub enum Init {}
+	pub enum OnlyIn {}
+	pub enum PrimInBufOut {}
+	pub enum BufInBufOut {}
+
+	impl State for Init {}
+	impl State for OnlyIn {}
+	impl State for PrimInBufOut {}
+	impl State for BufInBufOut {}
+
+	impl PrimIn for OnlyIn {}
+	impl PrimOut for OnlyIn {}
+	impl PrimIn for PrimInBufOut {}
+	impl BufOut for PrimInBufOut {}
+	impl BufIn for BufInBufOut {}
+	impl BufOut for BufInBufOut {}
+}
addedpallets/contracts/src/exec.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/exec.rs
@@ -0,0 +1,1836 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::{
+	CodeHash, Event, Config, Pallet as Contracts, TrieId, BalanceOf, ContractInfo,
+	gas::GasMeter,
+	rent::Rent,
+	storage::{self, Storage},
+	Error, ContractInfoOf, Schedule, AliveContractInfo,
+};
+use sp_core::crypto::UncheckedFrom;
+use sp_std::{prelude::*, marker::PhantomData};
+use sp_runtime::{
+	Perbill,
+	traits::{Bounded, Zero, Convert, Saturating},
+};
+use frame_support::{
+	dispatch::{DispatchResult, DispatchError},
+	traits::{ExistenceRequirement, Currency, Time, Randomness, Get},
+	weights::Weight,
+	ensure,
+};
+use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags};
+
+pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
+pub type MomentOf<T> = <<T as Config>::Time as Time>::Moment;
+pub type SeedOf<T> = <T as frame_system::Config>::Hash;
+pub type BlockNumberOf<T> = <T as frame_system::Config>::BlockNumber;
+pub type StorageKey = [u8; 32];
+pub type ExecResult = Result<ExecReturnValue, ExecError>;
+
+/// A type that represents a topic of an event. At the moment a hash is used.
+pub type TopicOf<T> = <T as frame_system::Config>::Hash;
+
+/// Origin of the error.
+///
+/// Call or instantiate both called into other contracts and pass through errors happening
+/// in those to the caller. This enum is for the caller to distinguish whether the error
+/// happened during the execution of the callee or in the current execution context.
+#[cfg_attr(test, derive(Debug, PartialEq))]
+pub enum ErrorOrigin {
+	/// Caller error origin.
+	///
+	/// The error happened in the current exeuction context rather than in the one
+	/// of the contract that is called into.
+	Caller,
+	/// The error happened during execution of the called contract.
+	Callee,
+}
+
+/// Error returned by contract exection.
+#[cfg_attr(test, derive(Debug, PartialEq))]
+pub struct ExecError {
+	/// The reason why the execution failed.
+	pub error: DispatchError,
+	/// Origin of the error.
+	pub origin: ErrorOrigin,
+}
+
+impl<T: Into<DispatchError>> From<T> for ExecError {
+	fn from(error: T) -> Self {
+		Self {
+			error: error.into(),
+			origin: ErrorOrigin::Caller,
+		}
+	}
+}
+
+/// Information needed for rent calculations that can be requested by a contract.
+#[derive(codec::Encode)]
+#[cfg_attr(test, derive(Debug, PartialEq))]
+pub struct RentParams<T: Config> {
+	/// The total balance of the contract. Includes the balance transferred from the caller.
+	total_balance: BalanceOf<T>,
+	/// The free balance of the contract. Includes the balance transferred from the caller.
+	free_balance: BalanceOf<T>,
+	/// See crate [`Contracts::subsistence_threshold()`].
+	subsistence_threshold: BalanceOf<T>,
+	/// See crate [`Config::DepositPerContract`].
+	deposit_per_contract: BalanceOf<T>,
+	/// See crate [`Config::DepositPerStorageByte`].
+	deposit_per_storage_byte: BalanceOf<T>,
+	/// See crate [`Config::DepositPerStorageItem`].
+	deposit_per_storage_item: BalanceOf<T>,
+	/// See crate [`Ext::rent_allowance()`].
+	rent_allowance: BalanceOf<T>,
+	/// See crate [`Config::RentFraction`].
+	rent_fraction: Perbill,
+	/// See crate [`AliveContractInfo::storage_size`].
+	storage_size: u32,
+	/// See crate [`Executable::aggregate_code_len()`].
+	code_size: u32,
+	/// See crate [`Executable::refcount()`].
+	code_refcount: u32,
+	/// Reserved for backwards compatible changes to this data structure.
+	_reserved: Option<()>,
+}
+
+impl<T> RentParams<T>
+where
+	T: Config,
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+{
+	fn new<E: Executable<T>>(
+		account_id: &T::AccountId,
+		contract: &AliveContractInfo<T>,
+		executable: &E,
+	) -> Self {
+		Self {
+			total_balance: T::Currency::total_balance(account_id),
+			free_balance: T::Currency::free_balance(account_id),
+			subsistence_threshold: <Contracts<T>>::subsistence_threshold(),
+			deposit_per_contract: T::DepositPerContract::get(),
+			deposit_per_storage_byte: T::DepositPerStorageByte::get(),
+			deposit_per_storage_item: T::DepositPerStorageItem::get(),
+			rent_allowance: contract.rent_allowance,
+			rent_fraction: T::RentFraction::get(),
+			storage_size: contract.storage_size,
+			code_size: executable.aggregate_code_len(),
+			code_refcount: executable.refcount(),
+			_reserved: None,
+		}
+	}
+}
+
+/// We cannot derive `Default` because `T` does not necessarily implement `Default`.
+#[cfg(test)]
+impl<T: Config> Default for RentParams<T> {
+	fn default() -> Self {
+		Self {
+			total_balance: Default::default(),
+			free_balance: Default::default(),
+			subsistence_threshold: Default::default(),
+			deposit_per_contract: Default::default(),
+			deposit_per_storage_byte: Default::default(),
+			deposit_per_storage_item: Default::default(),
+			rent_allowance: Default::default(),
+			rent_fraction: Default::default(),
+			storage_size: Default::default(),
+			code_size: Default::default(),
+			code_refcount: Default::default(),
+			_reserved: Default::default(),
+		}
+	}
+}
+
+/// An interface that provides access to the external environment in which the
+/// smart-contract is executed.
+///
+/// This interface is specialized to an account of the executing code, so all
+/// operations are implicitly performed on that account.
+///
+/// # Note
+///
+/// This trait is sealed and cannot be implemented by downstream crates.
+pub trait Ext: sealing::Sealed {
+	type T: Config;
+
+	/// Returns the storage entry of the executing account by the given `key`.
+	///
+	/// Returns `None` if the `key` wasn't previously set by `set_storage` or
+	/// was deleted.
+	fn get_storage(&self, key: &StorageKey) -> Option<Vec<u8>>;
+
+	/// Sets the storage entry by the given key to the specified value. If `value` is `None` then
+	/// the storage entry is deleted.
+	fn set_storage(&mut self, key: StorageKey, value: Option<Vec<u8>>) -> DispatchResult;
+
+	/// Instantiate a contract from the given code.
+	///
+	/// Returns the original code size of the called contract.
+	/// The newly created account will be associated with `code`. `value` specifies the amount of value
+	/// transferred from this to the newly created account (also known as endowment).
+	///
+	/// # Return Value
+	///
+	/// Result<(AccountId, ExecReturnValue, CodeSize), (ExecError, CodeSize)>
+	fn instantiate(
+		&mut self,
+		code: CodeHash<Self::T>,
+		value: BalanceOf<Self::T>,
+		gas_meter: &mut GasMeter<Self::T>,
+		input_data: Vec<u8>,
+		salt: &[u8],
+	) -> Result<(AccountIdOf<Self::T>, ExecReturnValue, u32), (ExecError, u32)>;
+
+	/// Transfer some amount of funds into the specified account.
+	fn transfer(&mut self, to: &AccountIdOf<Self::T>, value: BalanceOf<Self::T>) -> DispatchResult;
+
+	/// Transfer all funds to `beneficiary` and delete the contract.
+	///
+	/// Returns the original code size of the terminated contract.
+	/// Since this function removes the self contract eagerly, if succeeded, no further actions should
+	/// be performed on this `Ext` instance.
+	///
+	/// This function will fail if the same contract is present on the contract
+	/// call stack.
+	///
+	/// # Return Value
+	///
+	/// Result<CodeSize, (DispatchError, CodeSize)>
+	fn terminate(
+		&mut self,
+		beneficiary: &AccountIdOf<Self::T>,
+	) -> Result<u32, (DispatchError, u32)>;
+
+	/// Call (possibly transferring some amount of funds) into the specified account.
+	///
+	/// Returns the original code size of the called contract.
+	///
+	/// # Return Value
+	///
+	/// Result<(ExecReturnValue, CodeSize), (ExecError, CodeSize)>
+	fn call(
+		&mut self,
+		to: &AccountIdOf<Self::T>,
+		value: BalanceOf<Self::T>,
+		gas_meter: &mut GasMeter<Self::T>,
+		input_data: Vec<u8>,
+	) -> Result<(ExecReturnValue, u32), (ExecError, u32)>;
+
+	/// Restores the given destination contract sacrificing the current one.
+	///
+	/// Since this function removes the self contract eagerly, if succeeded, no further actions should
+	/// be performed on this `Ext` instance.
+	///
+	/// This function will fail if the same contract is present
+	/// on the contract call stack.
+	///
+	/// # Return Value
+	///
+	/// Result<(CallerCodeSize, DestCodeSize), (DispatchError, CallerCodeSize, DestCodesize)>
+	fn restore_to(
+		&mut self,
+		dest: AccountIdOf<Self::T>,
+		code_hash: CodeHash<Self::T>,
+		rent_allowance: BalanceOf<Self::T>,
+		delta: Vec<StorageKey>,
+	) -> Result<(u32, u32), (DispatchError, u32, u32)>;
+
+	/// Returns a reference to the account id of the caller.
+	fn caller(&self) -> &AccountIdOf<Self::T>;
+
+	/// Returns a reference to the account id of the current contract.
+	fn address(&self) -> &AccountIdOf<Self::T>;
+
+	/// Returns the balance of the current contract.
+	///
+	/// The `value_transferred` is already added.
+	fn balance(&self) -> BalanceOf<Self::T>;
+
+	/// Returns the value transferred along with this call or as endowment.
+	fn value_transferred(&self) -> BalanceOf<Self::T>;
+
+	/// Returns a reference to the timestamp of the current block
+	fn now(&self) -> &MomentOf<Self::T>;
+
+	/// Returns the minimum balance that is required for creating an account.
+	fn minimum_balance(&self) -> BalanceOf<Self::T>;
+
+	/// Returns the deposit required to create a tombstone upon contract eviction.
+	fn tombstone_deposit(&self) -> BalanceOf<Self::T>;
+
+	/// Returns a random number for the current block with the given subject.
+	fn random(&self, subject: &[u8]) -> (SeedOf<Self::T>, BlockNumberOf<Self::T>);
+
+	/// Deposit an event with the given topics.
+	///
+	/// There should not be any duplicates in `topics`.
+	fn deposit_event(&mut self, topics: Vec<TopicOf<Self::T>>, data: Vec<u8>);
+
+	/// Set rent allowance of the contract
+	fn set_rent_allowance(&mut self, rent_allowance: BalanceOf<Self::T>);
+
+	/// Rent allowance of the contract
+	fn rent_allowance(&self) -> BalanceOf<Self::T>;
+
+	/// Returns the current block number.
+	fn block_number(&self) -> BlockNumberOf<Self::T>;
+
+	/// Returns the maximum allowed size of a storage item.
+	fn max_value_size(&self) -> u32;
+
+	/// Returns the price for the specified amount of weight.
+	fn get_weight_price(&self, weight: Weight) -> BalanceOf<Self::T>;
+
+	/// Get a reference to the schedule used by the current call.
+	fn schedule(&self) -> &Schedule<Self::T>;
+
+	/// Information needed for rent calculations.
+	fn rent_params(&self) -> &RentParams<Self::T>;
+}
+
+/// Describes the different functions that can be exported by an [`Executable`].
+#[cfg_attr(test, derive(Clone, Copy, PartialEq))]
+pub enum ExportedFunction {
+	/// The constructor function which is executed on deployment of a contract.
+	Constructor,
+	/// The function which is executed when a contract is called.
+	Call,
+}
+
+/// A trait that represents something that can be executed.
+///
+/// In the on-chain environment this would be represented by a wasm module. This trait exists in
+/// order to be able to mock the wasm logic for testing.
+pub trait Executable<T: Config>: Sized {
+	/// Load the executable from storage.
+	fn from_storage(
+		code_hash: CodeHash<T>,
+		schedule: &Schedule<T>,
+		gas_meter: &mut GasMeter<T>,
+	) -> Result<Self, DispatchError>;
+
+	/// Load the module from storage without re-instrumenting it.
+	///
+	/// A code module is re-instrumented on-load when it was originally instrumented with
+	/// an older schedule. This skips this step for cases where the code storage is
+	/// queried for purposes other than execution.
+	fn from_storage_noinstr(code_hash: CodeHash<T>) -> Result<Self, DispatchError>;
+
+	/// Decrements the refcount by one and deletes the code if it drops to zero.
+	fn drop_from_storage(self);
+
+	/// Increment the refcount by one. Fails if the code does not exist on-chain.
+	///
+	/// Returns the size of the original code.
+	fn add_user(code_hash: CodeHash<T>) -> Result<u32, DispatchError>;
+
+	/// Decrement the refcount by one and remove the code when it drops to zero.
+	///
+	/// Returns the size of the original code.
+	fn remove_user(code_hash: CodeHash<T>) -> u32;
+
+	/// Execute the specified exported function and return the result.
+	///
+	/// When the specified function is `Constructor` the executable is stored and its
+	/// refcount incremented.
+	///
+	/// # Note
+	///
+	/// This functions expects to be executed in a storage transaction that rolls back
+	/// all of its emitted storage changes.
+	fn execute<E: Ext<T = T>>(
+		self,
+		ext: E,
+		function: &ExportedFunction,
+		input_data: Vec<u8>,
+		gas_meter: &mut GasMeter<T>,
+	) -> ExecResult;
+
+	/// The code hash of the executable.
+	fn code_hash(&self) -> &CodeHash<T>;
+
+	/// The storage that is occupied by the instrumented executable and its pristine source.
+	///
+	/// The returned size is already divided by the number of users who share the code.
+	/// This is essentially `aggregate_code_len() / refcount()`.
+	///
+	/// # Note
+	///
+	/// This works with the current in-memory value of refcount. When calling any contract
+	/// without refetching this from storage the result can be inaccurate as it might be
+	/// working with a stale value. Usually this inaccuracy is tolerable.
+	fn occupied_storage(&self) -> u32;
+
+	/// Size of the instrumented code in bytes.
+	fn code_len(&self) -> u32;
+
+	/// Sum of instrumented and pristine code len.
+	fn aggregate_code_len(&self) -> u32;
+
+	// The number of contracts using this executable.
+	fn refcount(&self) -> u32;
+}
+
+pub struct ExecutionContext<'a, T: Config + 'a, E> {
+	caller: Option<&'a ExecutionContext<'a, T, E>>,
+	self_account: T::AccountId,
+	self_trie_id: Option<TrieId>,
+	depth: usize,
+	schedule: &'a Schedule<T>,
+	timestamp: MomentOf<T>,
+	block_number: T::BlockNumber,
+	_phantom: PhantomData<E>,
+}
+
+impl<'a, T, E> ExecutionContext<'a, T, E>
+where
+	T: Config,
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+	E: Executable<T>,
+{
+	/// Create the top level execution context.
+	///
+	/// The specified `origin` address will be used as `sender` for. The `origin` must be a regular
+	/// account (not a contract).
+	pub fn top_level(origin: T::AccountId, schedule: &'a Schedule<T>) -> Self {
+		ExecutionContext {
+			caller: None,
+			self_trie_id: None,
+			self_account: origin,
+			depth: 0,
+			schedule,
+			timestamp: T::Time::now(),
+			block_number: <frame_system::Pallet<T>>::block_number(),
+			_phantom: Default::default(),
+		}
+	}
+
+	fn nested<'b, 'c: 'b>(
+		&'c self,
+		dest: T::AccountId,
+		trie_id: TrieId,
+	) -> ExecutionContext<'b, T, E> {
+		ExecutionContext {
+			caller: Some(self),
+			self_trie_id: Some(trie_id),
+			self_account: dest,
+			depth: self.depth + 1,
+			schedule: self.schedule,
+			timestamp: self.timestamp.clone(),
+			block_number: self.block_number.clone(),
+			_phantom: Default::default(),
+		}
+	}
+
+	/// Make a call to the specified address, optionally transferring some funds.
+	///
+	/// # Return Value
+	///
+	/// Result<(ExecReturnValue, CodeSize), (ExecError, CodeSize)>
+	pub fn call(
+		&mut self,
+		dest: T::AccountId,
+		value: BalanceOf<T>,
+		gas_meter: &mut GasMeter<T>,
+		input_data: Vec<u8>,
+	) -> Result<(ExecReturnValue, u32), (ExecError, u32)> {
+		if self.depth == T::MaxDepth::get() as usize {
+			return Err((Error::<T>::MaxCallDepthReached.into(), 0));
+		}
+
+		let contract = <ContractInfoOf<T>>::get(&dest)
+			.and_then(|contract| contract.get_alive())
+			.ok_or((Error::<T>::NotCallable.into(), 0))?;
+
+		let executable = E::from_storage(contract.code_hash, &self.schedule, gas_meter)
+			.map_err(|e| (e.into(), 0))?;
+		let code_len = executable.code_len();
+
+		// This charges the rent and denies access to a contract that is in need of
+		// eviction by returning `None`. We cannot evict eagerly here because those
+		// changes would be rolled back in case this contract is called by another
+		// contract.
+		// See: https://github.com/paritytech/substrate/issues/6439#issuecomment-648754324
+		let contract = Rent::<T, E>::charge(&dest, contract, executable.occupied_storage())
+			.map_err(|e| (e.into(), code_len))?
+			.ok_or((Error::<T>::NotCallable.into(), code_len))?;
+
+		let transactor_kind = self.transactor_kind();
+		let caller = self.self_account.clone();
+
+		let result = self
+			.with_nested_context(dest.clone(), contract.trie_id.clone(), |nested| {
+				if value > BalanceOf::<T>::zero() {
+					transfer::<T>(TransferCause::Call, transactor_kind, &caller, &dest, value)?
+				}
+
+				let call_context =
+					nested.new_call_context(caller, &dest, value, &contract, &executable);
+
+				let output = executable
+					.execute(call_context, &ExportedFunction::Call, input_data, gas_meter)
+					.map_err(|e| ExecError {
+						error: e.error,
+						origin: ErrorOrigin::Callee,
+					})?;
+				Ok(output)
+			})
+			.map_err(|e| (e, code_len))?;
+		Ok((result, code_len))
+	}
+
+	pub fn instantiate(
+		&mut self,
+		endowment: BalanceOf<T>,
+		gas_meter: &mut GasMeter<T>,
+		executable: E,
+		input_data: Vec<u8>,
+		salt: &[u8],
+	) -> Result<(T::AccountId, ExecReturnValue), ExecError> {
+		if self.depth == T::MaxDepth::get() as usize {
+			Err(Error::<T>::MaxCallDepthReached)?
+		}
+
+		let transactor_kind = self.transactor_kind();
+		let caller = self.self_account.clone();
+		let dest = Contracts::<T>::contract_address(&caller, executable.code_hash(), salt);
+
+		let output = frame_support::storage::with_transaction(|| {
+			// Generate the trie id in a new transaction to only increment the counter on success.
+			let dest_trie_id = Storage::<T>::generate_trie_id(&dest);
+
+			let output = self.with_nested_context(dest.clone(), dest_trie_id, |nested| {
+				let contract = Storage::<T>::place_contract(
+					&dest,
+					nested
+						.self_trie_id
+						.clone()
+						.expect("the nested context always has to have self_trie_id"),
+					executable.code_hash().clone(),
+				)?;
+
+				// Send funds unconditionally here. If the `endowment` is below existential_deposit
+				// then error will be returned here.
+				transfer::<T>(
+					TransferCause::Instantiate,
+					transactor_kind,
+					&caller,
+					&dest,
+					endowment,
+				)?;
+
+				// Cache the value before calling into the constructor because that
+				// consumes the value. If the constructor creates additional contracts using
+				// the same code hash we still charge the "1 block rent" as if they weren't
+				// spawned. This is OK as overcharging is always safe.
+				let occupied_storage = executable.occupied_storage();
+
+				let call_context = nested.new_call_context(
+					caller.clone(),
+					&dest,
+					endowment,
+					&contract,
+					&executable,
+				);
+
+				let output = executable
+					.execute(
+						call_context,
+						&ExportedFunction::Constructor,
+						input_data,
+						gas_meter,
+					)
+					.map_err(|e| ExecError {
+						error: e.error,
+						origin: ErrorOrigin::Callee,
+					})?;
+
+				// We need to re-fetch the contract because changes are written to storage
+				// eagerly during execution.
+				let contract = <ContractInfoOf<T>>::get(&dest)
+					.and_then(|contract| contract.get_alive())
+					.ok_or(Error::<T>::NotCallable)?;
+
+				// Collect the rent for the first block to prevent the creation of very large
+				// contracts that never intended to pay for even one block.
+				// This also makes sure that it is above the subsistence threshold
+				// in order to keep up the guarantuee that we always leave a tombstone behind
+				// with the exception of a contract that called `seal_terminate`.
+				Rent::<T, E>::charge(&dest, contract, occupied_storage)?
+					.ok_or(Error::<T>::NewContractNotFunded)?;
+
+				// Deposit an instantiation event.
+				deposit_event::<T>(vec![], Event::Instantiated(caller.clone(), dest.clone()));
+
+				Ok(output)
+			});
+
+			use frame_support::storage::TransactionOutcome::*;
+			match output {
+				Ok(_) => Commit(output),
+				Err(_) => Rollback(output),
+			}
+		})?;
+
+		Ok((dest, output))
+	}
+
+	fn new_call_context<'b>(
+		&'b mut self,
+		caller: T::AccountId,
+		dest: &T::AccountId,
+		value: BalanceOf<T>,
+		contract: &AliveContractInfo<T>,
+		executable: &E,
+	) -> CallContext<'b, 'a, T, E> {
+		let timestamp = self.timestamp.clone();
+		let block_number = self.block_number.clone();
+		CallContext {
+			ctx: self,
+			caller,
+			value_transferred: value,
+			timestamp,
+			block_number,
+			rent_params: RentParams::new(dest, contract, executable),
+			_phantom: Default::default(),
+		}
+	}
+
+	/// Execute the given closure within a nested execution context.
+	fn with_nested_context<F>(&mut self, dest: T::AccountId, trie_id: TrieId, func: F) -> ExecResult
+	where
+		F: FnOnce(&mut ExecutionContext<T, E>) -> ExecResult,
+	{
+		use frame_support::storage::TransactionOutcome::*;
+		let mut nested = self.nested(dest, trie_id);
+		frame_support::storage::with_transaction(|| {
+			let output = func(&mut nested);
+			match output {
+				Ok(ref rv) if !rv.flags.contains(ReturnFlags::REVERT) => Commit(output),
+				_ => Rollback(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.caller.map_or(false, |caller| caller.is_live(account))
+	}
+
+	fn transactor_kind(&self) -> TransactorKind {
+		if self.depth == 0 {
+			debug_assert!(self.self_trie_id.is_none());
+			debug_assert!(self.caller.is_none());
+			debug_assert!(ContractInfoOf::<T>::get(&self.self_account).is_none());
+			TransactorKind::PlainAccount
+		} else {
+			TransactorKind::Contract
+		}
+	}
+}
+
+/// Describes whether we deal with a contract or a plain account.
+enum TransactorKind {
+	/// Transaction was initiated from a plain account. That can be either be through a
+	/// signed transaction or through RPC.
+	PlainAccount,
+	/// The call was initiated by a contract account.
+	Contract,
+}
+
+/// Describes possible transfer causes.
+enum TransferCause {
+	Call,
+	Instantiate,
+	Terminate,
+}
+
+/// Transfer some funds from `transactor` to `dest`.
+///
+/// We only allow allow for draining all funds of the sender if `cause` is
+/// is specified as `Terminate`. Otherwise, any transfer that would bring the sender below the
+/// subsistence threshold (for contracts) or the existential deposit (for plain accounts)
+/// results in an error.
+fn transfer<T: Config>(
+	cause: TransferCause,
+	origin: TransactorKind,
+	transactor: &T::AccountId,
+	dest: &T::AccountId,
+	value: BalanceOf<T>,
+) -> DispatchResult
+where
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+{
+	use self::TransferCause::*;
+	use self::TransactorKind::*;
+
+	// Only seal_terminate is allowed to bring the sender below the subsistence
+	// threshold or even existential deposit.
+	let existence_requirement = match (cause, origin) {
+		(Terminate, _) => ExistenceRequirement::AllowDeath,
+		(_, Contract) => {
+			ensure!(
+				T::Currency::total_balance(transactor).saturating_sub(value)
+					>= Contracts::<T>::subsistence_threshold(),
+				Error::<T>::BelowSubsistenceThreshold,
+			);
+			ExistenceRequirement::KeepAlive
+		}
+		(_, PlainAccount) => ExistenceRequirement::KeepAlive,
+	};
+
+	T::Currency::transfer(transactor, dest, value, existence_requirement)
+		.map_err(|_| Error::<T>::TransferFailed)?;
+
+	Ok(())
+}
+
+/// A context that is active within a call.
+///
+/// This context has some invariants that must be held at all times. Specifically:
+///`ctx` always points to a context of an alive contract. That implies that it has an existent
+/// `self_trie_id`.
+///
+/// Be advised that there are brief time spans where these invariants could be invalidated.
+/// For example, when a contract requests self-termination the contract is removed eagerly. That
+/// implies that the control won't be returned to the contract anymore, but there is still some code
+/// on the path of the return from that call context. Therefore, care must be taken in these
+/// situations.
+struct CallContext<'a, 'b: 'a, T: Config + 'b, E> {
+	ctx: &'a mut ExecutionContext<'b, T, E>,
+	caller: T::AccountId,
+	value_transferred: BalanceOf<T>,
+	timestamp: MomentOf<T>,
+	block_number: T::BlockNumber,
+	rent_params: RentParams<T>,
+	_phantom: PhantomData<E>,
+}
+
+impl<'a, 'b: 'a, T, E> Ext for CallContext<'a, 'b, T, E>
+where
+	T: Config + 'b,
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+	E: Executable<T>,
+{
+	type T = T;
+
+	fn get_storage(&self, key: &StorageKey) -> Option<Vec<u8>> {
+		let trie_id = self.ctx.self_trie_id.as_ref().expect(
+			"`ctx.self_trie_id` points to an alive contract within the `CallContext`;\
+				it cannot be `None`;\
+				expect can't fail;\
+				qed",
+		);
+		Storage::<T>::read(trie_id, key)
+	}
+
+	fn set_storage(&mut self, key: StorageKey, value: Option<Vec<u8>>) -> DispatchResult {
+		let trie_id = self.ctx.self_trie_id.as_ref().expect(
+			"`ctx.self_trie_id` points to an alive contract within the `CallContext`;\
+				it cannot be `None`;\
+				expect can't fail;\
+				qed",
+		);
+		// write panics if the passed account is not alive.
+		// the contract must be in the alive state within the `CallContext`;\
+		// the contract cannot be absent in storage;
+		// write cannot return `None`;
+		// qed
+		Storage::<T>::write(&self.ctx.self_account, trie_id, &key, value)
+	}
+
+	fn instantiate(
+		&mut self,
+		code_hash: CodeHash<T>,
+		endowment: BalanceOf<T>,
+		gas_meter: &mut GasMeter<T>,
+		input_data: Vec<u8>,
+		salt: &[u8],
+	) -> Result<(AccountIdOf<T>, ExecReturnValue, u32), (ExecError, u32)> {
+		let executable =
+			E::from_storage(code_hash, &self.ctx.schedule, gas_meter).map_err(|e| (e.into(), 0))?;
+		let code_len = executable.code_len();
+		self.ctx
+			.instantiate(endowment, gas_meter, executable, input_data, salt)
+			.map(|r| (r.0, r.1, code_len))
+			.map_err(|e| (e, code_len))
+	}
+
+	fn transfer(&mut self, to: &T::AccountId, value: BalanceOf<T>) -> DispatchResult {
+		transfer::<T>(
+			TransferCause::Call,
+			TransactorKind::Contract,
+			&self.ctx.self_account.clone(),
+			to,
+			value,
+		)
+	}
+
+	fn terminate(
+		&mut self,
+		beneficiary: &AccountIdOf<Self::T>,
+	) -> Result<u32, (DispatchError, u32)> {
+		let self_id = self.ctx.self_account.clone();
+		let value = T::Currency::free_balance(&self_id);
+		if let Some(caller_ctx) = self.ctx.caller {
+			if caller_ctx.is_live(&self_id) {
+				return Err((Error::<T>::ReentranceDenied.into(), 0));
+			}
+		}
+		transfer::<T>(
+			TransferCause::Terminate,
+			TransactorKind::Contract,
+			&self_id,
+			beneficiary,
+			value,
+		)
+		.map_err(|e| (e, 0))?;
+		if let Some(ContractInfo::Alive(info)) = ContractInfoOf::<T>::take(&self_id) {
+			Storage::<T>::queue_trie_for_deletion(&info).map_err(|e| (e, 0))?;
+			let code_len = E::remove_user(info.code_hash);
+			Contracts::<T>::deposit_event(Event::Terminated(self_id, beneficiary.clone()));
+			Ok(code_len)
+		} else {
+			panic!(
+				"this function is only invoked by in the context of a contract;\
+				this contract is therefore alive;\
+				qed"
+			);
+		}
+	}
+
+	fn call(
+		&mut self,
+		to: &T::AccountId,
+		value: BalanceOf<T>,
+		gas_meter: &mut GasMeter<T>,
+		input_data: Vec<u8>,
+	) -> Result<(ExecReturnValue, u32), (ExecError, u32)> {
+		self.ctx.call(to.clone(), value, gas_meter, input_data)
+	}
+
+	fn restore_to(
+		&mut self,
+		dest: AccountIdOf<Self::T>,
+		code_hash: CodeHash<Self::T>,
+		rent_allowance: BalanceOf<Self::T>,
+		delta: Vec<StorageKey>,
+	) -> Result<(u32, u32), (DispatchError, u32, u32)> {
+		if let Some(caller_ctx) = self.ctx.caller {
+			if caller_ctx.is_live(&self.ctx.self_account) {
+				return Err((Error::<T>::ReentranceDenied.into(), 0, 0));
+			}
+		}
+
+		let result = Rent::<T, E>::restore_to(
+			self.ctx.self_account.clone(),
+			dest.clone(),
+			code_hash.clone(),
+			rent_allowance,
+			delta,
+		);
+		if let Ok(_) = result {
+			deposit_event::<Self::T>(
+				vec![],
+				Event::Restored(
+					self.ctx.self_account.clone(),
+					dest,
+					code_hash,
+					rent_allowance,
+				),
+			);
+		}
+		result
+	}
+
+	fn address(&self) -> &T::AccountId {
+		&self.ctx.self_account
+	}
+
+	fn caller(&self) -> &T::AccountId {
+		&self.caller
+	}
+
+	fn balance(&self) -> BalanceOf<T> {
+		T::Currency::free_balance(&self.ctx.self_account)
+	}
+
+	fn value_transferred(&self) -> BalanceOf<T> {
+		self.value_transferred
+	}
+
+	fn random(&self, subject: &[u8]) -> (SeedOf<T>, BlockNumberOf<T>) {
+		T::Randomness::random(subject)
+	}
+
+	fn now(&self) -> &MomentOf<T> {
+		&self.timestamp
+	}
+
+	fn minimum_balance(&self) -> BalanceOf<T> {
+		T::Currency::minimum_balance()
+	}
+
+	fn tombstone_deposit(&self) -> BalanceOf<T> {
+		T::TombstoneDeposit::get()
+	}
+
+	fn deposit_event(&mut self, topics: Vec<T::Hash>, data: Vec<u8>) {
+		deposit_event::<Self::T>(
+			topics,
+			Event::ContractEmitted(self.ctx.self_account.clone(), data),
+		);
+	}
+
+	fn set_rent_allowance(&mut self, rent_allowance: BalanceOf<T>) {
+		if let Err(storage::ContractAbsentError) =
+			Storage::<T>::set_rent_allowance(&self.ctx.self_account, rent_allowance)
+		{
+			panic!(
+				"`self_account` points to an alive contract within the `CallContext`;
+					set_rent_allowance cannot return `Err`; qed"
+			);
+		}
+	}
+
+	fn rent_allowance(&self) -> BalanceOf<T> {
+		Storage::<T>::rent_allowance(&self.ctx.self_account)
+			.unwrap_or_else(|_| <BalanceOf<T>>::max_value()) // Must never be triggered actually
+	}
+
+	fn block_number(&self) -> T::BlockNumber {
+		self.block_number
+	}
+
+	fn max_value_size(&self) -> u32 {
+		T::MaxValueSize::get()
+	}
+
+	fn get_weight_price(&self, weight: Weight) -> BalanceOf<Self::T> {
+		T::WeightPrice::convert(weight)
+	}
+
+	fn schedule(&self) -> &Schedule<Self::T> {
+		&self.ctx.schedule
+	}
+
+	fn rent_params(&self) -> &RentParams<Self::T> {
+		&self.rent_params
+	}
+}
+
+fn deposit_event<T: Config>(topics: Vec<T::Hash>, event: Event<T>) {
+	<frame_system::Pallet<T>>::deposit_event_indexed(
+		&*topics,
+		<T as Config>::Event::from(event).into(),
+	)
+}
+
+mod sealing {
+	use super::*;
+
+	pub trait Sealed {}
+
+	impl<'a, 'b: 'a, T: Config, E> Sealed for CallContext<'a, 'b, T, E> {}
+
+	#[cfg(test)]
+	impl Sealed for crate::wasm::MockExt {}
+
+	#[cfg(test)]
+	impl Sealed for &mut crate::wasm::MockExt {}
+}
+
+/// These tests exercise the executive layer.
+///
+/// In these tests the VM/loader are mocked. Instead of dealing with wasm bytecode they use simple closures.
+/// This allows you to tackle executive logic more thoroughly without writing a
+/// wasm VM code.
+#[cfg(test)]
+mod tests {
+	use super::*;
+	use crate::{
+		gas::GasMeter,
+		tests::{ExtBuilder, Test, Event as MetaEvent},
+		storage::{Storage, ContractAbsentError},
+		tests::{
+			ALICE, BOB, CHARLIE,
+			test_utils::{place_contract, set_balance, get_balance},
+		},
+		exec::ExportedFunction::*,
+		Error, Weight, CurrentSchedule,
+	};
+	use sp_core::Bytes;
+	use frame_support::assert_noop;
+	use sp_runtime::DispatchError;
+	use assert_matches::assert_matches;
+	use std::{cell::RefCell, collections::HashMap, rc::Rc};
+	use pretty_assertions::{assert_eq, assert_ne};
+
+	type MockContext<'a> = ExecutionContext<'a, Test, MockExecutable>;
+
+	const GAS_LIMIT: Weight = 10_000_000_000;
+
+	thread_local! {
+		static LOADER: RefCell<MockLoader> = RefCell::new(MockLoader::default());
+	}
+
+	fn events() -> Vec<Event<Test>> {
+		<frame_system::Pallet<Test>>::events()
+			.into_iter()
+			.filter_map(|meta| match meta.event {
+				MetaEvent::pallet_contracts(contract_event) => Some(contract_event),
+				_ => None,
+			})
+			.collect()
+	}
+
+	struct MockCtx<'a> {
+		ext: &'a mut dyn Ext<T = Test>,
+		input_data: Vec<u8>,
+		gas_meter: &'a mut GasMeter<Test>,
+	}
+
+	#[derive(Clone)]
+	struct MockExecutable {
+		func: Rc<dyn Fn(MockCtx, &Self) -> ExecResult + 'static>,
+		func_type: ExportedFunction,
+		code_hash: CodeHash<Test>,
+		refcount: u64,
+	}
+
+	#[derive(Default)]
+	struct MockLoader {
+		map: HashMap<CodeHash<Test>, MockExecutable>,
+		counter: u64,
+	}
+
+	impl MockLoader {
+		fn insert(
+			func_type: ExportedFunction,
+			f: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static,
+		) -> CodeHash<Test> {
+			LOADER.with(|loader| {
+				let mut loader = loader.borrow_mut();
+				// Generate code hashes as monotonically increasing values.
+				let hash = <Test as frame_system::Config>::Hash::from_low_u64_be(loader.counter);
+				loader.counter += 1;
+				loader.map.insert(
+					hash,
+					MockExecutable {
+						func: Rc::new(f),
+						func_type,
+						code_hash: hash.clone(),
+						refcount: 1,
+					},
+				);
+				hash
+			})
+		}
+
+		fn increment_refcount(code_hash: CodeHash<Test>) {
+			LOADER.with(|loader| {
+				let mut loader = loader.borrow_mut();
+				loader
+					.map
+					.entry(code_hash)
+					.and_modify(|executable| executable.refcount += 1)
+					.or_insert_with(|| panic!("code_hash does not exist"));
+			});
+		}
+
+		fn decrement_refcount(code_hash: CodeHash<Test>) {
+			use std::collections::hash_map::Entry::Occupied;
+			LOADER.with(|loader| {
+				let mut loader = loader.borrow_mut();
+				let mut entry = match loader.map.entry(code_hash) {
+					Occupied(e) => e,
+					_ => panic!("code_hash does not exist"),
+				};
+				let refcount = &mut entry.get_mut().refcount;
+				*refcount -= 1;
+				if *refcount == 0 {
+					entry.remove();
+				}
+			});
+		}
+
+		fn refcount(code_hash: &CodeHash<Test>) -> u32 {
+			LOADER.with(|loader| {
+				loader
+					.borrow()
+					.map
+					.get(code_hash)
+					.expect("code_hash does not exist")
+					.refcount()
+			})
+		}
+	}
+
+	impl Executable<Test> for MockExecutable {
+		fn from_storage(
+			code_hash: CodeHash<Test>,
+			_schedule: &Schedule<Test>,
+			_gas_meter: &mut GasMeter<Test>,
+		) -> Result<Self, DispatchError> {
+			Self::from_storage_noinstr(code_hash)
+		}
+
+		fn from_storage_noinstr(code_hash: CodeHash<Test>) -> Result<Self, DispatchError> {
+			LOADER.with(|loader| {
+				loader
+					.borrow_mut()
+					.map
+					.get(&code_hash)
+					.cloned()
+					.ok_or(Error::<Test>::CodeNotFound.into())
+			})
+		}
+
+		fn drop_from_storage(self) {
+			MockLoader::decrement_refcount(self.code_hash);
+		}
+
+		fn add_user(code_hash: CodeHash<Test>) -> Result<u32, DispatchError> {
+			MockLoader::increment_refcount(code_hash);
+			Ok(0)
+		}
+
+		fn remove_user(code_hash: CodeHash<Test>) -> u32 {
+			MockLoader::decrement_refcount(code_hash);
+			0
+		}
+
+		fn execute<E: Ext<T = Test>>(
+			self,
+			mut ext: E,
+			function: &ExportedFunction,
+			input_data: Vec<u8>,
+			gas_meter: &mut GasMeter<Test>,
+		) -> ExecResult {
+			if let &Constructor = function {
+				MockLoader::increment_refcount(self.code_hash);
+			}
+			if function == &self.func_type {
+				(self.func)(
+					MockCtx {
+						ext: &mut ext,
+						input_data,
+						gas_meter,
+					},
+					&self,
+				)
+			} else {
+				exec_success()
+			}
+		}
+
+		fn code_hash(&self) -> &CodeHash<Test> {
+			&self.code_hash
+		}
+
+		fn occupied_storage(&self) -> u32 {
+			0
+		}
+
+		fn code_len(&self) -> u32 {
+			0
+		}
+
+		fn aggregate_code_len(&self) -> u32 {
+			0
+		}
+
+		fn refcount(&self) -> u32 {
+			self.refcount as u32
+		}
+	}
+
+	fn exec_success() -> ExecResult {
+		Ok(ExecReturnValue {
+			flags: ReturnFlags::empty(),
+			data: Bytes(Vec::new()),
+		})
+	}
+
+	#[test]
+	fn it_works() {
+		thread_local! {
+			static TEST_DATA: RefCell<Vec<usize>> = RefCell::new(vec![0]);
+		}
+
+		let value = Default::default();
+		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+		let exec_ch = MockLoader::insert(Call, |_ctx, _executable| {
+			TEST_DATA.with(|data| data.borrow_mut().push(1));
+			exec_success()
+		});
+
+		ExtBuilder::default().build().execute_with(|| {
+			let schedule = <CurrentSchedule<Test>>::get();
+			let mut ctx = MockContext::top_level(ALICE, &schedule);
+			place_contract(&BOB, exec_ch);
+
+			assert_matches!(ctx.call(BOB, value, &mut gas_meter, vec![]), Ok(_));
+		});
+
+		TEST_DATA.with(|data| assert_eq!(*data.borrow(), vec![0, 1]));
+	}
+
+	#[test]
+	fn transfer_works() {
+		// This test verifies that a contract is able to transfer
+		// some funds to another account.
+		let origin = ALICE;
+		let dest = BOB;
+
+		ExtBuilder::default().build().execute_with(|| {
+			set_balance(&origin, 100);
+			set_balance(&dest, 0);
+
+			super::transfer::<Test>(
+				super::TransferCause::Call,
+				super::TransactorKind::PlainAccount,
+				&origin,
+				&dest,
+				55,
+			)
+			.unwrap();
+
+			assert_eq!(get_balance(&origin), 45);
+			assert_eq!(get_balance(&dest), 55);
+		});
+	}
+
+	#[test]
+	fn changes_are_reverted_on_failing_call() {
+		// This test verifies that changes are reverted on a call which fails (or equally, returns
+		// a non-zero status code).
+		let origin = ALICE;
+		let dest = BOB;
+
+		let return_ch = MockLoader::insert(Call, |_, _| {
+			Ok(ExecReturnValue {
+				flags: ReturnFlags::REVERT,
+				data: Bytes(Vec::new()),
+			})
+		});
+
+		ExtBuilder::default().build().execute_with(|| {
+			let schedule = <CurrentSchedule<Test>>::get();
+			let mut ctx = MockContext::top_level(origin.clone(), &schedule);
+			place_contract(&BOB, return_ch);
+			set_balance(&origin, 100);
+			let balance = get_balance(&dest);
+
+			let output = ctx
+				.call(
+					dest.clone(),
+					55,
+					&mut GasMeter::<Test>::new(GAS_LIMIT),
+					vec![],
+				)
+				.unwrap();
+
+			assert!(!output.0.is_success());
+			assert_eq!(get_balance(&origin), 100);
+
+			// the rent is still charged
+			assert!(get_balance(&dest) < balance);
+		});
+	}
+
+	#[test]
+	fn balance_too_low() {
+		// This test verifies that a contract can't send value if it's
+		// balance is too low.
+		let origin = ALICE;
+		let dest = BOB;
+
+		ExtBuilder::default().build().execute_with(|| {
+			set_balance(&origin, 0);
+
+			let result = super::transfer::<Test>(
+				super::TransferCause::Call,
+				super::TransactorKind::PlainAccount,
+				&origin,
+				&dest,
+				100,
+			);
+
+			assert_eq!(result, Err(Error::<Test>::TransferFailed.into()));
+			assert_eq!(get_balance(&origin), 0);
+			assert_eq!(get_balance(&dest), 0);
+		});
+	}
+
+	#[test]
+	fn output_is_returned_on_success() {
+		// Verifies that if a contract returns data with a successful exit status, this data
+		// is returned from the execution context.
+		let origin = ALICE;
+		let dest = BOB;
+		let return_ch = MockLoader::insert(Call, |_, _| {
+			Ok(ExecReturnValue {
+				flags: ReturnFlags::empty(),
+				data: Bytes(vec![1, 2, 3, 4]),
+			})
+		});
+
+		ExtBuilder::default().build().execute_with(|| {
+			let schedule = <CurrentSchedule<Test>>::get();
+			let mut ctx = MockContext::top_level(origin, &schedule);
+			place_contract(&BOB, return_ch);
+
+			let result = ctx.call(dest, 0, &mut GasMeter::<Test>::new(GAS_LIMIT), vec![]);
+
+			let output = result.unwrap();
+			assert!(output.0.is_success());
+			assert_eq!(output.0.data, Bytes(vec![1, 2, 3, 4]));
+		});
+	}
+
+	#[test]
+	fn output_is_returned_on_failure() {
+		// Verifies that if a contract returns data with a failing exit status, this data
+		// is returned from the execution context.
+		let origin = ALICE;
+		let dest = BOB;
+		let return_ch = MockLoader::insert(Call, |_, _| {
+			Ok(ExecReturnValue {
+				flags: ReturnFlags::REVERT,
+				data: Bytes(vec![1, 2, 3, 4]),
+			})
+		});
+
+		ExtBuilder::default().build().execute_with(|| {
+			let schedule = <CurrentSchedule<Test>>::get();
+			let mut ctx = MockContext::top_level(origin, &schedule);
+			place_contract(&BOB, return_ch);
+
+			let result = ctx.call(dest, 0, &mut GasMeter::<Test>::new(GAS_LIMIT), vec![]);
+
+			let output = result.unwrap();
+			assert!(!output.0.is_success());
+			assert_eq!(output.0.data, Bytes(vec![1, 2, 3, 4]));
+		});
+	}
+
+	#[test]
+	fn input_data_to_call() {
+		let input_data_ch = MockLoader::insert(Call, |ctx, _| {
+			assert_eq!(ctx.input_data, &[1, 2, 3, 4]);
+			exec_success()
+		});
+
+		// This one tests passing the input data into a contract via call.
+		ExtBuilder::default().build().execute_with(|| {
+			let schedule = <CurrentSchedule<Test>>::get();
+			let mut ctx = MockContext::top_level(ALICE, &schedule);
+			place_contract(&BOB, input_data_ch);
+
+			let result = ctx.call(
+				BOB,
+				0,
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
+				vec![1, 2, 3, 4],
+			);
+			assert_matches!(result, Ok(_));
+		});
+	}
+
+	#[test]
+	fn input_data_to_instantiate() {
+		let input_data_ch = MockLoader::insert(Constructor, |ctx, _| {
+			assert_eq!(ctx.input_data, &[1, 2, 3, 4]);
+			exec_success()
+		});
+
+		// This one tests passing the input data into a contract via instantiate.
+		ExtBuilder::default().build().execute_with(|| {
+			let schedule = <CurrentSchedule<Test>>::get();
+			let subsistence = Contracts::<Test>::subsistence_threshold();
+			let mut ctx = MockContext::top_level(ALICE, &schedule);
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+			let executable =
+				MockExecutable::from_storage(input_data_ch, &schedule, &mut gas_meter).unwrap();
+
+			set_balance(&ALICE, subsistence * 10);
+
+			let result = ctx.instantiate(
+				subsistence * 3,
+				&mut gas_meter,
+				executable,
+				vec![1, 2, 3, 4],
+				&[],
+			);
+			assert_matches!(result, Ok(_));
+		});
+	}
+
+	#[test]
+	fn max_depth() {
+		// This test verifies that when we reach the maximal depth creation of an
+		// yet another context fails.
+		thread_local! {
+			static REACHED_BOTTOM: RefCell<bool> = RefCell::new(false);
+		}
+		let value = Default::default();
+		let recurse_ch = MockLoader::insert(Call, |ctx, _| {
+			// Try to call into yourself.
+			let r = ctx.ext.call(&BOB, 0, ctx.gas_meter, vec![]);
+
+			REACHED_BOTTOM.with(|reached_bottom| {
+				let mut reached_bottom = reached_bottom.borrow_mut();
+				if !*reached_bottom {
+					// We are first time here, it means we just reached bottom.
+					// Verify that we've got proper error and set `reached_bottom`.
+					assert_eq!(r, Err((Error::<Test>::MaxCallDepthReached.into(), 0)));
+					*reached_bottom = true;
+				} else {
+					// We just unwinding stack here.
+					assert_matches!(r, Ok(_));
+				}
+			});
+
+			exec_success()
+		});
+
+		ExtBuilder::default().build().execute_with(|| {
+			let schedule = <CurrentSchedule<Test>>::get();
+			let mut ctx = MockContext::top_level(ALICE, &schedule);
+			set_balance(&BOB, 1);
+			place_contract(&BOB, recurse_ch);
+
+			let result = ctx.call(BOB, value, &mut GasMeter::<Test>::new(GAS_LIMIT), vec![]);
+
+			assert_matches!(result, Ok(_));
+		});
+	}
+
+	#[test]
+	fn caller_returns_proper_values() {
+		let origin = ALICE;
+		let dest = BOB;
+
+		thread_local! {
+			static WITNESSED_CALLER_BOB: RefCell<Option<AccountIdOf<Test>>> = RefCell::new(None);
+			static WITNESSED_CALLER_CHARLIE: RefCell<Option<AccountIdOf<Test>>> = RefCell::new(None);
+		}
+
+		let bob_ch = MockLoader::insert(Call, |ctx, _| {
+			// Record the caller for bob.
+			WITNESSED_CALLER_BOB
+				.with(|caller| *caller.borrow_mut() = Some(ctx.ext.caller().clone()));
+
+			// Call into CHARLIE contract.
+			assert_matches!(ctx.ext.call(&CHARLIE, 0, ctx.gas_meter, vec![]), Ok(_));
+			exec_success()
+		});
+		let charlie_ch = MockLoader::insert(Call, |ctx, _| {
+			// Record the caller for charlie.
+			WITNESSED_CALLER_CHARLIE
+				.with(|caller| *caller.borrow_mut() = Some(ctx.ext.caller().clone()));
+			exec_success()
+		});
+
+		ExtBuilder::default().build().execute_with(|| {
+			let schedule = <CurrentSchedule<Test>>::get();
+			let mut ctx = MockContext::top_level(origin.clone(), &schedule);
+			place_contract(&dest, bob_ch);
+			place_contract(&CHARLIE, charlie_ch);
+
+			let result = ctx.call(
+				dest.clone(),
+				0,
+				&mut GasMeter::<Test>::new(GAS_LIMIT),
+				vec![],
+			);
+
+			assert_matches!(result, Ok(_));
+		});
+
+		WITNESSED_CALLER_BOB.with(|caller| assert_eq!(*caller.borrow(), Some(origin)));
+		WITNESSED_CALLER_CHARLIE.with(|caller| assert_eq!(*caller.borrow(), Some(dest)));
+	}
+
+	#[test]
+	fn address_returns_proper_values() {
+		let bob_ch = MockLoader::insert(Call, |ctx, _| {
+			// Verify that address matches BOB.
+			assert_eq!(*ctx.ext.address(), BOB);
+
+			// Call into charlie contract.
+			assert_matches!(ctx.ext.call(&CHARLIE, 0, ctx.gas_meter, vec![]), Ok(_));
+			exec_success()
+		});
+		let charlie_ch = MockLoader::insert(Call, |ctx, _| {
+			assert_eq!(*ctx.ext.address(), CHARLIE);
+			exec_success()
+		});
+
+		ExtBuilder::default().build().execute_with(|| {
+			let schedule = <CurrentSchedule<Test>>::get();
+			let mut ctx = MockContext::top_level(ALICE, &schedule);
+			place_contract(&BOB, bob_ch);
+			place_contract(&CHARLIE, charlie_ch);
+
+			let result = ctx.call(BOB, 0, &mut GasMeter::<Test>::new(GAS_LIMIT), vec![]);
+
+			assert_matches!(result, Ok(_));
+		});
+	}
+
+	#[test]
+	fn refuse_instantiate_with_value_below_existential_deposit() {
+		let dummy_ch = MockLoader::insert(Constructor, |_, _| exec_success());
+
+		ExtBuilder::default()
+			.existential_deposit(15)
+			.build()
+			.execute_with(|| {
+				let schedule = <CurrentSchedule<Test>>::get();
+				let mut ctx = MockContext::top_level(ALICE, &schedule);
+				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+				let executable =
+					MockExecutable::from_storage(dummy_ch, &schedule, &mut gas_meter).unwrap();
+
+				assert_matches!(
+					ctx.instantiate(
+						0, // <- zero endowment
+						&mut gas_meter,
+						executable,
+						vec![],
+						&[],
+					),
+					Err(_)
+				);
+			});
+	}
+
+	#[test]
+	fn instantiation_work_with_success_output() {
+		let dummy_ch = MockLoader::insert(Constructor, |_, _| {
+			Ok(ExecReturnValue {
+				flags: ReturnFlags::empty(),
+				data: Bytes(vec![80, 65, 83, 83]),
+			})
+		});
+
+		ExtBuilder::default()
+			.existential_deposit(15)
+			.build()
+			.execute_with(|| {
+				let schedule = <CurrentSchedule<Test>>::get();
+				let mut ctx = MockContext::top_level(ALICE, &schedule);
+				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+				let executable =
+					MockExecutable::from_storage(dummy_ch, &schedule, &mut gas_meter).unwrap();
+				set_balance(&ALICE, 1000);
+
+				let instantiated_contract_address = assert_matches!(
+					ctx.instantiate(
+						100,
+						&mut gas_meter,
+						executable,
+						vec![],
+						&[],
+					),
+					Ok((address, ref output)) if output.data == Bytes(vec![80, 65, 83, 83]) => address
+				);
+
+				// Check that the newly created account has the expected code hash and
+				// there are instantiation event.
+				assert_eq!(
+					Storage::<Test>::code_hash(&instantiated_contract_address).unwrap(),
+					dummy_ch
+				);
+				assert_eq!(
+					&events(),
+					&[Event::Instantiated(ALICE, instantiated_contract_address)]
+				);
+			});
+	}
+
+	#[test]
+	fn instantiation_fails_with_failing_output() {
+		let dummy_ch = MockLoader::insert(Constructor, |_, _| {
+			Ok(ExecReturnValue {
+				flags: ReturnFlags::REVERT,
+				data: Bytes(vec![70, 65, 73, 76]),
+			})
+		});
+
+		ExtBuilder::default()
+			.existential_deposit(15)
+			.build()
+			.execute_with(|| {
+				let schedule = <CurrentSchedule<Test>>::get();
+				let mut ctx = MockContext::top_level(ALICE, &schedule);
+				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+				let executable =
+					MockExecutable::from_storage(dummy_ch, &schedule, &mut gas_meter).unwrap();
+				set_balance(&ALICE, 1000);
+
+				let instantiated_contract_address = assert_matches!(
+					ctx.instantiate(
+						100,
+						&mut gas_meter,
+						executable,
+						vec![],
+						&[],
+					),
+					Ok((address, ref output)) if output.data == Bytes(vec![70, 65, 73, 76]) => address
+				);
+
+				// Check that the account has not been created.
+				assert_noop!(
+					Storage::<Test>::code_hash(&instantiated_contract_address),
+					ContractAbsentError,
+				);
+				assert!(events().is_empty());
+			});
+	}
+
+	#[test]
+	fn instantiation_from_contract() {
+		let dummy_ch = MockLoader::insert(Call, |_, _| exec_success());
+		let instantiated_contract_address = Rc::new(RefCell::new(None::<AccountIdOf<Test>>));
+		let instantiator_ch = MockLoader::insert(Call, {
+			let dummy_ch = dummy_ch.clone();
+			let instantiated_contract_address = Rc::clone(&instantiated_contract_address);
+			move |ctx, _| {
+				// Instantiate a contract and save it's address in `instantiated_contract_address`.
+				let (address, output, _) = ctx
+					.ext
+					.instantiate(
+						dummy_ch,
+						Contracts::<Test>::subsistence_threshold() * 3,
+						ctx.gas_meter,
+						vec![],
+						&[48, 49, 50],
+					)
+					.unwrap();
+
+				*instantiated_contract_address.borrow_mut() = address.into();
+				Ok(output)
+			}
+		});
+
+		ExtBuilder::default()
+			.existential_deposit(15)
+			.build()
+			.execute_with(|| {
+				let schedule = <CurrentSchedule<Test>>::get();
+				let mut ctx = MockContext::top_level(ALICE, &schedule);
+				set_balance(&ALICE, Contracts::<Test>::subsistence_threshold() * 100);
+				place_contract(&BOB, instantiator_ch);
+
+				assert_matches!(
+					ctx.call(BOB, 20, &mut GasMeter::<Test>::new(GAS_LIMIT), vec![]),
+					Ok(_)
+				);
+
+				let instantiated_contract_address = instantiated_contract_address
+					.borrow()
+					.as_ref()
+					.unwrap()
+					.clone();
+
+				// Check that the newly created account has the expected code hash and
+				// there are instantiation event.
+				assert_eq!(
+					Storage::<Test>::code_hash(&instantiated_contract_address).unwrap(),
+					dummy_ch
+				);
+				assert_eq!(
+					&events(),
+					&[Event::Instantiated(BOB, instantiated_contract_address)]
+				);
+			});
+	}
+
+	#[test]
+	fn instantiation_traps() {
+		let dummy_ch = MockLoader::insert(Constructor, |_, _| Err("It's a trap!".into()));
+		let instantiator_ch = MockLoader::insert(Call, {
+			let dummy_ch = dummy_ch.clone();
+			move |ctx, _| {
+				// Instantiate a contract and save it's address in `instantiated_contract_address`.
+				assert_matches!(
+					ctx.ext
+						.instantiate(dummy_ch, 15u64, ctx.gas_meter, vec![], &[],),
+					Err((
+						ExecError {
+							error: DispatchError::Other("It's a trap!"),
+							origin: ErrorOrigin::Callee,
+						},
+						0
+					))
+				);
+
+				exec_success()
+			}
+		});
+
+		ExtBuilder::default()
+			.existential_deposit(15)
+			.build()
+			.execute_with(|| {
+				let schedule = <CurrentSchedule<Test>>::get();
+				let mut ctx = MockContext::top_level(ALICE, &schedule);
+				set_balance(&ALICE, 1000);
+				set_balance(&BOB, 100);
+				place_contract(&BOB, instantiator_ch);
+
+				assert_matches!(
+					ctx.call(BOB, 20, &mut GasMeter::<Test>::new(GAS_LIMIT), vec![]),
+					Ok(_)
+				);
+
+				// The contract wasn't instantiated so we don't expect to see an instantiation
+				// event here.
+				assert_eq!(&events(), &[]);
+			});
+	}
+
+	#[test]
+	fn termination_from_instantiate_fails() {
+		let terminate_ch = MockLoader::insert(Constructor, |ctx, _| {
+			ctx.ext.terminate(&ALICE).unwrap();
+			exec_success()
+		});
+
+		ExtBuilder::default()
+			.existential_deposit(15)
+			.build()
+			.execute_with(|| {
+				let schedule = <CurrentSchedule<Test>>::get();
+				let mut ctx = MockContext::top_level(ALICE, &schedule);
+				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+				let executable =
+					MockExecutable::from_storage(terminate_ch, &schedule, &mut gas_meter).unwrap();
+				set_balance(&ALICE, 1000);
+
+				assert_eq!(
+					ctx.instantiate(100, &mut gas_meter, executable, vec![], &[],),
+					Err(Error::<Test>::NotCallable.into())
+				);
+
+				assert_eq!(&events(), &[]);
+			});
+	}
+
+	#[test]
+	fn rent_allowance() {
+		let rent_allowance_ch = MockLoader::insert(Constructor, |ctx, _| {
+			let subsistence = Contracts::<Test>::subsistence_threshold();
+			let allowance = subsistence * 3;
+			assert_eq!(ctx.ext.rent_allowance(), <BalanceOf<Test>>::max_value());
+			ctx.ext.set_rent_allowance(allowance);
+			assert_eq!(ctx.ext.rent_allowance(), allowance);
+			exec_success()
+		});
+
+		ExtBuilder::default().build().execute_with(|| {
+			let subsistence = Contracts::<Test>::subsistence_threshold();
+			let schedule = <CurrentSchedule<Test>>::get();
+			let mut ctx = MockContext::top_level(ALICE, &schedule);
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+			let executable =
+				MockExecutable::from_storage(rent_allowance_ch, &schedule, &mut gas_meter).unwrap();
+			set_balance(&ALICE, subsistence * 10);
+
+			let result = ctx.instantiate(subsistence * 5, &mut gas_meter, executable, vec![], &[]);
+			assert_matches!(result, Ok(_));
+		});
+	}
+
+	#[test]
+	fn rent_params_works() {
+		let code_hash = MockLoader::insert(Call, |ctx, executable| {
+			let address = ctx.ext.address();
+			let contract = <ContractInfoOf<Test>>::get(address)
+				.and_then(|c| c.get_alive())
+				.unwrap();
+			assert_eq!(
+				ctx.ext.rent_params(),
+				&RentParams::new(address, &contract, executable)
+			);
+			exec_success()
+		});
+
+		ExtBuilder::default().build().execute_with(|| {
+			let subsistence = Contracts::<Test>::subsistence_threshold();
+			let schedule = <CurrentSchedule<Test>>::get();
+			let mut ctx = MockContext::top_level(ALICE, &schedule);
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+			set_balance(&ALICE, subsistence * 10);
+			place_contract(&BOB, code_hash);
+			ctx.call(BOB, 0, &mut gas_meter, vec![]).unwrap();
+		});
+	}
+
+	#[test]
+	fn rent_params_snapshotted() {
+		let code_hash = MockLoader::insert(Call, |ctx, executable| {
+			let subsistence = Contracts::<Test>::subsistence_threshold();
+			let address = ctx.ext.address();
+			let contract = <ContractInfoOf<Test>>::get(address)
+				.and_then(|c| c.get_alive())
+				.unwrap();
+			let rent_params = RentParams::new(address, &contract, executable);
+
+			// Changing the allowance during the call: rent params stay unchanged.
+			let allowance = 42;
+			assert_ne!(allowance, rent_params.rent_allowance);
+			ctx.ext.set_rent_allowance(allowance);
+			assert_eq!(ctx.ext.rent_params(), &rent_params);
+
+			// Creating another instance from the same code_hash increases the refcount.
+			// This is also not reflected in the rent params.
+			assert_eq!(MockLoader::refcount(&executable.code_hash), 1);
+			ctx.ext
+				.instantiate(
+					executable.code_hash,
+					subsistence * 25,
+					&mut GasMeter::<Test>::new(GAS_LIMIT),
+					vec![],
+					&[],
+				)
+				.unwrap();
+			assert_eq!(MockLoader::refcount(&executable.code_hash), 2);
+			assert_eq!(ctx.ext.rent_params(), &rent_params);
+
+			exec_success()
+		});
+
+		ExtBuilder::default().build().execute_with(|| {
+			let subsistence = Contracts::<Test>::subsistence_threshold();
+			let schedule = <CurrentSchedule<Test>>::get();
+			let mut ctx = MockContext::top_level(ALICE, &schedule);
+			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
+			set_balance(&ALICE, subsistence * 100);
+			place_contract(&BOB, code_hash);
+			ctx.call(BOB, subsistence * 50, &mut gas_meter, vec![])
+				.unwrap();
+		});
+	}
+}
addedpallets/contracts/src/gas.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/gas.rs
@@ -0,0 +1,364 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::{Config, Error, exec::ExecError};
+use sp_std::marker::PhantomData;
+use sp_runtime::traits::Zero;
+use frame_support::{
+	dispatch::{
+		DispatchResultWithPostInfo, PostDispatchInfo, DispatchErrorWithPostInfo, DispatchError,
+	},
+	weights::Weight,
+};
+use sp_core::crypto::UncheckedFrom;
+
+#[cfg(test)]
+use std::{any::Any, fmt::Debug};
+
+#[derive(Debug, PartialEq, Eq)]
+pub struct ChargedAmount(Weight);
+
+impl ChargedAmount {
+	pub fn amount(&self) -> Weight {
+		self.0
+	}
+}
+
+#[cfg(not(test))]
+pub trait TestAuxiliaries {}
+#[cfg(not(test))]
+impl<T> TestAuxiliaries for T {}
+
+#[cfg(test)]
+pub trait TestAuxiliaries: Any + Debug + PartialEq + Eq {}
+#[cfg(test)]
+impl<T: Any + Debug + PartialEq + Eq> TestAuxiliaries for T {}
+
+/// This trait represents a token that can be used for charging `GasMeter`.
+/// There is no other way of charging it.
+///
+/// Implementing type is expected to be super lightweight hence `Copy` (`Clone` is added
+/// for consistency). If inlined there should be no observable difference compared
+/// to a hand-written code.
+pub trait Token<T: Config>: Copy + Clone + TestAuxiliaries {
+	/// Metadata type, which the token can require for calculating the amount
+	/// of gas to charge. Can be a some configuration type or
+	/// just the `()`.
+	type Metadata;
+
+	/// Calculate amount of gas that should be taken by this token.
+	///
+	/// This function should be really lightweight and must not fail. It is not
+	/// expected that implementors will query the storage or do any kinds of heavy operations.
+	///
+	/// That said, implementors of this function still can run into overflows
+	/// while calculating the amount. In this case it is ok to use saturating operations
+	/// since on overflow they will return `max_value` which should consume all gas.
+	fn calculate_amount(&self, metadata: &Self::Metadata) -> Weight;
+}
+
+/// A wrapper around a type-erased trait object of what used to be a `Token`.
+#[cfg(test)]
+pub struct ErasedToken {
+	pub description: String,
+	pub token: Box<dyn Any>,
+}
+
+pub struct GasMeter<T: Config> {
+	gas_limit: Weight,
+	/// Amount of gas left from initial gas limit. Can reach zero.
+	gas_left: Weight,
+	_phantom: PhantomData<T>,
+	#[cfg(test)]
+	tokens: Vec<ErasedToken>,
+}
+
+impl<T: Config> GasMeter<T>
+where
+	T::AccountId: UncheckedFrom<<T as frame_system::Config>::Hash> + AsRef<[u8]>,
+{
+	pub fn new(gas_limit: Weight) -> Self {
+		GasMeter {
+			gas_limit,
+			gas_left: gas_limit,
+			_phantom: PhantomData,
+			#[cfg(test)]
+			tokens: Vec::new(),
+		}
+	}
+
+	/// Account for used gas.
+	///
+	/// Amount is calculated by the given `token`.
+	///
+	/// Returns `OutOfGas` if there is not enough gas or addition of the specified
+	/// amount of gas has lead to overflow. On success returns `Proceed`.
+	///
+	/// NOTE that amount is always consumed, i.e. if there is not enough gas
+	/// then the counter will be set to zero.
+	#[inline]
+	pub fn charge<Tok: Token<T>>(
+		&mut self,
+		metadata: &Tok::Metadata,
+		token: Tok,
+	) -> Result<ChargedAmount, DispatchError> {
+		#[cfg(test)]
+		{
+			// Unconditionally add the token to the storage.
+			let erased_tok = ErasedToken {
+				description: format!("{:?}", token),
+				token: Box::new(token),
+			};
+			self.tokens.push(erased_tok);
+		}
+
+		let amount = token.calculate_amount(metadata);
+		let new_value = self.gas_left.checked_sub(amount);
+
+		// We always consume the gas even if there is not enough gas.
+		self.gas_left = new_value.unwrap_or_else(Zero::zero);
+
+		match new_value {
+			Some(_) => Ok(ChargedAmount(amount)),
+			None => Err(Error::<T>::OutOfGas.into()),
+		}
+	}
+
+	/// Adjust a previously charged amount down to its actual amount.
+	///
+	/// This is when a maximum a priori amount was charged and then should be partially
+	/// refunded to match the actual amount.
+	pub fn adjust_gas<Tok: Token<T>>(
+		&mut self,
+		charged_amount: ChargedAmount,
+		metadata: &Tok::Metadata,
+		token: Tok,
+	) {
+		let adjustment = charged_amount
+			.0
+			.saturating_sub(token.calculate_amount(metadata));
+		self.gas_left = self.gas_left.saturating_add(adjustment).min(self.gas_limit);
+	}
+
+	/// Refund previously charged gas back to the gas meter.
+	///
+	/// This can be used if a gas worst case estimation must be charged before
+	/// performing a certain action. This way the difference can be refundend when
+	/// the worst case did not happen.
+	pub fn refund(&mut self, amount: ChargedAmount) {
+		self.gas_left = self.gas_left.saturating_add(amount.0).min(self.gas_limit)
+	}
+
+	/// Allocate some amount of gas and perform some work with
+	/// a newly created nested gas meter.
+	///
+	/// Invokes `f` with either the gas meter that has `amount` gas left or
+	/// with `None`, if this gas meter has not enough gas to allocate given `amount`.
+	///
+	/// All unused gas in the nested gas meter is returned to this gas meter.
+	pub fn with_nested<R, F: FnOnce(Option<&mut GasMeter<T>>) -> R>(
+		&mut self,
+		amount: Weight,
+		f: F,
+	) -> R {
+		// NOTE that it is ok to allocate all available gas since it still ensured
+		// by `charge` that it doesn't reach zero.
+		if self.gas_left < amount {
+			f(None)
+		} else {
+			self.gas_left = self.gas_left - amount;
+			let mut nested = GasMeter::new(amount);
+
+			let r = f(Some(&mut nested));
+
+			self.gas_left = self.gas_left + nested.gas_left;
+
+			r
+		}
+	}
+
+	/// Returns how much gas was used.
+	pub fn gas_spent(&self) -> Weight {
+		self.gas_limit - self.gas_left
+	}
+
+	/// Returns how much gas left from the initial budget.
+	pub fn gas_left(&self) -> Weight {
+		self.gas_left
+	}
+
+	/// Turn this GasMeter into a DispatchResult that contains the actually used gas.
+	pub fn into_dispatch_result<R, E>(
+		self,
+		result: Result<R, E>,
+		base_weight: Weight,
+	) -> DispatchResultWithPostInfo
+	where
+		E: Into<ExecError>,
+	{
+		let post_info = PostDispatchInfo {
+			actual_weight: Some(self.gas_spent().saturating_add(base_weight)),
+			pays_fee: Default::default(),
+		};
+
+		result
+			.map(|_| post_info)
+			.map_err(|e| DispatchErrorWithPostInfo {
+				post_info,
+				error: e.into().error,
+			})
+	}
+
+	#[cfg(test)]
+	pub fn tokens(&self) -> &[ErasedToken] {
+		&self.tokens
+	}
+}
+
+#[cfg(test)]
+mod tests {
+	use super::{GasMeter, Token};
+	use crate::tests::Test;
+
+	/// A simple utility macro that helps to match against a
+	/// list of tokens.
+	macro_rules! match_tokens {
+		($tokens_iter:ident,) => {
+		};
+		($tokens_iter:ident, $x:expr, $($rest:tt)*) => {
+			{
+				let next = ($tokens_iter).next().unwrap();
+				let pattern = $x;
+
+				// Note that we don't specify the type name directly in this macro,
+				// we only have some expression $x of some type. At the same time, we
+				// have an iterator of Box<dyn Any> and to downcast we need to specify
+				// the type which we want downcast to.
+				//
+				// So what we do is we assign `_pattern_typed_next_ref` to a variable which has
+				// the required type.
+				//
+				// Then we make `_pattern_typed_next_ref = token.downcast_ref()`. This makes
+				// rustc infer the type `T` (in `downcast_ref<T: Any>`) to be the same as in $x.
+
+				let mut _pattern_typed_next_ref = &pattern;
+				_pattern_typed_next_ref = match next.token.downcast_ref() {
+					Some(p) => {
+						assert_eq!(p, &pattern);
+						p
+					}
+					None => {
+						panic!("expected type {} got {}", stringify!($x), next.description);
+					}
+				};
+			}
+
+			match_tokens!($tokens_iter, $($rest)*);
+		};
+	}
+
+	/// A trivial token that charges the specified number of gas units.
+	#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+	struct SimpleToken(u64);
+	impl Token<Test> for SimpleToken {
+		type Metadata = ();
+		fn calculate_amount(&self, _metadata: &()) -> u64 {
+			self.0
+		}
+	}
+
+	struct MultiplierTokenMetadata {
+		multiplier: u64,
+	}
+	/// A simple token that charges for the given amount multiplied to
+	/// a multiplier taken from a given metadata.
+	#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+	struct MultiplierToken(u64);
+
+	impl Token<Test> for MultiplierToken {
+		type Metadata = MultiplierTokenMetadata;
+		fn calculate_amount(&self, metadata: &MultiplierTokenMetadata) -> u64 {
+			// Probably you want to use saturating mul in production code.
+			self.0 * metadata.multiplier
+		}
+	}
+
+	#[test]
+	fn it_works() {
+		let gas_meter = GasMeter::<Test>::new(50000);
+		assert_eq!(gas_meter.gas_left(), 50000);
+	}
+
+	#[test]
+	fn simple() {
+		let mut gas_meter = GasMeter::<Test>::new(50000);
+
+		let result = gas_meter.charge(
+			&MultiplierTokenMetadata { multiplier: 3 },
+			MultiplierToken(10),
+		);
+		assert!(!result.is_err());
+
+		assert_eq!(gas_meter.gas_left(), 49_970);
+	}
+
+	#[test]
+	fn tracing() {
+		let mut gas_meter = GasMeter::<Test>::new(50000);
+		assert!(!gas_meter.charge(&(), SimpleToken(1)).is_err());
+		assert!(!gas_meter
+			.charge(
+				&MultiplierTokenMetadata { multiplier: 3 },
+				MultiplierToken(10)
+			)
+			.is_err());
+
+		let mut tokens = gas_meter.tokens()[0..2].iter();
+		match_tokens!(tokens, SimpleToken(1), MultiplierToken(10),);
+	}
+
+	// This test makes sure that nothing can be executed if there is no gas.
+	#[test]
+	fn refuse_to_execute_anything_if_zero() {
+		let mut gas_meter = GasMeter::<Test>::new(0);
+		assert!(gas_meter.charge(&(), SimpleToken(1)).is_err());
+	}
+
+	// Make sure that if the gas meter is charged by exceeding amount then not only an error
+	// returned for that charge, but also for all consequent charges.
+	//
+	// This is not strictly necessary, because the execution should be interrupted immediately
+	// if the gas meter runs out of gas. However, this is just a nice property to have.
+	#[test]
+	fn overcharge_is_unrecoverable() {
+		let mut gas_meter = GasMeter::<Test>::new(200);
+
+		// The first charge is should lead to OOG.
+		assert!(gas_meter.charge(&(), SimpleToken(300)).is_err());
+
+		// The gas meter is emptied at this moment, so this should also fail.
+		assert!(gas_meter.charge(&(), SimpleToken(1)).is_err());
+	}
+
+	// Charging the exact amount that the user paid for should be
+	// possible.
+	#[test]
+	fn charge_exact_amount() {
+		let mut gas_meter = GasMeter::<Test>::new(25);
+		assert!(!gas_meter.charge(&(), SimpleToken(25)).is_err());
+	}
+}
addedpallets/contracts/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/lib.rs
@@ -0,0 +1,831 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! # Contract Pallet
+//!
+//! The Contract module provides functionality for the runtime to deploy and execute WebAssembly smart-contracts.
+//!
+//! - [`Config`]
+//! - [`Call`]
+//!
+//! ## Overview
+//!
+//! This module extends accounts based on the [`Currency`] trait to have smart-contract functionality. It can
+//! be used with other modules that implement accounts based on [`Currency`]. These "smart-contract accounts"
+//! have the ability to instantiate smart-contracts and make calls to other contract and non-contract accounts.
+//!
+//! The smart-contract code is stored once in a code cache, and later retrievable via its hash.
+//! This means that multiple smart-contracts can be instantiated from the same hash, without replicating
+//! the code each time.
+//!
+//! When a smart-contract is called, its associated code is retrieved via the code hash and gets executed.
+//! This call can alter the storage entries of the smart-contract account, instantiate new smart-contracts,
+//! or call other smart-contracts.
+//!
+//! Finally, when an account is reaped, its associated code and storage of the smart-contract account
+//! will also be deleted.
+//!
+//! ### Gas
+//!
+//! Senders must specify a gas limit with every call, as all instructions invoked by the smart-contract require gas.
+//! Unused gas is refunded after the call, regardless of the execution outcome.
+//!
+//! If the gas limit is reached, then all calls and state changes (including balance transfers) are only
+//! reverted at the current call's contract level. For example, if contract A calls B and B runs out of gas mid-call,
+//! then all of B's calls are reverted. Assuming correct error handling by contract A, A's other calls and state
+//! changes still persist.
+//!
+//! ### Notable Scenarios
+//!
+//! Contract call failures are not always cascading. When failures occur in a sub-call, they do not "bubble up",
+//! and the call will only revert at the specific contract level. For example, if contract A calls contract B, and B
+//! fails, A can decide how to handle that failure, either proceeding or reverting A's changes.
+//!
+//! ## Interface
+//!
+//! ### Dispatchable functions
+//!
+//! * [`Pallet::update_schedule`] -
+//! ([Root Origin](https://substrate.dev/docs/en/knowledgebase/runtime/origin) Only) -
+//! Set a new [`Schedule`].
+//! * [`Pallet::instantiate_with_code`] - Deploys a new contract from the supplied wasm binary,
+//! optionally transferring
+//! some balance. This instantiates a new smart contract account with the supplied code and
+//! calls its constructor to initialize the contract.
+//! * [`Pallet::instantiate`] - The same as `instantiate_with_code` but instead of uploading new
+//! code an existing `code_hash` is supplied.
+//! * [`Pallet::call`] - Makes a call to an account, optionally transferring some balance.
+//! * [`Pallet::claim_surcharge`] - Evict a contract that cannot pay rent anymore.
+//!
+//! ## Usage
+//!
+//! The Contract module is a work in progress. The following examples show how this Contract module
+//! can be used to instantiate and call contracts.
+//!
+//! * [`ink`](https://github.com/paritytech/ink) is
+//! an [`eDSL`](https://wiki.haskell.org/Embedded_domain_specific_language) that enables writing
+//! WebAssembly based smart contracts in the Rust programming language. This is a work in progress.
+//!
+//! ## Related Modules
+//!
+//! * [Balances](../pallet_balances/index.html)
+
+#![cfg_attr(not(feature = "std"), no_std)]
+#![cfg_attr(feature = "runtime-benchmarks", recursion_limit = "512")]
+
+#[macro_use]
+mod gas;
+mod benchmarking;
+mod exec;
+mod migration;
+mod rent;
+mod schedule;
+mod storage;
+mod wasm;
+
+pub mod chain_extension;
+pub mod weights;
+
+#[cfg(test)]
+mod tests;
+
+pub use crate::{pallet::*, schedule::Schedule};
+use crate::{
+	gas::GasMeter,
+	exec::{ExecutionContext, Executable},
+	rent::Rent,
+	storage::{Storage, DeletedContract, ContractInfo, AliveContractInfo, TombstoneContractInfo},
+	weights::WeightInfo,
+	wasm::PrefabWasmModule,
+};
+use sp_core::{Bytes, crypto::UncheckedFrom};
+use sp_std::prelude::*;
+use sp_runtime::{
+	traits::{Hash, StaticLookup, Convert, Saturating, Zero},
+	Perbill,
+};
+use frame_support::{
+	traits::{OnUnbalanced, Currency, Get, Time, Randomness},
+	weights::{Weight, PostDispatchInfo, WithPostDispatchInfo},
+};
+use frame_system::Pallet as System;
+use pallet_contracts_primitives::{
+	RentProjectionResult, GetStorageResult, ContractAccessError, ContractExecResult,
+	ContractInstantiateResult, Code, InstantiateReturnValue,
+};
+
+type CodeHash<T> = <T as frame_system::Config>::Hash;
+type TrieId = Vec<u8>;
+type BalanceOf<T> =
+	<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
+type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<
+	<T as frame_system::Config>::AccountId,
+>>::NegativeImbalance;
+
+#[frame_support::pallet]
+pub mod pallet {
+	use frame_support::pallet_prelude::*;
+	use frame_system::pallet_prelude::*;
+	use super::*;
+
+	#[pallet::config]
+	pub trait Config: frame_system::Config {
+		/// The time implementation used to supply timestamps to conntracts through `seal_now`.
+		type Time: Time;
+
+		/// The generator used to supply randomness to contracts through `seal_random`.
+		type Randomness: Randomness<Self::Hash, Self::BlockNumber>;
+
+		/// The currency in which fees are paid and contract balances are held.
+		type Currency: Currency<Self::AccountId>;
+
+		/// The overarching event type.
+		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
+
+		/// Handler for rent payments.
+		type RentPayment: OnUnbalanced<NegativeImbalanceOf<Self>>;
+
+		/// Number of block delay an extrinsic claim surcharge has.
+		///
+		/// When claim surcharge is called by an extrinsic the rent is checked
+		/// for current_block - delay
+		#[pallet::constant]
+		type SignedClaimHandicap: Get<Self::BlockNumber>;
+
+		/// The minimum amount required to generate a tombstone.
+		#[pallet::constant]
+		type TombstoneDeposit: Get<BalanceOf<Self>>;
+
+		/// The balance every contract needs to deposit to stay alive indefinitely.
+		///
+		/// This is different from the [`Self::TombstoneDeposit`] because this only needs to be
+		/// deposited while the contract is alive. Costs for additional storage are added to
+		/// this base cost.
+		///
+		/// This is a simple way to ensure that contracts with empty storage eventually get deleted by
+		/// making them pay rent. This creates an incentive to remove them early in order to save rent.
+		#[pallet::constant]
+		type DepositPerContract: Get<BalanceOf<Self>>;
+
+		/// The balance a contract needs to deposit per storage byte to stay alive indefinitely.
+		///
+		/// Let's suppose the deposit is 1,000 BU (balance units)/byte and the rent is 1 BU/byte/day,
+		/// then a contract with 1,000,000 BU that uses 1,000 bytes of storage would pay no rent.
+		/// But if the balance reduced to 500,000 BU and the storage stayed the same at 1,000,
+		/// then it would pay 500 BU/day.
+		#[pallet::constant]
+		type DepositPerStorageByte: Get<BalanceOf<Self>>;
+
+		/// The balance a contract needs to deposit per storage item to stay alive indefinitely.
+		///
+		/// It works the same as [`Self::DepositPerStorageByte`] but for storage items.
+		#[pallet::constant]
+		type DepositPerStorageItem: Get<BalanceOf<Self>>;
+
+		/// The fraction of the deposit that should be used as rent per block.
+		///
+		/// When a contract hasn't enough balance deposited to stay alive indefinitely it needs
+		/// to pay per block for the storage it consumes that is not covered by the deposit.
+		/// This determines how high this rent payment is per block as a fraction of the deposit.
+		#[pallet::constant]
+		type RentFraction: Get<Perbill>;
+
+		/// Reward that is received by the party whose touch has led
+		/// to removal of a contract.
+		#[pallet::constant]
+		type SurchargeReward: Get<BalanceOf<Self>>;
+
+		/// The maximum nesting level of a call/instantiate stack.
+		#[pallet::constant]
+		type MaxDepth: Get<u32>;
+
+		/// The maximum size of a storage value and event payload in bytes.
+		#[pallet::constant]
+		type MaxValueSize: Get<u32>;
+
+		/// Used to answer contracts' queries regarding the current weight price. This is **not**
+		/// used to calculate the actual fee and is only for informational purposes.
+		type WeightPrice: Convert<Weight, BalanceOf<Self>>;
+
+		/// Describes the weights of the dispatchables of this module and is also used to
+		/// construct a default cost schedule.
+		type WeightInfo: WeightInfo;
+
+		/// Type that allows the runtime authors to add new host functions for a contract to call.
+		type ChainExtension: chain_extension::ChainExtension<Self>;
+
+		/// The maximum number of tries that can be queued for deletion.
+		#[pallet::constant]
+		type DeletionQueueDepth: Get<u32>;
+
+		/// The maximum amount of weight that can be consumed per block for lazy trie removal.
+		#[pallet::constant]
+		type DeletionWeightLimit: Get<Weight>;
+
+		/// The maximum length of a contract code in bytes. This limit applies to the instrumented
+		/// version of the code. Therefore `instantiate_with_code` can fail even when supplying
+		/// a wasm binary below this maximum size.
+		#[pallet::constant]
+		type MaxCodeSize: Get<u32>;
+	}
+
+	#[pallet::pallet]
+	pub struct Pallet<T>(PhantomData<T>);
+
+	#[pallet::hooks]
+	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T>
+	where
+		T::AccountId: UncheckedFrom<T::Hash>,
+		T::AccountId: AsRef<[u8]>,
+	{
+		fn on_initialize(_block: T::BlockNumber) -> Weight {
+			// We do not want to go above the block limit and rather avoid lazy deletion
+			// in that case. This should only happen on runtime upgrades.
+			let weight_limit = T::BlockWeights::get()
+				.max_block
+				.saturating_sub(System::<T>::block_weight().total())
+				.min(T::DeletionWeightLimit::get());
+			Storage::<T>::process_deletion_queue_batch(weight_limit)
+				.saturating_add(T::WeightInfo::on_initialize())
+		}
+
+		fn on_runtime_upgrade() -> Weight {
+			migration::migrate::<T>()
+		}
+	}
+
+	#[pallet::call]
+	impl<T: Config> Pallet<T>
+	where
+		T::AccountId: UncheckedFrom<T::Hash>,
+		T::AccountId: AsRef<[u8]>,
+	{
+		/// Updates the schedule for metering contracts.
+		///
+		/// The schedule's version cannot be less than the version of the stored schedule.
+		/// If a schedule does not change the instruction weights the version does not
+		/// need to be increased. Therefore we allow storing a schedule that has the same
+		/// version as the stored one.
+		#[pallet::weight(T::WeightInfo::update_schedule())]
+		pub fn update_schedule(
+			origin: OriginFor<T>,
+			schedule: Schedule<T>,
+		) -> DispatchResultWithPostInfo {
+			ensure_root(origin)?;
+			if <CurrentSchedule<T>>::get().version > schedule.version {
+				Err(Error::<T>::InvalidScheduleVersion)?
+			}
+			Self::deposit_event(Event::ScheduleUpdated(schedule.version));
+			CurrentSchedule::put(schedule);
+			Ok(().into())
+		}
+
+		/// Makes a call to an account, optionally transferring some balance.
+		///
+		/// * If the account is a smart-contract account, the associated code will be
+		/// executed and any value will be transferred.
+		/// * If the account is a regular account, any value will be transferred.
+		/// * If no account exists and the call value is not less than `existential_deposit`,
+		/// a regular account will be created and any value will be transferred.
+		#[pallet::weight(T::WeightInfo::call(T::MaxCodeSize::get() / 1024).saturating_add(*gas_limit))]
+		pub fn call(
+			origin: OriginFor<T>,
+			dest: <T::Lookup as StaticLookup>::Source,
+			#[pallet::compact] value: BalanceOf<T>,
+			#[pallet::compact] gas_limit: Weight,
+			data: Vec<u8>,
+		) -> DispatchResultWithPostInfo {
+			let origin = ensure_signed(origin)?;
+			let dest = T::Lookup::lookup(dest)?;
+			let mut gas_meter = GasMeter::new(gas_limit);
+			let schedule = <CurrentSchedule<T>>::get();
+			let mut ctx = ExecutionContext::<T, PrefabWasmModule<T>>::top_level(origin, &schedule);
+			let (result, code_len) = match ctx.call(dest, value, &mut gas_meter, data) {
+				Ok((output, len)) => (Ok(output), len),
+				Err((err, len)) => (Err(err), len),
+			};
+			gas_meter.into_dispatch_result(result, T::WeightInfo::call(code_len / 1024))
+		}
+
+		/// Instantiates a new contract from the supplied `code` optionally transferring
+		/// some balance.
+		///
+		/// This is the only function that can deploy new code to the chain.
+		///
+		/// # Parameters
+		///
+		/// * `endowment`: The balance to transfer from the `origin` to the newly created contract.
+		/// * `gas_limit`: The gas limit enforced when executing the constructor.
+		/// * `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 [`Pallet::contract_address`].
+		///
+		/// Instantiation is executed as follows:
+		///
+		/// - The supplied `code` is instrumented, deployed, and a `code_hash` is created for that code.
+		/// - If the `code_hash` already exists on the chain the underlying `code` will be shared.
+		/// - The destination address is computed based on the sender, code_hash and the salt.
+		/// - The smart-contract account is created at the computed address.
+		/// - The `endowment` is transferred to the new account.
+		/// - The `deploy` function is executed in the context of the newly-created account.
+		#[pallet::weight(
+			T::WeightInfo::instantiate_with_code(
+				code.len() as u32 / 1024,
+				salt.len() as u32 / 1024,
+			)
+			.saturating_add(*gas_limit)
+		)]
+		pub fn instantiate_with_code(
+			origin: OriginFor<T>,
+			#[pallet::compact] endowment: BalanceOf<T>,
+			#[pallet::compact] gas_limit: Weight,
+			code: Vec<u8>,
+			data: Vec<u8>,
+			salt: Vec<u8>,
+		) -> DispatchResultWithPostInfo {
+			let origin = ensure_signed(origin)?;
+			let code_len = code.len() as u32;
+			ensure!(code_len <= T::MaxCodeSize::get(), Error::<T>::CodeTooLarge);
+			let mut gas_meter = GasMeter::new(gas_limit);
+			let schedule = <CurrentSchedule<T>>::get();
+			let executable = PrefabWasmModule::from_code(code, &schedule)?;
+			let code_len = executable.code_len();
+			ensure!(code_len <= T::MaxCodeSize::get(), Error::<T>::CodeTooLarge);
+			let mut ctx = ExecutionContext::<T, PrefabWasmModule<T>>::top_level(origin, &schedule);
+			let result = ctx
+				.instantiate(endowment, &mut gas_meter, executable, data, &salt)
+				.map(|(_address, output)| output);
+			gas_meter.into_dispatch_result(
+				result,
+				T::WeightInfo::instantiate_with_code(code_len / 1024, salt.len() as u32 / 1024),
+			)
+		}
+
+		/// Instantiates a contract from a previously deployed wasm binary.
+		///
+		/// This function is identical to [`Self::instantiate_with_code`] but without the
+		/// code deployment step. Instead, the `code_hash` of an on-chain deployed wasm binary
+		/// must be supplied.
+		#[pallet::weight(
+			T::WeightInfo::instantiate(T::MaxCodeSize::get() / 1024, salt.len() as u32 / 1024)
+				.saturating_add(*gas_limit)
+		)]
+		pub fn instantiate(
+			origin: OriginFor<T>,
+			#[pallet::compact] endowment: BalanceOf<T>,
+			#[pallet::compact] gas_limit: Weight,
+			code_hash: CodeHash<T>,
+			data: Vec<u8>,
+			salt: Vec<u8>,
+		) -> DispatchResultWithPostInfo {
+			let origin = ensure_signed(origin)?;
+			let mut gas_meter = GasMeter::new(gas_limit);
+			let schedule = <CurrentSchedule<T>>::get();
+			let executable = PrefabWasmModule::from_storage(code_hash, &schedule, &mut gas_meter)?;
+			let mut ctx = ExecutionContext::<T, PrefabWasmModule<T>>::top_level(origin, &schedule);
+			let code_len = executable.code_len();
+			let result = ctx
+				.instantiate(endowment, &mut gas_meter, executable, data, &salt)
+				.map(|(_address, output)| output);
+			gas_meter.into_dispatch_result(
+				result,
+				T::WeightInfo::instantiate(code_len / 1024, salt.len() as u32 / 1024),
+			)
+		}
+
+		/// Allows block producers to claim a small reward for evicting a contract. If a block
+		/// producer fails to do so, a regular users will be allowed to claim the reward.
+		///
+		/// In case of a successful eviction no fees are charged from the sender. However, the
+		/// reward is capped by the total amount of rent that was payed by the contract while
+		/// it was alive.
+		///
+		/// If contract is not evicted as a result of this call, [`Error::ContractNotEvictable`]
+		/// is returned and the sender is not eligible for the reward.
+		#[pallet::weight(T::WeightInfo::claim_surcharge(T::MaxCodeSize::get() / 1024))]
+		pub fn claim_surcharge(
+			origin: OriginFor<T>,
+			dest: T::AccountId,
+			aux_sender: Option<T::AccountId>,
+		) -> DispatchResultWithPostInfo {
+			let origin = origin.into();
+			let (signed, rewarded) = match (origin, aux_sender) {
+				(Ok(frame_system::RawOrigin::Signed(account)), None) => (true, account),
+				(Ok(frame_system::RawOrigin::None), Some(aux_sender)) => (false, aux_sender),
+				_ => Err(Error::<T>::InvalidSurchargeClaim)?,
+			};
+
+			// Add some advantage for block producers (who send unsigned extrinsics) by
+			// adding a handicap: for signed extrinsics we use a slightly older block number
+			// for the eviction check. This can be viewed as if we pushed regular users back in past.
+			let handicap = if signed {
+				T::SignedClaimHandicap::get()
+			} else {
+				Zero::zero()
+			};
+
+			// If poking the contract has lead to eviction of the contract, give out the rewards.
+			match Rent::<T, PrefabWasmModule<T>>::try_eviction(&dest, handicap)? {
+				(Some(rent_payed), code_len) => T::Currency::deposit_into_existing(
+					&rewarded,
+					T::SurchargeReward::get().min(rent_payed),
+				)
+				.map(|_| PostDispatchInfo {
+					actual_weight: Some(T::WeightInfo::claim_surcharge(code_len / 1024)),
+					pays_fee: Pays::No,
+				})
+				.map_err(Into::into),
+				(None, code_len) => Err(Error::<T>::ContractNotEvictable
+					.with_weight(T::WeightInfo::claim_surcharge(code_len / 1024))),
+			}
+		}
+	}
+
+	#[pallet::event]
+	#[pallet::generate_deposit(pub(super) fn deposit_event)]
+	#[pallet::metadata(T::AccountId = "AccountId", T::Hash = "Hash", BalanceOf<T> = "Balance")]
+	pub enum Event<T: Config> {
+		/// Contract deployed by address at the specified address. \[deployer, contract\]
+		Instantiated(T::AccountId, T::AccountId),
+
+		/// Contract has been evicted and is now in tombstone state. \[contract\]
+		Evicted(T::AccountId),
+
+		/// Contract has been terminated without leaving a tombstone.
+		/// \[contract, beneficiary\]
+		///
+		/// # Params
+		///
+		/// - `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(T::AccountId, T::AccountId),
+
+		/// Restoration of a contract has been successful.
+		/// \[restorer, dest, code_hash, rent_allowance\]
+		///
+		/// # Params
+		///
+		/// - `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(T::AccountId, T::AccountId, T::Hash, BalanceOf<T>),
+
+		/// Code with the specified hash has been stored. \[code_hash\]
+		CodeStored(T::Hash),
+
+		/// Triggered when the current schedule is updated.
+		/// \[version\]
+		///
+		/// # Params
+		///
+		/// - `version`: The version of the newly set schedule.
+		ScheduleUpdated(u32),
+
+		/// 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(T::AccountId, Vec<u8>),
+
+		/// A code with the specified hash was removed.
+		/// \[code_hash\]
+		///
+		/// This happens when the last contract that uses this code hash was removed or evicted.
+		CodeRemoved(T::Hash),
+	}
+
+	#[pallet::error]
+	pub enum Error<T> {
+		/// A new schedule must have a greater version than the current one.
+		InvalidScheduleVersion,
+		/// An origin must be signed or inherent and auxiliary sender only provided on inherent.
+		InvalidSurchargeClaim,
+		/// Cannot restore from nonexisting or tombstone contract.
+		InvalidSourceContract,
+		/// Cannot restore to nonexisting or alive contract.
+		InvalidDestinationContract,
+		/// Tombstones don't match.
+		InvalidTombstone,
+		/// An origin TrieId written in the current block.
+		InvalidContractOrigin,
+		/// The executed contract exhausted its gas limit.
+		OutOfGas,
+		/// The output buffer supplied to a contract API call was too small.
+		OutputBufferTooSmall,
+		/// Performing the requested transfer would have brought the contract below
+		/// the subsistence threshold. No transfer is allowed to do this in order to allow
+		/// for a tombstone to be created. Use `seal_terminate` to remove a contract without
+		/// leaving a tombstone behind.
+		BelowSubsistenceThreshold,
+		/// The newly created contract is below the subsistence threshold after executing
+		/// its contructor. No contracts are allowed to exist below that threshold.
+		NewContractNotFunded,
+		/// Performing the requested transfer failed for a reason originating in the
+		/// chosen currency implementation of the runtime. Most probably the balance is
+		/// too low or locks are placed on it.
+		TransferFailed,
+		/// Performing a call was denied because the calling depth reached the limit
+		/// of what is specified in the schedule.
+		MaxCallDepthReached,
+		/// The contract that was called is either no contract at all (a plain account)
+		/// or is a tombstone.
+		NotCallable,
+		/// The code supplied to `instantiate_with_code` exceeds the limit specified in the
+		/// current schedule.
+		CodeTooLarge,
+		/// No code could be found at the supplied code hash.
+		CodeNotFound,
+		/// A buffer outside of sandbox memory was passed to a contract API function.
+		OutOfBounds,
+		/// Input passed to a contract API function failed to decode as expected type.
+		DecodingFailed,
+		/// Contract trapped during execution.
+		ContractTrapped,
+		/// The size defined in `T::MaxValueSize` was exceeded.
+		ValueTooLarge,
+		/// The action performed is not allowed while the contract performing it is already
+		/// on the call stack. Those actions are contract self destruction and restoration
+		/// of a tombstone.
+		ReentranceDenied,
+		/// `seal_input` was called twice from the same contract execution context.
+		InputAlreadyRead,
+		/// The subject passed to `seal_random` exceeds the limit.
+		RandomSubjectTooLong,
+		/// The amount of topics passed to `seal_deposit_events` exceeds the limit.
+		TooManyTopics,
+		/// The topics passed to `seal_deposit_events` contains at least one duplicate.
+		DuplicateTopics,
+		/// The chain does not provide a chain extension. Calling the chain extension results
+		/// in this error. Note that this usually  shouldn't happen as deploying such contracts
+		/// is rejected.
+		NoChainExtension,
+		/// Removal of a contract failed because the deletion queue is full.
+		///
+		/// This can happen when either calling [`Pallet::claim_surcharge`] or `seal_terminate`.
+		/// The queue is filled by deleting contracts and emptied by a fixed amount each block.
+		/// Trying again during another block is the only way to resolve this issue.
+		DeletionQueueFull,
+		/// A contract could not be evicted because it has enough balance to pay rent.
+		///
+		/// This can be returned from [`Pallet::claim_surcharge`] because the target
+		/// contract has enough balance to pay for its rent.
+		ContractNotEvictable,
+		/// A storage modification exhausted the 32bit type that holds the storage size.
+		///
+		/// This can either happen when the accumulated storage in bytes is too large or
+		/// when number of storage items is too large.
+		StorageExhausted,
+		/// A contract with the same AccountId already exists.
+		DuplicateContract,
+	}
+
+	/// Current cost schedule for contracts.
+	#[pallet::storage]
+	pub(crate) type CurrentSchedule<T: Config> = StorageValue<_, Schedule<T>, ValueQuery>;
+
+	/// A mapping from an original code hash to the original code, untouched by instrumentation.
+	#[pallet::storage]
+	pub(crate) type PristineCode<T: Config> = StorageMap<_, Identity, CodeHash<T>, Vec<u8>>;
+
+	/// A mapping between an original code hash and instrumented wasm code, ready for execution.
+	#[pallet::storage]
+	pub(crate) type CodeStorage<T: Config> =
+		StorageMap<_, Identity, CodeHash<T>, PrefabWasmModule<T>>;
+
+	/// The subtrie counter.
+	#[pallet::storage]
+	pub(crate) type AccountCounter<T: Config> = StorageValue<_, u64, ValueQuery>;
+
+	/// The code associated with a given account.
+	///
+	/// TWOX-NOTE: SAFE since `AccountId` is a secure hash.
+	#[pallet::storage]
+	pub(crate) type ContractInfoOf<T: Config> =
+		StorageMap<_, Twox64Concat, T::AccountId, ContractInfo<T>>;
+
+	/// Evicted contracts that await child trie deletion.
+	///
+	/// Child trie deletion is a heavy operation depending on the amount of storage items
+	/// stored in said trie. Therefore this operation is performed lazily in `on_initialize`.
+	#[pallet::storage]
+	pub(crate) type DeletionQueue<T: Config> = StorageValue<_, Vec<DeletedContract>, ValueQuery>;
+
+	#[pallet::genesis_config]
+	pub struct GenesisConfig<T: Config> {
+		#[doc = "Current cost schedule for contracts."]
+		pub current_schedule: Schedule<T>,
+	}
+
+	#[cfg(feature = "std")]
+	impl<T: Config> Default for GenesisConfig<T> {
+		fn default() -> Self {
+			Self {
+				current_schedule: Default::default(),
+			}
+		}
+	}
+
+	#[pallet::genesis_build]
+	impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
+		fn build(&self) {
+			<CurrentSchedule<T>>::put(&self.current_schedule);
+		}
+	}
+}
+
+impl<T: Config> Pallet<T>
+where
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+{
+	/// Perform a call to a specified contract.
+	///
+	/// This function is similar to [`Self::call`], but doesn't perform any address lookups
+	/// and better suitable for calling directly from Rust.
+	///
+	/// It returns the execution result and the amount of used weight.
+	pub fn bare_call(
+		origin: T::AccountId,
+		dest: T::AccountId,
+		value: BalanceOf<T>,
+		gas_limit: Weight,
+		input_data: Vec<u8>,
+	) -> ContractExecResult {
+		let mut gas_meter = GasMeter::new(gas_limit);
+		let schedule = <CurrentSchedule<T>>::get();
+		let mut ctx = ExecutionContext::<T, PrefabWasmModule<T>>::top_level(origin, &schedule);
+		let result = ctx.call(dest, value, &mut gas_meter, input_data);
+		let gas_consumed = gas_meter.gas_spent();
+		ContractExecResult {
+			result: result.map(|r| r.0).map_err(|r| r.0.error),
+			gas_consumed,
+			debug_message: Bytes(Vec::new()).to_vec(),
+		}
+	}
+
+	/// Instantiate a new contract.
+	///
+	/// This function is similar to [`Self::instantiate`], but doesn't perform any address lookups
+	/// and better suitable for calling directly from Rust.
+	///
+	/// It returns the execution result, account id and the amount of used weight.
+	///
+	/// If `compute_projection` is set to `true` the result also contains the rent projection.
+	/// This is optional because some non trivial and stateful work is performed to compute
+	/// the projection. See [`Self::rent_projection`].
+	pub fn bare_instantiate(
+		origin: T::AccountId,
+		endowment: BalanceOf<T>,
+		gas_limit: Weight,
+		code: Code<CodeHash<T>>,
+		data: Vec<u8>,
+		salt: Vec<u8>,
+		compute_projection: bool,
+	) -> ContractInstantiateResult<T::AccountId, T::BlockNumber> {
+		let mut gas_meter = GasMeter::new(gas_limit);
+		let schedule = <CurrentSchedule<T>>::get();
+		let mut ctx = ExecutionContext::<T, PrefabWasmModule<T>>::top_level(origin, &schedule);
+		let executable = match code {
+			Code::Upload(Bytes(binary)) => PrefabWasmModule::from_code(binary, &schedule),
+			Code::Existing(hash) => PrefabWasmModule::from_storage(hash, &schedule, &mut gas_meter),
+		};
+		let executable = match executable {
+			Ok(executable) => executable,
+			Err(error) => {
+				return ContractInstantiateResult {
+					result: Err(error.into()),
+					gas_consumed: gas_meter.gas_spent(),
+					debug_message: Bytes(Vec::new()).to_vec(),
+				}
+			}
+		};
+		let result = ctx
+			.instantiate(endowment, &mut gas_meter, executable, data, &salt)
+			.and_then(|(account_id, result)| {
+				let rent_projection = if compute_projection {
+					Some(
+						Rent::<T, PrefabWasmModule<T>>::compute_projection(&account_id)
+							.map_err(|_| <Error<T>>::NewContractNotFunded)?,
+					)
+				} else {
+					None
+				};
+
+				Ok(InstantiateReturnValue {
+					result,
+					account_id,
+					rent_projection,
+				})
+			});
+		ContractInstantiateResult {
+			result: result.map_err(|e| e.error),
+			gas_consumed: gas_meter.gas_spent(),
+			debug_message: Bytes(Vec::new()).to_vec(),
+		}
+	}
+
+	/// Query storage of a specified contract under a specified key.
+	pub fn get_storage(address: T::AccountId, key: [u8; 32]) -> GetStorageResult {
+		let contract_info = ContractInfoOf::<T>::get(&address)
+			.ok_or(ContractAccessError::DoesntExist)?
+			.get_alive()
+			.ok_or(ContractAccessError::IsTombstone)?;
+
+		let maybe_value = Storage::<T>::read(&contract_info.trie_id, &key);
+		Ok(maybe_value)
+	}
+
+	/// Query how many blocks the contract stays alive given that the amount endowment
+	/// and consumed storage does not change.
+	pub fn rent_projection(address: T::AccountId) -> RentProjectionResult<T::BlockNumber> {
+		Rent::<T, PrefabWasmModule<T>>::compute_projection(&address)
+	}
+
+	/// Determine the address of a contract,
+	///
+	/// This is the address generation function used by contract instantiation. Its result
+	/// is only dependend on its inputs. It can therefore be used to reliably predict the
+	/// address of a contract. This is akin to the formular of eth's CREATE2 opcode. There
+	/// is no CREATE equivalent because CREATE2 is strictly more powerful.
+	///
+	/// Formula: `hash(deploying_address ++ code_hash ++ salt)`
+	pub fn contract_address(
+		deploying_address: &T::AccountId,
+		code_hash: &CodeHash<T>,
+		salt: &[u8],
+	) -> T::AccountId {
+		let buf: Vec<_> = deploying_address
+			.as_ref()
+			.iter()
+			.chain(code_hash.as_ref())
+			.chain(salt)
+			.cloned()
+			.collect();
+		UncheckedFrom::unchecked_from(T::Hashing::hash(&buf))
+	}
+
+	/// Subsistence threshold is the extension of the minimum balance (aka existential deposit)
+	/// by the tombstone deposit, required for leaving a tombstone.
+	///
+	/// Rent or any contract initiated balance transfer mechanism cannot make the balance lower
+	/// than the subsistence threshold in order to guarantee that a tombstone is created.
+	///
+	/// The only way to completely kill a contract without a tombstone is calling `seal_terminate`.
+	pub fn subsistence_threshold() -> BalanceOf<T> {
+		T::Currency::minimum_balance().saturating_add(T::TombstoneDeposit::get())
+	}
+
+	/// The in-memory size in bytes of the data structure associated with each contract.
+	///
+	/// The data structure is also put into storage for each contract. The in-storage size
+	/// is never larger than the in-memory representation and usually smaller due to compact
+	/// encoding and lack of padding.
+	///
+	/// # Note
+	///
+	/// This returns the in-memory size because the in-storage size (SCALE encoded) cannot
+	/// be efficiently determined. Treat this as an upper bound of the in-storage size.
+	pub fn contract_info_size() -> u32 {
+		sp_std::mem::size_of::<ContractInfo<T>>() as u32
+	}
+
+	/// Store code for benchmarks which does not check nor instrument the code.
+	#[cfg(feature = "runtime-benchmarks")]
+	fn store_code_raw(code: Vec<u8>) -> frame_support::dispatch::DispatchResult {
+		let schedule = <CurrentSchedule<T>>::get();
+		PrefabWasmModule::store_code_unchecked(code, &schedule)?;
+		Ok(())
+	}
+
+	/// This exists so that benchmarks can determine the weight of running an instrumentation.
+	#[cfg(feature = "runtime-benchmarks")]
+	fn reinstrument_module(
+		module: &mut PrefabWasmModule<T>,
+		schedule: &Schedule<T>,
+	) -> frame_support::dispatch::DispatchResult {
+		self::wasm::reinstrument(module, schedule)
+	}
+}
addedpallets/contracts/src/migration.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/migration.rs
@@ -0,0 +1,41 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::{Config, Weight, CurrentSchedule, Pallet, Schedule};
+use frame_support::traits::{GetPalletVersion, PalletVersion, Get};
+
+pub fn migrate<T: Config>() -> Weight {
+	let mut weight: Weight = 0;
+
+	match <Pallet<T>>::storage_version() {
+		// Replace the schedule with the new default and increment its version.
+		Some(version) if version == PalletVersion::new(3, 0, 0) => {
+			weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1));
+			let _ = <CurrentSchedule<T>>::translate::<u32, _>(|version| {
+				version.map(|version| Schedule {
+					version: version.saturating_add(1),
+					// Default limits were not decreased. Therefore it is OK to overwrite
+					// the schedule with the new defaults.
+					..Default::default()
+				})
+			});
+		}
+		_ => (),
+	}
+
+	weight
+}
addedpallets/contracts/src/rent.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/rent.rs
@@ -0,0 +1,553 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! A module responsible for computing the right amount of weight and charging it.
+
+use crate::{
+	AliveContractInfo, BalanceOf, ContractInfo, ContractInfoOf, Pallet, Event,
+	TombstoneContractInfo, Config, CodeHash, Error, storage::Storage, wasm::PrefabWasmModule,
+	exec::Executable,
+};
+use sp_std::prelude::*;
+use sp_io::hashing::blake2_256;
+use sp_core::crypto::UncheckedFrom;
+use frame_support::{
+	storage::child,
+	traits::{Currency, ExistenceRequirement, Get, OnUnbalanced, WithdrawReasons},
+};
+use pallet_contracts_primitives::{ContractAccessError, RentProjection, RentProjectionResult};
+use sp_runtime::{
+	DispatchError,
+	traits::{Bounded, CheckedDiv, CheckedMul, SaturatedConversion, Saturating, Zero},
+};
+
+/// The amount to charge.
+///
+/// This amount respects the contract's rent allowance and the subsistence deposit.
+/// Because of that, charging the amount cannot remove the contract.
+struct OutstandingAmount<T: Config> {
+	amount: BalanceOf<T>,
+}
+
+impl<T: Config> OutstandingAmount<T> {
+	/// Create the new outstanding amount.
+	///
+	/// The amount should be always withdrawable and it should not kill the account.
+	fn new(amount: BalanceOf<T>) -> Self {
+		Self { amount }
+	}
+
+	/// Returns the amount this instance wraps.
+	fn peek(&self) -> BalanceOf<T> {
+		self.amount
+	}
+
+	/// Withdraws the outstanding amount from the given account.
+	fn withdraw(self, account: &T::AccountId) {
+		if let Ok(imbalance) = T::Currency::withdraw(
+			account,
+			self.amount,
+			WithdrawReasons::FEE,
+			ExistenceRequirement::KeepAlive,
+		) {
+			// This should never fail. However, let's err on the safe side.
+			T::RentPayment::on_unbalanced(imbalance);
+		}
+	}
+}
+
+enum Verdict<T: Config> {
+	/// The contract is exempted from paying rent.
+	///
+	/// For example, it already paid its rent in the current block, or it has enough deposit for not
+	/// paying rent at all.
+	Exempt,
+	/// The contract cannot afford payment within its rent budget so it gets evicted. However,
+	/// because its balance is greater than the subsistence threshold it leaves a tombstone.
+	Evict {
+		amount: Option<OutstandingAmount<T>>,
+	},
+	/// Everything is OK, we just only take some charge.
+	Charge { amount: OutstandingAmount<T> },
+}
+
+pub struct Rent<T, E>(sp_std::marker::PhantomData<(T, E)>);
+
+impl<T, E> Rent<T, E>
+where
+	T: Config,
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+	E: Executable<T>,
+{
+	/// Returns a fee charged per block from the contract.
+	///
+	/// This function accounts for the storage rent deposit. I.e. if the contract possesses enough funds
+	/// then the fee can drop to zero.
+	fn compute_fee_per_block(
+		free_balance: &BalanceOf<T>,
+		contract: &AliveContractInfo<T>,
+		code_size_share: u32,
+	) -> BalanceOf<T> {
+		let uncovered_by_balance = T::DepositPerStorageByte::get()
+			.saturating_mul(contract.storage_size.saturating_add(code_size_share).into())
+			.saturating_add(
+				T::DepositPerStorageItem::get().saturating_mul(contract.pair_count.into()),
+			)
+			.saturating_add(T::DepositPerContract::get())
+			.saturating_sub(*free_balance);
+		T::RentFraction::get().mul_ceil(uncovered_by_balance)
+	}
+
+	/// Returns amount of funds available to consume by rent mechanism.
+	///
+	/// Rent mechanism cannot consume more than `rent_allowance` set by the contract and it cannot make
+	/// the balance lower than [`subsistence_threshold`].
+	///
+	/// In case the toal_balance is below the subsistence threshold, this function returns `None`.
+	fn rent_budget(
+		total_balance: &BalanceOf<T>,
+		free_balance: &BalanceOf<T>,
+		contract: &AliveContractInfo<T>,
+	) -> Option<BalanceOf<T>> {
+		let subsistence_threshold = Pallet::<T>::subsistence_threshold();
+		// Reserved balance contributes towards the subsistence threshold to stay consistent
+		// with the existential deposit where the reserved balance is also counted.
+		if *total_balance < subsistence_threshold {
+			return None;
+		}
+
+		// However, reserved balance cannot be charged so we need to use the free balance
+		// to calculate the actual budget (which can be 0).
+		let rent_allowed_to_charge = free_balance.saturating_sub(subsistence_threshold);
+		Some(<BalanceOf<T>>::min(
+			contract.rent_allowance,
+			rent_allowed_to_charge,
+		))
+	}
+
+	/// Consider the case for rent payment of the given account and returns a `Verdict`.
+	///
+	/// Use `handicap` in case you want to change the reference block number. (To get more details see
+	/// `try_eviction` ).
+	fn consider_case(
+		account: &T::AccountId,
+		current_block_number: T::BlockNumber,
+		handicap: T::BlockNumber,
+		contract: &AliveContractInfo<T>,
+		code_size: u32,
+	) -> Verdict<T> {
+		// How much block has passed since the last deduction for the contract.
+		let blocks_passed = {
+			// Calculate an effective block number, i.e. after adjusting for handicap.
+			let effective_block_number = current_block_number.saturating_sub(handicap);
+			effective_block_number.saturating_sub(contract.deduct_block)
+		};
+		if blocks_passed.is_zero() {
+			// Rent has already been paid
+			return Verdict::Exempt;
+		}
+
+		let total_balance = T::Currency::total_balance(account);
+		let free_balance = T::Currency::free_balance(account);
+
+		// An amount of funds to charge per block for storage taken up by the contract.
+		let fee_per_block = Self::compute_fee_per_block(&free_balance, contract, code_size);
+		if fee_per_block.is_zero() {
+			// The rent deposit offset reduced the fee to 0. This means that the contract
+			// gets the rent for free.
+			return Verdict::Exempt;
+		}
+
+		let rent_budget = match Self::rent_budget(&total_balance, &free_balance, contract) {
+			Some(rent_budget) => rent_budget,
+			None => {
+				// All functions that allow a contract to transfer balance enforce
+				// that the contract always stays above the subsistence threshold.
+				// We want the rent system to always leave a tombstone to prevent the
+				// accidental loss of a contract. Ony `seal_terminate` can remove a
+				// contract without a tombstone. Therefore this case should be never
+				// hit.
+				log::error!(
+					target: "runtime::contracts",
+					"Tombstoned a contract that is below the subsistence threshold: {:?}",
+					account,
+				);
+				0u32.into()
+			}
+		};
+
+		let dues = fee_per_block
+			.checked_mul(&blocks_passed.saturated_into::<u32>().into())
+			.unwrap_or_else(|| <BalanceOf<T>>::max_value());
+		let insufficient_rent = rent_budget < dues;
+
+		// If the rent payment cannot be withdrawn due to locks on the account balance, then evict the
+		// account.
+		//
+		// NOTE: This seems problematic because it provides a way to tombstone an account while
+		// avoiding the last rent payment. In effect, someone could retroactively set rent_allowance
+		// for their contract to 0.
+		let dues_limited = dues.min(rent_budget);
+		let can_withdraw_rent = T::Currency::ensure_can_withdraw(
+			account,
+			dues_limited,
+			WithdrawReasons::FEE,
+			free_balance.saturating_sub(dues_limited),
+		)
+		.is_ok();
+
+		if insufficient_rent || !can_withdraw_rent {
+			// The contract cannot afford the rent payment and has a balance above the subsistence
+			// threshold, so it leaves a tombstone.
+			let amount = if can_withdraw_rent {
+				Some(OutstandingAmount::new(dues_limited))
+			} else {
+				None
+			};
+			return Verdict::Evict { amount };
+		}
+
+		return Verdict::Charge {
+			// We choose to use `dues_limited` here instead of `dues` just to err on the safer side.
+			amount: OutstandingAmount::new(dues_limited),
+		};
+	}
+
+	/// Enacts the given verdict and returns the updated `ContractInfo`.
+	///
+	/// `alive_contract_info` should be from the same address as `account`.
+	///
+	/// # Note
+	///
+	/// if `evictable_code` is `None` an `Evict` verdict will not be enacted. This is for
+	/// when calling this function during a `call` where access to the soon to be evicted
+	/// contract should be denied but storage should be left unmodified.
+	fn enact_verdict(
+		account: &T::AccountId,
+		alive_contract_info: AliveContractInfo<T>,
+		current_block_number: T::BlockNumber,
+		verdict: Verdict<T>,
+		evictable_code: Option<PrefabWasmModule<T>>,
+	) -> Result<Option<AliveContractInfo<T>>, DispatchError> {
+		match (verdict, evictable_code) {
+			(Verdict::Evict { amount }, Some(code)) => {
+				// We need to remove the trie first because it is the only operation
+				// that can fail and this function is called without a storage
+				// transaction when called through `claim_surcharge`.
+				Storage::<T>::queue_trie_for_deletion(&alive_contract_info)?;
+
+				if let Some(amount) = amount {
+					amount.withdraw(account);
+				}
+
+				// Note: this operation is heavy.
+				let child_storage_root = child::root(&alive_contract_info.child_trie_info());
+
+				let tombstone = <TombstoneContractInfo<T>>::new(
+					&child_storage_root[..],
+					alive_contract_info.code_hash,
+				);
+				let tombstone_info = ContractInfo::Tombstone(tombstone);
+				<ContractInfoOf<T>>::insert(account, &tombstone_info);
+				code.drop_from_storage();
+				<Pallet<T>>::deposit_event(Event::Evicted(account.clone()));
+				Ok(None)
+			}
+			(Verdict::Evict { amount: _ }, None) => Ok(None),
+			(Verdict::Exempt, _) => {
+				let contract = ContractInfo::Alive(AliveContractInfo::<T> {
+					deduct_block: current_block_number,
+					..alive_contract_info
+				});
+				<ContractInfoOf<T>>::insert(account, &contract);
+				Ok(Some(
+					contract
+						.get_alive()
+						.expect("We just constructed it as alive. qed"),
+				))
+			}
+			(Verdict::Charge { amount }, _) => {
+				let contract = ContractInfo::Alive(AliveContractInfo::<T> {
+					rent_allowance: alive_contract_info.rent_allowance - amount.peek(),
+					deduct_block: current_block_number,
+					rent_payed: alive_contract_info.rent_payed.saturating_add(amount.peek()),
+					..alive_contract_info
+				});
+				<ContractInfoOf<T>>::insert(account, &contract);
+				amount.withdraw(account);
+				Ok(Some(
+					contract
+						.get_alive()
+						.expect("We just constructed it as alive. qed"),
+				))
+			}
+		}
+	}
+
+	/// Make account paying the rent for the current block number
+	///
+	/// This functions does **not** evict the contract. It returns `None` in case the
+	/// contract is in need of eviction. [`try_eviction`] must
+	/// be called to perform the eviction.
+	pub fn charge(
+		account: &T::AccountId,
+		contract: AliveContractInfo<T>,
+		code_size: u32,
+	) -> Result<Option<AliveContractInfo<T>>, DispatchError> {
+		let current_block_number = <frame_system::Pallet<T>>::block_number();
+		let verdict = Self::consider_case(
+			account,
+			current_block_number,
+			Zero::zero(),
+			&contract,
+			code_size,
+		);
+		Self::enact_verdict(account, contract, current_block_number, verdict, None)
+	}
+
+	/// Process a report that a contract under the given address should be evicted.
+	///
+	/// Enact the eviction right away if the contract should be evicted and return the amount
+	/// of rent that the contract payed over its lifetime.
+	/// Otherwise, **do nothing** and return None.
+	///
+	/// The `handicap` parameter gives a way to check the rent to a moment in the past instead
+	/// of current block. E.g. if the contract is going to be evicted at the current block,
+	/// `handicap = 1` can defer the eviction for 1 block. This is useful to handicap certain snitchers
+	/// relative to others.
+	///
+	/// NOTE this function performs eviction eagerly. All changes are read and written directly to
+	/// storage.
+	pub fn try_eviction(
+		account: &T::AccountId,
+		handicap: T::BlockNumber,
+	) -> Result<(Option<BalanceOf<T>>, u32), DispatchError> {
+		let contract = <ContractInfoOf<T>>::get(account);
+		let contract = match contract {
+			None | Some(ContractInfo::Tombstone(_)) => return Ok((None, 0)),
+			Some(ContractInfo::Alive(contract)) => contract,
+		};
+		let module = PrefabWasmModule::<T>::from_storage_noinstr(contract.code_hash)?;
+		let code_len = module.code_len();
+		let current_block_number = <frame_system::Pallet<T>>::block_number();
+		let verdict = Self::consider_case(
+			account,
+			current_block_number,
+			handicap,
+			&contract,
+			module.occupied_storage(),
+		);
+
+		// Enact the verdict only if the contract gets removed.
+		match verdict {
+			Verdict::Evict { ref amount } => {
+				// The outstanding `amount` is withdrawn inside `enact_verdict`.
+				let rent_payed = amount
+					.as_ref()
+					.map(|a| a.peek())
+					.unwrap_or_else(|| <BalanceOf<T>>::zero())
+					.saturating_add(contract.rent_payed);
+				Self::enact_verdict(
+					account,
+					contract,
+					current_block_number,
+					verdict,
+					Some(module),
+				)?;
+				Ok((Some(rent_payed), code_len))
+			}
+			_ => Ok((None, code_len)),
+		}
+	}
+
+	/// Returns the projected time a given contract will be able to sustain paying its rent. The
+	/// returned projection is relevant for the current block, i.e. it is as if the contract was
+	/// accessed at the beginning of the current block. Returns `None` in case if the contract was
+	/// evicted before or as a result of the rent collection.
+	///
+	/// The returned value is only an estimation. It doesn't take into account any top ups, changing the
+	/// rent allowance, or any problems coming from withdrawing the dues.
+	///
+	/// NOTE that this is not a side-effect free function! It will actually collect rent and then
+	/// compute the projection. This function is only used for implementation of an RPC method through
+	/// `RuntimeApi` meaning that the changes will be discarded anyway.
+	pub fn compute_projection(account: &T::AccountId) -> RentProjectionResult<T::BlockNumber> {
+		use ContractAccessError::IsTombstone;
+
+		let contract_info = <ContractInfoOf<T>>::get(account);
+		let alive_contract_info = match contract_info {
+			None | Some(ContractInfo::Tombstone(_)) => return Err(IsTombstone),
+			Some(ContractInfo::Alive(contract)) => contract,
+		};
+		let module = <PrefabWasmModule<T>>::from_storage_noinstr(alive_contract_info.code_hash)
+			.map_err(|_| IsTombstone)?;
+		let code_size = module.occupied_storage();
+		let current_block_number = <frame_system::Pallet<T>>::block_number();
+		let verdict = Self::consider_case(
+			account,
+			current_block_number,
+			Zero::zero(),
+			&alive_contract_info,
+			code_size,
+		);
+
+		// We skip the eviction in case one is in order.
+		// Evictions should only be performed by [`try_eviction`].
+		let new_contract_info = Self::enact_verdict(
+			account,
+			alive_contract_info,
+			current_block_number,
+			verdict,
+			None,
+		);
+
+		// Check what happened after enaction of the verdict.
+		let alive_contract_info = new_contract_info
+			.map_err(|_| IsTombstone)?
+			.ok_or_else(|| IsTombstone)?;
+
+		// Compute how much would the fee per block be with the *updated* balance.
+		let total_balance = T::Currency::total_balance(account);
+		let free_balance = T::Currency::free_balance(account);
+		let fee_per_block =
+			Self::compute_fee_per_block(&free_balance, &alive_contract_info, code_size);
+		if fee_per_block.is_zero() {
+			return Ok(RentProjection::NoEviction);
+		}
+
+		// Then compute how much the contract will sustain under these circumstances.
+		let rent_budget = Self::rent_budget(&total_balance, &free_balance, &alive_contract_info)
+			.expect(
+				"the contract exists and in the alive state;
+			the updated balance must be greater than subsistence deposit;
+			this function doesn't return `None`;
+			qed
+			",
+			);
+		let blocks_left = match rent_budget.checked_div(&fee_per_block) {
+			Some(blocks_left) => blocks_left,
+			None => {
+				// `fee_per_block` is not zero here, so `checked_div` can return `None` if
+				// there is an overflow. This cannot happen with integers though. Return
+				// `NoEviction` here just in case.
+				return Ok(RentProjection::NoEviction);
+			}
+		};
+
+		let blocks_left = blocks_left.saturated_into::<u32>().into();
+		Ok(RentProjection::EvictionAt(
+			current_block_number + blocks_left,
+		))
+	}
+
+	/// Restores the destination account using the origin as prototype.
+	///
+	/// The restoration will be performed iff:
+	/// - the supplied code_hash does still exist on-chain
+	/// - origin exists and is alive,
+	/// - the origin's storage is not written in the current block
+	/// - the restored account has tombstone
+	/// - the tombstone matches the hash of the origin storage root, and code hash.
+	///
+	/// Upon succesful restoration, `origin` will be destroyed, all its funds are transferred to
+	/// the restored account. The restored account will inherit the last write block and its last
+	/// deduct block will be set to the current block.
+	///
+	/// # Return Value
+	///
+	/// Result<(CallerCodeSize, DestCodeSize), (DispatchError, CallerCodeSize, DestCodesize)>
+	pub fn restore_to(
+		origin: T::AccountId,
+		dest: T::AccountId,
+		code_hash: CodeHash<T>,
+		rent_allowance: BalanceOf<T>,
+		delta: Vec<crate::exec::StorageKey>,
+	) -> Result<(u32, u32), (DispatchError, u32, u32)> {
+		let mut origin_contract = <ContractInfoOf<T>>::get(&origin)
+			.and_then(|c| c.get_alive())
+			.ok_or((Error::<T>::InvalidSourceContract.into(), 0, 0))?;
+
+		let child_trie_info = origin_contract.child_trie_info();
+
+		let current_block = <frame_system::Pallet<T>>::block_number();
+
+		if origin_contract.last_write == Some(current_block) {
+			return Err((Error::<T>::InvalidContractOrigin.into(), 0, 0));
+		}
+
+		let dest_tombstone = <ContractInfoOf<T>>::get(&dest)
+			.and_then(|c| c.get_tombstone())
+			.ok_or((Error::<T>::InvalidDestinationContract.into(), 0, 0))?;
+
+		let last_write = if !delta.is_empty() {
+			Some(current_block)
+		} else {
+			origin_contract.last_write
+		};
+
+		// Fails if the code hash does not exist on chain
+		let caller_code_len = E::add_user(code_hash).map_err(|e| (e, 0, 0))?;
+
+		// We are allowed to eagerly modify storage even though the function can
+		// fail later due to tombstones not matching. This is because the restoration
+		// is always called from a contract and therefore in a storage transaction.
+		// The failure of this function will lead to this transaction's rollback.
+		let bytes_taken: u32 = delta
+			.iter()
+			.filter_map(|key| {
+				let key = blake2_256(key);
+				child::get_raw(&child_trie_info, &key).map(|value| {
+					child::kill(&child_trie_info, &key);
+					value.len() as u32
+				})
+			})
+			.sum();
+
+		let tombstone = <TombstoneContractInfo<T>>::new(
+			// This operation is cheap enough because last_write (delta not included)
+			// is not this block as it has been checked earlier.
+			&child::root(&child_trie_info)[..],
+			code_hash,
+		);
+
+		if tombstone != dest_tombstone {
+			return Err((Error::<T>::InvalidTombstone.into(), caller_code_len, 0));
+		}
+
+		origin_contract.storage_size -= bytes_taken;
+
+		<ContractInfoOf<T>>::remove(&origin);
+		let tombstone_code_len = E::remove_user(origin_contract.code_hash);
+		<ContractInfoOf<T>>::insert(
+			&dest,
+			ContractInfo::Alive(AliveContractInfo::<T> {
+				code_hash,
+				rent_allowance,
+				rent_payed: <BalanceOf<T>>::zero(),
+				deduct_block: current_block,
+				last_write,
+				..origin_contract
+			}),
+		);
+
+		let origin_free_balance = T::Currency::free_balance(&origin);
+		T::Currency::make_free_balance_be(&origin, <BalanceOf<T>>::zero());
+		T::Currency::deposit_creating(&dest, origin_free_balance);
+
+		Ok((caller_code_len, tombstone_code_len))
+	}
+}
addedpallets/contracts/src/schedule.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/schedule.rs
@@ -0,0 +1,806 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This module contains the cost schedule and supporting code that constructs a
+//! sane default schedule from a `WeightInfo` implementation.
+
+use crate::{Config, weights::WeightInfo};
+
+#[cfg(feature = "std")]
+use serde::{Serialize, Deserialize};
+use pallet_contracts_proc_macro::{ScheduleDebug, WeightDebug};
+use frame_support::weights::Weight;
+use sp_std::{marker::PhantomData, vec::Vec};
+use codec::{Encode, Decode};
+use parity_wasm::elements;
+use pwasm_utils::rules;
+use sp_runtime::RuntimeDebug;
+
+/// How many API calls are executed in a single batch. The reason for increasing the amount
+/// of API calls in batches (per benchmark component increase) is so that the linear regression
+/// has an easier time determining the contribution of that component.
+pub const API_BENCHMARK_BATCH_SIZE: u32 = 100;
+
+/// How many instructions are executed in a single batch. The reasoning is the same
+/// as for `API_BENCHMARK_BATCH_SIZE`.
+pub const INSTR_BENCHMARK_BATCH_SIZE: u32 = 1_000;
+
+/// Definition of the cost schedule and other parameterizations for the wasm vm.
+///
+/// Its fields are private to the crate in order to allow addition of new contract
+/// callable functions without bumping to a new major version. A genesis config should
+/// rely on public functions of this type.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "std", serde(bound(serialize = "", deserialize = "")))]
+#[derive(Clone, Encode, Decode, PartialEq, Eq, ScheduleDebug)]
+pub struct Schedule<T: Config> {
+	/// Version of the schedule.
+	///
+	/// # Note
+	///
+	/// Must be incremented whenever the [`self.instruction_weights`] are changed. The
+	/// reason is that changes to instruction weights require a re-instrumentation
+	/// of all contracts which are triggered by a version comparison on call.
+	/// Changes to other parts of the schedule should not increment the version in
+	/// order to avoid unnecessary re-instrumentations.
+	pub(crate) version: u32,
+
+	/// Whether the `seal_println` function is allowed to be used contracts.
+	/// MUST only be enabled for `dev` chains, NOT for production chains
+	pub(crate) enable_println: bool,
+
+	/// Describes the upper limits on various metrics.
+	pub(crate) limits: Limits,
+
+	/// The weights for individual wasm instructions.
+	pub(crate) instruction_weights: InstructionWeights<T>,
+
+	/// The weights for each imported function a contract is allowed to call.
+	pub(crate) host_fn_weights: HostFnWeights<T>,
+}
+
+/// Describes the upper limits on various metrics.
+///
+/// # Note
+///
+/// The values in this struct should only ever be increased for a deployed chain. The reason
+/// is that decreasing those values will break existing contracts which are above the new limits.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)]
+pub struct Limits {
+	/// The maximum number of topics supported by an event.
+	pub event_topics: u32,
+
+	/// Maximum allowed stack height in number of elements.
+	///
+	/// See <https://wiki.parity.io/WebAssembly-StackHeight> to find out
+	/// how the stack frame cost is calculated. Each element can be of one of the
+	/// wasm value types. This means the maximum size per element is 64bit.
+	pub stack_height: u32,
+
+	/// Maximum number of globals a module is allowed to declare.
+	///
+	/// Globals are not limited through the `stack_height` as locals are. Neither does
+	/// the linear memory limit `memory_pages` applies to them.
+	pub globals: u32,
+
+	/// Maximum numbers of parameters a function can have.
+	///
+	/// Those need to be limited to prevent a potentially exploitable interaction with
+	/// the stack height instrumentation: The costs of executing the stack height
+	/// instrumentation for an indirectly called function scales linearly with the amount
+	/// of parameters of this function. Because the stack height instrumentation itself is
+	/// is not weight metered its costs must be static (via this limit) and included in
+	/// the costs of the instructions that cause them (call, call_indirect).
+	pub parameters: u32,
+
+	/// Maximum number of memory pages allowed for a contract.
+	pub memory_pages: u32,
+
+	/// Maximum number of elements allowed in a table.
+	///
+	/// Currently, the only type of element that is allowed in a table is funcref.
+	pub table_size: u32,
+
+	/// Maximum number of elements that can appear as immediate value to the br_table instruction.
+	pub br_table_size: u32,
+
+	/// The maximum length of a subject in bytes used for PRNG generation.
+	pub subject_len: u32,
+}
+
+impl Limits {
+	/// The maximum memory size in bytes that a contract can occupy.
+	pub fn max_memory_size(&self) -> u32 {
+		self.memory_pages * 64 * 1024
+	}
+}
+
+/// Describes the weight for all categories of supported wasm instructions.
+///
+/// There there is one field for each wasm instruction that describes the weight to
+/// execute one instruction of that name. There are a few execptions:
+///
+/// 1. If there is a i64 and a i32 variant of an instruction we use the weight
+///    of the former for both.
+/// 2. The following instructions are free of charge because they merely structure the
+///    wasm module and cannot be spammed without making the module invalid (and rejected):
+///    End, Unreachable, Return, Else
+/// 3. The following instructions cannot be benchmarked because they are removed by any
+///    real world execution engine as a preprocessing step and therefore don't yield a
+///    meaningful benchmark result. However, in contrast to the instructions mentioned
+///    in 2. they can be spammed. We price them with the same weight as the "default"
+///    instruction (i64.const): Block, Loop, Nop
+/// 4. We price both i64.const and drop as InstructionWeights.i64const / 2. The reason
+///    for that is that we cannot benchmark either of them on its own but we need their
+///    individual values to derive (by subtraction) the weight of all other instructions
+///    that use them as supporting instructions. Supporting means mainly pushing arguments
+///    and dropping return values in order to maintain a valid module.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[derive(Clone, Encode, Decode, PartialEq, Eq, WeightDebug)]
+pub struct InstructionWeights<T: Config> {
+	pub i64const: u32,
+	pub i64load: u32,
+	pub i64store: u32,
+	pub select: u32,
+	pub r#if: u32,
+	pub br: u32,
+	pub br_if: u32,
+	pub br_table: u32,
+	pub br_table_per_entry: u32,
+	pub call: u32,
+	pub call_indirect: u32,
+	pub call_indirect_per_param: u32,
+	pub local_get: u32,
+	pub local_set: u32,
+	pub local_tee: u32,
+	pub global_get: u32,
+	pub global_set: u32,
+	pub memory_current: u32,
+	pub memory_grow: u32,
+	pub i64clz: u32,
+	pub i64ctz: u32,
+	pub i64popcnt: u32,
+	pub i64eqz: u32,
+	pub i64extendsi32: u32,
+	pub i64extendui32: u32,
+	pub i32wrapi64: u32,
+	pub i64eq: u32,
+	pub i64ne: u32,
+	pub i64lts: u32,
+	pub i64ltu: u32,
+	pub i64gts: u32,
+	pub i64gtu: u32,
+	pub i64les: u32,
+	pub i64leu: u32,
+	pub i64ges: u32,
+	pub i64geu: u32,
+	pub i64add: u32,
+	pub i64sub: u32,
+	pub i64mul: u32,
+	pub i64divs: u32,
+	pub i64divu: u32,
+	pub i64rems: u32,
+	pub i64remu: u32,
+	pub i64and: u32,
+	pub i64or: u32,
+	pub i64xor: u32,
+	pub i64shl: u32,
+	pub i64shrs: u32,
+	pub i64shru: u32,
+	pub i64rotl: u32,
+	pub i64rotr: u32,
+	/// The type parameter is used in the default implementation.
+	#[codec(skip)]
+	pub _phantom: PhantomData<T>,
+}
+
+/// Describes the weight for each imported function that a contract is allowed to call.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[derive(Clone, Encode, Decode, PartialEq, Eq, WeightDebug)]
+pub struct HostFnWeights<T: Config> {
+	/// Weight of calling `seal_caller`.
+	pub caller: Weight,
+
+	/// Weight of calling `seal_address`.
+	pub address: Weight,
+
+	/// Weight of calling `seal_gas_left`.
+	pub gas_left: Weight,
+
+	/// Weight of calling `seal_balance`.
+	pub balance: Weight,
+
+	/// Weight of calling `seal_value_transferred`.
+	pub value_transferred: Weight,
+
+	/// Weight of calling `seal_minimum_balance`.
+	pub minimum_balance: Weight,
+
+	/// Weight of calling `seal_tombstone_deposit`.
+	pub tombstone_deposit: Weight,
+
+	/// Weight of calling `seal_rent_allowance`.
+	pub rent_allowance: Weight,
+
+	/// Weight of calling `seal_block_number`.
+	pub block_number: Weight,
+
+	/// Weight of calling `seal_now`.
+	pub now: Weight,
+
+	/// Weight of calling `seal_weight_to_fee`.
+	pub weight_to_fee: Weight,
+
+	/// Weight of calling `gas`.
+	pub gas: Weight,
+
+	/// Weight of calling `seal_input`.
+	pub input: Weight,
+
+	/// Weight per input byte copied to contract memory by `seal_input`.
+	pub input_per_byte: Weight,
+
+	/// Weight of calling `seal_return`.
+	pub r#return: Weight,
+
+	/// Weight per byte returned through `seal_return`.
+	pub return_per_byte: Weight,
+
+	/// Weight of calling `seal_terminate`.
+	pub terminate: Weight,
+
+	/// Weight per byte of the terminated contract.
+	pub terminate_per_code_byte: Weight,
+
+	/// Weight of calling `seal_restore_to`.
+	pub restore_to: Weight,
+
+	/// Weight per byte of the restoring contract.
+	pub restore_to_per_caller_code_byte: Weight,
+
+	/// Weight per byte of the restored contract.
+	pub restore_to_per_tombstone_code_byte: Weight,
+
+	/// Weight per delta key supplied to `seal_restore_to`.
+	pub restore_to_per_delta: Weight,
+
+	/// Weight of calling `seal_random`.
+	pub random: Weight,
+
+	/// Weight of calling `seal_reposit_event`.
+	pub deposit_event: Weight,
+
+	/// Weight per topic supplied to `seal_deposit_event`.
+	pub deposit_event_per_topic: Weight,
+
+	/// Weight per byte of an event deposited through `seal_deposit_event`.
+	pub deposit_event_per_byte: Weight,
+
+	/// Weight of calling `seal_set_rent_allowance`.
+	pub set_rent_allowance: Weight,
+
+	/// Weight of calling `seal_set_storage`.
+	pub set_storage: Weight,
+
+	/// Weight per byte of an item stored with `seal_set_storage`.
+	pub set_storage_per_byte: Weight,
+
+	/// Weight of calling `seal_clear_storage`.
+	pub clear_storage: Weight,
+
+	/// Weight of calling `seal_get_storage`.
+	pub get_storage: Weight,
+
+	/// Weight per byte of an item received via `seal_get_storage`.
+	pub get_storage_per_byte: Weight,
+
+	/// Weight of calling `seal_transfer`.
+	pub transfer: Weight,
+
+	/// Weight of calling `seal_call`.
+	pub call: Weight,
+
+	/// Weight per byte of the called contract.
+	pub call_per_code_byte: Weight,
+
+	/// Weight surcharge that is claimed if `seal_call` does a balance transfer.
+	pub call_transfer_surcharge: Weight,
+
+	/// Weight per input byte supplied to `seal_call`.
+	pub call_per_input_byte: Weight,
+
+	/// Weight per output byte received through `seal_call`.
+	pub call_per_output_byte: Weight,
+
+	/// Weight of calling `seal_instantiate`.
+	pub instantiate: Weight,
+
+	/// Weight per byte of the instantiated contract.
+	pub instantiate_per_code_byte: Weight,
+
+	/// Weight per input byte supplied to `seal_instantiate`.
+	pub instantiate_per_input_byte: Weight,
+
+	/// Weight per output byte received through `seal_instantiate`.
+	pub instantiate_per_output_byte: Weight,
+
+	/// Weight per salt byte supplied to `seal_instantiate`.
+	pub instantiate_per_salt_byte: Weight,
+
+	/// Weight of calling `seal_hash_sha_256`.
+	pub hash_sha2_256: Weight,
+
+	/// Weight per byte hashed by `seal_hash_sha_256`.
+	pub hash_sha2_256_per_byte: Weight,
+
+	/// Weight of calling `seal_hash_keccak_256`.
+	pub hash_keccak_256: Weight,
+
+	/// Weight per byte hashed by `seal_hash_keccak_256`.
+	pub hash_keccak_256_per_byte: Weight,
+
+	/// Weight of calling `seal_hash_blake2_256`.
+	pub hash_blake2_256: Weight,
+
+	/// Weight per byte hashed by `seal_hash_blake2_256`.
+	pub hash_blake2_256_per_byte: Weight,
+
+	/// Weight of calling `seal_hash_blake2_128`.
+	pub hash_blake2_128: Weight,
+
+	/// Weight per byte hashed by `seal_hash_blake2_128`.
+	pub hash_blake2_128_per_byte: Weight,
+
+	/// Weight of calling `seal_rent_params`.
+	pub rent_params: Weight,
+
+	/// The type parameter is used in the default implementation.
+	#[codec(skip)]
+	pub _phantom: PhantomData<T>,
+}
+
+macro_rules! replace_token {
+	($_in:tt $replacement:tt) => {
+		$replacement
+	};
+}
+
+macro_rules! call_zero {
+	($name:ident, $( $arg:expr ),*) => {
+		T::WeightInfo::$name($( replace_token!($arg 0) ),*)
+	};
+}
+
+macro_rules! cost_args {
+	($name:ident, $( $arg: expr ),+) => {
+		(T::WeightInfo::$name($( $arg ),+).saturating_sub(call_zero!($name, $( $arg ),+)))
+	}
+}
+
+macro_rules! cost_batched_args {
+	($name:ident, $( $arg: expr ),+) => {
+		cost_args!($name, $( $arg ),+) / Weight::from(API_BENCHMARK_BATCH_SIZE)
+	}
+}
+
+macro_rules! cost_instr_no_params_with_batch_size {
+	($name:ident, $batch_size:expr) => {
+		(cost_args!($name, 1) / Weight::from($batch_size)) as u32
+	};
+}
+
+macro_rules! cost_instr_with_batch_size {
+	($name:ident, $num_params:expr, $batch_size:expr) => {
+		cost_instr_no_params_with_batch_size!($name, $batch_size).saturating_sub(
+			(cost_instr_no_params_with_batch_size!(instr_i64const, $batch_size) / 2)
+				.saturating_mul($num_params),
+		)
+	};
+}
+
+macro_rules! cost_instr {
+	($name:ident, $num_params:expr) => {
+		cost_instr_with_batch_size!($name, $num_params, INSTR_BENCHMARK_BATCH_SIZE)
+	};
+}
+
+macro_rules! cost_byte_args {
+	($name:ident, $( $arg: expr ),+) => {
+		cost_args!($name, $( $arg ),+) / 1024
+	}
+}
+
+macro_rules! cost_byte_batched_args {
+	($name:ident, $( $arg: expr ),+) => {
+		cost_batched_args!($name, $( $arg ),+) / 1024
+	}
+}
+
+macro_rules! cost {
+	($name:ident) => {
+		cost_args!($name, 1)
+	};
+}
+
+macro_rules! cost_batched {
+	($name:ident) => {
+		cost_batched_args!($name, 1)
+	};
+}
+
+macro_rules! cost_byte {
+	($name:ident) => {
+		cost_byte_args!($name, 1)
+	};
+}
+
+macro_rules! cost_byte_batched {
+	($name:ident) => {
+		cost_byte_batched_args!($name, 1)
+	};
+}
+
+impl<T: Config> Default for Schedule<T> {
+	fn default() -> Self {
+		Self {
+			version: 0,
+			enable_println: false,
+			limits: Default::default(),
+			instruction_weights: Default::default(),
+			host_fn_weights: Default::default(),
+		}
+	}
+}
+
+impl Default for Limits {
+	fn default() -> Self {
+		Self {
+			event_topics: 4,
+			// 512 * sizeof(i64) will give us a 4k stack.
+			stack_height: 512,
+			globals: 256,
+			parameters: 128,
+			memory_pages: 16,
+			// 4k function pointers (This is in count not bytes).
+			table_size: 4096,
+			br_table_size: 256,
+			subject_len: 32,
+		}
+	}
+}
+
+impl<T: Config> Default for InstructionWeights<T> {
+	fn default() -> Self {
+		let max_pages = Limits::default().memory_pages;
+		Self {
+			i64const: cost_instr!(instr_i64const, 1),
+			i64load: cost_instr!(instr_i64load, 2),
+			i64store: cost_instr!(instr_i64store, 2),
+			select: cost_instr!(instr_select, 4),
+			r#if: cost_instr!(instr_if, 3),
+			br: cost_instr!(instr_br, 2),
+			br_if: cost_instr!(instr_br_if, 5),
+			br_table: cost_instr!(instr_br_table, 3),
+			br_table_per_entry: cost_instr!(instr_br_table_per_entry, 0),
+			call: cost_instr!(instr_call, 2),
+			call_indirect: cost_instr!(instr_call_indirect, 3),
+			call_indirect_per_param: cost_instr!(instr_call_indirect_per_param, 1),
+			local_get: cost_instr!(instr_local_get, 1),
+			local_set: cost_instr!(instr_local_set, 1),
+			local_tee: cost_instr!(instr_local_tee, 2),
+			global_get: cost_instr!(instr_global_get, 1),
+			global_set: cost_instr!(instr_global_set, 1),
+			memory_current: cost_instr!(instr_memory_current, 1),
+			memory_grow: cost_instr_with_batch_size!(instr_memory_grow, 1, max_pages),
+			i64clz: cost_instr!(instr_i64clz, 2),
+			i64ctz: cost_instr!(instr_i64ctz, 2),
+			i64popcnt: cost_instr!(instr_i64popcnt, 2),
+			i64eqz: cost_instr!(instr_i64eqz, 2),
+			i64extendsi32: cost_instr!(instr_i64extendsi32, 2),
+			i64extendui32: cost_instr!(instr_i64extendui32, 2),
+			i32wrapi64: cost_instr!(instr_i32wrapi64, 2),
+			i64eq: cost_instr!(instr_i64eq, 3),
+			i64ne: cost_instr!(instr_i64ne, 3),
+			i64lts: cost_instr!(instr_i64lts, 3),
+			i64ltu: cost_instr!(instr_i64ltu, 3),
+			i64gts: cost_instr!(instr_i64gts, 3),
+			i64gtu: cost_instr!(instr_i64gtu, 3),
+			i64les: cost_instr!(instr_i64les, 3),
+			i64leu: cost_instr!(instr_i64leu, 3),
+			i64ges: cost_instr!(instr_i64ges, 3),
+			i64geu: cost_instr!(instr_i64geu, 3),
+			i64add: cost_instr!(instr_i64add, 3),
+			i64sub: cost_instr!(instr_i64sub, 3),
+			i64mul: cost_instr!(instr_i64mul, 3),
+			i64divs: cost_instr!(instr_i64divs, 3),
+			i64divu: cost_instr!(instr_i64divu, 3),
+			i64rems: cost_instr!(instr_i64rems, 3),
+			i64remu: cost_instr!(instr_i64remu, 3),
+			i64and: cost_instr!(instr_i64and, 3),
+			i64or: cost_instr!(instr_i64or, 3),
+			i64xor: cost_instr!(instr_i64xor, 3),
+			i64shl: cost_instr!(instr_i64shl, 3),
+			i64shrs: cost_instr!(instr_i64shrs, 3),
+			i64shru: cost_instr!(instr_i64shru, 3),
+			i64rotl: cost_instr!(instr_i64rotl, 3),
+			i64rotr: cost_instr!(instr_i64rotr, 3),
+			_phantom: PhantomData,
+		}
+	}
+}
+
+impl<T: Config> Default for HostFnWeights<T> {
+	fn default() -> Self {
+		Self {
+			caller: cost_batched!(seal_caller),
+			address: cost_batched!(seal_address),
+			gas_left: cost_batched!(seal_gas_left),
+			balance: cost_batched!(seal_balance),
+			value_transferred: cost_batched!(seal_value_transferred),
+			minimum_balance: cost_batched!(seal_minimum_balance),
+			tombstone_deposit: cost_batched!(seal_tombstone_deposit),
+			rent_allowance: cost_batched!(seal_rent_allowance),
+			block_number: cost_batched!(seal_block_number),
+			now: cost_batched!(seal_now),
+			weight_to_fee: cost_batched!(seal_weight_to_fee),
+			gas: cost_batched!(seal_gas),
+			input: cost!(seal_input),
+			input_per_byte: cost_byte!(seal_input_per_kb),
+			r#return: cost!(seal_return),
+			return_per_byte: cost_byte!(seal_return_per_kb),
+			terminate: cost!(seal_terminate),
+			terminate_per_code_byte: cost_byte!(seal_terminate_per_code_kb),
+			restore_to: cost!(seal_restore_to),
+			restore_to_per_caller_code_byte: cost_byte_args!(
+				seal_restore_to_per_code_kb_delta,
+				1,
+				0,
+				0
+			),
+			restore_to_per_tombstone_code_byte: cost_byte_args!(
+				seal_restore_to_per_code_kb_delta,
+				0,
+				1,
+				0
+			),
+			restore_to_per_delta: cost_batched_args!(seal_restore_to_per_code_kb_delta, 0, 0, 1),
+			random: cost_batched!(seal_random),
+			deposit_event: cost_batched!(seal_deposit_event),
+			deposit_event_per_topic: cost_batched_args!(seal_deposit_event_per_topic_and_kb, 1, 0),
+			deposit_event_per_byte: cost_byte_batched_args!(
+				seal_deposit_event_per_topic_and_kb,
+				0,
+				1
+			),
+			set_rent_allowance: cost_batched!(seal_set_rent_allowance),
+			set_storage: cost_batched!(seal_set_storage),
+			set_storage_per_byte: cost_byte_batched!(seal_set_storage_per_kb),
+			clear_storage: cost_batched!(seal_clear_storage),
+			get_storage: cost_batched!(seal_get_storage),
+			get_storage_per_byte: cost_byte_batched!(seal_get_storage_per_kb),
+			transfer: cost_batched!(seal_transfer),
+			call: cost_batched!(seal_call),
+			call_per_code_byte: cost_byte_batched_args!(
+				seal_call_per_code_transfer_input_output_kb,
+				1,
+				0,
+				0,
+				0
+			),
+			call_transfer_surcharge: cost_batched_args!(
+				seal_call_per_code_transfer_input_output_kb,
+				0,
+				1,
+				0,
+				0
+			),
+			call_per_input_byte: cost_byte_batched_args!(
+				seal_call_per_code_transfer_input_output_kb,
+				0,
+				0,
+				1,
+				0
+			),
+			call_per_output_byte: cost_byte_batched_args!(
+				seal_call_per_code_transfer_input_output_kb,
+				0,
+				0,
+				0,
+				1
+			),
+			instantiate: cost_batched!(seal_instantiate),
+			instantiate_per_code_byte: cost_byte_batched_args!(
+				seal_instantiate_per_code_input_output_salt_kb,
+				1,
+				0,
+				0,
+				0
+			),
+			instantiate_per_input_byte: cost_byte_batched_args!(
+				seal_instantiate_per_code_input_output_salt_kb,
+				0,
+				1,
+				0,
+				0
+			),
+			instantiate_per_output_byte: cost_byte_batched_args!(
+				seal_instantiate_per_code_input_output_salt_kb,
+				0,
+				0,
+				1,
+				0
+			),
+			instantiate_per_salt_byte: cost_byte_batched_args!(
+				seal_instantiate_per_code_input_output_salt_kb,
+				0,
+				0,
+				0,
+				1
+			),
+			hash_sha2_256: cost_batched!(seal_hash_sha2_256),
+			hash_sha2_256_per_byte: cost_byte_batched!(seal_hash_sha2_256_per_kb),
+			hash_keccak_256: cost_batched!(seal_hash_keccak_256),
+			hash_keccak_256_per_byte: cost_byte_batched!(seal_hash_keccak_256_per_kb),
+			hash_blake2_256: cost_batched!(seal_hash_blake2_256),
+			hash_blake2_256_per_byte: cost_byte_batched!(seal_hash_blake2_256_per_kb),
+			hash_blake2_128: cost_batched!(seal_hash_blake2_128),
+			hash_blake2_128_per_byte: cost_byte_batched!(seal_hash_blake2_128_per_kb),
+			rent_params: cost_batched!(seal_rent_params),
+			_phantom: PhantomData,
+		}
+	}
+}
+
+struct ScheduleRules<'a, T: Config> {
+	schedule: &'a Schedule<T>,
+	params: Vec<u32>,
+}
+
+impl<T: Config> Schedule<T> {
+	/// Allow contracts to call `seal_println` in order to print messages to the console.
+	///
+	/// This should only ever be activated in development chains. The printed messages
+	/// can be observed on the console by setting the environment variable
+	/// `RUST_LOG=runtime=debug` when running the node.
+	///
+	/// # Note
+	///
+	/// Is set to `false` by default.
+	pub fn enable_println(mut self, enable: bool) -> Self {
+		self.enable_println = enable;
+		self
+	}
+
+	pub(crate) fn rules(&self, module: &elements::Module) -> impl rules::Rules + '_ {
+		ScheduleRules {
+			schedule: &self,
+			params: module
+				.type_section()
+				.iter()
+				.flat_map(|section| section.types())
+				.map(|func| {
+					let elements::Type::Function(func) = func;
+					func.params().len() as u32
+				})
+				.collect(),
+		}
+	}
+}
+
+impl<'a, T: Config> rules::Rules for ScheduleRules<'a, T> {
+	fn instruction_cost(&self, instruction: &elements::Instruction) -> Option<u32> {
+		use parity_wasm::elements::Instruction::*;
+		let w = &self.schedule.instruction_weights;
+		let max_params = self.schedule.limits.parameters;
+
+		let weight = match *instruction {
+			End | Unreachable | Return | Else => 0,
+			I32Const(_) | I64Const(_) | Block(_) | Loop(_) | Nop | Drop => w.i64const,
+			I32Load(_, _)
+			| I32Load8S(_, _)
+			| I32Load8U(_, _)
+			| I32Load16S(_, _)
+			| I32Load16U(_, _)
+			| I64Load(_, _)
+			| I64Load8S(_, _)
+			| I64Load8U(_, _)
+			| I64Load16S(_, _)
+			| I64Load16U(_, _)
+			| I64Load32S(_, _)
+			| I64Load32U(_, _) => w.i64load,
+			I32Store(_, _)
+			| I32Store8(_, _)
+			| I32Store16(_, _)
+			| I64Store(_, _)
+			| I64Store8(_, _)
+			| I64Store16(_, _)
+			| I64Store32(_, _) => w.i64store,
+			Select => w.select,
+			If(_) => w.r#if,
+			Br(_) => w.br,
+			BrIf(_) => w.br_if,
+			Call(_) => w.call,
+			GetLocal(_) => w.local_get,
+			SetLocal(_) => w.local_set,
+			TeeLocal(_) => w.local_tee,
+			GetGlobal(_) => w.global_get,
+			SetGlobal(_) => w.global_set,
+			CurrentMemory(_) => w.memory_current,
+			GrowMemory(_) => w.memory_grow,
+			CallIndirect(idx, _) => *self.params.get(idx as usize).unwrap_or(&max_params),
+			BrTable(ref data) => w
+				.br_table
+				.saturating_add(w.br_table_per_entry.saturating_mul(data.table.len() as u32)),
+			I32Clz | I64Clz => w.i64clz,
+			I32Ctz | I64Ctz => w.i64ctz,
+			I32Popcnt | I64Popcnt => w.i64popcnt,
+			I32Eqz | I64Eqz => w.i64eqz,
+			I64ExtendSI32 => w.i64extendsi32,
+			I64ExtendUI32 => w.i64extendui32,
+			I32WrapI64 => w.i32wrapi64,
+			I32Eq | I64Eq => w.i64eq,
+			I32Ne | I64Ne => w.i64ne,
+			I32LtS | I64LtS => w.i64lts,
+			I32LtU | I64LtU => w.i64ltu,
+			I32GtS | I64GtS => w.i64gts,
+			I32GtU | I64GtU => w.i64gtu,
+			I32LeS | I64LeS => w.i64les,
+			I32LeU | I64LeU => w.i64leu,
+			I32GeS | I64GeS => w.i64ges,
+			I32GeU | I64GeU => w.i64geu,
+			I32Add | I64Add => w.i64add,
+			I32Sub | I64Sub => w.i64sub,
+			I32Mul | I64Mul => w.i64mul,
+			I32DivS | I64DivS => w.i64divs,
+			I32DivU | I64DivU => w.i64divu,
+			I32RemS | I64RemS => w.i64rems,
+			I32RemU | I64RemU => w.i64remu,
+			I32And | I64And => w.i64and,
+			I32Or | I64Or => w.i64or,
+			I32Xor | I64Xor => w.i64xor,
+			I32Shl | I64Shl => w.i64shl,
+			I32ShrS | I64ShrS => w.i64shrs,
+			I32ShrU | I64ShrU => w.i64shru,
+			I32Rotl | I64Rotl => w.i64rotl,
+			I32Rotr | I64Rotr => w.i64rotr,
+
+			// Returning None makes the gas instrumentation fail which we intend for
+			// unsupported or unknown instructions.
+			_ => return None,
+		};
+		Some(weight)
+	}
+
+	fn memory_grow_cost(&self) -> Option<rules::MemoryGrowCost> {
+		// We benchmarked the memory.grow instruction with the maximum allowed pages.
+		// The cost for growing is therefore already included in the instruction cost.
+		None
+	}
+}
+
+#[cfg(test)]
+mod test {
+	use crate::tests::Test;
+	use super::*;
+
+	#[test]
+	fn print_test_schedule() {
+		let schedule = Schedule::<Test>::default();
+		println!("{:#?}", schedule);
+	}
+}
addedpallets/contracts/src/storage.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/storage.rs
@@ -0,0 +1,440 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This module contains routines for accessing and altering a contract related state.
+
+use crate::{
+	exec::{AccountIdOf, StorageKey},
+	BalanceOf, CodeHash, ContractInfoOf, Config, TrieId, AccountCounter, DeletionQueue, Error,
+	weights::WeightInfo,
+};
+use codec::{Codec, Encode, Decode};
+use sp_std::prelude::*;
+use sp_std::{marker::PhantomData, fmt::Debug};
+use sp_io::hashing::blake2_256;
+use sp_runtime::{
+	RuntimeDebug,
+	traits::{Bounded, Saturating, Zero, Hash, Member, MaybeSerializeDeserialize},
+};
+use sp_core::crypto::UncheckedFrom;
+use frame_support::{
+	dispatch::{DispatchError, DispatchResult},
+	storage::child::{self, KillChildStorageResult, ChildInfo},
+	traits::Get,
+	weights::Weight,
+};
+
+pub type AliveContractInfo<T> =
+	RawAliveContractInfo<CodeHash<T>, BalanceOf<T>, <T as frame_system::Config>::BlockNumber>;
+pub type TombstoneContractInfo<T> = RawTombstoneContractInfo<
+	<T as frame_system::Config>::Hash,
+	<T as frame_system::Config>::Hashing,
+>;
+
+/// Information for managing an account and its sub trie abstraction.
+/// This is the required info to cache for an account
+#[derive(Encode, Decode, RuntimeDebug)]
+pub enum ContractInfo<T: Config> {
+	Alive(AliveContractInfo<T>),
+	Tombstone(TombstoneContractInfo<T>),
+}
+
+impl<T: Config> ContractInfo<T> {
+	/// If contract is alive then return some alive info
+	pub fn get_alive(self) -> Option<AliveContractInfo<T>> {
+		if let ContractInfo::Alive(alive) = self {
+			Some(alive)
+		} else {
+			None
+		}
+	}
+	/// If contract is alive then return some reference to alive info
+	pub fn as_alive(&self) -> Option<&AliveContractInfo<T>> {
+		if let ContractInfo::Alive(ref alive) = self {
+			Some(alive)
+		} else {
+			None
+		}
+	}
+
+	/// If contract is tombstone then return some tombstone info
+	pub fn get_tombstone(self) -> Option<TombstoneContractInfo<T>> {
+		if let ContractInfo::Tombstone(tombstone) = self {
+			Some(tombstone)
+		} else {
+			None
+		}
+	}
+}
+
+/// Information for managing an account and its sub trie abstraction.
+/// This is the required info to cache for an account.
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
+pub struct RawAliveContractInfo<CodeHash, Balance, BlockNumber> {
+	/// Unique ID for the subtree encoded as a bytes vector.
+	pub trie_id: TrieId,
+	/// The total number of bytes used by this contract.
+	///
+	/// It is a sum of each key-value pair stored by this contract.
+	pub storage_size: u32,
+	/// The total number of key-value pairs in storage of this contract.
+	pub pair_count: u32,
+	/// The code associated with a given account.
+	pub code_hash: CodeHash,
+	/// Pay rent at most up to this value.
+	pub rent_allowance: Balance,
+	/// The amount of rent that was payed by the contract over its whole lifetime.
+	///
+	/// A restored contract starts with a value of zero just like a new contract.
+	pub rent_payed: Balance,
+	/// Last block rent has been payed.
+	pub deduct_block: BlockNumber,
+	/// Last block child storage has been written.
+	pub last_write: Option<BlockNumber>,
+	/// This field is reserved for future evolution of format.
+	pub _reserved: Option<()>,
+}
+
+impl<CodeHash, Balance, BlockNumber> RawAliveContractInfo<CodeHash, Balance, BlockNumber> {
+	/// Associated child trie unique id is built from the hash part of the trie id.
+	pub fn child_trie_info(&self) -> ChildInfo {
+		child_trie_info(&self.trie_id[..])
+	}
+}
+
+/// Associated child trie unique id is built from the hash part of the trie id.
+fn child_trie_info(trie_id: &[u8]) -> ChildInfo {
+	ChildInfo::new_default(trie_id)
+}
+
+#[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug)]
+pub struct RawTombstoneContractInfo<H, Hasher>(H, PhantomData<Hasher>);
+
+impl<H, Hasher> RawTombstoneContractInfo<H, Hasher>
+where
+	H: Member
+		+ MaybeSerializeDeserialize
+		+ Debug
+		+ AsRef<[u8]>
+		+ AsMut<[u8]>
+		+ Copy
+		+ Default
+		+ sp_std::hash::Hash
+		+ Codec,
+	Hasher: Hash<Output = H>,
+{
+	pub fn new(storage_root: &[u8], code_hash: H) -> Self {
+		let mut buf = Vec::new();
+		storage_root.using_encoded(|encoded| buf.extend_from_slice(encoded));
+		buf.extend_from_slice(code_hash.as_ref());
+		RawTombstoneContractInfo(<Hasher as Hash>::hash(&buf[..]), PhantomData)
+	}
+}
+
+impl<T: Config> From<AliveContractInfo<T>> for ContractInfo<T> {
+	fn from(alive_info: AliveContractInfo<T>) -> Self {
+		Self::Alive(alive_info)
+	}
+}
+
+/// An error that means that the account requested either doesn't exist or represents a tombstone
+/// account.
+#[cfg_attr(test, derive(PartialEq, Eq, Debug))]
+pub struct ContractAbsentError;
+
+#[derive(Encode, Decode)]
+pub struct DeletedContract {
+	pair_count: u32,
+	trie_id: TrieId,
+}
+
+pub struct Storage<T>(PhantomData<T>);
+
+impl<T> Storage<T>
+where
+	T: Config,
+	T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
+{
+	/// Reads a storage kv pair of a contract.
+	///
+	/// The read is performed from the `trie_id` only. The `address` is not necessary. If the contract
+	/// doesn't store under the given `key` `None` is returned.
+	pub fn read(trie_id: &TrieId, key: &StorageKey) -> Option<Vec<u8>> {
+		child::get_raw(&child_trie_info(&trie_id), &blake2_256(key))
+	}
+
+	/// Update a storage entry into a contract's kv storage.
+	///
+	/// If the `opt_new_value` is `None` then the kv pair is removed.
+	///
+	/// This function also updates the bookkeeping info such as: number of total non-empty pairs a
+	/// contract owns, the last block the storage was written to, etc. That's why, in contrast to
+	/// `read`, this function also requires the `account` ID.
+	///
+	/// If the contract specified by the id `account` doesn't exist `Err` is returned.`
+	///
+	/// # Panics
+	///
+	/// Panics iff the `account` specified is not alive and in storage.
+	pub fn write(
+		account: &AccountIdOf<T>,
+		trie_id: &TrieId,
+		key: &StorageKey,
+		opt_new_value: Option<Vec<u8>>,
+	) -> DispatchResult {
+		let mut new_info = match <ContractInfoOf<T>>::get(account) {
+			Some(ContractInfo::Alive(alive)) => alive,
+			None | Some(ContractInfo::Tombstone(_)) => panic!("Contract not found"),
+		};
+
+		let hashed_key = blake2_256(key);
+		let child_trie_info = &child_trie_info(&trie_id);
+
+		let opt_prev_len = child::len(&child_trie_info, &hashed_key);
+
+		// Update the total number of KV pairs and the number of empty pairs.
+		match (&opt_prev_len, &opt_new_value) {
+			(Some(_), None) => {
+				new_info.pair_count = new_info
+					.pair_count
+					.checked_sub(1)
+					.ok_or_else(|| Error::<T>::StorageExhausted)?;
+			}
+			(None, Some(_)) => {
+				new_info.pair_count = new_info
+					.pair_count
+					.checked_add(1)
+					.ok_or_else(|| Error::<T>::StorageExhausted)?;
+			}
+			(Some(_), Some(_)) => {}
+			(None, None) => {}
+		}
+
+		// Update the total storage size.
+		let prev_value_len = opt_prev_len.unwrap_or(0);
+		let new_value_len = opt_new_value
+			.as_ref()
+			.map(|new_value| new_value.len() as u32)
+			.unwrap_or(0);
+		new_info.storage_size = new_info
+			.storage_size
+			.checked_sub(prev_value_len)
+			.and_then(|val| val.checked_add(new_value_len))
+			.ok_or_else(|| Error::<T>::StorageExhausted)?;
+
+		new_info.last_write = Some(<frame_system::Pallet<T>>::block_number());
+		<ContractInfoOf<T>>::insert(&account, ContractInfo::Alive(new_info));
+
+		// Finally, perform the change on the storage.
+		match opt_new_value {
+			Some(new_value) => child::put_raw(&child_trie_info, &hashed_key, &new_value[..]),
+			None => child::kill(&child_trie_info, &hashed_key),
+		}
+
+		Ok(())
+	}
+
+	/// Returns the rent allowance set for the contract give by the account id.
+	pub fn rent_allowance(account: &AccountIdOf<T>) -> Result<BalanceOf<T>, ContractAbsentError> {
+		<ContractInfoOf<T>>::get(account)
+			.and_then(|i| i.as_alive().map(|i| i.rent_allowance))
+			.ok_or(ContractAbsentError)
+	}
+
+	/// Set the rent allowance for the contract given by the account id.
+	///
+	/// Returns `Err` if the contract doesn't exist or is a tombstone.
+	pub fn set_rent_allowance(
+		account: &AccountIdOf<T>,
+		rent_allowance: BalanceOf<T>,
+	) -> Result<(), ContractAbsentError> {
+		<ContractInfoOf<T>>::mutate(account, |maybe_contract_info| match maybe_contract_info {
+			Some(ContractInfo::Alive(ref mut alive_info)) => {
+				alive_info.rent_allowance = rent_allowance;
+				Ok(())
+			}
+			_ => Err(ContractAbsentError),
+		})
+	}
+
+	/// Creates a new contract descriptor in the storage with the given code hash at the given address.
+	///
+	/// Returns `Err` if there is already a contract (or a tombstone) exists at the given address.
+	pub fn place_contract(
+		account: &AccountIdOf<T>,
+		trie_id: TrieId,
+		ch: CodeHash<T>,
+	) -> Result<AliveContractInfo<T>, DispatchError> {
+		<ContractInfoOf<T>>::try_mutate(account, |existing| {
+			if existing.is_some() {
+				return Err(Error::<T>::DuplicateContract.into());
+			}
+
+			let contract = AliveContractInfo::<T> {
+				code_hash: ch,
+				storage_size: 0,
+				trie_id,
+				deduct_block:
+					// We want to charge rent for the first block in advance. Therefore we
+					// treat the contract as if it was created in the last block and then
+					// charge rent for it during instantiation.
+					<frame_system::Pallet<T>>::block_number().saturating_sub(1u32.into()),
+				rent_allowance: <BalanceOf<T>>::max_value(),
+				rent_payed: <BalanceOf<T>>::zero(),
+				pair_count: 0,
+				last_write: None,
+				_reserved: None,
+			};
+
+			*existing = Some(contract.clone().into());
+
+			Ok(contract)
+		})
+	}
+
+	/// Push a contract's trie to the deletion queue for lazy removal.
+	///
+	/// You must make sure that the contract is also removed or converted into a tombstone
+	/// when queuing the trie for deletion.
+	pub fn queue_trie_for_deletion(contract: &AliveContractInfo<T>) -> DispatchResult {
+		if <DeletionQueue<T>>::decode_len().unwrap_or(0) >= T::DeletionQueueDepth::get() as usize {
+			Err(Error::<T>::DeletionQueueFull.into())
+		} else {
+			<DeletionQueue<T>>::append(DeletedContract {
+				pair_count: contract.pair_count,
+				trie_id: contract.trie_id.clone(),
+			});
+			Ok(())
+		}
+	}
+
+	/// Calculates the weight that is necessary to remove one key from the trie and how many
+	/// of those keys can be deleted from the deletion queue given the supplied queue length
+	/// and weight limit.
+	pub fn deletion_budget(queue_len: usize, weight_limit: Weight) -> (u64, u32) {
+		let base_weight = T::WeightInfo::on_initialize();
+		let weight_per_queue_item = T::WeightInfo::on_initialize_per_queue_item(1)
+			- T::WeightInfo::on_initialize_per_queue_item(0);
+		let weight_per_key = T::WeightInfo::on_initialize_per_trie_key(1)
+			- T::WeightInfo::on_initialize_per_trie_key(0);
+		let decoding_weight = weight_per_queue_item.saturating_mul(queue_len as Weight);
+
+		// `weight_per_key` being zero makes no sense and would constitute a failure to
+		// benchmark properly. We opt for not removing any keys at all in this case.
+		let key_budget = weight_limit
+			.saturating_sub(base_weight)
+			.saturating_sub(decoding_weight)
+			.checked_div(weight_per_key)
+			.unwrap_or(0) as u32;
+
+		(weight_per_key, key_budget)
+	}
+
+	/// Delete as many items from the deletion queue possible within the supplied weight limit.
+	///
+	/// It returns the amount of weight used for that task or `None` when no weight was used
+	/// apart from the base weight.
+	pub fn process_deletion_queue_batch(weight_limit: Weight) -> Weight {
+		let queue_len = <DeletionQueue<T>>::decode_len().unwrap_or(0);
+		if queue_len == 0 {
+			return weight_limit;
+		}
+
+		let (weight_per_key, mut remaining_key_budget) =
+			Self::deletion_budget(queue_len, weight_limit);
+
+		// We want to check whether we have enough weight to decode the queue before
+		// proceeding. Too little weight for decoding might happen during runtime upgrades
+		// which consume the whole block before the other `on_initialize` blocks are called.
+		if remaining_key_budget == 0 {
+			return weight_limit;
+		}
+
+		let mut queue = <DeletionQueue<T>>::get();
+
+		while !queue.is_empty() && remaining_key_budget > 0 {
+			// Cannot panic due to loop condition
+			let trie = &mut queue[0];
+			let pair_count = trie.pair_count;
+			let outcome =
+				child::kill_storage(&child_trie_info(&trie.trie_id), Some(remaining_key_budget));
+			if pair_count > remaining_key_budget {
+				// Cannot underflow because of the if condition
+				trie.pair_count -= remaining_key_budget;
+			} else {
+				// We do not care to preserve order. The contract is deleted already and
+				// noone waits for the trie to be deleted.
+				let removed = queue.swap_remove(0);
+				match outcome {
+					// This should not happen as our budget was large enough to remove all keys.
+					KillChildStorageResult::SomeRemaining(_) => {
+						log::error!(
+							target: "runtime::contracts",
+							"After deletion keys are remaining in this child trie: {:?}",
+							removed.trie_id,
+						);
+					}
+					KillChildStorageResult::AllRemoved(_) => (),
+				}
+			}
+			remaining_key_budget =
+				remaining_key_budget.saturating_sub(remaining_key_budget.min(pair_count));
+		}
+
+		<DeletionQueue<T>>::put(queue);
+		weight_limit.saturating_sub(weight_per_key.saturating_mul(remaining_key_budget as Weight))
+	}
+
+	/// This generator uses inner counter for account id and applies the hash over `AccountId +
+	/// accountid_counter`.
+	pub fn generate_trie_id(account_id: &AccountIdOf<T>) -> TrieId {
+		// Note that skipping a value due to error is not an issue here.
+		// We only need uniqueness, not sequence.
+		let new_seed = <AccountCounter<T>>::mutate(|v| {
+			*v = v.wrapping_add(1);
+			*v
+		});
+
+		let buf: Vec<_> = account_id
+			.as_ref()
+			.iter()
+			.chain(&new_seed.to_le_bytes())
+			.cloned()
+			.collect();
+		T::Hashing::hash(&buf).as_ref().into()
+	}
+
+	/// Returns the code hash of the contract specified by `account` ID.
+	#[cfg(test)]
+	pub fn code_hash(account: &AccountIdOf<T>) -> Result<CodeHash<T>, ContractAbsentError> {
+		<ContractInfoOf<T>>::get(account)
+			.and_then(|i| i.as_alive().map(|i| i.code_hash))
+			.ok_or(ContractAbsentError)
+	}
+
+	/// Fill up the queue in order to exercise the limits during testing.
+	#[cfg(test)]
+	pub fn fill_queue_with_dummies() {
+		let queue: Vec<_> = (0..T::DeletionQueueDepth::get())
+			.map(|_| DeletedContract {
+				pair_count: 0,
+				trie_id: vec![],
+			})
+			.collect();
+		<DeletionQueue<T>>::put(queue);
+	}
+}
addedpallets/contracts/src/tests.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/tests.rs
@@ -0,0 +1,2971 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::{
+	BalanceOf, ContractInfo, ContractInfoOf, Pallet, Config, Schedule, Error,
+	storage::Storage,
+	chain_extension::{
+		Result as ExtensionResult, Environment, ChainExtension, Ext, SysConfig, RetVal,
+		UncheckedFrom, InitState, ReturnFlags,
+	},
+	exec::{AccountIdOf, Executable},
+	wasm::PrefabWasmModule,
+	weights::WeightInfo,
+	wasm::ReturnCode as RuntimeReturnCode,
+	storage::RawAliveContractInfo,
+};
+use assert_matches::assert_matches;
+use codec::Encode;
+use sp_core::Bytes;
+use sp_runtime::{
+	traits::{BlakeTwo256, Hash, IdentityLookup, Convert},
+	testing::{Header, H256},
+	AccountId32, Perbill,
+};
+use sp_io::hashing::blake2_256;
+use frame_support::{
+	assert_ok, assert_err, assert_err_ignore_postinfo, parameter_types, assert_storage_noop,
+	traits::{Currency, ReservableCurrency, OnInitialize, GenesisBuild},
+	weights::{Weight, PostDispatchInfo, DispatchClass, constants::WEIGHT_PER_SECOND},
+	dispatch::DispatchErrorWithPostInfo,
+	storage::child,
+};
+use frame_system::{self as system, EventRecord, Phase};
+use pretty_assertions::assert_eq;
+
+use crate as pallet_contracts;
+
+type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
+type Block = frame_system::mocking::MockBlock<Test>;
+
+frame_support::construct_runtime!(
+	pub enum Test where
+		Block = Block,
+		NodeBlock = Block,
+		UncheckedExtrinsic = UncheckedExtrinsic,
+	{
+		System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
+		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
+		Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
+		Randomness: pallet_randomness_collective_flip::{Pallet, Call, Storage},
+		Contracts: pallet_contracts::{Pallet, Call, Config<T>, Storage, Event<T>},
+	}
+);
+
+#[macro_use]
+pub mod test_utils {
+	use super::{Test, Balances};
+	use crate::{
+		ContractInfoOf, CodeHash,
+		storage::Storage,
+		exec::{StorageKey, AccountIdOf},
+		Pallet as Contracts,
+	};
+	use frame_support::traits::Currency;
+
+	pub fn set_storage(addr: &AccountIdOf<Test>, key: &StorageKey, value: Option<Vec<u8>>) {
+		let contract_info = <ContractInfoOf<Test>>::get(&addr)
+			.unwrap()
+			.get_alive()
+			.unwrap();
+		Storage::<Test>::write(addr, &contract_info.trie_id, key, value).unwrap();
+	}
+	pub fn get_storage(addr: &AccountIdOf<Test>, key: &StorageKey) -> Option<Vec<u8>> {
+		let contract_info = <ContractInfoOf<Test>>::get(&addr)
+			.unwrap()
+			.get_alive()
+			.unwrap();
+		Storage::<Test>::read(&contract_info.trie_id, key)
+	}
+	pub fn place_contract(address: &AccountIdOf<Test>, code_hash: CodeHash<Test>) {
+		let trie_id = Storage::<Test>::generate_trie_id(address);
+		set_balance(address, Contracts::<Test>::subsistence_threshold() * 10);
+		Storage::<Test>::place_contract(&address, trie_id, code_hash).unwrap();
+	}
+	pub fn set_balance(who: &AccountIdOf<Test>, amount: u64) {
+		let imbalance = Balances::deposit_creating(who, amount);
+		drop(imbalance);
+	}
+	pub fn get_balance(who: &AccountIdOf<Test>) -> u64 {
+		Balances::free_balance(who)
+	}
+	macro_rules! assert_return_code {
+		( $x:expr , $y:expr $(,)? ) => {{
+			use sp_std::convert::TryInto;
+			assert_eq!(
+				u32::from_le_bytes($x.data[..].try_into().unwrap()),
+				$y as u32
+			);
+		}};
+	}
+	macro_rules! assert_refcount {
+		( $code_hash:expr , $should:expr $(,)? ) => {{
+			let is = crate::CodeStorage::<Test>::get($code_hash)
+				.map(|m| m.refcount())
+				.unwrap_or(0);
+			assert_eq!(is, $should);
+		}};
+	}
+}
+
+thread_local! {
+	static TEST_EXTENSION: sp_std::cell::RefCell<TestExtension> = Default::default();
+}
+
+pub struct TestExtension {
+	enabled: bool,
+	last_seen_buffer: Vec<u8>,
+	last_seen_inputs: (u32, u32, u32, u32),
+}
+
+impl TestExtension {
+	fn disable() {
+		TEST_EXTENSION.with(|e| e.borrow_mut().enabled = false)
+	}
+
+	fn last_seen_buffer() -> Vec<u8> {
+		TEST_EXTENSION.with(|e| e.borrow().last_seen_buffer.clone())
+	}
+
+	fn last_seen_inputs() -> (u32, u32, u32, u32) {
+		TEST_EXTENSION.with(|e| e.borrow().last_seen_inputs.clone())
+	}
+}
+
+impl Default for TestExtension {
+	fn default() -> Self {
+		Self {
+			enabled: true,
+			last_seen_buffer: vec![],
+			last_seen_inputs: (0, 0, 0, 0),
+		}
+	}
+}
+
+impl ChainExtension<Test> for TestExtension {
+	fn call<E>(func_id: u32, env: Environment<E, InitState>) -> ExtensionResult<RetVal>
+	where
+		E: Ext<T = Test>,
+		<E::T as SysConfig>::AccountId: UncheckedFrom<<E::T as SysConfig>::Hash> + AsRef<[u8]>,
+	{
+		match func_id {
+			0 => {
+				let mut env = env.buf_in_buf_out();
+				let input = env.read(2)?;
+				env.write(&input, false, None)?;
+				TEST_EXTENSION.with(|e| e.borrow_mut().last_seen_buffer = input);
+				Ok(RetVal::Converging(func_id))
+			}
+			1 => {
+				let env = env.only_in();
+				TEST_EXTENSION.with(|e| {
+					e.borrow_mut().last_seen_inputs =
+						(env.val0(), env.val1(), env.val2(), env.val3())
+				});
+				Ok(RetVal::Converging(func_id))
+			}
+			2 => {
+				let mut env = env.buf_in_buf_out();
+				let weight = env.read(2)?[1].into();
+				env.charge_weight(weight)?;
+				Ok(RetVal::Converging(func_id))
+			}
+			3 => Ok(RetVal::Diverging {
+				flags: ReturnFlags::REVERT,
+				data: vec![42, 99],
+			}),
+			_ => {
+				panic!(
+					"Passed unknown func_id to test chain extension: {}",
+					func_id
+				);
+			}
+		}
+	}
+
+	fn enabled() -> bool {
+		TEST_EXTENSION.with(|e| e.borrow().enabled)
+	}
+}
+
+parameter_types! {
+	pub const BlockHashCount: u64 = 250;
+	pub BlockWeights: frame_system::limits::BlockWeights =
+		frame_system::limits::BlockWeights::simple_max(2 * WEIGHT_PER_SECOND);
+	pub static ExistentialDeposit: u64 = 0;
+}
+impl frame_system::Config for Test {
+	type BaseCallFilter = ();
+	type BlockWeights = BlockWeights;
+	type BlockLength = ();
+	type DbWeight = ();
+	type Origin = Origin;
+	type Index = u64;
+	type BlockNumber = u64;
+	type Hash = H256;
+	type Call = Call;
+	type Hashing = BlakeTwo256;
+	type AccountId = AccountId32;
+	type Lookup = IdentityLookup<Self::AccountId>;
+	type Header = Header;
+	type Event = Event;
+	type BlockHashCount = BlockHashCount;
+	type Version = ();
+	type PalletInfo = PalletInfo;
+	type AccountData = pallet_balances::AccountData<u64>;
+	type OnNewAccount = ();
+	type OnKilledAccount = ();
+	type SystemWeightInfo = ();
+	type SS58Prefix = ();
+	type OnSetCode = ();
+}
+impl pallet_balances::Config for Test {
+	type MaxLocks = ();
+	type Balance = u64;
+	type Event = Event;
+	type DustRemoval = ();
+	type ExistentialDeposit = ExistentialDeposit;
+	type AccountStore = System;
+	type WeightInfo = ();
+}
+parameter_types! {
+	pub const MinimumPeriod: u64 = 1;
+}
+impl pallet_timestamp::Config for Test {
+	type Moment = u64;
+	type OnTimestampSet = ();
+	type MinimumPeriod = MinimumPeriod;
+	type WeightInfo = ();
+}
+parameter_types! {
+	pub const SignedClaimHandicap: u64 = 2;
+	pub const TombstoneDeposit: u64 = 16;
+	pub const DepositPerContract: u64 = 8 * DepositPerStorageByte::get();
+	pub const DepositPerStorageByte: u64 = 10_000;
+	pub const DepositPerStorageItem: u64 = 10_000;
+	pub RentFraction: Perbill = Perbill::from_rational(4u32, 10_000u32);
+	pub const SurchargeReward: u64 = 500_000;
+	pub const MaxDepth: u32 = 100;
+	pub const MaxValueSize: u32 = 16_384;
+	pub const DeletionQueueDepth: u32 = 1024;
+	pub const DeletionWeightLimit: Weight = 500_000_000_000;
+	pub const MaxCodeSize: u32 = 2 * 1024;
+}
+
+parameter_types! {
+	pub const TransactionByteFee: u64 = 0;
+}
+
+impl Convert<Weight, BalanceOf<Self>> for Test {
+	fn convert(w: Weight) -> BalanceOf<Self> {
+		w
+	}
+}
+
+impl Config for Test {
+	type Time = Timestamp;
+	type Randomness = Randomness;
+	type Currency = Balances;
+	type Event = Event;
+	type RentPayment = ();
+	type SignedClaimHandicap = SignedClaimHandicap;
+	type TombstoneDeposit = TombstoneDeposit;
+	type DepositPerContract = DepositPerContract;
+	type DepositPerStorageByte = DepositPerStorageByte;
+	type DepositPerStorageItem = DepositPerStorageItem;
+	type RentFraction = RentFraction;
+	type SurchargeReward = SurchargeReward;
+	type MaxDepth = MaxDepth;
+	type MaxValueSize = MaxValueSize;
+	type WeightPrice = Self;
+	type WeightInfo = ();
+	type ChainExtension = TestExtension;
+	type DeletionQueueDepth = DeletionQueueDepth;
+	type DeletionWeightLimit = DeletionWeightLimit;
+	type MaxCodeSize = MaxCodeSize;
+}
+
+pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]);
+pub const BOB: AccountId32 = AccountId32::new([2u8; 32]);
+pub const CHARLIE: AccountId32 = AccountId32::new([3u8; 32]);
+pub const DJANGO: AccountId32 = AccountId32::new([4u8; 32]);
+
+const GAS_LIMIT: Weight = 10_000_000_000;
+
+pub struct ExtBuilder {
+	existential_deposit: u64,
+}
+impl Default for ExtBuilder {
+	fn default() -> Self {
+		Self {
+			existential_deposit: 1,
+		}
+	}
+}
+impl ExtBuilder {
+	pub fn existential_deposit(mut self, existential_deposit: u64) -> Self {
+		self.existential_deposit = existential_deposit;
+		self
+	}
+	pub fn set_associated_consts(&self) {
+		EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit);
+	}
+	pub fn build(self) -> sp_io::TestExternalities {
+		self.set_associated_consts();
+		let mut t = frame_system::GenesisConfig::default()
+			.build_storage::<Test>()
+			.unwrap();
+		pallet_balances::GenesisConfig::<Test> { balances: vec![] }
+			.assimilate_storage(&mut t)
+			.unwrap();
+		pallet_contracts::GenesisConfig {
+			current_schedule: Schedule::<Test> {
+				enable_println: true,
+				..Default::default()
+			},
+		}
+		.assimilate_storage(&mut t)
+		.unwrap();
+		let mut ext = sp_io::TestExternalities::new(t);
+		ext.execute_with(|| System::set_block_number(1));
+		ext
+	}
+}
+
+/// Load a given wasm module represented by a .wat file and returns a wasm binary contents along
+/// with it's hash.
+///
+/// The fixture files are located under the `fixtures/` directory.
+fn compile_module<T>(fixture_name: &str) -> wat::Result<(Vec<u8>, <T::Hashing as Hash>::Output)>
+where
+	T: frame_system::Config,
+{
+	let fixture_path = ["fixtures/", fixture_name, ".wat"].concat();
+	let wasm_binary = wat::parse_file(fixture_path)?;
+	let code_hash = T::Hashing::hash(&wasm_binary);
+	Ok((wasm_binary, code_hash))
+}
+
+// Perform a call to a plain account.
+// The actual transfer fails because we can only call contracts.
+// Then we check that at least the base costs where charged (no runtime gas costs.)
+#[test]
+fn calling_plain_account_fails() {
+	ExtBuilder::default().build().execute_with(|| {
+		let _ = Balances::deposit_creating(&ALICE, 100_000_000);
+		let base_cost = <<Test as Config>::WeightInfo as WeightInfo>::call(0);
+
+		assert_eq!(
+			Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, Vec::new()),
+			Err(DispatchErrorWithPostInfo {
+				error: Error::<Test>::NotCallable.into(),
+				post_info: PostDispatchInfo {
+					actual_weight: Some(base_cost),
+					pays_fee: Default::default(),
+				},
+			})
+		);
+	});
+}
+
+#[test]
+fn account_removal_does_not_remove_storage() {
+	use self::test_utils::{set_storage, get_storage};
+
+	ExtBuilder::default()
+		.existential_deposit(100)
+		.build()
+		.execute_with(|| {
+			let trie_id1 = Storage::<Test>::generate_trie_id(&ALICE);
+			let trie_id2 = Storage::<Test>::generate_trie_id(&BOB);
+			let key1 = &[1; 32];
+			let key2 = &[2; 32];
+
+			// Set up two accounts with free balance above the existential threshold.
+			{
+				let alice_contract_info = ContractInfo::Alive(RawAliveContractInfo {
+					trie_id: trie_id1.clone(),
+					storage_size: 0,
+					pair_count: 0,
+					deduct_block: System::block_number(),
+					code_hash: H256::repeat_byte(1),
+					rent_allowance: 40,
+					rent_payed: 0,
+					last_write: None,
+					_reserved: None,
+				});
+				let _ = Balances::deposit_creating(&ALICE, 110);
+				ContractInfoOf::<Test>::insert(ALICE, &alice_contract_info);
+				set_storage(&ALICE, &key1, Some(b"1".to_vec()));
+				set_storage(&ALICE, &key2, Some(b"2".to_vec()));
+
+				let bob_contract_info = ContractInfo::Alive(RawAliveContractInfo {
+					trie_id: trie_id2.clone(),
+					storage_size: 0,
+					pair_count: 0,
+					deduct_block: System::block_number(),
+					code_hash: H256::repeat_byte(2),
+					rent_allowance: 40,
+					rent_payed: 0,
+					last_write: None,
+					_reserved: None,
+				});
+				let _ = Balances::deposit_creating(&BOB, 110);
+				ContractInfoOf::<Test>::insert(BOB, &bob_contract_info);
+				set_storage(&BOB, &key1, Some(b"3".to_vec()));
+				set_storage(&BOB, &key2, Some(b"4".to_vec()));
+			}
+
+			// Transfer funds from ALICE account of such amount that after this transfer
+			// the balance of the ALICE account will be below the existential threshold.
+			//
+			// This does not remove the contract storage as we are not notified about a
+			// account removal. This cannot happen in reality because a contract can only
+			// remove itself by `seal_terminate`. There is no external event that can remove
+			// the account appart from that.
+			assert_ok!(Balances::transfer(Origin::signed(ALICE), BOB, 20));
+
+			// Verify that no entries are removed.
+			{
+				assert_eq!(get_storage(&ALICE, key1), Some(b"1".to_vec()));
+				assert_eq!(get_storage(&ALICE, key2), Some(b"2".to_vec()));
+
+				assert_eq!(get_storage(&BOB, key1), Some(b"3".to_vec()));
+				assert_eq!(get_storage(&BOB, key2), Some(b"4".to_vec()));
+			}
+		});
+}
+
+#[test]
+fn instantiate_and_call_and_deposit_event() {
+	let (wasm, code_hash) = compile_module::<Test>("return_from_start_fn").unwrap();
+
+	ExtBuilder::default()
+		.existential_deposit(100)
+		.build()
+		.execute_with(|| {
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+
+			// Check at the end to get hash on error easily
+			let creation = Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				wasm,
+				vec![],
+				vec![],
+			);
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+
+			assert_eq!(
+				System::events(),
+				vec![
+					EventRecord {
+						phase: Phase::Initialization,
+						event: Event::frame_system(frame_system::Event::NewAccount(ALICE.clone())),
+						topics: vec![],
+					},
+					EventRecord {
+						phase: Phase::Initialization,
+						event: Event::pallet_balances(pallet_balances::Event::Endowed(
+							ALICE, 1_000_000
+						)),
+						topics: vec![],
+					},
+					EventRecord {
+						phase: Phase::Initialization,
+						event: Event::frame_system(frame_system::Event::NewAccount(addr.clone())),
+						topics: vec![],
+					},
+					EventRecord {
+						phase: Phase::Initialization,
+						event: Event::pallet_balances(pallet_balances::Event::Endowed(
+							addr.clone(),
+							subsistence * 100
+						)),
+						topics: vec![],
+					},
+					EventRecord {
+						phase: Phase::Initialization,
+						event: Event::pallet_balances(pallet_balances::Event::Transfer(
+							ALICE,
+							addr.clone(),
+							subsistence * 100
+						)),
+						topics: vec![],
+					},
+					EventRecord {
+						phase: Phase::Initialization,
+						event: Event::pallet_contracts(crate::Event::CodeStored(code_hash.into())),
+						topics: vec![],
+					},
+					EventRecord {
+						phase: Phase::Initialization,
+						event: Event::pallet_contracts(crate::Event::ContractEmitted(
+							addr.clone(),
+							vec![1, 2, 3, 4]
+						)),
+						topics: vec![],
+					},
+					EventRecord {
+						phase: Phase::Initialization,
+						event: Event::pallet_contracts(crate::Event::Instantiated(
+							ALICE,
+							addr.clone()
+						)),
+						topics: vec![],
+					},
+				]
+			);
+
+			assert_ok!(creation);
+			assert!(ContractInfoOf::<Test>::contains_key(&addr));
+		});
+}
+
+#[test]
+fn deposit_event_max_value_limit() {
+	let (wasm, code_hash) = compile_module::<Test>("event_size").unwrap();
+
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				30_000,
+				GAS_LIMIT,
+				wasm,
+				vec![],
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+
+			// Call contract with allowed storage value.
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr.clone(),
+				0,
+				GAS_LIMIT * 2, // we are copying a huge buffer,
+				<Test as Config>::MaxValueSize::get().encode(),
+			));
+
+			// Call contract with too large a storage value.
+			assert_err_ignore_postinfo!(
+				Contracts::call(
+					Origin::signed(ALICE),
+					addr,
+					0,
+					GAS_LIMIT,
+					(<Test as Config>::MaxValueSize::get() + 1).encode(),
+				),
+				Error::<Test>::ValueTooLarge,
+			);
+		});
+}
+
+#[test]
+fn run_out_of_gas() {
+	let (wasm, code_hash) = compile_module::<Test>("run_out_of_gas").unwrap();
+	let subsistence = Pallet::<Test>::subsistence_threshold();
+
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				100 * subsistence,
+				GAS_LIMIT,
+				wasm,
+				vec![],
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+
+			// Call the contract with a fixed gas limit. It must run out of gas because it just
+			// loops forever.
+			assert_err_ignore_postinfo!(
+				Contracts::call(
+					Origin::signed(ALICE),
+					addr, // newly created account
+					0,
+					67_500_000,
+					vec![],
+				),
+				Error::<Test>::OutOfGas,
+			);
+		});
+}
+
+/// Input data for each call in set_rent code
+mod call {
+	use super::{AccountIdOf, Test};
+	pub fn set_storage_4_byte() -> Vec<u8> {
+		0u32.to_le_bytes().to_vec()
+	}
+	pub fn remove_storage_4_byte() -> Vec<u8> {
+		1u32.to_le_bytes().to_vec()
+	}
+	#[allow(dead_code)]
+	pub fn transfer(to: &AccountIdOf<Test>) -> Vec<u8> {
+		2u32.to_le_bytes()
+			.iter()
+			.chain(AsRef::<[u8]>::as_ref(to))
+			.cloned()
+			.collect()
+	}
+	pub fn null() -> Vec<u8> {
+		3u32.to_le_bytes().to_vec()
+	}
+}
+
+#[test]
+fn storage_size() {
+	let (wasm, code_hash) = compile_module::<Test>("set_rent").unwrap();
+
+	// Storage size
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				30_000,
+				GAS_LIMIT,
+				wasm,
+				// rent_allowance
+				<Test as pallet_balances::Config>::Balance::from(10_000u32).encode(),
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+			let bob_contract = ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			assert_eq!(bob_contract.storage_size, 4);
+			assert_eq!(bob_contract.pair_count, 1,);
+
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr.clone(),
+				0,
+				GAS_LIMIT,
+				call::set_storage_4_byte()
+			));
+			let bob_contract = ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			assert_eq!(bob_contract.storage_size, 4 + 4);
+			assert_eq!(bob_contract.pair_count, 2,);
+
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr.clone(),
+				0,
+				GAS_LIMIT,
+				call::remove_storage_4_byte()
+			));
+			let bob_contract = ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			assert_eq!(bob_contract.storage_size, 4);
+			assert_eq!(bob_contract.pair_count, 1,);
+		});
+}
+
+#[test]
+fn empty_kv_pairs() {
+	let (wasm, code_hash) = compile_module::<Test>("set_empty_storage").unwrap();
+
+	ExtBuilder::default().build().execute_with(|| {
+		let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+		assert_ok!(Contracts::instantiate_with_code(
+			Origin::signed(ALICE),
+			30_000,
+			GAS_LIMIT,
+			wasm,
+			vec![],
+			vec![],
+		));
+		let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+		let bob_contract = ContractInfoOf::<Test>::get(&addr)
+			.unwrap()
+			.get_alive()
+			.unwrap();
+
+		assert_eq!(bob_contract.storage_size, 0,);
+		assert_eq!(bob_contract.pair_count, 1,);
+	});
+}
+
+fn initialize_block(number: u64) {
+	System::initialize(
+		&number,
+		&[0u8; 32].into(),
+		&Default::default(),
+		Default::default(),
+	);
+}
+
+#[test]
+fn deduct_blocks() {
+	let (wasm, code_hash) = compile_module::<Test>("set_rent").unwrap();
+	let endowment: BalanceOf<Test> = 100_000;
+	let allowance: BalanceOf<Test> = 70_000;
+
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				endowment,
+				GAS_LIMIT,
+				wasm,
+				allowance.encode(),
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+			let contract = ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			let code_len: BalanceOf<Test> =
+				PrefabWasmModule::<Test>::from_storage_noinstr(contract.code_hash)
+					.unwrap()
+					.occupied_storage()
+					.into();
+
+			// The instantiation deducted the rent for one block immediately
+			let rent0 = <Test as Config>::RentFraction::get()
+				// (base_deposit(8) + bytes in storage(4) + size of code) * byte_price
+				// + 1 storage item (10_000) - free_balance
+				.mul_ceil((8 + 4 + code_len) * 10_000 + 10_000 - endowment)
+				// blocks to rent
+				* 1;
+			assert!(rent0 > 0);
+			assert_eq!(contract.rent_allowance, allowance - rent0);
+			assert_eq!(contract.deduct_block, 1);
+			assert_eq!(Balances::free_balance(&addr), endowment - rent0);
+
+			// Advance 4 blocks
+			initialize_block(5);
+
+			// Trigger rent through call
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr.clone(),
+				0,
+				GAS_LIMIT,
+				call::null()
+			));
+
+			// Check result
+			let rent = <Test as Config>::RentFraction::get()
+				.mul_ceil((8 + 4 + code_len) * 10_000 + 10_000 - (endowment - rent0))
+				* 4;
+			let contract = ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			assert_eq!(contract.rent_allowance, allowance - rent0 - rent);
+			assert_eq!(contract.deduct_block, 5);
+			assert_eq!(Balances::free_balance(&addr), endowment - rent0 - rent);
+
+			// Advance 2 blocks more
+			initialize_block(7);
+
+			// Trigger rent through call
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr.clone(),
+				0,
+				GAS_LIMIT,
+				call::null()
+			));
+
+			// Check result
+			let rent_2 = <Test as Config>::RentFraction::get()
+				.mul_ceil((8 + 4 + code_len) * 10_000 + 10_000 - (endowment - rent0 - rent))
+				* 2;
+			let contract = ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			assert_eq!(contract.rent_allowance, allowance - rent0 - rent - rent_2);
+			assert_eq!(contract.deduct_block, 7);
+			assert_eq!(
+				Balances::free_balance(&addr),
+				endowment - rent0 - rent - rent_2
+			);
+
+			// Second call on same block should have no effect on rent
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr.clone(),
+				0,
+				GAS_LIMIT,
+				call::null()
+			));
+			let contract = ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			assert_eq!(contract.rent_allowance, allowance - rent0 - rent - rent_2);
+			assert_eq!(contract.deduct_block, 7);
+			assert_eq!(
+				Balances::free_balance(&addr),
+				endowment - rent0 - rent - rent_2
+			)
+		});
+}
+
+#[test]
+fn inherent_claim_surcharge_contract_removals() {
+	removals(|addr| Contracts::claim_surcharge(Origin::none(), addr, Some(ALICE)).is_ok());
+}
+
+#[test]
+fn signed_claim_surcharge_contract_removals() {
+	removals(|addr| Contracts::claim_surcharge(Origin::signed(ALICE), addr, None).is_ok());
+}
+
+#[test]
+fn claim_surcharge_malus() {
+	// Test surcharge malus for inherent
+	claim_surcharge(
+		8,
+		|addr| Contracts::claim_surcharge(Origin::none(), addr, Some(ALICE)).is_ok(),
+		true,
+	);
+	claim_surcharge(
+		7,
+		|addr| Contracts::claim_surcharge(Origin::none(), addr, Some(ALICE)).is_ok(),
+		true,
+	);
+	claim_surcharge(
+		6,
+		|addr| Contracts::claim_surcharge(Origin::none(), addr, Some(ALICE)).is_ok(),
+		true,
+	);
+	claim_surcharge(
+		5,
+		|addr| Contracts::claim_surcharge(Origin::none(), addr, Some(ALICE)).is_ok(),
+		false,
+	);
+
+	// Test surcharge malus for signed
+	claim_surcharge(
+		8,
+		|addr| Contracts::claim_surcharge(Origin::signed(ALICE), addr, None).is_ok(),
+		true,
+	);
+	claim_surcharge(
+		7,
+		|addr| Contracts::claim_surcharge(Origin::signed(ALICE), addr, None).is_ok(),
+		false,
+	);
+	claim_surcharge(
+		6,
+		|addr| Contracts::claim_surcharge(Origin::signed(ALICE), addr, None).is_ok(),
+		false,
+	);
+	claim_surcharge(
+		5,
+		|addr| Contracts::claim_surcharge(Origin::signed(ALICE), addr, None).is_ok(),
+		false,
+	);
+}
+
+/// Claim surcharge with the given trigger_call at the given blocks.
+/// If `removes` is true then assert that the contract is a tombstone.
+fn claim_surcharge(blocks: u64, trigger_call: impl Fn(AccountIdOf<Test>) -> bool, removes: bool) {
+	let (wasm, code_hash) = compile_module::<Test>("set_rent").unwrap();
+
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				100_000,
+				GAS_LIMIT,
+				wasm,
+				<Test as pallet_balances::Config>::Balance::from(30_000u32).encode(), // rent allowance
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+
+			// Advance blocks
+			initialize_block(blocks);
+
+			// Trigger rent through call
+			assert_eq!(trigger_call(addr.clone()), removes);
+
+			if removes {
+				assert!(ContractInfoOf::<Test>::get(&addr)
+					.unwrap()
+					.get_tombstone()
+					.is_some());
+			} else {
+				assert!(ContractInfoOf::<Test>::get(&addr)
+					.unwrap()
+					.get_alive()
+					.is_some());
+			}
+		});
+}
+
+/// Test for all kind of removals for the given trigger:
+/// * if balance is reached and balance > subsistence threshold
+/// * if allowance is exceeded
+/// * if balance is reached and balance < subsistence threshold
+///	    * this case cannot be triggered by a contract: we check whether a tombstone is left
+fn removals(trigger_call: impl Fn(AccountIdOf<Test>) -> bool) {
+	let (wasm, code_hash) = compile_module::<Test>("set_rent").unwrap();
+
+	// Balance reached and superior to subsistence threshold
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				70_000,
+				GAS_LIMIT,
+				wasm.clone(),
+				<Test as pallet_balances::Config>::Balance::from(100_000u32).encode(), // rent allowance
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+			let allowance = ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap()
+				.rent_allowance;
+			let balance = Balances::free_balance(&addr);
+
+			let subsistence_threshold = Pallet::<Test>::subsistence_threshold();
+
+			// Trigger rent must have no effect
+			assert!(!trigger_call(addr.clone()));
+			assert_eq!(
+				ContractInfoOf::<Test>::get(&addr)
+					.unwrap()
+					.get_alive()
+					.unwrap()
+					.rent_allowance,
+				allowance,
+			);
+			assert_eq!(Balances::free_balance(&addr), balance);
+
+			// Advance blocks
+			initialize_block(27);
+
+			// Trigger rent through call (should remove the contract)
+			assert!(trigger_call(addr.clone()));
+			assert!(ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_tombstone()
+				.is_some());
+			assert_eq!(Balances::free_balance(&addr), subsistence_threshold);
+
+			// Advance blocks
+			initialize_block(30);
+
+			// Trigger rent must have no effect
+			assert!(!trigger_call(addr.clone()));
+			assert!(ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_tombstone()
+				.is_some());
+			assert_eq!(Balances::free_balance(&addr), subsistence_threshold);
+		});
+
+	// Allowance exceeded
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				100_000,
+				GAS_LIMIT,
+				wasm.clone(),
+				<Test as pallet_balances::Config>::Balance::from(70_000u32).encode(), // rent allowance
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+			let allowance = ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap()
+				.rent_allowance;
+			let balance = Balances::free_balance(&addr);
+
+			// Trigger rent must have no effect
+			assert!(!trigger_call(addr.clone()));
+			assert_eq!(
+				ContractInfoOf::<Test>::get(&addr)
+					.unwrap()
+					.get_alive()
+					.unwrap()
+					.rent_allowance,
+				allowance,
+			);
+			assert_eq!(Balances::free_balance(&addr), balance);
+
+			// Advance blocks
+			initialize_block(27);
+
+			// Trigger rent through call
+			assert!(trigger_call(addr.clone()));
+			assert!(ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_tombstone()
+				.is_some());
+			// Balance should be initial balance - initial rent_allowance
+			assert_eq!(Balances::free_balance(&addr), 30_000);
+
+			// Advance blocks
+			initialize_block(20);
+
+			// Trigger rent must have no effect
+			assert!(!trigger_call(addr.clone()));
+			assert!(ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_tombstone()
+				.is_some());
+			assert_eq!(Balances::free_balance(&addr), 30_000);
+		});
+
+	// Balance reached and inferior to subsistence threshold
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let subsistence_threshold = Pallet::<Test>::subsistence_threshold();
+			let _ = Balances::deposit_creating(&ALICE, subsistence_threshold * 1000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence_threshold * 100,
+				GAS_LIMIT,
+				wasm,
+				(subsistence_threshold * 100).encode(), // rent allowance
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+			let allowance = ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap()
+				.rent_allowance;
+			let balance = Balances::free_balance(&addr);
+
+			// Trigger rent must have no effect
+			assert!(!trigger_call(addr.clone()));
+			assert_eq!(
+				ContractInfoOf::<Test>::get(&addr)
+					.unwrap()
+					.get_alive()
+					.unwrap()
+					.rent_allowance,
+				allowance,
+			);
+			assert_eq!(Balances::free_balance(&addr), balance,);
+
+			// Make contract have exactly the subsistence threshold
+			Balances::make_free_balance_be(&addr, subsistence_threshold);
+			assert_eq!(Balances::free_balance(&addr), subsistence_threshold);
+
+			// Advance blocks (should remove as balance is exactly subsistence)
+			initialize_block(10);
+
+			// Trigger rent through call
+			assert!(trigger_call(addr.clone()));
+			assert_matches!(
+				ContractInfoOf::<Test>::get(&addr),
+				Some(ContractInfo::Tombstone(_))
+			);
+			assert_eq!(Balances::free_balance(&addr), subsistence_threshold);
+
+			// Advance blocks
+			initialize_block(20);
+
+			// Trigger rent must have no effect
+			assert!(!trigger_call(addr.clone()));
+			assert_matches!(
+				ContractInfoOf::<Test>::get(&addr),
+				Some(ContractInfo::Tombstone(_))
+			);
+			assert_eq!(Balances::free_balance(&addr), subsistence_threshold);
+		});
+}
+
+#[test]
+fn call_removed_contract() {
+	let (wasm, code_hash) = compile_module::<Test>("set_rent").unwrap();
+
+	// Balance reached and superior to subsistence threshold
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				30_000,
+				GAS_LIMIT,
+				wasm,
+				// rent allowance
+				<Test as pallet_balances::Config>::Balance::from(10_000u32).encode(),
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+
+			// Calling contract should succeed.
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr.clone(),
+				0,
+				GAS_LIMIT,
+				call::null()
+			));
+
+			// Advance blocks
+			initialize_block(27);
+
+			// Calling contract should deny access because rent cannot be paid.
+			assert_err_ignore_postinfo!(
+				Contracts::call(
+					Origin::signed(ALICE),
+					addr.clone(),
+					0,
+					GAS_LIMIT,
+					call::null()
+				),
+				Error::<Test>::NotCallable
+			);
+			// No event is generated because the contract is not actually removed.
+			assert_eq!(System::events(), vec![]);
+
+			// Subsequent contract calls should also fail.
+			assert_err_ignore_postinfo!(
+				Contracts::call(
+					Origin::signed(ALICE),
+					addr.clone(),
+					0,
+					GAS_LIMIT,
+					call::null()
+				),
+				Error::<Test>::NotCallable
+			);
+
+			// A snitch can now remove the contract
+			assert_ok!(Contracts::claim_surcharge(
+				Origin::none(),
+				addr.clone(),
+				Some(ALICE)
+			));
+			assert!(ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_tombstone()
+				.is_some());
+		})
+}
+
+#[test]
+fn default_rent_allowance_on_instantiate() {
+	let (wasm, code_hash) = compile_module::<Test>("check_default_rent_allowance").unwrap();
+
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				30_000,
+				GAS_LIMIT,
+				wasm,
+				vec![],
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+			let contract = ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			let code_len: BalanceOf<Test> =
+				PrefabWasmModule::<Test>::from_storage_noinstr(contract.code_hash)
+					.unwrap()
+					.occupied_storage()
+					.into();
+
+			// The instantiation deducted the rent for one block immediately
+			let first_rent = <Test as Config>::RentFraction::get()
+				// (base_deposit(8) + code_len) * byte_price - free_balance
+				.mul_ceil((8 + code_len) * 10_000 - 30_000)
+				// blocks to rent
+				* 1;
+			assert_eq!(
+				contract.rent_allowance,
+				<BalanceOf<Test>>::max_value() - first_rent
+			);
+
+			// Advance blocks
+			initialize_block(5);
+
+			// Trigger rent through call
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr.clone(),
+				0,
+				GAS_LIMIT,
+				call::null()
+			));
+
+			// Check contract is still alive
+			let contract = ContractInfoOf::<Test>::get(&addr).unwrap().get_alive();
+			assert!(contract.is_some())
+		});
+}
+
+#[test]
+fn restorations_dirty_storage_and_different_storage() {
+	restoration(true, true, false);
+}
+
+#[test]
+fn restorations_dirty_storage() {
+	restoration(false, true, false);
+}
+
+#[test]
+fn restoration_different_storage() {
+	restoration(true, false, false);
+}
+
+#[test]
+fn restoration_code_evicted() {
+	restoration(false, false, true);
+}
+
+#[test]
+fn restoration_success() {
+	restoration(false, false, false);
+}
+
+fn restoration(
+	test_different_storage: bool,
+	test_restore_to_with_dirty_storage: bool,
+	test_code_evicted: bool,
+) {
+	let (set_rent_wasm, set_rent_code_hash) = compile_module::<Test>("set_rent").unwrap();
+	let (restoration_wasm, restoration_code_hash) = compile_module::<Test>("restoration").unwrap();
+	let allowance: <Test as pallet_balances::Config>::Balance = 10_000;
+
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+
+			// Create an account with address `BOB` with code `CODE_SET_RENT`.
+			// The input parameter sets the rent allowance to 0.
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				30_000,
+				GAS_LIMIT,
+				set_rent_wasm.clone(),
+				allowance.encode(),
+				vec![],
+			));
+			let addr_bob = Contracts::contract_address(&ALICE, &set_rent_code_hash, &[]);
+
+			let mut events = vec![
+				EventRecord {
+					phase: Phase::Initialization,
+					event: Event::frame_system(frame_system::Event::NewAccount(ALICE)),
+					topics: vec![],
+				},
+				EventRecord {
+					phase: Phase::Initialization,
+					event: Event::pallet_balances(pallet_balances::Event::Endowed(
+						ALICE, 1_000_000,
+					)),
+					topics: vec![],
+				},
+				EventRecord {
+					phase: Phase::Initialization,
+					event: Event::frame_system(frame_system::Event::NewAccount(addr_bob.clone())),
+					topics: vec![],
+				},
+				EventRecord {
+					phase: Phase::Initialization,
+					event: Event::pallet_balances(pallet_balances::Event::Endowed(
+						addr_bob.clone(),
+						30_000,
+					)),
+					topics: vec![],
+				},
+				EventRecord {
+					phase: Phase::Initialization,
+					event: Event::pallet_balances(pallet_balances::Event::Transfer(
+						ALICE,
+						addr_bob.clone(),
+						30_000,
+					)),
+					topics: vec![],
+				},
+				EventRecord {
+					phase: Phase::Initialization,
+					event: Event::pallet_contracts(crate::Event::CodeStored(
+						set_rent_code_hash.into(),
+					)),
+					topics: vec![],
+				},
+				EventRecord {
+					phase: Phase::Initialization,
+					event: Event::pallet_contracts(crate::Event::Instantiated(
+						ALICE,
+						addr_bob.clone(),
+					)),
+					topics: vec![],
+				},
+			];
+
+			// Create another contract from the same code in order to increment the codes
+			// refcounter so that it stays on chain.
+			if !test_code_evicted {
+				assert_ok!(Contracts::instantiate_with_code(
+					Origin::signed(ALICE),
+					20_000,
+					GAS_LIMIT,
+					set_rent_wasm,
+					allowance.encode(),
+					vec![1],
+				));
+				assert_refcount!(set_rent_code_hash, 2);
+				let addr_dummy = Contracts::contract_address(&ALICE, &set_rent_code_hash, &[1]);
+				events.extend(
+					[
+						EventRecord {
+							phase: Phase::Initialization,
+							event: Event::frame_system(frame_system::Event::NewAccount(
+								addr_dummy.clone(),
+							)),
+							topics: vec![],
+						},
+						EventRecord {
+							phase: Phase::Initialization,
+							event: Event::pallet_balances(pallet_balances::Event::Endowed(
+								addr_dummy.clone(),
+								20_000,
+							)),
+							topics: vec![],
+						},
+						EventRecord {
+							phase: Phase::Initialization,
+							event: Event::pallet_balances(pallet_balances::Event::Transfer(
+								ALICE,
+								addr_dummy.clone(),
+								20_000,
+							)),
+							topics: vec![],
+						},
+						EventRecord {
+							phase: Phase::Initialization,
+							event: Event::pallet_contracts(crate::Event::Instantiated(
+								ALICE,
+								addr_dummy.clone(),
+							)),
+							topics: vec![],
+						},
+					]
+					.iter()
+					.cloned(),
+				);
+			}
+
+			assert_eq!(System::events(), events);
+
+			// Check if `BOB` was created successfully and that the rent allowance is below what
+			// we specified as the first rent was already collected.
+			let bob_contract = ContractInfoOf::<Test>::get(&addr_bob)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			assert!(bob_contract.rent_allowance < allowance);
+
+			if test_different_storage {
+				assert_ok!(Contracts::call(
+					Origin::signed(ALICE),
+					addr_bob.clone(),
+					0,
+					GAS_LIMIT,
+					call::set_storage_4_byte()
+				));
+			}
+
+			// Advance blocks in order to make the contract run out of money for rent.
+			initialize_block(27);
+
+			// Call `BOB`, which makes it pay rent. Since the rent allowance is set to 20_000
+			// we expect that it is no longer callable but keeps existing until someone
+			// calls `claim_surcharge`.
+			assert_err_ignore_postinfo!(
+				Contracts::call(
+					Origin::signed(ALICE),
+					addr_bob.clone(),
+					0,
+					GAS_LIMIT,
+					call::null()
+				),
+				Error::<Test>::NotCallable
+			);
+			assert!(System::events().is_empty());
+			assert!(ContractInfoOf::<Test>::get(&addr_bob)
+				.unwrap()
+				.get_alive()
+				.is_some());
+			assert_ok!(Contracts::claim_surcharge(
+				Origin::none(),
+				addr_bob.clone(),
+				Some(ALICE)
+			));
+			assert!(ContractInfoOf::<Test>::get(&addr_bob)
+				.unwrap()
+				.get_tombstone()
+				.is_some());
+			if test_code_evicted {
+				assert_refcount!(set_rent_code_hash, 0);
+			} else {
+				assert_refcount!(set_rent_code_hash, 1);
+			}
+
+			// Create another account with the address `DJANGO` with `CODE_RESTORATION`.
+			//
+			// Note that we can't use `ALICE` for creating `DJANGO` so we create yet another
+			// account `CHARLIE` and create `DJANGO` with it.
+			let _ = Balances::deposit_creating(&CHARLIE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(CHARLIE),
+				30_000,
+				GAS_LIMIT,
+				restoration_wasm,
+				vec![],
+				vec![],
+			));
+			let addr_django = Contracts::contract_address(&CHARLIE, &restoration_code_hash, &[]);
+
+			// Before performing a call to `DJANGO` save its original trie id.
+			let django_trie_id = ContractInfoOf::<Test>::get(&addr_django)
+				.unwrap()
+				.get_alive()
+				.unwrap()
+				.trie_id;
+
+			// The trie is regarded as 'dirty' when it was written to in the current block.
+			if !test_restore_to_with_dirty_storage {
+				// Advance 1 block.
+				initialize_block(28);
+			}
+
+			// Perform a call to `DJANGO`. This should either perform restoration successfully or
+			// fail depending on the test parameters.
+			let perform_the_restoration = || {
+				Contracts::call(
+					Origin::signed(ALICE),
+					addr_django.clone(),
+					0,
+					GAS_LIMIT,
+					set_rent_code_hash
+						.as_ref()
+						.iter()
+						.chain(AsRef::<[u8]>::as_ref(&addr_bob))
+						.cloned()
+						.collect(),
+				)
+			};
+
+			// The key that is used in the restorer contract but is not in the target contract.
+			// Is supplied as delta to the restoration. We need it to check whether the key
+			// is properly removed on success but still there on failure.
+			let delta_key = {
+				let mut key = [0u8; 32];
+				key[0] = 1;
+				key
+			};
+
+			if test_different_storage || test_restore_to_with_dirty_storage || test_code_evicted {
+				// Parametrization of the test imply restoration failure. Check that `DJANGO` aka
+				// restoration contract is still in place and also that `BOB` doesn't exist.
+				let result = perform_the_restoration();
+				assert!(ContractInfoOf::<Test>::get(&addr_bob)
+					.unwrap()
+					.get_tombstone()
+					.is_some());
+				let django_contract = ContractInfoOf::<Test>::get(&addr_django)
+					.unwrap()
+					.get_alive()
+					.unwrap();
+				assert_eq!(django_contract.storage_size, 8);
+				assert_eq!(django_contract.trie_id, django_trie_id);
+				assert_eq!(django_contract.deduct_block, System::block_number());
+				assert_eq!(
+					Storage::<Test>::read(&django_trie_id, &delta_key),
+					Some(vec![40, 0, 0, 0]),
+				);
+				match (
+					test_different_storage,
+					test_restore_to_with_dirty_storage,
+					test_code_evicted,
+				) {
+					(true, false, false) => {
+						assert_err_ignore_postinfo!(result, Error::<Test>::InvalidTombstone,);
+						assert_eq!(System::events(), vec![]);
+					}
+					(_, true, false) => {
+						assert_err_ignore_postinfo!(result, Error::<Test>::InvalidContractOrigin,);
+						assert_eq!(
+							System::events(),
+							vec![
+								EventRecord {
+									phase: Phase::Initialization,
+									event: Event::pallet_contracts(crate::Event::Evicted(addr_bob)),
+									topics: vec![],
+								},
+								EventRecord {
+									phase: Phase::Initialization,
+									event: Event::frame_system(frame_system::Event::NewAccount(
+										CHARLIE
+									)),
+									topics: vec![],
+								},
+								EventRecord {
+									phase: Phase::Initialization,
+									event: Event::pallet_balances(pallet_balances::Event::Endowed(
+										CHARLIE, 1_000_000
+									)),
+									topics: vec![],
+								},
+								EventRecord {
+									phase: Phase::Initialization,
+									event: Event::frame_system(frame_system::Event::NewAccount(
+										addr_django.clone()
+									)),
+									topics: vec![],
+								},
+								EventRecord {
+									phase: Phase::Initialization,
+									event: Event::pallet_balances(pallet_balances::Event::Endowed(
+										addr_django.clone(),
+										30_000
+									)),
+									topics: vec![],
+								},
+								EventRecord {
+									phase: Phase::Initialization,
+									event: Event::pallet_balances(
+										pallet_balances::Event::Transfer(
+											CHARLIE,
+											addr_django.clone(),
+											30_000
+										)
+									),
+									topics: vec![],
+								},
+								EventRecord {
+									phase: Phase::Initialization,
+									event: Event::pallet_contracts(crate::Event::CodeStored(
+										restoration_code_hash
+									)),
+									topics: vec![],
+								},
+								EventRecord {
+									phase: Phase::Initialization,
+									event: Event::pallet_contracts(crate::Event::Instantiated(
+										CHARLIE,
+										addr_django.clone()
+									)),
+									topics: vec![],
+								},
+							]
+						);
+					}
+					(false, false, true) => {
+						assert_err_ignore_postinfo!(result, Error::<Test>::CodeNotFound,);
+						assert_refcount!(set_rent_code_hash, 0);
+						assert_eq!(System::events(), vec![]);
+					}
+					_ => unreachable!(),
+				}
+			} else {
+				assert_ok!(perform_the_restoration());
+				assert_refcount!(set_rent_code_hash, 2);
+
+				// Here we expect that the restoration is succeeded. Check that the restoration
+				// contract `DJANGO` ceased to exist and that `BOB` returned back.
+				let bob_contract = ContractInfoOf::<Test>::get(&addr_bob)
+					.unwrap()
+					.get_alive()
+					.unwrap();
+				assert_eq!(bob_contract.rent_allowance, 50);
+				assert_eq!(bob_contract.storage_size, 4);
+				assert_eq!(bob_contract.trie_id, django_trie_id);
+				assert_eq!(bob_contract.deduct_block, System::block_number());
+				assert!(ContractInfoOf::<Test>::get(&addr_django).is_none());
+				assert_matches!(Storage::<Test>::read(&django_trie_id, &delta_key), None);
+				assert_eq!(
+					System::events(),
+					vec![
+						EventRecord {
+							phase: Phase::Initialization,
+							event: Event::pallet_contracts(crate::Event::CodeRemoved(
+								restoration_code_hash
+							)),
+							topics: vec![],
+						},
+						EventRecord {
+							phase: Phase::Initialization,
+							event: Event::frame_system(system::Event::KilledAccount(
+								addr_django.clone()
+							)),
+							topics: vec![],
+						},
+						EventRecord {
+							phase: Phase::Initialization,
+							event: Event::pallet_contracts(crate::Event::Restored(
+								addr_django,
+								addr_bob,
+								bob_contract.code_hash,
+								50
+							)),
+							topics: vec![],
+						},
+					]
+				);
+			}
+		});
+}
+
+#[test]
+fn storage_max_value_limit() {
+	let (wasm, code_hash) = compile_module::<Test>("storage_size").unwrap();
+
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				30_000,
+				GAS_LIMIT,
+				wasm,
+				vec![],
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+			ContractInfoOf::<Test>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+
+			// Call contract with allowed storage value.
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr.clone(),
+				0,
+				GAS_LIMIT * 2, // we are copying a huge buffer
+				<Test as Config>::MaxValueSize::get().encode(),
+			));
+
+			// Call contract with too large a storage value.
+			assert_err_ignore_postinfo!(
+				Contracts::call(
+					Origin::signed(ALICE),
+					addr,
+					0,
+					GAS_LIMIT,
+					(<Test as Config>::MaxValueSize::get() + 1).encode(),
+				),
+				Error::<Test>::ValueTooLarge,
+			);
+		});
+}
+
+#[test]
+fn deploy_and_call_other_contract() {
+	let (callee_wasm, callee_code_hash) = compile_module::<Test>("return_with_data").unwrap();
+	let (caller_wasm, caller_code_hash) = compile_module::<Test>("caller_contract").unwrap();
+
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				100_000,
+				GAS_LIMIT,
+				caller_wasm,
+				vec![],
+				vec![],
+			));
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				100_000,
+				GAS_LIMIT,
+				callee_wasm,
+				0u32.to_le_bytes().encode(),
+				vec![42],
+			));
+
+			// Call BOB contract, which attempts to instantiate and call the callee contract and
+			// makes various assertions on the results from those calls.
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				Contracts::contract_address(&ALICE, &caller_code_hash, &[]),
+				0,
+				GAS_LIMIT,
+				callee_code_hash.as_ref().to_vec(),
+			));
+		});
+}
+
+#[test]
+fn cannot_self_destruct_through_draning() {
+	let (wasm, code_hash) = compile_module::<Test>("drain").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+
+			// Instantiate the BOB contract.
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				100_000,
+				GAS_LIMIT,
+				wasm,
+				vec![],
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+
+			// Check that the BOB contract has been instantiated.
+			assert_matches!(
+				ContractInfoOf::<Test>::get(&addr),
+				Some(ContractInfo::Alive(_))
+			);
+
+			// Call BOB which makes it send all funds to the zero address
+			// The contract code asserts that the correct error value is returned.
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr,
+				0,
+				GAS_LIMIT,
+				vec![],
+			));
+		});
+}
+
+#[test]
+fn cannot_self_destruct_while_live() {
+	let (wasm, code_hash) = compile_module::<Test>("self_destruct").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+
+			// Instantiate the BOB contract.
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				100_000,
+				GAS_LIMIT,
+				wasm,
+				vec![],
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+
+			// Check that the BOB contract has been instantiated.
+			assert_matches!(
+				ContractInfoOf::<Test>::get(&addr),
+				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_ignore_postinfo!(
+				Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, vec![0],),
+				Error::<Test>::ContractTrapped,
+			);
+
+			// Check that BOB is still alive.
+			assert_matches!(
+				ContractInfoOf::<Test>::get(&addr),
+				Some(ContractInfo::Alive(_))
+			);
+		});
+}
+
+#[test]
+fn self_destruct_works() {
+	let (wasm, code_hash) = compile_module::<Test>("self_destruct").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			let _ = Balances::deposit_creating(&DJANGO, 1_000_000);
+
+			// Instantiate the BOB contract.
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				100_000,
+				GAS_LIMIT,
+				wasm,
+				vec![],
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+
+			// Check that the BOB contract has been instantiated.
+			assert_matches!(
+				ContractInfoOf::<Test>::get(&addr),
+				Some(ContractInfo::Alive(_))
+			);
+
+			// Drop all previous events
+			initialize_block(2);
+
+			// Call BOB without input data which triggers termination.
+			assert_matches!(
+				Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, vec![],),
+				Ok(_)
+			);
+
+			pretty_assertions::assert_eq!(
+				System::events(),
+				vec![
+					EventRecord {
+						phase: Phase::Initialization,
+						event: Event::frame_system(frame_system::Event::KilledAccount(
+							addr.clone()
+						)),
+						topics: vec![],
+					},
+					EventRecord {
+						phase: Phase::Initialization,
+						event: Event::pallet_balances(pallet_balances::Event::Transfer(
+							addr.clone(),
+							DJANGO,
+							93_086
+						)),
+						topics: vec![],
+					},
+					EventRecord {
+						phase: Phase::Initialization,
+						event: Event::pallet_contracts(crate::Event::CodeRemoved(code_hash)),
+						topics: vec![],
+					},
+					EventRecord {
+						phase: Phase::Initialization,
+						event: Event::pallet_contracts(crate::Event::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
+			// some rent was deducted before termination
+			assert_eq!(Balances::free_balance(DJANGO), 1_093_086);
+		});
+}
+
+// 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>("self_destruct").unwrap();
+	let (caller_wasm, caller_code_hash) = compile_module::<Test>("destroy_and_transfer").unwrap();
+
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				200_000,
+				GAS_LIMIT,
+				callee_wasm,
+				vec![],
+				vec![42]
+			));
+
+			// This deploys the BOB contract, which in turn deploys the CHARLIE contract during
+			// construction.
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				200_000,
+				GAS_LIMIT,
+				caller_wasm,
+				callee_code_hash.as_ref().to_vec(),
+				vec![],
+			));
+			let addr_bob = Contracts::contract_address(&ALICE, &caller_code_hash, &[]);
+			let addr_charlie =
+				Contracts::contract_address(&addr_bob, &callee_code_hash, &[0x47, 0x11]);
+
+			// Check that the CHARLIE contract has been instantiated.
+			assert_matches!(
+				ContractInfoOf::<Test>::get(&addr_charlie),
+				Some(ContractInfo::Alive(_))
+			);
+
+			// Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct.
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr_bob,
+				0,
+				GAS_LIMIT,
+				addr_charlie.encode(),
+			));
+
+			// Check that CHARLIE has moved on to the great beyond (ie. died).
+			assert!(ContractInfoOf::<Test>::get(&addr_charlie).is_none());
+		});
+}
+
+#[test]
+fn cannot_self_destruct_in_constructor() {
+	let (wasm, _) = compile_module::<Test>("self_destructing_constructor").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+
+			// Fail to instantiate the BOB because the contructor calls seal_terminate.
+			assert_err_ignore_postinfo!(
+				Contracts::instantiate_with_code(
+					Origin::signed(ALICE),
+					100_000,
+					GAS_LIMIT,
+					wasm,
+					vec![],
+					vec![],
+				),
+				Error::<Test>::NotCallable,
+			);
+		});
+}
+
+#[test]
+fn crypto_hashes() {
+	let (wasm, code_hash) = compile_module::<Test>("crypto_hashes").unwrap();
+
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+
+			// Instantiate the CRYPTO_HASHES contract.
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				100_000,
+				GAS_LIMIT,
+				wasm,
+				vec![],
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+			// Perform the call.
+			let input = b"_DEAD_BEEF";
+			use sp_io::hashing::*;
+			// Wraps a hash function into a more dynamic form usable for testing.
+			macro_rules! dyn_hash_fn {
+				($name:ident) => {
+					Box::new(|input| $name(input).as_ref().to_vec().into_boxed_slice())
+				};
+			}
+			// All hash functions and their associated output byte lengths.
+			let test_cases: &[(Box<dyn Fn(&[u8]) -> Box<[u8]>>, usize)] = &[
+				(dyn_hash_fn!(sha2_256), 32),
+				(dyn_hash_fn!(keccak_256), 32),
+				(dyn_hash_fn!(blake2_256), 32),
+				(dyn_hash_fn!(blake2_128), 16),
+			];
+			// Test the given hash functions for the input: "_DEAD_BEEF"
+			for (n, (hash_fn, expected_size)) in test_cases.iter().enumerate() {
+				// We offset data in the contract tables by 1.
+				let mut params = vec![(n + 1) as u8];
+				params.extend_from_slice(input);
+				let result = <Pallet<Test>>::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, params)
+					.result
+					.unwrap();
+				assert!(result.is_success());
+				let expected = hash_fn(input.as_ref());
+				assert_eq!(&result.data[..*expected_size], &*expected);
+			}
+		})
+}
+
+#[test]
+fn transfer_return_code() {
+	let (wasm, code_hash) = compile_module::<Test>("transfer_return_code").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+			let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence);
+
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				wasm,
+				vec![],
+				vec![],
+			),);
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+
+			// Contract has only the minimal balance so any transfer will return BelowSubsistence.
+			Balances::make_free_balance_be(&addr, subsistence);
+			let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![])
+				.result
+				.unwrap();
+			assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold);
+
+			// Contract has enough total balance in order to not go below the subsistence
+			// threshold when transfering 100 balance but this balance is reserved so
+			// the transfer still fails but with another return code.
+			Balances::make_free_balance_be(&addr, subsistence + 100);
+			Balances::reserve(&addr, subsistence + 100).unwrap();
+			let result = Contracts::bare_call(ALICE, addr, 0, GAS_LIMIT, vec![])
+				.result
+				.unwrap();
+			assert_return_code!(result, RuntimeReturnCode::TransferFailed);
+		});
+}
+
+#[test]
+fn call_return_code() {
+	let (caller_code, caller_hash) = compile_module::<Test>("call_return_code").unwrap();
+	let (callee_code, callee_hash) = compile_module::<Test>("ok_trap_revert").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+			let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence);
+			let _ = Balances::deposit_creating(&CHARLIE, 1000 * subsistence);
+
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				caller_code,
+				vec![0],
+				vec![],
+			),);
+			let addr_bob = Contracts::contract_address(&ALICE, &caller_hash, &[]);
+			Balances::make_free_balance_be(&addr_bob, subsistence);
+
+			// Contract calls into Django which is no valid contract
+			let result = Contracts::bare_call(
+				ALICE,
+				addr_bob.clone(),
+				0,
+				GAS_LIMIT,
+				AsRef::<[u8]>::as_ref(&DJANGO).to_vec(),
+			)
+			.result
+			.unwrap();
+			assert_return_code!(result, RuntimeReturnCode::NotCallable);
+
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(CHARLIE),
+				subsistence * 100,
+				GAS_LIMIT,
+				callee_code,
+				vec![0],
+				vec![],
+			),);
+			let addr_django = Contracts::contract_address(&CHARLIE, &callee_hash, &[]);
+			Balances::make_free_balance_be(&addr_django, subsistence);
+
+			// Contract has only the minimal balance so any transfer will return BelowSubsistence.
+			let result = Contracts::bare_call(
+				ALICE,
+				addr_bob.clone(),
+				0,
+				GAS_LIMIT,
+				AsRef::<[u8]>::as_ref(&addr_django)
+					.iter()
+					.chain(&0u32.to_le_bytes())
+					.cloned()
+					.collect(),
+			)
+			.result
+			.unwrap();
+			assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold);
+
+			// Contract has enough total balance in order to not go below the subsistence
+			// threshold when transfering 100 balance but this balance is reserved so
+			// the transfer still fails but with another return code.
+			Balances::make_free_balance_be(&addr_bob, subsistence + 100);
+			Balances::reserve(&addr_bob, subsistence + 100).unwrap();
+			let result = Contracts::bare_call(
+				ALICE,
+				addr_bob.clone(),
+				0,
+				GAS_LIMIT,
+				AsRef::<[u8]>::as_ref(&addr_django)
+					.iter()
+					.chain(&0u32.to_le_bytes())
+					.cloned()
+					.collect(),
+			)
+			.result
+			.unwrap();
+			assert_return_code!(result, RuntimeReturnCode::TransferFailed);
+
+			// Contract has enough balance but callee reverts because "1" is passed.
+			Balances::make_free_balance_be(&addr_bob, subsistence + 1000);
+			let result = Contracts::bare_call(
+				ALICE,
+				addr_bob.clone(),
+				0,
+				GAS_LIMIT,
+				AsRef::<[u8]>::as_ref(&addr_django)
+					.iter()
+					.chain(&1u32.to_le_bytes())
+					.cloned()
+					.collect(),
+			)
+			.result
+			.unwrap();
+			assert_return_code!(result, RuntimeReturnCode::CalleeReverted);
+
+			// Contract has enough balance but callee traps because "2" is passed.
+			let result = Contracts::bare_call(
+				ALICE,
+				addr_bob,
+				0,
+				GAS_LIMIT,
+				AsRef::<[u8]>::as_ref(&addr_django)
+					.iter()
+					.chain(&2u32.to_le_bytes())
+					.cloned()
+					.collect(),
+			)
+			.result
+			.unwrap();
+			assert_return_code!(result, RuntimeReturnCode::CalleeTrapped);
+		});
+}
+
+#[test]
+fn instantiate_return_code() {
+	let (caller_code, caller_hash) = compile_module::<Test>("instantiate_return_code").unwrap();
+	let (callee_code, callee_hash) = compile_module::<Test>("ok_trap_revert").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+			let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence);
+			let _ = Balances::deposit_creating(&CHARLIE, 1000 * subsistence);
+			let callee_hash = callee_hash.as_ref().to_vec();
+
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				callee_code,
+				vec![],
+				vec![],
+			),);
+
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				caller_code,
+				vec![],
+				vec![],
+			),);
+			let addr = Contracts::contract_address(&ALICE, &caller_hash, &[]);
+
+			// Contract has only the minimal balance so any transfer will return BelowSubsistence.
+			Balances::make_free_balance_be(&addr, subsistence);
+			let result =
+				Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, callee_hash.clone())
+					.result
+					.unwrap();
+			assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold);
+
+			// Contract has enough total balance in order to not go below the subsistence
+			// threshold when transfering the balance but this balance is reserved so
+			// the transfer still fails but with another return code.
+			Balances::make_free_balance_be(&addr, subsistence + 10_000);
+			Balances::reserve(&addr, subsistence + 10_000).unwrap();
+			let result =
+				Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, callee_hash.clone())
+					.result
+					.unwrap();
+			assert_return_code!(result, RuntimeReturnCode::TransferFailed);
+
+			// Contract has enough balance but the passed code hash is invalid
+			Balances::make_free_balance_be(&addr, subsistence + 10_000);
+			let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![0; 33])
+				.result
+				.unwrap();
+			assert_return_code!(result, RuntimeReturnCode::CodeNotFound);
+
+			// Contract has enough balance but callee reverts because "1" is passed.
+			let result = Contracts::bare_call(
+				ALICE,
+				addr.clone(),
+				0,
+				GAS_LIMIT,
+				callee_hash
+					.iter()
+					.chain(&1u32.to_le_bytes())
+					.cloned()
+					.collect(),
+			)
+			.result
+			.unwrap();
+			assert_return_code!(result, RuntimeReturnCode::CalleeReverted);
+
+			// Contract has enough balance but callee traps because "2" is passed.
+			let result = Contracts::bare_call(
+				ALICE,
+				addr,
+				0,
+				GAS_LIMIT,
+				callee_hash
+					.iter()
+					.chain(&2u32.to_le_bytes())
+					.cloned()
+					.collect(),
+			)
+			.result
+			.unwrap();
+			assert_return_code!(result, RuntimeReturnCode::CalleeTrapped);
+		});
+}
+
+#[test]
+fn disabled_chain_extension_wont_deploy() {
+	let (code, _hash) = compile_module::<Test>("chain_extension").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+			let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence);
+			TestExtension::disable();
+			assert_err_ignore_postinfo!(
+				Contracts::instantiate_with_code(
+					Origin::signed(ALICE),
+					3 * subsistence,
+					GAS_LIMIT,
+					code,
+					vec![],
+					vec![],
+				),
+				"module uses chain extensions but chain extensions are disabled",
+			);
+		});
+}
+
+#[test]
+fn disabled_chain_extension_errors_on_call() {
+	let (code, hash) = compile_module::<Test>("chain_extension").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+			let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				code,
+				vec![],
+				vec![],
+			),);
+			let addr = Contracts::contract_address(&ALICE, &hash, &[]);
+			TestExtension::disable();
+			assert_err_ignore_postinfo!(
+				Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, vec![],),
+				Error::<Test>::NoChainExtension,
+			);
+		});
+}
+
+#[test]
+fn chain_extension_works() {
+	let (code, hash) = compile_module::<Test>("chain_extension").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+			let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				code,
+				vec![],
+				vec![],
+			),);
+			let addr = Contracts::contract_address(&ALICE, &hash, &[]);
+
+			// The contract takes a up to 2 byte buffer where the first byte passed is used as
+			// as func_id to the chain extension which behaves differently based on the
+			// func_id.
+
+			// 0 = read input buffer and pass it through as output
+			let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![0, 99]);
+			let gas_consumed = result.gas_consumed;
+			assert_eq!(TestExtension::last_seen_buffer(), vec![0, 99]);
+			assert_eq!(result.result.unwrap().data, Bytes(vec![0, 99]));
+
+			// 1 = treat inputs as integer primitives and store the supplied integers
+			Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![1])
+				.result
+				.unwrap();
+			// those values passed in the fixture
+			assert_eq!(TestExtension::last_seen_inputs(), (4, 1, 16, 12));
+
+			// 2 = charge some extra weight (amount supplied in second byte)
+			let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![2, 42]);
+			assert_ok!(result.result);
+			assert_eq!(result.gas_consumed, gas_consumed + 42);
+
+			// 3 = diverging chain extension call that sets flags to 0x1 and returns a fixed buffer
+			let result = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, vec![3])
+				.result
+				.unwrap();
+			assert_eq!(result.flags, ReturnFlags::REVERT);
+			assert_eq!(result.data, Bytes(vec![42, 99]));
+		});
+}
+
+#[test]
+fn lazy_removal_works() {
+	let (code, hash) = compile_module::<Test>("self_destruct").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+			let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence);
+
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				code,
+				vec![],
+				vec![],
+			),);
+
+			let addr = Contracts::contract_address(&ALICE, &hash, &[]);
+			let info = <ContractInfoOf<Test>>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			let trie = &info.child_trie_info();
+
+			// Put value into the contracts child trie
+			child::put(trie, &[99], &42);
+
+			// Terminate the contract
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr.clone(),
+				0,
+				GAS_LIMIT,
+				vec![],
+			));
+
+			// Contract info should be gone
+			assert!(!<ContractInfoOf::<Test>>::contains_key(&addr));
+
+			// But value should be still there as the lazy removal did not run, yet.
+			assert_matches!(child::get(trie, &[99]), Some(42));
+
+			// Run the lazy removal
+			Contracts::on_initialize(Weight::max_value());
+
+			// Value should be gone now
+			assert_matches!(child::get::<i32>(trie, &[99]), None);
+		});
+}
+
+#[test]
+fn lazy_removal_partial_remove_works() {
+	let (code, hash) = compile_module::<Test>("self_destruct").unwrap();
+
+	// We create a contract with some extra keys above the weight limit
+	let extra_keys = 7u32;
+	let weight_limit = 5_000_000_000;
+	let (_, max_keys) = Storage::<Test>::deletion_budget(1, weight_limit);
+	let vals: Vec<_> = (0..max_keys + extra_keys)
+		.map(|i| (blake2_256(&i.encode()), (i as u32), (i as u32).encode()))
+		.collect();
+
+	let mut ext = ExtBuilder::default().existential_deposit(50).build();
+
+	let trie = ext.execute_with(|| {
+		let subsistence = Pallet::<Test>::subsistence_threshold();
+		let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence);
+
+		assert_ok!(Contracts::instantiate_with_code(
+			Origin::signed(ALICE),
+			subsistence * 100,
+			GAS_LIMIT,
+			code,
+			vec![],
+			vec![],
+		),);
+
+		let addr = Contracts::contract_address(&ALICE, &hash, &[]);
+		let info = <ContractInfoOf<Test>>::get(&addr)
+			.unwrap()
+			.get_alive()
+			.unwrap();
+		let trie = &info.child_trie_info();
+
+		// Put value into the contracts child trie
+		for val in &vals {
+			Storage::<Test>::write(&addr, &info.trie_id, &val.0, Some(val.2.clone())).unwrap();
+		}
+
+		// Terminate the contract
+		assert_ok!(Contracts::call(
+			Origin::signed(ALICE),
+			addr.clone(),
+			0,
+			GAS_LIMIT,
+			vec![],
+		));
+
+		// Contract info should be gone
+		assert!(!<ContractInfoOf::<Test>>::contains_key(&addr));
+
+		// But value should be still there as the lazy removal did not run, yet.
+		for val in &vals {
+			assert_eq!(child::get::<u32>(trie, &blake2_256(&val.0)), Some(val.1));
+		}
+
+		trie.clone()
+	});
+
+	// The lazy removal limit only applies to the backend but not to the overlay.
+	// This commits all keys from the overlay to the backend.
+	ext.commit_all().unwrap();
+
+	ext.execute_with(|| {
+		// Run the lazy removal
+		let weight_used = Storage::<Test>::process_deletion_queue_batch(weight_limit);
+
+		// Weight should be exhausted because we could not even delete all keys
+		assert_eq!(weight_used, weight_limit);
+
+		let mut num_deleted = 0u32;
+		let mut num_remaining = 0u32;
+
+		for val in &vals {
+			match child::get::<u32>(&trie, &blake2_256(&val.0)) {
+				None => num_deleted += 1,
+				Some(x) if x == val.1 => num_remaining += 1,
+				Some(_) => panic!("Unexpected value in contract storage"),
+			}
+		}
+
+		// All but one key is removed
+		assert_eq!(num_deleted + num_remaining, vals.len() as u32);
+		assert_eq!(num_deleted, max_keys);
+		assert_eq!(num_remaining, extra_keys);
+	});
+}
+
+#[test]
+fn lazy_removal_does_no_run_on_full_block() {
+	let (code, hash) = compile_module::<Test>("self_destruct").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+			let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence);
+
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				code,
+				vec![],
+				vec![],
+			),);
+
+			let addr = Contracts::contract_address(&ALICE, &hash, &[]);
+			let info = <ContractInfoOf<Test>>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			let trie = &info.child_trie_info();
+			let max_keys = 30;
+
+			// Create some storage items for the contract.
+			let vals: Vec<_> = (0..max_keys)
+				.map(|i| (blake2_256(&i.encode()), (i as u32), (i as u32).encode()))
+				.collect();
+
+			// Put value into the contracts child trie
+			for val in &vals {
+				Storage::<Test>::write(&addr, &info.trie_id, &val.0, Some(val.2.clone())).unwrap();
+			}
+
+			// Terminate the contract
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr.clone(),
+				0,
+				GAS_LIMIT,
+				vec![],
+			));
+
+			// Contract info should be gone
+			assert!(!<ContractInfoOf::<Test>>::contains_key(&addr));
+
+			// But value should be still there as the lazy removal did not run, yet.
+			for val in &vals {
+				assert_eq!(child::get::<u32>(trie, &blake2_256(&val.0)), Some(val.1));
+			}
+
+			// Fill up the block which should prevent the lazy storage removal from running.
+			System::register_extra_weight_unchecked(
+				<Test as system::Config>::BlockWeights::get().max_block,
+				DispatchClass::Mandatory,
+			);
+
+			// Run the lazy removal without any limit so that all keys would be removed if there
+			// had been some weight left in the block.
+			let weight_used = Contracts::on_initialize(Weight::max_value());
+			let base = <<Test as Config>::WeightInfo as WeightInfo>::on_initialize();
+			assert_eq!(weight_used, base);
+
+			// All the keys are still in place
+			for val in &vals {
+				assert_eq!(child::get::<u32>(trie, &blake2_256(&val.0)), Some(val.1));
+			}
+
+			// Run the lazy removal directly which disregards the block limits
+			Storage::<Test>::process_deletion_queue_batch(Weight::max_value());
+
+			// Now the keys should be gone
+			for val in &vals {
+				assert_eq!(child::get::<u32>(trie, &blake2_256(&val.0)), None);
+			}
+		});
+}
+
+#[test]
+fn lazy_removal_does_not_use_all_weight() {
+	let (code, hash) = compile_module::<Test>("self_destruct").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+			let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence);
+
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				code,
+				vec![],
+				vec![],
+			),);
+
+			let addr = Contracts::contract_address(&ALICE, &hash, &[]);
+			let info = <ContractInfoOf<Test>>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			let trie = &info.child_trie_info();
+			let weight_limit = 5_000_000_000;
+			let (weight_per_key, max_keys) = Storage::<Test>::deletion_budget(1, weight_limit);
+
+			// We create a contract with one less storage item than we can remove within the limit
+			let vals: Vec<_> = (0..max_keys - 1)
+				.map(|i| (blake2_256(&i.encode()), (i as u32), (i as u32).encode()))
+				.collect();
+
+			// Put value into the contracts child trie
+			for val in &vals {
+				Storage::<Test>::write(&addr, &info.trie_id, &val.0, Some(val.2.clone())).unwrap();
+			}
+
+			// Terminate the contract
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr.clone(),
+				0,
+				GAS_LIMIT,
+				vec![],
+			));
+
+			// Contract info should be gone
+			assert!(!<ContractInfoOf::<Test>>::contains_key(&addr));
+
+			// But value should be still there as the lazy removal did not run, yet.
+			for val in &vals {
+				assert_eq!(child::get::<u32>(trie, &blake2_256(&val.0)), Some(val.1));
+			}
+
+			// Run the lazy removal
+			let weight_used = Storage::<Test>::process_deletion_queue_batch(weight_limit);
+
+			// We have one less key in our trie than our weight limit suffices for
+			assert_eq!(weight_used, weight_limit - weight_per_key);
+
+			// All the keys are removed
+			for val in vals {
+				assert_eq!(child::get::<u32>(trie, &blake2_256(&val.0)), None);
+			}
+		});
+}
+
+#[test]
+fn deletion_queue_full() {
+	let (code, hash) = compile_module::<Test>("self_destruct").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+			let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence);
+
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				code,
+				vec![],
+				vec![],
+			),);
+
+			let addr = Contracts::contract_address(&ALICE, &hash, &[]);
+
+			// fill the deletion queue up until its limit
+			Storage::<Test>::fill_queue_with_dummies();
+
+			// Terminate the contract should fail
+			assert_err_ignore_postinfo!(
+				Contracts::call(Origin::signed(ALICE), addr.clone(), 0, GAS_LIMIT, vec![],),
+				Error::<Test>::DeletionQueueFull,
+			);
+
+			// Contract should be alive because removal failed
+			<ContractInfoOf<Test>>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+
+			// make the contract ripe for eviction
+			initialize_block(5);
+
+			// eviction should fail for the same reason as termination
+			assert_err!(
+				Contracts::claim_surcharge(Origin::none(), addr.clone(), Some(ALICE)),
+				Error::<Test>::DeletionQueueFull,
+			);
+
+			// Contract should be alive because removal failed
+			<ContractInfoOf<Test>>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+		});
+}
+
+#[test]
+fn not_deployed_if_endowment_too_low_for_first_rent() {
+	let (wasm, code_hash) = compile_module::<Test>("set_rent").unwrap();
+
+	// The instantiation deducted the rent for one block immediately
+	let first_rent = <Test as Config>::RentFraction::get()
+		// base_deposit + deploy_set_storage (4 bytes in 1 item) - free_balance
+		.mul_ceil(80_000u32 + 40_000 + 10_000 - 30_000)
+		// blocks to rent
+		* 1;
+
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			// Create
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_storage_noop!(assert_err_ignore_postinfo!(
+				Contracts::instantiate_with_code(
+					Origin::signed(ALICE),
+					30_000,
+					GAS_LIMIT,
+					wasm,
+					(BalanceOf::<Test>::from(first_rent) - BalanceOf::<Test>::from(1u32)).encode(), // rent allowance
+					vec![],
+				),
+				Error::<Test>::NewContractNotFunded,
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+			assert_matches!(ContractInfoOf::<Test>::get(&addr), None);
+		});
+}
+
+#[test]
+fn surcharge_reward_is_capped() {
+	let (wasm, code_hash) = compile_module::<Test>("set_rent").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				30_000,
+				GAS_LIMIT,
+				wasm,
+				<BalanceOf<Test>>::from(10_000u32).encode(), // rent allowance
+				vec![],
+			));
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+			let contract = <ContractInfoOf<Test>>::get(&addr)
+				.unwrap()
+				.get_alive()
+				.unwrap();
+			let balance = Balances::free_balance(&ALICE);
+			let reward = <Test as Config>::SurchargeReward::get();
+
+			// some rent should have payed due to instantiation
+			assert_ne!(contract.rent_payed, 0);
+
+			// the reward should be parameterized sufficiently high to make this test useful
+			assert!(reward > contract.rent_payed);
+
+			// make contract eligible for eviction
+			initialize_block(40);
+
+			// this should have removed the contract
+			assert_ok!(Contracts::claim_surcharge(
+				Origin::none(),
+				addr.clone(),
+				Some(ALICE)
+			));
+
+			// this reward does not take into account the last rent payment collected during eviction
+			let capped_reward = reward.min(contract.rent_payed);
+
+			// this is smaller than the actual reward because it does not take into account the
+			// rent collected during eviction
+			assert!(Balances::free_balance(&ALICE) > balance + capped_reward);
+
+			// the full reward is not payed out because of the cap introduced by rent_payed
+			assert!(Balances::free_balance(&ALICE) < balance + reward);
+		});
+}
+
+#[test]
+fn refcounter() {
+	let (wasm, code_hash) = compile_module::<Test>("self_destruct").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+
+			// Create two contracts with the same code and check that they do in fact share it.
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				wasm.clone(),
+				vec![],
+				vec![0],
+			));
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				wasm.clone(),
+				vec![],
+				vec![1],
+			));
+			assert_refcount!(code_hash, 2);
+
+			// Sharing should also work with the usual instantiate call
+			assert_ok!(Contracts::instantiate(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				code_hash,
+				vec![],
+				vec![2],
+			));
+			assert_refcount!(code_hash, 3);
+
+			// addresses of all three existing contracts
+			let addr0 = Contracts::contract_address(&ALICE, &code_hash, &[0]);
+			let addr1 = Contracts::contract_address(&ALICE, &code_hash, &[1]);
+			let addr2 = Contracts::contract_address(&ALICE, &code_hash, &[2]);
+
+			// Terminating one contract should decrement the refcount
+			assert_ok!(Contracts::call(
+				Origin::signed(ALICE),
+				addr0,
+				0,
+				GAS_LIMIT,
+				vec![],
+			));
+			assert_refcount!(code_hash, 2);
+
+			// make remaining contracts eligible for eviction
+			initialize_block(40);
+
+			// remove one of them
+			assert_ok!(Contracts::claim_surcharge(
+				Origin::none(),
+				addr1,
+				Some(ALICE)
+			));
+			assert_refcount!(code_hash, 1);
+
+			// Pristine code should still be there
+			crate::PristineCode::<Test>::get(code_hash).unwrap();
+
+			// remove the last contract
+			assert_ok!(Contracts::claim_surcharge(
+				Origin::none(),
+				addr2,
+				Some(ALICE)
+			));
+			assert_refcount!(code_hash, 0);
+
+			// all code should be gone
+			assert_matches!(crate::PristineCode::<Test>::get(code_hash), None);
+			assert_matches!(crate::CodeStorage::<Test>::get(code_hash), None);
+		});
+}
+
+#[test]
+fn reinstrument_does_charge() {
+	let (wasm, code_hash) = compile_module::<Test>("return_with_data").unwrap();
+	ExtBuilder::default()
+		.existential_deposit(50)
+		.build()
+		.execute_with(|| {
+			let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+			let subsistence = Pallet::<Test>::subsistence_threshold();
+			let zero = 0u32.to_le_bytes().encode();
+			let code_len = wasm.len() as u32;
+
+			assert_ok!(Contracts::instantiate_with_code(
+				Origin::signed(ALICE),
+				subsistence * 100,
+				GAS_LIMIT,
+				wasm,
+				zero.clone(),
+				vec![],
+			));
+
+			let addr = Contracts::contract_address(&ALICE, &code_hash, &[]);
+
+			// Call the contract two times without reinstrument
+
+			let result0 = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, zero.clone());
+			assert!(result0.result.unwrap().is_success());
+
+			let result1 = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, zero.clone());
+			assert!(result1.result.unwrap().is_success());
+
+			// They should match because both where called with the same schedule.
+			assert_eq!(result0.gas_consumed, result1.gas_consumed);
+
+			// Update the schedule version but keep the rest the same
+			crate::CurrentSchedule::mutate(|old: &mut Schedule<Test>| {
+				old.version += 1;
+			});
+
+			// This call should trigger reinstrumentation
+			let result2 = Contracts::bare_call(ALICE, addr.clone(), 0, GAS_LIMIT, zero.clone());
+			assert!(result2.result.unwrap().is_success());
+			assert!(result2.gas_consumed > result1.gas_consumed);
+			assert_eq!(
+				result2.gas_consumed,
+				result1.gas_consumed + <Test as Config>::WeightInfo::instrument(code_len / 1024),
+			);
+		});
+}
addedpallets/contracts/src/weights.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/contracts/src/weights.rs
@@ -0,0 +1,1417 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2021 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Autogenerated weights for pallet_contracts
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
+//! DATE: 2021-02-18, STEPS: `[50, ]`, REPEAT: 20, LOW RANGE: [], HIGH RANGE: []
+//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128
+
+// Executed Command:
+// target/release/substrate
+// benchmark
+// --chain=dev
+// --steps=50
+// --repeat=20
+// --pallet=pallet_contracts
+// --extrinsic=*
+// --execution=wasm
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --output=./frame/contracts/src/weights.rs
+// --template=./.maintain/frame-weight-template.hbs
+
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{
+	traits::Get,
+	weights::{Weight, constants::RocksDbWeight},
+};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for pallet_contracts.
+pub trait WeightInfo {
+	fn on_initialize() -> Weight;
+	fn on_initialize_per_trie_key(k: u32) -> Weight;
+	fn on_initialize_per_queue_item(q: u32) -> Weight;
+	fn instrument(c: u32) -> Weight;
+	fn update_schedule() -> Weight;
+	fn instantiate_with_code(c: u32, s: u32) -> Weight;
+	fn instantiate(c: u32, s: u32) -> Weight;
+	fn call(c: u32) -> Weight;
+	fn claim_surcharge(c: u32) -> Weight;
+	fn seal_caller(r: u32) -> Weight;
+	fn seal_address(r: u32) -> Weight;
+	fn seal_gas_left(r: u32) -> Weight;
+	fn seal_balance(r: u32) -> Weight;
+	fn seal_value_transferred(r: u32) -> Weight;
+	fn seal_minimum_balance(r: u32) -> Weight;
+	fn seal_tombstone_deposit(r: u32) -> Weight;
+	fn seal_rent_allowance(r: u32) -> Weight;
+	fn seal_block_number(r: u32) -> Weight;
+	fn seal_now(r: u32) -> Weight;
+	fn seal_rent_params(r: u32) -> Weight;
+	fn seal_weight_to_fee(r: u32) -> Weight;
+	fn seal_gas(r: u32) -> Weight;
+	fn seal_input(r: u32) -> Weight;
+	fn seal_input_per_kb(n: u32) -> Weight;
+	fn seal_return(r: u32) -> Weight;
+	fn seal_return_per_kb(n: u32) -> Weight;
+	fn seal_terminate(r: u32) -> Weight;
+	fn seal_terminate_per_code_kb(c: u32) -> Weight;
+	fn seal_restore_to(r: u32) -> Weight;
+	fn seal_restore_to_per_code_kb_delta(c: u32, t: u32, d: u32) -> Weight;
+	fn seal_random(r: u32) -> Weight;
+	fn seal_deposit_event(r: u32) -> Weight;
+	fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32) -> Weight;
+	fn seal_set_rent_allowance(r: u32) -> Weight;
+	fn seal_set_storage(r: u32) -> Weight;
+	fn seal_set_storage_per_kb(n: u32) -> Weight;
+	fn seal_clear_storage(r: u32) -> Weight;
+	fn seal_get_storage(r: u32) -> Weight;
+	fn seal_get_storage_per_kb(n: u32) -> Weight;
+	fn seal_transfer(r: u32) -> Weight;
+	fn seal_call(r: u32) -> Weight;
+	fn seal_call_per_code_transfer_input_output_kb(c: u32, t: u32, i: u32, o: u32) -> Weight;
+	fn seal_instantiate(r: u32) -> Weight;
+	fn seal_instantiate_per_code_input_output_salt_kb(c: u32, i: u32, o: u32, s: u32) -> Weight;
+	fn seal_hash_sha2_256(r: u32) -> Weight;
+	fn seal_hash_sha2_256_per_kb(n: u32) -> Weight;
+	fn seal_hash_keccak_256(r: u32) -> Weight;
+	fn seal_hash_keccak_256_per_kb(n: u32) -> Weight;
+	fn seal_hash_blake2_256(r: u32) -> Weight;
+	fn seal_hash_blake2_256_per_kb(n: u32) -> Weight;
+	fn seal_hash_blake2_128(r: u32) -> Weight;
+	fn seal_hash_blake2_128_per_kb(n: u32) -> Weight;
+	fn instr_i64const(r: u32) -> Weight;
+	fn instr_i64load(r: u32) -> Weight;
+	fn instr_i64store(r: u32) -> Weight;
+	fn instr_select(r: u32) -> Weight;
+	fn instr_if(r: u32) -> Weight;
+	fn instr_br(r: u32) -> Weight;
+	fn instr_br_if(r: u32) -> Weight;
+	fn instr_br_table(r: u32) -> Weight;
+	fn instr_br_table_per_entry(e: u32) -> Weight;
+	fn instr_call(r: u32) -> Weight;
+	fn instr_call_indirect(r: u32) -> Weight;
+	fn instr_call_indirect_per_param(p: u32) -> Weight;
+	fn instr_local_get(r: u32) -> Weight;
+	fn instr_local_set(r: u32) -> Weight;
+	fn instr_local_tee(r: u32) -> Weight;
+	fn instr_global_get(r: u32) -> Weight;
+	fn instr_global_set(r: u32) -> Weight;
+	fn instr_memory_current(r: u32) -> Weight;
+	fn instr_memory_grow(r: u32) -> Weight;
+	fn instr_i64clz(r: u32) -> Weight;
+	fn instr_i64ctz(r: u32) -> Weight;
+	fn instr_i64popcnt(r: u32) -> Weight;
+	fn instr_i64eqz(r: u32) -> Weight;
+	fn instr_i64extendsi32(r: u32) -> Weight;
+	fn instr_i64extendui32(r: u32) -> Weight;
+	fn instr_i32wrapi64(r: u32) -> Weight;
+	fn instr_i64eq(r: u32) -> Weight;
+	fn instr_i64ne(r: u32) -> Weight;
+	fn instr_i64lts(r: u32) -> Weight;
+	fn instr_i64ltu(r: u32) -> Weight;
+	fn instr_i64gts(r: u32) -> Weight;
+	fn instr_i64gtu(r: u32) -> Weight;
+	fn instr_i64les(r: u32) -> Weight;
+	fn instr_i64leu(r: u32) -> Weight;
+	fn instr_i64ges(r: u32) -> Weight;
+	fn instr_i64geu(r: u32) -> Weight;
+	fn instr_i64add(r: u32) -> Weight;
+	fn instr_i64sub(r: u32) -> Weight;
+	fn instr_i64mul(r: u32) -> Weight;
+	fn instr_i64divs(r: u32) -> Weight;
+	fn instr_i64divu(r: u32) -> Weight;
+	fn instr_i64rems(r: u32) -> Weight;
+	fn instr_i64remu(r: u32) -> Weight;
+	fn instr_i64and(r: u32) -> Weight;
+	fn instr_i64or(r: u32) -> Weight;
+	fn instr_i64xor(r: u32) -> Weight;
+	fn instr_i64shl(r: u32) -> Weight;
+	fn instr_i64shrs(r: u32) -> Weight;
+	fn instr_i64shru(r: u32) -> Weight;
+	fn instr_i64rotl(r: u32) -> Weight;
+	fn instr_i64rotr(r: u32) -> Weight;
+}
+
+/// Weights for pallet_contracts using the Substrate node and recommended hardware.
+pub struct SubstrateWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
+	fn on_initialize() -> Weight {
+		(3_850_000 as Weight).saturating_add(T::DbWeight::get().reads(1 as Weight))
+	}
+	fn on_initialize_per_trie_key(k: u32) -> Weight {
+		(52_925_000 as Weight)
+			// Standard Error: 5_000
+			.saturating_add((2_297_000 as Weight).saturating_mul(k as Weight))
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(k as Weight)))
+	}
+	fn on_initialize_per_queue_item(q: u32) -> Weight {
+		(434_698_000 as Weight)
+			// Standard Error: 210_000
+			.saturating_add((166_559_000 as Weight).saturating_mul(q as Weight))
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn instrument(c: u32) -> Weight {
+		(29_918_000 as Weight)
+			// Standard Error: 185_000
+			.saturating_add((123_774_000 as Weight).saturating_mul(c as Weight))
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn update_schedule() -> Weight {
+		(29_795_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn instantiate_with_code(c: u32, s: u32) -> Weight {
+		(225_834_000 as Weight)
+			// Standard Error: 144_000
+			.saturating_add((165_632_000 as Weight).saturating_mul(c as Weight))
+			// Standard Error: 9_000
+			.saturating_add((2_563_000 as Weight).saturating_mul(s as Weight))
+			.saturating_add(T::DbWeight::get().reads(6 as Weight))
+			.saturating_add(T::DbWeight::get().writes(5 as Weight))
+	}
+	fn instantiate(c: u32, s: u32) -> Weight {
+		(190_482_000 as Weight)
+			// Standard Error: 12_000
+			.saturating_add((8_724_000 as Weight).saturating_mul(c as Weight))
+			// Standard Error: 1_000
+			.saturating_add((2_512_000 as Weight).saturating_mul(s as Weight))
+			.saturating_add(T::DbWeight::get().reads(6 as Weight))
+			.saturating_add(T::DbWeight::get().writes(4 as Weight))
+	}
+	fn call(c: u32) -> Weight {
+		(195_414_000 as Weight)
+			// Standard Error: 2_000
+			.saturating_add((3_920_000 as Weight).saturating_mul(c as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+			.saturating_add(T::DbWeight::get().writes(2 as Weight))
+	}
+	fn claim_surcharge(c: u32) -> Weight {
+		(336_867_000 as Weight)
+			// Standard Error: 10_000
+			.saturating_add((5_262_000 as Weight).saturating_mul(c as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+			.saturating_add(T::DbWeight::get().writes(4 as Weight))
+	}
+	fn seal_caller(r: u32) -> Weight {
+		(143_935_000 as Weight)
+			// Standard Error: 128_000
+			.saturating_add((266_876_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_address(r: u32) -> Weight {
+		(150_342_000 as Weight)
+			// Standard Error: 127_000
+			.saturating_add((266_051_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_gas_left(r: u32) -> Weight {
+		(144_833_000 as Weight)
+			// Standard Error: 124_000
+			.saturating_add((259_279_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_balance(r: u32) -> Weight {
+		(152_032_000 as Weight)
+			// Standard Error: 218_000
+			.saturating_add((573_038_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_value_transferred(r: u32) -> Weight {
+		(148_831_000 as Weight)
+			// Standard Error: 147_000
+			.saturating_add((260_718_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_minimum_balance(r: u32) -> Weight {
+		(142_925_000 as Weight)
+			// Standard Error: 130_000
+			.saturating_add((260_426_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_tombstone_deposit(r: u32) -> Weight {
+		(143_151_000 as Weight)
+			// Standard Error: 119_000
+			.saturating_add((260_964_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_rent_allowance(r: u32) -> Weight {
+		(155_126_000 as Weight)
+			// Standard Error: 225_000
+			.saturating_add((599_056_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_block_number(r: u32) -> Weight {
+		(144_566_000 as Weight)
+			// Standard Error: 110_000
+			.saturating_add((257_620_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_now(r: u32) -> Weight {
+		(147_274_000 as Weight)
+			// Standard Error: 115_000
+			.saturating_add((258_627_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_rent_params(r: u32) -> Weight {
+		(168_575_000 as Weight)
+			// Standard Error: 394_000
+			.saturating_add((397_754_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_weight_to_fee(r: u32) -> Weight {
+		(148_102_000 as Weight)
+			// Standard Error: 201_000
+			.saturating_add((537_088_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(6 as Weight))
+	}
+	fn seal_gas(r: u32) -> Weight {
+		(125_122_000 as Weight)
+			// Standard Error: 89_000
+			.saturating_add((122_350_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_input(r: u32) -> Weight {
+		(137_334_000 as Weight)
+			// Standard Error: 99_000
+			.saturating_add((7_359_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_input_per_kb(n: u32) -> Weight {
+		(145_094_000 as Weight)
+			// Standard Error: 0
+			.saturating_add((283_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_return(r: u32) -> Weight {
+		(127_544_000 as Weight)
+			// Standard Error: 138_000
+			.saturating_add((4_640_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_return_per_kb(n: u32) -> Weight {
+		(137_517_000 as Weight)
+			// Standard Error: 0
+			.saturating_add((783_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_terminate(r: u32) -> Weight {
+		(138_292_000 as Weight)
+			// Standard Error: 689_000
+			.saturating_add((111_698_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+			.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(r as Weight)))
+			.saturating_add(T::DbWeight::get().writes((5 as Weight).saturating_mul(r as Weight)))
+	}
+	fn seal_terminate_per_code_kb(c: u32) -> Weight {
+		(263_507_000 as Weight)
+			// Standard Error: 12_000
+			.saturating_add((8_409_000 as Weight).saturating_mul(c as Weight))
+			.saturating_add(T::DbWeight::get().reads(7 as Weight))
+			.saturating_add(T::DbWeight::get().writes(5 as Weight))
+	}
+	fn seal_restore_to(r: u32) -> Weight {
+		(232_291_000 as Weight)
+			// Standard Error: 301_000
+			.saturating_add((136_379_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+			.saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(r as Weight)))
+			.saturating_add(T::DbWeight::get().writes((6 as Weight).saturating_mul(r as Weight)))
+	}
+	fn seal_restore_to_per_code_kb_delta(c: u32, t: u32, d: u32) -> Weight {
+		(0 as Weight)
+			// Standard Error: 162_000
+			.saturating_add((8_619_000 as Weight).saturating_mul(c as Weight))
+			// Standard Error: 162_000
+			.saturating_add((4_877_000 as Weight).saturating_mul(t as Weight))
+			// Standard Error: 1_433_000
+			.saturating_add((3_762_810_000 as Weight).saturating_mul(d as Weight))
+			.saturating_add(T::DbWeight::get().reads(8 as Weight))
+			.saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(d as Weight)))
+			.saturating_add(T::DbWeight::get().writes(7 as Weight))
+			.saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(d as Weight)))
+	}
+	fn seal_random(r: u32) -> Weight {
+		(153_634_000 as Weight)
+			// Standard Error: 267_000
+			.saturating_add((650_160_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(6 as Weight))
+	}
+	fn seal_deposit_event(r: u32) -> Weight {
+		(137_080_000 as Weight)
+			// Standard Error: 1_009_000
+			.saturating_add((949_228_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32) -> Weight {
+		(1_259_129_000 as Weight)
+			// Standard Error: 2_542_000
+			.saturating_add((609_859_000 as Weight).saturating_mul(t as Weight))
+			// Standard Error: 501_000
+			.saturating_add((249_496_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+			.saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(t as Weight)))
+			.saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(t as Weight)))
+	}
+	fn seal_set_rent_allowance(r: u32) -> Weight {
+		(170_417_000 as Weight)
+			// Standard Error: 434_000
+			.saturating_add((721_511_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn seal_set_storage(r: u32) -> Weight {
+		(1_870_542_000 as Weight)
+			// Standard Error: 26_871_000
+			.saturating_add((18_312_239_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+			.saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight)))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight)))
+	}
+	fn seal_set_storage_per_kb(n: u32) -> Weight {
+		(1_763_732_000 as Weight)
+			// Standard Error: 258_000
+			.saturating_add((74_848_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(T::DbWeight::get().reads(6 as Weight))
+			.saturating_add(T::DbWeight::get().writes(2 as Weight))
+	}
+	fn seal_clear_storage(r: u32) -> Weight {
+		(0 as Weight)
+			// Standard Error: 2_745_000
+			.saturating_add((2_316_433_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+			.saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight)))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight)))
+	}
+	fn seal_get_storage(r: u32) -> Weight {
+		(87_218_000 as Weight)
+			// Standard Error: 745_000
+			.saturating_add((948_121_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+			.saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight)))
+	}
+	fn seal_get_storage_per_kb(n: u32) -> Weight {
+		(719_050_000 as Weight)
+			// Standard Error: 266_000
+			.saturating_add((154_812_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(T::DbWeight::get().reads(6 as Weight))
+	}
+	fn seal_transfer(r: u32) -> Weight {
+		(19_439_000 as Weight)
+			// Standard Error: 2_468_000
+			.saturating_add((5_674_822_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+			.saturating_add(T::DbWeight::get().reads((100 as Weight).saturating_mul(r as Weight)))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes((100 as Weight).saturating_mul(r as Weight)))
+	}
+	fn seal_call(r: u32) -> Weight {
+		(0 as Weight)
+			// Standard Error: 7_465_000
+			.saturating_add((11_066_530_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(6 as Weight))
+			.saturating_add(T::DbWeight::get().reads((200 as Weight).saturating_mul(r as Weight)))
+	}
+	fn seal_call_per_code_transfer_input_output_kb(c: u32, t: u32, i: u32, o: u32) -> Weight {
+		(9_916_288_000 as Weight)
+			// Standard Error: 552_000
+			.saturating_add((397_842_000 as Weight).saturating_mul(c as Weight))
+			// Standard Error: 229_902_000
+			.saturating_add((5_243_673_000 as Weight).saturating_mul(t as Weight))
+			// Standard Error: 72_000
+			.saturating_add((59_737_000 as Weight).saturating_mul(i as Weight))
+			// Standard Error: 77_000
+			.saturating_add((82_259_000 as Weight).saturating_mul(o as Weight))
+			.saturating_add(T::DbWeight::get().reads(206 as Weight))
+			.saturating_add(T::DbWeight::get().writes((101 as Weight).saturating_mul(t as Weight)))
+	}
+	fn seal_instantiate(r: u32) -> Weight {
+		(0 as Weight)
+			// Standard Error: 32_016_000
+			.saturating_add((22_206_489_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(6 as Weight))
+			.saturating_add(T::DbWeight::get().reads((300 as Weight).saturating_mul(r as Weight)))
+			.saturating_add(T::DbWeight::get().writes(2 as Weight))
+			.saturating_add(T::DbWeight::get().writes((300 as Weight).saturating_mul(r as Weight)))
+	}
+	fn seal_instantiate_per_code_input_output_salt_kb(c: u32, i: u32, o: u32, s: u32) -> Weight {
+		(9_991_947_000 as Weight)
+			// Standard Error: 637_000
+			.saturating_add((881_981_000 as Weight).saturating_mul(c as Weight))
+			// Standard Error: 90_000
+			.saturating_add((63_638_000 as Weight).saturating_mul(i as Weight))
+			// Standard Error: 90_000
+			.saturating_add((87_288_000 as Weight).saturating_mul(o as Weight))
+			// Standard Error: 90_000
+			.saturating_add((311_808_000 as Weight).saturating_mul(s as Weight))
+			.saturating_add(T::DbWeight::get().reads(207 as Weight))
+			.saturating_add(T::DbWeight::get().writes(203 as Weight))
+	}
+	fn seal_hash_sha2_256(r: u32) -> Weight {
+		(132_452_000 as Weight)
+			// Standard Error: 227_000
+			.saturating_add((239_671_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_sha2_256_per_kb(n: u32) -> Weight {
+		(756_802_000 as Weight)
+			// Standard Error: 48_000
+			.saturating_add((429_454_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_keccak_256(r: u32) -> Weight {
+		(139_440_000 as Weight)
+			// Standard Error: 128_000
+			.saturating_add((249_514_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_keccak_256_per_kb(n: u32) -> Weight {
+		(658_595_000 as Weight)
+			// Standard Error: 35_000
+			.saturating_add((343_814_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_blake2_256(r: u32) -> Weight {
+		(138_124_000 as Weight)
+			// Standard Error: 140_000
+			.saturating_add((223_189_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_blake2_256_per_kb(n: u32) -> Weight {
+		(689_667_000 as Weight)
+			// Standard Error: 41_000
+			.saturating_add((160_006_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_blake2_128(r: u32) -> Weight {
+		(140_225_000 as Weight)
+			// Standard Error: 156_000
+			.saturating_add((223_696_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_blake2_128_per_kb(n: u32) -> Weight {
+		(693_756_000 as Weight)
+			// Standard Error: 40_000
+			.saturating_add((159_996_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+	}
+	fn instr_i64const(r: u32) -> Weight {
+		(24_250_000 as Weight)
+			// Standard Error: 14_000
+			.saturating_add((3_134_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64load(r: u32) -> Weight {
+		(26_509_000 as Weight)
+			// Standard Error: 27_000
+			.saturating_add((161_556_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64store(r: u32) -> Weight {
+		(26_499_000 as Weight)
+			// Standard Error: 59_000
+			.saturating_add((233_755_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_select(r: u32) -> Weight {
+		(24_175_000 as Weight)
+			// Standard Error: 16_000
+			.saturating_add((12_450_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_if(r: u32) -> Weight {
+		(24_219_000 as Weight)
+			// Standard Error: 26_000
+			.saturating_add((12_058_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_br(r: u32) -> Weight {
+		(24_146_000 as Weight)
+			// Standard Error: 20_000
+			.saturating_add((6_017_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_br_if(r: u32) -> Weight {
+		(24_229_000 as Weight)
+			// Standard Error: 24_000
+			.saturating_add((13_726_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_br_table(r: u32) -> Weight {
+		(24_219_000 as Weight)
+			// Standard Error: 27_000
+			.saturating_add((15_115_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_br_table_per_entry(e: u32) -> Weight {
+		(34_981_000 as Weight)
+			// Standard Error: 1_000
+			.saturating_add((156_000 as Weight).saturating_mul(e as Weight))
+	}
+	fn instr_call(r: u32) -> Weight {
+		(24_599_000 as Weight)
+			// Standard Error: 102_000
+			.saturating_add((95_771_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_call_indirect(r: u32) -> Weight {
+		(32_584_000 as Weight)
+			// Standard Error: 176_000
+			.saturating_add((193_216_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_call_indirect_per_param(p: u32) -> Weight {
+		(240_739_000 as Weight)
+			// Standard Error: 6_000
+			.saturating_add((3_407_000 as Weight).saturating_mul(p as Weight))
+	}
+	fn instr_local_get(r: u32) -> Weight {
+		(41_963_000 as Weight)
+			// Standard Error: 15_000
+			.saturating_add((3_110_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_local_set(r: u32) -> Weight {
+		(41_956_000 as Weight)
+			// Standard Error: 9_000
+			.saturating_add((3_460_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_local_tee(r: u32) -> Weight {
+		(42_002_000 as Weight)
+			// Standard Error: 20_000
+			.saturating_add((4_591_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_global_get(r: u32) -> Weight {
+		(27_646_000 as Weight)
+			// Standard Error: 23_000
+			.saturating_add((7_821_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_global_set(r: u32) -> Weight {
+		(27_615_000 as Weight)
+			// Standard Error: 27_000
+			.saturating_add((11_807_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_memory_current(r: u32) -> Weight {
+		(27_106_000 as Weight)
+			// Standard Error: 78_000
+			.saturating_add((2_952_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_memory_grow(r: u32) -> Weight {
+		(24_956_000 as Weight)
+			// Standard Error: 3_541_000
+			.saturating_add((2_332_414_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64clz(r: u32) -> Weight {
+		(24_183_000 as Weight)
+			// Standard Error: 18_000
+			.saturating_add((5_166_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64ctz(r: u32) -> Weight {
+		(24_142_000 as Weight)
+			// Standard Error: 17_000
+			.saturating_add((5_146_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64popcnt(r: u32) -> Weight {
+		(24_161_000 as Weight)
+			// Standard Error: 23_000
+			.saturating_add((5_807_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64eqz(r: u32) -> Weight {
+		(24_167_000 as Weight)
+			// Standard Error: 24_000
+			.saturating_add((5_288_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64extendsi32(r: u32) -> Weight {
+		(24_252_000 as Weight)
+			// Standard Error: 9_000
+			.saturating_add((5_091_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64extendui32(r: u32) -> Weight {
+		(24_243_000 as Weight)
+			// Standard Error: 16_000
+			.saturating_add((5_076_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i32wrapi64(r: u32) -> Weight {
+		(24_227_000 as Weight)
+			// Standard Error: 15_000
+			.saturating_add((5_135_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64eq(r: u32) -> Weight {
+		(24_278_000 as Weight)
+			// Standard Error: 15_000
+			.saturating_add((7_124_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64ne(r: u32) -> Weight {
+		(24_254_000 as Weight)
+			// Standard Error: 19_000
+			.saturating_add((7_067_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64lts(r: u32) -> Weight {
+		(24_220_000 as Weight)
+			// Standard Error: 14_000
+			.saturating_add((7_122_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64ltu(r: u32) -> Weight {
+		(24_221_000 as Weight)
+			// Standard Error: 19_000
+			.saturating_add((7_221_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64gts(r: u32) -> Weight {
+		(24_259_000 as Weight)
+			// Standard Error: 13_000
+			.saturating_add((7_135_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64gtu(r: u32) -> Weight {
+		(24_245_000 as Weight)
+			// Standard Error: 10_000
+			.saturating_add((7_193_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64les(r: u32) -> Weight {
+		(24_289_000 as Weight)
+			// Standard Error: 22_000
+			.saturating_add((7_023_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64leu(r: u32) -> Weight {
+		(24_239_000 as Weight)
+			// Standard Error: 21_000
+			.saturating_add((7_065_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64ges(r: u32) -> Weight {
+		(24_256_000 as Weight)
+			// Standard Error: 13_000
+			.saturating_add((7_119_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64geu(r: u32) -> Weight {
+		(24_240_000 as Weight)
+			// Standard Error: 18_000
+			.saturating_add((7_225_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64add(r: u32) -> Weight {
+		(24_266_000 as Weight)
+			// Standard Error: 24_000
+			.saturating_add((6_996_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64sub(r: u32) -> Weight {
+		(24_265_000 as Weight)
+			// Standard Error: 17_000
+			.saturating_add((6_974_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64mul(r: u32) -> Weight {
+		(24_232_000 as Weight)
+			// Standard Error: 15_000
+			.saturating_add((7_103_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64divs(r: u32) -> Weight {
+		(24_245_000 as Weight)
+			// Standard Error: 20_000
+			.saturating_add((12_915_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64divu(r: u32) -> Weight {
+		(24_177_000 as Weight)
+			// Standard Error: 21_000
+			.saturating_add((12_232_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64rems(r: u32) -> Weight {
+		(24_171_000 as Weight)
+			// Standard Error: 15_000
+			.saturating_add((12_939_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64remu(r: u32) -> Weight {
+		(24_788_000 as Weight)
+			// Standard Error: 22_000
+			.saturating_add((11_657_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64and(r: u32) -> Weight {
+		(24_252_000 as Weight)
+			// Standard Error: 19_000
+			.saturating_add((7_003_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64or(r: u32) -> Weight {
+		(24_263_000 as Weight)
+			// Standard Error: 12_000
+			.saturating_add((7_005_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64xor(r: u32) -> Weight {
+		(24_239_000 as Weight)
+			// Standard Error: 17_000
+			.saturating_add((7_020_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64shl(r: u32) -> Weight {
+		(24_212_000 as Weight)
+			// Standard Error: 13_000
+			.saturating_add((7_172_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64shrs(r: u32) -> Weight {
+		(24_220_000 as Weight)
+			// Standard Error: 27_000
+			.saturating_add((7_246_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64shru(r: u32) -> Weight {
+		(24_213_000 as Weight)
+			// Standard Error: 14_000
+			.saturating_add((7_191_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64rotl(r: u32) -> Weight {
+		(24_221_000 as Weight)
+			// Standard Error: 18_000
+			.saturating_add((7_192_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64rotr(r: u32) -> Weight {
+		(24_235_000 as Weight)
+			// Standard Error: 12_000
+			.saturating_add((7_106_000 as Weight).saturating_mul(r as Weight))
+	}
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+	fn on_initialize() -> Weight {
+		(3_850_000 as Weight).saturating_add(RocksDbWeight::get().reads(1 as Weight))
+	}
+	fn on_initialize_per_trie_key(k: u32) -> Weight {
+		(52_925_000 as Weight)
+			// Standard Error: 5_000
+			.saturating_add((2_297_000 as Weight).saturating_mul(k as Weight))
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(k as Weight)))
+	}
+	fn on_initialize_per_queue_item(q: u32) -> Weight {
+		(434_698_000 as Weight)
+			// Standard Error: 210_000
+			.saturating_add((166_559_000 as Weight).saturating_mul(q as Weight))
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn instrument(c: u32) -> Weight {
+		(29_918_000 as Weight)
+			// Standard Error: 185_000
+			.saturating_add((123_774_000 as Weight).saturating_mul(c as Weight))
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn update_schedule() -> Weight {
+		(29_795_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn instantiate_with_code(c: u32, s: u32) -> Weight {
+		(225_834_000 as Weight)
+			// Standard Error: 144_000
+			.saturating_add((165_632_000 as Weight).saturating_mul(c as Weight))
+			// Standard Error: 9_000
+			.saturating_add((2_563_000 as Weight).saturating_mul(s as Weight))
+			.saturating_add(RocksDbWeight::get().reads(6 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(5 as Weight))
+	}
+	fn instantiate(c: u32, s: u32) -> Weight {
+		(190_482_000 as Weight)
+			// Standard Error: 12_000
+			.saturating_add((8_724_000 as Weight).saturating_mul(c as Weight))
+			// Standard Error: 1_000
+			.saturating_add((2_512_000 as Weight).saturating_mul(s as Weight))
+			.saturating_add(RocksDbWeight::get().reads(6 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
+	}
+	fn call(c: u32) -> Weight {
+		(195_414_000 as Weight)
+			// Standard Error: 2_000
+			.saturating_add((3_920_000 as Weight).saturating_mul(c as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(2 as Weight))
+	}
+	fn claim_surcharge(c: u32) -> Weight {
+		(336_867_000 as Weight)
+			// Standard Error: 10_000
+			.saturating_add((5_262_000 as Weight).saturating_mul(c as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
+	}
+	fn seal_caller(r: u32) -> Weight {
+		(143_935_000 as Weight)
+			// Standard Error: 128_000
+			.saturating_add((266_876_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_address(r: u32) -> Weight {
+		(150_342_000 as Weight)
+			// Standard Error: 127_000
+			.saturating_add((266_051_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_gas_left(r: u32) -> Weight {
+		(144_833_000 as Weight)
+			// Standard Error: 124_000
+			.saturating_add((259_279_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_balance(r: u32) -> Weight {
+		(152_032_000 as Weight)
+			// Standard Error: 218_000
+			.saturating_add((573_038_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_value_transferred(r: u32) -> Weight {
+		(148_831_000 as Weight)
+			// Standard Error: 147_000
+			.saturating_add((260_718_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_minimum_balance(r: u32) -> Weight {
+		(142_925_000 as Weight)
+			// Standard Error: 130_000
+			.saturating_add((260_426_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_tombstone_deposit(r: u32) -> Weight {
+		(143_151_000 as Weight)
+			// Standard Error: 119_000
+			.saturating_add((260_964_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_rent_allowance(r: u32) -> Weight {
+		(155_126_000 as Weight)
+			// Standard Error: 225_000
+			.saturating_add((599_056_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_block_number(r: u32) -> Weight {
+		(144_566_000 as Weight)
+			// Standard Error: 110_000
+			.saturating_add((257_620_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_now(r: u32) -> Weight {
+		(147_274_000 as Weight)
+			// Standard Error: 115_000
+			.saturating_add((258_627_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_rent_params(r: u32) -> Weight {
+		(168_575_000 as Weight)
+			// Standard Error: 394_000
+			.saturating_add((397_754_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_weight_to_fee(r: u32) -> Weight {
+		(148_102_000 as Weight)
+			// Standard Error: 201_000
+			.saturating_add((537_088_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(6 as Weight))
+	}
+	fn seal_gas(r: u32) -> Weight {
+		(125_122_000 as Weight)
+			// Standard Error: 89_000
+			.saturating_add((122_350_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_input(r: u32) -> Weight {
+		(137_334_000 as Weight)
+			// Standard Error: 99_000
+			.saturating_add((7_359_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_input_per_kb(n: u32) -> Weight {
+		(145_094_000 as Weight)
+			// Standard Error: 0
+			.saturating_add((283_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_return(r: u32) -> Weight {
+		(127_544_000 as Weight)
+			// Standard Error: 138_000
+			.saturating_add((4_640_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_return_per_kb(n: u32) -> Weight {
+		(137_517_000 as Weight)
+			// Standard Error: 0
+			.saturating_add((783_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_terminate(r: u32) -> Weight {
+		(138_292_000 as Weight)
+			// Standard Error: 689_000
+			.saturating_add((111_698_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(r as Weight)))
+			.saturating_add(RocksDbWeight::get().writes((5 as Weight).saturating_mul(r as Weight)))
+	}
+	fn seal_terminate_per_code_kb(c: u32) -> Weight {
+		(263_507_000 as Weight)
+			// Standard Error: 12_000
+			.saturating_add((8_409_000 as Weight).saturating_mul(c as Weight))
+			.saturating_add(RocksDbWeight::get().reads(7 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(5 as Weight))
+	}
+	fn seal_restore_to(r: u32) -> Weight {
+		(232_291_000 as Weight)
+			// Standard Error: 301_000
+			.saturating_add((136_379_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(r as Weight)))
+			.saturating_add(RocksDbWeight::get().writes((6 as Weight).saturating_mul(r as Weight)))
+	}
+	fn seal_restore_to_per_code_kb_delta(c: u32, t: u32, d: u32) -> Weight {
+		(0 as Weight)
+			// Standard Error: 162_000
+			.saturating_add((8_619_000 as Weight).saturating_mul(c as Weight))
+			// Standard Error: 162_000
+			.saturating_add((4_877_000 as Weight).saturating_mul(t as Weight))
+			// Standard Error: 1_433_000
+			.saturating_add((3_762_810_000 as Weight).saturating_mul(d as Weight))
+			.saturating_add(RocksDbWeight::get().reads(8 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(d as Weight)))
+			.saturating_add(RocksDbWeight::get().writes(7 as Weight))
+			.saturating_add(
+				RocksDbWeight::get().writes((100 as Weight).saturating_mul(d as Weight)),
+			)
+	}
+	fn seal_random(r: u32) -> Weight {
+		(153_634_000 as Weight)
+			// Standard Error: 267_000
+			.saturating_add((650_160_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(6 as Weight))
+	}
+	fn seal_deposit_event(r: u32) -> Weight {
+		(137_080_000 as Weight)
+			// Standard Error: 1_009_000
+			.saturating_add((949_228_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_deposit_event_per_topic_and_kb(t: u32, n: u32) -> Weight {
+		(1_259_129_000 as Weight)
+			// Standard Error: 2_542_000
+			.saturating_add((609_859_000 as Weight).saturating_mul(t as Weight))
+			// Standard Error: 501_000
+			.saturating_add((249_496_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(t as Weight)))
+			.saturating_add(
+				RocksDbWeight::get().writes((100 as Weight).saturating_mul(t as Weight)),
+			)
+	}
+	fn seal_set_rent_allowance(r: u32) -> Weight {
+		(170_417_000 as Weight)
+			// Standard Error: 434_000
+			.saturating_add((721_511_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn seal_set_storage(r: u32) -> Weight {
+		(1_870_542_000 as Weight)
+			// Standard Error: 26_871_000
+			.saturating_add((18_312_239_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight)))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+			.saturating_add(
+				RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight)),
+			)
+	}
+	fn seal_set_storage_per_kb(n: u32) -> Weight {
+		(1_763_732_000 as Weight)
+			// Standard Error: 258_000
+			.saturating_add((74_848_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(RocksDbWeight::get().reads(6 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(2 as Weight))
+	}
+	fn seal_clear_storage(r: u32) -> Weight {
+		(0 as Weight)
+			// Standard Error: 2_745_000
+			.saturating_add((2_316_433_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight)))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+			.saturating_add(
+				RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight)),
+			)
+	}
+	fn seal_get_storage(r: u32) -> Weight {
+		(87_218_000 as Weight)
+			// Standard Error: 745_000
+			.saturating_add((948_121_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight)))
+	}
+	fn seal_get_storage_per_kb(n: u32) -> Weight {
+		(719_050_000 as Weight)
+			// Standard Error: 266_000
+			.saturating_add((154_812_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(RocksDbWeight::get().reads(6 as Weight))
+	}
+	fn seal_transfer(r: u32) -> Weight {
+		(19_439_000 as Weight)
+			// Standard Error: 2_468_000
+			.saturating_add((5_674_822_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((100 as Weight).saturating_mul(r as Weight)))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+			.saturating_add(
+				RocksDbWeight::get().writes((100 as Weight).saturating_mul(r as Weight)),
+			)
+	}
+	fn seal_call(r: u32) -> Weight {
+		(0 as Weight)
+			// Standard Error: 7_465_000
+			.saturating_add((11_066_530_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(6 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((200 as Weight).saturating_mul(r as Weight)))
+	}
+	fn seal_call_per_code_transfer_input_output_kb(c: u32, t: u32, i: u32, o: u32) -> Weight {
+		(9_916_288_000 as Weight)
+			// Standard Error: 552_000
+			.saturating_add((397_842_000 as Weight).saturating_mul(c as Weight))
+			// Standard Error: 229_902_000
+			.saturating_add((5_243_673_000 as Weight).saturating_mul(t as Weight))
+			// Standard Error: 72_000
+			.saturating_add((59_737_000 as Weight).saturating_mul(i as Weight))
+			// Standard Error: 77_000
+			.saturating_add((82_259_000 as Weight).saturating_mul(o as Weight))
+			.saturating_add(RocksDbWeight::get().reads(206 as Weight))
+			.saturating_add(
+				RocksDbWeight::get().writes((101 as Weight).saturating_mul(t as Weight)),
+			)
+	}
+	fn seal_instantiate(r: u32) -> Weight {
+		(0 as Weight)
+			// Standard Error: 32_016_000
+			.saturating_add((22_206_489_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(6 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((300 as Weight).saturating_mul(r as Weight)))
+			.saturating_add(RocksDbWeight::get().writes(2 as Weight))
+			.saturating_add(
+				RocksDbWeight::get().writes((300 as Weight).saturating_mul(r as Weight)),
+			)
+	}
+	fn seal_instantiate_per_code_input_output_salt_kb(c: u32, i: u32, o: u32, s: u32) -> Weight {
+		(9_991_947_000 as Weight)
+			// Standard Error: 637_000
+			.saturating_add((881_981_000 as Weight).saturating_mul(c as Weight))
+			// Standard Error: 90_000
+			.saturating_add((63_638_000 as Weight).saturating_mul(i as Weight))
+			// Standard Error: 90_000
+			.saturating_add((87_288_000 as Weight).saturating_mul(o as Weight))
+			// Standard Error: 90_000
+			.saturating_add((311_808_000 as Weight).saturating_mul(s as Weight))
+			.saturating_add(RocksDbWeight::get().reads(207 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(203 as Weight))
+	}
+	fn seal_hash_sha2_256(r: u32) -> Weight {
+		(132_452_000 as Weight)
+			// Standard Error: 227_000
+			.saturating_add((239_671_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_sha2_256_per_kb(n: u32) -> Weight {
+		(756_802_000 as Weight)
+			// Standard Error: 48_000
+			.saturating_add((429_454_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_keccak_256(r: u32) -> Weight {
+		(139_440_000 as Weight)
+			// Standard Error: 128_000
+			.saturating_add((249_514_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_keccak_256_per_kb(n: u32) -> Weight {
+		(658_595_000 as Weight)
+			// Standard Error: 35_000
+			.saturating_add((343_814_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_blake2_256(r: u32) -> Weight {
+		(138_124_000 as Weight)
+			// Standard Error: 140_000
+			.saturating_add((223_189_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_blake2_256_per_kb(n: u32) -> Weight {
+		(689_667_000 as Weight)
+			// Standard Error: 41_000
+			.saturating_add((160_006_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_blake2_128(r: u32) -> Weight {
+		(140_225_000 as Weight)
+			// Standard Error: 156_000
+			.saturating_add((223_696_000 as Weight).saturating_mul(r as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn seal_hash_blake2_128_per_kb(n: u32) -> Weight {
+		(693_756_000 as Weight)
+			// Standard Error: 40_000
+			.saturating_add((159_996_000 as Weight).saturating_mul(n as Weight))
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+	}
+	fn instr_i64const(r: u32) -> Weight {
+		(24_250_000 as Weight)
+			// Standard Error: 14_000
+			.saturating_add((3_134_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64load(r: u32) -> Weight {
+		(26_509_000 as Weight)
+			// Standard Error: 27_000
+			.saturating_add((161_556_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64store(r: u32) -> Weight {
+		(26_499_000 as Weight)
+			// Standard Error: 59_000
+			.saturating_add((233_755_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_select(r: u32) -> Weight {
+		(24_175_000 as Weight)
+			// Standard Error: 16_000
+			.saturating_add((12_450_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_if(r: u32) -> Weight {
+		(24_219_000 as Weight)
+			// Standard Error: 26_000
+			.saturating_add((12_058_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_br(r: u32) -> Weight {
+		(24_146_000 as Weight)
+			// Standard Error: 20_000
+			.saturating_add((6_017_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_br_if(r: u32) -> Weight {
+		(24_229_000 as Weight)
+			// Standard Error: 24_000
+			.saturating_add((13_726_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_br_table(r: u32) -> Weight {
+		(24_219_000 as Weight)
+			// Standard Error: 27_000
+			.saturating_add((15_115_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_br_table_per_entry(e: u32) -> Weight {
+		(34_981_000 as Weight)
+			// Standard Error: 1_000
+			.saturating_add((156_000 as Weight).saturating_mul(e as Weight))
+	}
+	fn instr_call(r: u32) -> Weight {
+		(24_599_000 as Weight)
+			// Standard Error: 102_000
+			.saturating_add((95_771_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_call_indirect(r: u32) -> Weight {
+		(32_584_000 as Weight)
+			// Standard Error: 176_000
+			.saturating_add((193_216_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_call_indirect_per_param(p: u32) -> Weight {
+		(240_739_000 as Weight)
+			// Standard Error: 6_000
+			.saturating_add((3_407_000 as Weight).saturating_mul(p as Weight))
+	}
+	fn instr_local_get(r: u32) -> Weight {
+		(41_963_000 as Weight)
+			// Standard Error: 15_000
+			.saturating_add((3_110_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_local_set(r: u32) -> Weight {
+		(41_956_000 as Weight)
+			// Standard Error: 9_000
+			.saturating_add((3_460_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_local_tee(r: u32) -> Weight {
+		(42_002_000 as Weight)
+			// Standard Error: 20_000
+			.saturating_add((4_591_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_global_get(r: u32) -> Weight {
+		(27_646_000 as Weight)
+			// Standard Error: 23_000
+			.saturating_add((7_821_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_global_set(r: u32) -> Weight {
+		(27_615_000 as Weight)
+			// Standard Error: 27_000
+			.saturating_add((11_807_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_memory_current(r: u32) -> Weight {
+		(27_106_000 as Weight)
+			// Standard Error: 78_000
+			.saturating_add((2_952_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_memory_grow(r: u32) -> Weight {
+		(24_956_000 as Weight)
+			// Standard Error: 3_541_000
+			.saturating_add((2_332_414_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64clz(r: u32) -> Weight {
+		(24_183_000 as Weight)
+			// Standard Error: 18_000
+			.saturating_add((5_166_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64ctz(r: u32) -> Weight {
+		(24_142_000 as Weight)
+			// Standard Error: 17_000
+			.saturating_add((5_146_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64popcnt(r: u32) -> Weight {
+		(24_161_000 as Weight)
+			// Standard Error: 23_000
+			.saturating_add((5_807_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64eqz(r: u32) -> Weight {
+		(24_167_000 as Weight)
+			// Standard Error: 24_000
+			.saturating_add((5_288_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64extendsi32(r: u32) -> Weight {
+		(24_252_000 as Weight)
+			// Standard Error: 9_000
+			.saturating_add((5_091_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64extendui32(r: u32) -> Weight {
+		(24_243_000 as Weight)
+			// Standard Error: 16_000
+			.saturating_add((5_076_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i32wrapi64(r: u32) -> Weight {
+		(24_227_000 as Weight)
+			// Standard Error: 15_000
+			.saturating_add((5_135_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64eq(r: u32) -> Weight {
+		(24_278_000 as Weight)
+			// Standard Error: 15_000
+			.saturating_add((7_124_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64ne(r: u32) -> Weight {
+		(24_254_000 as Weight)
+			// Standard Error: 19_000
+			.saturating_add((7_067_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64lts(r: u32) -> Weight {
+		(24_220_000 as Weight)
+			// Standard Error: 14_000
+			.saturating_add((7_122_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64ltu(r: u32) -> Weight {
+		(24_221_000 as Weight)
+			// Standard Error: 19_000
+			.saturating_add((7_221_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64gts(r: u32) -> Weight {
+		(24_259_000 as Weight)
+			// Standard Error: 13_000
+			.saturating_add((7_135_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64gtu(r: u32) -> Weight {
+		(24_245_000 as Weight)
+			// Standard Error: 10_000
+			.saturating_add((7_193_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64les(r: u32) -> Weight {
+		(24_289_000 as Weight)
+			// Standard Error: 22_000
+			.saturating_add((7_023_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64leu(r: u32) -> Weight {
+		(24_239_000 as Weight)
+			// Standard Error: 21_000
+			.saturating_add((7_065_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64ges(r: u32) -> Weight {
+		(24_256_000 as Weight)
+			// Standard Error: 13_000
+			.saturating_add((7_119_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64geu(r: u32) -> Weight {
+		(24_240_000 as Weight)
+			// Standard Error: 18_000
+			.saturating_add((7_225_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64add(r: u32) -> Weight {
+		(24_266_000 as Weight)
+			// Standard Error: 24_000
+			.saturating_add((6_996_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64sub(r: u32) -> Weight {
+		(24_265_000 as Weight)
+			// Standard Error: 17_000
+			.saturating_add((6_974_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64mul(r: u32) -> Weight {
+		(24_232_000 as Weight)
+			// Standard Error: 15_000
+			.saturating_add((7_103_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64divs(r: u32) -> Weight {
+		(24_245_000 as Weight)
+			// Standard Error: 20_000
+			.saturating_add((12_915_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64divu(r: u32) -> Weight {
+		(24_177_000 as Weight)
+			// Standard Error: 21_000
+			.saturating_add((12_232_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64rems(r: u32) -> Weight {
+		(24_171_000 as Weight)
+			// Standard Error: 15_000
+			.saturating_add((12_939_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64remu(r: u32) -> Weight {
+		(24_788_000 as Weight)
+			// Standard Error: 22_000
+			.saturating_add((11_657_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64and(r: u32) -> Weight {
+		(24_252_000 as Weight)
+			// Standard Error: 19_000
+			.saturating_add((7_003_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64or(r: u32) -> Weight {
+		(24_263_000 as Weight)
+			// Standard Error: 12_000
+			.saturating_add((7_005_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64xor(r: u32) -> Weight {
+		(24_239_000 as Weight)
+			// Standard Error: 17_000
+			.saturating_add((7_020_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64shl(r: u32) -> Weight {
+		(24_212_000 as Weight)
+			// Standard Error: 13_000
+			.saturating_add((7_172_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64shrs(r: u32) -> Weight {
+		(24_220_000 as Weight)
+			// Standard Error: 27_000
+			.saturating_add((7_246_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64shru(r: u32) -> Weight {
+		(24_213_000 as Weight)
+			// Standard Error: 14_000
+			.saturating_add((7_191_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64rotl(r: u32) -> Weight {
+		(24_221_000 as Weight)
+			// Standard Error: 18_000
+			.saturating_add((7_192_000 as Weight).saturating_mul(r as Weight))
+	}
+	fn instr_i64rotr(r: u32) -> Weight {
+		(24_235_000 as Weight)
+			// Standard Error: 12_000
+			.saturating_add((7_106_000 as Weight).saturating_mul(r as Weight))
+	}
+}
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -175,7 +175,7 @@
 		BadCreateRefungibleCall,
 		/// Gas limit exceeded
 		OutOfGas,
-		/// Metadata update denied by collection settings 
+		/// Metadata update denied by collection settings
 		MetadataUpdateDenied,
 		/// Metadata update flag become unmutable with None option
 		MetadataFlagFrozen,
@@ -951,7 +951,7 @@
 				Error::<T>::MetadataFlagFrozen
 			);
 			Self::check_owner_permissions(&target_collection, &sender)?;
-			
+
 			target_collection.meta_update_permission = value;
 			Self::save_collection(target_collection);
 
@@ -1531,27 +1531,27 @@
 		Ok(())
 	}
 
-	pub fn meta_update_check(		
+	pub fn meta_update_check(
 		sender: &T::CrossAccountId,
 		collection: &CollectionHandle<T>,
-		item_id: TokenId) -> DispatchResult {
-
+		item_id: TokenId,
+	) -> DispatchResult {
 		match collection.meta_update_permission {
 			MetaUpdatePermission::ItemOwner => {
 				ensure!(
-					Self::is_item_owner(sender, collection, item_id), 
+					Self::is_item_owner(sender, collection, item_id),
 					Error::<T>::NoPermission
 				);
-			},
+			}
 			MetaUpdatePermission::Admin => {
 				ensure!(
-					Self::is_owner_or_admin_permissions(collection, sender), 
+					Self::is_owner_or_admin_permissions(collection, sender),
 					Error::<T>::NoPermission
 				);
-			},
+			}
 			MetaUpdatePermission::None => {
 				fail!(Error::<T>::MetadataUpdateDenied);
-			},
+			}
 		}
 
 		Ok(())
modifiedpallets/nft/src/tests.rsdiffbeforeafterboth
--- a/pallets/nft/src/tests.rs
+++ b/pallets/nft/src/tests.rs
@@ -2364,7 +2364,11 @@
 		let data = default_nft_data();
 		create_test_item(1, &data.into());
 
-		TemplateModule::set_meta_update_permission_flag(origin1.clone(), collection_id, MetaUpdatePermission::ItemOwner);
+		TemplateModule::set_meta_update_permission_flag(
+			origin1.clone(),
+			collection_id,
+			MetaUpdatePermission::ItemOwner,
+		);
 
 		let variable_data = b"test set_variable_meta_data method.".to_vec();
 		assert_ok!(TemplateModule::set_variable_meta_data(
@@ -2407,15 +2411,21 @@
 		let data = default_nft_data();
 		create_test_item(1, &data.into());
 
-		TemplateModule::set_meta_update_permission_flag(origin2.clone(), collection_id, MetaUpdatePermission::ItemOwner);
+		TemplateModule::set_meta_update_permission_flag(
+			origin2.clone(),
+			collection_id,
+			MetaUpdatePermission::ItemOwner,
+		);
 
 		let variable_data = b"test set_variable_meta_data method.".to_vec();
-		assert_noop!(TemplateModule::set_variable_meta_data(
-			origin2,
-			collection_id,
-			1,
-			variable_data.clone()),
-		Error::<Test>::NoPermission
+		assert_noop!(
+			TemplateModule::set_variable_meta_data(
+				origin2,
+				collection_id,
+				1,
+				variable_data.clone()
+			),
+			Error::<Test>::NoPermission
 		);
 	});
 }
@@ -2450,7 +2460,11 @@
 		let data = default_nft_data();
 		create_test_item(1, &data.into());
 
-		TemplateModule::set_meta_update_permission_flag(origin2.clone(), collection_id, MetaUpdatePermission::Admin);
+		TemplateModule::set_meta_update_permission_flag(
+			origin2.clone(),
+			collection_id,
+			MetaUpdatePermission::Admin,
+		);
 
 		let variable_data = b"test set_variable_meta_data method.".to_vec();
 		assert_ok!(TemplateModule::set_variable_meta_data(
@@ -2493,15 +2507,21 @@
 		let data = default_nft_data();
 		create_test_item(1, &data.into());
 
-		TemplateModule::set_meta_update_permission_flag(origin2.clone(), collection_id, MetaUpdatePermission::Admin);
+		TemplateModule::set_meta_update_permission_flag(
+			origin2.clone(),
+			collection_id,
+			MetaUpdatePermission::Admin,
+		);
 
 		let variable_data = b"test set_variable_meta_data method.".to_vec();
-		assert_noop!(TemplateModule::set_variable_meta_data(
-			origin1,
-			collection_id,
-			1,
-			variable_data.clone()),
-		Error::<Test>::NoPermission
+		assert_noop!(
+			TemplateModule::set_variable_meta_data(
+				origin1,
+				collection_id,
+				1,
+				variable_data.clone()
+			),
+			Error::<Test>::NoPermission
 		);
 	});
 }
@@ -2515,12 +2535,18 @@
 
 		let origin2 = Origin::signed(2);
 
-		TemplateModule::set_meta_update_permission_flag(origin2.clone(), collection_id, MetaUpdatePermission::None);
-		assert_noop!(TemplateModule::set_meta_update_permission_flag(
+		TemplateModule::set_meta_update_permission_flag(
 			origin2.clone(),
 			collection_id,
-			MetaUpdatePermission::Admin),
-		Error::<Test>::MetadataFlagFrozen
+			MetaUpdatePermission::None,
+		);
+		assert_noop!(
+			TemplateModule::set_meta_update_permission_flag(
+				origin2.clone(),
+				collection_id,
+				MetaUpdatePermission::Admin
+			),
+			Error::<Test>::MetadataFlagFrozen
 		);
 	});
 }
@@ -2536,15 +2562,21 @@
 		let data = default_nft_data();
 		create_test_item(1, &data.into());
 
-		TemplateModule::set_meta_update_permission_flag(origin1.clone(), collection_id, MetaUpdatePermission::None);
+		TemplateModule::set_meta_update_permission_flag(
+			origin1.clone(),
+			collection_id,
+			MetaUpdatePermission::None,
+		);
 
 		let variable_data = b"test set_variable_meta_data method.".to_vec();
-		assert_noop!(TemplateModule::set_variable_meta_data(
-			origin1.clone(),
-			collection_id,
-			1,
-			variable_data.clone()),
-		Error::<Test>::MetadataUpdateDenied
+		assert_noop!(
+			TemplateModule::set_variable_meta_data(
+				origin1.clone(),
+				collection_id,
+				1,
+				variable_data.clone()
+			),
+			Error::<Test>::MetadataUpdateDenied
 		);
 	});
-}
\ No newline at end of file
+}
modifiedprimitives/nft/src/lib.rsdiffbeforeafterboth
--- a/primitives/nft/src/lib.rs
+++ b/primitives/nft/src/lib.rs
@@ -242,7 +242,7 @@
 
 #[derive(Encode, Decode, Debug, Clone, PartialEq)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-pub enum MetaUpdatePermission  {
+pub enum MetaUpdatePermission {
 	ItemOwner,
 	Admin,
 	None,
modifiedtests/src/change-collection-owner.test.tsdiffbeforeafterboth
--- a/tests/src/change-collection-owner.test.ts
+++ b/tests/src/change-collection-owner.test.ts
@@ -7,7 +7,7 @@
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from './substrate/privateKey';
 import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';
-import { createCollectionExpectSuccess, normalizeAccountId } from './util/helpers';
+import { createCollectionExpectSuccess } from './util/helpers';
 
 chai.use(chaiAsPromised);
 const expect = chai.expect;
modifiedtests/src/metadataUpdate.test.tsdiffbeforeafterboth
--- a/tests/src/metadataUpdate.test.ts
+++ b/tests/src/metadataUpdate.test.ts
@@ -17,7 +17,7 @@
   addToWhiteListExpectSuccess,
   addCollectionAdminExpectSuccess,
   setVariableMetaDataExpectFailure,
-  setMetadataUpdatePermissionFlagExpectFailure
+  setMetadataUpdatePermissionFlagExpectFailure,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -26,14 +26,13 @@
   it('Set variable metadata with ItemOwner permission flag', async () => {
     await usingApi(async () => {
       const Alice = privateKey('//Alice');
-      const Bob = privateKey('//Bob');
 
       const data = [1, 2, 254, 255];
 
       // nft
       const nftCollectionId = await createCollectionExpectSuccess();
       const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
-      await setMetadataUpdatePermissionFlagExpectSuccess(Alice, nftCollectionId, "ItemOwner");
+      await setMetadataUpdatePermissionFlagExpectSuccess(Alice, nftCollectionId, 'ItemOwner');
 
       await setVariableMetaDataExpectSuccess(Alice, nftCollectionId, newNftTokenId, data);
     });
@@ -41,71 +40,67 @@
 
   it('User can\'n set variable metadata with ItemOwner permission flag', async () => {
     await usingApi(async () => {
-        const Alice = privateKey('//Alice');
-        const Bob = privateKey('//Bob');
+      const Alice = privateKey('//Alice');
+      const Bob = privateKey('//Bob');
   
-        const data = [1, 2, 254, 255];
+      const data = [1, 2, 254, 255];
   
-        // nft
-        const nftCollectionId = await createCollectionExpectSuccess();
-        const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
-        await setMetadataUpdatePermissionFlagExpectSuccess(Alice, nftCollectionId, "ItemOwner");
+      // nft
+      const nftCollectionId = await createCollectionExpectSuccess();
+      const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
+      await setMetadataUpdatePermissionFlagExpectSuccess(Alice, nftCollectionId, 'ItemOwner');
 
-        await setMintPermissionExpectSuccess(Alice, nftCollectionId, true);
-        await addToWhiteListExpectSuccess(Alice, nftCollectionId, Bob.address);
-        await addCollectionAdminExpectSuccess(Alice, nftCollectionId, Bob);
+      await setMintPermissionExpectSuccess(Alice, nftCollectionId, true);
+      await addToWhiteListExpectSuccess(Alice, nftCollectionId, Bob.address);
+      await addCollectionAdminExpectSuccess(Alice, nftCollectionId, Bob);
   
-        await setVariableMetaDataExpectFailure(Bob, nftCollectionId, newNftTokenId, data);
+      await setVariableMetaDataExpectFailure(Bob, nftCollectionId, newNftTokenId, data);
     });
   });
 
   it('Admin can set variable metadata with Admin permission flag', async () => {
     await usingApi(async () => {
-        const Alice = privateKey('//Alice');
-        const Bob = privateKey('//Bob');
+      const Alice = privateKey('//Alice');
+      const Bob = privateKey('//Bob');
   
-        const data = [1, 2, 254, 255];
+      const data = [1, 2, 254, 255];
   
-        // nft
-        const nftCollectionId = await createCollectionExpectSuccess();
-        const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
-        await setMetadataUpdatePermissionFlagExpectSuccess(Alice, nftCollectionId, "Admin");
+      // nft
+      const nftCollectionId = await createCollectionExpectSuccess();
+      const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
+      await setMetadataUpdatePermissionFlagExpectSuccess(Alice, nftCollectionId, 'Admin');
 
-        await setMintPermissionExpectSuccess(Alice, nftCollectionId, true);
-        await addToWhiteListExpectSuccess(Alice, nftCollectionId, Bob.address);
-        await addCollectionAdminExpectSuccess(Alice, nftCollectionId, Bob);
+      await setMintPermissionExpectSuccess(Alice, nftCollectionId, true);
+      await addToWhiteListExpectSuccess(Alice, nftCollectionId, Bob.address);
+      await addCollectionAdminExpectSuccess(Alice, nftCollectionId, Bob);
   
-        await setVariableMetaDataExpectSuccess(Bob, nftCollectionId, newNftTokenId, data);
+      await setVariableMetaDataExpectSuccess(Bob, nftCollectionId, newNftTokenId, data);
     });
   });
 
   it('Nobody can set variable metadata with None flag', async () => {
     await usingApi(async () => {
-        const Alice = privateKey('//Alice');
-        const Bob = privateKey('//Bob');
+      const Alice = privateKey('//Alice');
   
-        const data = [1, 2, 254, 255];
+      const data = [1, 2, 254, 255];
   
-        // nft
-        const nftCollectionId = await createCollectionExpectSuccess();
-        const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
-        await setMetadataUpdatePermissionFlagExpectSuccess(Alice, nftCollectionId, "None");
+      // nft
+      const nftCollectionId = await createCollectionExpectSuccess();
+      const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
+      await setMetadataUpdatePermissionFlagExpectSuccess(Alice, nftCollectionId, 'None');
   
-        await setVariableMetaDataExpectFailure(Alice, nftCollectionId, newNftTokenId, data);
+      await setVariableMetaDataExpectFailure(Alice, nftCollectionId, newNftTokenId, data);
     });
   });
 
   it('Nobody can set variable metadata flag after freeze', async () => {
     await usingApi(async () => {
-        const Alice = privateKey('//Alice');
-        const Bob = privateKey('//Bob');
-  
-        const data = [1, 2, 254, 255];
+      const Alice = privateKey('//Alice');
   
-        // nft
-        const nftCollectionId = await createCollectionExpectSuccess();
-        await setMetadataUpdatePermissionFlagExpectSuccess(Alice, nftCollectionId, "None");
-        await setMetadataUpdatePermissionFlagExpectFailure(Alice, nftCollectionId, "Admin");
+      // nft
+      const nftCollectionId = await createCollectionExpectSuccess();
+      await setMetadataUpdatePermissionFlagExpectSuccess(Alice, nftCollectionId, 'None');
+      await setMetadataUpdatePermissionFlagExpectFailure(Alice, nftCollectionId, 'Admin');
         
     });
   });
modifiedtests/src/pallet-presence.test.tsdiffbeforeafterboth
--- a/tests/src/pallet-presence.test.ts
+++ b/tests/src/pallet-presence.test.ts
@@ -32,14 +32,14 @@
   'nft',
   'scheduler',
   'nftpayment',
-  'charging'
+  'charging',
 ];
 
 // Pallets that depend on consensus and governance configuration
 const consensusPallets = [
   'sudo',
   'aura',
-  'auraext'
+  'auraext',
 ];
 
 describe('Pallet presence', () => {
modifiedtests/src/setConstOnChainSchema.test.tsdiffbeforeafterboth
--- a/tests/src/setConstOnChainSchema.test.ts
+++ b/tests/src/setConstOnChainSchema.test.ts
@@ -11,7 +11,6 @@
 import {
   createCollectionExpectSuccess,
   destroyCollectionExpectSuccess,
-  normalizeAccountId,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
modifiedtests/src/setVariableOnChainSchema.test.tsdiffbeforeafterboth
--- a/tests/src/setVariableOnChainSchema.test.ts
+++ b/tests/src/setVariableOnChainSchema.test.ts
@@ -11,7 +11,6 @@
 import {
   createCollectionExpectSuccess,
   destroyCollectionExpectSuccess,
-  normalizeAccountId,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
modifiedtests/src/substrate/substrate-api.tsdiffbeforeafterboth
--- a/tests/src/substrate/substrate-api.ts
+++ b/tests/src/substrate/substrate-api.ts
@@ -48,12 +48,12 @@
   console.warn = outFn;
 
   try {
-   await promisifySubstrate(api, async () => {
+    await promisifySubstrate(api, async () => {
       if (api) {
         await api.isReadyOrError;
         result = await action(api);
       }
-   })();
+    })();
   } finally {
     await api.disconnect();
     console.error = consoleErr;
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -565,7 +565,7 @@
   });
 }
 
-export async function toggleContractWhitelistExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, value: boolean = true) {
+export async function toggleContractWhitelistExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, value = true) {
   await usingApi(async (api) => {
     const tx = api.tx.nft.toggleContractWhiteList(contractAddress, value);
     const events = await submitTransactionAsync(sender, tx);
@@ -771,7 +771,7 @@
   recipient: IKeyringPair,
   value: number | bigint = 1,
   blockTimeMs: number,
-  blockSchedule: number
+  blockSchedule: number,
 ) {
   await usingApi(async (api: ApiPromise) => {
     const blockNumber: number | undefined = await getBlockNumber(api);