Repository: paritytech/ink
Pull request #923 (2021-09-16 22:17:17)

Changed the field `name` to `label`
Updated the code generation of ABI. Instead of "name" in messages, constructors, arguments, events we are using "label".
Changed the behavior of "label" for messages and constructors, now it is a string instead of an array. 
For trait's messages, we will use the "TRAIT_IDENT::MESSAGE_IDENT" format of representation.

This PR is related to https://github.com/paritytech/ink/issues/900.

xgreenx: @cmichi What do you think about updating `displayName` to be a string instead of an array too? 
cmichi: Hey nice, that you created a PR for this!

> @cmichi What do you think about updating `displayName` to be a string instead of an array too?

:-) I actually had intended to create a ticket for this today! I agree that it's a good idea, but let's keep this to a separate issue. I'll create one where we track this.
Robbepop: @xgreenx please rebase this on the current `master` branch so we might be ready for another round of review and merge it.
cmichi: I've lost a bit track of where we are with this PR and where the discussion went.

@xgreenx Could you maybe quickly summarize what decision needs to be made for you to be able to finish the PR?
xgreenx: We need to decide do we need the `label` attribute or not. You think that [better to add](https://github.com/paritytech/ink/issues/900#issuecomment-949449714), @Robbepop thinks it is[ better to not add](https://github.com/paritytech/ink/issues/900#issuecomment-949433312) additional attributes=) [My thoughts](https://github.com/paritytech/ink/issues/900#issuecomment-949518025)
Robbepop: > We need to decide do we need the `label` attribute or not. You think that [better to add](https://github.com/paritytech/ink/issues/900#issuecomment-949449714), @Robbepop thinks it is[ better to not add](https://github.com/paritytech/ink/issues/900#issuecomment-949433312) additional attributes=) [My thoughts](https://github.com/paritytech/ink/issues/900#issuecomment-949518025)

I am strictly against adding the label attribute. the metadata changes are ok. i see no reason in adding a feature where there is no strict requirement and where we are not 100% sure about its design.
cmichi: >i see no reason in adding a feature where there is no strict requirement and where we are not 100% sure about its design.

@Robbepop Could you please reply to the points brought up in the discussion [here](https://github.com/paritytech/ink/issues/900#issuecomment-949449714)?
cmichi: @xgreenx I've discussed it with @Robbepop and the outcome is that we'll only include the metadata changes for now and revisit the `#[ink(label)]` discussion at a later point. Would you be so kind to adapt your PR?
xgreenx: Sure, will adapt it for the master branch and will remove `label` related code=)
xgreenx: I've updated the PR. In ABI we still use "name" for storage layout and for types. Do I need to update it for storage layout? (because in the case of types we need to update `scale-info`)
cmichi: @xgreenx Could you merge `master` into this PR?
cmichi: >In ABI we still use "name" for storage layout and for types. Do I need to update it for storage layout? (because in the case of types we need to update scale-info)

Nope, no need to adapt those.
codecov-commenter: # [Codecov](https://codecov.io/gh/paritytech/ink/pull/923?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech) Report
> Merging [#923](https://codecov.io/gh/paritytech/ink/pull/923?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech) (154e546) into [master](https://codecov.io/gh/paritytech/ink/commit/2ee203d41839ee15b594db6cb5de8ed2855757c9?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech) (2ee203d) will **increase** coverage by `4.65%`.
> The diff coverage is `63.63%`.

[![Impacted file tree graph](https://codecov.io/gh/paritytech/ink/pull/923/graphs/tree.svg?width=650&height=150&src=pr&token=tYyVaCZb7o&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech)](https://codecov.io/gh/paritytech/ink/pull/923?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech)

```diff
@@            Coverage Diff             @@
##           master     #923      +/-   ##
==========================================
+ Coverage   74.15%   78.80%   +4.65%     
==========================================
  Files         246      246              
  Lines        9258     9251       -7     
==========================================
+ Hits         6865     7290     +425     
+ Misses       2393     1961     -432     
```


| [Impacted Files](https://codecov.io/gh/paritytech/ink/pull/923?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech) | Coverage Δ | |
|---|---|---|
| [crates/metadata/src/specs.rs](https://codecov.io/gh/paritytech/ink/pull/923/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech#diff-Y3JhdGVzL21ldGFkYXRhL3NyYy9zcGVjcy5ycw==) | `73.33% <60.00%> (+0.60%)` | :arrow_up: |
| [crates/lang/codegen/src/generator/metadata.rs](https://codecov.io/gh/paritytech/ink/pull/923/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech#diff-Y3JhdGVzL2xhbmcvY29kZWdlbi9zcmMvZ2VuZXJhdG9yL21ldGFkYXRhLnJz) | `97.36% <100.00%> (+0.02%)` | :arrow_up: |
| [crates/storage/src/collections/vec/fuzz\_tests.rs](https://codecov.io/gh/paritytech/ink/pull/923/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech#diff-Y3JhdGVzL3N0b3JhZ2Uvc3JjL2NvbGxlY3Rpb25zL3ZlYy9mdXp6X3Rlc3RzLnJz) | `85.71% <0.00%> (-14.29%)` | :arrow_down: |
| [crates/allocator/src/bump.rs](https://codecov.io/gh/paritytech/ink/pull/923/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech#diff-Y3JhdGVzL2FsbG9jYXRvci9zcmMvYnVtcC5ycw==) | `62.50% <0.00%> (-4.17%)` | :arrow_down: |
| [crates/storage/src/traits/impls/prims.rs](https://codecov.io/gh/paritytech/ink/pull/923/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech#diff-Y3JhdGVzL3N0b3JhZ2Uvc3JjL3RyYWl0cy9pbXBscy9wcmltcy5ycw==) | `96.92% <0.00%> (+1.53%)` | :arrow_up: |
| [crates/lang/ir/src/ir/attrs.rs](https://codecov.io/gh/paritytech/ink/pull/923/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech#diff-Y3JhdGVzL2xhbmcvaXIvc3JjL2lyL2F0dHJzLnJz) | `83.07% <0.00%> (+4.07%)` | :arrow_up: |
| [crates/lang/ir/src/ir/item\_impl/callable.rs](https://codecov.io/gh/paritytech/ink/pull/923/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech#diff-Y3JhdGVzL2xhbmcvaXIvc3JjL2lyL2l0ZW1faW1wbC9jYWxsYWJsZS5ycw==) | `91.75% <0.00%> (+4.12%)` | :arrow_up: |
| [...ates/storage/src/collections/hashmap/fuzz\_tests.rs](https://codecov.io/gh/paritytech/ink/pull/923/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech#diff-Y3JhdGVzL3N0b3JhZ2Uvc3JjL2NvbGxlY3Rpb25zL2hhc2htYXAvZnV6el90ZXN0cy5ycw==) | `100.00% <0.00%> (+4.25%)` | :arrow_up: |
| [crates/env/src/api.rs](https://codecov.io/gh/paritytech/ink/pull/923/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech#diff-Y3JhdGVzL2Vudi9zcmMvYXBpLnJz) | `36.36% <0.00%> (+4.54%)` | :arrow_up: |
| [crates/metadata/src/layout/mod.rs](https://codecov.io/gh/paritytech/ink/pull/923/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech#diff-Y3JhdGVzL21ldGFkYXRhL3NyYy9sYXlvdXQvbW9kLnJz) | `77.01% <0.00%> (+4.59%)` | :arrow_up: |
| ... and [36 more](https://codecov.io/gh/paritytech/ink/pull/923/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/paritytech/ink/pull/923?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/paritytech/ink/pull/923?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech). Last update [2ee203d...154e546](https://codecov.io/gh/paritytech/ink/pull/923?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=paritytech).

cmichi: @xgreenx The `ink-waterfall` CI stage is expected to fail, since it builds our example contracts and tries to upload them via polkadot-js. Since that UI doesn't understand the new metadata format yet the upload fails. I've created an issue for it and will merge the PR after that one is solved. Feel free to implement the namespace inclusion in the meantime or as a follow-up, whatever works best for you :-).

Patch:
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 491f3a6f9e..ae030304cd 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -13,6 +13,7 @@ default:
       - api_failure
 
 stages:
+  - lint
   - check
   - workspace
   - examples
@@ -105,7 +106,92 @@ workflow:
       file:                        false
     GITHUB_SSH_PRIV_KEY:
       vault:                       cicd/gitlab/$CI_PROJECT_PATH/GITHUB_SSH_PRIV_KEY@kv
-      file:                        true
+      file:                        false
+
+#### stage:                        lint
+#
+# Note: For all of these lints we `allow_failure` so that the rest of the build can
+# continue running despite them not passing. Merging is still disallowed since (most) of
+# the lint steps are marked as "Required" in GitHub.
+spellcheck:
+  stage:                           lint
+  <<:                              *docker-env
+  <<:                              *test-refs
+  script:
+    - cargo spellcheck check -vvvv --cfg=.config/cargo_spellcheck.toml --checkers hunspell --code 1 -- recursive .
+    - cargo spellcheck check -vvvv --cfg=.config/cargo_spellcheck.toml --checkers hunspell --code 1 -- recursive examples/
+  allow_failure:                   true
+
+fmt:
+  stage:                           lint
+  <<:                              *docker-env
+  <<:                              *test-refs
+  script:
+    - cargo fmt --verbose --all -- --check
+    # For the UI tests we need to disable the license check
+    - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/tests/ui/contract/{pass,fail}/*.rs
+    - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/tests/ui/trait_def/{pass,fail}/*.rs
+  allow_failure:                   true
+
+examples-fmt:
+  stage:                           lint
+  <<:                              *docker-env
+  <<:                              *test-refs
+  script:
+    # Note that we disable the license header check for the examples, since they are unlicensed.
+    - for example in examples/*/; do
+        cargo fmt --verbose --manifest-path ${example}/Cargo.toml -- --check --config=license_template_path="";
+      done
+    - for contract in ${DELEGATOR_SUBCONTRACTS}; do
+        cargo fmt --verbose --manifest-path examples/delegator/${contract}/Cargo.toml -- --check --config=license_template_path="";
+      done
+  allow_failure:                   true
+
+clippy-std:
+  stage:                           lint
+  <<:                              *docker-env
+  <<:                              *test-refs
+  script:
+    - for crate in ${ALL_CRATES}; do
+        cargo clippy --verbose --all-targets --all-features --manifest-path crates/${crate}/Cargo.toml -- -D warnings;
+      done
+
+clippy-wasm:
+  stage:                           lint
+  <<:                              *docker-env
+  <<:                              *test-refs
+  script:
+    - for crate in ${ALSO_WASM_CRATES}; do
+        cargo clippy --verbose --no-default-features --manifest-path crates/${crate}/Cargo.toml --target wasm32-unknown-unknown -- -D warnings;
+      done
+  allow_failure:                   true
+
+examples-clippy-std:
+  stage:                           lint
+  <<:                              *docker-env
+  <<:                              *test-refs
+  script:
+    - for example in examples/*/; do
+        cargo clippy --verbose --all-targets --manifest-path ${example}/Cargo.toml -- -D warnings;
+      done
+    - for contract in ${DELEGATOR_SUBCONTRACTS}; do
+        cargo clippy --verbose --all-targets --manifest-path examples/delegator/${contract}/Cargo.toml -- -D warnings;
+      done
+  allow_failure:                   true
+
+examples-clippy-wasm:
+  stage:                           lint
+  <<:                              *docker-env
+  <<:                              *test-refs
+  script:
+    - for example in examples/*/; do
+        cargo clippy --verbose --manifest-path ${example}/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings;
+      done
+    - for contract in ${DELEGATOR_SUBCONTRACTS}; do
+        cargo clippy --verbose --manifest-path examples/delegator/${contract}/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings;
+      done
+  allow_failure:                   true
+
 
 #### stage:                        check
 
@@ -199,13 +285,6 @@ docs:
     # FIXME: remove me after CI image gets nonroot
     - chown -R nonroot:nonroot ./crate-docs
 
-spellcheck:
-  stage:                           workspace
-  <<:                              *docker-env
-  <<:                              *test-refs
-  script:
-    - cargo spellcheck check -vvvv --cfg=.config/cargo_spellcheck.toml --checkers hunspell --code 1 -- recursive .
-    - cargo spellcheck check -vvvv --cfg=.config/cargo_spellcheck.toml --checkers hunspell --code 1 -- recursive examples/
 
 codecov:
   stage:                           workspace
@@ -256,40 +335,6 @@ codecov:
     - rust-covfix lcov-lines.info --output lcov-lines-fixed.info
     - codecov --token "$CODECOV_TOKEN" --file lcov-lines-fixed.info --nonZero
 
-clippy-std:
-  stage:                           workspace
-  <<:                              *docker-env
-  <<:                              *test-refs
-  needs:
-    - job:                         check-std
-      artifacts:                   false
-  script:
-    - for crate in ${ALL_CRATES}; do
-        cargo clippy --verbose --all-targets --all-features --manifest-path crates/${crate}/Cargo.toml -- -D warnings;
-      done
-
-clippy-wasm:
-  stage:                           workspace
-  <<:                              *docker-env
-  <<:                              *test-refs
-  needs:
-    - job:                         check-wasm
-      artifacts:                   false
-  script:
-    - for crate in ${ALSO_WASM_CRATES}; do
-        cargo clippy --verbose --no-default-features --manifest-path crates/${crate}/Cargo.toml --target wasm32-unknown-unknown -- -D warnings;
-      done
-
-fmt:
-  stage:                           workspace
-  <<:                              *docker-env
-  <<:                              *test-refs
-  script:
-    - cargo fmt --verbose --all -- --check
-    # For the UI tests we need to disable the license check
-    - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/tests/ui/contract/{pass,fail}/*.rs
-    - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/tests/ui/trait_def/{pass,fail}/*.rs
-
 
 #### stage:                        examples
 
@@ -323,45 +368,6 @@ examples-test-experimental-engine:
     - cargo test --no-default-features --features std, ink-experimental-engine --verbose --manifest-path examples/contract-terminate/Cargo.toml
     - cargo test --no-default-features --features std, ink-experimental-engine --verbose --manifest-path examples/contract-transfer/Cargo.toml
 
-examples-fmt:
-  stage:                           examples
-  <<:                              *docker-env
-  <<:                              *test-refs
-  script:
-    # Note that we disable the license header check for the examples, since they are unlicensed.
-    - for example in examples/*/; do
-        cargo fmt --verbose --manifest-path ${example}/Cargo.toml -- --check --config=license_template_path="";
-      done
-    - for contract in ${DELEGATOR_SUBCONTRACTS}; do
-        cargo fmt --verbose --manifest-path examples/delegator/${contract}/Cargo.toml -- --check --config=license_template_path="";
-      done
-
-examples-clippy-std:
-  stage:                           examples
-  <<:                              *docker-env
-  <<:                              *test-refs
-  needs:
-    - job:                         clippy-std
-      artifacts:                   false
-  script:
-    - for example in examples/*/; do
-        cargo clippy --verbose --all-targets --manifest-path ${example}/Cargo.toml -- -D warnings;
-      done
-    - for contract in ${DELEGATOR_SUBCONTRACTS}; do
-        cargo clippy --verbose --all-targets --manifest-path examples/delegator/${contract}/Cargo.toml -- -D warnings;
-      done
-
-examples-clippy-wasm:
-  stage:                           examples
-  <<:                              *docker-env
-  <<:                              *test-refs
-  script:
-    - for example in examples/*/; do
-        cargo clippy --verbose --manifest-path ${example}/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings;
-      done
-    - for contract in ${DELEGATOR_SUBCONTRACTS}; do
-        cargo clippy --verbose --manifest-path examples/delegator/${contract}/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings;
-      done
 
 examples-contract-build:
   stage:                           examples
@@ -445,9 +451,12 @@ publish-docs:
   before_script:
     - unset CARGO_TARGET_DIR
   script:
-    - rm -rf /tmp/*
+    # Setup ssh
+    - eval $(ssh-agent)
+    - ssh-add - <<< ${GITHUB_SSH_PRIV_KEY}
+    - mkdir ~/.ssh && touch ~/.ssh/known_hosts
+    - ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
     # Set git config
-    - git config core.sshCommand "ssh -i ${GITHUB_SSH_PRIV_KEY} -F /dev/null -o StrictHostKeyChecking=no"
     - git config user.email "devops-team@parity.io"
     - git config user.name "${GITHUB_USER}"
     - git config remote.origin.url "git@github.com:/paritytech/${CI_PROJECT_NAME}.git"
diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644
index 0000000000..fa342a285f
--- /dev/null
+++ b/CODEOWNERS
@@ -0,0 +1,25 @@
+# Lists some code owners.
+#
+# A codeowner just oversees some part of the codebase. If an owned file is changed then the
+# corresponding codeowner receives a review request. An approval of the codeowner might be
+# required for merging a PR (depends on repository settings).
+#
+# For details about syntax, see:
+# https://help.github.com/en/articles/about-code-owners
+# But here are some important notes:
+#
+# - Glob syntax is git-like, e.g. `/core` means the core directory in the root, unlike `core`
+#   which can be everywhere.
+# - Multiple owners are supported.
+# - Either handle (e.g, @github_user or @github_org/team) or email can be used. Keep in mind,
+#   that handles might work better because they are more recognizable on GitHub,
+#   you can use them for mentioning unlike an email.
+# - The latest matching rule, if multiple, takes precedence.
+
+# All of the core team members are global code owners.
+* @Robbepop @cmichi @ascjones @HCastano
+
+# CI
+/.github/workflows/ @paritytech/ci @Robbepop @cmichi @ascjones @HCastano
+/scripts/.ci/ @paritytech/ci @Robbepop @cmichi @ascjones @HCastano
+/.gitlab-ci.yml @paritytech/ci @Robbepop @cmichi @ascjones @HCastano
diff --git a/Cargo.toml b/Cargo.toml
index 48f592ff03..ded10b8e9d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,9 +7,12 @@ members = [
     "crates/lang/macro",
     "crates/lang/ir",
     "crates/lang/codegen",
+    "crates/lang/macro",
     "crates/prelude",
     "crates/primitives",
+    "crates/engine",
     "crates/env",
+    "crates/eth_compatibility",
     "crates/storage",
     "crates/storage/derive",
 ]
diff --git a/README.md b/README.md
index d30389b776..f48af5a042 100644
--- a/README.md
+++ b/README.md
@@ -224,6 +224,7 @@ In a module annotated with `#[ink::contract]` these attributes are available:
 | `#[ink(constructor)]` | Applicable to method. | Flags a method for the ink! storage struct as constructor making it available to the API for instantiating the contract. |
 | `#[ink(payable)]` | Applicable to ink! messages. | Allows receiving value as part of the call of the ink! message. ink! constructors are implicitly payable. |
 | `#[ink(selector = S:u32)]` | Applicable to ink! messages and ink! constructors. | Specifies a concrete dispatch selector for the flagged entity. This allows a contract author to precisely control the selectors of their APIs making it possible to rename their API without breakage. |
+| `#[ink(selector = _)]` | Applicable to ink! messages. | Specifies a fallback message that is invoked if no other ink! message matches a selector. |
 | `#[ink(namespace = N:string)]` | Applicable to ink! trait implementation blocks. | Changes the resulting selectors of all the ink! messages and ink! constructors within the trait implementation. Allows to disambiguate between trait implementations with overlapping message or constructor names. Use only with great care and consideration! |
 | `#[ink(impl)]` | Applicable to ink! implementation blocks. | Tells the ink! codegen that some implementation block shall be granted access to ink! internals even without it containing any ink! messages or ink! constructors. |
 
diff --git a/RELEASES.md b/RELEASES.md
index f0367b135a..ac7b46c740 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,49 +1,89 @@
-# Version 3.0-rc7 (UNRELEASED)
+# Version 3.0-rc8 (UNRELEASED)
+
+This is the 8th release candidate for ink! 3.0.
+
+## Change
+- Renamed the `ink_env` function `transferred_balance()` to `transferred_value()` ‒ [#1063](https://github.com/paritytech/ink/pull/1063).
+
+# Version 3.0-rc7
 
 This is the 7th release candidate for ink! 3.0.
 
+Since our last release candidate we implemented a number of contract size improvements.
+With those improvements the size of our `erc20` example has reduced significantly:
+
+|          |             | Release Build with `cargo-contract` |
+|:---------|:------------|:------------------------------------|
+| `erc20`  | `3.0.0-rc6` | 29.3 K                              |
+| `erc20`  | `3.0.0-rc7` | 10.4 K                              |
+
+The savings apply partly to our other examples; for `erc20` they are most
+significant since it has been migrated to use a new [`Mapping`](https://paritytech.github.io/ink/ink_storage/lazy/struct.Mapping.html)
+data structure, which we introduce with this release candidate.
+The other examples will be migrated to this new data structure as a next step.
+
+## Compatibility
+
+You need to upgrade to a new version of the `contracts` pallet in order to use
+this ink! release. This is because we upgraded to a newer `seal_call` API.
+Specifically you need to upgrade to at least the pallet version
+[e9fca0f](https://github.com/paritytech/substrate/commit/e9fca0f4d7a65998206f29baf0133a7931452104)
+(or newer than Nov 24).
+
+## Removed
+- Removed the state rent API ‒ [#1036](https://github.com/paritytech/ink/pull/1036).
+
 ## Added
-- The ink! codegen now heavily relies on static type information based on traits defined in `ink_lang`.
+- Added support for wildcard selectors ‒ [#1020](https://github.com/paritytech/ink/pull/1020).
+    - This enables writing upgradable smart contracts using the proxy/forward pattern.
+      We added a new example to illustrate this ‒ the [proxy](https://github.com/paritytech/ink/tree/master/examples/proxy) example.
+    - Annotating a wildcard selector in traits is not supported.
+- The ink! codegen now heavily relies on static type information based on traits defined in `ink_lang` ‒ [#665](https://github.com/paritytech/ink/pull/665).
     - Some of those traits and their carried information can be used for static reflection of ink!
       smart contracts. Those types and traits reside in the new `ink_lang::reflect` module and is
       publicly usable by ink! smart contract authors.
 
 ## Changed
-- Upgraded to the unstable `seal_call` API ‒ [#960](https://github.com/paritytech/ink/pull/960).
+- Upgraded to the `seal_call` v1 API ‒ [#960](https://github.com/paritytech/ink/pull/960).
   - This API now enables control over the behavior of cross-contract calls, e.g. to forward/clone input,
     enable tail calls and control reentrancy.
     The crate documentation contains more details on the [`CallFlags`](https://paritytech.github.io/ink/ink_env/struct.CallFlags.html).
   - **Note:** The default behavior of cross-contract calls now disallows reentering the calling contract.
-  - **Note:** In order to support this you currently have to enable the `unstable-interface` of
-    the `contracts` pallet, [like here](https://github.com/paritytech/substrate-contracts-node/blob/main/runtime/Cargo.toml#L104-L108).
-- ink! contract definitions via `#[ink::contract]`:
-    - ink! smart contracts now generate two contract types. Given `MyContract`:
+- ink! contract definitions via `#[ink::contract]` ‒ [#665](https://github.com/paritytech/ink/pull/665).<br/>
+  For ink! smart contracts we now generate two contract types. Given `MyContract`:
     - `MyContract` will still be the storage struct.
       However, it can now additionally be used as static dependency in other smart contracts.
       Static dependencies can be envisioned as being directly embedded into a smart contract.
     - `MyContractRef` is pretty much the same of what we had gotten with the old `ink-as-dependency`.
       It is a typed thin-wrapper around an `AccountId` that is mirroring the ink! smart contract's API
       and implemented traits.
-- ink! trait definitions via `#[ink::trait_definition]`:
+- ink! trait definitions via `#[ink::trait_definition]` ‒ [#665](https://github.com/paritytech/ink/pull/665).
     - ink! trait definitions no longer can define trait constructors.
     - ink! trait implementations now inherit `selector` and `payable` properties for trait messages.
         - Now explicitly setting `selector` or `payable` property for an implemented ink! trait method
           will only act as a guard that the set property is in fact the same as defined by the ink!
           trait definition.
-- Improved some ink! specific compile errors:
-    - For example, when using ink! messages and constructors that have inputs or
-      outputs that cannot be encoded or decoded using the SCALE codec.
-- Simplified selector computation for ink! trait methods.
+- Improved some ink! specific compile errors ‒ [#665](https://github.com/paritytech/ink/pull/665).
+    - For example, when using ink! messages and constructors which have inputs (or
+      outputs) that cannot be encoded (or decoded) using the SCALE codec.
+- Simplified selector computation for ink! trait methods ‒ [#665](https://github.com/paritytech/ink/pull/665).
     - Now selectors are encoded as `blake2b({namespace}::{trait_identifier}::{message_identifier})[0..4]`.
       If no `namespace` is set for the ink! trait definition then the formula is
       `blake2b({trait_identifier}::{message_identifier})[0..4]`.
       Where `trait_identifier` and `message_identifier` both refer to the identifiers of the ink! trait
       definition and ink! trait message respectively.
+- We switched to Rust edition 2021 ‒ [#977](https://github.com/paritytech/ink/pull/977).
+- Update chain extension example to show argument passing ‒ [#1029](https://github.com/paritytech/ink/pull/1029).
 
 ## Fixed
-- Contracts that are compiled as root (the default) now properly revert the transaction if a message
-  returned `Result::Err`.
-    - This does not apply to ink! smart contracts that are used as dependencies. Therefore it is still possible to match against a result return type for a called dependency.
+- Contracts now revert the transaction if an ink! message returns `Result::Err` ‒ [#975](https://github.com/paritytech/ink/pull/975), [#998](https://github.com/paritytech/ink/pull/998).
+    - It is still possible to match against a `Result` return type for a called dependency contract
+      ‒ i.e. a sub-contract specified in the contract's `Cargo.toml`.
+- We implemented a number of Wasm contract size improvements:
+    - Simple Mapping Storage Primitive ‒ [#946](https://github.com/paritytech/ink/pull/946).
+    - Remove `always` from `inline` to allow compiler decide that to do ‒ [#1012](https://github.com/paritytech/ink/pull/1012) (thanks [@xgreenx](https://github.com/xgreenx)).
+    - Add a way to allocate a storage facility using spread (and packed) layouts ‒ [#978](https://github.com/paritytech/ink/pull/978).
+    - Extract non-generic part of `push_topic` to reduce code size ‒ [#1026](https://github.com/paritytech/ink/pull/1026).
 
 # Version 3.0-rc6
 
diff --git a/crates/allocator/Cargo.toml b/crates/allocator/Cargo.toml
index e3560e9d71..8858471d7f 100644
--- a/crates/allocator/Cargo.toml
+++ b/crates/allocator/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_allocator"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>", "Robin Freyler <robin@parity.io>"]
 edition = "2021"
 
diff --git a/crates/engine/Cargo.toml b/crates/engine/Cargo.toml
index 08325e1bfe..c483b39949 100644
--- a/crates/engine/Cargo.toml
+++ b/crates/engine/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_engine"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>", "Michael Müller <michi@parity.io>"]
 edition = "2021"
 
@@ -18,12 +18,12 @@ include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]
 scale = { package = "parity-scale-codec", version = "2.3", default-features = false, features = ["derive", "full"] }
 derive_more = { version = "0.99", default-features = false, features = ["from", "display"] }
 
-sha2 = { version = "0.9" }
-sha3 = { version = "0.9" }
+sha2 = { version = "0.10" }
+sha3 = { version = "0.10" }
 blake2 = { version = "0.9" }
 
 # ECDSA for the off-chain environment.
-libsecp256k1 = { version = "0.7.0" }
+secp256k1 = { version = "0.20.3", features = ["recovery"] }
 
 [features]
 default = ["std"]
diff --git a/crates/engine/src/exec_context.rs b/crates/engine/src/exec_context.rs
index 873cfc7506..0029e9dfc7 100644
--- a/crates/engine/src/exec_context.rs
+++ b/crates/engine/src/exec_context.rs
@@ -22,14 +22,14 @@ use super::types::{
 pub struct ExecContext {
     /// The caller of the contract execution. Might be user or another contract.
     ///
-    /// We don't know the specifics of the AccountId ‒ like how many bytes or what
+    /// We don't know the specifics of the `AccountId` ‒ like how many bytes or what
     /// type of default `AccountId` makes sense ‒ they are left to be initialized
     /// by the crate which uses the `engine`. Methods which require a caller might
     /// panic when it has not been set.
     pub caller: Option<AccountId>,
     /// The callee of the contract execution. Might be user or another contract.
     ///
-    /// We don't know the specifics of the AccountId ‒ like how many bytes or what
+    /// We don't know the specifics of the `AccountId` ‒ like how many bytes or what
     /// type of default `AccountId` makes sense ‒ they are left to be initialized
     /// by the crate which uses the `engine`. Methods which require a callee might
     /// panic when it has not been set.
diff --git a/crates/engine/src/ext.rs b/crates/engine/src/ext.rs
index a28957954c..24087c33a0 100644
--- a/crates/engine/src/ext.rs
+++ b/crates/engine/src/ext.rs
@@ -24,10 +24,7 @@ use crate::{
         DebugInfo,
         EmittedEvent,
     },
-    types::{
-        AccountId,
-        Key,
-    },
+    types::AccountId,
 };
 use std::panic::panic_any;
 
@@ -89,13 +86,13 @@ define_error_codes! {
     NewContractNotFunded = 6,
     /// No code could be found at the supplied code hash.
     CodeNotFound = 7,
-    /// The account that was called is either no contract (e.g. user account) or is a tombstone.
+    /// The account that was called is no contract, but a plain account.
     NotCallable = 8,
     /// The call to `seal_debug_message` had no effect because debug message
     /// recording was disabled.
     LoggingDisabled = 9,
     /// ECDSA pubkey recovery failed. Most probably wrong recovery id or signature.
-    EcdsaRecoverFailed = 11,
+    EcdsaRecoveryFailed = 11,
 }
 
 /// The raw return code returned by the host side.
@@ -244,9 +241,6 @@ impl Engine {
         self.transfer(beneficiary, value)
             .expect("transfer did not work");
 
-        // What is currently missing is to set a tombstone with a code hash here
-        // and remove the contract storage subsequently.
-
         // Encode the result of the termination and panic with it.
         // This enables testing for the proper result and makes sure this
         // method returns `Never`.
@@ -299,29 +293,6 @@ impl Engine {
         set_output(output, callee)
     }
 
-    /// Restores a tombstone to the original smart contract.
-    ///
-    /// # Params
-    ///
-    /// - `account_id`: Encoded bytes of the `AccountId` of the to-be-restored contract.
-    /// - `code_hash`: Encoded code hash of the to-be-restored contract.
-    /// - `rent_allowance`: The encoded rent allowance of the restored contract
-    ///                     upon successful restoration.
-    /// - `filtered_keys`: Storage keys that will be ignored for the tombstone hash
-    ///                    match calculation that decide whether the original contract
-    ///                    storage and the storage of the restorer contract is equal.
-    pub fn restore_to(
-        &mut self,
-        _account_id: &[u8],
-        _code_hash: &[u8],
-        _rent_allowance: &[u8],
-        filtered_keys: &[&[u8]],
-    ) {
-        let _filtered_keys: Vec<crate::Key> =
-            filtered_keys.iter().map(|k| Key::from_bytes(k)).collect();
-        unimplemented!("off-chain environment does not yet support `restore_to`");
-    }
-
     /// Records the given debug message and appends to stdout.
     pub fn debug_message(&mut self, message: &str) {
         self.debug_info.record_debug_message(String::from(message));
@@ -360,18 +331,10 @@ impl Engine {
         unimplemented!("off-chain environment does not yet support `gas_left`");
     }
 
-    pub fn rent_allowance(&self, _output: &mut &mut [u8]) {
-        unimplemented!("off-chain environment does not yet support `rent_allowance`");
-    }
-
     pub fn minimum_balance(&self, _output: &mut &mut [u8]) {
         unimplemented!("off-chain environment does not yet support `minimum_balance`");
     }
 
-    pub fn tombstone_deposit(&self, _output: &mut &mut [u8]) {
-        unimplemented!("off-chain environment does not yet support `tombstone_deposit`");
-    }
-
     #[allow(clippy::too_many_arguments)]
     pub fn instantiate(
         &mut self,
@@ -401,10 +364,6 @@ impl Engine {
         unimplemented!("off-chain environment does not yet support `weight_to_fee`");
     }
 
-    pub fn set_rent_allowance(&mut self, _value: &[u8]) {
-        unimplemented!("off-chain environment does not yet support `set_rent_allowance`");
-    }
-
     pub fn random(&self, _subject: &[u8], _output: &mut &mut [u8]) {
         unimplemented!("off-chain environment does not yet support `random`");
     }
@@ -428,11 +387,13 @@ impl Engine {
         message_hash: &[u8; 32],
         output: &mut [u8; 33],
     ) -> Result {
-        use libsecp256k1::{
-            recover,
+        use secp256k1::{
+            recovery::{
+                RecoverableSignature,
+                RecoveryId,
+            },
             Message,
-            RecoveryId,
-            Signature,
+            Secp256k1,
         };
 
         // In most implementations, the v is just 0 or 1 internally, but 27 was added
@@ -442,20 +403,27 @@ impl Engine {
         } else {
             signature[64]
         };
-        let message = Message::parse(message_hash);
-        let signature = Signature::parse_standard_slice(&signature[0..64])
-            .unwrap_or_else(|error| panic!("Unable to parse the signature: {}", error));
 
-        let recovery_id = RecoveryId::parse(recovery_byte)
+        let recovery_id = RecoveryId::from_i32(recovery_byte as i32)
             .unwrap_or_else(|error| panic!("Unable to parse the recovery id: {}", error));
 
-        let pub_key = recover(&message, &signature, &recovery_id);
+        let message = Message::from_slice(message_hash).unwrap_or_else(|error| {
+            panic!("Unable to create the message from hash: {}", error)
+        });
+        let signature =
+            RecoverableSignature::from_compact(&signature[0..64], recovery_id)
+                .unwrap_or_else(|error| {
+                    panic!("Unable to parse the signature: {}", error)
+                });
+
+        let secp = Secp256k1::new();
+        let pub_key = secp.recover(&message, &signature);
         match pub_key {
             Ok(pub_key) => {
-                *output = pub_key.serialize_compressed();
+                *output = pub_key.serialize();
                 Ok(())
             }
-            Err(_) => Err(Error::EcdsaRecoverFailed),
+            Err(_) => Err(Error::EcdsaRecoveryFailed),
         }
     }
 }
diff --git a/crates/engine/src/hashing.rs b/crates/engine/src/hashing.rs
index e80f4d45b4..207b5c7607 100644
--- a/crates/engine/src/hashing.rs
+++ b/crates/engine/src/hashing.rs
@@ -38,10 +38,7 @@ pub fn blake2b_128(input: &[u8], output: &mut [u8; 16]) {
 /// Conduct the KECCAK 256-bit hash and place the result into `output`.
 pub fn keccak_256(input: &[u8], output: &mut [u8; 32]) {
     use sha3::{
-        digest::{
-            generic_array::GenericArray,
-            FixedOutput as _,
-        },
+        digest::generic_array::GenericArray,
         Digest as _,
     };
     let mut hasher = sha3::Keccak256::new();
@@ -49,13 +46,10 @@ pub fn keccak_256(input: &[u8], output: &mut [u8; 32]) {
     hasher.finalize_into(<&mut GenericArray<u8, _>>::from(&mut output[..]));
 }
 
-/// Conduct the SHA2 256-bit hash and place the result into `output`.
+/// Conduct the SHA-2 256-bit hash and place the result into `output`.
 pub fn sha2_256(input: &[u8], output: &mut [u8; 32]) {
     use sha2::{
-        digest::{
-            generic_array::GenericArray,
-            FixedOutput as _,
-        },
+        digest::generic_array::GenericArray,
         Digest as _,
     };
     let mut hasher = sha2::Sha256::new();
diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs
index a6deba086e..ca1c306750 100644
--- a/crates/engine/src/lib.rs
+++ b/crates/engine/src/lib.rs
@@ -24,7 +24,6 @@ mod types;
 mod tests;
 
 pub use types::AccountError;
-use types::Key;
 
 use derive_more::From;
 
diff --git a/crates/engine/src/types.rs b/crates/engine/src/types.rs
index 5237f7a594..0f94cf9908 100644
--- a/crates/engine/src/types.rs
+++ b/crates/engine/src/types.rs
@@ -49,6 +49,7 @@ pub struct Key(Vec<u8>);
 
 impl Key {
     /// Creates a new `Key` from the given raw bytes.
+    #[allow(dead_code)]
     pub fn from_bytes(bytes: &[u8]) -> Self {
         Self(bytes.to_vec())
     }
diff --git a/crates/env/Cargo.toml b/crates/env/Cargo.toml
index abafb26179..617f667977 100644
--- a/crates/env/Cargo.toml
+++ b/crates/env/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_env"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>", "Robin Freyler <robin@parity.io>"]
 edition = "2021"
 
@@ -15,10 +15,10 @@ categories = ["no-std", "embedded"]
 include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]
 
 [dependencies]
-ink_metadata = { version = "3.0.0-rc6", path = "../metadata/", default-features = false, features = ["derive"], optional = true }
-ink_allocator = { version = "3.0.0-rc6", path = "../allocator/", default-features = false }
-ink_primitives = { version = "3.0.0-rc6", path = "../primitives/", default-features = false }
-ink_prelude = { version = "3.0.0-rc6", path = "../prelude/", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../metadata/", default-features = false, features = ["derive"], optional = true }
+ink_allocator = { version = "3.0.0-rc7", path = "../allocator/", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../primitives/", default-features = false }
+ink_prelude = { version = "3.0.0-rc7", path = "../prelude/", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2.3", default-features = false, features = ["derive", "full"] }
 derive_more = { version = "0.99", default-features = false, features = ["from", "display"] }
@@ -27,21 +27,20 @@ cfg-if = "1.0"
 paste = "1.0"
 arrayref = "0.3"
 static_assertions = "1.1"
-sp-arithmetic = { version = "3.0", default-features = false }
 
 [target.'cfg(target_arch = "wasm32")'.dependencies]
-libsecp256k1 = { version = "0.7.0", default-features = false }
+rlibc = "1"
 
 [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
-ink_engine = { version = "3.0.0-rc6", path = "../engine/", default-features = false, optional = true }
+ink_engine = { version = "3.0.0-rc7", path = "../engine/", default-features = false, optional = true }
 
 # Hashes for the off-chain environment.
-sha2 = { version = "0.9", optional = true }
-sha3 = { version = "0.9", optional = true }
+sha2 = { version = "0.10", optional = true }
+sha3 = { version = "0.10", optional = true }
 blake2 = { version = "0.9", optional = true }
 
 # ECDSA for the off-chain environment.
-libsecp256k1 = { version = "0.7.0" }
+secp256k1 = { version = "0.20.3", features = ["recovery"] }
 
 # Only used in the off-chain environment.
 #
diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs
index d9a4bcc28d..363308a05a 100644
--- a/crates/env/src/api.rs
+++ b/crates/env/src/api.rs
@@ -34,10 +34,6 @@ use crate::{
         HashOutput,
     },
     topics::Topics,
-    types::{
-        RentParams,
-        RentStatus,
-    },
     Environment,
     Result,
 };
@@ -57,17 +53,17 @@ where
     })
 }
 
-/// Returns the transferred balance for the contract execution.
+/// Returns the transferred value for the contract execution.
 ///
 /// # Errors
 ///
 /// If the returned value cannot be properly decoded.
-pub fn transferred_balance<T>() -> T::Balance
+pub fn transferred_value<T>() -> T::Balance
 where
     T: Environment,
 {
     <EnvInstance as OnInstance>::on_instance(|instance| {
-        TypedEnvBackend::transferred_balance::<T>(instance)
+        TypedEnvBackend::transferred_value::<T>(instance)
     })
 }
 
@@ -145,56 +141,6 @@ where
     })
 }
 
-/// Returns the current rent allowance for the executed contract.
-///
-/// # Errors
-///
-/// If the returned value cannot be properly decoded.
-pub fn rent_allowance<T>() -> T::Balance
-where
-    T: Environment,
-{
-    <EnvInstance as OnInstance>::on_instance(|instance| {
-        TypedEnvBackend::rent_allowance::<T>(instance)
-    })
-}
-
-/// Returns information needed for rent calculations.
-///
-/// # Errors
-///
-/// If the returned value cannot be properly decoded.
-pub fn rent_params<T>() -> Result<RentParams<T>>
-where
-    T: Environment,
-{
-    <EnvInstance as OnInstance>::on_instance(|instance| {
-        TypedEnvBackend::rent_params::<T>(instance)
-    })
-}
-
-/// Returns information about the required deposit and resulting rent.
-///
-/// # Parameters
-///
-/// - `at_refcount`: The `refcount` assumed for the returned `custom_refcount_*` fields.
-///   If `None` is supplied the `custom_refcount_*` fields will also be `None`.
-///
-///   The `current_*` fields of `RentStatus` do **not** consider changes to the code's
-///   `refcount` made during the currently running call.
-///
-/// # Errors
-///
-/// If the returned value cannot be properly decoded.
-pub fn rent_status<T>(at_refcount: Option<core::num::NonZeroU32>) -> Result<RentStatus<T>>
-where
-    T: Environment,
-{
-    <EnvInstance as OnInstance>::on_instance(|instance| {
-        TypedEnvBackend::rent_status::<T>(instance, at_refcount)
-    })
-}
-
 /// Returns the current block number.
 ///
 /// # Errors
@@ -223,20 +169,6 @@ where
     })
 }
 
-/// Returns the tombstone deposit for the contracts chain.
-///
-/// # Errors
-///
-/// If the returned value cannot be properly decoded.
-pub fn tombstone_deposit<T>() -> T::Balance
-where
-    T: Environment,
-{
-    <EnvInstance as OnInstance>::on_instance(|instance| {
-        TypedEnvBackend::tombstone_deposit::<T>(instance)
-    })
-}
-
 /// Emits an event with the given event data.
 pub fn emit_event<T, Event>(event: Event)
 where
@@ -248,16 +180,6 @@ where
     })
 }
 
-/// Sets the rent allowance of the executed contract to the new value.
-pub fn set_rent_allowance<T>(new_value: T::Balance)
-where
-    T: Environment,
-{
-    <EnvInstance as OnInstance>::on_instance(|instance| {
-        TypedEnvBackend::set_rent_allowance::<T>(instance, new_value)
-    })
-}
-
 /// Writes the value to the contract storage under the given key.
 ///
 /// # Panics
@@ -306,7 +228,6 @@ pub fn clear_contract_storage(key: &Key) {
 ///
 /// - If the called account does not exist.
 /// - If the called account is not a contract.
-/// - If the called contract is a tombstone.
 /// - If arguments passed to the called contract message are invalid.
 /// - If the called contract execution has trapped.
 /// - If the called contract ran out of gas upon execution.
@@ -331,7 +252,6 @@ where
 ///
 /// - If the called account does not exist.
 /// - If the called account is not a contract.
-/// - If the called contract is a tombstone.
 /// - If arguments passed to the called contract message are invalid.
 /// - If the called contract execution has trapped.
 /// - If the called contract ran out of gas upon execution.
@@ -375,75 +295,11 @@ where
     })
 }
 
-/// Restores a smart contract in tombstone state.
-///
-/// # Params
-///
-/// - `account_id`: Account ID of the to-be-restored contract.
-/// - `code_hash`: Code hash of the to-be-restored contract.
-/// - `rent_allowance`: Rent allowance of the restored contract
-///                     upon successful restoration.
-/// - `filtered_keys`: Storage keys to be excluded when calculating the tombstone hash,
-///                    which is used to decide whether the original contract and the
-///                    to-be-restored contract have matching storage.
-///
-/// # Usage
-///
-/// A smart contract that has too few funds to pay for its storage fees
-/// can eventually be evicted. An evicted smart contract `C` leaves behind
-/// a tombstone associated with a hash that has been computed partially
-/// by its storage contents.
-///
-/// To restore contract `C` back to a fully working contract the normal
-/// process is to write another contract `C2` with the only purpose to
-/// eventually have the absolutely same contract storage as `C` did when
-/// it was evicted.
-/// For that purpose `C2` can use other storage keys that have not been in
-/// use by contract `C`.
-/// Once `C2` contract storage matches the storage of `C` when it was evicted
-/// `C2` can invoke this method in order to initiate restoration of `C`.
-/// A tombstone hash is calculated for `C2` and if it matches the tombstone
-/// hash of `C` the restoration is going to be successful.
-/// The `filtered_keys` argument can be used to ignore the extraneous keys
-/// used by `C2` but not used by `C`.
-///
-/// The process of such a smart contract restoration can generally be very expensive.
-///
-/// # Note
-///
-/// - `filtered_keys` can be used to ignore certain storage regions
-///   in the restorer contract to not influence the hash calculations.
-/// - Does *not* perform restoration right away but defers it to the end of
-///   the contract execution.
-/// - Restoration is canceled if there is no tombstone in the destination
-///   address or if the hashes don't match. No changes are made in this case.
-pub fn restore_contract<T>(
-    account_id: T::AccountId,
-    code_hash: T::Hash,
-    rent_allowance: T::Balance,
-    filtered_keys: &[Key],
-) where
-    T: Environment,
-{
-    <EnvInstance as OnInstance>::on_instance(|instance| {
-        TypedEnvBackend::restore_contract::<T>(
-            instance,
-            account_id,
-            code_hash,
-            rent_allowance,
-            filtered_keys,
-        )
-    })
-}
-
-/// Terminates the existence of the currently executed smart contract
-/// without creating a tombstone.
+/// Terminates the existence of the currently executed smart contract.
 ///
 /// This removes the calling account and transfers all remaining balance
 /// to the given beneficiary.
 ///
-/// No tombstone will be created, this function kills a contract completely!
-///
 /// # Note
 ///
 /// This function never returns. Either the termination was successful and the
diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs
index 743ecdfc35..1c2a09e281 100644
--- a/crates/env/src/backend.rs
+++ b/crates/env/src/backend.rs
@@ -23,10 +23,6 @@ use crate::{
         HashOutput,
     },
     topics::Topics,
-    types::{
-        RentParams,
-        RentStatus,
-    },
     Environment,
     Result,
 };
@@ -294,12 +290,12 @@ pub trait TypedEnvBackend: EnvBackend {
     /// For more details visit: [`caller`][`crate::caller`]
     fn caller<T: Environment>(&mut self) -> T::AccountId;
 
-    /// Returns the transferred balance for the contract execution.
+    /// Returns the transferred value for the contract execution.
     ///
     /// # Note
     ///
-    /// For more details visit: [`transferred_balance`][`crate::transferred_balance`]
-    fn transferred_balance<T: Environment>(&mut self) -> T::Balance;
+    /// For more details visit: [`transferred_value`][`crate::transferred_value`]
+    fn transferred_value<T: Environment>(&mut self) -> T::Balance;
 
     /// Returns the price for the specified amount of gas.
     ///
@@ -336,30 +332,6 @@ pub trait TypedEnvBackend: EnvBackend {
     /// For more details visit: [`balance`][`crate::balance`]
     fn balance<T: Environment>(&mut self) -> T::Balance;
 
-    /// Returns the current rent allowance for the executed contract.
-    ///
-    /// # Note
-    ///
-    /// For more details visit: [`rent_allowance`][`crate::rent_allowance`]
-    fn rent_allowance<T: Environment>(&mut self) -> T::Balance;
-
-    /// Returns information needed for rent calculations.
-    ///
-    /// # Note
-    ///
-    /// For more details visit: [`RentParams`][`crate::RentParams`]
-    fn rent_params<T: Environment>(&mut self) -> Result<RentParams<T>>;
-
-    /// Returns information about the required deposit and resulting rent.
-    ///
-    /// # Note
-    ///
-    /// For more details visit: [`RentStatus`][`crate::RentStatus`]
-    fn rent_status<T: Environment>(
-        &mut self,
-        at_refcount: Option<core::num::NonZeroU32>,
-    ) -> Result<RentStatus<T>>;
-
     /// Returns the current block number.
     ///
     /// # Note
@@ -374,13 +346,6 @@ pub trait TypedEnvBackend: EnvBackend {
     /// For more details visit: [`minimum_balance`][`crate::minimum_balance`]
     fn minimum_balance<T: Environment>(&mut self) -> T::Balance;
 
-    /// Returns the tombstone deposit of the contract chain.
-    ///
-    /// # Note
-    ///
-    /// For more details visit: [`tombstone_deposit`][`crate::tombstone_deposit`]
-    fn tombstone_deposit<T: Environment>(&mut self) -> T::Balance;
-
     /// Emits an event with the given event data.
     ///
     /// # Note
@@ -391,15 +356,6 @@ pub trait TypedEnvBackend: EnvBackend {
         T: Environment,
         Event: Topics + scale::Encode;
 
-    /// Sets the rent allowance of the executed contract to the new value.
-    ///
-    /// # Note
-    ///
-    /// For more details visit: [`set_rent_allowance`][`crate::set_rent_allowance`]
-    fn set_rent_allowance<T>(&mut self, new_value: T::Balance)
-    where
-        T: Environment;
-
     /// Invokes a contract message.
     ///
     /// # Note
@@ -441,20 +397,6 @@ pub trait TypedEnvBackend: EnvBackend {
         Args: scale::Encode,
         Salt: AsRef<[u8]>;
 
-    /// Restores a smart contract tombstone.
-    ///
-    /// # Note
-    ///
-    /// For more details visit: [`restore_contract`][`crate::restore_contract`]
-    fn restore_contract<T>(
-        &mut self,
-        account_id: T::AccountId,
-        code_hash: T::Hash,
-        rent_allowance: T::Balance,
-        filtered_keys: &[Key],
-    ) where
-        T: Environment;
-
     /// Terminates a smart contract.
     ///
     /// # Note
diff --git a/crates/env/src/call/call_builder.rs b/crates/env/src/call/call_builder.rs
index b449365bfc..049dd692c1 100644
--- a/crates/env/src/call/call_builder.rs
+++ b/crates/env/src/call/call_builder.rs
@@ -130,7 +130,7 @@ where
 /// ## Example 1: No Return Value
 ///
 /// The below example shows calling of a message of another contract that does
-/// not return any value back to its caller. The called function ...
+/// not return any value back to its caller. The called function:
 ///
 /// - has a selector equal to `0xDEADBEEF`
 /// - is provided with 5000 units of gas for its execution
@@ -165,7 +165,7 @@ where
 /// ## Example 2: With Return Value
 ///
 /// The below example shows calling of a message of another contract that does
-/// return a `i32` value back to its caller. The called function ...
+/// return a `i32` value back to its caller. The called function:
 ///
 /// - has a selector equal to `0xDEADBEEF`
 /// - is provided with 5000 units of gas for its execution
diff --git a/crates/env/src/call/create_builder.rs b/crates/env/src/call/create_builder.rs
index bd50b65fa4..adc6480d8a 100644
--- a/crates/env/src/call/create_builder.rs
+++ b/crates/env/src/call/create_builder.rs
@@ -145,7 +145,7 @@ where
 ///
 /// The below example shows instantiation of contract of type `MyContract`.
 ///
-/// The used constructor ...
+/// The used constructor:
 ///
 /// - has a selector equal to `0xDEADBEEF`
 /// - is provided with 4000 units of gas for its execution
diff --git a/crates/env/src/engine/experimental_off_chain/impls.rs b/crates/env/src/engine/experimental_off_chain/impls.rs
index 98f754a352..2e96703aac 100644
--- a/crates/env/src/engine/experimental_off_chain/impls.rs
+++ b/crates/env/src/engine/experimental_off_chain/impls.rs
@@ -35,8 +35,6 @@ use crate::{
     EnvBackend,
     Environment,
     Error,
-    RentParams,
-    RentStatus,
     Result,
     ReturnFlags,
     TypedEnvBackend,
@@ -113,7 +111,7 @@ impl From<ext::Error> for crate::Error {
             ext::Error::CodeNotFound => Self::CodeNotFound,
             ext::Error::NotCallable => Self::NotCallable,
             ext::Error::LoggingDisabled => Self::LoggingDisabled,
-            ext::Error::EcdsaRecoverFailed => Self::EcdsaRecoverFailed,
+            ext::Error::EcdsaRecoveryFailed => Self::EcdsaRecoveryFailed,
         }
     }
 }
@@ -253,11 +251,13 @@ impl EnvBackend for EnvInstance {
         message_hash: &[u8; 32],
         output: &mut [u8; 33],
     ) -> Result<()> {
-        use libsecp256k1::{
-            recover,
+        use secp256k1::{
+            recovery::{
+                RecoverableSignature,
+                RecoveryId,
+            },
             Message,
-            RecoveryId,
-            Signature,
+            Secp256k1,
         };
 
         // In most implementations, the v is just 0 or 1 internally, but 27 was added
@@ -267,20 +267,25 @@ impl EnvBackend for EnvInstance {
         } else {
             signature[64]
         };
-        let message = Message::parse(message_hash);
-        let signature = Signature::parse_standard_slice(&signature[0..64])
-            .unwrap_or_else(|error| panic!("Unable to parse the signature: {}", error));
-
-        let recovery_id = RecoveryId::parse(recovery_byte)
+        let recovery_id = RecoveryId::from_i32(recovery_byte as i32)
             .unwrap_or_else(|error| panic!("Unable to parse the recovery id: {}", error));
-
-        let pub_key = recover(&message, &signature, &recovery_id);
+        let message = Message::from_slice(message_hash).unwrap_or_else(|error| {
+            panic!("Unable to create the message from hash: {}", error)
+        });
+        let signature =
+            RecoverableSignature::from_compact(&signature[0..64], recovery_id)
+                .unwrap_or_else(|error| {
+                    panic!("Unable to parse the signature: {}", error)
+                });
+
+        let secp = Secp256k1::new();
+        let pub_key = secp.recover(&message, &signature);
         match pub_key {
             Ok(pub_key) => {
-                *output = pub_key.serialize_compressed();
+                *output = pub_key.serialize();
                 Ok(())
             }
-            Err(_) => Err(Error::EcdsaRecoverFailed),
+            Err(_) => Err(Error::EcdsaRecoveryFailed),
         }
     }
 
@@ -319,7 +324,7 @@ impl TypedEnvBackend for EnvInstance {
             })
     }
 
-    fn transferred_balance<T: Environment>(&mut self) -> T::Balance {
+    fn transferred_value<T: Environment>(&mut self) -> T::Balance {
         self.get_property::<T::Balance>(Engine::value_transferred)
             .unwrap_or_else(|error| {
                 panic!("could not read `transferred_value` property: {:?}", error)
@@ -354,30 +359,6 @@ impl TypedEnvBackend for EnvInstance {
             })
     }
 
-    fn rent_allowance<T: Environment>(&mut self) -> T::Balance {
-        self.get_property::<T::Balance>(Engine::rent_allowance)
-            .unwrap_or_else(|error| {
-                panic!("could not read `rent_allowance` property: {:?}", error)
-            })
-    }
-
-    fn rent_params<T>(&mut self) -> Result<RentParams<T>>
-    where
-        T: Environment,
-    {
-        unimplemented!("off-chain environment does not support rent params")
-    }
-
-    fn rent_status<T>(
-        &mut self,
-        _at_refcount: Option<core::num::NonZeroU32>,
-    ) -> Result<RentStatus<T>>
-    where
-        T: Environment,
-    {
-        unimplemented!("off-chain environment does not support rent status")
-    }
-
     fn block_number<T: Environment>(&mut self) -> T::BlockNumber {
         self.get_property::<T::BlockNumber>(Engine::block_number)
             .unwrap_or_else(|error| {
@@ -392,13 +373,6 @@ impl TypedEnvBackend for EnvInstance {
             })
     }
 
-    fn tombstone_deposit<T: Environment>(&mut self) -> T::Balance {
-        self.get_property::<T::Balance>(Engine::tombstone_deposit)
-            .unwrap_or_else(|error| {
-                panic!("could not read `tombstone_deposit` property: {:?}", error)
-            })
-    }
-
     fn emit_event<T, Event>(&mut self, event: Event)
     where
         T: Environment,
@@ -410,14 +384,6 @@ impl TypedEnvBackend for EnvInstance {
         self.engine.deposit_event(&enc_topics[..], enc_data);
     }
 
-    fn set_rent_allowance<T>(&mut self, new_value: T::Balance)
-    where
-        T: Environment,
-    {
-        let buffer = &scale::Encode::encode(&new_value)[..];
-        self.engine.set_rent_allowance(buffer)
-    }
-
     fn invoke_contract<T, Args>(&mut self, params: &CallParams<T, Args, ()>) -> Result<()>
     where
         T: Environment,
@@ -460,29 +426,6 @@ impl TypedEnvBackend for EnvInstance {
         unimplemented!("off-chain environment does not support contract instantiation")
     }
 
-    fn restore_contract<T>(
-        &mut self,
-        account_id: T::AccountId,
-        code_hash: T::Hash,
-        rent_allowance: T::Balance,
-        filtered_keys: &[Key],
-    ) where
-        T: Environment,
-    {
-        let enc_account_id = &scale::Encode::encode(&account_id)[..];
-        let enc_code_hash = &scale::Encode::encode(&code_hash)[..];
-        let enc_rent_allowance = &scale::Encode::encode(&rent_allowance)[..];
-
-        let filtered: Vec<&[u8]> =
-            filtered_keys.iter().map(|k| &k.as_ref()[..]).collect();
-        self.engine.restore_to(
-            enc_account_id,
-            enc_code_hash,
-            enc_rent_allowance,
-            &filtered[..],
-        );
-    }
-
     fn terminate_contract<T>(&mut self, beneficiary: T::AccountId) -> !
     where
         T: Environment,
diff --git a/crates/env/src/engine/off_chain/db/accounts.rs b/crates/env/src/engine/off_chain/db/accounts.rs
index e23f9ce474..2b36d13f09 100644
--- a/crates/env/src/engine/off_chain/db/accounts.rs
+++ b/crates/env/src/engine/off_chain/db/accounts.rs
@@ -150,7 +150,6 @@ impl AccountsDb {
         &mut self,
         account_id: T::AccountId,
         initial_balance: T::Balance,
-        rent_allowance: T::Balance,
     ) where
         T: Environment,
     {
@@ -158,7 +157,7 @@ impl AccountsDb {
             OffAccountId::new(&account_id),
             Account {
                 balance: OffBalance::new(&initial_balance),
-                kind: AccountKind::Contract(ContractAccount::new::<T>(rent_allowance)),
+                kind: AccountKind::Contract(ContractAccount::new::<T>()),
             },
         );
     }
@@ -217,28 +216,6 @@ impl Account {
         }
     }
 
-    /// Returns the rent allowance of the contract account or an error.
-    pub fn rent_allowance<T>(&self) -> Result<T::Balance>
-    where
-        T: Environment,
-    {
-        self.contract_or_err()
-            .and_then(|contract| contract.rent_allowance.decode().map_err(Into::into))
-    }
-
-    /// Sets the rent allowance for the contract account or returns an error.
-    pub fn set_rent_allowance<T>(&mut self, new_rent_allowance: T::Balance) -> Result<()>
-    where
-        T: Environment,
-    {
-        self.contract_or_err_mut().and_then(|contract| {
-            contract
-                .rent_allowance
-                .assign(&new_rent_allowance)
-                .map_err(Into::into)
-        })
-    }
-
     /// Sets the contract storage of key to the new value.
     pub fn set_storage<T>(&mut self, at: Key, new_value: &T) -> Result<()>
     where
@@ -285,20 +262,17 @@ pub enum AccountKind {
 
 /// Extraneous fields for contract accounts.
 pub struct ContractAccount {
-    /// The contract's rent allowance.
-    rent_allowance: OffBalance,
     /// The contract storage.
     pub storage: ContractStorage,
 }
 
 impl ContractAccount {
-    /// Creates a new contract account with the given initial rent allowance.
-    pub fn new<T>(rent_allowance: T::Balance) -> Self
+    /// Creates a new contract account.
+    pub fn new<T>() -> Self
     where
         T: Environment,
     {
         Self {
-            rent_allowance: OffBalance::new(&rent_allowance),
             storage: ContractStorage::new(),
         }
     }
diff --git a/crates/env/src/engine/off_chain/db/chain_spec.rs b/crates/env/src/engine/off_chain/db/chain_spec.rs
index 444accff60..5edd6b1846 100644
--- a/crates/env/src/engine/off_chain/db/chain_spec.rs
+++ b/crates/env/src/engine/off_chain/db/chain_spec.rs
@@ -17,20 +17,14 @@ use super::{
     OffBalance,
     OffTimestamp,
 };
-use crate::{
-    engine::off_chain::types::OffRentFraction,
-    Environment,
-};
-use sp_arithmetic::PerThing;
+use crate::Environment;
 
 /// The chain specification.
 pub struct ChainSpec {
     /// The current gas price.
     gas_price: OffBalance,
-    /// The minimum value an account of the chain may have.
+    /// The minimum value an account of the chain must have.
     minimum_balance: OffBalance,
-    /// The tombstone deposit.
-    tombstone_deposit: OffBalance,
     /// The targeted block time.
     block_time: OffTimestamp,
     /// The balance a contract needs to deposit per storage byte to stay alive indefinitely.
@@ -39,8 +33,6 @@ pub struct ChainSpec {
     deposit_per_contract: OffBalance,
     /// The balance a contract needs to deposit per storage item to stay alive indefinitely.
     deposit_per_storage_item: OffBalance,
-    /// The fraction of the deposit costs that should be used as rent per block.
-    rent_fraction: OffRentFraction,
 }
 
 impl ChainSpec {
@@ -49,12 +41,10 @@ impl ChainSpec {
         Self {
             gas_price: OffBalance::uninitialized(),
             minimum_balance: OffBalance::uninitialized(),
-            tombstone_deposit: OffBalance::uninitialized(),
             block_time: OffTimestamp::uninitialized(),
             deposit_per_storage_byte: OffBalance::uninitialized(),
             deposit_per_contract: OffBalance::uninitialized(),
             deposit_per_storage_item: OffBalance::uninitialized(),
-            rent_fraction: OffRentFraction::uninitialized(),
         }
     }
 
@@ -62,12 +52,10 @@ impl ChainSpec {
     pub fn reset(&mut self) {
         self.gas_price = OffBalance::uninitialized();
         self.minimum_balance = OffBalance::uninitialized();
-        self.tombstone_deposit = OffBalance::uninitialized();
         self.block_time = OffTimestamp::uninitialized();
         self.deposit_per_storage_byte = OffBalance::uninitialized();
         self.deposit_per_contract = OffBalance::uninitialized();
         self.deposit_per_storage_item = OffBalance::uninitialized();
-        self.rent_fraction = OffRentFraction::uninitialized();
     }
 
     /// Default initialization for the off-chain specification.
@@ -80,8 +68,6 @@ impl ChainSpec {
             .try_initialize::<T::Balance>(&T::Balance::from(100u32))?;
         self.minimum_balance
             .try_initialize::<T::Balance>(&T::Balance::from(42u32))?;
-        self.tombstone_deposit
-            .try_initialize::<T::Balance>(&T::Balance::from(16u32))?;
         self.block_time
             .try_initialize::<T::Timestamp>(&T::Timestamp::from(5u32))?;
 
@@ -94,9 +80,6 @@ impl ChainSpec {
             ))?;
         self.deposit_per_storage_item
             .try_initialize::<T::Balance>(&T::Balance::from(10_000u32))?;
-        self.rent_fraction.try_initialize::<T::RentFraction>(
-            &T::RentFraction::from_rational_approximation(4, 10_000),
-        )?;
 
         Ok(())
     }
@@ -125,14 +108,6 @@ impl ChainSpec {
         self.minimum_balance.decode().map_err(Into::into)
     }
 
-    /// Returns the tombstone deposit for the chain.
-    pub fn tombstone_deposit<T>(&self) -> Result<T::Balance>
-    where
-        T: Environment,
-    {
-        self.tombstone_deposit.decode().map_err(Into::into)
-    }
-
     /// Returns the targeted block time for the chain.
     pub fn block_time<T>(&self) -> Result<T::Timestamp>
     where
@@ -164,12 +139,4 @@ impl ChainSpec {
     {
         self.deposit_per_storage_item.decode().map_err(Into::into)
     }
-
-    /// The fraction of the deposit costs that should be used as rent per block.
-    pub fn rent_fraction<T>(&self) -> Result<T::RentFraction>
-    where
-        T: Environment,
-    {
-        self.rent_fraction.decode().map_err(Into::into)
-    }
 }
diff --git a/crates/env/src/engine/off_chain/hashing.rs b/crates/env/src/engine/off_chain/hashing.rs
index 73c64fb753..58879987e4 100644
--- a/crates/env/src/engine/off_chain/hashing.rs
+++ b/crates/env/src/engine/off_chain/hashing.rs
@@ -38,10 +38,7 @@ pub fn blake2b_128(input: &[u8], output: &mut [u8; 16]) {
 /// Conduct the KECCAK 256-bit hash and place the result into `output`.
 pub fn keccak_256(input: &[u8], output: &mut [u8; 32]) {
     use ::sha3::{
-        digest::{
-            generic_array::GenericArray,
-            FixedOutput as _,
-        },
+        digest::generic_array::GenericArray,
         Digest as _,
     };
     let mut hasher = ::sha3::Keccak256::new();
@@ -52,10 +49,7 @@ pub fn keccak_256(input: &[u8], output: &mut [u8; 32]) {
 /// Conduct the SHA-2 256-bit hash and place the result into `output`.
 pub fn sha2_256(input: &[u8], output: &mut [u8; 32]) {
     use ::sha2::{
-        digest::{
-            generic_array::GenericArray,
-            FixedOutput as _,
-        },
+        digest::generic_array::GenericArray,
         Digest as _,
     };
     let mut hasher = ::sha2::Sha256::new();
diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs
index 2b25b45ddf..5f21d40e2b 100644
--- a/crates/env/src/engine/off_chain/impls.rs
+++ b/crates/env/src/engine/off_chain/impls.rs
@@ -32,10 +32,6 @@ use crate::{
         Sha2x256,
     },
     topics::Topics,
-    types::{
-        RentParams,
-        RentStatus,
-    },
     EnvBackend,
     Environment,
     Error,
@@ -201,11 +197,13 @@ impl EnvBackend for EnvInstance {
         message_hash: &[u8; 32],
         output: &mut [u8; 33],
     ) -> Result<()> {
-        use libsecp256k1::{
-            recover,
+        use secp256k1::{
+            recovery::{
+                RecoverableSignature,
+                RecoveryId,
+            },
             Message,
-            RecoveryId,
-            Signature,
+            Secp256k1,
         };
 
         // In most implementations, the v is just 0 or 1 internally, but 27 was added
@@ -215,20 +213,25 @@ impl EnvBackend for EnvInstance {
         } else {
             signature[64]
         };
-        let message = Message::parse(message_hash);
-        let signature = Signature::parse_standard_slice(&signature[0..64])
-            .unwrap_or_else(|error| panic!("Unable to parse the signature: {}", error));
-
-        let recovery_id = RecoveryId::parse(recovery_byte)
+        let recovery_id = RecoveryId::from_i32(recovery_byte as i32)
             .unwrap_or_else(|error| panic!("Unable to parse the recovery id: {}", error));
-
-        let pub_key = recover(&message, &signature, &recovery_id);
+        let message = Message::from_slice(message_hash).unwrap_or_else(|error| {
+            panic!("Unable to create the message from hash: {}", error)
+        });
+        let signature =
+            RecoverableSignature::from_compact(&signature[0..64], recovery_id)
+                .unwrap_or_else(|error| {
+                    panic!("Unable to parse the signature: {}", error)
+                });
+
+        let secp = Secp256k1::new();
+        let pub_key = secp.recover(&message, &signature);
         match pub_key {
             Ok(pub_key) => {
-                *output = pub_key.serialize_compressed();
+                *output = pub_key.serialize();
                 Ok(())
             }
-            Err(_) => Err(Error::EcdsaRecoverFailed),
+            Err(_) => Err(Error::EcdsaRecoveryFailed),
         }
     }
 
@@ -308,10 +311,6 @@ impl EnvInstance {
         let contract_id = self.account_id::<T>();
         self.accounts.remove_account::<T>(contract_id);
 
-        // The on-chain implementation would set a tombstone with a code hash here
-        // and remove the contract storage subsequently. Both is not easily achievable
-        // with our current off-chain env, hence we left it out here for the moment.
-
         // Encode the result of the termination and panic with it.
         // This enables testing for the proper result and makes sure this
         // method returns `Never`.
@@ -333,12 +332,12 @@ impl TypedEnvBackend for EnvInstance {
             })
     }
 
-    fn transferred_balance<T: Environment>(&mut self) -> T::Balance {
+    fn transferred_value<T: Environment>(&mut self) -> T::Balance {
         self.exec_context()
             .expect(UNINITIALIZED_EXEC_CONTEXT)
             .transferred_value::<T>()
             .unwrap_or_else(|error| {
-                panic!("could not read `transferred_balance` property: {:?}", error)
+                panic!("could not read `transferred_value` property: {:?}", error)
             })
     }
 
@@ -384,64 +383,6 @@ impl TypedEnvBackend for EnvInstance {
             })
     }
 
-    fn rent_allowance<T: Environment>(&mut self) -> T::Balance {
-        self.callee_account()
-            .rent_allowance::<T>()
-            .unwrap_or_else(|error| {
-                panic!("could not read `rent_allowance` property: {:?}", error)
-            })
-    }
-
-    fn rent_params<T>(&mut self) -> Result<RentParams<T>>
-    where
-        T: Environment,
-    {
-        use crate::arithmetic::Saturating as _;
-
-        let total_balance = self.balance::<T>();
-
-        // the off-chain environment does currently not support reserved balance,
-        // hence we just use the total balance here.
-        let free_balance = self.balance::<T>();
-
-        let deposit_per_contract = self.chain_spec.deposit_per_contract::<T>()?;
-        let deposit_per_storage_byte = self.chain_spec.deposit_per_storage_byte::<T>()?;
-        let deposit_per_storage_item = self.chain_spec.deposit_per_storage_item::<T>()?;
-        let rent_fraction = self.chain_spec.rent_fraction::<T>()?;
-        let minimum_balance: T::Balance = self.minimum_balance::<T>();
-        let tombstone_deposit = self.tombstone_deposit::<T>();
-        let subsistence_threshold = minimum_balance.saturating_add(tombstone_deposit);
-        let rent_allowance = self.rent_allowance::<T>();
-
-        Ok(RentParams {
-            deposit_per_contract,
-            deposit_per_storage_byte,
-            deposit_per_storage_item,
-            rent_fraction,
-            subsistence_threshold,
-
-            rent_allowance,
-            total_balance,
-            free_balance,
-
-            storage_size: 0,
-            code_size: 0,
-            code_refcount: 0,
-
-            _reserved: None,
-        })
-    }
-
-    fn rent_status<T>(
-        &mut self,
-        _at_refcount: Option<core::num::NonZeroU32>,
-    ) -> Result<RentStatus<T>>
-    where
-        T: Environment,
-    {
-        unimplemented!("off-chain environment does not support rent status")
-    }
-
     fn block_number<T: Environment>(&mut self) -> T::BlockNumber {
         self.current_block()
             .expect(UNINITIALIZED_EXEC_CONTEXT)
@@ -459,14 +400,6 @@ impl TypedEnvBackend for EnvInstance {
             })
     }
 
-    fn tombstone_deposit<T: Environment>(&mut self) -> T::Balance {
-        self.chain_spec
-            .tombstone_deposit::<T>()
-            .unwrap_or_else(|error| {
-                panic!("could not read `tombstone_deposit` property: {:?}", error)
-            })
-    }
-
     fn emit_event<T, Event>(&mut self, new_event: Event)
     where
         T: Environment,
@@ -475,15 +408,6 @@ impl TypedEnvBackend for EnvInstance {
         self.emitted_events.record::<T, Event>(new_event)
     }
 
-    fn set_rent_allowance<T>(&mut self, new_rent_allowance: T::Balance)
-    where
-        T: Environment,
-    {
-        self.callee_account_mut()
-            .set_rent_allowance::<T>(new_rent_allowance)
-            .expect("could not encode rent allowance")
-    }
-
     fn invoke_contract<T, Args>(&mut self, params: &CallParams<T, Args, ()>) -> Result<()>
     where
         T: Environment,
@@ -533,18 +457,6 @@ impl TypedEnvBackend for EnvInstance {
         self.terminate_contract_impl::<T>(beneficiary)
     }
 
-    fn restore_contract<T>(
-        &mut self,
-        _account_id: T::AccountId,
-        _code_hash: T::Hash,
-        _rent_allowance: T::Balance,
-        _filtered_keys: &[Key],
-    ) where
-        T: Environment,
-    {
-        unimplemented!("off-chain environment does not support contract restoration")
-    }
-
     fn transfer<T>(&mut self, destination: T::AccountId, value: T::Balance) -> Result<()>
     where
         T: Environment,
diff --git a/crates/env/src/engine/off_chain/mod.rs b/crates/env/src/engine/off_chain/mod.rs
index 6ff31e65d8..df1e0767d1 100644
--- a/crates/env/src/engine/off_chain/mod.rs
+++ b/crates/env/src/engine/off_chain/mod.rs
@@ -194,7 +194,6 @@ impl EnvInstance {
         self.accounts.add_contract_account::<T>(
             contract_account_id.clone(),
             T::Balance::from(0u32),
-            T::Balance::from(20u32),
         );
         // Initialize the execution context for the first contract execution.
         use crate::call::Selector;
diff --git a/crates/env/src/engine/off_chain/types.rs b/crates/env/src/engine/off_chain/types.rs
index 4e86a4a6c5..55d4c1fd14 100644
--- a/crates/env/src/engine/off_chain/types.rs
+++ b/crates/env/src/engine/off_chain/types.rs
@@ -40,8 +40,6 @@ mod type_marker {
     #[derive(Debug, Clone)] pub enum OffTimestamp {}
     /// Type marker representing an environmental `BlockNumber`.
     #[derive(Debug, Clone)] pub enum BlockNumber {}
-    /// Type marker representing an environmental `RentFraction`.
-    #[derive(Debug, Clone)] pub enum RentFraction {}
 }
 
 /// Off-chain environment account ID type.
@@ -54,5 +52,3 @@ pub type OffHash = TypedEncoded<type_marker::Hash>;
 pub type OffTimestamp = TypedEncoded<type_marker::OffTimestamp>;
 /// Off-chain environment block number type.
 pub type OffBlockNumber = TypedEncoded<type_marker::BlockNumber>;
-/// Off-chain environment rent fraction type.
-pub type OffRentFraction = TypedEncoded<type_marker::RentFraction>;
diff --git a/crates/env/src/engine/on_chain/ext.rs b/crates/env/src/engine/on_chain/ext.rs
index badbb39be8..75826728b9 100644
--- a/crates/env/src/engine/on_chain/ext.rs
+++ b/crates/env/src/engine/on_chain/ext.rs
@@ -18,7 +18,6 @@
 
 use crate::ReturnFlags;
 use core::marker::PhantomData;
-use ink_primitives::Key;
 
 macro_rules! define_error_codes {
     (
@@ -74,13 +73,13 @@ define_error_codes! {
     NewContractNotFunded = 6,
     /// No code could be found at the supplied code hash.
     CodeNotFound = 7,
-    /// The account that was called is either no contract (e.g. user account) or is a tombstone.
+    /// The account that was called is no contract.
     NotCallable = 8,
      /// The call to `seal_debug_message` had no effect because debug message
     /// recording was disabled.
     LoggingDisabled = 9,
     /// ECDSA pubkey recovery failed. Most probably wrong recovery id or signature.
-    EcdsaRecoverFailed = 11,
+    EcdsaRecoveryFailed = 11,
 }
 
 /// Thin-wrapper around a `u32` representing a pointer for Wasm32.
@@ -195,7 +194,6 @@ type Result = core::result::Result<(), Error>;
 
 mod sys {
     use super::{
-        Key,
         Ptr32,
         Ptr32Mut,
         ReturnCode,
@@ -203,22 +201,6 @@ mod sys {
 
     #[link(wasm_import_module = "seal0")]
     extern "C" {
-        pub fn seal_instantiate(
-            init_code_ptr: Ptr32<[u8]>,
-            init_code_len: u32,
-            gas: u64,
-            endowment_ptr: Ptr32<[u8]>,
-            endowment_len: u32,
-            input_ptr: Ptr32<[u8]>,
-            input_len: u32,
-            address_ptr: Ptr32Mut<[u8]>,
-            address_len_ptr: Ptr32Mut<u32>,
-            output_ptr: Ptr32Mut<[u8]>,
-            output_len_ptr: Ptr32Mut<u32>,
-            salt_ptr: Ptr32<[u8]>,
-            salt_len: u32,
-        ) -> ReturnCode;
-
         pub fn seal_transfer(
             account_id_ptr: Ptr32<[u8]>,
             account_id_len: u32,
@@ -245,18 +227,6 @@ mod sys {
         ) -> ReturnCode;
         pub fn seal_clear_storage(key_ptr: Ptr32<[u8]>);
 
-        pub fn seal_restore_to(
-            dest_ptr: Ptr32<[u8]>,
-            dest_len: u32,
-            code_hash_ptr: Ptr32<[u8]>,
-            code_hash_len: u32,
-            rent_allowance_ptr: Ptr32<[u8]>,
-            rent_allowance_len: u32,
-            delta_ptr: Ptr32<[Key]>,
-            delta_count: u32,
-        );
-        pub fn seal_terminate(beneficiary_ptr: Ptr32<[u8]>, beneficiary_len: u32) -> !;
-
         pub fn seal_call_chain_extension(
             func_id: u32,
             input_ptr: Ptr32<[u8]>,
@@ -286,20 +256,10 @@ mod sys {
             output_len_ptr: Ptr32Mut<u32>,
         );
         pub fn seal_now(output_ptr: Ptr32Mut<[u8]>, output_len_ptr: Ptr32Mut<u32>);
-        pub fn seal_rent_allowance(
-            output_ptr: Ptr32Mut<[u8]>,
-            output_len_ptr: Ptr32Mut<u32>,
-        );
         pub fn seal_minimum_balance(
             output_ptr: Ptr32Mut<[u8]>,
             output_len_ptr: Ptr32Mut<u32>,
         );
-        pub fn seal_tombstone_deposit(
-            output_ptr: Ptr32Mut<[u8]>,
-            output_len_ptr: Ptr32Mut<u32>,
-        );
-
-        pub fn seal_set_rent_allowance(value_ptr: Ptr32<[u8]>, value_len: u32);
 
         pub fn seal_hash_keccak_256(
             input_ptr: Ptr32<[u8]>,
@@ -328,16 +288,29 @@ mod sys {
 
     #[link(wasm_import_module = "seal1")]
     extern "C" {
+        pub fn seal_instantiate(
+            init_code_ptr: Ptr32<[u8]>,
+            gas: u64,
+            endowment_ptr: Ptr32<[u8]>,
+            input_ptr: Ptr32<[u8]>,
+            input_len: u32,
+            address_ptr: Ptr32Mut<[u8]>,
+            address_len_ptr: Ptr32Mut<u32>,
+            output_ptr: Ptr32Mut<[u8]>,
+            output_len_ptr: Ptr32Mut<u32>,
+            salt_ptr: Ptr32<[u8]>,
+            salt_len: u32,
+        ) -> ReturnCode;
+
+        pub fn seal_terminate(beneficiary_ptr: Ptr32<[u8]>) -> !;
+
         pub fn seal_random(
             subject_ptr: Ptr32<[u8]>,
             subject_len: u32,
             output_ptr: Ptr32Mut<[u8]>,
             output_len_ptr: Ptr32Mut<u32>,
         );
-    }
 
-    #[link(wasm_import_module = "__unstable__")]
-    extern "C" {
         pub fn seal_call(
             flags: u32,
             callee_ptr: Ptr32<[u8]>,
@@ -348,18 +321,10 @@ mod sys {
             output_ptr: Ptr32Mut<[u8]>,
             output_len_ptr: Ptr32Mut<u32>,
         ) -> ReturnCode;
+    }
 
-        pub fn seal_rent_params(
-            output_ptr: Ptr32Mut<[u8]>,
-            output_len_ptr: Ptr32Mut<u32>,
-        );
-
-        pub fn seal_rent_status(
-            at_refcount: u32,
-            output_ptr: Ptr32Mut<[u8]>,
-            output_len_ptr: Ptr32Mut<u32>,
-        );
-
+    #[link(wasm_import_module = "__unstable__")]
+    extern "C" {
         pub fn seal_ecdsa_recover(
             // 65 bytes of ecdsa signature
             signature_ptr: Ptr32<[u8]>,
@@ -391,10 +356,8 @@ pub fn instantiate(
         unsafe {
             sys::seal_instantiate(
                 Ptr32::from_slice(code_hash),
-                code_hash.len() as u32,
                 gas_limit,
                 Ptr32::from_slice(endowment),
-                endowment.len() as u32,
                 Ptr32::from_slice(input),
                 input.len() as u32,
                 Ptr32Mut::from_slice(out_address),
@@ -490,41 +453,8 @@ pub fn get_storage(key: &[u8], output: &mut &mut [u8]) -> Result {
     ret_code.into()
 }
 
-/// Restores a tombstone to the original smart contract.
-///
-/// # Params
-///
-/// - `account_id`: Encoded bytes of the `AccountId` of the to-be-restored contract.
-/// - `code_hash`: Encoded code hash of the to-be-restored contract.
-/// - `rent_allowance`: The encoded rent allowance of the restored contract
-///                     upon successful restoration.
-/// - `filtered_keys`: Storage keys that will be ignored for the tombstone hash
-///                    match calculation that decide whether the original contract
-///                    storage and the storage of the restorer contract is equal.
-pub fn restore_to(
-    account_id: &[u8],
-    code_hash: &[u8],
-    rent_allowance: &[u8],
-    filtered_keys: &[Key],
-) {
-    unsafe {
-        sys::seal_restore_to(
-            Ptr32::from_slice(account_id),
-            account_id.len() as u32,
-            Ptr32::from_slice(code_hash),
-            code_hash.len() as u32,
-            Ptr32::from_slice(rent_allowance),
-            rent_allowance.len() as u32,
-            Ptr32::from_slice(filtered_keys),
-            filtered_keys.len() as u32,
-        )
-    }
-}
-
 pub fn terminate(beneficiary: &[u8]) -> ! {
-    unsafe {
-        sys::seal_terminate(Ptr32::from_slice(beneficiary), beneficiary.len() as u32)
-    }
+    unsafe { sys::seal_terminate(Ptr32::from_slice(beneficiary)) }
 }
 
 pub fn call_chain_extension(func_id: u32, input: &[u8], output: &mut &mut [u8]) -> u32 {
@@ -593,9 +523,7 @@ impl_seal_wrapper_for! {
     (gas_left => seal_gas_left),
     (value_transferred => seal_value_transferred),
     (now => seal_now),
-    (rent_allowance => seal_rent_allowance),
     (minimum_balance => seal_minimum_balance),
-    (tombstone_deposit => seal_tombstone_deposit),
 }
 
 pub fn weight_to_fee(gas: u64, output: &mut &mut [u8]) {
@@ -612,37 +540,6 @@ pub fn weight_to_fee(gas: u64, output: &mut &mut [u8]) {
     extract_from_slice(output, output_len as usize);
 }
 
-pub fn set_rent_allowance(value: &[u8]) {
-    unsafe { sys::seal_set_rent_allowance(Ptr32::from_slice(value), value.len() as u32) }
-}
-
-pub fn rent_params(output: &mut &mut [u8]) {
-    let mut output_len = output.len() as u32;
-    {
-        unsafe {
-            sys::seal_rent_params(
-                Ptr32Mut::from_slice(output),
-                Ptr32Mut::from_ref(&mut output_len),
-            )
-        };
-    }
-    extract_from_slice(output, output_len as usize);
-}
-
-pub fn rent_status(at_refcount: Option<core::num::NonZeroU32>, output: &mut &mut [u8]) {
-    let mut output_len = output.len() as u32;
-    {
-        unsafe {
-            sys::seal_rent_status(
-                at_refcount.map_or(0, |rc| rc.get()),
-                Ptr32Mut::from_slice(output),
-                Ptr32Mut::from_ref(&mut output_len),
-            )
-        };
-    }
-    extract_from_slice(output, output_len as usize);
-}
-
 pub fn random(subject: &[u8], output: &mut &mut [u8]) {
     let mut output_len = output.len() as u32;
     {
diff --git a/crates/env/src/engine/on_chain/impls.rs b/crates/env/src/engine/on_chain/impls.rs
index 990cabceb6..2c2ff91742 100644
--- a/crates/env/src/engine/on_chain/impls.rs
+++ b/crates/env/src/engine/on_chain/impls.rs
@@ -36,10 +36,6 @@ use crate::{
         Topics,
         TopicsBuilderBackend,
     },
-    types::{
-        RentParams,
-        RentStatus,
-    },
     Clear,
     EnvBackend,
     Environment,
@@ -112,7 +108,7 @@ impl From<ext::Error> for Error {
             ext::Error::CodeNotFound => Self::CodeNotFound,
             ext::Error::NotCallable => Self::NotCallable,
             ext::Error::LoggingDisabled => Self::LoggingDisabled,
-            ext::Error::EcdsaRecoverFailed => Self::EcdsaRecoverFailed,
+            ext::Error::EcdsaRecoveryFailed => Self::EcdsaRecoveryFailed,
         }
     }
 }
@@ -361,7 +357,7 @@ impl TypedEnvBackend for EnvInstance {
         self.get_property_inplace::<T::AccountId>(ext::caller)
     }
 
-    fn transferred_balance<T: Environment>(&mut self) -> T::Balance {
+    fn transferred_value<T: Environment>(&mut self) -> T::Balance {
         self.get_property_little_endian::<T::Balance>(ext::value_transferred)
     }
 
@@ -381,10 +377,6 @@ impl TypedEnvBackend for EnvInstance {
         self.get_property_little_endian::<T::Balance>(ext::balance)
     }
 
-    fn rent_allowance<T: Environment>(&mut self) -> T::Balance {
-        self.get_property_little_endian::<T::Balance>(ext::rent_allowance)
-    }
-
     fn block_number<T: Environment>(&mut self) -> T::BlockNumber {
         self.get_property_little_endian::<T::BlockNumber>(ext::block_number)
     }
@@ -393,10 +385,6 @@ impl TypedEnvBackend for EnvInstance {
         self.get_property_little_endian::<T::Balance>(ext::minimum_balance)
     }
 
-    fn tombstone_deposit<T: Environment>(&mut self) -> T::Balance {
-        self.get_property_little_endian::<T::Balance>(ext::tombstone_deposit)
-    }
-
     fn emit_event<T, Event>(&mut self, event: Event)
     where
         T: Environment,
@@ -408,33 +396,6 @@ impl TypedEnvBackend for EnvInstance {
         ext::deposit_event(enc_topics, enc_data);
     }
 
-    fn set_rent_allowance<T>(&mut self, new_value: T::Balance)
-    where
-        T: Environment,
-    {
-        let buffer = self.scoped_buffer().take_encoded(&new_value);
-        ext::set_rent_allowance(&buffer[..])
-    }
-
-    fn rent_params<T>(&mut self) -> Result<RentParams<T>>
-    where
-        T: Environment,
-    {
-        self.get_property::<RentParams<T>>(ext::rent_params)
-    }
-
-    fn rent_status<T>(
-        &mut self,
-        at_refcount: Option<core::num::NonZeroU32>,
-    ) -> Result<RentStatus<T>>
-    where
-        T: Environment,
-    {
-        let output = &mut self.scoped_buffer().take_rest();
-        ext::rent_status(at_refcount, output);
-        scale::Decode::decode(&mut &output[..]).map_err(Into::into)
-    }
-
     fn invoke_contract<T, Args>(
         &mut self,
         call_params: &CallParams<T, Args, ()>,
@@ -495,27 +456,6 @@ impl TypedEnvBackend for EnvInstance {
         Ok(account_id)
     }
 
-    fn restore_contract<T>(
-        &mut self,
-        account_id: T::AccountId,
-        code_hash: T::Hash,
-        rent_allowance: T::Balance,
-        filtered_keys: &[Key],
-    ) where
-        T: Environment,
-    {
-        let mut scope = self.scoped_buffer();
-        let enc_account_id = scope.take_encoded(&account_id);
-        let enc_code_hash = scope.take_encoded(&code_hash);
-        let enc_rent_allowance = scope.take_encoded(&rent_allowance);
-        ext::restore_to(
-            enc_account_id,
-            enc_code_hash,
-            enc_rent_allowance,
-            filtered_keys,
-        );
-    }
-
     fn terminate_contract<T>(&mut self, beneficiary: T::AccountId) -> !
     where
         T: Environment,
diff --git a/crates/env/src/error.rs b/crates/env/src/error.rs
index a6b9be65de..5fdfb3141b 100644
--- a/crates/env/src/error.rs
+++ b/crates/env/src/error.rs
@@ -42,7 +42,7 @@ pub enum Error {
     NewContractNotFunded,
     /// No code could be found at the supplied code hash.
     CodeNotFound,
-    /// The account that was called is either no contract (e.g. user account) or is a tombstone.
+    /// The account that was called is no contract, but a plain account.
     NotCallable,
     /// An unknown error has occurred.
     Unknown,
@@ -50,7 +50,7 @@ pub enum Error {
     /// recording was disabled.
     LoggingDisabled,
     /// ECDSA pubkey recovery failed. Most probably wrong recovery id or signature.
-    EcdsaRecoverFailed,
+    EcdsaRecoveryFailed,
 }
 
 /// A result of environmental operations.
diff --git a/crates/env/src/lib.rs b/crates/env/src/lib.rs
index 609cd35c62..2ac97464ae 100644
--- a/crates/env/src/lib.rs
+++ b/crates/env/src/lib.rs
@@ -43,6 +43,10 @@
     unused_extern_crates
 )]
 
+#[cfg(all(not(feature = "std"), target_arch = "wasm32"))]
+#[allow(unused_extern_crates)]
+extern crate rlibc;
+
 #[cfg(all(not(feature = "std"), target_arch = "wasm32"))]
 #[allow(unused_variables)]
 #[panic_handler]
@@ -103,9 +107,6 @@ pub use self::{
         FromLittleEndian,
         Hash,
         NoChainExtension,
-        Perbill,
-        RentParams,
-        RentStatus,
     },
 };
 
diff --git a/crates/env/src/types.rs b/crates/env/src/types.rs
index fff2d3a886..a2d07be1c7 100644
--- a/crates/env/src/types.rs
+++ b/crates/env/src/types.rs
@@ -43,8 +43,6 @@ use scale::{
 };
 #[cfg(feature = "std")]
 use scale_info::TypeInfo;
-use sp_arithmetic::PerThing;
-pub use sp_arithmetic::Perbill;
 
 /// Allows to instantiate a type from its little-endian bytes representation.
 pub trait FromLittleEndian {
@@ -167,9 +165,6 @@ pub trait Environment {
     ///
     /// [chain_extension]: https://paritytech.github.io/ink/ink_lang/attr.chain_extension.html
     type ChainExtension;
-
-    /// The fraction of the deposit costs that should be used as rent per block.
-    type RentFraction: 'static + scale::Codec + Clone + PartialEq + Eq + Ord + PerThing;
 }
 
 /// Placeholder for chains that have no defined chain extension.
@@ -189,7 +184,6 @@ impl Environment for DefaultEnvironment {
     type Timestamp = Timestamp;
     type BlockNumber = BlockNumber;
     type ChainExtension = NoChainExtension;
-    type RentFraction = RentFraction;
 }
 
 /// The default balance type.
@@ -201,9 +195,6 @@ pub type Timestamp = u64;
 /// The default block number type.
 pub type BlockNumber = u32;
 
-/// The default rent fraction type.
-pub type RentFraction = Perbill;
-
 /// The default environment `AccountId` type.
 ///
 /// # Note
@@ -338,106 +329,3 @@ impl Clear for Hash {
         Self(<[u8; 32] as Clear>::clear())
     }
 }
-
-/// Information needed for rent calculations that can be requested by a contract.
-#[derive(scale::Decode)]
-#[cfg_attr(test, derive(Debug, PartialEq))]
-pub struct RentParams<T: Environment> {
-    /// The total balance of the contract. Includes the balance transferred from the caller.
-    pub total_balance: T::Balance,
-
-    /// The free balance of the contract, i.e. the portion of the contract's balance
-    /// that is not reserved. Includes the balance transferred from the caller.
-    pub free_balance: T::Balance,
-
-    /// 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 subsistence_threshold: T::Balance,
-
-    /// The balance every contract needs to deposit to stay alive indefinitely.
-    ///
-    /// This is different from the tombstone deposit 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.
-    pub deposit_per_contract: T::Balance,
-
-    /// 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.
-    pub deposit_per_storage_byte: T::Balance,
-
-    /// The balance a contract needs to deposit per storage item to stay alive indefinitely.
-    ///
-    /// It works as [`Self::deposit_per_storage_byte`] but for storage items.
-    pub deposit_per_storage_item: T::Balance,
-
-    /// The contract's rent allowance, the rent mechanism cannot consume more than this.
-    pub rent_allowance: T::Balance,
-
-    /// The fraction of the deposit costs that should be used as rent per block.
-    ///
-    /// When a contract does not have 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 costs.
-    pub rent_fraction: T::RentFraction,
-
-    /// 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,
-
-    /// Sum of instrumented and pristine code length.
-    pub code_size: u32,
-
-    /// The number of contracts using this executable.
-    pub code_refcount: u32,
-
-    /// Reserved for backwards compatible changes to this data structure.
-    pub _reserved: Option<()>,
-}
-
-/// Information about the required deposit and resulting rent.
-///
-/// The easiest way to guarantee that a contract stays alive is to assert that
-/// `max_rent == 0` at the **end** of a contract's execution.
-///
-/// # Note
-///
-/// The `current_*` fields do **not** consider changes to the code's `refcount`
-/// made during the currently running call.
-#[derive(scale::Decode)]
-#[cfg_attr(test, derive(Debug, PartialEq))]
-pub struct RentStatus<T: Environment> {
-    /// Required deposit assuming that this contract is the only user of its code.
-    pub max_deposit: T::Balance,
-
-    /// Required deposit assuming the code's current `refcount`.
-    pub current_deposit: T::Balance,
-
-    /// Required deposit assuming the specified `refcount` (`None` if `0` is supplied).
-    pub custom_refcount_deposit: Option<T::Balance>,
-
-    /// Rent that is paid assuming that the contract is the only user of its code.
-    pub max_rent: T::Balance,
-
-    /// Rent that is paid given the code's current refcount.
-    pub current_rent: T::Balance,
-
-    /// Rent that is paid assuming the specified refcount (`None` if `0` is supplied).
-    pub custom_refcount_rent: Option<T::Balance>,
-
-    /// Reserved for backwards compatible changes to this data structure.
-    pub _reserved: Option<()>,
-}
diff --git a/crates/eth_compatibility/Cargo.toml b/crates/eth_compatibility/Cargo.toml
index b6681d6876..a0f6b2d08f 100644
--- a/crates/eth_compatibility/Cargo.toml
+++ b/crates/eth_compatibility/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_eth_compatibility"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
@@ -15,7 +15,12 @@ categories = ["no-std", "embedded"]
 include = ["Cargo.toml", "src/**/*.rs", "/README.md", "/LICENSE"]
 
 [dependencies]
-ink_env = { version = "3.0.0-rc6", path = "../env", default-features = false }
+ink_env = { version = "3.0.0-rc7", path = "../env", default-features = false }
+
+[target.'cfg(not(target_os = "windows"))'.dependencies]
+# We do not include `libsecp256k1` on Windows, since it's incompatible.
+# We have https://github.com/paritytech/ink/issues/1068 for removing
+# this dependency altogether.
 libsecp256k1 = { version = "0.7.0", default-features = false }
 
 [features]
diff --git a/crates/eth_compatibility/src/lib.rs b/crates/eth_compatibility/src/lib.rs
index 827384ed3b..c67cb9788b 100644
--- a/crates/eth_compatibility/src/lib.rs
+++ b/crates/eth_compatibility/src/lib.rs
@@ -91,6 +91,11 @@ impl ECDSAPublicKey {
     ///
     /// assert_eq!(pub_key.to_eth_address().as_ref(), EXPECTED_ETH_ADDRESS.as_ref());
     /// ```
+    // We do not include this function on Windows, since it depends on `libsecp256k1`,
+    // which is incompatible with Windows.
+    // We have https://github.com/paritytech/ink/issues/1068 for removing this
+    // dependency altogether.
+    #[cfg(not(target_os = "windows"))]
     pub fn to_eth_address(&self) -> EthereumAddress {
         use ink_env::hash;
         use libsecp256k1::PublicKey;
@@ -114,7 +119,7 @@ impl ECDSAPublicKey {
     }
 
     /// Returns the default Substrate's `AccountId` from the ECDSA compressed public key.
-    /// It hashes the compressed public key with the blake2b256 algorithm like in substrate.
+    /// It hashes the compressed public key with the `blake2b_256` algorithm like in substrate.
     ///
     /// # Example
     ///
diff --git a/crates/lang/Cargo.toml b/crates/lang/Cargo.toml
index 033957a79d..f0d424eccb 100644
--- a/crates/lang/Cargo.toml
+++ b/crates/lang/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_lang"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>", "Robin Freyler <robin@parity.io>"]
 edition = "2021"
 
@@ -15,20 +15,20 @@ categories = ["no-std", "embedded"]
 include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]
 
 [dependencies]
-ink_env = { version = "3.0.0-rc6", path = "../env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../storage", default-features = false }
-ink_primitives = { version = "3.0.0-rc6", path = "../primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../metadata", default-features = false, optional = true }
-ink_prelude = { version = "3.0.0-rc6", path = "../prelude", default-features = false }
-ink_eth_compatibility = { version = "3.0.0-rc6", path = "../eth_compatibility", default-features = false }
-ink_lang_macro = { version = "3.0.0-rc6", path = "macro", default-features = false }
+ink_env = { version = "3.0.0-rc7", path = "../env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../storage", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../metadata", default-features = false, optional = true }
+ink_prelude = { version = "3.0.0-rc7", path = "../prelude", default-features = false }
+ink_eth_compatibility = { version = "3.0.0-rc7", path = "../eth_compatibility", default-features = false }
+ink_lang_macro = { version = "3.0.0-rc7", path = "macro", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2.3", default-features = false, features = ["derive", "full"] }
 derive_more = { version = "0.99", default-features = false, features = ["from"] }
 
 [dev-dependencies]
-ink_lang_ir = { version = "3.0.0-rc6", path = "ir" }
-ink_metadata = { version = "3.0.0-rc6", default-features = false, path = "../metadata" }
+ink_lang_ir = { version = "3.0.0-rc7", path = "ir" }
+ink_metadata = { version = "3.0.0-rc7", default-features = false, path = "../metadata" }
 
 trybuild = { version = "1.0.52", features = ["diff"] }
 # Required for the doctest of `env_access::EnvAccess::instantiate_contract`
diff --git a/crates/lang/codegen/Cargo.toml b/crates/lang/codegen/Cargo.toml
index 0c4db60d99..28d34563e6 100644
--- a/crates/lang/codegen/Cargo.toml
+++ b/crates/lang/codegen/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_lang_codegen"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>", "Robin Freyler <robin@parity.io>"]
 edition = "2021"
 
@@ -18,7 +18,7 @@ include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]
 name = "ink_lang_codegen"
 
 [dependencies]
-ir = { version = "3.0.0-rc6", package = "ink_lang_ir", path = "../ir", default-features = false }
+ir = { version = "3.0.0-rc7", package = "ink_lang_ir", path = "../ir", default-features = false }
 quote = "1"
 syn = { version = "1.0", features = ["parsing", "full", "extra-traits"] }
 proc-macro2 = "1.0"
diff --git a/crates/lang/codegen/src/generator/as_dependency/mod.rs b/crates/lang/codegen/src/generator/as_dependency/mod.rs
index 4a6acacadb..aef4011579 100644
--- a/crates/lang/codegen/src/generator/as_dependency/mod.rs
+++ b/crates/lang/codegen/src/generator/as_dependency/mod.rs
@@ -27,7 +27,7 @@ use derive_more::From;
 use proc_macro2::TokenStream as TokenStream2;
 use quote::quote;
 
-/// Generates `#[cfg(..)]` code to guard against compilation under `ink-as-dependency`.
+/// Generates `#[cfg(...)]` code to guard against compilation under `ink-as-dependency`.
 #[derive(From)]
 pub struct NotAsDependencyCfg<'a> {
     contract: &'a ir::Contract,
@@ -44,7 +44,7 @@ impl GenerateCode for NotAsDependencyCfg<'_> {
     }
 }
 
-/// Generates `#[cfg(..)]` code to only allow compilation when `ink-as-dependency` is enabled.
+/// Generates `#[cfg(...)]` code to only allow compilation when `ink-as-dependency` is enabled.
 ///
 /// The `ink-as-dependency` can be enabled mainly by 2 different ways:
 ///
diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs
index 3937f21455..edb233ae58 100644
--- a/crates/lang/codegen/src/generator/dispatch.rs
+++ b/crates/lang/codegen/src/generator/dispatch.rs
@@ -97,8 +97,7 @@ impl Dispatch<'_> {
         self.contract
             .module()
             .impls()
-            .map(|item_impl| item_impl.iter_constructors())
-            .flatten()
+            .flat_map(|item_impl| item_impl.iter_constructors())
             .count()
     }
 
@@ -109,11 +108,28 @@ impl Dispatch<'_> {
         self.contract
             .module()
             .impls()
-            .map(|item_impl| item_impl.iter_messages())
-            .flatten()
+            .flat_map(|item_impl| item_impl.iter_messages())
             .count()
     }
 
+    /// Returns the index of the ink! message which has a wildcard selector, if existent.
+    fn query_wildcard_message(&self) -> Option<usize> {
+        self.contract
+            .module()
+            .impls()
+            .flat_map(|item_impl| item_impl.iter_messages())
+            .position(|item| item.has_wildcard_selector())
+    }
+
+    /// Returns the index of the ink! constructor which has a wildcard selector, if existent.
+    fn query_wildcard_constructor(&self) -> Option<usize> {
+        self.contract
+            .module()
+            .impls()
+            .flat_map(|item_impl| item_impl.iter_constructors())
+            .position(|item| item.has_wildcard_selector())
+    }
+
     /// Generates code for the [`ink_lang::ContractDispatchables`] trait implementation.
     ///
     /// This trait implementation stores information of how many dispatchable
@@ -146,8 +162,7 @@ impl Dispatch<'_> {
             .module()
             .impls()
             .filter(|item_impl| item_impl.trait_path().is_none())
-            .map(|item_impl| item_impl.iter_messages())
-            .flatten()
+            .flat_map(|item_impl| item_impl.iter_messages())
             .map(|message| {
                 let span = message.span();
                 message_spans.push(span);
@@ -213,8 +228,7 @@ impl Dispatch<'_> {
             .contract
             .module()
             .impls()
-            .map(|item_impl| item_impl.iter_constructors())
-            .flatten()
+            .flat_map(|item_impl| item_impl.iter_constructors())
             .map(|constructor| {
                 let span = constructor.span();
                 constructor_spans.push(span);
@@ -249,8 +263,7 @@ impl Dispatch<'_> {
             .contract
             .module()
             .impls()
-            .map(|item_impl| item_impl.iter_constructors())
-            .flatten()
+            .flat_map(|item_impl| item_impl.iter_constructors())
             .map(|constructor| {
                 let constructor_span = constructor.span();
                 let constructor_ident = constructor.ident();
@@ -289,8 +302,7 @@ impl Dispatch<'_> {
             .module()
             .impls()
             .filter(|item_impl| item_impl.trait_path().is_none())
-            .map(|item_impl| item_impl.iter_messages())
-            .flatten()
+            .flat_map(|item_impl| item_impl.iter_messages())
             .map(|message| {
                 let message_span = message.span();
                 let message_ident = message.ident();
@@ -413,6 +425,7 @@ impl Dispatch<'_> {
 
             #[cfg(not(test))]
             #[no_mangle]
+            #[allow(clippy::nonminimal_bool)]
             fn call() {
                 if !#any_message_accept_payment {
                     ::ink_lang::codegen::deny_payment::<<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env>()
@@ -495,6 +508,30 @@ impl Dispatch<'_> {
                 }
             )
         });
+        let possibly_wildcard_selector_constructor = match self
+            .query_wildcard_constructor()
+        {
+            Some(wildcard_index) => {
+                let constructor_span = constructor_spans[wildcard_index];
+                let constructor_ident = constructor_variant_ident(wildcard_index);
+                let constructor_input = expand_constructor_input(
+                    constructor_span,
+                    storage_ident,
+                    wildcard_index,
+                );
+                quote! {
+                    ::core::result::Result::Ok(Self::#constructor_ident(
+                        <#constructor_input as ::scale::Decode>::decode(input)
+                            .map_err(|_| ::ink_lang::reflect::DispatchError::InvalidParameters)?
+                    ))
+                }
+            }
+            None => {
+                quote! {
+                    ::core::result::Result::Err(::ink_lang::reflect::DispatchError::UnknownSelector)
+                }
+            }
+        };
         let constructor_execute = (0..count_constructors).map(|index| {
             let constructor_span = constructor_spans[index];
             let constructor_ident = constructor_variant_ident(index);
@@ -537,9 +574,7 @@ impl Dispatch<'_> {
                             .map_err(|_| ::ink_lang::reflect::DispatchError::InvalidSelector)?
                         {
                             #( #constructor_match , )*
-                            _invalid => ::core::result::Result::Err(
-                                ::ink_lang::reflect::DispatchError::UnknownSelector
-                            )
+                            _invalid => #possibly_wildcard_selector_constructor
                         }
                     }
                 }
@@ -631,6 +666,25 @@ impl Dispatch<'_> {
                 }
             )
         });
+        let possibly_wildcard_selector_message = match self.query_wildcard_message() {
+            Some(wildcard_index) => {
+                let message_span = message_spans[wildcard_index];
+                let message_ident = message_variant_ident(wildcard_index);
+                let message_input =
+                    expand_message_input(message_span, storage_ident, wildcard_index);
+                quote! {
+                    ::core::result::Result::Ok(Self::#message_ident(
+                        <#message_input as ::scale::Decode>::decode(input)
+                            .map_err(|_| ::ink_lang::reflect::DispatchError::InvalidParameters)?
+                    ))
+                }
+            }
+            None => {
+                quote! {
+                    ::core::result::Result::Err(::ink_lang::reflect::DispatchError::UnknownSelector)
+                }
+            }
+        };
         let any_message_accept_payment =
             self.any_message_accepts_payment_expr(message_spans);
         let message_execute = (0..count_messages).map(|index| {
@@ -713,9 +767,7 @@ impl Dispatch<'_> {
                             .map_err(|_| ::ink_lang::reflect::DispatchError::InvalidSelector)?
                         {
                             #( #message_match , )*
-                            _invalid => ::core::result::Result::Err(
-                                ::ink_lang::reflect::DispatchError::UnknownSelector
-                            )
+                            _invalid => #possibly_wildcard_selector_message
                         }
                     }
                 }
diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs
index 28fe7fb6cc..5e6bb42759 100644
--- a/crates/lang/codegen/src/generator/item_impls.rs
+++ b/crates/lang/codegen/src/generator/item_impls.rs
@@ -48,7 +48,7 @@ impl GenerateCode for ItemImpls<'_> {
         let trait_message_property_guards = self.generate_trait_message_property_guards();
         let use_emit_event =
             self.contract.module().events().next().is_some().then(|| {
-                // Required to make `self.env().emit_event(..)` syntax available.
+                // Required to make `self.env().emit_event(...)` syntax available.
                 quote! { use ::ink_lang::codegen::EmitEvent as _; }
             });
         quote! {
@@ -126,8 +126,7 @@ impl ItemImpls<'_> {
             .contract
             .module()
             .impls()
-            .map(|item_impl| item_impl.iter_constructors())
-            .flatten()
+            .flat_map(|item_impl| item_impl.iter_constructors())
             .map(|constructor| {
                 let constructor_span = constructor.span();
                 let constructor_inputs = constructor.inputs().map(|input| {
@@ -147,8 +146,7 @@ impl ItemImpls<'_> {
             .contract
             .module()
             .impls()
-            .map(|item_impl| item_impl.iter_messages())
-            .flatten()
+            .flat_map(|item_impl| item_impl.iter_messages())
             .map(|message| {
                 let message_span = message.span();
                 let message_inputs = message.inputs().map(|input| {
diff --git a/crates/lang/codegen/src/generator/metadata.rs b/crates/lang/codegen/src/generator/metadata.rs
index 81c3a94e8a..d76c113e2b 100644
--- a/crates/lang/codegen/src/generator/metadata.rs
+++ b/crates/lang/codegen/src/generator/metadata.rs
@@ -108,8 +108,7 @@ impl Metadata<'_> {
         self.contract
             .module()
             .impls()
-            .map(|item_impl| item_impl.iter_constructors())
-            .flatten()
+            .flat_map(|item_impl| item_impl.iter_constructors())
             .map(|constructor| Self::generate_constructor(constructor))
     }
 
@@ -127,7 +126,7 @@ impl Metadata<'_> {
         let ident = constructor.ident();
         let args = constructor.inputs().map(Self::generate_dispatch_argument);
         quote_spanned!(span=>
-            ::ink_metadata::ConstructorSpec::from_name(::core::stringify!(#ident))
+            ::ink_metadata::ConstructorSpec::from_label(::core::stringify!(#ident))
                 .selector([
                     #( #selector_bytes ),*
                 ])
@@ -200,8 +199,7 @@ impl Metadata<'_> {
             .module()
             .impls()
             .filter(|item_impl| item_impl.trait_path().is_none())
-            .map(|item_impl| item_impl.iter_messages())
-            .flatten()
+            .flat_map(|item_impl| item_impl.iter_messages())
             .map(|message| {
                 let span = message.span();
                 let docs = message
@@ -216,7 +214,7 @@ impl Metadata<'_> {
                 let args = message.inputs().map(Self::generate_dispatch_argument);
                 let ret_ty = Self::generate_return_type(message.output());
                 quote_spanned!(span =>
-                    ::ink_metadata::MessageSpec::from_name(::core::stringify!(#ident))
+                    ::ink_metadata::MessageSpec::from_label(::core::stringify!(#ident))
                         .selector([
                             #( #selector_bytes ),*
                         ])
@@ -275,11 +273,9 @@ impl Metadata<'_> {
                         as ::ink_lang::reflect::TraitMessageInfo<#local_id>>::SELECTOR
                 }};
                 let ret_ty = Self::generate_return_type(message.output());
+                let label = [trait_ident.to_string(), message_ident.to_string()].join("::");
                 quote_spanned!(message_span=>
-                    ::ink_metadata::MessageSpec::from_trait_and_name(
-                        ::core::stringify!(#trait_ident),
-                        ::core::stringify!(#message_ident)
-                    )
+                    ::ink_metadata::MessageSpec::from_label(#label)
                         .selector(#selector)
                         .args([
                             #( #message_args ),*
@@ -384,13 +380,15 @@ mod tests {
         assert_eq!(
             extract_doc_attributes(&[syn::parse_quote!(
                 /**
-                 * Multi-line comments ...
-                 * May span many lines
+                 * Multi-line comments
+                 * may span many,
+                 * many lines
                  */
             )]),
             vec![r"
-                 * Multi-line comments ...
-                 * May span many lines
+                 * Multi-line comments
+                 * may span many,
+                 * many lines
                  "
             .to_string()],
         );
diff --git a/crates/lang/codegen/src/generator/storage.rs b/crates/lang/codegen/src/generator/storage.rs
index d7f68e5f0f..7c678595dc 100644
--- a/crates/lang/codegen/src/generator/storage.rs
+++ b/crates/lang/codegen/src/generator/storage.rs
@@ -35,7 +35,7 @@ impl GenerateCode for Storage<'_> {
         let storage_struct = self.generate_storage_struct();
         let use_emit_event =
             self.contract.module().events().next().is_some().then(|| {
-                // Required to allow for `self.env().emit_event(..)` in messages and constructors.
+                // Required to allow for `self.env().emit_event(...)` in messages and constructors.
                 quote! { use ::ink_lang::codegen::EmitEvent as _; }
             });
         quote_spanned!(storage_span =>
diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs
index d067dbb19f..ad108d89c9 100644
--- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs
+++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs
@@ -307,7 +307,7 @@ impl CallBuilder<'_> {
     /// the respective ink! trait message calls of the called smart contract
     /// instance.
     /// The way these messages are built-up allows the caller to customize message
-    /// parameters such as gas limit and transferred balance.
+    /// parameters such as gas limit and transferred value.
     fn generate_ink_trait_impl(&self) -> TokenStream2 {
         let span = self.trait_def.span();
         let trait_ident = self.trait_def.trait_def.item().ident();
diff --git a/crates/lang/ir/Cargo.toml b/crates/lang/ir/Cargo.toml
index 77e5e4cd08..ba96db6797 100644
--- a/crates/lang/ir/Cargo.toml
+++ b/crates/lang/ir/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_lang_ir"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>", "Robin Freyler <robin@parity.io>"]
 edition = "2021"
 
diff --git a/crates/lang/ir/src/ast/mod.rs b/crates/lang/ir/src/ast/mod.rs
index 58b807472d..af0ff02755 100644
--- a/crates/lang/ir/src/ast/mod.rs
+++ b/crates/lang/ir/src/ast/mod.rs
@@ -20,7 +20,7 @@
 //! syntax.
 //!
 //! At the time of this writing we currently only use this for the argument
-//! parsing of ink! configuration header `#[ink(env = my::env::Types, etc...)]`
+//! parsing of ink! configuration header `#[ink(env = my::env::Types, ...)]`
 //! in order to be able to parse identifiers in `name = value` segments for
 //! the `value` part.
 
diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs
index 99ba725f94..04cb7da440 100644
--- a/crates/lang/ir/src/ir/attrs.rs
+++ b/crates/lang/ir/src/ir/attrs.rs
@@ -25,8 +25,11 @@ use core::{
     result::Result,
 };
 use proc_macro2::{
+    Group as Group2,
     Ident,
     Span,
+    TokenStream as TokenStream2,
+    TokenTree as TokenTree2,
 };
 use std::collections::HashMap;
 use syn::spanned::Spanned;
@@ -207,8 +210,8 @@ impl InkAttribute {
         Ok(())
     }
 
-    /// Converts a sequence of `#[ink(..)]` attributes into a single flattened
-    /// `#[ink(..)]` attribute that contains all of the input arguments.
+    /// Converts a sequence of `#[ink(...)]` attributes into a single flattened
+    /// `#[ink(...)]` attribute that contains all of the input arguments.
     ///
     /// # Example
     ///
@@ -225,8 +228,7 @@ impl InkAttribute {
     {
         let args = attrs
             .into_iter()
-            .map(|attr| attr.args)
-            .flatten()
+            .flat_map(|attr| attr.args)
             .collect::<Vec<_>>();
         if args.is_empty() {
             return Err(format_err!(
@@ -265,7 +267,7 @@ impl InkAttribute {
     }
 
     /// Returns the selector of the ink! attribute if any.
-    pub fn selector(&self) -> Option<ir::Selector> {
+    pub fn selector(&self) -> Option<SelectorOrWildcard> {
         self.args().find_map(|arg| {
             if let ir::AttributeArg::Selector(selector) = arg.kind() {
                 return Some(*selector)
@@ -280,6 +282,16 @@ impl InkAttribute {
             .any(|arg| matches!(arg.kind(), AttributeArg::Payable))
     }
 
+    /// Returns `true` if the ink! attribute contains the wildcard selector.
+    pub fn has_wildcard_selector(&self) -> bool {
+        self.args().any(|arg| {
+            matches!(
+                arg.kind(),
+                AttributeArg::Selector(SelectorOrWildcard::Wildcard)
+            )
+        })
+    }
+
     /// Returns `true` if the ink! attribute contains the `anonymous` argument.
     pub fn is_anonymous(&self) -> bool {
         self.args()
@@ -342,6 +354,7 @@ pub enum AttributeArgKind {
     Constructor,
     /// `#[ink(payable)]`
     Payable,
+    /// `#[ink(selector = _)]`
     /// `#[ink(selector = 0xDEADBEEF)]`
     Selector,
     /// `#[ink(extension = N: u32)]`
@@ -395,11 +408,15 @@ pub enum AttributeArg {
     /// Applied on ink! constructors or messages in order to specify that they
     /// can receive funds from callers.
     Payable,
-    /// `#[ink(selector = 0xDEADBEEF)]`
+    /// Can be either one of:
     ///
-    /// Applied on ink! constructors or messages to manually control their
-    /// selectors.
-    Selector(Selector),
+    /// - `#[ink(selector = 0xDEADBEEF)]`
+    ///   Applied on ink! constructors or messages to manually control their
+    ///   selectors.
+    /// - `#[ink(selector = _)]`
+    ///   Applied on ink! messages to define a fallback messages that is invoked
+    ///   if no other ink! message matches a given selector.
+    Selector(SelectorOrWildcard),
     /// `#[ink(namespace = "my_namespace")]`
     ///
     /// Applied on ink! trait implementation blocks to disambiguate other trait
@@ -413,8 +430,8 @@ pub enum AttributeArg {
     /// of them. This is useful if such an implementation block does not contain
     /// any other ink! attributes, so it would be flagged by ink! as a Rust item.
     /// Adding `#[ink(impl)]` on such implementation blocks makes them treated
-    /// as ink! implementation blocks thus allowing to access the environment
-    /// etc. Note that ink! messages and constructors still need to be explicitly
+    /// as ink! implementation blocks thus allowing to access the environment, etc..
+    /// Note that ink! messages and constructors still need to be explicitly
     /// flagged as such.
     Implementation,
     /// `#[ink(extension = N: u32)]`
@@ -449,7 +466,7 @@ impl core::fmt::Display for AttributeArgKind {
             Self::Constructor => write!(f, "constructor"),
             Self::Payable => write!(f, "payable"),
             Self::Selector => {
-                write!(f, "selector = S:[u8; 4]")
+                write!(f, "selector = S:[u8; 4] || _")
             }
             Self::Extension => {
                 write!(f, "extension = N:u32)")
@@ -495,9 +512,7 @@ impl core::fmt::Display for AttributeArg {
             Self::Message => write!(f, "message"),
             Self::Constructor => write!(f, "constructor"),
             Self::Payable => write!(f, "payable"),
-            Self::Selector(selector) => {
-                write!(f, "selector = {:?}", selector.to_bytes())
-            }
+            Self::Selector(selector) => core::fmt::Display::fmt(&selector, f),
             Self::Extension(extension) => {
                 write!(f, "extension = {:?}", extension.into_u32())
             }
@@ -511,6 +526,32 @@ impl core::fmt::Display for AttributeArg {
     }
 }
 
+/// Either a wildcard selector or a specified selector.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum SelectorOrWildcard {
+    /// A wildcard selector. If no other selector matches, the message/constructor
+    /// annotated with the wildcard selector will be invoked.
+    Wildcard,
+    /// A user provided selector.
+    UserProvided(ir::Selector),
+}
+
+impl SelectorOrWildcard {
+    /// Create a new `SelectorOrWildcard::Selector` from the supplied bytes.
+    fn selector(bytes: [u8; 4]) -> SelectorOrWildcard {
+        SelectorOrWildcard::UserProvided(Selector::from(bytes))
+    }
+}
+
+impl core::fmt::Display for SelectorOrWildcard {
+    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
+        match self {
+            Self::UserProvided(selector) => core::fmt::Debug::fmt(&selector, f),
+            Self::Wildcard => write!(f, "_"),
+        }
+    }
+}
+
 /// An ink! namespace applicable to a trait implementation block.
 #[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct Namespace {
@@ -532,7 +573,7 @@ impl Namespace {
 }
 
 /// Returns `true` if the given iterator yields at least one attribute of the form
-/// `#[ink(..)]` or `#[ink]`.
+/// `#[ink(...)]` or `#[ink]`.
 ///
 /// # Note
 ///
@@ -723,13 +764,66 @@ impl From<InkAttribute> for Attribute {
     }
 }
 
+/// This function replaces occurrences of a `TokenTree::Ident` of the sequence
+/// `selector = _` with the sequence `selector = "_"`.
+///
+/// This is done because `syn::Attribute::parse_meta` does not support parsing a
+/// verbatim like `_`. For this we would need to switch to `syn::Attribute::parse_args`,
+/// which requires a more in-depth rewrite of our IR parsing.
+fn transform_wildcard_selector_to_string(group: Group2) -> TokenTree2 {
+    let mut found_selector = false;
+    let mut found_equal = false;
+
+    let new_group: TokenStream2 = group
+        .stream()
+        .into_iter()
+        .map(|tt| {
+            match tt {
+                TokenTree2::Group(grp) => transform_wildcard_selector_to_string(grp),
+                TokenTree2::Ident(ident)
+                    if found_selector && found_equal && ident == "_" =>
+                {
+                    let mut lit = proc_macro2::Literal::string("_");
+                    lit.set_span(ident.span());
+                    found_selector = false;
+                    found_equal = false;
+                    TokenTree2::Literal(lit)
+                }
+                TokenTree2::Ident(ident) if ident == "selector" => {
+                    found_selector = true;
+                    TokenTree2::Ident(ident)
+                }
+                TokenTree2::Punct(punct) if punct.as_char() == '=' => {
+                    found_equal = true;
+                    TokenTree2::Punct(punct)
+                }
+                _ => tt,
+            }
+        })
+        .collect();
+    TokenTree2::Group(Group2::new(group.delimiter(), new_group))
+}
+
 impl TryFrom<syn::Attribute> for InkAttribute {
     type Error = syn::Error;
 
-    fn try_from(attr: syn::Attribute) -> Result<Self, Self::Error> {
+    fn try_from(mut attr: syn::Attribute) -> Result<Self, Self::Error> {
         if !attr.path.is_ident("ink") {
             return Err(format_err_spanned!(attr, "unexpected non-ink! attribute"))
         }
+
+        let ts: TokenStream2 = attr
+            .tokens
+            .into_iter()
+            .map(|tt| {
+                match tt {
+                    TokenTree2::Group(grp) => transform_wildcard_selector_to_string(grp),
+                    _ => tt,
+                }
+            })
+            .collect();
+        attr.tokens = ts;
+
         match attr.parse_meta().map_err(|_| {
             format_err_spanned!(attr, "unexpected ink! attribute structure")
         })? {
@@ -809,6 +903,23 @@ impl TryFrom<syn::NestedMeta> for AttributeFrag {
                 match &meta {
                     syn::Meta::NameValue(name_value) => {
                         if name_value.path.is_ident("selector") {
+                            if let syn::Lit::Str(lit_str) = &name_value.lit {
+                                let argument = lit_str.value();
+                                // We've pre-processed the verbatim `_` to `"_"`. This was done
+                                // because `syn::Attribute::parse_meta` does not support verbatim.
+                                if argument != "_" {
+                                    return Err(format_err!(
+                                        name_value,
+                                        "#[ink(selector = ..)] attributes with string inputs are deprecated. \
+                                        use an integer instead, e.g. #[ink(selector = 1)] or #[ink(selector = 0xC0DECAFE)]."
+                                    ))
+                                }
+                                return Ok(AttributeFrag {
+                                    ast: meta,
+                                    arg: AttributeArg::Selector(SelectorOrWildcard::Wildcard),
+                                })
+                            }
+
                             if let syn::Lit::Int(lit_int) = &name_value.lit {
                                 let selector_u32 = lit_int.base10_parse::<u32>()
                                     .map_err(|error| {
@@ -821,17 +932,10 @@ impl TryFrom<syn::NestedMeta> for AttributeFrag {
                                 let selector = Selector::from(selector_u32.to_be_bytes());
                                 return Ok(AttributeFrag {
                                     ast: meta,
-                                    arg: AttributeArg::Selector(selector),
+                                    arg: AttributeArg::Selector(SelectorOrWildcard::UserProvided(selector)),
                                 })
                             }
-                            if let syn::Lit::Str(_) = &name_value.lit {
-                                return Err(format_err!(
-                                    name_value,
-                                    "#[ink(selector = ..)] attributes with string inputs are deprecated. \
-                                    use an integer instead, e.g. #[ink(selector = 1)] or #[ink(selector = 0xC0DECAFE)]."
-                                ))
-                            }
-                            return Err(format_err!(name_value, "expecteded 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE]"))
+                            return Err(format_err!(name_value, "expected 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE]"))
                         }
                         if name_value.path.is_ident("namespace") {
                             if let syn::Lit::Str(lit_str) = &name_value.lit {
@@ -865,7 +969,7 @@ impl TryFrom<syn::NestedMeta> for AttributeFrag {
                                     ),
                                 })
                             }
-                            return Err(format_err!(name_value, "expecteded `u32` integer type for `N` in #[ink(extension = N)]"))
+                            return Err(format_err!(name_value, "expected `u32` integer type for `N` in #[ink(extension = N)]"))
                         }
                         if name_value.path.is_ident("handle_status") {
                             if let syn::Lit::Bool(lit_bool) = &name_value.lit {
@@ -875,7 +979,7 @@ impl TryFrom<syn::NestedMeta> for AttributeFrag {
                                     arg: AttributeArg::HandleStatus(value),
                                 })
                             }
-                            return Err(format_err!(name_value, "expecteded `bool` value type for `flag` in #[ink(handle_status = flag)]"))
+                            return Err(format_err!(name_value, "expected `bool` value type for `flag` in #[ink(handle_status = flag)]"))
                         }
                         if name_value.path.is_ident("returns_result") {
                             if let syn::Lit::Bool(lit_bool) = &name_value.lit {
@@ -885,7 +989,7 @@ impl TryFrom<syn::NestedMeta> for AttributeFrag {
                                     arg: AttributeArg::ReturnsResult(value),
                                 })
                             }
-                            return Err(format_err!(name_value, "expecteded `bool` value type for `flag` in #[ink(returns_result = flag)]"))
+                            return Err(format_err!(name_value, "expected `bool` value type for `flag` in #[ink(returns_result = flag)]"))
                         }
                         Err(format_err_spanned!(
                             meta,
@@ -1116,7 +1220,7 @@ mod tests {
                 #[ink(selector = 42)]
             },
             Ok(test::Attribute::Ink(vec![AttributeArg::Selector(
-                Selector::from([0, 0, 0, 42]),
+                SelectorOrWildcard::UserProvided(Selector::from([0, 0, 0, 42])),
             )])),
         );
         assert_attribute_try_from(
@@ -1124,7 +1228,7 @@ mod tests {
                 #[ink(selector = 0xDEADBEEF)]
             },
             Ok(test::Attribute::Ink(vec![AttributeArg::Selector(
-                Selector::from([0xDE, 0xAD, 0xBE, 0xEF]),
+                SelectorOrWildcard::selector([0xDE, 0xAD, 0xBE, 0xEF]),
             )])),
         );
     }
@@ -1161,7 +1265,7 @@ mod tests {
             syn::parse_quote! {
                 #[ink(selector = true)]
             },
-            Err("expecteded 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE]"),
+            Err("expected 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE]"),
         );
     }
 
@@ -1228,7 +1332,7 @@ mod tests {
             syn::parse_quote! {
                 #[ink(extension = "string")]
             },
-            Err("expecteded `u32` integer type for `N` in #[ink(extension = N)]"),
+            Err("expected `u32` integer type for `N` in #[ink(extension = N)]"),
         );
     }
 
@@ -1306,9 +1410,7 @@ mod tests {
             syn::parse_quote! {
                 #[ink(handle_status = "string")]
             },
-            Err(
-                "expecteded `bool` value type for `flag` in #[ink(handle_status = flag)]",
-            ),
+            Err("expected `bool` value type for `flag` in #[ink(handle_status = flag)]"),
         );
     }
 
@@ -1352,7 +1454,7 @@ mod tests {
             syn::parse_quote! {
                 #[ink(returns_result = "string")]
             },
-            Err("expecteded `bool` value type for `flag` in #[ink(returns_result = flag)]"),
+            Err("expected `bool` value type for `flag` in #[ink(returns_result = flag)]"),
         );
     }
 
diff --git a/crates/lang/ir/src/ir/chain_extension.rs b/crates/lang/ir/src/ir/chain_extension.rs
index e589f54747..a654655280 100644
--- a/crates/lang/ir/src/ir/chain_extension.rs
+++ b/crates/lang/ir/src/ir/chain_extension.rs
@@ -776,7 +776,7 @@ mod tests {
             }
         );
         assert_ink_chain_extension_eq_err!(
-            error: "expecteded `u32` integer type for `N` in #[ink(extension = N)]",
+            error: "expected `u32` integer type for `N` in #[ink(extension = N)]",
             pub trait MyChainExtension {
                 #[ink(extension = "Hello, World!")]
                 fn has_self_receiver();
diff --git a/crates/lang/ir/src/ir/contract.rs b/crates/lang/ir/src/ir/contract.rs
index f7533a8bb7..4895f650fe 100644
--- a/crates/lang/ir/src/ir/contract.rs
+++ b/crates/lang/ir/src/ir/contract.rs
@@ -83,7 +83,7 @@ impl Contract {
     /// ```no_compile
     /// #[ink::contract]
     /// mod my_contract {
-    ///     // ... definitions
+    ///     // ...definitions
     /// }
     /// ```
     pub fn module(&self) -> &ir::ItemMod {
diff --git a/crates/lang/ir/src/ir/item_impl/callable.rs b/crates/lang/ir/src/ir/item_impl/callable.rs
index d7ab1bca1c..fcb2463a3d 100644
--- a/crates/lang/ir/src/ir/item_impl/callable.rs
+++ b/crates/lang/ir/src/ir/item_impl/callable.rs
@@ -116,6 +116,10 @@ where
         <C as Callable>::is_payable(self.callable)
     }
 
+    fn has_wildcard_selector(&self) -> bool {
+        <C as Callable>::has_wildcard_selector(self.callable)
+    }
+
     fn visibility(&self) -> Visibility {
         <C as Callable>::visibility(self.callable)
     }
@@ -162,6 +166,9 @@ pub trait Callable {
     /// Flagging as payable is done using the `#[ink(payable)]` attribute.
     fn is_payable(&self) -> bool;
 
+    /// Returns `true` if the ink! callable is flagged as a wildcard selector.
+    fn has_wildcard_selector(&self) -> bool;
+
     /// Returns the visibility of the ink! callable.
     fn visibility(&self) -> Visibility;
 
@@ -214,7 +221,7 @@ pub trait Callable {
 /// }
 /// ```
 ///
-/// ... then the selector of `my_message` is simply `0xDEADBEEF` since it overrides
+/// …then the selector of `my_message` is simply `0xDEADBEEF` since it overrides
 /// the composed selector.
 ///
 /// ## Inherent implementation block
@@ -228,7 +235,7 @@ pub trait Callable {
 /// }
 /// ```
 ///
-/// ... then the selector of `my_message` is composed such as:
+/// …then the selector of `my_message` is composed such as:
 /// ```no_compile
 /// BLAKE2("my_message".to_string().as_bytes())[0..4]
 /// ```
@@ -244,7 +251,7 @@ pub trait Callable {
 /// }
 /// ```
 ///
-/// ... then the selector of `my_message` is composed such as:
+/// …then the selector of `my_message` is composed such as:
 /// ```no_compile
 /// BLAKE2("MyTrait::my_message".to_string().as_bytes())[0..4]
 /// ```
@@ -260,7 +267,7 @@ pub trait Callable {
 /// }
 /// ```
 ///
-/// ... then the selector of `my_message` is composed such as:
+/// …then the selector of `my_message` is composed such as:
 /// ```no_compile
 /// BLAKE2("::my_full::long_path::MyTrait::my_message".to_string().as_bytes())[0..4]
 /// ```
@@ -277,7 +284,7 @@ pub trait Callable {
 /// }
 /// ```
 ///
-/// ... then the selector of `my_message` is composed such as:
+/// …then the selector of `my_message` is composed such as:
 /// ```no_compile
 /// BLAKE2("my_namespace::MyTrait::my_message".to_string().as_bytes())[0..4]
 /// ```
diff --git a/crates/lang/ir/src/ir/item_impl/constructor.rs b/crates/lang/ir/src/ir/item_impl/constructor.rs
index f44be1ca1a..e20bf44089 100644
--- a/crates/lang/ir/src/ir/item_impl/constructor.rs
+++ b/crates/lang/ir/src/ir/item_impl/constructor.rs
@@ -19,7 +19,10 @@ use super::{
     InputsIter,
     Visibility,
 };
-use crate::ir;
+use crate::{
+    ir,
+    ir::attrs::SelectorOrWildcard,
+};
 use core::convert::TryFrom;
 use proc_macro2::{
     Ident,
@@ -70,7 +73,7 @@ pub struct Constructor {
     ///
     /// This overrides the computed selector, even when using a manual namespace
     /// for the parent implementation block.
-    selector: Option<ir::Selector>,
+    selector: Option<SelectorOrWildcard>,
 }
 
 impl quote::ToTokens for Constructor {
@@ -200,7 +203,17 @@ impl Callable for Constructor {
     }
 
     fn user_provided_selector(&self) -> Option<&ir::Selector> {
-        self.selector.as_ref()
+        if let Some(SelectorOrWildcard::UserProvided(selector)) = self.selector.as_ref() {
+            return Some(selector)
+        }
+        None
+    }
+
+    fn has_wildcard_selector(&self) -> bool {
+        if let Some(SelectorOrWildcard::Wildcard) = self.selector {
+            return true
+        }
+        false
     }
 
     fn is_payable(&self) -> bool {
@@ -578,4 +591,13 @@ mod tests {
             )
         }
     }
+
+    #[test]
+    fn try_from_wildcard_constructor_works() {
+        let item: syn::ImplItemMethod = syn::parse_quote! {
+            #[ink(constructor, selector = _)]
+            pub fn my_constructor() -> Self {}
+        };
+        assert!(<ir::Constructor as TryFrom<_>>::try_from(item).is_ok());
+    }
 }
diff --git a/crates/lang/ir/src/ir/item_impl/message.rs b/crates/lang/ir/src/ir/item_impl/message.rs
index 9659531f80..b14f49b9df 100644
--- a/crates/lang/ir/src/ir/item_impl/message.rs
+++ b/crates/lang/ir/src/ir/item_impl/message.rs
@@ -21,6 +21,7 @@ use super::{
 };
 use crate::ir::{
     self,
+    attrs::SelectorOrWildcard,
     utils,
 };
 use core::convert::TryFrom;
@@ -106,7 +107,7 @@ pub struct Message {
     ///
     /// This overrides the computed selector, even when using a manual namespace
     /// for the parent implementation block.
-    selector: Option<ir::Selector>,
+    selector: Option<SelectorOrWildcard>,
 }
 
 impl quote::ToTokens for Message {
@@ -226,7 +227,17 @@ impl Callable for Message {
     }
 
     fn user_provided_selector(&self) -> Option<&ir::Selector> {
-        self.selector.as_ref()
+        if let Some(SelectorOrWildcard::UserProvided(selector)) = self.selector.as_ref() {
+            return Some(selector)
+        }
+        None
+    }
+
+    fn has_wildcard_selector(&self) -> bool {
+        if let Some(SelectorOrWildcard::Wildcard) = self.selector {
+            return true
+        }
+        false
     }
 
     fn is_payable(&self) -> bool {
diff --git a/crates/lang/ir/src/ir/item_impl/mod.rs b/crates/lang/ir/src/ir/item_impl/mod.rs
index 1e7ed9acd5..48b277ac41 100644
--- a/crates/lang/ir/src/ir/item_impl/mod.rs
+++ b/crates/lang/ir/src/ir/item_impl/mod.rs
@@ -352,8 +352,7 @@ impl ItemImpl {
     /// Returns `None` if this is an inherent implementation block.
     pub fn trait_ident(&self) -> Option<&Ident> {
         self.trait_path()
-            .map(|trait_path| trait_path.segments.last())
-            .flatten()
+            .and_then(|trait_path| trait_path.segments.last())
             .map(|segment| &segment.ident)
     }
 
diff --git a/crates/lang/ir/src/ir/item_mod.rs b/crates/lang/ir/src/ir/item_mod.rs
index 858035889d..32bd3b7640 100644
--- a/crates/lang/ir/src/ir/item_mod.rs
+++ b/crates/lang/ir/src/ir/item_mod.rs
@@ -15,6 +15,7 @@
 use crate::{
     ir,
     ir::idents_lint,
+    Callable,
 };
 use core::convert::TryFrom;
 use proc_macro2::{
@@ -239,6 +240,58 @@ impl ItemMod {
         }
         Ok(())
     }
+
+    /// Ensures that at most one wildcard selector exists among ink! messages, as well as
+    /// ink! constructors.
+    fn ensure_only_one_wildcard_selector(items: &[ir::Item]) -> Result<(), syn::Error> {
+        let mut wildcard_selector: Option<&ir::Message> = None;
+        for item_impl in items
+            .iter()
+            .filter_map(ir::Item::map_ink_item)
+            .filter_map(ir::InkItem::filter_map_impl_block)
+        {
+            for message in item_impl.iter_messages() {
+                if !message.has_wildcard_selector() {
+                    continue
+                }
+                match wildcard_selector {
+                    None => wildcard_selector = Some(message.callable()),
+                    Some(overlap) => {
+                        use crate::error::ExtError as _;
+                        return Err(format_err!(
+                            message.callable().span(),
+                            "encountered ink! messages with overlapping wildcard selectors",
+                        )
+                        .into_combine(format_err!(
+                            overlap.span(),
+                            "first ink! message with overlapping wildcard selector here",
+                        )))
+                    }
+                }
+            }
+            let mut wildcard_selector: Option<&ir::Constructor> = None;
+            for constructor in item_impl.iter_constructors() {
+                if !constructor.has_wildcard_selector() {
+                    continue
+                }
+                match wildcard_selector {
+                    None => wildcard_selector = Some(constructor.callable()),
+                    Some(overlap) => {
+                        use crate::error::ExtError as _;
+                        return Err(format_err!(
+                            constructor.callable().span(),
+                            "encountered ink! constructor with overlapping wildcard selectors",
+                        )
+                            .into_combine(format_err!(
+                            overlap.span(),
+                            "first ink! constructor with overlapping wildcard selector here",
+                        )))
+                    }
+                }
+            }
+        }
+        Ok(())
+    }
 }
 
 impl TryFrom<syn::ItemMod> for ItemMod {
@@ -278,6 +331,7 @@ impl TryFrom<syn::ItemMod> for ItemMod {
         Self::ensure_contains_message(module_span, &items)?;
         Self::ensure_contains_constructor(module_span, &items)?;
         Self::ensure_no_overlapping_selectors(&items)?;
+        Self::ensure_only_one_wildcard_selector(&items)?;
         Ok(Self {
             attrs: other_attrs,
             vis: module.vis,
@@ -805,4 +859,70 @@ mod tests {
             .is_ok()
         );
     }
+
+    #[test]
+    fn overlapping_wildcard_selectors_fails() {
+        assert_fail(
+            syn::parse_quote! {
+                mod my_module {
+                    #[ink(storage)]
+                    pub struct MyStorage {}
+
+                    impl MyStorage {
+                        #[ink(constructor)]
+                        pub fn my_constructor() -> Self {}
+
+                        #[ink(message, selector = _)]
+                        pub fn my_message1(&self) {}
+
+                        #[ink(message, selector = _)]
+                        pub fn my_message2(&self) {}
+                    }
+                }
+            },
+            "encountered ink! messages with overlapping wildcard selectors",
+        );
+    }
+
+    #[test]
+    fn wildcard_selector_on_constructor_works() {
+        assert!(
+            <ir::ItemMod as TryFrom<syn::ItemMod>>::try_from(syn::parse_quote! {
+                mod my_module {
+                    #[ink(storage)]
+                    pub struct MyStorage {}
+
+                    impl MyStorage {
+                        #[ink(constructor, selector = _)]
+                        pub fn my_constructor() -> Self {}
+
+                        #[ink(message)]
+                        pub fn my_message(&self) {}
+                    }
+                }
+            })
+            .is_ok()
+        );
+    }
+
+    #[test]
+    fn overlap_between_wildcard_selector_and_composed_selector_fails() {
+        assert_fail(
+            syn::parse_quote! {
+                mod my_module {
+                    #[ink(storage)]
+                    pub struct MyStorage {}
+
+                    impl MyStorage {
+                        #[ink(constructor)]
+                        pub fn my_constructor() -> Self {}
+
+                        #[ink(message, selector = _, selector = 0xCAFEBABE)]
+                        pub fn my_message(&self) {}
+                    }
+                }
+            },
+            "encountered ink! attribute arguments with equal kinds",
+        );
+    }
 }
diff --git a/crates/lang/ir/src/ir/trait_def/item/mod.rs b/crates/lang/ir/src/ir/trait_def/item/mod.rs
index 69cb677a38..8f04dde187 100644
--- a/crates/lang/ir/src/ir/trait_def/item/mod.rs
+++ b/crates/lang/ir/src/ir/trait_def/item/mod.rs
@@ -26,7 +26,10 @@ pub use self::{
 use super::TraitDefinitionConfig;
 use crate::{
     ir,
-    ir::idents_lint,
+    ir::{
+        attrs::SelectorOrWildcard,
+        idents_lint,
+    },
     Selector,
 };
 #[cfg(test)]
@@ -356,8 +359,10 @@ impl InkItemTrait {
             let ident = callable.ident();
             let ink_attrs = callable.ink_attrs();
             let selector = match ink_attrs.selector() {
-                Some(manual_selector) => manual_selector,
-                None => Selector::compose(trait_prefix, ident),
+                Some(SelectorOrWildcard::UserProvided(manual_selector)) => {
+                    manual_selector
+                }
+                _ => Selector::compose(trait_prefix, ident),
             };
             let (duplicate_selector, duplicate_ident) = match callable {
                 InkTraitItem::Message(_) => {
diff --git a/crates/lang/ir/src/ir/trait_def/item/trait_item.rs b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs
index 9fddf5cbd8..e077bc63f5 100644
--- a/crates/lang/ir/src/ir/trait_def/item/trait_item.rs
+++ b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs
@@ -16,6 +16,7 @@ use super::super::InkAttribute;
 use crate::{
     ir::{
         self,
+        attrs::SelectorOrWildcard,
         utils,
     },
     InputsIter,
@@ -83,6 +84,8 @@ impl<'a> InkTraitMessage<'a> {
             &ir::AttributeArgKind::Message,
             |arg| {
                 match arg.kind() {
+                    ir::AttributeArg::Selector(SelectorOrWildcard::Wildcard) =>
+                        Err(Some(format_err!(arg.span(), "wildcard selectors are only supported for inherent ink! messages or constructors, not for traits."))),
                     ir::AttributeArg::Message
                     | ir::AttributeArg::Payable
                     | ir::AttributeArg::Selector(_) => Ok(()),
diff --git a/crates/lang/macro/Cargo.toml b/crates/lang/macro/Cargo.toml
index fbfeb28f9a..86946d8af6 100644
--- a/crates/lang/macro/Cargo.toml
+++ b/crates/lang/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_lang_macro"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>", "Robin Freyler <robin@parity.io>"]
 edition = "2021"
 
@@ -15,19 +15,19 @@ categories = ["no-std", "embedded"]
 include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]
 
 [dependencies]
-ink_lang_ir = { version = "3.0.0-rc6", path = "../ir", default-features = false }
-ink_lang_codegen = { version = "3.0.0-rc6", path = "../codegen", default-features = false }
-ink_primitives = { version = "3.0.0-rc6", path = "../../primitives/", default-features = false }
+ink_lang_ir = { version = "3.0.0-rc7", path = "../ir", default-features = false }
+ink_lang_codegen = { version = "3.0.0-rc7", path = "../codegen", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../primitives/", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2.3", default-features = false, features = ["derive"] }
 syn = "1"
 proc-macro2 = "1"
 
 [dev-dependencies]
-ink_metadata = { version = "3.0.0-rc6", path = "../../metadata/" }
-ink_env = { version = "3.0.0-rc6", path = "../../env/" }
-ink_storage = { version = "3.0.0-rc6", path = "../../storage/" }
-ink_lang = { version = "3.0.0-rc6", path = ".." }
+ink_metadata = { version = "3.0.0-rc7", path = "../../metadata/" }
+ink_env = { version = "3.0.0-rc7", path = "../../env/" }
+ink_storage = { version = "3.0.0-rc7", path = "../../storage/" }
+ink_lang = { version = "3.0.0-rc7", path = ".." }
 scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 
 [lib]
diff --git a/crates/lang/macro/src/lib.rs b/crates/lang/macro/src/lib.rs
index 203d8ff141..453f3c5a2f 100644
--- a/crates/lang/macro/src/lib.rs
+++ b/crates/lang/macro/src/lib.rs
@@ -220,7 +220,6 @@ pub fn selector_bytes(input: TokenStream) -> TokenStream {
 ///         type Hash = [u8; 32];
 ///         type Timestamp = u64;
 ///         type BlockNumber = u32;
-///         type RentFraction = ::ink_env::Perbill;
 ///         type ChainExtension = ::ink_env::NoChainExtension;
 ///     }
 ///     ```
@@ -240,7 +239,6 @@ pub fn selector_bytes(input: TokenStream) -> TokenStream {
 ///         #     type Timestamp = u64;
 ///         #     type BlockNumber = u32;
 ///         #     type ChainExtension = ::ink_env::NoChainExtension;
-///         #     type RentFraction = ::ink_env::Perbill;
 ///         # }
 ///         #
 ///         # #[ink(storage)]
@@ -397,7 +395,7 @@ pub fn selector_bytes(input: TokenStream) -> TokenStream {
 ///         }
 ///
 ///         /// Returns the current value.
-///         #[ink(message, payable)] // ... or specify payable inline.
+///         #[ink(message, payable)] // ...or specify payable inline.
 ///         pub fn get(&self) -> bool {
 ///             self.value
 ///         }
@@ -437,7 +435,7 @@ pub fn selector_bytes(input: TokenStream) -> TokenStream {
 ///         # }
 ///         #
 ///         /// Returns the current value.
-///         #[ink(message, selector = 0xFEEDBEEF)] // ... or specify selector inline.
+///         #[ink(message, selector = 0xFEEDBEEF)] // ...or specify selector inline.
 ///         pub fn get(&self) -> bool {
 ///             self.value
 ///         }
@@ -483,7 +481,7 @@ pub fn selector_bytes(input: TokenStream) -> TokenStream {
 ///         #[ink(message, payable)]
 ///         pub fn fund(&self) {
 ///             let caller = self.env().caller();
-///             let value = self.env().transferred_balance();
+///             let value = self.env().transferred_value();
 ///             debug_println!("thanks for the funding of {:?} from {:?}", value, caller);
 ///         }
 ///     }
@@ -515,7 +513,7 @@ pub fn selector_bytes(input: TokenStream) -> TokenStream {
 ///     #[ink(storage)]
 ///     pub struct Erc20 {
 ///         total_supply: Balance,
-///         // more fields ...
+///         // more fields...
 ///     }
 ///
 ///     impl Erc20 {
@@ -609,7 +607,7 @@ pub fn contract(attr: TokenStream, item: TokenStream) -> TokenStream {
 ///     #[ink(message)]
 ///     fn transfer(&mut self, amount: Balance, to: AccountId) -> bool;
 ///
-///     // etc ...
+///     // etc.
 /// }
 /// ```
 ///
@@ -756,7 +754,7 @@ pub fn test(attr: TokenStream, item: TokenStream) -> TokenStream {
 /// fn key_access_for_account(key: &[u8], account: &[u8]) -> Access;
 /// # }
 /// ```
-/// ... or as multiple stand alone ink! attributes applied to the same item:
+/// …or as multiple stand alone ink! attributes applied to the same item:
 /// ```
 /// # type Access = i32;
 /// # use ink_lang as ink;
@@ -827,7 +825,7 @@ pub fn test(attr: TokenStream, item: TokenStream) -> TokenStream {
 /// pub trait MyChainExtension {
 ///     type ErrorCode = MyErrorCode;
 ///
-///     // more definitions ...
+///     // more definitions
 /// }
 /// ```
 ///
@@ -982,7 +980,6 @@ pub fn test(attr: TokenStream, item: TokenStream) -> TokenStream {
 ///     type Hash = <DefaultEnvironment as Environment>::Hash;
 ///     type BlockNumber = <DefaultEnvironment as Environment>::BlockNumber;
 ///     type Timestamp = <DefaultEnvironment as Environment>::Timestamp;
-///     type RentFraction = <DefaultEnvironment as Environment>::RentFraction;
 ///
 ///     type ChainExtension = RuntimeReadWrite;
 /// }
@@ -999,7 +996,8 @@ pub fn test(attr: TokenStream, item: TokenStream) -> TokenStream {
 /// shown below.
 ///
 /// Note that chain extension methods are accessible through `Self::extension()` or
-/// `self.extension()`. For example as in `Self::extension().read(..)` or `self.extension().read(..)`.
+/// `self.extension()`. For example as in `Self::extension().read(...)` or
+/// `self.extension().read(...)`.
 ///
 /// ```
 /// # use ink_lang as ink;
@@ -1126,7 +1124,6 @@ pub fn test(attr: TokenStream, item: TokenStream) -> TokenStream {
 /// #     type Hash = <ink_env::DefaultEnvironment as ink_env::Environment>::Hash;
 /// #     type BlockNumber = <ink_env::DefaultEnvironment as ink_env::Environment>::BlockNumber;
 /// #     type Timestamp = <ink_env::DefaultEnvironment as ink_env::Environment>::Timestamp;
-/// #     type RentFraction = <ink_env::DefaultEnvironment as ink_env::Environment>::RentFraction;
 /// #
 /// #     type ChainExtension = RuntimeReadWrite;
 /// # }
diff --git a/crates/lang/src/chain_extension.rs b/crates/lang/src/chain_extension.rs
index f3432414a8..73bd882fc0 100644
--- a/crates/lang/src/chain_extension.rs
+++ b/crates/lang/src/chain_extension.rs
@@ -14,7 +14,7 @@
 
 /// Trait implemented by chain extensions.
 ///
-/// Allows to use the `self.env().extension().my_chain_extension(..)` syntax.
+/// Allows to use the `self.env().extension().my_chain_extension(...)` syntax.
 ///
 /// # Note
 ///
diff --git a/crates/lang/src/codegen/dispatch/execution.rs b/crates/lang/src/codegen/dispatch/execution.rs
index 28d28e0879..2618992b0f 100644
--- a/crates/lang/src/codegen/dispatch/execution.rs
+++ b/crates/lang/src/codegen/dispatch/execution.rs
@@ -63,7 +63,7 @@ pub fn deny_payment<E>() -> Result<(), DispatchError>
 where
     E: Environment,
 {
-    let transferred = ink_env::transferred_balance::<E>();
+    let transferred = ink_env::transferred_value::<E>();
     if transferred != <E as Environment>::Balance::from(0_u32) {
         return Err(DispatchError::PaidUnpayableMessage)
     }
diff --git a/crates/lang/src/codegen/event/emit.rs b/crates/lang/src/codegen/event/emit.rs
index e47980e8b1..7dc8b22cfc 100644
--- a/crates/lang/src/codegen/event/emit.rs
+++ b/crates/lang/src/codegen/event/emit.rs
@@ -14,7 +14,7 @@
 
 use crate::reflect::ContractEventBase;
 
-/// Allows for `self.env().emit_event(..)` syntax in ink! implementation blocks.
+/// Allows for `self.env().emit_event(...)` syntax in ink! implementation blocks.
 pub trait EmitEvent<C>
 where
     C: ContractEventBase,
diff --git a/crates/lang/src/env_access.rs b/crates/lang/src/env_access.rs
index d3e79a345d..0823a296a6 100644
--- a/crates/lang/src/env_access.rs
+++ b/crates/lang/src/env_access.rs
@@ -26,12 +26,9 @@ use ink_env::{
     },
     Environment,
     Error,
-    RentParams,
-    RentStatus,
     Result,
 };
 use ink_eth_compatibility::ECDSAPublicKey;
-use ink_primitives::Key;
 
 /// The API behind the `self.env()` and `Self::env()` syntax in ink!.
 ///
@@ -110,7 +107,7 @@ where
         ink_env::caller::<T>()
     }
 
-    /// Returns the transferred balance for the contract execution.
+    /// Returns the transferred value for the contract execution.
     ///
     /// # Example
     ///
@@ -128,11 +125,11 @@ where
     /// #             Self {}
     /// #         }
     /// #
-    /// /// Allows funding the contract. Prints a debug message with the transferred balance.
+    /// /// Allows funding the contract. Prints a debug message with the transferred value.
     /// #[ink(message, payable)]
     /// pub fn fund(&self) {
     ///     let caller = self.env().caller();
-    ///     let value = self.env().transferred_balance();
+    ///     let value = self.env().transferred_value();
     ///     ink_env::debug_println!("thanks for the funding of {:?} from {:?}", value, caller);
     /// }
     /// #
@@ -142,9 +139,9 @@ where
     ///
     /// # Note
     ///
-    /// For more details visit: [`ink_env::transferred_balance`]
-    pub fn transferred_balance(self) -> T::Balance {
-        ink_env::transferred_balance::<T>()
+    /// For more details visit: [`ink_env::transferred_value`]
+    pub fn transferred_value(self) -> T::Balance {
+        ink_env::transferred_value::<T>()
     }
 
     /// Returns the price for the specified amount of gas.
@@ -351,132 +348,6 @@ where
         ink_env::balance::<T>()
     }
 
-    /// Returns the current rent allowance for the executed contract.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # use ink_lang as ink;
-    /// # #[ink::contract]
-    /// # pub mod my_contract {
-    /// #     #[ink(storage)]
-    /// #     pub struct MyContract { }
-    /// #
-    /// #     impl MyContract {
-    /// #         #[ink(constructor)]
-    /// #         pub fn new() -> Self {
-    /// #             Self {}
-    /// #         }
-    /// #
-    /// /// Returns the amount of the contract's balance which
-    /// /// can be used for paying rent.
-    /// #[ink(message)]
-    /// pub fn rent_allowance(&self) -> Balance {
-    ///     self.env().rent_allowance()
-    /// }
-    /// #
-    /// #     }
-    /// # }
-    /// ```
-    ///
-    /// # Note
-    ///
-    /// For more details visit: [`ink_env::rent_allowance`]
-    pub fn rent_allowance(self) -> T::Balance {
-        ink_env::rent_allowance::<T>()
-    }
-
-    /// Sets the rent allowance of the executed contract to the new value.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # use ink_lang as ink;
-    /// # #[ink::contract]
-    /// # pub mod my_contract {
-    /// #     #[ink(storage)]
-    /// #     pub struct MyContract { }
-    /// #
-    /// #     impl MyContract {
-    /// #         #[ink(constructor)]
-    /// #         pub fn new() -> Self {
-    /// #             Self {}
-    /// #         }
-    /// #
-    /// /// Limits the amount of contract balance which can be used for paying rent
-    /// /// to half of the contract's total balance.
-    /// #[ink(message)]
-    /// pub fn limit_rent_allowance(&self) {
-    ///     self.env().set_rent_allowance(self.env().balance() / 2);
-    /// }
-    /// #
-    /// #     }
-    /// # }
-    /// ```
-    ///
-    /// # Note
-    ///
-    /// For more details visit: [`ink_env::set_rent_allowance`]
-    pub fn set_rent_allowance(self, new_value: T::Balance) {
-        ink_env::set_rent_allowance::<T>(new_value)
-    }
-
-    /// Returns information needed for rent calculations.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # use ink_lang as ink;
-    /// # #[ink::contract]
-    /// # pub mod my_contract {
-    /// #     #[ink(storage)]
-    /// #     pub struct MyContract { }
-    /// #
-    /// #     impl MyContract {
-    /// #         #[ink(constructor)]
-    /// #         pub fn new() -> Self {
-    /// #             Self {}
-    /// #         }
-    /// #
-    /// /// Returns the balance every contract needs to deposit on this chain
-    /// /// to stay alive indefinitely.
-    /// #[ink(message)]
-    /// pub fn deposit_per_contract(&self) -> Balance {
-    ///     self.env().rent_params().deposit_per_contract
-    /// }
-    /// #
-    /// #     }
-    /// # }
-    /// ```
-    ///
-    /// # Note
-    ///
-    /// For more details visit: [`ink_env::RentParams`]
-    pub fn rent_params(self) -> RentParams<T> {
-        ink_env::rent_params::<T>().expect("couldn't decode contract rent params")
-    }
-
-    /// Returns information about the required deposit and resulting rent.
-    ///
-    /// # Parameters
-    ///
-    /// - `at_refcount`: The `refcount` assumed for the returned `custom_refcount_*` fields.
-    ///   If `None` is supplied the `custom_refcount_*` fields will also be `None`.
-    ///
-    ///   The `current_*` fields of `RentStatus` do **not** consider changes to the code's
-    ///   `refcount` made during the currently running call.
-    ///
-    /// # Note
-    ///
-    /// For more details visit: [`ink_env::RentStatus`]
-    pub fn rent_status(
-        self,
-        at_refcount: Option<core::num::NonZeroU32>,
-    ) -> RentStatus<T> {
-        ink_env::rent_status::<T>(at_refcount)
-            .expect("couldn't decode contract rent params")
-    }
-
     /// Returns the current block number.
     ///
     /// # Example
@@ -550,39 +421,6 @@ where
         ink_env::minimum_balance::<T>()
     }
 
-    /// Returns the tombstone deposit for the contracts chain.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # use ink_lang as ink;
-    /// # #[ink::contract]
-    /// # pub mod my_contract {
-    /// #     #[ink(storage)]
-    /// #     pub struct MyContract { }
-    /// #
-    /// #     impl MyContract {
-    /// #         #[ink(constructor)]
-    /// #         pub fn new() -> Self {
-    /// #             Self {}
-    /// #         }
-    /// #
-    /// #[ink(message)]
-    /// pub fn tombstone_deposit(&self) -> Balance {
-    ///     self.env().tombstone_deposit()
-    /// }
-    /// #
-    /// #     }
-    /// # }
-    /// ```
-    ///
-    /// # Note
-    ///
-    /// For more details visit: [`ink_env::tombstone_deposit`]
-    pub fn tombstone_deposit(self) -> T::Balance {
-        ink_env::tombstone_deposit::<T>()
-    }
-
     /// Instantiates another contract.
     ///
     /// # Example
@@ -779,57 +617,7 @@ where
         ink_env::eval_contract::<T, Args, R>(params)
     }
 
-    /// Restores a smart contract from its tombstone state.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # use ink_lang as ink;
-    /// # #[ink::contract]
-    /// # pub mod my_contract {
-    /// #     #[ink(storage)]
-    /// #     pub struct MyContract { }
-    /// #
-    /// #     impl MyContract {
-    /// #         #[ink(constructor)]
-    /// #         pub fn new() -> Self {
-    /// #             Self {}
-    /// #         }
-    /// #
-    /// /// Simple resurrection of a contract.
-    /// #[ink(message)]
-    /// pub fn resurrect(&self, contract: AccountId) {
-    ///     self.env().restore_contract(
-    ///         contract,
-    ///         Hash::from([0x42; 32]),
-    ///         1000,
-    ///         &[]
-    ///     )
-    /// }
-    /// #
-    /// #     }
-    /// # }
-    /// ```
-    ///
-    /// # Note
-    ///
-    /// For more details visit: [`ink_env::restore_contract`]
-    pub fn restore_contract(
-        self,
-        account_id: T::AccountId,
-        code_hash: T::Hash,
-        rent_allowance: T::Balance,
-        filtered_keys: &[Key],
-    ) {
-        ink_env::restore_contract::<T>(
-            account_id,
-            code_hash,
-            rent_allowance,
-            filtered_keys,
-        )
-    }
-
-    /// Terminates the existence of a contract without creating a tombstone.
+    /// Terminates the existence of a contract.
     ///
     /// # Example
     ///
@@ -1033,7 +821,7 @@ where
     ///     let failed_result = self.env().ecdsa_recover(&signature, &[0; 32]);
     ///     assert!(failed_result.is_err());
     ///     if let Err(e) = failed_result {
-    ///         assert_eq!(e, ink_env::Error::EcdsaRecoverFailed);
+    ///         assert_eq!(e, ink_env::Error::EcdsaRecoveryFailed);
     ///     }
     /// }
     /// #
@@ -1048,6 +836,6 @@ where
         let mut output = [0; 33];
         ink_env::ecdsa_recover(signature, message_hash, &mut output)
             .map(|_| output.into())
-            .map_err(|_| Error::EcdsaRecoverFailed)
+            .map_err(|_| Error::EcdsaRecoveryFailed)
     }
 }
diff --git a/crates/lang/src/reflect/contract.rs b/crates/lang/src/reflect/contract.rs
index 7083f56f8b..965b27c878 100644
--- a/crates/lang/src/reflect/contract.rs
+++ b/crates/lang/src/reflect/contract.rs
@@ -110,7 +110,6 @@ pub trait ContractName {
 ///     type Hash = <DefaultEnvironment as Environment>::Hash;
 ///     type BlockNumber = u32;
 ///     type Timestamp = u64;
-///     type RentFraction = <DefaultEnvironment as Environment>::RentFraction;
 ///     type ChainExtension = <DefaultEnvironment as Environment>::ChainExtension;
 /// }
 ///
diff --git a/crates/metadata/Cargo.toml b/crates/metadata/Cargo.toml
index d5c1c5a284..810f9a07cd 100644
--- a/crates/metadata/Cargo.toml
+++ b/crates/metadata/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_metadata"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>", "Robin Freyler <robin@parity.io>"]
 edition = "2021"
 
@@ -15,8 +15,8 @@ categories = ["no-std", "embedded"]
 include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]
 
 [dependencies]
-ink_prelude = { version = "3.0.0-rc6", path = "../prelude/", default-features = false }
-ink_primitives = { version = "3.0.0-rc6", path = "../primitives/", default-features = false }
+ink_prelude = { version = "3.0.0-rc7", path = "../prelude/", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../primitives/", default-features = false }
 
 serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] }
 impl-serde = "0.3.1"
diff --git a/crates/metadata/src/lib.rs b/crates/metadata/src/lib.rs
index 552bd79a05..b80325726f 100644
--- a/crates/metadata/src/lib.rs
+++ b/crates/metadata/src/lib.rs
@@ -69,12 +69,14 @@ pub enum MetadataVersioned {
     /// Version 0 placeholder. Represents the original non-versioned metadata format.
     V0(MetadataVersionDeprecated),
     /// Version 1 of the contract metadata.
-    V1(InkProject),
+    V1(MetadataVersionDeprecated),
+    /// Version 2 of the contract metadata.
+    V2(InkProject),
 }
 
 impl From<InkProject> for MetadataVersioned {
     fn from(ink_project: InkProject) -> Self {
-        MetadataVersioned::V1(ink_project)
+        MetadataVersioned::V2(ink_project)
     }
 }
 
diff --git a/crates/metadata/src/specs.rs b/crates/metadata/src/specs.rs
index 30383131f1..8dca21b635 100644
--- a/crates/metadata/src/specs.rs
+++ b/crates/metadata/src/specs.rs
@@ -220,10 +220,10 @@ impl ContractSpec {
     deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
 ))]
 pub struct ConstructorSpec<F: Form = MetaForm> {
-    /// The name of the message.
+    /// The label of the constructor.
     ///
-    /// In case of a trait provided constructor the trait name is prefixed.
-    pub name: Vec<F::String>,
+    /// In case of a trait provided constructor the label is prefixed with the trait label.
+    pub label: F::String,
     /// The selector hash of the message.
     pub selector: Selector,
     /// The parameters of the deployment handler.
@@ -237,7 +237,7 @@ impl IntoPortable for ConstructorSpec {
 
     fn into_portable(self, registry: &mut Registry) -> Self::Output {
         ConstructorSpec {
-            name: registry.map_into_portable(self.name),
+            label: self.label.into_portable(registry),
             selector: self.selector,
             args: self
                 .args
@@ -253,11 +253,11 @@ impl<F> ConstructorSpec<F>
 where
     F: Form,
 {
-    /// Returns the name of the message.
+    /// Returns the label of the constructor.
     ///
-    /// In case of a trait provided constructor the trait name is prefixed.
-    pub fn name(&self) -> &[F::String] {
-        &self.name
+    /// In case of a trait provided constructor the label is prefixed with the trait label.
+    pub fn label(&self) -> &F::String {
+        &self.label
     }
 
     /// Returns the selector hash of the message.
@@ -290,15 +290,12 @@ pub struct ConstructorSpecBuilder<Selector> {
 
 impl ConstructorSpec {
     /// Creates a new constructor spec builder.
-    fn from_name_segments<T>(
-        segments: T,
-    ) -> ConstructorSpecBuilder<Missing<state::Selector>>
-    where
-        T: IntoIterator<Item = &'static str>,
-    {
+    pub fn from_label(
+        label: &'static str,
+    ) -> ConstructorSpecBuilder<Missing<state::Selector>> {
         ConstructorSpecBuilder {
             spec: Self {
-                name: segments.into_iter().collect(),
+                label,
                 selector: Selector::default(),
                 args: Vec::new(),
                 docs: Vec::new(),
@@ -306,21 +303,6 @@ impl ConstructorSpec {
             marker: PhantomData,
         }
     }
-
-    /// Creates a new constructor spec builder.
-    pub fn from_name(
-        name: &'static str,
-    ) -> ConstructorSpecBuilder<Missing<state::Selector>> {
-        Self::from_name_segments([name])
-    }
-
-    /// Creates a new constructor spec builder for a trait provided constructor.
-    pub fn from_trait_and_name(
-        trait_name: &'static str,
-        constructor_name: &'static str,
-    ) -> ConstructorSpecBuilder<Missing<state::Selector>> {
-        Self::from_name_segments([trait_name, constructor_name])
-    }
 }
 
 impl ConstructorSpecBuilder<Missing<state::Selector>> {
@@ -375,11 +357,11 @@ impl ConstructorSpecBuilder<state::Selector> {
 ))]
 #[serde(rename_all = "camelCase")]
 pub struct MessageSpec<F: Form = MetaForm> {
-    /// The name of the message and some optional prefixes.
+    /// The label of the message.
     ///
     /// In case of trait provided messages and constructors the prefix
-    /// by convention in ink! is the name of the trait.
-    name: Vec<F::String>,
+    /// by convention in ink! is the label of the trait.
+    label: F::String,
     /// The selector hash of the message.
     selector: Selector,
     /// If the message is allowed to mutate the contract state.
@@ -413,9 +395,9 @@ mod state {
 }
 
 impl MessageSpec {
-    /// Creates a new message spec from the given name segments.
-    fn from_name_segments(
-        segments: Vec<&'static str>,
+    /// Creates a new message spec builder.
+    pub fn from_label(
+        label: &'static str,
     ) -> MessageSpecBuilder<
         Missing<state::Selector>,
         Missing<state::Mutates>,
@@ -424,7 +406,7 @@ impl MessageSpec {
     > {
         MessageSpecBuilder {
             spec: Self {
-                name: segments,
+                label,
                 selector: Selector::default(),
                 mutates: false,
                 payable: false,
@@ -435,43 +417,18 @@ impl MessageSpec {
             marker: PhantomData,
         }
     }
-
-    /// Creates a new message spec builder.
-    pub fn from_name(
-        name: &'static str,
-    ) -> MessageSpecBuilder<
-        Missing<state::Selector>,
-        Missing<state::Mutates>,
-        Missing<state::IsPayable>,
-        Missing<state::Returns>,
-    > {
-        Self::from_name_segments(vec![name])
-    }
-
-    /// Creates a new message spec builder for a trait provided message.
-    pub fn from_trait_and_name(
-        trait_name: &'static str,
-        message_name: &'static str,
-    ) -> MessageSpecBuilder<
-        Missing<state::Selector>,
-        Missing<state::Mutates>,
-        Missing<state::IsPayable>,
-        Missing<state::Returns>,
-    > {
-        Self::from_name_segments(vec![trait_name, message_name])
-    }
 }
 
 impl<F> MessageSpec<F>
 where
     F: Form,
 {
-    /// Returns the name of the message and some optional prefixes.
+    /// Returns the label of the message.
     ///
     /// In case of trait provided messages and constructors the prefix
-    /// by convention in ink! is the name of the trait.
-    pub fn name(&self) -> &[F::String] {
-        &self.name
+    /// by convention in ink! is the label of the trait.
+    pub fn label(&self) -> &F::String {
+        &self.label
     }
 
     /// Returns the selector hash of the message.
@@ -617,7 +574,7 @@ impl IntoPortable for MessageSpec {
 
     fn into_portable(self, registry: &mut Registry) -> Self::Output {
         MessageSpec {
-            name: registry.map_into_portable(self.name),
+            label: self.label.into_portable(registry),
             selector: self.selector,
             mutates: self.mutates,
             payable: self.payable,
@@ -639,8 +596,8 @@ impl IntoPortable for MessageSpec {
     deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
 ))]
 pub struct EventSpec<F: Form = MetaForm> {
-    /// The name of the event.
-    name: F::String,
+    /// The label of the event.
+    label: F::String,
     /// The event arguments.
     args: Vec<EventParamSpec<F>>,
     /// The event documentation.
@@ -686,7 +643,7 @@ impl IntoPortable for EventSpec {
 
     fn into_portable(self, registry: &mut Registry) -> Self::Output {
         EventSpec {
-            name: self.name.into_portable(registry),
+            label: self.label.into_portable(registry),
             args: self
                 .args
                 .into_iter()
@@ -699,10 +656,10 @@ impl IntoPortable for EventSpec {
 
 impl EventSpec {
     /// Creates a new event specification builder.
-    pub fn new(name: &'static str) -> EventSpecBuilder {
+    pub fn new(label: &'static str) -> EventSpecBuilder {
         EventSpecBuilder {
             spec: Self {
-                name,
+                label,
                 args: Vec::new(),
                 docs: Vec::new(),
             },
@@ -714,9 +671,9 @@ impl<F> EventSpec<F>
 where
     F: Form,
 {
-    /// Returns the name of the event.
-    pub fn name(&self) -> &F::String {
-        &self.name
+    /// Returns the label of the event.
+    pub fn label(&self) -> &F::String {
+        &self.label
     }
 
     /// The event arguments.
@@ -892,15 +849,15 @@ where
     }
 }
 
-/// Describes a pair of parameter name and type.
+/// Describes a pair of parameter label and type.
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
 #[serde(bound(
     serialize = "F::Type: Serialize, F::String: Serialize",
     deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
 ))]
 pub struct EventParamSpec<F: Form = MetaForm> {
-    /// The name of the parameter.
-    name: F::String,
+    /// The label of the parameter.
+    label: F::String,
     /// If the event parameter is indexed.
     indexed: bool,
     /// The type of the parameter.
@@ -915,7 +872,7 @@ impl IntoPortable for EventParamSpec {
 
     fn into_portable(self, registry: &mut Registry) -> Self::Output {
         EventParamSpec {
-            name: self.name.into_portable(registry),
+            label: self.label.into_portable(registry),
             indexed: self.indexed,
             ty: self.ty.into_portable(registry),
             docs: registry.map_into_portable(self.docs),
@@ -925,10 +882,10 @@ impl IntoPortable for EventParamSpec {
 
 impl EventParamSpec {
     /// Creates a new event parameter specification builder.
-    pub fn new(name: &'static str) -> EventParamSpecBuilder {
+    pub fn new(label: &'static str) -> EventParamSpecBuilder {
         EventParamSpecBuilder {
             spec: Self {
-                name,
+                label,
                 // By default event parameters are not indexed.
                 indexed: false,
                 // We initialize every parameter type as `()`.
@@ -944,9 +901,9 @@ impl<F> EventParamSpec<F>
 where
     F: Form,
 {
-    /// Returns the name of the parameter.
-    pub fn name(&self) -> &F::String {
-        &self.name
+    /// Returns the label of the parameter.
+    pub fn label(&self) -> &F::String {
+        &self.label
     }
 
     /// Returns true if the event parameter is indexed.
@@ -1060,15 +1017,15 @@ where
     }
 }
 
-/// Describes a pair of parameter name and type.
+/// Describes a pair of parameter label and type.
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
 #[serde(bound(
     serialize = "F::Type: Serialize, F::String: Serialize",
     deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
 ))]
 pub struct MessageParamSpec<F: Form = MetaForm> {
-    /// The name of the parameter.
-    name: F::String,
+    /// The label of the parameter.
+    label: F::String,
     /// The type of the parameter.
     #[serde(rename = "type")]
     ty: TypeSpec<F>,
@@ -1079,7 +1036,7 @@ impl IntoPortable for MessageParamSpec {
 
     fn into_portable(self, registry: &mut Registry) -> Self::Output {
         MessageParamSpec {
-            name: self.name.into_portable(registry),
+            label: self.label.into_portable(registry),
             ty: self.ty.into_portable(registry),
         }
     }
@@ -1087,10 +1044,10 @@ impl IntoPortable for MessageParamSpec {
 
 impl MessageParamSpec {
     /// Constructs a new message parameter specification via builder.
-    pub fn new(name: &'static str) -> MessageParamSpecBuilder {
+    pub fn new(label: &'static str) -> MessageParamSpecBuilder {
         MessageParamSpecBuilder {
             spec: Self {
-                name,
+                label,
                 // Uses `()` type by default.
                 ty: TypeSpec::new::<()>(),
             },
@@ -1102,9 +1059,9 @@ impl<F> MessageParamSpec<F>
 where
     F: Form,
 {
-    /// Returns the name of the parameter.
-    pub fn name(&self) -> &F::String {
-        &self.name
+    /// Returns the label of the parameter.
+    pub fn label(&self) -> &F::String {
+        &self.label
     }
 
     /// Returns the type of the parameter.
diff --git a/crates/prelude/Cargo.toml b/crates/prelude/Cargo.toml
index ffd6d5c7e3..140946f45b 100644
--- a/crates/prelude/Cargo.toml
+++ b/crates/prelude/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_prelude"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>", "Robin Freyler <robin@parity.io>"]
 edition = "2021"
 
diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml
index 108fa86348..444be94253 100644
--- a/crates/primitives/Cargo.toml
+++ b/crates/primitives/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_primitives"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>", "Robin Freyler <robin@parity.io>"]
 edition = "2021"
 
@@ -15,7 +15,7 @@ categories = ["no-std", "embedded"]
 include = ["/Cargo.toml", "src/**/*.rs", "/README.md", "/LICENSE"]
 
 [dependencies]
-ink_prelude = { version = "3.0.0-rc6", path = "../prelude/", default-features = false }
+ink_prelude = { version = "3.0.0-rc7", path = "../prelude/", default-features = false }
 scale = { package = "parity-scale-codec", version = "2.3", default-features = false, features = ["derive", "full"] }
 scale-info = { version = "1.0", default-features = false, features = ["derive"], optional = true }
 cfg-if = "1"
diff --git a/crates/storage/Cargo.toml b/crates/storage/Cargo.toml
index dda5f8d48c..b1bba04d6d 100644
--- a/crates/storage/Cargo.toml
+++ b/crates/storage/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_storage"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>", "Robin Freyler <robin@parity.io>"]
 edition = "2021"
 
@@ -15,11 +15,11 @@ categories = ["no-std", "embedded"]
 include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]
 
 [dependencies]
-ink_env = { version = "3.0.0-rc6", path = "../env/", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../metadata/", default-features = false, features = ["derive"], optional = true }
-ink_primitives = { version = "3.0.0-rc6", path = "../primitives/", default-features = false }
-ink_storage_derive = { version = "3.0.0-rc6", path = "derive", default-features = false }
-ink_prelude = { version = "3.0.0-rc6", path = "../prelude/", default-features = false }
+ink_env = { version = "3.0.0-rc7", path = "../env/", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../metadata/", default-features = false, features = ["derive"], optional = true }
+ink_primitives = { version = "3.0.0-rc7", path = "../primitives/", default-features = false }
+ink_storage_derive = { version = "3.0.0-rc7", path = "derive", default-features = false }
+ink_prelude = { version = "3.0.0-rc7", path = "../prelude/", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2.3", default-features = false, features = ["derive", "full"] }
 derive_more = { version = "0.99", default-features = false, features = ["from", "display"] }
diff --git a/crates/storage/derive/Cargo.toml b/crates/storage/derive/Cargo.toml
index 69f3f9a8c9..3a895ae8dd 100644
--- a/crates/storage/derive/Cargo.toml
+++ b/crates/storage/derive/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ink_storage_derive"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>", "Robin Freyler <robin@parity.io>"]
 edition = "2021"
 
@@ -25,8 +25,8 @@ synstructure = "0.12.4"
 
 [dev-dependencies]
 scale = { package = "parity-scale-codec", version = "2.3", default-features = false, features = ["derive", "full"] }
-ink_env = { version = "3.0.0-rc6", path = "../../env" }
-ink_primitives = { version = "3.0.0-rc6", path = "../../primitives" }
-ink_metadata = { version = "3.0.0-rc6", path = "../../metadata" }
-ink_prelude = { version = "3.0.0-rc6", path = "../../prelude/" }
-ink_storage = { version = "3.0.0-rc6", path = ".." }
+ink_env = { version = "3.0.0-rc7", path = "../../env" }
+ink_primitives = { version = "3.0.0-rc7", path = "../../primitives" }
+ink_metadata = { version = "3.0.0-rc7", path = "../../metadata" }
+ink_prelude = { version = "3.0.0-rc7", path = "../../prelude/" }
+ink_storage = { version = "3.0.0-rc7", path = ".." }
diff --git a/crates/storage/src/collections/stash/mod.rs b/crates/storage/src/collections/stash/mod.rs
index 6c94fd6ad4..acba6ed8d2 100644
--- a/crates/storage/src/collections/stash/mod.rs
+++ b/crates/storage/src/collections/stash/mod.rs
@@ -308,8 +308,7 @@ where
         let prev = self
             .entries
             .get_mut(prev_vacant)
-            .map(Entry::try_to_vacant_mut)
-            .flatten()
+            .and_then(Entry::try_to_vacant_mut)
             .expect("`prev` must point to an existing entry at this point");
         if prev_vacant == next_vacant {
             // There is only one other vacant entry left.
@@ -325,8 +324,7 @@ where
             let next = self
                 .entries
                 .get_mut(next_vacant)
-                .map(Entry::try_to_vacant_mut)
-                .flatten()
+                .and_then(Entry::try_to_vacant_mut)
                 .expect("`next` must point to an existing entry at this point");
             debug_assert_eq!(next.prev, removed_index);
             next.prev = prev_vacant;
@@ -353,8 +351,7 @@ where
             let root_vacant = self
                 .entries
                 .get(index)
-                .map(|entry| entry.try_to_vacant())
-                .flatten()
+                .and_then(|entry| entry.try_to_vacant())
                 .expect("last_vacant must point to an existing vacant entry");
             // Form the linked vacant entries in a way that makes it more likely
             // for them to refill the stash from low indices.
@@ -390,8 +387,7 @@ where
             let entry = self
                 .entries
                 .get_mut(next)
-                .map(Entry::try_to_vacant_mut)
-                .flatten()
+                .and_then(Entry::try_to_vacant_mut)
                 .expect("`next` must point to an existing vacant entry at this point");
             entry.prev = at;
             entry.next = at;
@@ -400,14 +396,12 @@ where
             // different look-ups to update them.
             self.entries
                 .get_mut(prev)
-                .map(Entry::try_to_vacant_mut)
-                .flatten()
+                .and_then(Entry::try_to_vacant_mut)
                 .expect("`prev` must point to an existing vacant entry at this point")
                 .next = at;
             self.entries
                 .get_mut(next)
-                .map(Entry::try_to_vacant_mut)
-                .flatten()
+                .and_then(Entry::try_to_vacant_mut)
                 .expect("`next` must point to an existing vacant entry at this point")
                 .prev = at;
         }
diff --git a/crates/storage/src/lazy/lazy_array.rs b/crates/storage/src/lazy/lazy_array.rs
index 3bac215a74..4a07978ee9 100644
--- a/crates/storage/src/lazy/lazy_array.rs
+++ b/crates/storage/src/lazy/lazy_array.rs
@@ -241,8 +241,7 @@ impl<T, const N: usize> EntryArray<T, N> {
             unsafe { self.entries[at as usize].get_ptr().as_mut() },
             Some(StorageEntry::new(new_value, EntryState::Mutated)),
         )
-        .map(StorageEntry::into_value)
-        .flatten()
+        .and_then(StorageEntry::into_value)
     }
 
     /// Inserts a new entry into the cache and returns an exclusive reference to it.
diff --git a/crates/storage/src/lazy/lazy_hmap.rs b/crates/storage/src/lazy/lazy_hmap.rs
index 11caecd2d4..30f5c11c1c 100644
--- a/crates/storage/src/lazy/lazy_hmap.rs
+++ b/crates/storage/src/lazy/lazy_hmap.rs
@@ -103,7 +103,7 @@ pub struct LazyHashMap<K, V, H> {
 /// by querying the cache another time -- but this would be an additional
 /// search. So what we do instead is to save a reference to the inserted
 /// cache value in the `Occupied`. As a consequence all Entry API operations
-/// (`get`, `remove`, ...) need to distinguish both cases.
+/// (`get`, `remove`, …) need to distinguish both cases.
 enum EntryOrMutableValue<E, V> {
     /// An occupied `EntryMap` entry that holds a value.
     /// This represents the case where the key was in the cache.
diff --git a/crates/storage/src/lazy/mapping.rs b/crates/storage/src/lazy/mapping.rs
index f5b9fb8aab..6bc9c2f271 100644
--- a/crates/storage/src/lazy/mapping.rs
+++ b/crates/storage/src/lazy/mapping.rs
@@ -74,7 +74,7 @@ where
         Q: scale::EncodeLike<K>,
         R: scale::EncodeLike<V> + PackedLayout,
     {
-        push_packed_root(value, &self.storage_key(key));
+        push_packed_root(value, &self.storage_key(&key));
     }
 
     /// Get the `value` at `key` from the contract storage.
@@ -85,14 +85,30 @@ where
     where
         Q: scale::EncodeLike<K>,
     {
-        pull_packed_root_opt(&self.storage_key(key))
+        pull_packed_root_opt(&self.storage_key(&key))
+    }
+
+    /// Clears the value at `key` from storage.
+    pub fn remove<Q>(&self, key: Q)
+    where
+        Q: scale::EncodeLike<K>,
+    {
+        let storage_key = self.storage_key(&key);
+        if <V as SpreadLayout>::REQUIRES_DEEP_CLEAN_UP {
+            // There are types which need to perform some action before being cleared. Here we
+            // indicate to those types that they should start tidying up.
+            if let Some(value) = self.get(key) {
+                <V as PackedLayout>::clear_packed(&value, &storage_key);
+            }
+        }
+        ink_env::clear_contract_storage(&storage_key);
     }
 
     /// Returns a `Key` pointer used internally by the storage API.
     ///
     /// This key is a combination of the `Mapping`'s internal `offset_key`
     /// and the user provided `key`.
-    fn storage_key<Q>(&self, key: Q) -> Key
+    fn storage_key<Q>(&self, key: &Q) -> Key
     where
         Q: scale::EncodeLike<K>,
     {
@@ -186,4 +202,56 @@ mod tests {
         })
         .unwrap()
     }
+
+    #[test]
+    fn can_clear_entries() {
+        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
+            // We use `Pack` here since it `REQUIRES_DEEP_CLEAN_UP`
+            use crate::Pack;
+
+            // Given
+            let mut mapping: Mapping<u8, u8> = Mapping::new([0u8; 32].into());
+            let mut deep_mapping: Mapping<u8, Pack<u8>> = Mapping::new([1u8; 32].into());
+
+            mapping.insert(&1, &2);
+            assert_eq!(mapping.get(&1), Some(2));
+
+            deep_mapping.insert(&1u8, &Pack::new(Pack::new(2u8)));
+            assert_eq!(deep_mapping.get(&1), Some(Pack::new(2u8)));
+
+            // When
+            mapping.remove(&1);
+            deep_mapping.remove(&1);
+
+            // Then
+            assert_eq!(mapping.get(&1), None);
+            assert_eq!(deep_mapping.get(&1), None);
+
+            Ok(())
+        })
+        .unwrap()
+    }
+
+    #[test]
+    fn can_clear_unexistent_entries() {
+        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
+            // We use `Pack` here since it `REQUIRES_DEEP_CLEAN_UP`
+            use crate::Pack;
+
+            // Given
+            let mapping: Mapping<u8, u8> = Mapping::new([0u8; 32].into());
+            let deep_mapping: Mapping<u8, Pack<u8>> = Mapping::new([1u8; 32].into());
+
+            // When
+            mapping.remove(&1);
+            deep_mapping.remove(&1);
+
+            // Then
+            assert_eq!(mapping.get(&1), None);
+            assert_eq!(deep_mapping.get(&1), None);
+
+            Ok(())
+        })
+        .unwrap()
+    }
 }
diff --git a/examples/contract-terminate/Cargo.toml b/examples/contract-terminate/Cargo.toml
index 84e5e8b9a3..768aa7a6e6 100644
--- a/examples/contract-terminate/Cargo.toml
+++ b/examples/contract-terminate/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "contract_terminate"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -19,10 +19,6 @@ name = "contract_terminate"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/contract-transfer/Cargo.toml b/examples/contract-transfer/Cargo.toml
index 09e6d33bc5..2a34cc1c53 100644
--- a/examples/contract-transfer/Cargo.toml
+++ b/examples/contract-transfer/Cargo.toml
@@ -1,16 +1,16 @@
 [package]
 name = "contract_transfer"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false, features = [ "ink-debug" ] }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
-ink_prelude = { version = "3.0.0-rc6", path = "../../crates/prelude", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false, features = [ "ink-debug" ] }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
+ink_prelude = { version = "3.0.0-rc7", path = "../../crates/prelude", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -20,10 +20,6 @@ name = "contract_transfer"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/contract-transfer/lib.rs b/examples/contract-transfer/lib.rs
index f5ebf58891..18173674e0 100644
--- a/examples/contract-transfer/lib.rs
+++ b/examples/contract-transfer/lib.rs
@@ -21,9 +21,9 @@ pub mod give_me {
         /// Insufficient funds to execute transfer.
         InsufficientFunds,
         /// Transfer failed because it would have brought the contract's
-        /// balance below the subsistence threshold.
-        /// This is necessary to keep enough funds in the contract to
-        /// allow for a tombstone to be created.
+        /// balance below the subsistence threshold. No transfer is
+        /// allowed to do this. Use `self.env().terminate()` to recover
+        /// the deposit.
         BelowSubsistenceThreshold,
     }
 
@@ -73,12 +73,9 @@ pub mod give_me {
         pub fn was_it_ten(&self) {
             ink_env::debug_println!(
                 "received payment: {}",
-                self.env().transferred_balance()
-            );
-            assert!(
-                self.env().transferred_balance() == 10,
-                "payment was not ten"
+                self.env().transferred_value()
             );
+            assert!(self.env().transferred_value() == 10, "payment was not ten");
         }
     }
 
@@ -137,16 +134,16 @@ pub mod give_me {
                 0xCA, 0xFE, 0xBA, 0xBE,
             ]));
             data.push_arg(&accounts.eve);
-            let mock_transferred_balance = 10;
+            let mock_transferred_value = 10;
 
             // Push the new execution context which sets Eve as caller and
-            // the `mock_transferred_balance` as the value which the contract
+            // the `mock_transferred_value` as the value which the contract
             // will see as transferred to it.
             ink_env::test::push_execution_context::<ink_env::DefaultEnvironment>(
                 accounts.eve,
                 contract_id(),
                 1000000,
-                mock_transferred_balance,
+                mock_transferred_value,
                 data,
             );
 
@@ -168,16 +165,16 @@ pub mod give_me {
                 0xCA, 0xFE, 0xBA, 0xBE,
             ]));
             data.push_arg(&accounts.eve);
-            let mock_transferred_balance = 13;
+            let mock_transferred_value = 13;
 
             // Push the new execution context which sets Eve as caller and
-            // the `mock_transferred_balance` as the value which the contract
+            // the `mock_transferred_value` as the value which the contract
             // will see as transferred to it.
             ink_env::test::push_execution_context::<ink_env::DefaultEnvironment>(
                 accounts.eve,
                 contract_id(),
                 1000000,
-                mock_transferred_balance,
+                mock_transferred_value,
                 data,
             );
 
@@ -277,7 +274,7 @@ pub mod give_me {
 
             // when
             // Push the new execution context which sets Eve as caller and
-            // the `mock_transferred_balance` as the value which the contract
+            // the `mock_transferred_value` as the value which the contract
             // will see as transferred to it.
             set_sender(accounts.eve);
             ink_env::test::set_value_transferred::<ink_env::DefaultEnvironment>(10);
@@ -296,7 +293,7 @@ pub mod give_me {
 
             // when
             // Push the new execution context which sets Eve as caller and
-            // the `mock_transferred_balance` as the value which the contract
+            // the `mock_transferred_value` as the value which the contract
             // will see as transferred to it.
             set_sender(accounts.eve);
             ink_env::test::set_value_transferred::<ink_env::DefaultEnvironment>(13);
diff --git a/examples/delegator/Cargo.toml b/examples/delegator/Cargo.toml
index e30219d02c..94a02afccd 100644
--- a/examples/delegator/Cargo.toml
+++ b/examples/delegator/Cargo.toml
@@ -1,21 +1,21 @@
 [package]
 name = "delegator"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 
-adder = { version = "3.0.0-rc6", path = "adder", default-features = false, features = ["ink-as-dependency"] }
-subber = { version = "3.0.0-rc6", path = "subber", default-features = false, features = ["ink-as-dependency"] }
-accumulator = { version = "3.0.0-rc6", path = "accumulator", default-features = false, features = ["ink-as-dependency"] }
+adder = { version = "3.0.0-rc7", path = "adder", default-features = false, features = ["ink-as-dependency"] }
+subber = { version = "3.0.0-rc7", path = "subber", default-features = false, features = ["ink-as-dependency"] }
+accumulator = { version = "3.0.0-rc7", path = "accumulator", default-features = false, features = ["ink-as-dependency"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
 
 [lib]
@@ -23,10 +23,6 @@ name = "delegator"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/delegator/accumulator/Cargo.toml b/examples/delegator/accumulator/Cargo.toml
index d4a2a8d713..ca214498fd 100644
--- a/examples/delegator/accumulator/Cargo.toml
+++ b/examples/delegator/accumulator/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "accumulator"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../../crates/lang", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -24,10 +24,6 @@ crate-type = [
     "rlib",
 ]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/delegator/adder/Cargo.toml b/examples/delegator/adder/Cargo.toml
index 94aaa34977..57c16fc846 100644
--- a/examples/delegator/adder/Cargo.toml
+++ b/examples/delegator/adder/Cargo.toml
@@ -1,17 +1,17 @@
 [package]
 name = "adder"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../../crates/lang", default-features = false }
 
-accumulator = { version = "3.0.0-rc6", path = "../accumulator", default-features = false, features = ["ink-as-dependency"] }
+accumulator = { version = "3.0.0-rc7", path = "../accumulator", default-features = false, features = ["ink-as-dependency"] }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -26,10 +26,6 @@ crate-type = [
     "rlib",
 ]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/delegator/subber/Cargo.toml b/examples/delegator/subber/Cargo.toml
index a065150c4f..e00913c4b3 100644
--- a/examples/delegator/subber/Cargo.toml
+++ b/examples/delegator/subber/Cargo.toml
@@ -1,17 +1,17 @@
 [package]
 name = "subber"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../../crates/lang", default-features = false }
 
-accumulator = { version = "3.0.0-rc6", path = "../accumulator", default-features = false, features = ["ink-as-dependency"] }
+accumulator = { version = "3.0.0-rc7", path = "../accumulator", default-features = false, features = ["ink-as-dependency"] }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -26,10 +26,6 @@ crate-type = [
     "rlib",
 ]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/dns/Cargo.toml b/examples/dns/Cargo.toml
index b3cbb5634a..3a3b320d25 100644
--- a/examples/dns/Cargo.toml
+++ b/examples/dns/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "dns"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -19,10 +19,6 @@ name = "dns"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/dns/lib.rs b/examples/dns/lib.rs
index bbbb8d443a..52291995c1 100644
--- a/examples/dns/lib.rs
+++ b/examples/dns/lib.rs
@@ -4,11 +4,12 @@ use ink_lang as ink;
 
 #[ink::contract]
 mod dns {
-    #[cfg(not(feature = "ink-as-dependency"))]
     use ink_storage::{
-        collections::hashmap::Entry,
-        collections::HashMap as StorageHashMap,
-        lazy::Lazy,
+        lazy::{
+            Lazy,
+            Mapping,
+        },
+        traits::SpreadAllocate,
     };
 
     /// Emitted whenever a new name is being registered.
@@ -60,12 +61,12 @@ mod dns {
     /// to facilitate transfers, voting and DApp-related operations instead
     /// of resorting to long IP addresses that are hard to remember.
     #[ink(storage)]
-    #[derive(Default)]
+    #[derive(Default, SpreadAllocate)]
     pub struct DomainNameService {
         /// A hashmap to store all name to addresses mapping.
-        name_to_address: StorageHashMap<Hash, AccountId>,
+        name_to_address: Mapping<Hash, AccountId>,
         /// A hashmap to store all name to owners mapping.
-        name_to_owner: StorageHashMap<Hash, AccountId>,
+        name_to_owner: Mapping<Hash, AccountId>,
         /// The default address.
         default_address: Lazy<AccountId>,
     }
@@ -87,21 +88,22 @@ mod dns {
         /// Creates a new domain name service contract.
         #[ink(constructor)]
         pub fn new() -> Self {
-            Default::default()
+            ink_lang::codegen::initialize_contract(|contract: &mut Self| {
+                contract.default_address = Default::default();
+            })
         }
 
         /// Register specific name with caller as owner.
         #[ink(message)]
         pub fn register(&mut self, name: Hash) -> Result<()> {
             let caller = self.env().caller();
-            let entry = self.name_to_owner.entry(name);
-            match entry {
-                Entry::Occupied(_) => return Err(Error::NameAlreadyExists),
-                Entry::Vacant(vacant) => {
-                    vacant.insert(caller);
-                    self.env().emit_event(Register { name, from: caller });
-                }
+            if self.name_to_owner.get(&name).is_some() {
+                return Err(Error::NameAlreadyExists)
             }
+
+            self.name_to_owner.insert(&name, &caller);
+            self.env().emit_event(Register { name, from: caller });
+
             Ok(())
         }
 
@@ -113,7 +115,10 @@ mod dns {
             if caller != owner {
                 return Err(Error::CallerIsNotOwner)
             }
-            let old_address = self.name_to_address.insert(name, new_address);
+
+            let old_address = self.name_to_address.get(name);
+            self.name_to_address.insert(&name, &new_address);
+
             self.env().emit_event(SetAddress {
                 name,
                 from: caller,
@@ -131,13 +136,17 @@ mod dns {
             if caller != owner {
                 return Err(Error::CallerIsNotOwner)
             }
-            let old_owner = self.name_to_owner.insert(name, to);
+
+            let old_owner = self.name_to_owner.get(&name);
+            self.name_to_owner.insert(&name, &to);
+
             self.env().emit_event(Transfer {
                 name,
                 from: caller,
                 old_owner,
                 new_owner: to,
             });
+
             Ok(())
         }
 
@@ -149,18 +158,16 @@ mod dns {
 
         /// Returns the owner given the hash or the default address.
         fn get_owner_or_default(&self, name: Hash) -> AccountId {
-            *self
-                .name_to_owner
+            self.name_to_owner
                 .get(&name)
-                .unwrap_or(&*self.default_address)
+                .unwrap_or(*self.default_address)
         }
 
         /// Returns the address given the hash or the default address.
         fn get_address_or_default(&self, name: Hash) -> AccountId {
-            *self
-                .name_to_address
+            self.name_to_address
                 .get(&name)
-                .unwrap_or(&*self.default_address)
+                .unwrap_or(*self.default_address)
         }
     }
 
diff --git a/examples/erc1155/Cargo.toml b/examples/erc1155/Cargo.toml
index ca45af08db..88443ca8fb 100644
--- a/examples/erc1155/Cargo.toml
+++ b/examples/erc1155/Cargo.toml
@@ -1,16 +1,16 @@
 [package]
 name = "erc1155"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false, features = ["ink-debug"] }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
-ink_prelude = { version = "3.0.0-rc6", path = "../../crates/prelude", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false, features = ["ink-debug"] }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
+ink_prelude = { version = "3.0.0-rc7", path = "../../crates/prelude", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -20,10 +20,6 @@ name = "erc1155"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/erc1155/lib.rs b/examples/erc1155/lib.rs
index d91d5af194..aca894919a 100644
--- a/examples/erc1155/lib.rs
+++ b/examples/erc1155/lib.rs
@@ -187,10 +187,13 @@ pub trait Erc1155TokenReceiver {
 mod erc1155 {
     use super::*;
 
-    use ink_prelude::collections::BTreeMap;
-    use ink_storage::traits::{
-        PackedLayout,
-        SpreadLayout,
+    use ink_storage::{
+        lazy::Mapping,
+        traits::{
+            PackedLayout,
+            SpreadAllocate,
+            SpreadLayout,
+        },
     };
 
     /// Indicate that a token transfer has occured.
@@ -236,6 +239,7 @@ mod erc1155 {
         PartialOrd,
         Eq,
         PartialEq,
+        Default,
         PackedLayout,
         SpreadLayout,
         scale::Encode,
@@ -249,12 +253,12 @@ mod erc1155 {
 
     /// An ERC-1155 contract.
     #[ink(storage)]
-    #[derive(Default)]
+    #[derive(Default, SpreadAllocate)]
     pub struct Contract {
         /// Tracks the balances of accounts across the different tokens that they might be holding.
-        balances: BTreeMap<(AccountId, TokenId), Balance>,
+        balances: Mapping<(AccountId, TokenId), Balance>,
         /// Which accounts (called operators) have been approved to spend funds on behalf of an owner.
-        approvals: BTreeMap<Approval, ()>,
+        approvals: Mapping<Approval, ()>,
         /// A unique identifier for the tokens which have been minted (and are therefore supported)
         /// by this contract.
         token_id_nonce: TokenId,
@@ -264,7 +268,11 @@ mod erc1155 {
         /// Initialize a default instance of this ERC-1155 implementation.
         #[ink(constructor)]
         pub fn new() -> Self {
-            Default::default()
+            // This call is required in order to correctly initialize the
+            // `Mapping`s of our contract.
+            //
+            // Not that `token_id_nonce` will be initialized to its `Default` value.
+            ink_lang::codegen::initialize_contract(|_| {})
         }
 
         /// Create the initial supply for a token.
@@ -281,7 +289,7 @@ mod erc1155 {
 
             // Given that TokenId is a `u128` the likelihood of this overflowing is pretty slim.
             self.token_id_nonce += 1;
-            self.balances.insert((caller, self.token_id_nonce), value);
+            self.balances.insert(&(caller, self.token_id_nonce), &value);
 
             // Emit transfer event but with mint semantics
             self.env().emit_event(TransferSingle {
@@ -308,7 +316,7 @@ mod erc1155 {
             ensure!(token_id <= self.token_id_nonce, Error::UnexistentToken);
 
             let caller = self.env().caller();
-            self.balances.insert((caller, token_id), value);
+            self.balances.insert(&(caller, token_id), &value);
 
             // Emit transfer event but with mint semantics
             self.env().emit_event(TransferSingle {
@@ -326,6 +334,10 @@ mod erc1155 {
         //
         // Should not be used directly since it's missing certain checks which are important to the
         // ERC-1155 standard (it is expected that the caller has already performed these).
+        //
+        // # Panics
+        //
+        // If `from` does not hold any `token_id` tokens.
         fn perform_transfer(
             &mut self,
             from: AccountId,
@@ -333,14 +345,16 @@ mod erc1155 {
             token_id: TokenId,
             value: Balance,
         ) {
-            self.balances
-                .entry((from, token_id))
-                .and_modify(|b| *b -= value);
+            let mut sender_balance = self
+                .balances
+                .get(&(from, token_id))
+                .expect("Caller should have ensured that `from` holds `token_id`.");
+            sender_balance -= value;
+            self.balances.insert(&(from, token_id), &sender_balance);
 
-            self.balances
-                .entry((to, token_id))
-                .and_modify(|b| *b += value)
-                .or_insert(value);
+            let mut recipient_balance = self.balances.get(&(to, token_id)).unwrap_or(0);
+            recipient_balance += value;
+            self.balances.insert(&(to, token_id), &recipient_balance);
 
             let caller = self.env().caller();
             self.env().emit_event(TransferSingle {
@@ -507,7 +521,7 @@ mod erc1155 {
 
         #[ink(message)]
         fn balance_of(&self, owner: AccountId, token_id: TokenId) -> Balance {
-            *self.balances.get(&(owner, token_id)).unwrap_or(&0)
+            self.balances.get(&(owner, token_id)).unwrap_or(0)
         }
 
         #[ink(message)]
@@ -541,7 +555,7 @@ mod erc1155 {
             };
 
             if approved {
-                self.approvals.insert(approval, ());
+                self.approvals.insert(&approval, &());
             } else {
                 self.approvals.remove(&approval);
             }
@@ -653,9 +667,9 @@ mod erc1155 {
 
         fn init_contract() -> Contract {
             let mut erc = Contract::new();
-            erc.balances.insert((alice(), 1), 10);
-            erc.balances.insert((alice(), 2), 20);
-            erc.balances.insert((bob(), 1), 10);
+            erc.balances.insert((alice(), 1), &10);
+            erc.balances.insert((alice(), 2), &20);
+            erc.balances.insert((bob(), 1), &10);
 
             erc
         }
diff --git a/examples/erc20/Cargo.toml b/examples/erc20/Cargo.toml
index 29cdc71f83..21fd5e3de7 100644
--- a/examples/erc20/Cargo.toml
+++ b/examples/erc20/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "erc20"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -19,10 +19,6 @@ name = "erc20"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/erc721/Cargo.toml b/examples/erc721/Cargo.toml
index 1293a35cdf..6845e4c49a 100644
--- a/examples/erc721/Cargo.toml
+++ b/examples/erc721/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "erc721"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -19,10 +19,6 @@ name = "erc721"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/flipper/Cargo.toml b/examples/flipper/Cargo.toml
index e090489ebd..b512e079fa 100644
--- a/examples/flipper/Cargo.toml
+++ b/examples/flipper/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "flipper"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -19,10 +19,6 @@ name = "flipper"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/incrementer/Cargo.toml b/examples/incrementer/Cargo.toml
index 688958abda..2d1d68e9cc 100644
--- a/examples/incrementer/Cargo.toml
+++ b/examples/incrementer/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "incrementer"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -19,10 +19,6 @@ name = "incrementer"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/multisig/Cargo.toml b/examples/multisig/Cargo.toml
index 2b83f16774..bf4b20ba0b 100755
--- a/examples/multisig/Cargo.toml
+++ b/examples/multisig/Cargo.toml
@@ -5,12 +5,12 @@ authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
-ink_prelude = { version = "3.0.0-rc6", path = "../../crates/prelude", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
+ink_prelude = { version = "3.0.0-rc7", path = "../../crates/prelude", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -20,10 +20,6 @@ name = "multisig"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/multisig/lib.rs b/examples/multisig/lib.rs
index 658fc335f5..65a633cebb 100755
--- a/examples/multisig/lib.rs
+++ b/examples/multisig/lib.rs
@@ -483,7 +483,7 @@ mod multisig {
         ) -> Result<(), Error> {
             self.ensure_confirmed(trans_id);
             let t = self.take_transaction(trans_id).expect(WRONG_TRANSACTION_ID);
-            assert!(self.env().transferred_balance() == t.transferred_value);
+            assert!(self.env().transferred_value() == t.transferred_value);
             let result = build_call::<<Self as ::ink_lang::reflect::ContractEnv>::Env>()
                 .callee(t.callee)
                 .gas_limit(t.gas_limit)
diff --git a/examples/proxy/.gitignore b/examples/proxy/.gitignore
new file mode 100644
index 0000000000..bf910de10a
--- /dev/null
+++ b/examples/proxy/.gitignore
@@ -0,0 +1,9 @@
+# Ignore build artifacts from the local tests sub-crate.
+/target/
+
+# Ignore backup files creates by cargo fmt.
+**/*.rs.bk
+
+# Remove Cargo.lock when creating an executable, leave it for libraries
+# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
+Cargo.lock
\ No newline at end of file
diff --git a/examples/proxy/Cargo.toml b/examples/proxy/Cargo.toml
new file mode 100644
index 0000000000..2d7ee0a814
--- /dev/null
+++ b/examples/proxy/Cargo.toml
@@ -0,0 +1,40 @@
+[package]
+name = "proxy"
+version = "3.0.0-rc7"
+authors = ["Parity Technologies <admin@parity.io>"]
+edition = "2021"
+
+[dependencies]
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_prelude = { version = "3.0.0-rc7", path = "../../crates/prelude", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
+
+scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"], optional = true }
+
+[lib]
+name = "proxy"
+path = "lib.rs"
+crate-type = ["cdylib"]
+
+# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
+[profile.release]
+overflow-checks = false
+
+[features]
+default = ["std"]
+std = [
+    "ink_primitives/std",
+    "ink_metadata",
+    "ink_metadata/std",
+    "ink_env/std",
+    "ink_storage/std",
+    "ink_lang/std",
+    "scale/std",
+    "scale-info",
+    "scale-info/std",
+]
+ink-as-dependency = []
diff --git a/examples/proxy/README.md b/examples/proxy/README.md
new file mode 100644
index 0000000000..1aaba8b1ca
--- /dev/null
+++ b/examples/proxy/README.md
@@ -0,0 +1,39 @@
+# Proxy Smart Contract
+
+The proxy smart contract forwards any call that does not match a
+selector of itself to another, specified contract.
+
+The instantiator of the proxy contract on a blockchain can change
+the address to which calls are forwarded.
+
+This allows building upgradable contracts following the proxy pattern.
+Note though that the state is still stored in the contract to which
+calls are forwarded.
+
+In order to test it out you need to do the following:
+
+1. Build a contract containing some logic, e.g. our flipper example:
+   ```
+   cargo +nightly contract build --manifest-path=examples/flipper/Cargo.toml
+   ```
+   You will receive the respective `flipper.contract` bundle in the `examples/flipper/target/ink/` folder.
+1. Build the proxy contract:
+   ```
+   cargo +nightly contract build --manifest-path=examples/proxy/Cargo.toml
+   ```
+   You will receive the respective `proxy.contract` bundle in the `examples/proxy/target/ink/` folder.
+1. Upload the `flipper.contract` to the chain.
+1. Upload the `proxy.contract` to the chain. During instantiation specify the just instantiated
+   `flipper` contract as the `forward_to` parameter.
+1. Switch the metadata of the just instantiated `proxy` contract to the metadata of the `flipper`
+   contract. In the `polkadot-js` UI this can be done this way:
+   1. Click the icon left of the instantiated `proxy` contract to copy the address
+      of it into your clipboard.
+   1. Click `Add an existing contract`, insert the just copied address, upload the `flipper.contract`
+      for the `Contract ABI`.
+1. Now you are able to run the operations provided by the `flipper` smart contract via
+   the `proxy` contract.
+
+To change the address of the smart contract where calls are forwarded to you would
+switch the metadata (i.e. the `Contract ABI`) back to the `proxy` contract
+and then invoke the `change_forward_address` message.
diff --git a/examples/proxy/lib.rs b/examples/proxy/lib.rs
new file mode 100644
index 0000000000..1224e54e11
--- /dev/null
+++ b/examples/proxy/lib.rs
@@ -0,0 +1,92 @@
+//! This example demonstrates how the Proxy/Forward pattern can be
+//! implemented in ink!.
+//!
+//! What the contract does is:
+//!
+//!   * Any call to this contract that does not match a selector
+//!     of it is forwarded to a specified address.
+//!   * The instantiator of the contract can modify this specified
+//!     `forward_to` address at any point.
+//!
+//! Using this pattern it is possible to implement upgradable contracts.
+//!
+//! Note though that the contract to which calls are forwarded still
+//! contains it's own state.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+use ink_lang as ink;
+
+#[ink::contract]
+pub mod proxy {
+    /// A simple proxy contract.
+    #[ink(storage)]
+    pub struct Proxy {
+        /// The `AccountId` of a contract where any call that does not match a
+        /// selector of this contract is forwarded to.
+        forward_to: AccountId,
+        /// The `AccountId` of a privileged account that can update the
+        /// forwarding address. This address is set to the account that
+        /// instantiated this contract.
+        admin: AccountId,
+    }
+
+    impl Proxy {
+        /// Instantiate this contract with an address of the `logic` contract.
+        ///
+        /// Sets the privileged account to the caller. Only this account may
+        /// later changed the `forward_to` address.
+        #[ink(constructor)]
+        pub fn new(forward_to: AccountId) -> Self {
+            Self {
+                admin: Self::env().caller(),
+                forward_to,
+            }
+        }
+
+        /// Changes the `AccountId` of the contract where any call that does
+        /// not match a selector of this contract is forwarded to.
+        #[ink(message)]
+        pub fn change_forward_address(&mut self, new_address: AccountId) {
+            assert_eq!(
+                self.env().caller(),
+                self.admin,
+                "caller {:?} does not have sufficient permissions, only {:?} does",
+                self.env().caller(),
+                self.admin,
+            );
+            self.forward_to = new_address;
+        }
+
+        /// Fallback message for a contract call that doesn't match any
+        /// of the other message selectors.
+        ///
+        /// # Note:
+        ///
+        /// - We allow payable messages here and would forward any optionally supplied
+        ///   value as well.
+        /// - If the self receiver were `forward(&mut self)` here, this would not
+        ///   have any effect whatsoever on the contract we forward to.
+        #[ink(message, payable, selector = _)]
+        pub fn forward(&self) -> u32 {
+            ink_env::call::build_call::<ink_env::DefaultEnvironment>()
+                .callee(self.forward_to)
+                .call_flags(
+                    ink_env::CallFlags::default()
+                        .set_forward_input(true)
+                        .set_tail_call(true),
+                )
+                .transferred_value(self.env().transferred_value())
+                .fire()
+                .unwrap_or_else(|err| {
+                    panic!(
+                        "cross-contract call to {:?} failed due to {:?}",
+                        self.forward_to, err
+                    )
+                });
+            unreachable!(
+                "the forwarded call will never return since `tail_call` was set"
+            );
+        }
+    }
+}
diff --git a/examples/rand-extension/Cargo.toml b/examples/rand-extension/Cargo.toml
index ebf92f06bc..f1ff0936b8 100755
--- a/examples/rand-extension/Cargo.toml
+++ b/examples/rand-extension/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "rand_extension"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -19,10 +19,6 @@ name = "rand_extension"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/rand-extension/lib.rs b/examples/rand-extension/lib.rs
index d6033fd82f..bf6740937a 100755
--- a/examples/rand-extension/lib.rs
+++ b/examples/rand-extension/lib.rs
@@ -15,7 +15,7 @@ pub trait FetchRandom {
     /// Note: this gives the operation a corresponding `func_id` (1101 in this case),
     /// and the chain-side chain extension will get the `func_id` to do further operations.
     #[ink(extension = 1101, returns_result = false)]
-    fn fetch_random() -> [u8; 32];
+    fn fetch_random(subject: [u8; 32]) -> [u8; 32];
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)]
@@ -47,7 +47,6 @@ impl Environment for CustomEnvironment {
     type Hash = <ink_env::DefaultEnvironment as Environment>::Hash;
     type BlockNumber = <ink_env::DefaultEnvironment as Environment>::BlockNumber;
     type Timestamp = <ink_env::DefaultEnvironment as Environment>::Timestamp;
-    type RentFraction = <ink_env::DefaultEnvironment as Environment>::RentFraction;
 
     type ChainExtension = FetchRandom;
 }
@@ -86,11 +85,13 @@ mod rand_extension {
             Self::new(Default::default())
         }
 
-        /// Update the value from the runtimes random source.
+        /// Seed a random value by passing some known argument `subject` to the runtime's
+        /// random source. Then, update the current `value` stored in this contract with the
+        /// new random value.
         #[ink(message)]
-        pub fn update(&mut self) -> Result<(), RandomReadErr> {
+        pub fn update(&mut self, subject: [u8; 32]) -> Result<(), RandomReadErr> {
             // Get the on-chain random seed
-            let new_random = self.env().extension().fetch_random()?;
+            let new_random = self.env().extension().fetch_random(subject)?;
             self.value = new_random;
             // Emit the `RandomUpdated` event when the random seed
             // is successfully fetched.
@@ -146,7 +147,7 @@ mod rand_extension {
             assert_eq!(rand_extension.get(), [0; 32]);
 
             // when
-            rand_extension.update().expect("update must work");
+            rand_extension.update([0_u8; 32]).expect("update must work");
 
             // then
             assert_eq!(rand_extension.get(), [1; 32]);
diff --git a/examples/rand-extension/runtime/chain-extension-example.rs b/examples/rand-extension/runtime/chain-extension-example.rs
index 9aa9022d19..ac6ccf8111 100644
--- a/examples/rand-extension/runtime/chain-extension-example.rs
+++ b/examples/rand-extension/runtime/chain-extension-example.rs
@@ -29,7 +29,8 @@ impl ChainExtension<Runtime> for FetchRandomExtension {
         match func_id {
             1101 => {
                 let mut env = env.buf_in_buf_out();
-                let random_seed = crate::RandomnessCollectiveFlip::random_seed().0;
+                let arg: [u8; 32] = env.read_as()?;
+                let random_seed = crate::RandomnessCollectiveFlip::random(&arg).0;
                 let random_slice = random_seed.encode();
                 trace!(
                     target: "runtime",
diff --git a/examples/trait-erc20/Cargo.toml b/examples/trait-erc20/Cargo.toml
index d6c9592f83..d96a78540e 100644
--- a/examples/trait-erc20/Cargo.toml
+++ b/examples/trait-erc20/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "trait_erc20"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -19,10 +19,6 @@ name = "trait_erc20"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/trait-flipper/Cargo.toml b/examples/trait-flipper/Cargo.toml
index 0a0b10269a..6fedcbe5ea 100644
--- a/examples/trait-flipper/Cargo.toml
+++ b/examples/trait-flipper/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "trait_flipper"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -19,10 +19,6 @@ name = "trait_flipper"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/examples/trait-incrementer/Cargo.toml b/examples/trait-incrementer/Cargo.toml
index 6cbbf66cba..e97b082311 100644
--- a/examples/trait-incrementer/Cargo.toml
+++ b/examples/trait-incrementer/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "trait-incrementer"
-version = "3.0.0-rc6"
+version = "3.0.0-rc7"
 authors = ["Parity Technologies <admin@parity.io>"]
 edition = "2021"
 
 [dependencies]
-ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false }
-ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
-ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false }
-ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false }
-ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false }
+ink_primitives = { version = "3.0.0-rc7", path = "../../crates/primitives", default-features = false }
+ink_metadata = { version = "3.0.0-rc7", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc7", path = "../../crates/env", default-features = false }
+ink_storage = { version = "3.0.0-rc7", path = "../../crates/storage", default-features = false }
+ink_lang = { version = "3.0.0-rc7", path = "../../crates/lang", default-features = false }
 
 scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
 scale-info = { version = "1", default-features = false, features = ["derive"], optional = true }
@@ -19,10 +19,6 @@ name = "trait_incrementer"
 path = "lib.rs"
 crate-type = ["cdylib"]
 
-# Needed until https://github.com/paritytech/ink/issues/364 is resolved.
-[profile.release]
-overflow-checks = false
-
 [features]
 default = ["std"]
 std = [
diff --git a/scripts/.ci/trigger_pipeline.sh b/scripts/.ci/trigger_pipeline.sh
index 438700ce1f..40625eb49e 100755
--- a/scripts/.ci/trigger_pipeline.sh
+++ b/scripts/.ci/trigger_pipeline.sh
@@ -26,9 +26,10 @@ curl --silent \
 
 PIPELINE_ID=$(cat pipeline | jq ".id")
 PIPELINE_URL=$(cat pipeline | jq ".web_url")
-echo
+echo ""
 echo "ink-waterfall pipeline ${PIPELINE_URL} was successfully triggered."
 echo "Now we're polling it to obtain the distinguished status."
+echo ""
 
 # This is a workaround for a Gitlab bug, waits here until
 # https://gitlab.com/gitlab-org/gitlab/-/issues/326137 gets fixed.


Test patch:
diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs
index b8fd7179d5..b24ec56b7b 100644
--- a/crates/engine/src/tests.rs
+++ b/crates/engine/src/tests.rs
@@ -16,9 +16,11 @@ use crate::ext::{
     Engine,
     Error,
 };
-use libsecp256k1::{
+use secp256k1::{
+    recovery::RecoverableSignature,
     Message,
     PublicKey,
+    Secp256k1,
     SecretKey,
 };
 
@@ -236,11 +238,12 @@ fn ecdsa_recovery_test_from_contracts_pallet() {
 fn ecdsa_recovery_with_secp256k1_crate() {
     // given
     let mut engine = Engine::new();
+    let secp = Secp256k1::new();
     let seckey = [
         59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203,
         174, 253, 102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28,
     ];
-    let pubkey = PublicKey::parse_compressed(&[
+    let pubkey = PublicKey::from_slice(&[
         2, 29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, 245,
         41, 91, 141, 134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54,
     ])
@@ -249,12 +252,14 @@ fn ecdsa_recovery_with_secp256k1_crate() {
     let mut msg_hash = [0; 32];
     crate::hashing::sha2_256(b"Some message", &mut msg_hash);
 
-    let msg = Message::parse(&msg_hash);
-    let seckey = SecretKey::parse(&seckey).expect("secret key creation failed");
-    let (signature, recovery_id) = libsecp256k1::sign(&msg, &seckey);
+    let msg = Message::from_slice(&msg_hash).expect("message creation failed");
+    let seckey = SecretKey::from_slice(&seckey).expect("secret key creation failed");
+    let recoverable_signature: RecoverableSignature =
+        secp.sign_recoverable(&msg, &seckey);
 
-    let mut signature = signature.serialize().to_vec();
-    signature.push(recovery_id.serialize());
+    let recovery_id = recoverable_signature.serialize_compact().0.to_i32() as u8;
+    let mut signature = recoverable_signature.serialize_compact().1.to_vec();
+    signature.push(recovery_id);
     let signature_with_recovery_id: [u8; 65] = signature
         .try_into()
         .expect("unable to create signature with recovery id");
@@ -262,9 +267,9 @@ fn ecdsa_recovery_with_secp256k1_crate() {
     // when
     let mut output = [0; 33];
     engine
-        .ecdsa_recover(&signature_with_recovery_id, &msg.serialize(), &mut output)
+        .ecdsa_recover(&signature_with_recovery_id, msg.as_ref(), &mut output)
         .expect("ecdsa recovery failed");
 
     // then
-    assert_eq!(output, pubkey.serialize_compressed());
+    assert_eq!(output, pubkey.serialize());
 }
diff --git a/crates/env/src/engine/experimental_off_chain/test_api.rs b/crates/env/src/engine/experimental_off_chain/test_api.rs
index aebdb46c7b..7bedddf04e 100644
--- a/crates/env/src/engine/experimental_off_chain/test_api.rs
+++ b/crates/env/src/engine/experimental_off_chain/test_api.rs
@@ -82,41 +82,6 @@ where
     })
 }
 
-/// Sets the rent allowance of the contract account to the given rent allowance.
-///
-/// # Errors
-///
-/// - If `account` does not exist.
-/// - If the underlying `account` type does not match.
-/// - If the underlying `new_rent_allowance` type does not match.
-pub fn set_contract_rent_allowance<T>(
-    _account_id: T::AccountId,
-    _new_rent_allowance: T::Balance,
-) -> Result<()>
-where
-    T: Environment,
-{
-    unimplemented!(
-        "off-chain environment does not yet support `set_contract_rent_allowance`"
-    );
-}
-
-/// Returns the rent allowance of the contract account.
-///
-/// # Errors
-///
-/// - If `account` does not exist.
-/// - If the underlying `account` type does not match.
-/// - If the returned rent allowance cannot be properly decoded.
-pub fn get_contract_rent_allowance<T>(_account_id: T::AccountId) -> Result<T::Balance>
-where
-    T: Environment,
-{
-    unimplemented!(
-        "off-chain environment does not yet support `get_contract_rent_allowance`"
-    );
-}
-
 /// Set the entropy hash of the current block.
 ///
 /// # Note
diff --git a/crates/env/src/engine/off_chain/test_api.rs b/crates/env/src/engine/off_chain/test_api.rs
index ff3e9c8236..e7048f80f2 100644
--- a/crates/env/src/engine/off_chain/test_api.rs
+++ b/crates/env/src/engine/off_chain/test_api.rs
@@ -130,55 +130,6 @@ where
     })
 }
 
-/// Sets the rent allowance of the contract account to the given rent allowance.
-///
-/// # Errors
-///
-/// - If `account` does not exist.
-/// - If the underlying `account` type does not match.
-/// - If the underlying `new_rent_allowance` type does not match.
-pub fn set_contract_rent_allowance<T>(
-    account_id: T::AccountId,
-    new_rent_allowance: T::Balance,
-) -> Result<()>
-where
-    T: Environment,
-{
-    <EnvInstance as OnInstance>::on_instance(|instance| {
-        instance
-            .accounts
-            .get_account_mut::<T>(&account_id)
-            .ok_or_else(|| AccountError::no_account_for_id::<T>(&account_id))
-            .map_err(Into::into)
-            .and_then(|account| {
-                account
-                    .set_rent_allowance::<T>(new_rent_allowance)
-                    .map_err(Into::into)
-            })
-    })
-}
-
-/// Returns the rent allowance of the contract account.
-///
-/// # Errors
-///
-/// - If `account` does not exist.
-/// - If the underlying `account` type does not match.
-/// - If the returned rent allowance cannot be properly decoded.
-pub fn get_contract_rent_allowance<T>(account_id: T::AccountId) -> Result<T::Balance>
-where
-    T: Environment,
-{
-    <EnvInstance as OnInstance>::on_instance(|instance| {
-        instance
-            .accounts
-            .get_account::<T>(&account_id)
-            .ok_or_else(|| AccountError::no_account_for_id::<T>(&account_id))
-            .map_err(Into::into)
-            .and_then(|account| account.rent_allowance::<T>().map_err(Into::into))
-    })
-}
-
 /// Registers a new chain extension.
 pub fn register_chain_extension<E>(extension: E)
 where
diff --git a/crates/lang/tests/ui/chain_extension/E-01-simple.rs b/crates/lang/tests/ui/chain_extension/E-01-simple.rs
index 6ef333f61f..96bbfef087 100644
--- a/crates/lang/tests/ui/chain_extension/E-01-simple.rs
+++ b/crates/lang/tests/ui/chain_extension/E-01-simple.rs
@@ -117,7 +117,6 @@ impl Environment for CustomEnvironment {
     type Hash = <ink_env::DefaultEnvironment as Environment>::Hash;
     type BlockNumber = <ink_env::DefaultEnvironment as Environment>::BlockNumber;
     type Timestamp = <ink_env::DefaultEnvironment as Environment>::Timestamp;
-    type RentFraction = <ink_env::DefaultEnvironment as Environment>::RentFraction;
 
     type ChainExtension = RuntimeReadWrite;
 }
diff --git a/crates/lang/tests/ui/contract/fail/constructor-multiple-wildcard-selectors.rs b/crates/lang/tests/ui/contract/fail/constructor-multiple-wildcard-selectors.rs
new file mode 100644
index 0000000000..483c00ea59
--- /dev/null
+++ b/crates/lang/tests/ui/contract/fail/constructor-multiple-wildcard-selectors.rs
@@ -0,0 +1,24 @@
+use ink_lang as ink;
+
+#[ink::contract]
+mod contract {
+    #[ink(storage)]
+    pub struct Contract {}
+
+    impl Contract {
+        #[ink(constructor, selector = _)]
+        pub fn constructor1() -> Self {
+            Self {}
+        }
+
+        #[ink(constructor, selector = _)]
+        pub fn constructor2() -> Self {
+            Self {}
+        }
+
+        #[ink(message)]
+        pub fn message(&self) {}
+    }
+}
+
+fn main() {}
diff --git a/crates/lang/tests/ui/contract/fail/constructor-multiple-wildcard-selectors.stderr b/crates/lang/tests/ui/contract/fail/constructor-multiple-wildcard-selectors.stderr
new file mode 100644
index 0000000000..658bd70614
--- /dev/null
+++ b/crates/lang/tests/ui/contract/fail/constructor-multiple-wildcard-selectors.stderr
@@ -0,0 +1,15 @@
+error: encountered ink! constructor with overlapping wildcard selectors
+  --> tests/ui/contract/fail/constructor-multiple-wildcard-selectors.rs:15:9
+   |
+15 | /         pub fn constructor2() -> Self {
+16 | |             Self {}
+17 | |         }
+   | |_________^
+
+error: first ink! constructor with overlapping wildcard selector here
+  --> tests/ui/contract/fail/constructor-multiple-wildcard-selectors.rs:10:9
+   |
+10 | /         pub fn constructor1() -> Self {
+11 | |             Self {}
+12 | |         }
+   | |_________^
diff --git a/crates/lang/tests/ui/contract/fail/constructor-selector-and-wildcard-selector.rs b/crates/lang/tests/ui/contract/fail/constructor-selector-and-wildcard-selector.rs
new file mode 100644
index 0000000000..70025d254a
--- /dev/null
+++ b/crates/lang/tests/ui/contract/fail/constructor-selector-and-wildcard-selector.rs
@@ -0,0 +1,19 @@
+use ink_lang as ink;
+
+#[ink::contract]
+mod contract {
+    #[ink(storage)]
+    pub struct Contract {}
+
+    impl Contract {
+        #[ink(constructor, selector = 0xCAFEBABA, selector = _)]
+        pub fn constructor() -> Self {
+            Self {}
+        }
+
+        #[ink(message)]
+        pub fn message(&self) {}
+    }
+}
+
+fn main() {}
diff --git a/crates/lang/tests/ui/contract/fail/constructor-selector-and-wildcard-selector.stderr b/crates/lang/tests/ui/contract/fail/constructor-selector-and-wildcard-selector.stderr
new file mode 100644
index 0000000000..9c2c985c23
--- /dev/null
+++ b/crates/lang/tests/ui/contract/fail/constructor-selector-and-wildcard-selector.stderr
@@ -0,0 +1,11 @@
+error: encountered ink! attribute arguments with equal kinds
+ --> tests/ui/contract/fail/constructor-selector-and-wildcard-selector.rs:9:51
+  |
+9 |         #[ink(constructor, selector = 0xCAFEBABA, selector = _)]
+  |                                                   ^^^^^^^^^^^^
+
+error: first equal ink! attribute argument with equal kind here
+ --> tests/ui/contract/fail/constructor-selector-and-wildcard-selector.rs:9:28
+  |
+9 |         #[ink(constructor, selector = 0xCAFEBABA, selector = _)]
+  |                            ^^^^^^^^^^^^^^^^^^^^^
diff --git a/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.rs b/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.rs
index 7ef6b7499e..64fa8d5e04 100644
--- a/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.rs
+++ b/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.rs
@@ -15,7 +15,6 @@ impl ink_env::Environment for EnvironmentMoreTopics {
     type Timestamp = <DefaultEnvironment as Environment>::Timestamp;
     type BlockNumber = <DefaultEnvironment as Environment>::BlockNumber;
     type ChainExtension = ();
-    type RentFraction = <DefaultEnvironment as Environment>::RentFraction;
 }
 
 #[ink::contract(env = super::EnvironmentMoreTopics)]
diff --git a/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr b/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr
index 026ef1c4dd..57c4886dc1 100644
--- a/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr
+++ b/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr
@@ -1,13 +1,13 @@
 error[E0277]: the trait bound `EventTopics<4_usize>: RespectTopicLimit<2_usize>` is not satisfied
-  --> tests/ui/contract/fail/event-too-many-topics-anonymous.rs:27:5
+  --> tests/ui/contract/fail/event-too-many-topics-anonymous.rs:26:5
    |
-27 | /     pub struct Event {
-28 | |         #[ink(topic)]
-29 | |         arg_1: i8,
-30 | |         #[ink(topic)]
+26 | /     pub struct Event {
+27 | |         #[ink(topic)]
+28 | |         arg_1: i8,
+29 | |         #[ink(topic)]
 ...  |
-35 | |         arg_4: i32,
-36 | |     }
+34 | |         arg_4: i32,
+35 | |     }
    | |_____^ the trait `RespectTopicLimit<2_usize>` is not implemented for `EventTopics<4_usize>`
    |
    = help: the following implementations were found:
@@ -17,7 +17,7 @@ error[E0277]: the trait bound `EventTopics<4_usize>: RespectTopicLimit<2_usize>`
              <EventTopics<0_usize> as RespectTopicLimit<12_usize>>
            and 87 others
 note: required by a bound in `EventRespectsTopicLimit`
-  --> src/codegen/event/topics.rs:48:43
+  --> src/codegen/event/topics.rs
    |
-48 |     <Event as EventLenTopics>::LenTopics: RespectTopicLimit<LEN_MAX_TOPICS>,
+   |     <Event as EventLenTopics>::LenTopics: RespectTopicLimit<LEN_MAX_TOPICS>,
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EventRespectsTopicLimit`
diff --git a/crates/lang/tests/ui/contract/fail/event-too-many-topics.rs b/crates/lang/tests/ui/contract/fail/event-too-many-topics.rs
index c3834db8d9..659b047c44 100644
--- a/crates/lang/tests/ui/contract/fail/event-too-many-topics.rs
+++ b/crates/lang/tests/ui/contract/fail/event-too-many-topics.rs
@@ -15,7 +15,6 @@ impl ink_env::Environment for EnvironmentMoreTopics {
     type Timestamp = <DefaultEnvironment as Environment>::Timestamp;
     type BlockNumber = <DefaultEnvironment as Environment>::BlockNumber;
     type ChainExtension = ();
-    type RentFraction = <DefaultEnvironment as Environment>::RentFraction;
 }
 
 #[ink::contract(env = super::EnvironmentMoreTopics)]
diff --git a/crates/lang/tests/ui/contract/fail/event-too-many-topics.stderr b/crates/lang/tests/ui/contract/fail/event-too-many-topics.stderr
index 4ae2bbb32c..ad6aff4311 100644
--- a/crates/lang/tests/ui/contract/fail/event-too-many-topics.stderr
+++ b/crates/lang/tests/ui/contract/fail/event-too-many-topics.stderr
@@ -1,13 +1,13 @@
 error[E0277]: the trait bound `EventTopics<3_usize>: RespectTopicLimit<2_usize>` is not satisfied
-  --> tests/ui/contract/fail/event-too-many-topics.rs:27:5
+  --> tests/ui/contract/fail/event-too-many-topics.rs:26:5
    |
-27 | /     pub struct Event {
-28 | |         #[ink(topic)]
-29 | |         arg_1: i8,
-30 | |         #[ink(topic)]
+26 | /     pub struct Event {
+27 | |         #[ink(topic)]
+28 | |         arg_1: i8,
+29 | |         #[ink(topic)]
 ...  |
-33 | |         arg_3: i32,
-34 | |     }
+32 | |         arg_3: i32,
+33 | |     }
    | |_____^ the trait `RespectTopicLimit<2_usize>` is not implemented for `EventTopics<3_usize>`
    |
    = help: the following implementations were found:
@@ -17,7 +17,7 @@ error[E0277]: the trait bound `EventTopics<3_usize>: RespectTopicLimit<2_usize>`
              <EventTopics<0_usize> as RespectTopicLimit<12_usize>>
            and 87 others
 note: required by a bound in `EventRespectsTopicLimit`
-  --> src/codegen/event/topics.rs:48:43
+  --> src/codegen/event/topics.rs
    |
-48 |     <Event as EventLenTopics>::LenTopics: RespectTopicLimit<LEN_MAX_TOPICS>,
+   |     <Event as EventLenTopics>::LenTopics: RespectTopicLimit<LEN_MAX_TOPICS>,
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EventRespectsTopicLimit`
diff --git a/crates/lang/tests/ui/contract/fail/message-multiple-wildcard-selectors.rs b/crates/lang/tests/ui/contract/fail/message-multiple-wildcard-selectors.rs
new file mode 100644
index 0000000000..0eb135fcdc
--- /dev/null
+++ b/crates/lang/tests/ui/contract/fail/message-multiple-wildcard-selectors.rs
@@ -0,0 +1,22 @@
+use ink_lang as ink;
+
+#[ink::contract]
+mod contract {
+    #[ink(storage)]
+    pub struct Contract {}
+
+    impl Contract {
+        #[ink(constructor)]
+        pub fn constructor() -> Self {
+            Self {}
+        }
+
+        #[ink(message, selector = _)]
+        pub fn message1(&self) {}
+
+        #[ink(message, selector = _)]
+        pub fn message2(&self) {}
+    }
+}
+
+fn main() {}
diff --git a/crates/lang/tests/ui/contract/fail/message-multiple-wildcard-selectors.stderr b/crates/lang/tests/ui/contract/fail/message-multiple-wildcard-selectors.stderr
new file mode 100644
index 0000000000..d063519224
--- /dev/null
+++ b/crates/lang/tests/ui/contract/fail/message-multiple-wildcard-selectors.stderr
@@ -0,0 +1,11 @@
+error: encountered ink! messages with overlapping wildcard selectors
+  --> tests/ui/contract/fail/message-multiple-wildcard-selectors.rs:18:9
+   |
+18 |         pub fn message2(&self) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: first ink! message with overlapping wildcard selector here
+  --> tests/ui/contract/fail/message-multiple-wildcard-selectors.rs:15:9
+   |
+15 |         pub fn message1(&self) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/crates/lang/tests/ui/contract/fail/message-selector-and-wildcard-selector.rs b/crates/lang/tests/ui/contract/fail/message-selector-and-wildcard-selector.rs
new file mode 100644
index 0000000000..ce19e5d0de
--- /dev/null
+++ b/crates/lang/tests/ui/contract/fail/message-selector-and-wildcard-selector.rs
@@ -0,0 +1,19 @@
+use ink_lang as ink;
+
+#[ink::contract]
+mod contract {
+    #[ink(storage)]
+    pub struct Contract {}
+
+    impl Contract {
+        #[ink(constructor)]
+        pub fn constructor() -> Self {
+            Self {}
+        }
+
+        #[ink(message, selector = 0xCAFEBABA, selector = _)]
+        pub fn message(&self) {}
+    }
+}
+
+fn main() {}
diff --git a/crates/lang/tests/ui/contract/fail/message-selector-and-wildcard-selector.stderr b/crates/lang/tests/ui/contract/fail/message-selector-and-wildcard-selector.stderr
new file mode 100644
index 0000000000..246e1a606e
--- /dev/null
+++ b/crates/lang/tests/ui/contract/fail/message-selector-and-wildcard-selector.stderr
@@ -0,0 +1,11 @@
+error: encountered ink! attribute arguments with equal kinds
+  --> tests/ui/contract/fail/message-selector-and-wildcard-selector.rs:14:47
+   |
+14 |         #[ink(message, selector = 0xCAFEBABA, selector = _)]
+   |                                               ^^^^^^^^^^^^
+
+error: first equal ink! attribute argument with equal kind here
+  --> tests/ui/contract/fail/message-selector-and-wildcard-selector.rs:14:24
+   |
+14 |         #[ink(message, selector = 0xCAFEBABA, selector = _)]
+   |                        ^^^^^^^^^^^^^^^^^^^^^
diff --git a/crates/lang/tests/ui/contract/fail/message-selector-invalid-type-02.stderr b/crates/lang/tests/ui/contract/fail/message-selector-invalid-type-02.stderr
index f261b80a9b..893067fe7c 100644
--- a/crates/lang/tests/ui/contract/fail/message-selector-invalid-type-02.stderr
+++ b/crates/lang/tests/ui/contract/fail/message-selector-invalid-type-02.stderr
@@ -1,4 +1,4 @@
-error: expecteded 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE]
+error: expected 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE]
   --> tests/ui/contract/fail/message-selector-invalid-type-02.rs:14:24
    |
 14 |         #[ink(message, selector = true)]
diff --git a/crates/lang/tests/ui/contract/fail/trait-message-wildcard-selector.rs b/crates/lang/tests/ui/contract/fail/trait-message-wildcard-selector.rs
new file mode 100644
index 0000000000..e5b2d161ee
--- /dev/null
+++ b/crates/lang/tests/ui/contract/fail/trait-message-wildcard-selector.rs
@@ -0,0 +1,33 @@
+mod foo {
+    use ink_lang as ink;
+
+    #[ink::trait_definition]
+    pub trait TraitDefinition {
+        #[ink(message, selector = _)]
+        fn message(&self);
+    }
+}
+
+use ink_lang as ink;
+
+#[ink::contract]
+pub mod contract {
+    use super::foo::TraitDefinition;
+
+    #[ink(storage)]
+    pub struct Contract {}
+
+    impl Contract {
+        #[ink(constructor)]
+        pub fn constructor() -> Self {
+            Self {}
+        }
+    }
+
+    impl TraitDefinition for Contract {
+        #[ink(message)]
+        fn message(&self) {}
+    }
+}
+
+fn main() {}
diff --git a/crates/lang/tests/ui/contract/fail/trait-message-wildcard-selector.stderr b/crates/lang/tests/ui/contract/fail/trait-message-wildcard-selector.stderr
new file mode 100644
index 0000000000..a9c620180a
--- /dev/null
+++ b/crates/lang/tests/ui/contract/fail/trait-message-wildcard-selector.stderr
@@ -0,0 +1,17 @@
+error: encountered conflicting ink! attribute argument
+ --> tests/ui/contract/fail/trait-message-wildcard-selector.rs:6:24
+  |
+6 |         #[ink(message, selector = _)]
+  |                        ^^^^^^^^^^^^
+
+error: wildcard selectors are only supported for inherent ink! messages or constructors, not for traits.
+ --> tests/ui/contract/fail/trait-message-wildcard-selector.rs:6:24
+  |
+6 |         #[ink(message, selector = _)]
+  |                        ^^^^^^^^^^^^
+
+error[E0432]: unresolved import `super::foo::TraitDefinition`
+  --> tests/ui/contract/fail/trait-message-wildcard-selector.rs:15:9
+   |
+15 |     use super::foo::TraitDefinition;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `TraitDefinition` in `foo`
diff --git a/crates/lang/tests/ui/contract/pass/config-custom-env.rs b/crates/lang/tests/ui/contract/pass/config-custom-env.rs
index 613205f007..90958764ac 100644
--- a/crates/lang/tests/ui/contract/pass/config-custom-env.rs
+++ b/crates/lang/tests/ui/contract/pass/config-custom-env.rs
@@ -10,9 +10,6 @@ impl ink_env::Environment for CustomEnv {
     type Timestamp = u64;
     type BlockNumber = u64;
     type ChainExtension = ();
-    // Too lazy to define a test type that fits the required trait bounds.
-    type RentFraction =
-        <ink_env::DefaultEnvironment as ink_env::Environment>::RentFraction;
 }
 
 #[ink::contract(env = super::CustomEnv)]
diff --git a/crates/lang/tests/ui/contract/pass/constructor-wildcard-selector.rs b/crates/lang/tests/ui/contract/pass/constructor-wildcard-selector.rs
new file mode 100644
index 0000000000..9c2dbe8a39
--- /dev/null
+++ b/crates/lang/tests/ui/contract/pass/constructor-wildcard-selector.rs
@@ -0,0 +1,19 @@
+use ink_lang as ink;
+
+#[ink::contract]
+mod contract {
+    #[ink(storage)]
+    pub struct Contract {}
+
+    impl Contract {
+        #[ink(constructor, selector = _)]
+        pub fn constructor() -> Self {
+            Self {}
+        }
+
+        #[ink(message)]
+        pub fn message(&self) {}
+    }
+}
+
+fn main() {}
diff --git a/crates/lang/tests/ui/contract/pass/env-access.rs b/crates/lang/tests/ui/contract/pass/env-access.rs
index 46437085c5..7717040742 100644
--- a/crates/lang/tests/ui/contract/pass/env-access.rs
+++ b/crates/lang/tests/ui/contract/pass/env-access.rs
@@ -16,7 +16,7 @@ mod contract {
             let _ = Self::env().gas_left();
             let _ = Self::env().minimum_balance();
             let _ = Self::env().random(&[]);
-            let _ = Self::env().transferred_balance();
+            let _ = Self::env().transferred_value();
             let _ = Self::env().weight_to_fee(0);
             Self {}
         }
@@ -31,7 +31,7 @@ mod contract {
             let _ = self.env().gas_left();
             let _ = self.env().minimum_balance();
             let _ = self.env().random(&[]);
-            let _ = self.env().transferred_balance();
+            let _ = self.env().transferred_value();
             let _ = self.env().weight_to_fee(0);
         }
     }
diff --git a/crates/lang/tests/ui/contract/pass/event-config-more-topics.rs b/crates/lang/tests/ui/contract/pass/event-config-more-topics.rs
index e7b73525a8..7e357a7614 100644
--- a/crates/lang/tests/ui/contract/pass/event-config-more-topics.rs
+++ b/crates/lang/tests/ui/contract/pass/event-config-more-topics.rs
@@ -15,7 +15,6 @@ impl ink_env::Environment for EnvironmentMoreTopics {
     type Timestamp = <DefaultEnvironment as Environment>::Timestamp;
     type BlockNumber = <DefaultEnvironment as Environment>::BlockNumber;
     type ChainExtension = ();
-    type RentFraction = <DefaultEnvironment as Environment>::RentFraction;
 }
 
 #[ink::contract(env = super::EnvironmentMoreTopics)]
diff --git a/crates/lang/tests/ui/contract/pass/message-wildcard-selector.rs b/crates/lang/tests/ui/contract/pass/message-wildcard-selector.rs
new file mode 100644
index 0000000000..7f27e48a4b
--- /dev/null
+++ b/crates/lang/tests/ui/contract/pass/message-wildcard-selector.rs
@@ -0,0 +1,25 @@
+use ink_lang as ink;
+
+#[ink::contract]
+mod contract {
+    #[ink(storage)]
+    pub struct Contract {}
+
+    impl Contract {
+        #[ink(constructor)]
+        pub fn constructor() -> Self {
+            Self {}
+        }
+
+        #[ink(message)]
+        pub fn message_0(&self) {}
+
+        #[ink(message, selector = 1)]
+        pub fn message_1(&self) {}
+
+        #[ink(message, selector = _)]
+        pub fn message_2(&self) {}
+    }
+}
+
+fn main() {}
diff --git a/crates/lang/tests/ui/trait_def/fail/message_selector_invalid_1.stderr b/crates/lang/tests/ui/trait_def/fail/message_selector_invalid_1.stderr
index 33da5adc7d..1de6c7b6c3 100644
--- a/crates/lang/tests/ui/trait_def/fail/message_selector_invalid_1.stderr
+++ b/crates/lang/tests/ui/trait_def/fail/message_selector_invalid_1.stderr
@@ -1,4 +1,4 @@
-error: expecteded 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE]
+error: expected 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE]
  --> tests/ui/trait_def/fail/message_selector_invalid_1.rs:5:20
   |
 5 |     #[ink(message, selector = true)]
diff --git a/crates/metadata/src/tests.rs b/crates/metadata/src/tests.rs
index aefa57d6fc..3e1c8031ab 100644
--- a/crates/metadata/src/tests.rs
+++ b/crates/metadata/src/tests.rs
@@ -23,8 +23,8 @@ use serde_json::json;
 #[test]
 fn spec_constructor_selector_must_serialize_to_hex() {
     // given
-    let name = "foo";
-    let cs = ConstructorSpec::from_name(name)
+    let label = "foo";
+    let cs = ConstructorSpec::from_label(label)
         .selector(123_456_789u32.to_be_bytes())
         .done();
     let mut registry = Registry::new();
@@ -39,7 +39,7 @@ fn spec_constructor_selector_must_serialize_to_hex() {
     assert_eq!(
         json,
         json!({
-            "name": ["foo"],
+            "label": "foo",
             "selector": "0x075bcd15",
             "args": [],
             "docs": []
@@ -53,7 +53,7 @@ fn spec_contract_json() {
     // given
     let contract: ContractSpec = ContractSpec::new()
         .constructors(vec![
-            ConstructorSpec::from_name("new")
+            ConstructorSpec::from_label("new")
                 .selector([94u8, 189u8, 136u8, 214u8])
                 .args(vec![MessageParamSpec::new("init_value")
                     .of_type(TypeSpec::with_name_segs::<i32, _>(
@@ -62,14 +62,14 @@ fn spec_contract_json() {
                     .done()])
                 .docs(Vec::new())
                 .done(),
-            ConstructorSpec::from_name("default")
+            ConstructorSpec::from_label("default")
                 .selector([2u8, 34u8, 255u8, 24u8])
                 .args(Vec::new())
                 .docs(Vec::new())
                 .done(),
         ])
         .messages(vec![
-            MessageSpec::from_name("inc")
+            MessageSpec::from_label("inc")
                 .selector([231u8, 208u8, 89u8, 15u8])
                 .mutates(true)
                 .payable(true)
@@ -81,7 +81,7 @@ fn spec_contract_json() {
                 .docs(Vec::new())
                 .returns(ReturnTypeSpec::new(None))
                 .done(),
-            MessageSpec::from_name("get")
+            MessageSpec::from_label("get")
                 .selector([37u8, 68u8, 74u8, 254u8])
                 .mutates(false)
                 .payable(false)
@@ -109,7 +109,7 @@ fn spec_contract_json() {
                 {
                     "args": [
                         {
-                            "name": "init_value",
+                            "label": "init_value",
                             "type": {
                                 "displayName": [
                                     "i32"
@@ -119,13 +119,13 @@ fn spec_contract_json() {
                         }
                     ],
                     "docs": [],
-                    "name": ["new"],
+                    "label": "new",
                     "selector": "0x5ebd88d6"
                 },
                 {
                     "args": [],
                     "docs": [],
-                    "name": ["default"],
+                    "label": "default",
                     "selector": "0x0222ff18"
                 }
             ],
@@ -135,7 +135,7 @@ fn spec_contract_json() {
                 {
                     "args": [
                         {
-                            "name": "by",
+                            "label": "by",
                             "type": {
                                 "displayName": [
                                     "i32"
@@ -147,7 +147,7 @@ fn spec_contract_json() {
                     "docs": [],
                     "mutates": true,
                     "payable": true,
-                    "name": ["inc"],
+                    "label": "inc",
                     "returnType": null,
                     "selector": "0xe7d0590f"
                 },
@@ -156,7 +156,7 @@ fn spec_contract_json() {
                     "docs": [],
                     "mutates": false,
                     "payable": false,
-                    "name": ["get"],
+                    "label": "get",
                     "returnType": {
                         "displayName": [
                             "i32"
@@ -173,8 +173,8 @@ fn spec_contract_json() {
 #[test]
 fn trim_docs() {
     // given
-    let name = "foo";
-    let cs = ConstructorSpec::from_name(name)
+    let label = "foo";
+    let cs = ConstructorSpec::from_label(label)
         .selector(123_456_789u32.to_be_bytes())
         .docs(vec![" foobar      "])
         .done();
@@ -190,7 +190,7 @@ fn trim_docs() {
     assert_eq!(
         json,
         json!({
-            "name": ["foo"],
+            "label": "foo",
             "selector": "0x075bcd15",
             "args": [],
             "docs": ["foobar"]