Repository: paritytech/ink
Pull request #663 (2021-01-28 11:25:58)

Update to new scale-info and codec releases
Related https://github.com/paritytech/cargo-contract/pull/164


Patch:
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 514cd9c15a..137cdaa97f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -169,15 +169,17 @@ codecov:
     - cargo build --verbose --all-features --workspace
     - cargo test --verbose --all-features --no-fail-fast --workspace
     # coverage with branches
-    - grcov ./target -s . -t lcov --llvm --branch --ignore-not-existing --ignore "/*" --ignore "tests/*" -o lcov-w-branch.info
-    - rust-covfix -o lcov-w-branch.info lcov-w-branch.info
+    - grcov . --source-dir . --output-type lcov --llvm --branch --ignore-not-existing
+        --ignore "/*" --ignore "tests/*" --output-path lcov-w-branch.info
+    - rust-covfix lcov-w-branch.info --output lcov-w-branch-fixed.info
     # We'd like to not use a remote bash script for uploading the coverage reports,
     # however this job seems to be more tricky than we hoped.
-    - bash <(curl -s https://codecov.io/bash) -t "$CODECOV_P_TOKEN" -f lcov-w-branch.info
+    - bash <(curl -s https://codecov.io/bash) -t "$CODECOV_P_TOKEN" -f lcov-w-branch-fixed.info
     # lines coverage
-    - grcov ./target -s . -t lcov --llvm --ignore-not-existing --ignore "/*" --ignore "tests/*" -o lcov-lines.info
-    - rust-covfix -o lcov-lines.info lcov-lines.info
-    - bash <(curl -s https://codecov.io/bash) -f lcov-lines.info
+    - grcov . --source-dir . --output-type lcov --llvm --ignore-not-existing
+        --ignore "/*" --ignore "tests/*" --output-path lcov-lines.info
+    - rust-covfix lcov-lines.info --output lcov-lines-fixed.info
+    - bash <(curl -s https://codecov.io/bash) -f lcov-lines-fixed.info
 
 clippy-std:
   stage:                           workspace
diff --git a/crates/env/Cargo.toml b/crates/env/Cargo.toml
index 04b54a7b4f..0b353d459a 100644
--- a/crates/env/Cargo.toml
+++ b/crates/env/Cargo.toml
@@ -20,7 +20,7 @@ ink_allocator = { version = "3.0.0-rc2", path = "../allocator/", default-feature
 ink_primitives = { version = "3.0.0-rc2", path = "../primitives/", default-features = false }
 ink_prelude = { version = "3.0.0-rc2", path = "../prelude/", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive", "full"] }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive", "full"] }
 derive_more = { version = "0.99", default-features = false, features = ["from", "display"] }
 num-traits = { version = "0.2", default-features = false, features = ["i128"] }
 cfg-if = "1.0"
@@ -38,7 +38,7 @@ blake2 = { version = "0.9", optional = true }
 # Sadly couldn't be marked as dev-dependency.
 # Never use this crate outside of the off-chain environment!
 rand = { version = "0.8", default-features = false, features = ["alloc"], optional = true }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 [features]
 default = ["std"]
diff --git a/crates/env/src/call/execution_input.rs b/crates/env/src/call/execution_input.rs
index 180f8baa82..148dda60b9 100644
--- a/crates/env/src/call/execution_input.rs
+++ b/crates/env/src/call/execution_input.rs
@@ -152,7 +152,7 @@ where
     }
 
     #[inline]
-    fn encode_to<O: scale::Output>(&self, output: &mut O) {
+    fn encode_to<O: scale::Output + ?Sized>(&self, output: &mut O) {
         <T as scale::Encode>::encode_to(&self.arg, output)
     }
 }
@@ -164,7 +164,7 @@ impl scale::Encode for EmptyArgumentList {
     }
 
     #[inline]
-    fn encode_to<O: scale::Output>(&self, _output: &mut O) {}
+    fn encode_to<O: scale::Output + ?Sized>(&self, _output: &mut O) {}
 }
 
 impl<'a, Head, Rest> scale::Encode for ArgumentList<Argument<Head>, Rest>
@@ -178,7 +178,7 @@ where
     }
 
     #[inline]
-    fn encode_to<O: scale::Output>(&self, output: &mut O) {
+    fn encode_to<O: scale::Output + ?Sized>(&self, output: &mut O) {
         // We reverse the order of encoding because we build up the list of
         // arguments in reverse order, too. This way we encode the arguments
         // in the same order in which they have been pushed to the argument list
@@ -198,7 +198,7 @@ where
     }
 
     #[inline]
-    fn encode_to<O: scale::Output>(&self, output: &mut O) {
+    fn encode_to<O: scale::Output + ?Sized>(&self, output: &mut O) {
         scale::Encode::encode_to(&self.selector, output);
         scale::Encode::encode_to(&self.args, output);
     }
diff --git a/crates/env/src/engine/off_chain/call_data.rs b/crates/env/src/engine/off_chain/call_data.rs
index 156cea4390..b6b4dbf88a 100644
--- a/crates/env/src/engine/off_chain/call_data.rs
+++ b/crates/env/src/engine/off_chain/call_data.rs
@@ -74,7 +74,7 @@ impl scale::Encode for CallData {
         self.bytes.len()
     }
 
-    fn encode_to<T: scale::Output>(&self, dest: &mut T) {
+    fn encode_to<T: scale::Output + ?Sized>(&self, dest: &mut T) {
         dest.write(self.bytes.as_slice());
     }
 }
diff --git a/crates/env/src/topics.rs b/crates/env/src/topics.rs
index d2d8249926..54afc37ce6 100644
--- a/crates/env/src/topics.rs
+++ b/crates/env/src/topics.rs
@@ -229,7 +229,7 @@ where
     }
 
     #[inline]
-    fn encode_to<T: scale::Output>(&self, dest: &mut T) {
+    fn encode_to<T: scale::Output + ?Sized>(&self, dest: &mut T) {
         self.prefix.encode_to(dest);
         self.value.encode_to(dest);
     }
diff --git a/crates/lang/Cargo.toml b/crates/lang/Cargo.toml
index 178458125a..72d34d1653 100644
--- a/crates/lang/Cargo.toml
+++ b/crates/lang/Cargo.toml
@@ -22,7 +22,7 @@ ink_metadata = { version = "3.0.0-rc2", path = "../metadata", default-features =
 ink_prelude = { version = "3.0.0-rc2", path = "../prelude/", default-features = false }
 ink_lang_macro = { version = "3.0.0-rc2", path = "macro", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive", "full"] }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive", "full"] }
 derive_more = { version = "0.99", default-features = false, features = ["from"] }
 static_assertions = "1.1"
 
diff --git a/crates/lang/macro/Cargo.toml b/crates/lang/macro/Cargo.toml
index aef78cb43e..1339b48353 100644
--- a/crates/lang/macro/Cargo.toml
+++ b/crates/lang/macro/Cargo.toml
@@ -19,7 +19,7 @@ ink_lang_ir = { version = "3.0.0-rc2", path = "../ir", default-features = false
 ink_lang_codegen = { version = "3.0.0-rc2", path = "../codegen", default-features = false }
 ink_primitives = { version = "3.0.0-rc2", path = "../../primitives/", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
 syn = "1"
 proc-macro2 = "1"
 
@@ -30,7 +30,7 @@ ink_storage = { version = "3.0.0-rc2", path = "../../storage/" }
 ink_lang = { version = "3.0.0-rc2", path = ".." }
 
 trybuild = "1.0.24"
-scale-info = { version = "0.4", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"] }
 
 [lib]
 name = "ink_lang_macro"
diff --git a/crates/metadata/Cargo.toml b/crates/metadata/Cargo.toml
index 3d016eb7b8..74558b97ef 100644
--- a/crates/metadata/Cargo.toml
+++ b/crates/metadata/Cargo.toml
@@ -21,7 +21,7 @@ ink_primitives = { version = "3.0.0-rc2", path = "../primitives/", default-featu
 serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] }
 impl-serde = "0.3.1"
 derive_more = { version = "0.99", default-features = false, features = ["from"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive", "serde"] }
 
 [dev-dependencies]
 pretty_assertions = "0.6.1"
diff --git a/crates/metadata/src/layout/mod.rs b/crates/metadata/src/layout/mod.rs
index 12f6258721..e7caea6070 100644
--- a/crates/metadata/src/layout/mod.rs
+++ b/crates/metadata/src/layout/mod.rs
@@ -27,12 +27,12 @@ use ink_prelude::collections::btree_map::BTreeMap;
 use ink_primitives::Key;
 use scale_info::{
     form::{
-        CompactForm,
         Form,
         MetaForm,
+        PortableForm,
     },
     meta_type,
-    IntoCompact,
+    IntoPortable,
     Registry,
     TypeInfo,
 };
@@ -146,10 +146,10 @@ impl CellLayout {
     }
 }
 
-impl IntoCompact for CellLayout {
-    type Output = CellLayout<CompactForm>;
+impl IntoPortable for CellLayout {
+    type Output = CellLayout<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         CellLayout {
             key: self.key,
             ty: registry.register_type(&self.ty),
@@ -157,22 +157,26 @@ impl IntoCompact for CellLayout {
     }
 }
 
-impl IntoCompact for Layout {
-    type Output = Layout<CompactForm>;
+impl IntoPortable for Layout {
+    type Output = Layout<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         match self {
             Layout::Cell(encoded_cell) => {
-                Layout::Cell(encoded_cell.into_compact(registry))
+                Layout::Cell(encoded_cell.into_portable(registry))
+            }
+            Layout::Hash(hash_layout) => {
+                Layout::Hash(hash_layout.into_portable(registry))
             }
-            Layout::Hash(hash_layout) => Layout::Hash(hash_layout.into_compact(registry)),
             Layout::Array(array_layout) => {
-                Layout::Array(array_layout.into_compact(registry))
+                Layout::Array(array_layout.into_portable(registry))
             }
             Layout::Struct(struct_layout) => {
-                Layout::Struct(struct_layout.into_compact(registry))
+                Layout::Struct(struct_layout.into_portable(registry))
+            }
+            Layout::Enum(enum_layout) => {
+                Layout::Enum(enum_layout.into_portable(registry))
             }
-            Layout::Enum(enum_layout) => Layout::Enum(enum_layout.into_compact(registry)),
         }
     }
 }
@@ -209,14 +213,14 @@ pub struct HashLayout<F: Form = MetaForm> {
     layout: Box<Layout<F>>,
 }
 
-impl IntoCompact for HashLayout {
-    type Output = HashLayout<CompactForm>;
+impl IntoPortable for HashLayout {
+    type Output = HashLayout<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         HashLayout {
             offset: self.offset,
             strategy: self.strategy,
-            layout: Box::new(self.layout.into_compact(registry)),
+            layout: Box::new(self.layout.into_portable(registry)),
         }
     }
 }
@@ -380,15 +384,15 @@ where
     }
 }
 
-impl IntoCompact for ArrayLayout {
-    type Output = ArrayLayout<CompactForm>;
+impl IntoPortable for ArrayLayout {
+    type Output = ArrayLayout<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         ArrayLayout {
             offset: self.offset,
             len: self.len,
             cells_per_elem: self.cells_per_elem,
-            layout: Box::new(self.layout.into_compact(registry)),
+            layout: Box::new(self.layout.into_portable(registry)),
         }
     }
 }
@@ -426,15 +430,15 @@ where
     }
 }
 
-impl IntoCompact for StructLayout {
-    type Output = StructLayout<CompactForm>;
+impl IntoPortable for StructLayout {
+    type Output = StructLayout<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         StructLayout {
             fields: self
                 .fields
                 .into_iter()
-                .map(|field| field.into_compact(registry))
+                .map(|field| field.into_portable(registry))
                 .collect::<Vec<_>>(),
         }
     }
@@ -492,13 +496,13 @@ where
     }
 }
 
-impl IntoCompact for FieldLayout {
-    type Output = FieldLayout<CompactForm>;
+impl IntoPortable for FieldLayout {
+    type Output = FieldLayout<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         FieldLayout {
-            name: self.name.map(|name| name.into_compact(registry)),
-            layout: self.layout.into_compact(registry),
+            name: self.name.map(|name| name.into_portable(registry)),
+            layout: self.layout.into_portable(registry),
         }
     }
 }
@@ -563,17 +567,17 @@ where
     }
 }
 
-impl IntoCompact for EnumLayout {
-    type Output = EnumLayout<CompactForm>;
+impl IntoPortable for EnumLayout {
+    type Output = EnumLayout<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         EnumLayout {
             dispatch_key: self.dispatch_key,
             variants: self
                 .variants
                 .into_iter()
                 .map(|(discriminant, layout)| {
-                    (discriminant, layout.into_compact(registry))
+                    (discriminant, layout.into_portable(registry))
                 })
                 .collect(),
         }
diff --git a/crates/metadata/src/lib.rs b/crates/metadata/src/lib.rs
index 181b0bfd79..ad39c6de12 100644
--- a/crates/metadata/src/lib.rs
+++ b/crates/metadata/src/lib.rs
@@ -47,25 +47,30 @@ use impl_serde::serialize as serde_hex;
 
 #[cfg(feature = "derive")]
 use scale_info::{
-    form::CompactForm,
-    IntoCompact as _,
+    form::{
+        FormString,
+        PortableForm,
+    },
+    IntoPortable as _,
+    PortableRegistry,
     Registry,
-    RegistryReadOnly,
 };
 use serde::{
+    de::DeserializeOwned,
     Deserialize,
     Serialize,
 };
 
 /// An entire ink! project for metadata file generation purposes.
 #[derive(Debug, Serialize, Deserialize)]
-pub struct InkProject {
+#[serde(bound(deserialize = "S: DeserializeOwned"))]
+pub struct InkProject<S: FormString = &'static str> {
     #[serde(flatten)]
-    registry: RegistryReadOnly,
+    registry: PortableRegistry<S>,
     #[serde(rename = "storage")]
     /// The layout of the storage data structure
-    layout: layout::Layout<CompactForm>,
-    spec: ContractSpec<CompactForm>,
+    layout: layout::Layout<PortableForm<S>>,
+    spec: ContractSpec<PortableForm<S>>,
 }
 
 impl InkProject {
@@ -77,26 +82,29 @@ impl InkProject {
         let mut registry = Registry::new();
 
         Self {
-            layout: layout.into().into_compact(&mut registry),
-            spec: spec.into().into_compact(&mut registry),
+            layout: layout.into().into_portable(&mut registry),
+            spec: spec.into().into_portable(&mut registry),
             registry: registry.into(),
         }
     }
 }
 
-impl InkProject {
+impl<S> InkProject<S>
+where
+    S: FormString,
+{
     /// Returns a read-only registry of types in the contract.
-    pub fn registry(&self) -> &RegistryReadOnly {
+    pub fn registry(&self) -> &PortableRegistry<S> {
         &self.registry
     }
 
     /// Returns the storage layout of the contract.
-    pub fn layout(&self) -> &layout::Layout<CompactForm> {
+    pub fn layout(&self) -> &layout::Layout<PortableForm<S>> {
         &self.layout
     }
 
     /// Returns the specification of the contract.
-    pub fn spec(&self) -> &ContractSpec<CompactForm> {
+    pub fn spec(&self) -> &ContractSpec<PortableForm<S>> {
         &self.spec
     }
 }
diff --git a/crates/metadata/src/specs.rs b/crates/metadata/src/specs.rs
index e9b4230465..9c8c2f6561 100644
--- a/crates/metadata/src/specs.rs
+++ b/crates/metadata/src/specs.rs
@@ -24,12 +24,12 @@ use alloc::{
 use core::marker::PhantomData;
 use scale_info::{
     form::{
-        CompactForm,
         Form,
         MetaForm,
+        PortableForm,
     },
     meta_type,
-    IntoCompact,
+    IntoPortable,
     Registry,
     TypeInfo,
 };
@@ -56,27 +56,27 @@ pub struct ContractSpec<F: Form = MetaForm> {
     docs: Vec<F::String>,
 }
 
-impl IntoCompact for ContractSpec {
-    type Output = ContractSpec<CompactForm>;
+impl IntoPortable for ContractSpec {
+    type Output = ContractSpec<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         ContractSpec {
             constructors: self
                 .constructors
                 .into_iter()
-                .map(|constructor| constructor.into_compact(registry))
+                .map(|constructor| constructor.into_portable(registry))
                 .collect::<Vec<_>>(),
             messages: self
                 .messages
                 .into_iter()
-                .map(|msg| msg.into_compact(registry))
+                .map(|msg| msg.into_portable(registry))
                 .collect::<Vec<_>>(),
             events: self
                 .events
                 .into_iter()
-                .map(|event| event.into_compact(registry))
+                .map(|event| event.into_portable(registry))
                 .collect::<Vec<_>>(),
-            docs: registry.map_into_compact(self.docs),
+            docs: registry.map_into_portable(self.docs),
         }
     }
 }
@@ -232,19 +232,19 @@ pub struct ConstructorSpec<F: Form = MetaForm> {
     pub docs: Vec<F::String>,
 }
 
-impl IntoCompact for ConstructorSpec {
-    type Output = ConstructorSpec<CompactForm>;
+impl IntoPortable for ConstructorSpec {
+    type Output = ConstructorSpec<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         ConstructorSpec {
-            name: registry.map_into_compact(self.name),
+            name: registry.map_into_portable(self.name),
             selector: self.selector,
             args: self
                 .args
                 .into_iter()
-                .map(|arg| arg.into_compact(registry))
+                .map(|arg| arg.into_portable(registry))
                 .collect::<Vec<_>>(),
-            docs: registry.map_into_compact(self.docs),
+            docs: registry.map_into_portable(self.docs),
         }
     }
 }
@@ -609,22 +609,22 @@ impl
     }
 }
 
-impl IntoCompact for MessageSpec {
-    type Output = MessageSpec<CompactForm>;
+impl IntoPortable for MessageSpec {
+    type Output = MessageSpec<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         MessageSpec {
-            name: registry.map_into_compact(self.name),
+            name: registry.map_into_portable(self.name),
             selector: self.selector,
             mutates: self.mutates,
             payable: self.payable,
             args: self
                 .args
                 .into_iter()
-                .map(|arg| arg.into_compact(registry))
+                .map(|arg| arg.into_portable(registry))
                 .collect::<Vec<_>>(),
-            return_type: self.return_type.into_compact(registry),
-            docs: registry.map_into_compact(self.docs),
+            return_type: self.return_type.into_portable(registry),
+            docs: registry.map_into_portable(self.docs),
         }
     }
 }
@@ -678,18 +678,18 @@ impl EventSpecBuilder {
     }
 }
 
-impl IntoCompact for EventSpec {
-    type Output = EventSpec<CompactForm>;
+impl IntoPortable for EventSpec {
+    type Output = EventSpec<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         EventSpec {
-            name: self.name.into_compact(registry),
+            name: self.name.into_portable(registry),
             args: self
                 .args
                 .into_iter()
-                .map(|arg| arg.into_compact(registry))
+                .map(|arg| arg.into_portable(registry))
                 .collect::<Vec<_>>(),
-            docs: registry.map_into_compact(self.docs),
+            docs: registry.map_into_portable(self.docs),
         }
     }
 }
@@ -808,13 +808,13 @@ pub struct TypeSpec<F: Form = MetaForm> {
     display_name: DisplayName<F>,
 }
 
-impl IntoCompact for TypeSpec {
-    type Output = TypeSpec<CompactForm>;
+impl IntoPortable for TypeSpec {
+    type Output = TypeSpec<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         TypeSpec {
             ty: registry.register_type(&self.ty),
-            display_name: self.display_name.into_compact(registry),
+            display_name: self.display_name.into_portable(registry),
         }
     }
 }
@@ -907,15 +907,15 @@ pub struct EventParamSpec<F: Form = MetaForm> {
     docs: Vec<F::String>,
 }
 
-impl IntoCompact for EventParamSpec {
-    type Output = EventParamSpec<CompactForm>;
+impl IntoPortable for EventParamSpec {
+    type Output = EventParamSpec<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         EventParamSpec {
-            name: self.name.into_compact(registry),
+            name: self.name.into_portable(registry),
             indexed: self.indexed,
-            ty: self.ty.into_compact(registry),
-            docs: registry.map_into_compact(self.docs),
+            ty: self.ty.into_portable(registry),
+            docs: registry.map_into_portable(self.docs),
         }
     }
 }
@@ -1015,14 +1015,14 @@ pub struct ReturnTypeSpec<F: Form = MetaForm> {
     opt_type: Option<TypeSpec<F>>,
 }
 
-impl IntoCompact for ReturnTypeSpec {
-    type Output = ReturnTypeSpec<CompactForm>;
+impl IntoPortable for ReturnTypeSpec {
+    type Output = ReturnTypeSpec<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         ReturnTypeSpec {
             opt_type: self
                 .opt_type
-                .map(|opt_type| opt_type.into_compact(registry)),
+                .map(|opt_type| opt_type.into_portable(registry)),
         }
     }
 }
@@ -1071,13 +1071,13 @@ pub struct MessageParamSpec<F: Form = MetaForm> {
     ty: TypeSpec<F>,
 }
 
-impl IntoCompact for MessageParamSpec {
-    type Output = MessageParamSpec<CompactForm>;
+impl IntoPortable for MessageParamSpec {
+    type Output = MessageParamSpec<PortableForm>;
 
-    fn into_compact(self, registry: &mut Registry) -> Self::Output {
+    fn into_portable(self, registry: &mut Registry) -> Self::Output {
         MessageParamSpec {
-            name: self.name.into_compact(registry),
-            ty: self.ty.into_compact(registry),
+            name: self.name.into_portable(registry),
+            ty: self.ty.into_portable(registry),
         }
     }
 }
diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml
index 2a2475761a..51826dd47d 100644
--- a/crates/primitives/Cargo.toml
+++ b/crates/primitives/Cargo.toml
@@ -17,8 +17,8 @@ include = ["/Cargo.toml", "src/**/*.rs", "/README.md", "/LICENSE"]
 [dependencies]
 ink_prelude = { version = "3.0.0-rc2", path = "../prelude/", default-features = false }
 tiny-keccak = { version = "2.0", features = ["keccak"] }
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive", "full"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive", "full"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [dev-dependencies]
diff --git a/crates/primitives/src/key.rs b/crates/primitives/src/key.rs
index f218b2791d..4dacd56d77 100644
--- a/crates/primitives/src/key.rs
+++ b/crates/primitives/src/key.rs
@@ -149,7 +149,7 @@ impl scale::Encode for Key {
     }
 
     #[inline]
-    fn encode_to<T: scale::Output>(&self, dest: &mut T) {
+    fn encode_to<T: scale::Output + ?Sized>(&self, dest: &mut T) {
         if cfg!(target_endian = "little") {
             dest.write(self.try_as_bytes().expect("little endian is asserted"))
         } else {
@@ -236,10 +236,12 @@ const _: () = {
     };
 
     impl TypeInfo for Key {
+        type Identity = Self;
+
         fn type_info() -> Type {
             Type::builder()
                 .path(Path::new("Key", "ink_primitives"))
-                .composite(Fields::unnamed().field_of::<[u8; 32]>())
+                .composite(Fields::unnamed().field_of::<[u8; 32]>("[u8; 32]"))
         }
     }
 };
diff --git a/crates/storage/Cargo.toml b/crates/storage/Cargo.toml
index 6f2228db42..77ddef3a56 100644
--- a/crates/storage/Cargo.toml
+++ b/crates/storage/Cargo.toml
@@ -21,9 +21,9 @@ ink_primitives = { version = "3.0.0-rc2", path = "../primitives/", default-featu
 ink_storage_derive = { version = "3.0.0-rc2", path = "derive", default-features = false }
 ink_prelude = { version = "3.0.0-rc2", path = "../prelude/", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive", "full"] }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive", "full"] }
 derive_more = { version = "0.99", default-features = false, features = ["from", "display"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 cfg-if = "1.0"
 array-init = "1.0"
 generic-array = "0.14.1"
diff --git a/crates/storage/src/alloc/allocation.rs b/crates/storage/src/alloc/allocation.rs
index 227ad47f6a..0f8e6c1078 100644
--- a/crates/storage/src/alloc/allocation.rs
+++ b/crates/storage/src/alloc/allocation.rs
@@ -124,7 +124,7 @@ impl DynamicAllocation {
             #[rustfmt::skip]
             fn encode_to<O>(&self, output: &mut O)
             where
-                O: scale::Output,
+                O: scale::Output + ?Sized,
             {
                 <[u8; 21] as scale::Encode>::encode_to(&[
                     b'D', b'Y', b'N', b'A', b'M', b'I', b'C', b'A', b'L', b'L', b'Y',
diff --git a/crates/storage/src/alloc/boxed/storage.rs b/crates/storage/src/alloc/boxed/storage.rs
index 91e54d40ff..0624bdedab 100644
--- a/crates/storage/src/alloc/boxed/storage.rs
+++ b/crates/storage/src/alloc/boxed/storage.rs
@@ -49,8 +49,10 @@ const _: () = {
 
     impl<T> scale_info::TypeInfo for StorageBox<T>
     where
-        T: SpreadLayout,
+        T: SpreadLayout + 'static,
     {
+        type Identity = Self;
+
         fn type_info() -> scale_info::Type {
             scale_info::Type::builder()
                 .path(
@@ -66,7 +68,7 @@ const _: () = {
                 // .type_params(vec![scale_info::MetaType::new::<T>()])
                 .composite(
                     scale_info::build::Fields::named()
-                        .field_of::<DynamicAllocation>("allocation"),
+                        .field_of::<DynamicAllocation>("allocation", "DynamicAllocation"),
                 )
         }
     }
@@ -99,7 +101,7 @@ where
         <DynamicAllocation as scale::Encode>::size_hint(&self.allocation)
     }
 
-    fn encode_to<O: scale::Output>(&self, dest: &mut O) {
+    fn encode_to<O: scale::Output + ?Sized>(&self, dest: &mut O) {
         <DynamicAllocation as scale::Encode>::encode_to(&self.allocation, dest)
     }
 
diff --git a/crates/storage/src/collections/binary_heap/reverse.rs b/crates/storage/src/collections/binary_heap/reverse.rs
index a3649e765c..1ae64edbe6 100644
--- a/crates/storage/src/collections/binary_heap/reverse.rs
+++ b/crates/storage/src/collections/binary_heap/reverse.rs
@@ -94,7 +94,7 @@ where
     }
 
     #[inline]
-    fn encode_to<O: scale::Output>(&self, dest: &mut O) {
+    fn encode_to<O: scale::Output + ?Sized>(&self, dest: &mut O) {
         <T as scale::Encode>::encode_to(self.value(), dest)
     }
 
diff --git a/crates/storage/src/lazy/entry.rs b/crates/storage/src/lazy/entry.rs
index fb6da768d2..3c73db03ee 100644
--- a/crates/storage/src/lazy/entry.rs
+++ b/crates/storage/src/lazy/entry.rs
@@ -131,7 +131,7 @@ where
     }
 
     #[inline]
-    fn encode_to<O: scale::Output>(&self, dest: &mut O) {
+    fn encode_to<O: scale::Output + ?Sized>(&self, dest: &mut O) {
         <Option<T> as scale::Encode>::encode_to(&self.value, dest)
     }
 
diff --git a/crates/storage/src/pack.rs b/crates/storage/src/pack.rs
index c5efdf177d..dce6b7e586 100644
--- a/crates/storage/src/pack.rs
+++ b/crates/storage/src/pack.rs
@@ -81,7 +81,7 @@ where
     }
 
     #[inline]
-    fn encode_to<O: scale::Output>(&self, dest: &mut O) {
+    fn encode_to<O: scale::Output + ?Sized>(&self, dest: &mut O) {
         <T as scale::Encode>::encode_to(&self.inner, dest)
     }
 
diff --git a/examples/contract-terminate/Cargo.toml b/examples/contract-terminate/Cargo.toml
index 05b208706b..1190073638 100644
--- a/examples/contract-terminate/Cargo.toml
+++ b/examples/contract-terminate/Cargo.toml
@@ -11,8 +11,8 @@ ink_env = { version = "3.0.0-rc1", path = "../../crates/env", default-features =
 ink_storage = { version = "3.0.0-rc1", path = "../../crates/storage", default-features = false }
 ink_lang = { version = "3.0.0-rc1", path = "../../crates/lang", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [lib]
diff --git a/examples/contract-transfer/Cargo.toml b/examples/contract-transfer/Cargo.toml
index 7f5dffdc71..f05ad12292 100644
--- a/examples/contract-transfer/Cargo.toml
+++ b/examples/contract-transfer/Cargo.toml
@@ -11,8 +11,8 @@ ink_env = { version = "3.0.0-rc1", path = "../../crates/env", default-features =
 ink_storage = { version = "3.0.0-rc1", path = "../../crates/storage", default-features = false }
 ink_lang = { version = "3.0.0-rc1", path = "../../crates/lang", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [lib]
diff --git a/examples/delegator/Cargo.toml b/examples/delegator/Cargo.toml
index 8d85f6464a..001dc99c8a 100644
--- a/examples/delegator/Cargo.toml
+++ b/examples/delegator/Cargo.toml
@@ -11,12 +11,12 @@ ink_env = { version = "3.0.0-rc2", path = "../../crates/env", default-features =
 ink_storage = { version = "3.0.0-rc2", path = "../../crates/storage", default-features = false }
 ink_lang = { version = "3.0.0-rc2", path = "../../crates/lang", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
 
 adder = { version = "3.0.0-rc2", path = "adder", default-features = false, features = ["ink-as-dependency"] }
 subber = { version = "3.0.0-rc2", path = "subber", default-features = false, features = ["ink-as-dependency"] }
 accumulator = { version = "3.0.0-rc2", path = "accumulator", default-features = false, features = ["ink-as-dependency"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 [lib]
 name = "delegator"
diff --git a/examples/delegator/accumulator/Cargo.toml b/examples/delegator/accumulator/Cargo.toml
index 5c271ffbe3..b1679f8b9b 100644
--- a/examples/delegator/accumulator/Cargo.toml
+++ b/examples/delegator/accumulator/Cargo.toml
@@ -11,8 +11,8 @@ ink_env = { version = "3.0.0-rc2", path = "../../../crates/env", default-feature
 ink_storage = { version = "3.0.0-rc2", path = "../../../crates/storage", default-features = false }
 ink_lang = { version = "3.0.0-rc2", path = "../../../crates/lang", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [lib]
diff --git a/examples/delegator/adder/Cargo.toml b/examples/delegator/adder/Cargo.toml
index 0614bbbf91..1211b2e1e4 100644
--- a/examples/delegator/adder/Cargo.toml
+++ b/examples/delegator/adder/Cargo.toml
@@ -13,8 +13,8 @@ ink_lang = { version = "3.0.0-rc2", path = "../../../crates/lang", default-featu
 
 accumulator = { version = "3.0.0-rc2", path = "../accumulator", default-features = false, features = ["ink-as-dependency"] }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [lib]
diff --git a/examples/delegator/subber/Cargo.toml b/examples/delegator/subber/Cargo.toml
index 2ca9b664f5..c16b184ea6 100644
--- a/examples/delegator/subber/Cargo.toml
+++ b/examples/delegator/subber/Cargo.toml
@@ -13,8 +13,8 @@ ink_lang = { version = "3.0.0-rc2", path = "../../../crates/lang", default-featu
 
 accumulator = { version = "3.0.0-rc2", path = "../accumulator", default-features = false, features = ["ink-as-dependency"] }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [lib]
diff --git a/examples/dns/Cargo.toml b/examples/dns/Cargo.toml
index 780bba1228..c7d6adc8d2 100644
--- a/examples/dns/Cargo.toml
+++ b/examples/dns/Cargo.toml
@@ -11,8 +11,8 @@ ink_env = { version = "3.0.0-rc2", path = "../../crates/env", default-features =
 ink_storage = { version = "3.0.0-rc2", path = "../../crates/storage", default-features = false }
 ink_lang = { version = "3.0.0-rc2", path = "../../crates/lang", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [lib]
diff --git a/examples/erc20/Cargo.toml b/examples/erc20/Cargo.toml
index ba0b8f9a43..f168e47c9a 100644
--- a/examples/erc20/Cargo.toml
+++ b/examples/erc20/Cargo.toml
@@ -11,8 +11,8 @@ ink_env = { version = "3.0.0-rc2", path = "../../crates/env", default-features =
 ink_storage = { version = "3.0.0-rc2", path = "../../crates/storage", default-features = false }
 ink_lang = { version = "3.0.0-rc2", path = "../../crates/lang", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [lib]
diff --git a/examples/erc20/lib.rs b/examples/erc20/lib.rs
index 992441aba6..40bf294d48 100644
--- a/examples/erc20/lib.rs
+++ b/examples/erc20/lib.rs
@@ -548,7 +548,7 @@ mod erc20 {
         }
 
         #[inline]
-        fn encode_to<T: scale::Output>(&self, dest: &mut T) {
+        fn encode_to<T: scale::Output + ?Sized>(&self, dest: &mut T) {
             self.prefix.encode_to(dest);
             self.value.encode_to(dest);
         }
diff --git a/examples/erc721/Cargo.toml b/examples/erc721/Cargo.toml
index a455795066..185abbb428 100644
--- a/examples/erc721/Cargo.toml
+++ b/examples/erc721/Cargo.toml
@@ -11,8 +11,8 @@ ink_env = { version = "3.0.0-rc2", path = "../../crates/env", default-features =
 ink_storage = { version = "3.0.0-rc2", path = "../../crates/storage", default-features = false }
 ink_lang = { version = "3.0.0-rc2", path = "../../crates/lang", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [lib]
diff --git a/examples/flipper/Cargo.toml b/examples/flipper/Cargo.toml
index fc056ade09..6749522054 100644
--- a/examples/flipper/Cargo.toml
+++ b/examples/flipper/Cargo.toml
@@ -11,8 +11,8 @@ ink_env = { version = "3.0.0-rc2", path = "../../crates/env", default-features =
 ink_storage = { version = "3.0.0-rc2", path = "../../crates/storage", default-features = false }
 ink_lang = { version = "3.0.0-rc2", path = "../../crates/lang", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [lib]
diff --git a/examples/incrementer/Cargo.toml b/examples/incrementer/Cargo.toml
index e754cd0554..e1408fefb5 100644
--- a/examples/incrementer/Cargo.toml
+++ b/examples/incrementer/Cargo.toml
@@ -11,8 +11,8 @@ ink_env = { version = "3.0.0-rc2", path = "../../crates/env", default-features =
 ink_storage = { version = "3.0.0-rc2", path = "../../crates/storage", default-features = false }
 ink_lang = { version = "3.0.0-rc2", path = "../../crates/lang", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [lib]
diff --git a/examples/multisig_plain/Cargo.toml b/examples/multisig_plain/Cargo.toml
index c20687e57d..80393b2fbd 100755
--- a/examples/multisig_plain/Cargo.toml
+++ b/examples/multisig_plain/Cargo.toml
@@ -12,8 +12,8 @@ ink_storage = { version = "3.0.0-rc2", path = "../../crates/storage", default-fe
 ink_lang = { version = "3.0.0-rc2", path = "../../crates/lang", default-features = false }
 ink_prelude = { version = "3.0.0-rc2", path = "../../crates/prelude", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [lib]
diff --git a/examples/multisig_plain/lib.rs b/examples/multisig_plain/lib.rs
index 2095675296..4f1057b517 100755
--- a/examples/multisig_plain/lib.rs
+++ b/examples/multisig_plain/lib.rs
@@ -111,7 +111,7 @@ mod multisig_plain {
     struct CallInput<'a>(&'a [u8]);
 
     impl<'a> scale::Encode for CallInput<'a> {
-        fn encode_to<T: Output>(&self, dest: &mut T) {
+        fn encode_to<T: Output + ?Sized>(&self, dest: &mut T) {
             dest.write(self.0);
         }
     }
diff --git a/examples/rand-extension/.gitignore b/examples/rand-extension/.gitignore
new file mode 100755
index 0000000000..8de8f877e4
--- /dev/null
+++ b/examples/rand-extension/.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
diff --git a/examples/rand-extension/Cargo.toml b/examples/rand-extension/Cargo.toml
new file mode 100755
index 0000000000..e9beecf6a7
--- /dev/null
+++ b/examples/rand-extension/Cargo.toml
@@ -0,0 +1,36 @@
+[package]
+name = "rand_extension"
+version = "0.1.0"
+authors = ["Hammewang <maggiedong@parity.io>"]
+edition = "2018"
+
+[dependencies]
+ink_primitives = { path = "../../crates/primitives", default-features = false }
+ink_metadata = { path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
+ink_env = { path = "../../crates/env", default-features = false }
+ink_storage = { path = "../../crates/storage", default-features = false }
+ink_lang = { path = "../../crates/lang", default-features = false }
+
+scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
+scale-info = { version = "0.4.1", default-features = false, features = ["derive"], optional = true }
+
+[lib]
+name = "rand_extension"
+path = "lib.rs"
+crate-type = [
+	# Used for normal contract Wasm blobs.
+	"cdylib",
+]
+
+[features]
+default = ["std"]
+std = [
+    "ink_metadata/std",
+    "ink_env/std",
+    "ink_storage/std",
+    "ink_primitives/std",
+    "scale/std",
+    "scale-info",
+    "scale-info/std",
+]
+ink-as-dependency = []
diff --git a/examples/rand-extension/lib.rs b/examples/rand-extension/lib.rs
new file mode 100755
index 0000000000..ecb22a0875
--- /dev/null
+++ b/examples/rand-extension/lib.rs
@@ -0,0 +1,132 @@
+// Copyright 2018-2021 Parity Technologies (UK) Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#![cfg_attr(not(feature = "std"), no_std)]
+
+use ink_env::Environment;
+use ink_lang as ink;
+
+/// This is an example of how ink! contract should
+/// call substrate runtime `RandomnessCollectiveFlip::random_seed`.
+
+/// Define the operations to interact with the substrate runtime
+#[ink::chain_extension]
+pub trait FetchRandom {
+    type ErrorCode = RandomReadErr;
+
+    /// 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];
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)]
+#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
+pub enum RandomReadErr {
+    FailGetRandomSource,
+}
+
+impl ink_env::chain_extension::FromStatusCode for RandomReadErr {
+    fn from_status_code(status_code: u32) -> Result<(), Self> {
+        match status_code {
+            0 => Ok(()),
+            1 => Err(Self::FailGetRandomSource),
+            _ => panic!("encountered unknown status code"),
+        }
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
+pub enum CustomEnvironment {}
+
+impl Environment for CustomEnvironment {
+    const MAX_EVENT_TOPICS: usize =
+        <ink_env::DefaultEnvironment as Environment>::MAX_EVENT_TOPICS;
+
+    type AccountId = <ink_env::DefaultEnvironment as Environment>::AccountId;
+    type Balance = <ink_env::DefaultEnvironment as Environment>::Balance;
+    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 ChainExtension = FetchRandom;
+}
+
+#[ink::contract(env = crate::CustomEnvironment)]
+mod rand_extension {
+    use super::RandomReadErr;
+
+    /// Defines the storage of your contract.
+    /// Here we store the random seed fetched from the chain
+    #[ink(storage)]
+    pub struct RandExtension {
+        /// Stores a single `bool` value on the storage.
+        value: [u8; 32],
+    }
+
+    #[ink(event)]
+    pub struct RandomUpdated {
+        #[ink(topic)]
+        new: [u8; 32],
+    }
+
+    impl RandExtension {
+        /// Constructor that initializes the `bool` value to the given `init_value`.
+        #[ink(constructor)]
+        pub fn new(init_value: [u8; 32]) -> Self {
+            Self { value: init_value }
+        }
+
+        /// Constructor that initializes the `bool` value to `false`.
+        ///
+        /// Constructors can delegate to other constructors.
+        #[ink(constructor)]
+        pub fn default() -> Self {
+            Self::new(Default::default())
+        }
+
+        /// update the value from runtime random source
+        #[ink(message)]
+        pub fn update(&mut self) -> Result<(), RandomReadErr> {
+            // Get the on-chain random seed
+            let new_random = self.env().extension().fetch_random()?;
+            self.value = new_random;
+            // emit the RandomUpdated event when the random seed
+            // is successfully fetched.
+            self.env().emit_event(RandomUpdated { new: new_random });
+            Ok(())
+        }
+
+        /// Simply returns the current value.
+        #[ink(message)]
+        pub fn get(&self) -> [u8; 32] {
+            self.value
+        }
+    }
+
+    /// Unit tests in Rust are normally defined within such a `#[cfg(test)]`
+    #[cfg(test)]
+    mod tests {
+        /// Imports all the definitions from the outer scope so we can use them here.
+        use super::*;
+        use ink_lang as ink;
+
+        /// We test if the default constructor does its job.
+        #[ink::test]
+        fn default_works() {
+            let rand_extension = RandExtension::default();
+            assert_eq!(rand_extension.get(), [0; 32]);
+        }
+    }
+}
diff --git a/examples/rand-extension/runtime/README.md b/examples/rand-extension/runtime/README.md
new file mode 100644
index 0000000000..0e006c9420
--- /dev/null
+++ b/examples/rand-extension/runtime/README.md
@@ -0,0 +1,3 @@
+# Chain-side Extension
+
+use this as an implement of trait `ChainExtension` in substrate and use it as the associated type ChainExtension of trait `pallet_contracts::Config`
\ No newline at end of file
diff --git a/examples/rand-extension/runtime/chain-extension-example.rs b/examples/rand-extension/runtime/chain-extension-example.rs
new file mode 100644
index 0000000000..ef9e2340f6
--- /dev/null
+++ b/examples/rand-extension/runtime/chain-extension-example.rs
@@ -0,0 +1,45 @@
+use codec::{Encode, Decode};
+
+use frame_support::debug::{error, native};
+use frame_support::traits::Randomness;
+use pallet_contracts::chain_extension::{
+    ChainExtension, Environment, Ext, InitState, RetVal, SysConfig, UncheckedFrom,
+};
+use sp_runtime::DispatchError;
+use sp_std::vec::Vec;
+
+/// contract extension for `FetchRandom`
+pub struct FetchRandomExtension;
+
+impl ChainExtension for FetchRandomExtension {
+    fn call<E: Ext>(func_id: u32, env: Environment<E, InitState>) -> Result<RetVal, DispatchError>
+        where
+            <E::T as SysConfig>::AccountId: UncheckedFrom<<E::T as SysConfig>::Hash> + AsRef<[u8]>,
+    {
+
+        match func_id {
+            1101 => {
+                let mut env = env.buf_in_buf_out();
+                let random_seed: [u8; 32] = super::RandomnessCollectiveFlip::random_seed().0;
+                let random_slice = random_seed.encode();
+                native::trace!(
+                    target: "runtime",
+                    "[ChainExtension]|call|func_id:{:}",
+                    func_id
+                );
+                env.write(&random_slice, false, None)
+                    .map_err(|_| DispatchError::Other("ChainExtension failed to call random"))?;
+            }
+
+            _ => {
+                error!("call an unregistered `func_id`, func_id:{:}", func_id);
+                return Err(DispatchError::Other("Unimplemented func_id"));
+            }
+        }
+        Ok(RetVal::Converging(0))
+    }
+
+    fn enabled() -> bool {
+        true
+    }
+}
diff --git a/examples/trait-erc20/Cargo.toml b/examples/trait-erc20/Cargo.toml
index ba0b8f9a43..f168e47c9a 100644
--- a/examples/trait-erc20/Cargo.toml
+++ b/examples/trait-erc20/Cargo.toml
@@ -11,8 +11,8 @@ ink_env = { version = "3.0.0-rc2", path = "../../crates/env", default-features =
 ink_storage = { version = "3.0.0-rc2", path = "../../crates/storage", default-features = false }
 ink_lang = { version = "3.0.0-rc2", path = "../../crates/lang", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 
 [lib]
diff --git a/examples/trait-erc20/lib.rs b/examples/trait-erc20/lib.rs
index 21e304d56f..1b3b350ebc 100644
--- a/examples/trait-erc20/lib.rs
+++ b/examples/trait-erc20/lib.rs
@@ -600,7 +600,7 @@ mod erc20 {
         }
 
         #[inline]
-        fn encode_to<T: scale::Output>(&self, dest: &mut T) {
+        fn encode_to<T: scale::Output + ?Sized>(&self, dest: &mut T) {
             self.prefix.encode_to(dest);
             self.value.encode_to(dest);
         }
diff --git a/examples/trait-flipper/Cargo.toml b/examples/trait-flipper/Cargo.toml
index e189710f93..a5d69926a7 100644
--- a/examples/trait-flipper/Cargo.toml
+++ b/examples/trait-flipper/Cargo.toml
@@ -11,8 +11,8 @@ ink_env = { version = "3.0.0-rc2", path = "../../crates/env", default-features =
 ink_storage = { version = "3.0.0-rc2", path = "../../crates/storage", default-features = false }
 ink_lang = { version = "3.0.0-rc2", path = "../../crates/lang", default-features = false }
 
-scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
-scale-info = { version = "0.4", default-features = false, features = ["derive"], optional = true }
+scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] }
+scale-info = { version = "0.5", default-features = false, features = ["derive"], optional = true }
 
 [lib]
 name = "flipper"


Test patch:
diff --git a/crates/metadata/src/layout/tests.rs b/crates/metadata/src/layout/tests.rs
index 741f2aa508..11d1878633 100644
--- a/crates/metadata/src/layout/tests.rs
+++ b/crates/metadata/src/layout/tests.rs
@@ -44,7 +44,7 @@ fn named_fields_struct_layout(key_ptr: &mut KeyPtr) -> Layout {
 fn named_fields_work() {
     let layout = named_fields_struct_layout(&mut KeyPtr::from(Key::from([0x00; 32])));
     let mut registry = Registry::new();
-    let compacted = layout.into_compact(&mut registry);
+    let compacted = layout.into_portable(&mut registry);
     let json = serde_json::to_value(&compacted).unwrap();
     let expected = serde_json::json! {
         {
@@ -101,7 +101,7 @@ fn tuple_struct_layout(key_ptr: &mut KeyPtr) -> Layout {
 fn tuple_struct_work() {
     let layout = tuple_struct_layout(&mut KeyPtr::from(Key::from([0x00; 32])));
     let mut registry = Registry::new();
-    let compacted = layout.into_compact(&mut registry);
+    let compacted = layout.into_portable(&mut registry);
     let json = serde_json::to_value(&compacted).unwrap();
     let expected = serde_json::json! {
         {
@@ -156,7 +156,7 @@ fn clike_enum_layout(key_ptr: &mut KeyPtr) -> Layout {
 fn clike_enum_work() {
     let layout = clike_enum_layout(&mut KeyPtr::from(Key::from([0x00; 32])));
     let mut registry = Registry::new();
-    let compacted = layout.into_compact(&mut registry);
+    let compacted = layout.into_portable(&mut registry);
     let json = serde_json::to_value(&compacted).unwrap();
     let expected = serde_json::json! {
         {
@@ -237,7 +237,7 @@ fn mixed_enum_layout(key_ptr: &mut KeyPtr) -> Layout {
 fn mixed_enum_work() {
     let layout = mixed_enum_layout(&mut KeyPtr::from(Key::from([0x00; 32])));
     let mut registry = Registry::new();
-    let compacted = layout.into_compact(&mut registry);
+    let compacted = layout.into_portable(&mut registry);
     let json = serde_json::to_value(&compacted).unwrap();
     let expected = serde_json::json! {
         {
@@ -336,7 +336,7 @@ fn unbounded_hashing_layout(key_ptr: &mut KeyPtr) -> Layout {
 fn unbounded_layout_works() {
     let layout = unbounded_hashing_layout(&mut KeyPtr::from(Key::from([0x00; 32])));
     let mut registry = Registry::new();
-    let compacted = layout.into_compact(&mut registry);
+    let compacted = layout.into_portable(&mut registry);
     let json = serde_json::to_value(&compacted).unwrap();
     let expected = serde_json::json! {
         {
diff --git a/crates/metadata/src/tests.rs b/crates/metadata/src/tests.rs
index 644c52847d..0ae170b81a 100644
--- a/crates/metadata/src/tests.rs
+++ b/crates/metadata/src/tests.rs
@@ -15,7 +15,7 @@
 use super::*;
 use pretty_assertions::assert_eq;
 use scale_info::{
-    IntoCompact,
+    IntoPortable,
     Registry,
 };
 use serde_json::json;
@@ -28,11 +28,11 @@ fn spec_constructor_selector_must_serialize_to_hex() {
         .selector(123_456_789u32.to_be_bytes())
         .done();
     let mut registry = Registry::new();
-    let compact_spec = cs.into_compact(&mut registry);
+    let portable_spec = cs.into_portable(&mut registry);
 
     // when
-    let json = serde_json::to_value(&compact_spec).unwrap();
-    let deserialized: ConstructorSpec<CompactForm> =
+    let json = serde_json::to_value(&portable_spec).unwrap();
+    let deserialized: ConstructorSpec<PortableForm<String>> =
         serde_json::from_value(json.clone()).unwrap();
 
     // then
@@ -45,7 +45,7 @@ fn spec_constructor_selector_must_serialize_to_hex() {
             "docs": []
         })
     );
-    assert_eq!(deserialized, compact_spec);
+    assert_eq!(deserialized.selector, portable_spec.selector);
 }
 
 #[test]
@@ -99,7 +99,7 @@ fn spec_contract_json() {
     let mut registry = Registry::new();
 
     // when
-    let json = serde_json::to_value(&contract.into_compact(&mut registry)).unwrap();
+    let json = serde_json::to_value(&contract.into_portable(&mut registry)).unwrap();
 
     // then
     assert_eq!(
@@ -179,11 +179,11 @@ fn trim_docs() {
         .docs(vec![" foobar      "])
         .done();
     let mut registry = Registry::new();
-    let compact_spec = cs.into_compact(&mut registry);
+    let compact_spec = cs.into_portable(&mut registry);
 
     // when
     let json = serde_json::to_value(&compact_spec).unwrap();
-    let deserialized: ConstructorSpec<CompactForm> =
+    let deserialized: ConstructorSpec<PortableForm<String>> =
         serde_json::from_value(json.clone()).unwrap();
 
     // then
@@ -196,5 +196,5 @@ fn trim_docs() {
             "docs": ["foobar"]
         })
     );
-    assert_eq!(deserialized, compact_spec);
+    assert_eq!(deserialized.docs, compact_spec.docs);
 }