diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock
index ff21ec8dd0109fb661209dcdea8498b3361b4a4e..7754e0ae6b62f132433521a5f4552ca4c06620c1 100644
--- a/substrate/Cargo.lock
+++ b/substrate/Cargo.lock
@@ -1790,9 +1790,9 @@ dependencies = [
 
 [[package]]
 name = "finality-grandpa"
-version = "0.14.1"
+version = "0.14.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74a1bfdcc776e63e49f741c7ce6116fa1b887e8ac2e3ccb14dd4aa113e54feb9"
+checksum = "e8ac3ff5224ef91f3c97e03eb1de2db82743427e91aaa5ac635f454f0b164f5a"
 dependencies = [
  "either",
  "futures 0.3.16",
@@ -1802,6 +1802,7 @@ dependencies = [
  "parity-scale-codec",
  "parking_lot 0.11.1",
  "rand 0.8.4",
+ "scale-info",
 ]
 
 [[package]]
@@ -1884,6 +1885,7 @@ dependencies = [
  "log 0.4.14",
  "parity-scale-codec",
  "paste 1.0.4",
+ "scale-info",
  "sp-api",
  "sp-io",
  "sp-runtime",
@@ -1924,6 +1926,7 @@ dependencies = [
  "frame-support",
  "frame-system",
  "parity-scale-codec",
+ "scale-info",
  "sp-arithmetic",
  "sp-core",
  "sp-io",
@@ -1942,6 +1945,7 @@ dependencies = [
  "pallet-balances",
  "pallet-transaction-payment",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-inherents",
  "sp-io",
@@ -1953,18 +1957,21 @@ dependencies = [
 
 [[package]]
 name = "frame-metadata"
-version = "14.0.0-dev"
+version = "14.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96616f82e069102b95a72c87de4c84d2f87ef7f0f20630e78ce3824436483110"
 dependencies = [
+ "cfg-if 1.0.0",
  "parity-scale-codec",
+ "scale-info",
  "serde",
- "sp-core",
- "sp-std",
 ]
 
 [[package]]
 name = "frame-support"
 version = "4.0.0-dev"
 dependencies = [
+ "assert_matches",
  "bitflags",
  "frame-metadata",
  "frame-support-procedural",
@@ -1976,6 +1983,7 @@ dependencies = [
  "parity-util-mem",
  "paste 1.0.4",
  "pretty_assertions 0.6.1",
+ "scale-info",
  "serde",
  "smallvec 1.6.1",
  "sp-arithmetic",
@@ -2024,19 +2032,21 @@ dependencies = [
 name = "frame-support-test"
 version = "3.0.0"
 dependencies = [
- "frame-metadata",
  "frame-support",
  "frame-support-test-pallet",
  "frame-system",
  "parity-scale-codec",
  "pretty_assertions 0.6.1",
  "rustversion",
+ "scale-info",
  "serde",
+ "sp-arithmetic",
  "sp-core",
  "sp-io",
  "sp-runtime",
  "sp-state-machine",
  "sp-std",
+ "sp-version",
  "trybuild",
 ]
 
@@ -2047,6 +2057,7 @@ dependencies = [
  "frame-support",
  "frame-system",
  "parity-scale-codec",
+ "scale-info",
 ]
 
 [[package]]
@@ -2057,6 +2068,7 @@ dependencies = [
  "frame-support",
  "log 0.4.14",
  "parity-scale-codec",
+ "scale-info",
  "serde",
  "sp-core",
  "sp-externalities",
@@ -2075,6 +2087,7 @@ dependencies = [
  "frame-support",
  "frame-system",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -4417,6 +4430,7 @@ dependencies = [
  "pallet-treasury",
  "parity-scale-codec",
  "sc-executor",
+ "scale-info",
  "sp-application-crypto",
  "sp-consensus-babe",
  "sp-core",
@@ -4450,6 +4464,7 @@ version = "2.0.0"
 dependencies = [
  "frame-system",
  "parity-scale-codec",
+ "scale-info",
  "sp-application-crypto",
  "sp-core",
  "sp-runtime",
@@ -4555,6 +4570,7 @@ dependencies = [
  "pallet-utility",
  "pallet-vesting",
  "parity-scale-codec",
+ "scale-info",
  "sp-api",
  "sp-authority-discovery",
  "sp-block-builder",
@@ -4633,6 +4649,7 @@ dependencies = [
  "pallet-transaction-payment",
  "pallet-transaction-payment-rpc-runtime-api",
  "parity-scale-codec",
+ "scale-info",
  "sp-api",
  "sp-block-builder",
  "sp-consensus-aura",
@@ -4899,6 +4916,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -4913,6 +4931,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -4927,6 +4946,7 @@ dependencies = [
  "frame-system",
  "pallet-timestamp",
  "parity-scale-codec",
+ "scale-info",
  "sp-application-crypto",
  "sp-consensus-aura",
  "sp-core",
@@ -4943,6 +4963,7 @@ dependencies = [
  "frame-system",
  "pallet-session",
  "parity-scale-codec",
+ "scale-info",
  "sp-application-crypto",
  "sp-authority-discovery",
  "sp-core",
@@ -4959,6 +4980,7 @@ dependencies = [
  "frame-system",
  "impl-trait-for-tuples",
  "parity-scale-codec",
+ "scale-info",
  "sp-authorship",
  "sp-core",
  "sp-io",
@@ -4983,6 +5005,7 @@ dependencies = [
  "pallet-staking-reward-curve",
  "pallet-timestamp",
  "parity-scale-codec",
+ "scale-info",
  "sp-application-crypto",
  "sp-consensus-babe",
  "sp-consensus-vrf",
@@ -5004,6 +5027,7 @@ dependencies = [
  "log 0.4.14",
  "pallet-transaction-payment",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5020,6 +5044,7 @@ dependencies = [
  "pallet-balances",
  "pallet-treasury",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5035,6 +5060,7 @@ dependencies = [
  "frame-system",
  "log 0.4.14",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5064,6 +5090,7 @@ dependencies = [
  "pwasm-utils",
  "rand 0.7.3",
  "rand_pcg 0.2.1",
+ "scale-info",
  "serde",
  "smallvec 1.6.1",
  "sp-core",
@@ -5081,6 +5108,7 @@ version = "4.0.0-dev"
 dependencies = [
  "bitflags",
  "parity-scale-codec",
+ "scale-info",
  "serde",
  "sp-core",
  "sp-runtime",
@@ -5121,6 +5149,7 @@ version = "4.0.0-dev"
 dependencies = [
  "pallet-contracts-primitives",
  "parity-scale-codec",
+ "scale-info",
  "sp-api",
  "sp-runtime",
  "sp-std",
@@ -5136,6 +5165,7 @@ dependencies = [
  "pallet-balances",
  "pallet-scheduler",
  "parity-scale-codec",
+ "scale-info",
  "serde",
  "sp-core",
  "sp-io",
@@ -5156,6 +5186,7 @@ dependencies = [
  "parity-scale-codec",
  "parking_lot 0.11.1",
  "rand 0.7.3",
+ "scale-info",
  "sp-arithmetic",
  "sp-core",
  "sp-io",
@@ -5176,6 +5207,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5192,6 +5224,7 @@ dependencies = [
  "log 0.4.14",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-npos-elections",
@@ -5210,6 +5243,7 @@ dependencies = [
  "log 0.4.14",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5225,6 +5259,7 @@ dependencies = [
  "lite-json",
  "log 0.4.14",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-keystore",
@@ -5239,6 +5274,7 @@ dependencies = [
  "frame-support",
  "frame-system",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5255,6 +5291,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-arithmetic",
  "sp-core",
  "sp-io",
@@ -5280,6 +5317,7 @@ dependencies = [
  "pallet-staking-reward-curve",
  "pallet-timestamp",
  "parity-scale-codec",
+ "scale-info",
  "sp-application-crypto",
  "sp-core",
  "sp-finality-grandpa",
@@ -5301,6 +5339,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5318,6 +5357,7 @@ dependencies = [
  "pallet-authorship",
  "pallet-session",
  "parity-scale-codec",
+ "scale-info",
  "sp-application-crypto",
  "sp-core",
  "sp-io",
@@ -5335,6 +5375,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-keyring",
@@ -5352,6 +5393,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5367,6 +5409,7 @@ dependencies = [
  "frame-system",
  "log 0.4.14",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5385,6 +5428,7 @@ dependencies = [
  "hex-literal",
  "pallet-mmr-primitives",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5433,6 +5477,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5447,6 +5492,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5461,6 +5507,7 @@ dependencies = [
  "frame-system",
  "log 0.4.14",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5476,6 +5523,7 @@ dependencies = [
  "log 0.4.14",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "serde",
  "sp-core",
  "sp-io",
@@ -5502,6 +5550,7 @@ dependencies = [
  "pallet-staking-reward-curve",
  "pallet-timestamp",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5519,6 +5568,7 @@ dependencies = [
  "pallet-balances",
  "pallet-utility",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5533,6 +5583,7 @@ dependencies = [
  "frame-system",
  "parity-scale-codec",
  "safe-mix",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5547,6 +5598,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5562,6 +5614,7 @@ dependencies = [
  "frame-system",
  "log 0.4.14",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5577,6 +5630,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5593,6 +5647,7 @@ dependencies = [
  "log 0.4.14",
  "pallet-timestamp",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5617,6 +5672,7 @@ dependencies = [
  "pallet-timestamp",
  "parity-scale-codec",
  "rand 0.7.3",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5634,6 +5690,7 @@ dependencies = [
  "pallet-balances",
  "parity-scale-codec",
  "rand_chacha 0.2.2",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5656,6 +5713,7 @@ dependencies = [
  "pallet-timestamp",
  "parity-scale-codec",
  "rand_chacha 0.2.2",
+ "scale-info",
  "serde",
  "sp-application-crypto",
  "sp-core",
@@ -5693,6 +5751,7 @@ dependencies = [
  "frame-support",
  "frame-system",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5707,6 +5766,7 @@ dependencies = [
  "frame-support",
  "frame-system",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5721,6 +5781,7 @@ dependencies = [
  "frame-system",
  "log 0.4.14",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-inherents",
  "sp-io",
@@ -5740,6 +5801,7 @@ dependencies = [
  "pallet-balances",
  "pallet-treasury",
  "parity-scale-codec",
+ "scale-info",
  "serde",
  "sp-core",
  "sp-io",
@@ -5756,6 +5818,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "serde",
  "serde_json",
  "smallvec 1.6.1",
@@ -5801,6 +5864,7 @@ dependencies = [
  "hex-literal",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "serde",
  "sp-core",
  "sp-inherents",
@@ -5820,6 +5884,7 @@ dependencies = [
  "impl-trait-for-tuples",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "serde",
  "sp-core",
  "sp-io",
@@ -5836,6 +5901,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5851,6 +5917,7 @@ dependencies = [
  "frame-system",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5867,6 +5934,7 @@ dependencies = [
  "log 0.4.14",
  "pallet-balances",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -6393,6 +6461,7 @@ dependencies = [
  "fixed-hash",
  "impl-codec",
  "impl-serde",
+ "scale-info",
  "uint",
 ]
 
@@ -8324,6 +8393,32 @@ dependencies = [
  "prometheus",
 ]
 
+[[package]]
+name = "scale-info"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c55b744399c25532d63a0d2789b109df8d46fc93752d46b0782991a931a782f"
+dependencies = [
+ "bitvec 0.20.2",
+ "cfg-if 1.0.0",
+ "derive_more",
+ "parity-scale-codec",
+ "scale-info-derive",
+ "serde",
+]
+
+[[package]]
+name = "scale-info-derive"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd"
+dependencies = [
+ "proc-macro-crate 1.0.0",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "schannel"
 version = "0.1.19"
@@ -8779,6 +8874,7 @@ name = "sp-application-crypto"
 version = "4.0.0-dev"
 dependencies = [
  "parity-scale-codec",
+ "scale-info",
  "serde",
  "sp-core",
  "sp-io",
@@ -8807,6 +8903,7 @@ dependencies = [
  "parity-scale-codec",
  "primitive-types",
  "rand 0.7.3",
+ "scale-info",
  "serde",
  "sp-debug-derive",
  "sp-std",
@@ -8828,6 +8925,7 @@ name = "sp-authority-discovery"
 version = "4.0.0-dev"
 dependencies = [
  "parity-scale-codec",
+ "scale-info",
  "sp-api",
  "sp-application-crypto",
  "sp-runtime",
@@ -8898,6 +8996,7 @@ version = "0.10.0-dev"
 dependencies = [
  "async-trait",
  "parity-scale-codec",
+ "scale-info",
  "sp-api",
  "sp-application-crypto",
  "sp-consensus",
@@ -8915,6 +9014,7 @@ dependencies = [
  "async-trait",
  "merlin",
  "parity-scale-codec",
+ "scale-info",
  "serde",
  "sp-api",
  "sp-application-crypto",
@@ -8945,6 +9045,7 @@ name = "sp-consensus-slots"
 version = "0.10.0-dev"
 dependencies = [
  "parity-scale-codec",
+ "scale-info",
  "sp-arithmetic",
  "sp-runtime",
 ]
@@ -8987,6 +9088,7 @@ dependencies = [
  "primitive-types",
  "rand 0.7.3",
  "regex",
+ "scale-info",
  "schnorrkel",
  "secrecy",
  "serde",
@@ -9041,6 +9143,7 @@ dependencies = [
  "finality-grandpa",
  "log 0.4.14",
  "parity-scale-codec",
+ "scale-info",
  "serde",
  "sp-api",
  "sp-application-crypto",
@@ -9129,6 +9232,7 @@ version = "4.0.0-dev"
 dependencies = [
  "parity-scale-codec",
  "rand 0.7.3",
+ "scale-info",
  "serde",
  "sp-arithmetic",
  "sp-core",
@@ -9145,6 +9249,7 @@ dependencies = [
  "honggfuzz",
  "parity-scale-codec",
  "rand 0.7.3",
+ "scale-info",
  "sp-npos-elections",
  "sp-runtime",
  "structopt",
@@ -9158,6 +9263,7 @@ dependencies = [
  "proc-macro-crate 1.0.0",
  "proc-macro2",
  "quote",
+ "scale-info",
  "sp-arithmetic",
  "sp-npos-elections",
  "syn",
@@ -9202,6 +9308,7 @@ dependencies = [
  "parity-util-mem",
  "paste 1.0.4",
  "rand 0.7.3",
+ "scale-info",
  "serde",
  "serde_json",
  "sp-api",
@@ -9314,6 +9421,7 @@ name = "sp-session"
 version = "4.0.0-dev"
 dependencies = [
  "parity-scale-codec",
+ "scale-info",
  "sp-api",
  "sp-core",
  "sp-runtime",
@@ -9326,6 +9434,7 @@ name = "sp-staking"
 version = "4.0.0-dev"
 dependencies = [
  "parity-scale-codec",
+ "scale-info",
  "sp-runtime",
  "sp-std",
 ]
@@ -9443,6 +9552,7 @@ dependencies = [
  "async-trait",
  "log 0.4.14",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-inherents",
  "sp-runtime",
@@ -9459,6 +9569,7 @@ dependencies = [
  "hex-literal",
  "memory-db",
  "parity-scale-codec",
+ "scale-info",
  "sp-core",
  "sp-runtime",
  "sp-std",
@@ -9475,6 +9586,7 @@ dependencies = [
  "impl-serde",
  "parity-scale-codec",
  "parity-wasm 0.42.2",
+ "scale-info",
  "serde",
  "sp-runtime",
  "sp-std",
@@ -9659,6 +9771,7 @@ dependencies = [
  "jsonrpc-client-transports",
  "parity-scale-codec",
  "sc-rpc-api",
+ "scale-info",
  "serde",
  "sp-storage",
  "tokio",
@@ -9745,6 +9858,7 @@ dependencies = [
  "sc-block-builder",
  "sc-executor",
  "sc-service",
+ "scale-info",
  "serde",
  "sp-api",
  "sp-application-crypto",
diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml
index 64cbbf38966c34ca54048fd7785d82a7df159cd7..bca0c816217ee90c09c970aab3ec7825900e5182 100644
--- a/substrate/Cargo.toml
+++ b/substrate/Cargo.toml
@@ -94,7 +94,6 @@ members = [
 	"frame/merkle-mountain-range",
 	"frame/merkle-mountain-range/primitives",
 	"frame/merkle-mountain-range/rpc",
-	"frame/metadata",
 	"frame/multisig",
 	"frame/nicks",
 	"frame/node-authorization",
@@ -261,7 +260,6 @@ wasmi = { opt-level = 3 }
 x25519-dalek = { opt-level = 3 }
 yamux = { opt-level = 3 }
 zeroize = { opt-level = 3 }
-
 [profile.release]
 # Substrate runtime requires unwinding.
-panic = "unwind"
+panic = "unwind"
\ No newline at end of file
diff --git a/substrate/bin/node-template/pallets/template/Cargo.toml b/substrate/bin/node-template/pallets/template/Cargo.toml
index bd4a91f0146af488289071a59fbf8e0fc494ab8b..b3eb747625b4ff9c19a5c8f774b3e4121e518bbd 100644
--- a/substrate/bin/node-template/pallets/template/Cargo.toml
+++ b/substrate/bin/node-template/pallets/template/Cargo.toml
@@ -17,6 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/support" }
 frame-system = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/system" }
 frame-benchmarking = { default-features = false, version = "4.0.0-dev", path = "../../../../frame/benchmarking", optional = true }
@@ -30,6 +31,7 @@ sp-runtime = { default-features = false, version = "4.0.0-dev", path = "../../..
 default = ['std']
 std = [
 	'codec/std',
+	'scale-info/std',
 	'frame-support/std',
 	'frame-system/std',
 	'frame-benchmarking/std',
diff --git a/substrate/bin/node-template/pallets/template/src/lib.rs b/substrate/bin/node-template/pallets/template/src/lib.rs
index 7a9830a21eb2adf1512ead6576b3d798eb00389a..ee3ca695b64da5ef6e7348a135964527b4c383ca 100644
--- a/substrate/bin/node-template/pallets/template/src/lib.rs
+++ b/substrate/bin/node-template/pallets/template/src/lib.rs
@@ -41,7 +41,6 @@ pub mod pallet {
 	// Pallets use events to inform users when important changes are made.
 	// https://substrate.dev/docs/en/knowledgebase/runtime/events
 	#[pallet::event]
-	#[pallet::metadata(T::AccountId = "AccountId")]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
 		/// Event documentation should end with an array that provides descriptive names for event
diff --git a/substrate/bin/node-template/runtime/Cargo.toml b/substrate/bin/node-template/runtime/Cargo.toml
index 72e19cc62b0ba82c35fbf7ec04fd9395da34b4f3..47e67af2b9ae1b4d7eec2935df31ff80ba3893d3 100644
--- a/substrate/bin/node-template/runtime/Cargo.toml
+++ b/substrate/bin/node-template/runtime/Cargo.toml
@@ -13,6 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 
 pallet-aura = { version = "4.0.0-dev", default-features = false, path = "../../../frame/aura" }
 pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../frame/balances" }
@@ -54,6 +55,7 @@ substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-bu
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"frame-executive/std",
 	"frame-support/std",
 	"frame-system-rpc-runtime-api/std",
diff --git a/substrate/bin/node-template/runtime/src/lib.rs b/substrate/bin/node-template/runtime/src/lib.rs
index eae40e1ab3564c808e20ca36beb5e36fca374816..eecc93e16666607a7f98b228bbd5fb885993b147 100644
--- a/substrate/bin/node-template/runtime/src/lib.rs
+++ b/substrate/bin/node-template/runtime/src/lib.rs
@@ -340,7 +340,7 @@ impl_runtime_apis! {
 
 	impl sp_api::Metadata<Block> for Runtime {
 		fn metadata() -> OpaqueMetadata {
-			Runtime::metadata().into()
+			OpaqueMetadata::new(Runtime::metadata().into())
 		}
 	}
 
diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs
index 9f48ab7e3ef3cd70c06dd2c91be1ee877f278681..acc7df5b1e5a37cf4e2f7708f30fadaaadd5e0a1 100644
--- a/substrate/bin/node/cli/src/service.rs
+++ b/substrate/bin/node/cli/src/service.rs
@@ -810,7 +810,8 @@ mod tests {
 				};
 				let signer = charlie.clone();
 
-				let function = Call::Balances(BalancesCall::transfer(to.into(), amount));
+				let function =
+					Call::Balances(BalancesCall::transfer { dest: to.into(), value: amount });
 
 				let check_spec_version = frame_system::CheckSpecVersion::new();
 				let check_tx_version = frame_system::CheckTxVersion::new();
diff --git a/substrate/bin/node/executor/Cargo.toml b/substrate/bin/node/executor/Cargo.toml
index 0db8a9e411bf7154a6fb083f17750f081586f71a..f283a913915f34934cb9b0c5a9be285de3c0fc14 100644
--- a/substrate/bin/node/executor/Cargo.toml
+++ b/substrate/bin/node/executor/Cargo.toml
@@ -13,6 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0" }
+scale-info = { version = "1.0", features = ["derive"] }
 node-primitives = { version = "2.0.0", path = "../primitives" }
 node-runtime = { version = "3.0.0-dev", path = "../runtime" }
 sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" }
diff --git a/substrate/bin/node/executor/benches/bench.rs b/substrate/bin/node/executor/benches/bench.rs
index 0058a5c70340fed4b7fbe566012ec4c72344b2e1..1a39c9decb321e7e604532205cdbbaabb7dca077 100644
--- a/substrate/bin/node/executor/benches/bench.rs
+++ b/substrate/bin/node/executor/benches/bench.rs
@@ -162,11 +162,14 @@ fn test_blocks(
 	let mut test_ext = new_test_ext(genesis_config);
 	let mut block1_extrinsics = vec![CheckedExtrinsic {
 		signed: None,
-		function: Call::Timestamp(pallet_timestamp::Call::set(0)),
+		function: Call::Timestamp(pallet_timestamp::Call::set { now: 0 }),
 	}];
 	block1_extrinsics.extend((0..20).map(|i| CheckedExtrinsic {
 		signed: Some((alice(), signed_extra(i, 0))),
-		function: Call::Balances(pallet_balances::Call::transfer(bob().into(), 1 * DOLLARS)),
+		function: Call::Balances(pallet_balances::Call::transfer {
+			dest: bob().into(),
+			value: 1 * DOLLARS,
+		}),
 	}));
 	let block1 =
 		construct_block(executor, &mut test_ext.ext(), 1, GENESIS_HASH.into(), block1_extrinsics);
diff --git a/substrate/bin/node/executor/tests/basic.rs b/substrate/bin/node/executor/tests/basic.rs
index e9e21e541e753e558f7338cf6af271f13a314807..c1ab5e5a0fe139b15d168a9957efd04cdad2a2a4 100644
--- a/substrate/bin/node/executor/tests/basic.rs
+++ b/substrate/bin/node/executor/tests/basic.rs
@@ -84,14 +84,14 @@ fn changes_trie_block() -> (Vec<u8>, Hash) {
 		vec![
 			CheckedExtrinsic {
 				signed: None,
-				function: Call::Timestamp(pallet_timestamp::Call::set(time)),
+				function: Call::Timestamp(pallet_timestamp::Call::set { now: time }),
 			},
 			CheckedExtrinsic {
 				signed: Some((alice(), signed_extra(0, 0))),
-				function: Call::Balances(pallet_balances::Call::transfer(
-					bob().into(),
-					69 * DOLLARS,
-				)),
+				function: Call::Balances(pallet_balances::Call::transfer {
+					dest: bob().into(),
+					value: 69 * DOLLARS,
+				}),
 			},
 		],
 		(time / SLOT_DURATION).into(),
@@ -111,14 +111,14 @@ fn blocks() -> ((Vec<u8>, Hash), (Vec<u8>, Hash)) {
 		vec![
 			CheckedExtrinsic {
 				signed: None,
-				function: Call::Timestamp(pallet_timestamp::Call::set(time1)),
+				function: Call::Timestamp(pallet_timestamp::Call::set { now: time1 }),
 			},
 			CheckedExtrinsic {
 				signed: Some((alice(), signed_extra(0, 0))),
-				function: Call::Balances(pallet_balances::Call::transfer(
-					bob().into(),
-					69 * DOLLARS,
-				)),
+				function: Call::Balances(pallet_balances::Call::transfer {
+					dest: bob().into(),
+					value: 69 * DOLLARS,
+				}),
 			},
 		],
 		(time1 / SLOT_DURATION).into(),
@@ -131,21 +131,21 @@ fn blocks() -> ((Vec<u8>, Hash), (Vec<u8>, Hash)) {
 		vec![
 			CheckedExtrinsic {
 				signed: None,
-				function: Call::Timestamp(pallet_timestamp::Call::set(time2)),
+				function: Call::Timestamp(pallet_timestamp::Call::set { now: time2 }),
 			},
 			CheckedExtrinsic {
 				signed: Some((bob(), signed_extra(0, 0))),
-				function: Call::Balances(pallet_balances::Call::transfer(
-					alice().into(),
-					5 * DOLLARS,
-				)),
+				function: Call::Balances(pallet_balances::Call::transfer {
+					dest: alice().into(),
+					value: 5 * DOLLARS,
+				}),
 			},
 			CheckedExtrinsic {
 				signed: Some((alice(), signed_extra(1, 0))),
-				function: Call::Balances(pallet_balances::Call::transfer(
-					bob().into(),
-					15 * DOLLARS,
-				)),
+				function: Call::Balances(pallet_balances::Call::transfer {
+					dest: bob().into(),
+					value: 15 * DOLLARS,
+				}),
 			},
 		],
 		(time2 / SLOT_DURATION).into(),
@@ -166,11 +166,11 @@ fn block_with_size(time: u64, nonce: u32, size: usize) -> (Vec<u8>, Hash) {
 		vec![
 			CheckedExtrinsic {
 				signed: None,
-				function: Call::Timestamp(pallet_timestamp::Call::set(time * 1000)),
+				function: Call::Timestamp(pallet_timestamp::Call::set { now: time * 1000 }),
 			},
 			CheckedExtrinsic {
 				signed: Some((alice(), signed_extra(nonce, 0))),
-				function: Call::System(frame_system::Call::remark(vec![0; size])),
+				function: Call::System(frame_system::Call::remark { remark: vec![0; size] }),
 			},
 		],
 		(time * 1000 / SLOT_DURATION).into(),
@@ -357,7 +357,7 @@ fn full_native_block_import_works() {
 	let mut fees = t.execute_with(|| transfer_fee(&xt()));
 
 	let transfer_weight = default_transfer_call().get_dispatch_info().weight;
-	let timestamp_weight = pallet_timestamp::Call::set::<Runtime>(Default::default())
+	let timestamp_weight = pallet_timestamp::Call::set::<Runtime> { now: Default::default() }
 		.get_dispatch_info()
 		.weight;
 
@@ -646,28 +646,28 @@ fn deploying_wasm_contract_should_work() {
 		vec![
 			CheckedExtrinsic {
 				signed: None,
-				function: Call::Timestamp(pallet_timestamp::Call::set(time)),
+				function: Call::Timestamp(pallet_timestamp::Call::set { now: time }),
 			},
 			CheckedExtrinsic {
 				signed: Some((charlie(), signed_extra(0, 0))),
 				function: Call::Contracts(
-					pallet_contracts::Call::instantiate_with_code::<Runtime>(
-						1000 * DOLLARS + subsistence,
-						500_000_000,
-						transfer_code,
-						Vec::new(),
-						Vec::new(),
-					),
+					pallet_contracts::Call::instantiate_with_code::<Runtime> {
+						endowment: 1000 * DOLLARS + subsistence,
+						gas_limit: 500_000_000,
+						code: transfer_code,
+						data: Vec::new(),
+						salt: Vec::new(),
+					},
 				),
 			},
 			CheckedExtrinsic {
 				signed: Some((charlie(), signed_extra(1, 0))),
-				function: Call::Contracts(pallet_contracts::Call::call::<Runtime>(
-					sp_runtime::MultiAddress::Id(addr.clone()),
-					10,
-					500_000_000,
-					vec![0x00, 0x01, 0x02, 0x03],
-				)),
+				function: Call::Contracts(pallet_contracts::Call::call::<Runtime> {
+					dest: sp_runtime::MultiAddress::Id(addr.clone()),
+					value: 10,
+					gas_limit: 500_000_000,
+					data: vec![0x00, 0x01, 0x02, 0x03],
+				}),
 			},
 		],
 		(time / SLOT_DURATION).into(),
diff --git a/substrate/bin/node/executor/tests/common.rs b/substrate/bin/node/executor/tests/common.rs
index a0edb46a0d6ae7b2f6266191d3667207447e6930..d1c24c83c836d5f14590f36a0ffe4bdf5ee22c95 100644
--- a/substrate/bin/node/executor/tests/common.rs
+++ b/substrate/bin/node/executor/tests/common.rs
@@ -88,7 +88,7 @@ pub fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic {
 }
 
 pub fn default_transfer_call() -> pallet_balances::Call<Runtime> {
-	pallet_balances::Call::transfer::<Runtime>(bob().into(), 69 * DOLLARS)
+	pallet_balances::Call::<Runtime>::transfer { dest: bob().into(), value: 69 * DOLLARS }
 }
 
 pub fn from_block_number(n: u32) -> Header {
diff --git a/substrate/bin/node/executor/tests/fees.rs b/substrate/bin/node/executor/tests/fees.rs
index 3bc9179da2b3d1f7d62a802e583c6d2fb159762c..379cdda5b76a3439a049204010f3c88bc5327c05 100644
--- a/substrate/bin/node/executor/tests/fees.rs
+++ b/substrate/bin/node/executor/tests/fees.rs
@@ -56,11 +56,13 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() {
 		vec![
 			CheckedExtrinsic {
 				signed: None,
-				function: Call::Timestamp(pallet_timestamp::Call::set(time1)),
+				function: Call::Timestamp(pallet_timestamp::Call::set { now: time1 }),
 			},
 			CheckedExtrinsic {
 				signed: Some((charlie(), signed_extra(0, 0))),
-				function: Call::System(frame_system::Call::fill_block(Perbill::from_percent(60))),
+				function: Call::System(frame_system::Call::fill_block {
+					ratio: Perbill::from_percent(60),
+				}),
 			},
 		],
 		(time1 / SLOT_DURATION).into(),
@@ -75,11 +77,11 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() {
 		vec![
 			CheckedExtrinsic {
 				signed: None,
-				function: Call::Timestamp(pallet_timestamp::Call::set(time2)),
+				function: Call::Timestamp(pallet_timestamp::Call::set { now: time2 }),
 			},
 			CheckedExtrinsic {
 				signed: Some((charlie(), signed_extra(1, 0))),
-				function: Call::System(frame_system::Call::remark(vec![0; 1])),
+				function: Call::System(frame_system::Call::remark { remark: vec![0; 1] }),
 			},
 		],
 		(time2 / SLOT_DURATION).into(),
@@ -321,11 +323,9 @@ fn block_length_capacity_report() {
 				},
 				CheckedExtrinsic {
 					signed: Some((charlie(), signed_extra(nonce, 0))),
-					function: Call::System(frame_system::Call::remark(vec![
-						0u8;
-						(block_number * factor)
-							as usize
-					])),
+					function: Call::System(frame_system::Call::remark {
+						remark: vec![0u8; (block_number * factor) as usize],
+					}),
 				},
 			],
 			(time * 1000 / SLOT_DURATION).into(),
diff --git a/substrate/bin/node/executor/tests/submit_transaction.rs b/substrate/bin/node/executor/tests/submit_transaction.rs
index c83e48c8c933b157eea8da24238c8fad07c339c9..19ca8e5677c430357df21237db64067c86cdef3f 100644
--- a/substrate/bin/node/executor/tests/submit_transaction.rs
+++ b/substrate/bin/node/executor/tests/submit_transaction.rs
@@ -42,7 +42,7 @@ fn should_submit_unsigned_transaction() {
 			validators_len: 0,
 		};
 
-		let call = pallet_im_online::Call::heartbeat(heartbeat_data, signature);
+		let call = pallet_im_online::Call::heartbeat { heartbeat: heartbeat_data, signature };
 		SubmitTransaction::<Runtime, pallet_im_online::Call<Runtime>>::submit_unsigned_transaction(
 			call.into(),
 		)
@@ -84,7 +84,10 @@ fn should_submit_signed_transaction() {
 	t.execute_with(|| {
 		let results =
 			Signer::<Runtime, TestAuthorityId>::all_accounts().send_signed_transaction(|_| {
-				pallet_balances::Call::transfer(Default::default(), Default::default())
+				pallet_balances::Call::transfer {
+					dest: Default::default(),
+					value: Default::default(),
+				}
 			});
 
 		let len = results.len();
@@ -118,7 +121,10 @@ fn should_submit_signed_twice_from_the_same_account() {
 	t.execute_with(|| {
 		let result =
 			Signer::<Runtime, TestAuthorityId>::any_account().send_signed_transaction(|_| {
-				pallet_balances::Call::transfer(Default::default(), Default::default())
+				pallet_balances::Call::transfer {
+					dest: Default::default(),
+					value: Default::default(),
+				}
 			});
 
 		assert!(result.is_some());
@@ -127,7 +133,10 @@ fn should_submit_signed_twice_from_the_same_account() {
 		// submit another one from the same account. The nonce should be incremented.
 		let result =
 			Signer::<Runtime, TestAuthorityId>::any_account().send_signed_transaction(|_| {
-				pallet_balances::Call::transfer(Default::default(), Default::default())
+				pallet_balances::Call::transfer {
+					dest: Default::default(),
+					value: Default::default(),
+				}
 			});
 
 		assert!(result.is_some());
@@ -163,7 +172,7 @@ fn should_submit_signed_twice_from_all_accounts() {
 	t.execute_with(|| {
 		let results = Signer::<Runtime, TestAuthorityId>::all_accounts()
 			.send_signed_transaction(|_| {
-				pallet_balances::Call::transfer(Default::default(), Default::default())
+				pallet_balances::Call::transfer { dest: Default::default(), value: Default::default() }
 			});
 
 		let len = results.len();
@@ -174,7 +183,7 @@ fn should_submit_signed_twice_from_all_accounts() {
 		// submit another one from the same account. The nonce should be incremented.
 		let results = Signer::<Runtime, TestAuthorityId>::all_accounts()
 			.send_signed_transaction(|_| {
-				pallet_balances::Call::transfer(Default::default(), Default::default())
+				pallet_balances::Call::transfer { dest: Default::default(), value: Default::default() }
 			});
 
 		let len = results.len();
@@ -227,7 +236,10 @@ fn submitted_transaction_should_be_valid() {
 	t.execute_with(|| {
 		let results =
 			Signer::<Runtime, TestAuthorityId>::all_accounts().send_signed_transaction(|_| {
-				pallet_balances::Call::transfer(Default::default(), Default::default())
+				pallet_balances::Call::transfer {
+					dest: Default::default(),
+					value: Default::default(),
+				}
 			});
 		let len = results.len();
 		assert_eq!(len, 1);
diff --git a/substrate/bin/node/primitives/Cargo.toml b/substrate/bin/node/primitives/Cargo.toml
index de6000b602065a16eec50bf36dc877f8bdaed87d..12ec57e4d55b6a1c2b74dbb83fde005fca97bfe6 100644
--- a/substrate/bin/node/primitives/Cargo.toml
+++ b/substrate/bin/node/primitives/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system" }
 sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/application-crypto" }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" }
@@ -23,6 +24,7 @@ sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../..
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"frame-system/std",
 	"sp-application-crypto/std",
 	"sp-core/std",
diff --git a/substrate/bin/node/runtime/Cargo.toml b/substrate/bin/node/runtime/Cargo.toml
index 2b9accffc8c3afe52fdfc5fe41bbe6b88ab86ac3..dafd9db8bab9687eb02014c9147822adf100cc5e 100644
--- a/substrate/bin/node/runtime/Cargo.toml
+++ b/substrate/bin/node/runtime/Cargo.toml
@@ -18,6 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features =
 	"derive",
 	"max-encoded-len",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 static_assertions = "1.1.0"
 hex-literal = { version = "0.3.1", optional = true }
 log = { version = "0.4.14", default-features = false }
@@ -113,6 +114,7 @@ std = [
 	"pallet-bounties/std",
 	"sp-block-builder/std",
 	"codec/std",
+	"scale-info/std",
 	"pallet-collective/std",
 	"pallet-contracts/std",
 	"pallet-contracts-primitives/std",
diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index d7257a9ea71b5d2c076aac425ac4d298aaf58ab0..7c6475bd18d6adce6f06b48e6d6f0fb161b7cb5f 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -255,7 +255,17 @@ parameter_types! {
 
 /// The type used to represent the kinds of proxying allowed.
 #[derive(
-	Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen,
+	Copy,
+	Clone,
+	Eq,
+	PartialEq,
+	Ord,
+	PartialOrd,
+	Encode,
+	Decode,
+	RuntimeDebug,
+	MaxEncodedLen,
+	scale_info::TypeInfo,
 )]
 pub enum ProxyType {
 	Any,
@@ -276,8 +286,8 @@ impl InstanceFilter<Call> for ProxyType {
 				c,
 				Call::Balances(..) |
 					Call::Assets(..) | Call::Uniques(..) |
-					Call::Vesting(pallet_vesting::Call::vested_transfer(..)) |
-					Call::Indices(pallet_indices::Call::transfer(..))
+					Call::Vesting(pallet_vesting::Call::vested_transfer { .. }) |
+					Call::Indices(pallet_indices::Call::transfer { .. })
 			),
 			ProxyType::Governance => matches!(
 				c,
@@ -1314,7 +1324,7 @@ impl_runtime_apis! {
 
 	impl sp_api::Metadata<Block> for Runtime {
 		fn metadata() -> OpaqueMetadata {
-			Runtime::metadata().into()
+			OpaqueMetadata::new(Runtime::metadata().into())
 		}
 	}
 
diff --git a/substrate/bin/node/test-runner-example/src/lib.rs b/substrate/bin/node/test-runner-example/src/lib.rs
index e7fe1ee002423b813e2618558b0140fff5524d8b..0de7f5a4e2b709266d383ce6273901c029a01ce8 100644
--- a/substrate/bin/node/test-runner-example/src/lib.rs
+++ b/substrate/bin/node/test-runner-example/src/lib.rs
@@ -115,7 +115,7 @@ mod tests {
 			let alice = MultiSigner::from(Alice.public()).into_account();
 			let _hash = node
 				.submit_extrinsic(
-					frame_system::Call::remark((b"hello world").to_vec()),
+					frame_system::Call::remark { remark: (b"hello world").to_vec() },
 					Some(alice),
 				)
 				.await
diff --git a/substrate/bin/node/testing/src/bench.rs b/substrate/bin/node/testing/src/bench.rs
index a1f9bc8710565adb987bae6f9c90a42041ec3c6c..cf0a463cc3e99be1ebe50749dff07362b2aecd1e 100644
--- a/substrate/bin/node/testing/src/bench.rs
+++ b/substrate/bin/node/testing/src/bench.rs
@@ -299,19 +299,19 @@ impl<'a> Iterator for BlockContentIterator<'a> {
 				)),
 				function: match self.content.block_type {
 					BlockType::RandomTransfersKeepAlive =>
-						Call::Balances(BalancesCall::transfer_keep_alive(
-							sp_runtime::MultiAddress::Id(receiver),
-							node_runtime::ExistentialDeposit::get() + 1,
-						)),
+						Call::Balances(BalancesCall::transfer_keep_alive {
+							dest: sp_runtime::MultiAddress::Id(receiver),
+							value: node_runtime::ExistentialDeposit::get() + 1,
+						}),
 					BlockType::RandomTransfersReaping => {
-						Call::Balances(BalancesCall::transfer(
-							sp_runtime::MultiAddress::Id(receiver),
+						Call::Balances(BalancesCall::transfer {
+							dest: sp_runtime::MultiAddress::Id(receiver),
 							// Transfer so that ending balance would be 1 less than existential
 							// deposit so that we kill the sender account.
-							100 * DOLLARS - (node_runtime::ExistentialDeposit::get() - 1),
-						))
+							value: 100 * DOLLARS - (node_runtime::ExistentialDeposit::get() - 1),
+						})
 					},
-					BlockType::Noop => Call::System(SystemCall::remark(Vec::new())),
+					BlockType::Noop => Call::System(SystemCall::remark { remark: Vec::new() }),
 				},
 			},
 			self.runtime_version.spec_version,
diff --git a/substrate/client/finality-grandpa-warp-sync/Cargo.toml b/substrate/client/finality-grandpa-warp-sync/Cargo.toml
index 6bb00b936574c63cf5651fcce1c8674e31d1ede6..a444125fdfa11aad977dfa470daf0889249c1190 100644
--- a/substrate/client/finality-grandpa-warp-sync/Cargo.toml
+++ b/substrate/client/finality-grandpa-warp-sync/Cargo.toml
@@ -26,7 +26,7 @@ sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality
 sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" }
 
 [dev-dependencies]
-finality-grandpa = { version = "0.14.1" }
+finality-grandpa = { version = "0.14.4" }
 rand = "0.8"
 sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" }
 sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" }
diff --git a/substrate/client/finality-grandpa/Cargo.toml b/substrate/client/finality-grandpa/Cargo.toml
index ffdfc80c4eb9b73413c6ecce997fdf07201bd682..7fdd91e557ab7c7b0acb9897d3fca3769d064f05 100644
--- a/substrate/client/finality-grandpa/Cargo.toml
+++ b/substrate/client/finality-grandpa/Cargo.toml
@@ -43,7 +43,7 @@ sc-network-gossip = { version = "0.10.0-dev", path = "../network-gossip" }
 sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" }
 prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.9.0" }
 sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" }
-finality-grandpa = { version = "0.14.1", features = ["derive-codec"] }
+finality-grandpa = { version = "0.14.4", features = ["derive-codec"] }
 async-trait = "0.1.50"
 
 [dev-dependencies]
diff --git a/substrate/client/finality-grandpa/rpc/Cargo.toml b/substrate/client/finality-grandpa/rpc/Cargo.toml
index 4f989ad4964cd9555da02fb1175e2e7e76f157ec..d2976ee71275fbf3c3c99a9a305d5b8cff7a46ec 100644
--- a/substrate/client/finality-grandpa/rpc/Cargo.toml
+++ b/substrate/client/finality-grandpa/rpc/Cargo.toml
@@ -14,7 +14,7 @@ sc-rpc = { version = "4.0.0-dev", path = "../../rpc" }
 sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" }
 sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" }
 sp-runtime = { version = "4.0.0-dev", path = "../../../primitives/runtime" }
-finality-grandpa = { version = "0.14.1", features = ["derive-codec"] }
+finality-grandpa = { version = "0.14.4", features = ["derive-codec"] }
 jsonrpc-core = "18.0.0"
 jsonrpc-core-client = "18.0.0"
 jsonrpc-derive = "18.0.0"
diff --git a/substrate/frame/assets/Cargo.toml b/substrate/frame/assets/Cargo.toml
index 504dd6957aeb9dfc45ec37b2dc4c383a1eb557df..05e7912dd07c625a99dce33103dbb7499b53df71 100644
--- a/substrate/frame/assets/Cargo.toml
+++ b/substrate/frame/assets/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 # Needed for various traits. In our case, `OnFinalize`.
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -33,6 +34,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-runtime/std",
 	"frame-support/std",
diff --git a/substrate/frame/assets/src/benchmarking.rs b/substrate/frame/assets/src/benchmarking.rs
index 89a1308db1712513b5eb7d5105c32d4f397e6869..43eadffbe849736b8f6c9bb42bb0d7223e337586 100644
--- a/substrate/frame/assets/src/benchmarking.rs
+++ b/substrate/frame/assets/src/benchmarking.rs
@@ -330,13 +330,13 @@ benchmarks_instance_pallet! {
 		create_default_asset::<T, I>(true);
 
 		let origin = T::ForceOrigin::successful_origin();
-		let call = Call::<T, I>::force_set_metadata(
-			Default::default(),
-			name.clone(),
-			symbol.clone(),
+		let call = Call::<T, I>::force_set_metadata {
+			id: Default::default(),
+			name: name.clone(),
+			symbol: symbol.clone(),
 			decimals,
-			false,
-		);
+			is_frozen: false,
+		};
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
 		let id = Default::default();
@@ -351,7 +351,7 @@ benchmarks_instance_pallet! {
 		Assets::<T, I>::set_metadata(origin, Default::default(), dummy.clone(), dummy, 12)?;
 
 		let origin = T::ForceOrigin::successful_origin();
-		let call = Call::<T, I>::force_clear_metadata(Default::default());
+		let call = Call::<T, I>::force_clear_metadata { id: Default::default() };
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
 		assert_last_event::<T, I>(Event::MetadataCleared(Default::default()).into());
@@ -361,16 +361,16 @@ benchmarks_instance_pallet! {
 		let (caller, caller_lookup) = create_default_asset::<T, I>(true);
 
 		let origin = T::ForceOrigin::successful_origin();
-		let call = Call::<T, I>::force_asset_status(
-			Default::default(),
-			caller_lookup.clone(),
-			caller_lookup.clone(),
-			caller_lookup.clone(),
-			caller_lookup.clone(),
-			100u32.into(),
-			true,
-			false,
-		);
+		let call = Call::<T, I>::force_asset_status {
+			id: Default::default(),
+			owner: caller_lookup.clone(),
+			issuer: caller_lookup.clone(),
+			admin: caller_lookup.clone(),
+			freezer: caller_lookup.clone(),
+			min_balance: 100u32.into(),
+			is_sufficient: true,
+			is_frozen: false,
+		};
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
 		assert_last_event::<T, I>(Event::AssetStatusChanged(Default::default()).into());
diff --git a/substrate/frame/assets/src/lib.rs b/substrate/frame/assets/src/lib.rs
index 386a3ea05c082dad70739f4cac0f302e944fd5a0..797a3ae7ee9fb8dca57032ef6391b3f95b561826 100644
--- a/substrate/frame/assets/src/lib.rs
+++ b/substrate/frame/assets/src/lib.rs
@@ -277,7 +277,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId", T::Balance = "Balance", T::AssetId = "AssetId")]
 	pub enum Event<T: Config<I>, I: 'static = ()> {
 		/// Some asset class was created. \[asset_id, creator, owner\]
 		Created(T::AssetId, T::AccountId, T::AccountId),
diff --git a/substrate/frame/assets/src/types.rs b/substrate/frame/assets/src/types.rs
index 5e867550b3801eb7e245ab9c2d8fe23bda3c33e6..bc2edce848a64cf39b64eb561ade4049732fdd3d 100644
--- a/substrate/frame/assets/src/types.rs
+++ b/substrate/frame/assets/src/types.rs
@@ -19,6 +19,7 @@
 
 use super::*;
 use frame_support::pallet_prelude::*;
+use scale_info::TypeInfo;
 
 use frame_support::traits::{fungible, tokens::BalanceConversion};
 use sp_runtime::{traits::Convert, FixedPointNumber, FixedPointOperand, FixedU128};
@@ -26,7 +27,7 @@ use sp_runtime::{traits::Convert, FixedPointNumber, FixedPointOperand, FixedU128
 pub(super) type DepositBalanceOf<T, I = ()> =
 	<<T as Config<I>>::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance;
 
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen)]
+#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 pub struct AssetDetails<Balance, AccountId, DepositBalance> {
 	/// Can change `owner`, `issuer`, `freezer` and `admin` accounts.
 	pub(super) owner: AccountId,
@@ -66,7 +67,7 @@ impl<Balance, AccountId, DepositBalance> AssetDetails<Balance, AccountId, Deposi
 }
 
 /// Data concerning an approval.
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, MaxEncodedLen)]
+#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, MaxEncodedLen, TypeInfo)]
 pub struct Approval<Balance, DepositBalance> {
 	/// The amount of funds approved for the balance transfer from the owner to some delegated
 	/// target.
@@ -75,7 +76,7 @@ pub struct Approval<Balance, DepositBalance> {
 	pub(super) deposit: DepositBalance,
 }
 
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, MaxEncodedLen)]
+#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, MaxEncodedLen, TypeInfo)]
 pub struct AssetBalance<Balance, Extra> {
 	/// The balance.
 	pub(super) balance: Balance,
@@ -87,7 +88,7 @@ pub struct AssetBalance<Balance, Extra> {
 	pub(super) extra: Extra,
 }
 
-#[derive(Clone, Encode, Decode, Eq, PartialEq, Default, RuntimeDebug, MaxEncodedLen)]
+#[derive(Clone, Encode, Decode, Eq, PartialEq, Default, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 pub struct AssetMetadata<DepositBalance, BoundedString> {
 	/// The balance deposited for this metadata.
 	///
@@ -104,7 +105,7 @@ pub struct AssetMetadata<DepositBalance, BoundedString> {
 }
 
 /// Witness data for the destroy transactions.
-#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen)]
+#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 pub struct DestroyWitness {
 	/// The number of accounts holding the asset.
 	#[codec(compact)]
diff --git a/substrate/frame/atomic-swap/Cargo.toml b/substrate/frame/atomic-swap/Cargo.toml
index 2519772ed46defa344279c233ef1cf5a1ad40162..53a8c3a81165b891cfcea2daa6492924d81dae3d 100644
--- a/substrate/frame/atomic-swap/Cargo.toml
+++ b/substrate/frame/atomic-swap/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -28,6 +29,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"frame-support/std",
 	"frame-system/std",
 	"sp-runtime/std",
diff --git a/substrate/frame/atomic-swap/src/lib.rs b/substrate/frame/atomic-swap/src/lib.rs
index b068dc7ba1a961a5cde169380994bf5aa21341d8..9cf92c3bd23375c3317ce18cc73d2f1d0d5e2319 100644
--- a/substrate/frame/atomic-swap/src/lib.rs
+++ b/substrate/frame/atomic-swap/src/lib.rs
@@ -49,6 +49,7 @@ use frame_support::{
 	weights::Weight,
 	RuntimeDebugNoBound,
 };
+use scale_info::TypeInfo;
 use sp_io::hashing::blake2_256;
 use sp_runtime::RuntimeDebug;
 use sp_std::{
@@ -58,7 +59,8 @@ use sp_std::{
 };
 
 /// Pending atomic swap operation.
-#[derive(Clone, Eq, PartialEq, RuntimeDebugNoBound, Encode, Decode)]
+#[derive(Clone, Eq, PartialEq, RuntimeDebugNoBound, Encode, Decode, TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct PendingSwap<T: Config> {
 	/// Source of the swap.
 	pub source: T::AccountId,
@@ -91,7 +93,8 @@ pub trait SwapAction<AccountId, T: Config> {
 }
 
 /// A swap action that only allows transferring balances.
-#[derive(Clone, RuntimeDebug, Eq, PartialEq, Encode, Decode)]
+#[derive(Clone, RuntimeDebug, Eq, PartialEq, Encode, Decode, TypeInfo)]
+#[scale_info(skip_type_params(C))]
 pub struct BalanceSwapAction<AccountId, C: ReservableCurrency<AccountId>> {
 	value: <C as Currency<AccountId>>::Balance,
 	_marker: PhantomData<C>,
@@ -213,7 +216,6 @@ pub mod pallet {
 
 	/// Event of atomic swap pallet.
 	#[pallet::event]
-	#[pallet::metadata(T::AccountId = "AccountId", PendingSwap<T> = "PendingSwap")]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
 		/// Swap created. \[account, proof, swap\]
diff --git a/substrate/frame/aura/Cargo.toml b/substrate/frame/aura/Cargo.toml
index ee7b15f91e359a3c701b169a6ce147dae33ee87e..8f5c42bc3c465836cd1d5642ff509b5ade575c58 100644
--- a/substrate/frame/aura/Cargo.toml
+++ b/substrate/frame/aura/Cargo.toml
@@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" }
 codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
@@ -31,6 +32,7 @@ default = ["std"]
 std = [
 	"sp-application-crypto/std",
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-runtime/std",
 	"frame-support/std",
diff --git a/substrate/frame/authority-discovery/Cargo.toml b/substrate/frame/authority-discovery/Cargo.toml
index f5f695b0a06448a2030bc909d5f837458ae1a538..80a320c31e77ffcbbf59484c1449d69f6e080634 100644
--- a/substrate/frame/authority-discovery/Cargo.toml
+++ b/substrate/frame/authority-discovery/Cargo.toml
@@ -18,6 +18,7 @@ sp-application-crypto = { version = "4.0.0-dev", default-features = false, path
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 pallet-session = { version = "4.0.0-dev", features = [
 	"historical",
@@ -36,6 +37,7 @@ std = [
 	"sp-application-crypto/std",
 	"sp-authority-discovery/std",
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"pallet-session/std",
 	"sp-runtime/std",
diff --git a/substrate/frame/authorship/Cargo.toml b/substrate/frame/authorship/Cargo.toml
index a5b8d96160918a5b835991794d0cf04013318ef8..120b72f8e65114723bd4cc8ba9d8540894f725cd 100644
--- a/substrate/frame/authorship/Cargo.toml
+++ b/substrate/frame/authorship/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-authorship = { version = "4.0.0-dev", default-features = false, path = "../../primitives/authorship" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -31,6 +32,7 @@ sp-io = { version = "4.0.0-dev", path = "../../primitives/io" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-runtime/std",
 	"sp-std/std",
 	"frame-support/std",
diff --git a/substrate/frame/authorship/src/lib.rs b/substrate/frame/authorship/src/lib.rs
index 325f80c74aa1e47c29cd5c5a4cd8d27febf51e26..5d36adabe888fa7930a457f9d715ea46bdbce052 100644
--- a/substrate/frame/authorship/src/lib.rs
+++ b/substrate/frame/authorship/src/lib.rs
@@ -115,7 +115,7 @@ where
 	}
 }
 
-#[derive(Encode, Decode, sp_runtime::RuntimeDebug)]
+#[derive(Encode, Decode, sp_runtime::RuntimeDebug, scale_info::TypeInfo)]
 #[cfg_attr(any(feature = "std", test), derive(PartialEq))]
 enum UncleEntryItem<BlockNumber, Hash, Author> {
 	InclusionHeight(BlockNumber),
@@ -238,7 +238,7 @@ pub mod pallet {
 
 		fn create_inherent(data: &InherentData) -> Option<Self::Call> {
 			let uncles = data.uncles().unwrap_or_default();
-			let mut set_uncles = Vec::new();
+			let mut new_uncles = Vec::new();
 
 			if !uncles.is_empty() {
 				let prev_uncles = <Uncles<T>>::get();
@@ -257,10 +257,10 @@ pub mod pallet {
 					match Self::verify_uncle(&uncle, &existing_hashes, &mut acc) {
 						Ok(_) => {
 							let hash = uncle.hash();
-							set_uncles.push(uncle);
+							new_uncles.push(uncle);
 							existing_hashes.push(hash);
 
-							if set_uncles.len() == MAX_UNCLES {
+							if new_uncles.len() == MAX_UNCLES {
 								break
 							}
 						},
@@ -271,10 +271,10 @@ pub mod pallet {
 				}
 			}
 
-			if set_uncles.is_empty() {
+			if new_uncles.is_empty() {
 				None
 			} else {
-				Some(Call::set_uncles(set_uncles))
+				Some(Call::set_uncles { new_uncles })
 			}
 		}
 
@@ -283,14 +283,14 @@ pub mod pallet {
 			_data: &InherentData,
 		) -> result::Result<(), Self::Error> {
 			match call {
-				Call::set_uncles(ref uncles) if uncles.len() > MAX_UNCLES =>
+				Call::set_uncles { ref new_uncles } if new_uncles.len() > MAX_UNCLES =>
 					Err(InherentError::Uncles(Error::<T>::TooManyUncles.as_str().into())),
 				_ => Ok(()),
 			}
 		}
 
 		fn is_inherent(call: &Self::Call) -> bool {
-			matches!(call, Call::set_uncles(_))
+			matches!(call, Call::set_uncles { .. })
 		}
 	}
 }
diff --git a/substrate/frame/babe/Cargo.toml b/substrate/frame/babe/Cargo.toml
index f1a93bb418e9f15e9d9cffa1b58ac9a6d5c5d3a3..d95f1419fd035fdb1fb92be375df5c257847aef3 100644
--- a/substrate/frame/babe/Cargo.toml
+++ b/substrate/frame/babe/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
@@ -42,6 +43,7 @@ frame-election-provider-support = { version = "4.0.0-dev", path = "../election-p
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"frame-benchmarking/std",
 	"frame-support/std",
 	"frame-system/std",
diff --git a/substrate/frame/babe/src/equivocation.rs b/substrate/frame/babe/src/equivocation.rs
index 2558ca8a6e25517285485a4f2c094e609634c1d9..2397918d1ef134e821b8f5d62a046981cf3d482b 100644
--- a/substrate/frame/babe/src/equivocation.rs
+++ b/substrate/frame/babe/src/equivocation.rs
@@ -155,8 +155,10 @@ where
 	) -> DispatchResult {
 		use frame_system::offchain::SubmitTransaction;
 
-		let call =
-			Call::report_equivocation_unsigned(Box::new(equivocation_proof), key_owner_proof);
+		let call = Call::report_equivocation_unsigned {
+			equivocation_proof: Box::new(equivocation_proof),
+			key_owner_proof,
+		};
 
 		match SubmitTransaction::<T, Call<T>>::submit_unsigned_transaction(call.into()) {
 			Ok(()) => log::info!(
@@ -184,7 +186,7 @@ where
 /// unsigned equivocation reports.
 impl<T: Config> Pallet<T> {
 	pub fn validate_unsigned(source: TransactionSource, call: &Call<T>) -> TransactionValidity {
-		if let Call::report_equivocation_unsigned(equivocation_proof, key_owner_proof) = call {
+		if let Call::report_equivocation_unsigned { equivocation_proof, key_owner_proof } = call {
 			// discard equivocation report not coming from the local node
 			match source {
 				TransactionSource::Local | TransactionSource::InBlock => { /* allowed */ },
@@ -219,7 +221,7 @@ impl<T: Config> Pallet<T> {
 	}
 
 	pub fn pre_dispatch(call: &Call<T>) -> Result<(), TransactionValidityError> {
-		if let Call::report_equivocation_unsigned(equivocation_proof, key_owner_proof) = call {
+		if let Call::report_equivocation_unsigned { equivocation_proof, key_owner_proof } = call {
 			is_known_offence::<T>(equivocation_proof, key_owner_proof)
 		} else {
 			Err(InvalidTransaction::Call.into())
diff --git a/substrate/frame/babe/src/tests.rs b/substrate/frame/babe/src/tests.rs
index edb3eeb059d8338ab46be19aa58d945848dc6209..dc2f74c71951974905c6b9a95cf028a600755426 100644
--- a/substrate/frame/babe/src/tests.rs
+++ b/substrate/frame/babe/src/tests.rs
@@ -726,10 +726,10 @@ fn report_equivocation_validate_unsigned_prevents_duplicates() {
 		let key = (sp_consensus_babe::KEY_TYPE, &offending_authority_pair.public());
 		let key_owner_proof = Historical::prove(key).unwrap();
 
-		let inner = Call::report_equivocation_unsigned(
-			Box::new(equivocation_proof.clone()),
-			key_owner_proof.clone(),
-		);
+		let inner = Call::report_equivocation_unsigned {
+			equivocation_proof: Box::new(equivocation_proof.clone()),
+			key_owner_proof: key_owner_proof.clone(),
+		};
 
 		// only local/inblock reports are allowed
 		assert_eq!(
@@ -822,10 +822,10 @@ fn valid_equivocation_reports_dont_pay_fees() {
 				.unwrap();
 
 		// check the dispatch info for the call.
-		let info = Call::<Test>::report_equivocation_unsigned(
-			Box::new(equivocation_proof.clone()),
-			key_owner_proof.clone(),
-		)
+		let info = Call::<Test>::report_equivocation_unsigned {
+			equivocation_proof: Box::new(equivocation_proof.clone()),
+			key_owner_proof: key_owner_proof.clone(),
+		}
 		.get_dispatch_info();
 
 		// it should have non-zero weight and the fee has to be paid.
diff --git a/substrate/frame/balances/Cargo.toml b/substrate/frame/balances/Cargo.toml
index 8b66f08d45d97cef715315325dbec1c2174cfe3e..2263387d6d8eff87c1e3eafcd07f0e2ab9ff0fb8 100644
--- a/substrate/frame/balances/Cargo.toml
+++ b/substrate/frame/balances/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
 frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../benchmarking", optional = true }
@@ -30,6 +31,7 @@ pallet-transaction-payment = { version = "4.0.0-dev", path = "../transaction-pay
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-runtime/std",
 	"frame-benchmarking/std",
diff --git a/substrate/frame/balances/src/lib.rs b/substrate/frame/balances/src/lib.rs
index 7ab8a54de232d2b118f10c4db5283d281618a856..f7102ad4895f9ae47e756910cafeac900044683b 100644
--- a/substrate/frame/balances/src/lib.rs
+++ b/substrate/frame/balances/src/lib.rs
@@ -177,6 +177,7 @@ use frame_support::{
 	WeakBoundedVec,
 };
 use frame_system as system;
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{
 		AtLeast32BitUnsigned, Bounded, CheckedAdd, CheckedSub, MaybeSerializeDeserialize,
@@ -206,7 +207,8 @@ pub mod pallet {
 			+ Copy
 			+ MaybeSerializeDeserialize
 			+ Debug
-			+ MaxEncodedLen;
+			+ MaxEncodedLen
+			+ TypeInfo;
 
 		/// Handler for the unbalanced reduction when removing a dust account.
 		type DustRemoval: OnUnbalanced<NegativeImbalance<Self, I>>;
@@ -435,7 +437,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId", T::Balance = "Balance")]
 	pub enum Event<T: Config<I>, I: 'static = ()> {
 		/// An account was created with some free balance. \[account, free_balance\]
 		Endowed(T::AccountId, T::Balance),
@@ -599,7 +600,7 @@ impl<T: Config<I>, I: 'static> GenesisConfig<T, I> {
 }
 
 /// Simplified reasons for withdrawing balance.
-#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, MaxEncodedLen)]
+#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 pub enum Reasons {
 	/// Paying system transaction fees.
 	Fee = 0,
@@ -633,7 +634,7 @@ impl BitOr for Reasons {
 
 /// A single lock on a balance. There can be many of these on an account and they "overlap", so the
 /// same balance is frozen by multiple locks.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 pub struct BalanceLock<Balance> {
 	/// An identifier for this lock. Only one lock may be in existence for each identifier.
 	pub id: LockIdentifier,
@@ -644,7 +645,7 @@ pub struct BalanceLock<Balance> {
 }
 
 /// Store named reserved balance.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 pub struct ReserveData<ReserveIdentifier, Balance> {
 	/// The identifier for the named reserve.
 	pub id: ReserveIdentifier,
@@ -653,7 +654,7 @@ pub struct ReserveData<ReserveIdentifier, Balance> {
 }
 
 /// All balance information for an account.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, Default, RuntimeDebug, MaxEncodedLen)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, Default, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 pub struct AccountData<Balance> {
 	/// Non-reserved part of the balance. There may still be restrictions on this, but it is the
 	/// total pool what may in principle be transferred, reserved and used for tipping.
@@ -700,7 +701,7 @@ impl<Balance: Saturating + Copy + Ord> AccountData<Balance> {
 // A value placed in storage that represents the current version of the Balances storage.
 // This value is used by the `on_runtime_upgrade` logic to determine whether we run
 // storage migration logic. This should match directly with the semantic versions of the Rust crate.
-#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, MaxEncodedLen)]
+#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 enum Releases {
 	V1_0_0,
 	V2_0_0,
diff --git a/substrate/frame/balances/src/tests.rs b/substrate/frame/balances/src/tests.rs
index fd57371b3a16b7e397f31fb772b8acd483483cf2..a08643821eba807a5db549d217d45fd9e7635039 100644
--- a/substrate/frame/balances/src/tests.rs
+++ b/substrate/frame/balances/src/tests.rs
@@ -39,7 +39,7 @@ macro_rules! decl_tests {
 		const ID_2: LockIdentifier = *b"2       ";
 
 		pub const CALL: &<$test as frame_system::Config>::Call =
-			&Call::Balances(pallet_balances::Call::transfer(0, 0));
+			&Call::Balances(pallet_balances::Call::transfer { dest: 0, value: 0 });
 
 		/// create a transaction info struct from weight. Handy to avoid building the whole struct.
 		pub fn info_from_weight(w: Weight) -> DispatchInfo {
diff --git a/substrate/frame/benchmarking/Cargo.toml b/substrate/frame/benchmarking/Cargo.toml
index ad15b8e6042ef1acd6761b1a4156eeb1b816b65e..ea690d966c979c923afbdf49849d405adb8b8212 100644
--- a/substrate/frame/benchmarking/Cargo.toml
+++ b/substrate/frame/benchmarking/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 linregress = { version = "0.4.3", optional = true }
 paste = "1.0"
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-api = { version = "4.0.0-dev", path = "../../primitives/api", default-features = false }
 sp-runtime-interface = { version = "4.0.0-dev", path = "../../primitives/runtime-interface", default-features = false }
 sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime", default-features = false }
@@ -33,6 +34,7 @@ hex-literal = "0.3.1"
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-runtime-interface/std",
 	"sp-runtime/std",
 	"sp-api/std",
diff --git a/substrate/frame/benchmarking/src/lib.rs b/substrate/frame/benchmarking/src/lib.rs
index 11c755e06c95fe17e82dfecb5999aa5bcf4c1833..6c124a8a7576186a57bd7263213f0c9c283d33a2 100644
--- a/substrate/frame/benchmarking/src/lib.rs
+++ b/substrate/frame/benchmarking/src/lib.rs
@@ -331,30 +331,38 @@ macro_rules! benchmarks_iter {
 		verify $postcode:block
 		$( $rest:tt )*
 	) => {
-		$crate::benchmarks_iter! {
-			{ $( $instance: $instance_bound )? }
-			{ $( $where_clause )* }
-			( $( $names )* )
-			( $( $names_extra )* )
-			( $( $names_skip_meta )* )
-			$name {
-				$( $code )*
-				let __benchmarked_call_encoded = $crate::frame_support::codec::Encode::encode(
-					&<Call<T $(, $instance )?>>::$dispatch($( $arg ),*)
-				);
-			}: {
-				let call_decoded = <
-					Call<T $(, $instance )?>
-					as $crate::frame_support::codec::Decode
-				>::decode(&mut &__benchmarked_call_encoded[..])
-					.expect("call is encoded above, encoding must be correct");
+		$crate::paste::paste! {
+			$crate::benchmarks_iter! {
+				{ $( $instance: $instance_bound )? }
+				{ $( $where_clause )* }
+				( $( $names )* )
+				( $( $names_extra )* )
+				( $( $names_skip_meta )* )
+				$name {
+					$( $code )*
+					let __call = Call::<
+						T
+						$( , $instance )?
+					>:: [< new_call_variant_ $dispatch >] (
+						$($arg),*
+					);
+					let __benchmarked_call_encoded = $crate::frame_support::codec::Encode::encode(
+						&__call
+					);
+				}: {
+					let call_decoded = <
+						Call<T $(, $instance )?>
+						as $crate::frame_support::codec::Decode
+					>::decode(&mut &__benchmarked_call_encoded[..])
+						.expect("call is encoded above, encoding must be correct");
 
-				<
-					Call<T $(, $instance)? > as $crate::frame_support::traits::UnfilteredDispatchable
-				>::dispatch_bypass_filter(call_decoded, $origin.into())?;
+					<
+						Call<T $(, $instance)? > as $crate::frame_support::traits::UnfilteredDispatchable
+					>::dispatch_bypass_filter(call_decoded, $origin.into())?;
+				}
+				verify $postcode
+				$( $rest )*
 			}
-			verify $postcode
-			$( $rest )*
 		}
 	};
 	// iteration arm:
diff --git a/substrate/frame/bounties/Cargo.toml b/substrate/frame/bounties/Cargo.toml
index 84147b96f9104e0ff50e773ef6f0ddfbcddbd8c2..3bb184d5b3393fc193789d5ff348512f2ec14f02 100644
--- a/substrate/frame/bounties/Cargo.toml
+++ b/substrate/frame/bounties/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
@@ -33,6 +34,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-runtime/std",
 	"frame-support/std",
diff --git a/substrate/frame/bounties/src/lib.rs b/substrate/frame/bounties/src/lib.rs
index a5be4a00cb94c2e743535711bf62e067d21680f8..77a8e4717401915f28c338a9d4aac1070c0f8e59 100644
--- a/substrate/frame/bounties/src/lib.rs
+++ b/substrate/frame/bounties/src/lib.rs
@@ -97,6 +97,7 @@ use frame_support::weights::Weight;
 
 use codec::{Decode, Encode};
 use frame_system::{self as system, ensure_signed};
+use scale_info::TypeInfo;
 pub use weights::WeightInfo;
 
 type BalanceOf<T> = pallet_treasury::BalanceOf<T>;
@@ -136,7 +137,7 @@ pub trait Config: frame_system::Config + pallet_treasury::Config {
 pub type BountyIndex = u32;
 
 /// A bounty proposal.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub struct Bounty<AccountId, Balance, BlockNumber> {
 	/// The account proposing it.
 	proposer: AccountId,
@@ -153,7 +154,7 @@ pub struct Bounty<AccountId, Balance, BlockNumber> {
 }
 
 /// The status of a bounty proposal.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub enum BountyStatus<AccountId, BlockNumber> {
 	/// The bounty is proposed and waiting for approval.
 	Proposed,
diff --git a/substrate/frame/collective/Cargo.toml b/substrate/frame/collective/Cargo.toml
index 8828c6a61cd3fa81c3bbbf3e545073cd53fa1c55..e88f28d417730cb7b7270c1191a286a4bde3ddcd 100644
--- a/substrate/frame/collective/Cargo.toml
+++ b/substrate/frame/collective/Cargo.toml
@@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
 log = { version = "0.4.14", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
@@ -30,6 +31,7 @@ default = ["std"]
 std = [
 	"codec/std",
 	"log/std",
+	"scale-info/std",
 	"sp-core/std",
 	"sp-io/std",
 	"sp-runtime/std",
diff --git a/substrate/frame/collective/src/benchmarking.rs b/substrate/frame/collective/src/benchmarking.rs
index 1ce7750278bc4ea8bc1c3b4c901935e10c2c481f..c7e695babf27d88f828eddd9aaa1398f55176df8 100644
--- a/substrate/frame/collective/src/benchmarking.rs
+++ b/substrate/frame/collective/src/benchmarking.rs
@@ -65,7 +65,9 @@ benchmarks_instance_pallet! {
 		let length = 100;
 		for i in 0 .. p {
 			// Proposals should be different so that different proposal hashes are generated
-			let proposal: T::Proposal = SystemCall::<T>::remark(vec![i as u8; length]).into();
+			let proposal: T::Proposal = SystemCall::<T>::remark {
+				remark: vec![i as u8; length]
+			}.into();
 			Collective::<T, I>::propose(
 				SystemOrigin::Signed(last_old_member.clone()).into(),
 				threshold,
@@ -121,7 +123,7 @@ benchmarks_instance_pallet! {
 
 		Collective::<T, I>::set_members(SystemOrigin::Root.into(), members, None, T::MaxMembers::get())?;
 
-		let proposal: T::Proposal = SystemCall::<T>::remark(vec![1; b as usize]).into();
+		let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![1; b as usize] }.into();
 
 	}: _(SystemOrigin::Signed(caller), Box::new(proposal.clone()), bytes_in_storage)
 	verify {
@@ -151,7 +153,7 @@ benchmarks_instance_pallet! {
 
 		Collective::<T, I>::set_members(SystemOrigin::Root.into(), members, None, T::MaxMembers::get())?;
 
-		let proposal: T::Proposal = SystemCall::<T>::remark(vec![1; b as usize]).into();
+		let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![1; b as usize] }.into();
 		let threshold = 1;
 
 	}: propose(SystemOrigin::Signed(caller), threshold, Box::new(proposal.clone()), bytes_in_storage)
@@ -185,7 +187,7 @@ benchmarks_instance_pallet! {
 		// Add previous proposals.
 		for i in 0 .. p - 1 {
 			// Proposals should be different so that different proposal hashes are generated
-			let proposal: T::Proposal = SystemCall::<T>::remark(vec![i as u8; b as usize]).into();
+			let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![i as u8; b as usize] }.into();
 			Collective::<T, I>::propose(
 				SystemOrigin::Signed(caller.clone()).into(),
 				threshold,
@@ -196,7 +198,7 @@ benchmarks_instance_pallet! {
 
 		assert_eq!(Collective::<T, I>::proposals().len(), (p - 1) as usize);
 
-		let proposal: T::Proposal = SystemCall::<T>::remark(vec![p as u8; b as usize]).into();
+		let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![p as u8; b as usize] }.into();
 
 	}: propose(SystemOrigin::Signed(caller.clone()), threshold, Box::new(proposal.clone()), bytes_in_storage)
 	verify {
@@ -233,7 +235,7 @@ benchmarks_instance_pallet! {
 		let mut last_hash = T::Hash::default();
 		for i in 0 .. p {
 			// Proposals should be different so that different proposal hashes are generated
-			let proposal: T::Proposal = SystemCall::<T>::remark(vec![i as u8; b as usize]).into();
+			let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![i as u8; b as usize] }.into();
 			Collective::<T, I>::propose(
 				SystemOrigin::Signed(proposer.clone()).into(),
 				threshold,
@@ -308,7 +310,9 @@ benchmarks_instance_pallet! {
 		let mut last_hash = T::Hash::default();
 		for i in 0 .. p {
 			// Proposals should be different so that different proposal hashes are generated
-			let proposal: T::Proposal = SystemCall::<T>::remark(vec![i as u8; bytes as usize]).into();
+			let proposal: T::Proposal = SystemCall::<T>::remark {
+				remark: vec![i as u8; bytes as usize]
+			}.into();
 			Collective::<T, I>::propose(
 				SystemOrigin::Signed(proposer.clone()).into(),
 				threshold,
@@ -385,7 +389,7 @@ benchmarks_instance_pallet! {
 		let mut last_hash = T::Hash::default();
 		for i in 0 .. p {
 			// Proposals should be different so that different proposal hashes are generated
-			let proposal: T::Proposal = SystemCall::<T>::remark(vec![i as u8; b as usize]).into();
+			let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![i as u8; b as usize] }.into();
 			Collective::<T, I>::propose(
 				SystemOrigin::Signed(caller.clone()).into(),
 				threshold,
@@ -471,7 +475,9 @@ benchmarks_instance_pallet! {
 		let mut last_hash = T::Hash::default();
 		for i in 0 .. p {
 			// Proposals should be different so that different proposal hashes are generated
-			let proposal: T::Proposal = SystemCall::<T>::remark(vec![i as u8; bytes as usize]).into();
+			let proposal: T::Proposal = SystemCall::<T>::remark {
+				remark: vec![i as u8; bytes as usize]
+			}.into();
 			Collective::<T, I>::propose(
 				SystemOrigin::Signed(caller.clone()).into(),
 				threshold,
@@ -543,7 +549,7 @@ benchmarks_instance_pallet! {
 		let mut last_hash = T::Hash::default();
 		for i in 0 .. p {
 			// Proposals should be different so that different proposal hashes are generated
-			let proposal: T::Proposal = SystemCall::<T>::remark(vec![i as u8; b as usize]).into();
+			let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![i as u8; b as usize] }.into();
 			Collective::<T, I>::propose(
 				SystemOrigin::Signed(caller.clone()).into(),
 				threshold,
@@ -614,7 +620,7 @@ benchmarks_instance_pallet! {
 		let mut last_hash = T::Hash::default();
 		for i in 0 .. p {
 			// Proposals should be different so that different proposal hashes are generated
-			let proposal: T::Proposal = SystemCall::<T>::remark(vec![i as u8; b as usize]).into();
+			let proposal: T::Proposal = SystemCall::<T>::remark { remark: vec![i as u8; b as usize] }.into();
 			Collective::<T, I>::propose(
 				SystemOrigin::Signed(caller.clone()).into(),
 				threshold,
diff --git a/substrate/frame/collective/src/lib.rs b/substrate/frame/collective/src/lib.rs
index fa537a0a439a13c34ccb797fb6daf6f184a5fcf0..89d4c8a150c361ddb076c194d52e91544ca8eb87 100644
--- a/substrate/frame/collective/src/lib.rs
+++ b/substrate/frame/collective/src/lib.rs
@@ -42,6 +42,7 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 #![recursion_limit = "128"]
 
+use scale_info::TypeInfo;
 use sp_core::u32_trait::Value as U32;
 use sp_io::storage;
 use sp_runtime::{traits::Hash, RuntimeDebug};
@@ -124,7 +125,8 @@ impl DefaultVote for MoreThanMajorityThenPrimeDefaultVote {
 }
 
 /// Origin for the collective module.
-#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode)]
+#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo)]
+#[scale_info(skip_type_params(I))]
 pub enum RawOrigin<AccountId, I> {
 	/// It has been condoned by a given number of members of the collective from a given total.
 	Members(MemberCount, MemberCount),
@@ -144,7 +146,7 @@ impl<AccountId, I> GetBacking for RawOrigin<AccountId, I> {
 }
 
 /// Info for keeping track of a motion being voted on.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
 pub struct Votes<AccountId, BlockNumber> {
 	/// The proposal's unique index.
 	index: ProposalIndex,
@@ -274,7 +276,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId", T::Hash = "Hash")]
 	pub enum Event<T: Config<I>, I: 'static = ()> {
 		/// A motion (given hash) has been proposed (by given account) with a threshold (given
 		/// `MemberCount`).
diff --git a/substrate/frame/collective/src/tests.rs b/substrate/frame/collective/src/tests.rs
index 5c662428fd9923b3e9123d51e9fad8948311f7b9..b8feb64867cf8531cb9ba5ac2b1487f1f1a8b4b9 100644
--- a/substrate/frame/collective/src/tests.rs
+++ b/substrate/frame/collective/src/tests.rs
@@ -172,7 +172,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
 }
 
 fn make_proposal(value: u64) -> Call {
-	Call::System(frame_system::Call::remark(value.encode()))
+	Call::System(frame_system::Call::remark { remark: value.encode() })
 }
 
 fn record(event: Event) -> EventRecord<Event, H256> {
@@ -229,8 +229,11 @@ fn close_works() {
 #[test]
 fn proposal_weight_limit_works_on_approve() {
 	new_test_ext().execute_with(|| {
-		let proposal =
-			Call::Collective(crate::Call::set_members(vec![1, 2, 3], None, MaxMembers::get()));
+		let proposal = Call::Collective(crate::Call::set_members {
+			new_members: vec![1, 2, 3],
+			prime: None,
+			old_count: MaxMembers::get(),
+		});
 		let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32);
 		let proposal_weight = proposal.get_dispatch_info().weight;
 		let hash = BlakeTwo256::hash_of(&proposal);
@@ -256,8 +259,11 @@ fn proposal_weight_limit_works_on_approve() {
 #[test]
 fn proposal_weight_limit_ignored_on_disapprove() {
 	new_test_ext().execute_with(|| {
-		let proposal =
-			Call::Collective(crate::Call::set_members(vec![1, 2, 3], None, MaxMembers::get()));
+		let proposal = Call::Collective(crate::Call::set_members {
+			new_members: vec![1, 2, 3],
+			prime: None,
+			old_count: MaxMembers::get(),
+		});
 		let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32);
 		let proposal_weight = proposal.get_dispatch_info().weight;
 		let hash = BlakeTwo256::hash_of(&proposal);
@@ -561,8 +567,11 @@ fn limit_active_proposals() {
 #[test]
 fn correct_validate_and_get_proposal() {
 	new_test_ext().execute_with(|| {
-		let proposal =
-			Call::Collective(crate::Call::set_members(vec![1, 2, 3], None, MaxMembers::get()));
+		let proposal = Call::Collective(crate::Call::set_members {
+			new_members: vec![1, 2, 3],
+			prime: None,
+			old_count: MaxMembers::get(),
+		});
 		let length = proposal.encode().len() as u32;
 		assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), length));
 
@@ -782,7 +791,7 @@ fn motions_reproposing_disapproved_works() {
 #[test]
 fn motions_approval_with_enough_votes_and_lower_voting_threshold_works() {
 	new_test_ext().execute_with(|| {
-		let proposal = Call::Democracy(mock_democracy::Call::external_propose_majority());
+		let proposal = Call::Democracy(mock_democracy::Call::external_propose_majority {});
 		let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32);
 		let proposal_weight = proposal.get_dispatch_info().weight;
 		let hash: H256 = proposal.blake2_256().into();
diff --git a/substrate/frame/contracts/Cargo.toml b/substrate/frame/contracts/Cargo.toml
index 36d05e35180bee0d9ecc66e628e76ec84184ef51..80dc0b05e75117ef7a5a62c68b30bc1ed655d2e6 100644
--- a/substrate/frame/contracts/Cargo.toml
+++ b/substrate/frame/contracts/Cargo.toml
@@ -18,6 +18,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features =
 	"derive",
 	"max-encoded-len",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 log = { version = "0.4", default-features = false }
 pwasm-utils = { version = "0.18.2", default-features = false }
 serde = { version = "1", optional = true, features = ["derive"] }
@@ -60,6 +61,7 @@ default = ["std"]
 std = [
 	"serde",
 	"codec/std",
+	"scale-info/std",
 	"sp-core/std",
 	"sp-runtime/std",
 	"sp-io/std",
diff --git a/substrate/frame/contracts/common/Cargo.toml b/substrate/frame/contracts/common/Cargo.toml
index e353b3af04714796c96c6809ba5933bed5deccb3..b441d88453ae261ea06b27695c3edd1efbfab595 100644
--- a/substrate/frame/contracts/common/Cargo.toml
+++ b/substrate/frame/contracts/common/Cargo.toml
@@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 bitflags = "1.0"
 codec = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 serde = { version = "1", features = ["derive"], optional = true }
 
 # Substrate Dependencies (This crate should not rely on frame)
@@ -26,6 +27,7 @@ sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../..
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-core/std",
 	"sp-runtime/std",
 	"sp-std/std",
diff --git a/substrate/frame/contracts/rpc/runtime-api/Cargo.toml b/substrate/frame/contracts/rpc/runtime-api/Cargo.toml
index fb5addc5a437bfa9a143ea583ae1531de524aba8..e5f6d1ec7eb8e370a460192ddd62a42d479e619c 100644
--- a/substrate/frame/contracts/rpc/runtime-api/Cargo.toml
+++ b/substrate/frame/contracts/rpc/runtime-api/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 
 # Substrate Dependencies
 pallet-contracts-primitives = { version = "4.0.0-dev", default-features = false, path = "../../common" }
@@ -26,6 +27,7 @@ default = ["std"]
 std = [
 	"sp-api/std",
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-runtime/std",
 	"pallet-contracts-primitives/std",
diff --git a/substrate/frame/contracts/src/exec.rs b/substrate/frame/contracts/src/exec.rs
index 516de3a22d5aeb9a7d10a951e44090fca787ea5c..cc468466c2922e2b68488b19e0233a9455853671 100644
--- a/substrate/frame/contracts/src/exec.rs
+++ b/substrate/frame/contracts/src/exec.rs
@@ -2060,7 +2060,9 @@ mod tests {
 	#[test]
 	fn call_runtime_works() {
 		let code_hash = MockLoader::insert(Call, |ctx, _| {
-			let call = Call::System(frame_system::Call::remark_with_event(b"Hello World".to_vec()));
+			let call = Call::System(frame_system::Call::remark_with_event {
+				remark: b"Hello World".to_vec(),
+			});
 			ctx.ext.call_runtime(call).unwrap();
 			exec_success()
 		});
@@ -2094,20 +2096,19 @@ mod tests {
 			use pallet_utility::Call as UtilCall;
 
 			// remark should still be allowed
-			let allowed_call = Call::System(SysCall::remark_with_event(b"Hello".to_vec()));
+			let allowed_call =
+				Call::System(SysCall::remark_with_event { remark: b"Hello".to_vec() });
 
 			// transfers are disallowed by the `TestFiler` (see below)
-			let forbidden_call = Call::Balances(BalanceCall::transfer(CHARLIE, 22));
+			let forbidden_call = Call::Balances(BalanceCall::transfer { dest: CHARLIE, value: 22 });
 
 			// simple cases: direct call
 			assert_err!(ctx.ext.call_runtime(forbidden_call.clone()), BadOrigin);
 
 			// as part of a patch: return is OK (but it interrupted the batch)
-			assert_ok!(ctx.ext.call_runtime(Call::Utility(UtilCall::batch(vec![
-				allowed_call.clone(),
-				forbidden_call,
-				allowed_call
-			]))),);
+			assert_ok!(ctx.ext.call_runtime(Call::Utility(UtilCall::batch {
+				calls: vec![allowed_call.clone(), forbidden_call, allowed_call]
+			})),);
 
 			// the transfer wasn't performed
 			assert_eq!(get_balance(&CHARLIE), 0);
@@ -2116,7 +2117,7 @@ mod tests {
 		});
 
 		TestFilter::set_filter(|call| match call {
-			Call::Balances(pallet_balances::Call::transfer(_, _)) => false,
+			Call::Balances(pallet_balances::Call::transfer { .. }) => false,
 			_ => true,
 		});
 
diff --git a/substrate/frame/contracts/src/lib.rs b/substrate/frame/contracts/src/lib.rs
index 7b165e51dcfe16aa5150e940e62f42807a4eee09..77efcc6986e64e4c4ac00fbab69f3cff33097d93 100644
--- a/substrate/frame/contracts/src/lib.rs
+++ b/substrate/frame/contracts/src/lib.rs
@@ -386,7 +386,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId", T::Hash = "Hash", BalanceOf<T> = "Balance")]
 	pub enum Event<T: Config> {
 		/// Contract deployed by address at the specified address. \[deployer, contract\]
 		Instantiated(T::AccountId, T::AccountId),
diff --git a/substrate/frame/contracts/src/schedule.rs b/substrate/frame/contracts/src/schedule.rs
index 51aefa8bdaf6305fe91fa33c332846aaa878692e..c14165b4c6aec2176979e598fc3014e071c4f0e5 100644
--- a/substrate/frame/contracts/src/schedule.rs
+++ b/substrate/frame/contracts/src/schedule.rs
@@ -24,6 +24,7 @@ use codec::{Decode, Encode};
 use frame_support::{weights::Weight, DefaultNoBound};
 use pallet_contracts_proc_macro::{ScheduleDebug, WeightDebug};
 use pwasm_utils::{parity_wasm::elements, rules};
+use scale_info::TypeInfo;
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
 use sp_runtime::RuntimeDebug;
@@ -72,7 +73,8 @@ pub const INSTR_BENCHMARK_BATCH_SIZE: u32 = 100;
 /// changes are made to its values.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "std", serde(bound(serialize = "", deserialize = "")))]
-#[derive(Clone, Encode, Decode, PartialEq, Eq, ScheduleDebug, DefaultNoBound)]
+#[derive(Clone, Encode, Decode, PartialEq, Eq, ScheduleDebug, DefaultNoBound, TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct Schedule<T: Config> {
 	/// Describes the upper limits on various metrics.
 	pub limits: Limits,
@@ -92,7 +94,7 @@ pub struct Schedule<T: Config> {
 /// values will break existing contracts which are above the new limits when a
 /// re-instrumentation is triggered.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)]
+#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub struct Limits {
 	/// The maximum number of topics supported by an event.
 	pub event_topics: u32,
@@ -174,7 +176,8 @@ impl Limits {
 ///    that use them as supporting instructions. Supporting means mainly pushing arguments
 ///    and dropping return values in order to maintain a valid module.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Clone, Encode, Decode, PartialEq, Eq, WeightDebug)]
+#[derive(Clone, Encode, Decode, PartialEq, Eq, WeightDebug, TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct InstructionWeights<T: Config> {
 	/// Version of the instruction weights.
 	///
@@ -247,7 +250,8 @@ pub struct InstructionWeights<T: Config> {
 
 /// Describes the weight for each imported function that a contract is allowed to call.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Clone, Encode, Decode, PartialEq, Eq, WeightDebug)]
+#[derive(Clone, Encode, Decode, PartialEq, Eq, WeightDebug, TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct HostFnWeights<T: Config> {
 	/// Weight of calling `seal_caller`.
 	pub caller: Weight,
diff --git a/substrate/frame/contracts/src/storage.rs b/substrate/frame/contracts/src/storage.rs
index 510a1c95f9a31e71904d33b6b7f09550828116e0..41db0796717e484afbed4aebb5c1c4d560f5cee9 100644
--- a/substrate/frame/contracts/src/storage.rs
+++ b/substrate/frame/contracts/src/storage.rs
@@ -29,6 +29,7 @@ use frame_support::{
 	traits::Get,
 	weights::Weight,
 };
+use scale_info::TypeInfo;
 use sp_core::crypto::UncheckedFrom;
 use sp_io::hashing::blake2_256;
 use sp_runtime::{traits::Hash, RuntimeDebug};
@@ -38,7 +39,7 @@ pub type ContractInfo<T> = RawContractInfo<CodeHash<T>>;
 
 /// Information for managing an account and its sub trie abstraction.
 /// This is the required info to cache for an account.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub struct RawContractInfo<CodeHash> {
 	/// Unique ID for the subtree encoded as a bytes vector.
 	pub trie_id: TrieId,
@@ -61,7 +62,7 @@ fn child_trie_info(trie_id: &[u8]) -> ChildInfo {
 	ChildInfo::new_default(trie_id)
 }
 
-#[derive(Encode, Decode)]
+#[derive(Encode, Decode, TypeInfo)]
 pub struct DeletedContract {
 	pub(crate) trie_id: TrieId,
 }
diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs
index 28f05fd390d5d1b0119839070fc94c40a9d25bd4..f5b95c192c42eac74bef6e1d1c7e509961c23584 100644
--- a/substrate/frame/contracts/src/tests.rs
+++ b/substrate/frame/contracts/src/tests.rs
@@ -1781,7 +1781,12 @@ fn gas_estimation_call_runtime() {
 
 		// Call something trivial with a huge gas limit so that we can observe the effects
 		// of pre-charging. This should create a difference between consumed and required.
-		let call = Call::Contracts(crate::Call::call(addr_callee, 0, GAS_LIMIT / 3, vec![]));
+		let call = Call::Contracts(crate::Call::call {
+			dest: addr_callee,
+			value: 0,
+			gas_limit: GAS_LIMIT / 3,
+			data: vec![],
+		});
 		let result =
 			Contracts::bare_call(ALICE, addr_caller.clone(), 0, GAS_LIMIT, call.encode(), false);
 		assert_ok!(&result.result);
diff --git a/substrate/frame/contracts/src/wasm/mod.rs b/substrate/frame/contracts/src/wasm/mod.rs
index b92ed111e9881013793f07f63cd827b53fb65653..855cb6e45091ff416989fad142cc94f31a7c0c61 100644
--- a/substrate/frame/contracts/src/wasm/mod.rs
+++ b/substrate/frame/contracts/src/wasm/mod.rs
@@ -50,7 +50,8 @@ pub use tests::MockExt;
 /// `instruction_weights_version` and `code` when a contract with an outdated instrumention is
 /// called. Therefore one must be careful when holding any in-memory representation of this
 /// type while calling into a contract as those fields can get out of date.
-#[derive(Clone, Encode, Decode)]
+#[derive(Clone, Encode, Decode, scale_info::TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct PrefabWasmModule<T: Config> {
 	/// Version of the instruction weights with which the code was instrumented.
 	#[codec(compact)]
@@ -1967,7 +1968,7 @@ mod tests {
 	#[cfg(feature = "unstable-interface")]
 	fn call_runtime_works() {
 		use std::convert::TryInto;
-		let call = Call::System(frame_system::Call::remark(b"Hello World".to_vec()));
+		let call = Call::System(frame_system::Call::remark { remark: b"Hello World".to_vec() });
 		let mut ext = MockExt::default();
 		let result = execute(CODE_CALL_RUNTIME, call.encode(), &mut ext).unwrap();
 		assert_eq!(*ext.runtime_calls.borrow(), vec![call]);
diff --git a/substrate/frame/democracy/Cargo.toml b/substrate/frame/democracy/Cargo.toml
index 98b034c3ce7ee1b21bf085f036e44ad4ae6bec2b..94719553e28aa0957d1a6d43c4e4cfaa89f565fd 100644
--- a/substrate/frame/democracy/Cargo.toml
+++ b/substrate/frame/democracy/Cargo.toml
@@ -17,6 +17,7 @@ serde = { version = "1.0.126", optional = true, features = ["derive"] }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -34,6 +35,7 @@ default = ["std"]
 std = [
 	"serde",
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-io/std",
 	"frame-benchmarking/std",
diff --git a/substrate/frame/democracy/src/benchmarking.rs b/substrate/frame/democracy/src/benchmarking.rs
index 487a52571941063cb7637b87700ebe39f79230ff..7d4d7aee140b977a0e164b7cf25b6b3454869dfb 100644
--- a/substrate/frame/democracy/src/benchmarking.rs
+++ b/substrate/frame/democracy/src/benchmarking.rs
@@ -73,7 +73,7 @@ fn add_referendum<T: Config>(n: u32) -> Result<ReferendumIndex, &'static str> {
 		None,
 		63,
 		frame_system::RawOrigin::Root.into(),
-		Call::enact_proposal(proposal_hash, referendum_index).into(),
+		Call::enact_proposal { proposal_hash, index: referendum_index }.into(),
 	)
 	.map_err(|_| "failed to schedule named")?;
 	Ok(referendum_index)
@@ -194,7 +194,7 @@ benchmarks! {
 	emergency_cancel {
 		let origin = T::CancellationOrigin::successful_origin();
 		let referendum_index = add_referendum::<T>(0)?;
-		let call = Call::<T>::emergency_cancel(referendum_index);
+		let call = Call::<T>::emergency_cancel { ref_index: referendum_index };
 		assert_ok!(Democracy::<T>::referendum_status(referendum_index));
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
@@ -224,7 +224,7 @@ benchmarks! {
 		let referendum_index = add_referendum::<T>(0)?;
 		assert_ok!(Democracy::<T>::referendum_status(referendum_index));
 
-		let call = Call::<T>::blacklist(hash, Some(referendum_index));
+		let call = Call::<T>::blacklist { proposal_hash: hash, maybe_ref_index: Some(referendum_index) };
 		let origin = T::BlacklistOrigin::successful_origin();
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
@@ -247,7 +247,7 @@ benchmarks! {
 			(T::BlockNumber::zero(), vec![T::AccountId::default(); v as usize])
 		);
 
-		let call = Call::<T>::external_propose(proposal_hash);
+		let call = Call::<T>::external_propose { proposal_hash };
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
 		// External proposal created
@@ -257,7 +257,7 @@ benchmarks! {
 	external_propose_majority {
 		let origin = T::ExternalMajorityOrigin::successful_origin();
 		let proposal_hash = T::Hashing::hash_of(&0);
-		let call = Call::<T>::external_propose_majority(proposal_hash);
+		let call = Call::<T>::external_propose_majority { proposal_hash };
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
 		// External proposal created
@@ -267,7 +267,7 @@ benchmarks! {
 	external_propose_default {
 		let origin = T::ExternalDefaultOrigin::successful_origin();
 		let proposal_hash = T::Hashing::hash_of(&0);
-		let call = Call::<T>::external_propose_default(proposal_hash);
+		let call = Call::<T>::external_propose_default { proposal_hash };
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
 		// External proposal created
@@ -283,7 +283,11 @@ benchmarks! {
 		let origin_fast_track = T::FastTrackOrigin::successful_origin();
 		let voting_period = T::FastTrackVotingPeriod::get();
 		let delay = 0u32;
-		let call = Call::<T>::fast_track(proposal_hash, voting_period.into(), delay.into());
+		let call = Call::<T>::fast_track {
+			proposal_hash,
+			voting_period: voting_period.into(),
+			delay: delay.into()
+		};
 
 	}: { call.dispatch_bypass_filter(origin_fast_track)? }
 	verify {
@@ -306,7 +310,7 @@ benchmarks! {
 		vetoers.sort();
 		Blacklist::<T>::insert(proposal_hash, (T::BlockNumber::zero(), vetoers));
 
-		let call = Call::<T>::veto_external(proposal_hash);
+		let call = Call::<T>::veto_external { proposal_hash };
 		let origin = T::VetoOrigin::successful_origin();
 		ensure!(NextExternal::<T>::get().is_some(), "no external proposal");
 	}: { call.dispatch_bypass_filter(origin)? }
@@ -356,7 +360,7 @@ benchmarks! {
 
 		let origin = T::ExternalMajorityOrigin::successful_origin();
 		let proposal_hash = T::Hashing::hash_of(&r);
-		let call = Call::<T>::external_propose_majority(proposal_hash);
+		let call = Call::<T>::external_propose_majority { proposal_hash };
 		call.dispatch_bypass_filter(origin)?;
 		// External proposal created
 		ensure!(<NextExternal<T>>::exists(), "External proposal didn't work");
@@ -739,7 +743,7 @@ benchmarks! {
 		let b in 0 .. MAX_BYTES;
 
 		let proposer = funded_account::<T>("proposer", 0);
-		let raw_call = Call::note_preimage(vec![1; b as usize]);
+		let raw_call = Call::note_preimage { encoded_proposal: vec![1; b as usize] };
 		let generic_call: T::Proposal = raw_call.into();
 		let encoded_proposal = generic_call.encode();
 		let proposal_hash = T::Hashing::hash(&encoded_proposal[..]);
diff --git a/substrate/frame/democracy/src/conviction.rs b/substrate/frame/democracy/src/conviction.rs
index 6b77acfab5b003f8eb129c2c2794c8e4e769f9c7..b4f24c93bb40fd5a1fb4c5a1d2f1cd19839aff6f 100644
--- a/substrate/frame/democracy/src/conviction.rs
+++ b/substrate/frame/democracy/src/conviction.rs
@@ -19,6 +19,7 @@
 
 use crate::types::Delegations;
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{Bounded, CheckedDiv, CheckedMul, Zero},
 	RuntimeDebug,
@@ -26,7 +27,7 @@ use sp_runtime::{
 use sp_std::{convert::TryFrom, result::Result};
 
 /// A value denoting the strength of conviction of a vote.
-#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug)]
+#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug, TypeInfo)]
 pub enum Conviction {
 	/// 0.1x votes, unlocked.
 	None,
diff --git a/substrate/frame/democracy/src/lib.rs b/substrate/frame/democracy/src/lib.rs
index 473ac964692cf2b0196fa01c40b3d5a7b846a0f7..8bc6921c4f8ad80fac2690e5a1cf5e0e73a60040 100644
--- a/substrate/frame/democracy/src/lib.rs
+++ b/substrate/frame/democracy/src/lib.rs
@@ -162,6 +162,7 @@ use frame_support::{
 	},
 	weights::Weight,
 };
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{Bounded, Dispatchable, Hash, Saturating, Zero},
 	ArithmeticError, DispatchError, DispatchResult, RuntimeDebug,
@@ -205,7 +206,7 @@ type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<
 	<T as frame_system::Config>::AccountId,
 >>::NegativeImbalance;
 
-#[derive(Clone, Encode, Decode, RuntimeDebug)]
+#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
 pub enum PreimageStatus<AccountId, Balance, BlockNumber> {
 	/// The preimage is imminently needed at the argument.
 	Missing(BlockNumber),
@@ -232,7 +233,7 @@ impl<AccountId, Balance, BlockNumber> PreimageStatus<AccountId, Balance, BlockNu
 // A value placed in storage that represents the current version of the Democracy storage.
 // This value is used by the `on_runtime_upgrade` logic to determine whether we run
 // storage migration logic.
-#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 enum Releases {
 	V1,
 }
@@ -505,13 +506,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(
-		T::AccountId = "AccountId",
-		Vec<T::AccountId> = "Vec<AccountId>",
-		BalanceOf<T> = "Balance",
-		T::BlockNumber = "BlockNumber",
-		T::Hash = "Hash",
-	)]
 	pub enum Event<T: Config> {
 		/// A motion has been proposed by a public account. \[proposal_index, deposit\]
 		Proposed(PropIndex, BalanceOf<T>),
@@ -1714,7 +1708,7 @@ impl<T: Config> Pallet<T> {
 					None,
 					63,
 					frame_system::RawOrigin::Root.into(),
-					Call::enact_proposal(status.proposal_hash, index).into(),
+					Call::enact_proposal { proposal_hash: status.proposal_hash, index }.into(),
 				)
 				.is_err()
 				{
diff --git a/substrate/frame/democracy/src/tests.rs b/substrate/frame/democracy/src/tests.rs
index 9a5e47c89ac7777a25e1e9e076423d17c65e420f..75104db51b971e73bd67bc23b3d67d382bab9ac2 100644
--- a/substrate/frame/democracy/src/tests.rs
+++ b/substrate/frame/democracy/src/tests.rs
@@ -72,7 +72,7 @@ frame_support::construct_runtime!(
 pub struct BaseFilter;
 impl Contains<Call> for BaseFilter {
 	fn contains(call: &Call) -> bool {
-		!matches!(call, &Call::Balances(pallet_balances::Call::set_balance(..)))
+		!matches!(call, &Call::Balances(pallet_balances::Call::set_balance { .. }))
 	}
 }
 
@@ -226,7 +226,8 @@ fn params_should_work() {
 }
 
 fn set_balance_proposal(value: u64) -> Vec<u8> {
-	Call::Balances(pallet_balances::Call::set_balance(42, value, 0)).encode()
+	Call::Balances(pallet_balances::Call::set_balance { who: 42, new_free: value, new_reserved: 0 })
+		.encode()
 }
 
 #[test]
diff --git a/substrate/frame/democracy/src/types.rs b/substrate/frame/democracy/src/types.rs
index 5c4002a46dd387d568ade7d519361ccd41d042dc..2eb004ba61bc4064be49b1c3523dd35005989da9 100644
--- a/substrate/frame/democracy/src/types.rs
+++ b/substrate/frame/democracy/src/types.rs
@@ -19,13 +19,14 @@
 
 use crate::{AccountVote, Conviction, Vote, VoteThreshold};
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Saturating, Zero},
 	RuntimeDebug,
 };
 
 /// Info regarding an ongoing referendum.
-#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub struct Tally<Balance> {
 	/// The number of aye votes, expressed in terms of post-conviction lock-vote.
 	pub ayes: Balance,
@@ -36,7 +37,7 @@ pub struct Tally<Balance> {
 }
 
 /// Amount of votes and capital placed in delegation for an account.
-#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub struct Delegations<Balance> {
 	/// The number of votes (this is post-conviction).
 	pub votes: Balance,
@@ -159,7 +160,7 @@ impl<
 }
 
 /// Info regarding an ongoing referendum.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub struct ReferendumStatus<BlockNumber, Hash, Balance> {
 	/// When voting on this referendum will end.
 	pub end: BlockNumber,
@@ -174,7 +175,7 @@ pub struct ReferendumStatus<BlockNumber, Hash, Balance> {
 }
 
 /// Info regarding a referendum, present or past.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub enum ReferendumInfo<BlockNumber, Hash, Balance> {
 	/// Referendum is happening, the arg is the block number at which it will end.
 	Ongoing(ReferendumStatus<BlockNumber, Hash, Balance>),
diff --git a/substrate/frame/democracy/src/vote.rs b/substrate/frame/democracy/src/vote.rs
index 7b1b32ea37f5825ef742b60c2f78c1b9a5908309..03ca020ca0949ba2061687565bfccc2b3c5efee9 100644
--- a/substrate/frame/democracy/src/vote.rs
+++ b/substrate/frame/democracy/src/vote.rs
@@ -19,6 +19,7 @@
 
 use crate::{Conviction, Delegations, ReferendumIndex};
 use codec::{Decode, Encode, EncodeLike, Input, Output};
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{Saturating, Zero},
 	RuntimeDebug,
@@ -51,8 +52,21 @@ impl Decode for Vote {
 	}
 }
 
+impl TypeInfo for Vote {
+	type Identity = Self;
+
+	fn type_info() -> scale_info::Type {
+		scale_info::Type::builder()
+			.path(scale_info::Path::new("Vote", module_path!()))
+			.composite(
+				scale_info::build::Fields::unnamed()
+					.field(|f| f.ty::<u8>().docs(&["Raw vote byte, encodes aye + conviction"])),
+			)
+	}
+}
+
 /// A vote for a referendum of a particular account.
-#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, RuntimeDebug)]
+#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo)]
 pub enum AccountVote<Balance> {
 	/// A standard vote, one-way (approve or reject) with a given amount of conviction.
 	Standard { vote: Vote, balance: Balance },
@@ -92,7 +106,9 @@ impl<Balance: Saturating> AccountVote<Balance> {
 }
 
 /// A "prior" lock, i.e. a lock for some now-forgotten reason.
-#[derive(Encode, Decode, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug)]
+#[derive(
+	Encode, Decode, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug, TypeInfo,
+)]
 pub struct PriorLock<BlockNumber, Balance>(BlockNumber, Balance);
 
 impl<BlockNumber: Ord + Copy + Zero, Balance: Ord + Copy + Zero> PriorLock<BlockNumber, Balance> {
@@ -115,7 +131,7 @@ impl<BlockNumber: Ord + Copy + Zero, Balance: Ord + Copy + Zero> PriorLock<Block
 }
 
 /// An indicator for what an account is doing; it can either be delegating or voting.
-#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo)]
 pub enum Voting<Balance, AccountId, BlockNumber> {
 	/// The account is voting directly. `delegations` is the total amount of post-conviction voting
 	/// weight that it controls from those that have delegated to it.
diff --git a/substrate/frame/democracy/src/vote_threshold.rs b/substrate/frame/democracy/src/vote_threshold.rs
index feaa596921c41142a80adb4a5c4376c510075a99..ad8bce290ed4f360146582cd45049cfdd8d19f87 100644
--- a/substrate/frame/democracy/src/vote_threshold.rs
+++ b/substrate/frame/democracy/src/vote_threshold.rs
@@ -19,13 +19,14 @@
 
 use crate::Tally;
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
 use sp_runtime::traits::{IntegerSquareRoot, Zero};
 use sp_std::ops::{Add, Div, Mul, Rem};
 
 /// A means of determining if a vote is past pass threshold.
-#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, sp_runtime::RuntimeDebug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, sp_runtime::RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub enum VoteThreshold {
 	/// A supermajority of approvals is needed to pass this vote.
diff --git a/substrate/frame/election-provider-multi-phase/Cargo.toml b/substrate/frame/election-provider-multi-phase/Cargo.toml
index 2dca7ed0a4f96adb22bf8a2c864ef2c8bc5a1ec4..b2d50321e8cd33e48b7306ff179b76a7db89b09c 100644
--- a/substrate/frame/election-provider-multi-phase/Cargo.toml
+++ b/substrate/frame/election-provider-multi-phase/Cargo.toml
@@ -17,6 +17,7 @@ static_assertions = "1.1.0"
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 log = { version = "0.4.14", default-features = false }
 
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
@@ -55,6 +56,7 @@ frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"log/std",
 
 	"frame-support/std",
diff --git a/substrate/frame/election-provider-multi-phase/src/benchmarking.rs b/substrate/frame/election-provider-multi-phase/src/benchmarking.rs
index bca9c359d47f7db927fd9787050c46331a9ad06b..fb5adda52e166bcb79711b20843b7c01a52b079d 100644
--- a/substrate/frame/election-provider-multi-phase/src/benchmarking.rs
+++ b/substrate/frame/election-provider-multi-phase/src/benchmarking.rs
@@ -353,7 +353,10 @@ frame_benchmarking::benchmarks! {
 
 		// encode the most significant storage item that needs to be decoded in the dispatch.
 		let encoded_snapshot = <MultiPhase<T>>::snapshot().ok_or("missing snapshot")?.encode();
-		let encoded_call = <Call<T>>::submit_unsigned(Box::new(raw_solution.clone()), witness).encode();
+		let encoded_call = Call::<T>::submit_unsigned {
+			raw_solution: Box::new(raw_solution.clone()),
+			witness
+		}.encode();
 	}: {
 		assert_ok!(
 			<MultiPhase<T>>::submit_unsigned(
diff --git a/substrate/frame/election-provider-multi-phase/src/lib.rs b/substrate/frame/election-provider-multi-phase/src/lib.rs
index a3b6083914ca516e3c9226a097b7e16c2a762eba..269057b55b09419a0f46bc3eb2ab190f344d7d9d 100644
--- a/substrate/frame/election-provider-multi-phase/src/lib.rs
+++ b/substrate/frame/election-provider-multi-phase/src/lib.rs
@@ -217,6 +217,7 @@ use frame_support::{
 	weights::{DispatchClass, Weight},
 };
 use frame_system::{ensure_none, offchain::SendTransactionTypes};
+use scale_info::TypeInfo;
 use sp_arithmetic::{
 	traits::{CheckedAdd, Saturating, Zero},
 	UpperOf,
@@ -311,7 +312,7 @@ impl<T: Config> ElectionProvider<T::AccountId, T::BlockNumber> for NoFallback<T>
 }
 
 /// Current phase of the pallet.
-#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug)]
+#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo)]
 pub enum Phase<Bn> {
 	/// Nothing, the election is not happening.
 	Off,
@@ -373,7 +374,7 @@ impl<Bn: PartialEq + Eq> Phase<Bn> {
 }
 
 /// The type of `Computation` that provided this election data.
-#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug)]
+#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo)]
 pub enum ElectionCompute {
 	/// Election was computed on-chain.
 	OnChain,
@@ -399,7 +400,7 @@ impl Default for ElectionCompute {
 ///
 /// Such a solution should never become effective in anyway before being checked by the
 /// `Pallet::feasibility_check`.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, PartialOrd, Ord)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, PartialOrd, Ord, TypeInfo)]
 pub struct RawSolution<S> {
 	/// the solution itself.
 	pub solution: S,
@@ -417,7 +418,7 @@ impl<C: Default> Default for RawSolution<C> {
 }
 
 /// A checked solution, ready to be enacted.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default, TypeInfo)]
 pub struct ReadySolution<A> {
 	/// The final supports of the solution.
 	///
@@ -436,7 +437,7 @@ pub struct ReadySolution<A> {
 /// [`ElectionDataProvider`] and are kept around until the round is finished.
 ///
 /// These are stored together because they are often accessed together.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default, TypeInfo)]
 pub struct RoundSnapshot<A> {
 	/// All of the voters.
 	pub voters: Vec<(A, VoteWeight, Vec<A>)>,
@@ -449,7 +450,7 @@ pub struct RoundSnapshot<A> {
 /// This is stored automatically on-chain, and it contains the **size of the entire snapshot**.
 /// This is also used in dispatchables as weight witness data and should **only contain the size of
 /// the presented solution**, not the entire snapshot.
-#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug, Default)]
+#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug, Default, TypeInfo)]
 pub struct SolutionOrSnapshotSize {
 	/// The length of voters.
 	#[codec(compact)]
@@ -643,7 +644,8 @@ pub mod pallet {
 			+ Clone
 			+ sp_std::fmt::Debug
 			+ Ord
-			+ NposSolution;
+			+ NposSolution
+			+ TypeInfo;
 
 		/// Configuration for the fallback
 		type Fallback: ElectionProvider<
@@ -949,7 +951,8 @@ pub mod pallet {
 			// create the submission
 			let deposit = Self::deposit_for(&raw_solution, size);
 			let reward = {
-				let call = Call::submit(raw_solution.clone(), num_signed_submissions);
+				let call =
+					Call::submit { raw_solution: raw_solution.clone(), num_signed_submissions };
 				let call_fee = T::EstimateCallFee::estimate_call_fee(&call, None.into());
 				T::SignedRewardBase::get().saturating_add(call_fee)
 			};
@@ -985,10 +988,6 @@ pub mod pallet {
 	}
 
 	#[pallet::event]
-	#[pallet::metadata(
-		<T as frame_system::Config>::AccountId = "AccountId",
-		BalanceOf<T> = "Balance"
-	)]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
 		/// A solution was stored with the given compute.
@@ -1042,14 +1041,14 @@ pub mod pallet {
 	impl<T: Config> ValidateUnsigned for Pallet<T> {
 		type Call = Call<T>;
 		fn validate_unsigned(source: TransactionSource, call: &Self::Call) -> TransactionValidity {
-			if let Call::submit_unsigned(solution, _) = call {
+			if let Call::submit_unsigned { raw_solution, .. } = call {
 				// Discard solution not coming from the local OCW.
 				match source {
 					TransactionSource::Local | TransactionSource::InBlock => { /* allowed */ },
 					_ => return InvalidTransaction::Call.into(),
 				}
 
-				let _ = Self::unsigned_pre_dispatch_checks(solution)
+				let _ = Self::unsigned_pre_dispatch_checks(raw_solution)
 					.map_err(|err| {
 						log!(debug, "unsigned transaction validation failed due to {:?}", err);
 						err
@@ -1060,11 +1059,11 @@ pub mod pallet {
 					// The higher the score[0], the better a solution is.
 					.priority(
 						T::MinerTxPriority::get()
-							.saturating_add(solution.score[0].saturated_into()),
+							.saturating_add(raw_solution.score[0].saturated_into()),
 					)
 					// Used to deduplicate unsigned solutions: each validator should produce one
 					// solution per round at most, and solutions are not propagate.
-					.and_provides(solution.round)
+					.and_provides(raw_solution.round)
 					// Transaction should stay in the pool for the duration of the unsigned phase.
 					.longevity(T::UnsignedPhase::get().saturated_into::<u64>())
 					// We don't propagate this. This can never be validated at a remote node.
@@ -1076,8 +1075,8 @@ pub mod pallet {
 		}
 
 		fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> {
-			if let Call::submit_unsigned(solution, _) = call {
-				Self::unsigned_pre_dispatch_checks(solution)
+			if let Call::submit_unsigned { raw_solution, .. } = call {
+				Self::unsigned_pre_dispatch_checks(raw_solution)
 					.map_err(dispatch_error_to_invalid)
 					.map_err(Into::into)
 			} else {
diff --git a/substrate/frame/election-provider-multi-phase/src/signed.rs b/substrate/frame/election-provider-multi-phase/src/signed.rs
index 72aa3e668034341cc780aadb483f99599a360e14..61215059c53a6e9cb150d5c517aefa4524be0ca8 100644
--- a/substrate/frame/election-provider-multi-phase/src/signed.rs
+++ b/substrate/frame/election-provider-multi-phase/src/signed.rs
@@ -42,7 +42,7 @@ use sp_std::{
 /// A raw, unchecked signed submission.
 ///
 /// This is just a wrapper around [`RawSolution`] and some additional info.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default, scale_info::TypeInfo)]
 pub struct SignedSubmission<AccountId, Balance: HasCompact, Solution> {
 	/// Who submitted this solution.
 	pub who: AccountId,
diff --git a/substrate/frame/election-provider-multi-phase/src/unsigned.rs b/substrate/frame/election-provider-multi-phase/src/unsigned.rs
index 0afb6eee16121a663ac8cb1f34a0cf1a44b7f15d..af0b79177d86c453ac2058a123e80bb9adbf0206 100644
--- a/substrate/frame/election-provider-multi-phase/src/unsigned.rs
+++ b/substrate/frame/election-provider-multi-phase/src/unsigned.rs
@@ -160,9 +160,9 @@ impl<T: Config> Pallet<T> {
 		let call = restore_solution::<T>()
 			.and_then(|call| {
 				// ensure the cached call is still current before submitting
-				if let Call::submit_unsigned(solution, _) = &call {
+				if let Call::submit_unsigned { raw_solution, .. } = &call {
 					// prevent errors arising from state changes in a forkful chain
-					Self::basic_checks(solution, "restored")?;
+					Self::basic_checks(raw_solution, "restored")?;
 					Ok(call)
 				} else {
 					Err(MinerError::SolutionCallInvalid)
@@ -213,7 +213,8 @@ impl<T: Config> Pallet<T> {
 		let (raw_solution, witness) = Self::mine_and_check()?;
 
 		let score = raw_solution.score.clone();
-		let call: Call<T> = Call::submit_unsigned(Box::new(raw_solution), witness).into();
+		let call: Call<T> =
+			Call::submit_unsigned { raw_solution: Box::new(raw_solution), witness }.into();
 
 		log!(
 			debug,
@@ -763,7 +764,10 @@ mod tests {
 		ExtBuilder::default().desired_targets(0).build_and_execute(|| {
 			let solution =
 				RawSolution::<TestNposSolution> { score: [5, 0, 0], ..Default::default() };
-			let call = Call::submit_unsigned(Box::new(solution.clone()), witness());
+			let call = Call::submit_unsigned {
+				raw_solution: Box::new(solution.clone()),
+				witness: witness(),
+			};
 
 			// initial
 			assert_eq!(MultiPhase::current_phase(), Phase::Off);
@@ -833,7 +837,10 @@ mod tests {
 
 			let solution =
 				RawSolution::<TestNposSolution> { score: [5, 0, 0], ..Default::default() };
-			let call = Call::submit_unsigned(Box::new(solution.clone()), witness());
+			let call = Call::submit_unsigned {
+				raw_solution: Box::new(solution.clone()),
+				witness: witness(),
+			};
 
 			// initial
 			assert!(<MultiPhase as ValidateUnsigned>::validate_unsigned(
@@ -870,7 +877,8 @@ mod tests {
 			assert!(MultiPhase::current_phase().is_unsigned());
 
 			let raw = RawSolution::<TestNposSolution> { score: [5, 0, 0], ..Default::default() };
-			let call = Call::submit_unsigned(Box::new(raw.clone()), witness());
+			let call =
+				Call::submit_unsigned { raw_solution: Box::new(raw.clone()), witness: witness() };
 			assert_eq!(raw.solution.unique_targets().len(), 0);
 
 			// won't work anymore.
@@ -896,7 +904,10 @@ mod tests {
 
 				let solution =
 					RawSolution::<TestNposSolution> { score: [5, 0, 0], ..Default::default() };
-				let call = Call::submit_unsigned(Box::new(solution.clone()), witness());
+				let call = Call::submit_unsigned {
+					raw_solution: Box::new(solution.clone()),
+					witness: witness(),
+				};
 
 				assert_eq!(
 					<MultiPhase as ValidateUnsigned>::validate_unsigned(
@@ -923,7 +934,10 @@ mod tests {
 			// This is in itself an invalid BS solution.
 			let solution =
 				RawSolution::<TestNposSolution> { score: [5, 0, 0], ..Default::default() };
-			let call = Call::submit_unsigned(Box::new(solution.clone()), witness());
+			let call = Call::submit_unsigned {
+				raw_solution: Box::new(solution.clone()),
+				witness: witness(),
+			};
 			let outer_call: OuterCall = call.into();
 			let _ = outer_call.dispatch(Origin::none());
 		})
@@ -944,7 +958,10 @@ mod tests {
 			let mut correct_witness = witness();
 			correct_witness.voters += 1;
 			correct_witness.targets -= 1;
-			let call = Call::submit_unsigned(Box::new(solution.clone()), correct_witness);
+			let call = Call::submit_unsigned {
+				raw_solution: Box::new(solution.clone()),
+				witness: correct_witness,
+			};
 			let outer_call: OuterCall = call.into();
 			let _ = outer_call.dispatch(Origin::none());
 		})
@@ -1350,7 +1367,7 @@ mod tests {
 			let encoded = pool.read().transactions[0].clone();
 			let extrinsic: Extrinsic = codec::Decode::decode(&mut &*encoded).unwrap();
 			let call = extrinsic.call;
-			assert!(matches!(call, OuterCall::MultiPhase(Call::submit_unsigned(..))));
+			assert!(matches!(call, OuterCall::MultiPhase(Call::submit_unsigned { .. })));
 		})
 	}
 
@@ -1367,7 +1384,7 @@ mod tests {
 			let encoded = pool.read().transactions[0].clone();
 			let extrinsic = Extrinsic::decode(&mut &*encoded).unwrap();
 			let call = match extrinsic.call {
-				OuterCall::MultiPhase(call @ Call::submit_unsigned(..)) => call,
+				OuterCall::MultiPhase(call @ Call::submit_unsigned { .. }) => call,
 				_ => panic!("bad call: unexpected submission"),
 			};
 
diff --git a/substrate/frame/election-provider-support/Cargo.toml b/substrate/frame/election-provider-support/Cargo.toml
index d713b98fcefa195617e9211602ab04fc95be5814..dfe2b1102433497e84e950095de09686e3c955af 100644
--- a/substrate/frame/election-provider-support/Cargo.toml
+++ b/substrate/frame/election-provider-support/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" }
 sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" }
diff --git a/substrate/frame/elections-phragmen/Cargo.toml b/substrate/frame/elections-phragmen/Cargo.toml
index 930c9c2c80832c597eac77c2e3342fab827e17a1..f2771a9f72783a3aa29d9b2afdd48f5a587fda58 100644
--- a/substrate/frame/elections-phragmen/Cargo.toml
+++ b/substrate/frame/elections-phragmen/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
 sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../primitives/npos-elections" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
@@ -35,6 +36,7 @@ substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"frame-support/std",
 	"sp-runtime/std",
 	"sp-npos-elections/std",
diff --git a/substrate/frame/elections-phragmen/src/lib.rs b/substrate/frame/elections-phragmen/src/lib.rs
index 8e0a31377f982974142cbb7c84c2ab7046955279..d7b42383da7570ca2e9a11130dfcb7ae29187af3 100644
--- a/substrate/frame/elections-phragmen/src/lib.rs
+++ b/substrate/frame/elections-phragmen/src/lib.rs
@@ -108,6 +108,7 @@ use frame_support::{
 	},
 	weights::Weight,
 };
+use scale_info::TypeInfo;
 use sp_npos_elections::{ElectionResult, ExtendedBalance};
 use sp_runtime::{
 	traits::{Saturating, StaticLookup, Zero},
@@ -135,7 +136,7 @@ type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<
 >>::NegativeImbalance;
 
 /// An indication that the renouncing account currently has which of the below roles.
-#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)]
 pub enum Renouncing {
 	/// A member is renouncing.
 	Member,
@@ -146,7 +147,7 @@ pub enum Renouncing {
 }
 
 /// An active voter.
-#[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq)]
+#[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq, TypeInfo)]
 pub struct Voter<AccountId, Balance> {
 	/// The members being backed.
 	pub votes: Vec<AccountId>,
@@ -159,7 +160,7 @@ pub struct Voter<AccountId, Balance> {
 }
 
 /// A holder of a seat as either a member or a runner-up.
-#[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq)]
+#[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq, TypeInfo)]
 pub struct SeatHolder<AccountId, Balance> {
 	/// The holder.
 	pub who: AccountId,
@@ -531,11 +532,6 @@ pub mod pallet {
 	}
 
 	#[pallet::event]
-	#[pallet::metadata(
-		<T as frame_system::Config>::AccountId = "AccountId",
-		BalanceOf<T> = "Balance",
-		Vec<(<T as frame_system::Config>::AccountId, BalanceOf<T>)> = "Vec<(AccountId, Balance)>",
-	)]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
 		/// A new term with \[new_members\]. This indicates that enough candidates existed to run
diff --git a/substrate/frame/elections/Cargo.toml b/substrate/frame/elections/Cargo.toml
index 29bc8f8a5cea499345776a02cca735019a75935d..8557cfba6b58cf097699dbd9bbef29b82e92fc7b 100644
--- a/substrate/frame/elections/Cargo.toml
+++ b/substrate/frame/elections/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
@@ -30,6 +31,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-core/std",
 	"sp-std/std",
 	"sp-io/std",
diff --git a/substrate/frame/elections/src/lib.rs b/substrate/frame/elections/src/lib.rs
index 5057a6e00f56522cb555bdd7fd31d14cf389cd96..ac13bce31b0f6f56fc4d7fd2b458996ab360fdf1 100644
--- a/substrate/frame/elections/src/lib.rs
+++ b/substrate/frame/elections/src/lib.rs
@@ -111,7 +111,9 @@ mod tests;
 // entries before they increase the capacity.
 
 /// The activity status of a voter.
-#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, Default, RuntimeDebug)]
+#[derive(
+	PartialEq, Eq, Copy, Clone, Encode, Decode, Default, RuntimeDebug, scale_info::TypeInfo,
+)]
 pub struct VoterInfo<Balance> {
 	/// Last VoteIndex in which this voter assigned (or initialized) approvals.
 	last_active: VoteIndex,
@@ -462,7 +464,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId", Vec<T::AccountId> = "Vec<AccountId>")]
 	pub enum Event<T: Config> {
 		/// Reaped \[voter, reaper\].
 		VoterReaped(T::AccountId, T::AccountId),
diff --git a/substrate/frame/example-offchain-worker/Cargo.toml b/substrate/frame/example-offchain-worker/Cargo.toml
index 69a5621748622dd2508db920e90b7269f8492c1e..1ccd9f33f0318718bc6e0334897a0fe2d6c98d47 100644
--- a/substrate/frame/example-offchain-worker/Cargo.toml
+++ b/substrate/frame/example-offchain-worker/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
@@ -28,6 +29,7 @@ log = { version = "0.4.14", default-features = false }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"frame-support/std",
 	"frame-system/std",
 	"lite-json/std",
diff --git a/substrate/frame/example-offchain-worker/src/lib.rs b/substrate/frame/example-offchain-worker/src/lib.rs
index 9e043c8bfb25077bf23f1b16c9e952ad5c245a40..644e1ca299a3c6fd6a53285454ae01bdb9787273 100644
--- a/substrate/frame/example-offchain-worker/src/lib.rs
+++ b/substrate/frame/example-offchain-worker/src/lib.rs
@@ -294,8 +294,10 @@ pub mod pallet {
 		/// are being whitelisted and marked as valid.
 		fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
 			// Firstly let's check that we call the right function.
-			if let Call::submit_price_unsigned_with_signed_payload(ref payload, ref signature) =
-				call
+			if let Call::submit_price_unsigned_with_signed_payload {
+				price_payload: ref payload,
+				ref signature,
+			} = call
 			{
 				let signature_valid =
 					SignedPayload::<T>::verify::<T::AuthorityId>(payload, signature.clone());
@@ -303,7 +305,7 @@ pub mod pallet {
 					return InvalidTransaction::BadProof.into()
 				}
 				Self::validate_transaction_parameters(&payload.block_number, &payload.price)
-			} else if let Call::submit_price_unsigned(block_number, new_price) = call {
+			} else if let Call::submit_price_unsigned { block_number, price: new_price } = call {
 				Self::validate_transaction_parameters(block_number, new_price)
 			} else {
 				InvalidTransaction::Call.into()
@@ -330,7 +332,7 @@ pub mod pallet {
 
 /// Payload used by this example crate to hold price
 /// data required to submit a transaction.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, scale_info::TypeInfo)]
 pub struct PricePayload<Public, BlockNumber> {
 	block_number: BlockNumber,
 	price: u32,
@@ -443,7 +445,7 @@ impl<T: Config> Pallet<T> {
 			// Received price is wrapped into a call to `submit_price` public function of this
 			// pallet. This means that the transaction, when executed, will simply call that
 			// function passing `price` as an argument.
-			Call::submit_price(price)
+			Call::submit_price { price }
 		});
 
 		for (acc, res) in &results {
@@ -472,7 +474,7 @@ impl<T: Config> Pallet<T> {
 		// Received price is wrapped into a call to `submit_price_unsigned` public function of this
 		// pallet. This means that the transaction, when executed, will simply call that function
 		// passing `price` as an argument.
-		let call = Call::submit_price_unsigned(block_number, price);
+		let call = Call::submit_price_unsigned { block_number, price };
 
 		// Now let's create a transaction out of this call and submit it to the pool.
 		// Here we showcase two ways to send an unsigned transaction / unsigned payload (raw)
@@ -507,8 +509,9 @@ impl<T: Config> Pallet<T> {
 		let (_, result) = Signer::<T, T::AuthorityId>::any_account()
 			.send_unsigned_transaction(
 				|account| PricePayload { price, block_number, public: account.public.clone() },
-				|payload, signature| {
-					Call::submit_price_unsigned_with_signed_payload(payload, signature)
+				|payload, signature| Call::submit_price_unsigned_with_signed_payload {
+					price_payload: payload,
+					signature,
 				},
 			)
 			.ok_or("No local accounts accounts available.")?;
@@ -536,8 +539,9 @@ impl<T: Config> Pallet<T> {
 		let transaction_results = Signer::<T, T::AuthorityId>::all_accounts()
 			.send_unsigned_transaction(
 				|account| PricePayload { price, block_number, public: account.public.clone() },
-				|payload, signature| {
-					Call::submit_price_unsigned_with_signed_payload(payload, signature)
+				|payload, signature| Call::submit_price_unsigned_with_signed_payload {
+					price_payload: payload,
+					signature,
 				},
 			);
 		for (_account_id, result) in transaction_results.into_iter() {
diff --git a/substrate/frame/example-offchain-worker/src/tests.rs b/substrate/frame/example-offchain-worker/src/tests.rs
index d0a3664abf4acfb7559346a52137cb38089fbf66..1dde8a1df60c8eb228c5d2a443acbd4a099860a9 100644
--- a/substrate/frame/example-offchain-worker/src/tests.rs
+++ b/substrate/frame/example-offchain-worker/src/tests.rs
@@ -227,7 +227,7 @@ fn should_submit_signed_transaction_on_chain() {
 		assert!(pool_state.read().transactions.is_empty());
 		let tx = Extrinsic::decode(&mut &*tx).unwrap();
 		assert_eq!(tx.signature.unwrap().0, 0);
-		assert_eq!(tx.call, Call::Example(crate::Call::submit_price(15523)));
+		assert_eq!(tx.call, Call::Example(crate::Call::submit_price { price: 15523 }));
 	});
 }
 
@@ -273,10 +273,10 @@ fn should_submit_unsigned_transaction_on_chain_for_any_account() {
 		let tx = pool_state.write().transactions.pop().unwrap();
 		let tx = Extrinsic::decode(&mut &*tx).unwrap();
 		assert_eq!(tx.signature, None);
-		if let Call::Example(crate::Call::submit_price_unsigned_with_signed_payload(
-			body,
+		if let Call::Example(crate::Call::submit_price_unsigned_with_signed_payload {
+			price_payload: body,
 			signature,
-		)) = tx.call
+		}) = tx.call
 		{
 			assert_eq!(body, price_payload);
 
@@ -333,10 +333,10 @@ fn should_submit_unsigned_transaction_on_chain_for_all_accounts() {
 		let tx = pool_state.write().transactions.pop().unwrap();
 		let tx = Extrinsic::decode(&mut &*tx).unwrap();
 		assert_eq!(tx.signature, None);
-		if let Call::Example(crate::Call::submit_price_unsigned_with_signed_payload(
-			body,
+		if let Call::Example(crate::Call::submit_price_unsigned_with_signed_payload {
+			price_payload: body,
 			signature,
-		)) = tx.call
+		}) = tx.call
 		{
 			assert_eq!(body, price_payload);
 
@@ -373,7 +373,10 @@ fn should_submit_raw_unsigned_transaction_on_chain() {
 		assert!(pool_state.read().transactions.is_empty());
 		let tx = Extrinsic::decode(&mut &*tx).unwrap();
 		assert_eq!(tx.signature, None);
-		assert_eq!(tx.call, Call::Example(crate::Call::submit_price_unsigned(1, 15523)));
+		assert_eq!(
+			tx.call,
+			Call::Example(crate::Call::submit_price_unsigned { block_number: 1, price: 15523 })
+		);
 	});
 }
 
diff --git a/substrate/frame/example-parallel/Cargo.toml b/substrate/frame/example-parallel/Cargo.toml
index 4d14d635201fffb1a1cbb422b7fc3ec5b5b9ab43..5e0f6d4bc255a3cbba17ceefb21f2275f3861e1f 100644
--- a/substrate/frame/example-parallel/Cargo.toml
+++ b/substrate/frame/example-parallel/Cargo.toml
@@ -13,6 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
@@ -25,6 +26,7 @@ sp-tasks = { version = "4.0.0-dev", default-features = false, path = "../../prim
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"frame-support/std",
 	"frame-system/std",
 	"sp-core/std",
diff --git a/substrate/frame/example-parallel/src/lib.rs b/substrate/frame/example-parallel/src/lib.rs
index c41cd2401dd257340bb91114417c5d01be9af680..c86cac4295684048e7ca4db74dc47d6d793d73a2 100644
--- a/substrate/frame/example-parallel/src/lib.rs
+++ b/substrate/frame/example-parallel/src/lib.rs
@@ -95,7 +95,7 @@ pub mod pallet {
 }
 
 /// Request to enlist participant.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, scale_info::TypeInfo)]
 pub struct EnlistedParticipant {
 	pub account: Vec<u8>,
 	pub signature: Vec<u8>,
diff --git a/substrate/frame/example/Cargo.toml b/substrate/frame/example/Cargo.toml
index 08d7af4ef673fd45ab76aaf1370f418e7ee8aa63..58daaf1c755589808bdf8d7161a6f406aafd4fc0 100644
--- a/substrate/frame/example/Cargo.toml
+++ b/substrate/frame/example/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
 pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" }
@@ -35,6 +36,7 @@ std = [
 	"frame-system/std",
 	"log/std",
 	"pallet-balances/std",
+	"scale-info/std",
 	"sp-io/std",
 	"sp-runtime/std",
 	"sp-std/std"
diff --git a/substrate/frame/example/src/lib.rs b/substrate/frame/example/src/lib.rs
index f588e11a6164d6b376e250e5f1dc31a88448f804..3f56b57dac8ca21a02794408a6bc9a823fd6f61e 100644
--- a/substrate/frame/example/src/lib.rs
+++ b/substrate/frame/example/src/lib.rs
@@ -277,6 +277,7 @@ use frame_support::{
 };
 use frame_system::ensure_signed;
 use log::info;
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{Bounded, DispatchInfoOf, SaturatedConversion, Saturating, SignedExtension},
 	transaction_validity::{
@@ -688,12 +689,13 @@ impl<T: Config> Pallet<T> {
 // types defined in the runtime. Lookup `pub type SignedExtra = (...)` in `node/runtime` and
 // `node-template` for an example of this.
 
-// A simple signed extension that checks for the `set_dummy` call. In that case, it increases the
-// priority and prints some log.
-//
-// Additionally, it drops any transaction with an encoded length higher than 200 bytes. No
-// particular reason why, just to demonstrate the power of signed extensions.
-#[derive(Encode, Decode, Clone, Eq, PartialEq)]
+/// A simple signed extension that checks for the `set_dummy` call. In that case, it increases the
+/// priority and prints some log.
+///
+/// Additionally, it drops any transaction with an encoded length higher than 200 bytes. No
+/// particular reason why, just to demonstrate the power of signed extensions.
+#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct WatchDummy<T: Config + Send + Sync>(PhantomData<T>);
 
 impl<T: Config + Send + Sync> sp_std::fmt::Debug for WatchDummy<T> {
@@ -730,7 +732,7 @@ where
 
 		// check for `set_dummy`
 		match call.is_sub_type() {
-			Some(Call::set_dummy(..)) => {
+			Some(Call::set_dummy { .. }) => {
 				sp_runtime::print("set_dummy was received.");
 
 				let mut valid_tx = ValidTransaction::default();
diff --git a/substrate/frame/example/src/tests.rs b/substrate/frame/example/src/tests.rs
index 645b5c9bc13ab6fcec4c568e97de14666c646798..87c2404f5b10012cbdd07daffe75510252394094 100644
--- a/substrate/frame/example/src/tests.rs
+++ b/substrate/frame/example/src/tests.rs
@@ -163,7 +163,7 @@ fn set_dummy_works() {
 #[test]
 fn signed_ext_watch_dummy_works() {
 	new_test_ext().execute_with(|| {
-		let call = <pallet_example::Call<Test>>::set_dummy(10).into();
+		let call = pallet_example::Call::set_dummy { new_value: 10 }.into();
 		let info = DispatchInfo::default();
 
 		assert_eq!(
@@ -183,14 +183,14 @@ fn signed_ext_watch_dummy_works() {
 #[test]
 fn weights_work() {
 	// must have a defined weight.
-	let default_call = <pallet_example::Call<Test>>::accumulate_dummy(10);
+	let default_call = pallet_example::Call::<Test>::accumulate_dummy { increase_by: 10 };
 	let info1 = default_call.get_dispatch_info();
 	// aka. `let info = <Call<Test> as GetDispatchInfo>::get_dispatch_info(&default_call);`
 	assert!(info1.weight > 0);
 
 	// `set_dummy` is simpler than `accumulate_dummy`, and the weight
 	//   should be less.
-	let custom_call = <pallet_example::Call<Test>>::set_dummy(20);
+	let custom_call = pallet_example::Call::<Test>::set_dummy { new_value: 20 };
 	let info2 = custom_call.get_dispatch_info();
 	assert!(info1.weight > info2.weight);
 }
diff --git a/substrate/frame/executive/Cargo.toml b/substrate/frame/executive/Cargo.toml
index a809da6f1cd359119bc963676d45e407d373d822..1abbf50e6a4c4134a9e4f9bebd0dab7e2b4809f5 100644
--- a/substrate/frame/executive/Cargo.toml
+++ b/substrate/frame/executive/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -38,6 +39,7 @@ default = ["std"]
 with-tracing = ["sp-tracing/with-tracing"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"frame-support/std",
 	"frame-system/std",
 	"sp-core/std",
diff --git a/substrate/frame/executive/src/lib.rs b/substrate/frame/executive/src/lib.rs
index 5f1ae23c2f53123f83a8ba3703e19f5c8fa63e7c..655a38fe1b540a0fd030bfffedbf9bf01a5b6cf4 100644
--- a/substrate/frame/executive/src/lib.rs
+++ b/substrate/frame/executive/src/lib.rs
@@ -645,7 +645,7 @@ mod tests {
 				None
 			}
 			fn is_inherent(call: &Self::Call) -> bool {
-				*call == Call::<T>::inherent_call()
+				*call == Call::<T>::inherent_call {}
 			}
 		}
 
@@ -658,7 +658,7 @@ mod tests {
 				call: &Self::Call,
 			) -> TransactionValidity {
 				match call {
-					Call::allowed_unsigned(..) => Ok(Default::default()),
+					Call::allowed_unsigned { .. } => Ok(Default::default()),
 					_ => UnknownTransaction::NoUnsignedValidator.into(),
 				}
 			}
@@ -666,8 +666,8 @@ mod tests {
 			// Inherent call is accepted for being dispatched
 			fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> {
 				match call {
-					Call::allowed_unsigned(..) => Ok(()),
-					Call::inherent_call(..) => Ok(()),
+					Call::allowed_unsigned { .. } => Ok(()),
+					Call::inherent_call { .. } => Ok(()),
 					_ => Err(UnknownTransaction::NoUnsignedValidator.into()),
 				}
 			}
@@ -809,13 +809,17 @@ mod tests {
 		Some((who, extra(nonce, fee)))
 	}
 
+	fn call_transfer(dest: u64, value: u64) -> Call {
+		Call::Balances(BalancesCall::transfer { dest, value })
+	}
+
 	#[test]
 	fn balance_transfer_dispatch_works() {
 		let mut t = frame_system::GenesisConfig::default().build_storage::<Runtime>().unwrap();
 		pallet_balances::GenesisConfig::<Runtime> { balances: vec![(1, 211)] }
 			.assimilate_storage(&mut t)
 			.unwrap();
-		let xt = TestXt::new(Call::Balances(BalancesCall::transfer(2, 69)), sign_extra(1, 0, 0));
+		let xt = TestXt::new(call_transfer(2, 69), sign_extra(1, 0, 0));
 		let weight = xt.get_dispatch_info().weight +
 			<Runtime as frame_system::Config>::BlockWeights::get()
 				.get(DispatchClass::Normal)
@@ -912,7 +916,7 @@ mod tests {
 	fn bad_extrinsic_not_inserted() {
 		let mut t = new_test_ext(1);
 		// bad nonce check!
-		let xt = TestXt::new(Call::Balances(BalancesCall::transfer(33, 69)), sign_extra(1, 30, 0));
+		let xt = TestXt::new(call_transfer(33, 69), sign_extra(1, 30, 0));
 		t.execute_with(|| {
 			Executive::initialize_block(&Header::new(
 				1,
@@ -933,7 +937,10 @@ mod tests {
 	fn block_weight_limit_enforced() {
 		let mut t = new_test_ext(10000);
 		// given: TestXt uses the encoded len as fixed Len:
-		let xt = TestXt::new(Call::Balances(BalancesCall::transfer(33, 0)), sign_extra(1, 0, 0));
+		let xt = TestXt::new(
+			Call::Balances(BalancesCall::transfer { dest: 33, value: 0 }),
+			sign_extra(1, 0, 0),
+		);
 		let encoded = xt.encode();
 		let encoded_len = encoded.len() as Weight;
 		// on_initialize weight + base block execution weight
@@ -954,7 +961,7 @@ mod tests {
 
 			for nonce in 0..=num_to_exhaust_block {
 				let xt = TestXt::new(
-					Call::Balances(BalancesCall::transfer(33, 0)),
+					Call::Balances(BalancesCall::transfer { dest: 33, value: 0 }),
 					sign_extra(1, nonce.into(), 0),
 				);
 				let res = Executive::apply_extrinsic(xt);
@@ -978,9 +985,18 @@ mod tests {
 
 	#[test]
 	fn block_weight_and_size_is_stored_per_tx() {
-		let xt = TestXt::new(Call::Balances(BalancesCall::transfer(33, 0)), sign_extra(1, 0, 0));
-		let x1 = TestXt::new(Call::Balances(BalancesCall::transfer(33, 0)), sign_extra(1, 1, 0));
-		let x2 = TestXt::new(Call::Balances(BalancesCall::transfer(33, 0)), sign_extra(1, 2, 0));
+		let xt = TestXt::new(
+			Call::Balances(BalancesCall::transfer { dest: 33, value: 0 }),
+			sign_extra(1, 0, 0),
+		);
+		let x1 = TestXt::new(
+			Call::Balances(BalancesCall::transfer { dest: 33, value: 0 }),
+			sign_extra(1, 1, 0),
+		);
+		let x2 = TestXt::new(
+			Call::Balances(BalancesCall::transfer { dest: 33, value: 0 }),
+			sign_extra(1, 2, 0),
+		);
 		let len = xt.clone().encode().len() as u32;
 		let mut t = new_test_ext(1);
 		t.execute_with(|| {
@@ -1034,8 +1050,8 @@ mod tests {
 
 	#[test]
 	fn validate_unsigned() {
-		let valid = TestXt::new(Call::Custom(custom::Call::allowed_unsigned()), None);
-		let invalid = TestXt::new(Call::Custom(custom::Call::unallowed_unsigned()), None);
+		let valid = TestXt::new(Call::Custom(custom::Call::allowed_unsigned {}), None);
+		let invalid = TestXt::new(Call::Custom(custom::Call::unallowed_unsigned {}), None);
 		let mut t = new_test_ext(1);
 
 		let mut default_with_prio_3 = ValidTransaction::default();
@@ -1074,8 +1090,10 @@ mod tests {
 				<pallet_balances::Pallet<Runtime> as LockableCurrency<Balance>>::set_lock(
 					id, &1, 110, lock,
 				);
-				let xt =
-					TestXt::new(Call::System(SystemCall::remark(vec![1u8])), sign_extra(1, 0, 0));
+				let xt = TestXt::new(
+					Call::System(SystemCall::remark { remark: vec![1u8] }),
+					sign_extra(1, 0, 0),
+				);
 				let weight = xt.get_dispatch_info().weight +
 					<Runtime as frame_system::Config>::BlockWeights::get()
 						.get(DispatchClass::Normal)
@@ -1222,7 +1240,10 @@ mod tests {
 	/// used through the `ExecuteBlock` trait.
 	#[test]
 	fn custom_runtime_upgrade_is_called_when_using_execute_block_trait() {
-		let xt = TestXt::new(Call::Balances(BalancesCall::transfer(33, 0)), sign_extra(1, 0, 0));
+		let xt = TestXt::new(
+			Call::Balances(BalancesCall::transfer { dest: 33, value: 0 }),
+			sign_extra(1, 0, 0),
+		);
 
 		let header = new_test_ext(1).execute_with(|| {
 			// Make sure `on_runtime_upgrade` is called.
@@ -1326,7 +1347,7 @@ mod tests {
 
 	#[test]
 	fn calculating_storage_root_twice_works() {
-		let call = Call::Custom(custom::Call::calculate_storage_root());
+		let call = Call::Custom(custom::Call::calculate_storage_root {});
 		let xt = TestXt::new(call, sign_extra(1, 0, 0));
 
 		let header = new_test_ext(1).execute_with(|| {
@@ -1352,8 +1373,11 @@ mod tests {
 	#[test]
 	#[should_panic(expected = "Invalid inherent position for extrinsic at index 1")]
 	fn invalid_inherent_position_fail() {
-		let xt1 = TestXt::new(Call::Balances(BalancesCall::transfer(33, 0)), sign_extra(1, 0, 0));
-		let xt2 = TestXt::new(Call::Custom(custom::Call::inherent_call()), None);
+		let xt1 = TestXt::new(
+			Call::Balances(BalancesCall::transfer { dest: 33, value: 0 }),
+			sign_extra(1, 0, 0),
+		);
+		let xt2 = TestXt::new(Call::Custom(custom::Call::inherent_call {}), None);
 
 		let header = new_test_ext(1).execute_with(|| {
 			// Let's build some fake block.
@@ -1378,8 +1402,8 @@ mod tests {
 
 	#[test]
 	fn valid_inherents_position_works() {
-		let xt1 = TestXt::new(Call::Custom(custom::Call::inherent_call()), None);
-		let xt2 = TestXt::new(Call::Balances(BalancesCall::transfer(33, 0)), sign_extra(1, 0, 0));
+		let xt1 = TestXt::new(Call::Custom(custom::Call::inherent_call {}), None);
+		let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0));
 
 		let header = new_test_ext(1).execute_with(|| {
 			// Let's build some fake block.
diff --git a/substrate/frame/gilt/Cargo.toml b/substrate/frame/gilt/Cargo.toml
index a6e59a2dcd65fe17ec8766764af6b723f68d6dd5..c275b693d8f276fa8c7031e9c6281e23f22faa13 100644
--- a/substrate/frame/gilt/Cargo.toml
+++ b/substrate/frame/gilt/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
 sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" }
@@ -30,6 +31,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-runtime/std",
 	"sp-arithmetic/std",
diff --git a/substrate/frame/gilt/src/benchmarking.rs b/substrate/frame/gilt/src/benchmarking.rs
index befa373e6e7fa8195933baa3cf7502921da4eb12..55d34a35a7ce41ccbb095db40f2bd52889229e8d 100644
--- a/substrate/frame/gilt/src/benchmarking.rs
+++ b/substrate/frame/gilt/src/benchmarking.rs
@@ -81,7 +81,7 @@ benchmarks! {
 	}
 
 	set_target {
-		let call = Call::<T>::set_target(Default::default());
+		let call = Call::<T>::set_target { target: Default::default() };
 		let origin = T::AdminOrigin::successful_origin();
 	}: { call.dispatch_bypass_filter(origin)? }
 
@@ -111,7 +111,7 @@ benchmarks! {
 			Gilt::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), T::MinFreeze::get(), 1)?;
 		}
 
-		Call::<T>::set_target(Perquintill::from_percent(100))
+		Call::<T>::set_target { target: Perquintill::from_percent(100) }
 			.dispatch_bypass_filter(T::AdminOrigin::successful_origin())?;
 
 	}: { Gilt::<T>::pursue_target(b) }
@@ -127,7 +127,7 @@ benchmarks! {
 			Gilt::<T>::place_bid(RawOrigin::Signed(caller.clone()).into(), T::MinFreeze::get(), i + 1)?;
 		}
 
-		Call::<T>::set_target(Perquintill::from_percent(100))
+		Call::<T>::set_target { target: Perquintill::from_percent(100) }
 			.dispatch_bypass_filter(T::AdminOrigin::successful_origin())?;
 
 	}: { Gilt::<T>::pursue_target(q) }
diff --git a/substrate/frame/gilt/src/lib.rs b/substrate/frame/gilt/src/lib.rs
index 7bfca872dc3f8a51a73ca91f87b6e5d41f3f7597..de114e4bb87de2baebeb6abecf7ad094f69f3242 100644
--- a/substrate/frame/gilt/src/lib.rs
+++ b/substrate/frame/gilt/src/lib.rs
@@ -82,6 +82,7 @@ pub mod pallet {
 		traits::{Currency, OnUnbalanced, ReservableCurrency},
 	};
 	use frame_system::pallet_prelude::*;
+	use scale_info::TypeInfo;
 	use sp_arithmetic::{PerThing, Perquintill};
 	use sp_runtime::traits::{Saturating, Zero};
 	use sp_std::prelude::*;
@@ -111,7 +112,8 @@ pub mod pallet {
 			+ MaybeSerializeDeserialize
 			+ sp_std::fmt::Debug
 			+ Default
-			+ From<u64>;
+			+ From<u64>
+			+ TypeInfo;
 
 		/// Origin required for setting the target proportion to be under gilt.
 		type AdminOrigin: EnsureOrigin<Self::Origin>;
@@ -181,7 +183,7 @@ pub mod pallet {
 	pub struct Pallet<T>(_);
 
 	/// A single bid on a gilt, an item of a *queue* in `Queues`.
-	#[derive(Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug)]
+	#[derive(Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug, TypeInfo)]
 	pub struct GiltBid<Balance, AccountId> {
 		/// The amount bid.
 		pub amount: Balance,
@@ -190,7 +192,7 @@ pub mod pallet {
 	}
 
 	/// Information representing an active gilt.
-	#[derive(Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug)]
+	#[derive(Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug, TypeInfo)]
 	pub struct ActiveGilt<Balance, AccountId, BlockNumber> {
 		/// The proportion of the effective total issuance (i.e. accounting for any eventual gilt
 		/// expansion or contraction that may eventually be claimed).
@@ -214,7 +216,7 @@ pub mod pallet {
 	/// `issuance - frozen + proportion * issuance`
 	///
 	/// where `issuance = total_issuance - IgnoredIssuance`
-	#[derive(Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug)]
+	#[derive(Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug, TypeInfo)]
 	pub struct ActiveGiltsTotal<Balance> {
 		/// The total amount of funds held in reserve for all active gilts.
 		pub frozen: Balance,
@@ -269,7 +271,6 @@ pub mod pallet {
 	}
 
 	#[pallet::event]
-	#[pallet::metadata(T::AccountId = "AccountId")]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
 		/// A bid was successfully placed.
diff --git a/substrate/frame/grandpa/Cargo.toml b/substrate/frame/grandpa/Cargo.toml
index 9e60ad0fb3c8a14362ed135dcf5385c895654ba6..53ab443783e5da9435cfb15ecdafc14513a82a32 100644
--- a/substrate/frame/grandpa/Cargo.toml
+++ b/substrate/frame/grandpa/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
 sp-finality-grandpa = { version = "4.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" }
@@ -44,6 +45,7 @@ frame-election-provider-support = { version = "4.0.0-dev", path = "../election-p
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"frame-benchmarking/std",
 	"sp-application-crypto/std",
 	"sp-core/std",
diff --git a/substrate/frame/grandpa/src/equivocation.rs b/substrate/frame/grandpa/src/equivocation.rs
index 40d8535dabb60941a69e9c3a5a641cad9c023bd8..8a23ce6e1ef1ef32f3077a76665b15db328d797a 100644
--- a/substrate/frame/grandpa/src/equivocation.rs
+++ b/substrate/frame/grandpa/src/equivocation.rs
@@ -164,8 +164,10 @@ where
 	) -> DispatchResult {
 		use frame_system::offchain::SubmitTransaction;
 
-		let call =
-			Call::report_equivocation_unsigned(Box::new(equivocation_proof), key_owner_proof);
+		let call = Call::report_equivocation_unsigned {
+			equivocation_proof: Box::new(equivocation_proof),
+			key_owner_proof,
+		};
 
 		match SubmitTransaction::<T, Call<T>>::submit_unsigned_transaction(call.into()) {
 			Ok(()) => log::info!(
@@ -203,7 +205,7 @@ pub struct GrandpaTimeSlot {
 /// unsigned equivocation reports.
 impl<T: Config> Pallet<T> {
 	pub fn validate_unsigned(source: TransactionSource, call: &Call<T>) -> TransactionValidity {
-		if let Call::report_equivocation_unsigned(equivocation_proof, key_owner_proof) = call {
+		if let Call::report_equivocation_unsigned { equivocation_proof, key_owner_proof } = call {
 			// discard equivocation report not coming from the local node
 			match source {
 				TransactionSource::Local | TransactionSource::InBlock => { /* allowed */ },
@@ -242,7 +244,7 @@ impl<T: Config> Pallet<T> {
 	}
 
 	pub fn pre_dispatch(call: &Call<T>) -> Result<(), TransactionValidityError> {
-		if let Call::report_equivocation_unsigned(equivocation_proof, key_owner_proof) = call {
+		if let Call::report_equivocation_unsigned { equivocation_proof, key_owner_proof } = call {
 			is_known_offence::<T>(equivocation_proof, key_owner_proof)
 		} else {
 			Err(InvalidTransaction::Call.into())
diff --git a/substrate/frame/grandpa/src/lib.rs b/substrate/frame/grandpa/src/lib.rs
index 7cad0d477c9eeacfd78207a163f654eba53f802f..cd75deea770b4b131f13d325a122f75c58ccbb88 100644
--- a/substrate/frame/grandpa/src/lib.rs
+++ b/substrate/frame/grandpa/src/lib.rs
@@ -67,6 +67,8 @@ pub use equivocation::{
 
 pub use pallet::*;
 
+use scale_info::TypeInfo;
+
 /// The current storage version.
 const STORAGE_VERSION: StorageVersion = StorageVersion::new(4);
 
@@ -354,7 +356,7 @@ pub trait WeightInfo {
 }
 
 /// A stored pending change.
-#[derive(Encode, Decode)]
+#[derive(Encode, Decode, TypeInfo)]
 pub struct StoredPendingChange<N> {
 	/// The block number this was scheduled at.
 	pub scheduled_at: N,
@@ -370,7 +372,7 @@ pub struct StoredPendingChange<N> {
 /// Current state of the GRANDPA authority set. State transitions must happen in
 /// the same order of states defined below, e.g. `Paused` implies a prior
 /// `PendingPause`.
-#[derive(Decode, Encode)]
+#[derive(Decode, Encode, TypeInfo)]
 #[cfg_attr(test, derive(Debug, PartialEq))]
 pub enum StoredState<N> {
 	/// The current authority set is live, and GRANDPA is enabled.
diff --git a/substrate/frame/grandpa/src/tests.rs b/substrate/frame/grandpa/src/tests.rs
index 034758e0a21b5ea58b07c8312d1655153502731a..98f54f966fadce530af454e17b52bafe496303ea 100644
--- a/substrate/frame/grandpa/src/tests.rs
+++ b/substrate/frame/grandpa/src/tests.rs
@@ -681,10 +681,10 @@ fn report_equivocation_validate_unsigned_prevents_duplicates() {
 		let key_owner_proof =
 			Historical::prove((sp_finality_grandpa::KEY_TYPE, &equivocation_key)).unwrap();
 
-		let call = Call::report_equivocation_unsigned(
-			Box::new(equivocation_proof.clone()),
-			key_owner_proof.clone(),
-		);
+		let call = Call::report_equivocation_unsigned {
+			equivocation_proof: Box::new(equivocation_proof.clone()),
+			key_owner_proof: key_owner_proof.clone(),
+		};
 
 		// only local/inblock reports are allowed
 		assert_eq!(
@@ -843,10 +843,10 @@ fn valid_equivocation_reports_dont_pay_fees() {
 			Historical::prove((sp_finality_grandpa::KEY_TYPE, &equivocation_key)).unwrap();
 
 		// check the dispatch info for the call.
-		let info = Call::<Test>::report_equivocation_unsigned(
-			Box::new(equivocation_proof.clone()),
-			key_owner_proof.clone(),
-		)
+		let info = Call::<Test>::report_equivocation_unsigned {
+			equivocation_proof: Box::new(equivocation_proof.clone()),
+			key_owner_proof: key_owner_proof.clone(),
+		}
 		.get_dispatch_info();
 
 		// it should have non-zero weight and the fee has to be paid.
diff --git a/substrate/frame/identity/Cargo.toml b/substrate/frame/identity/Cargo.toml
index 489a01b27da69d7352b41352f9855a7aea58ab52..598be25c5ef38a602700fc57519d426b7bd8b607 100644
--- a/substrate/frame/identity/Cargo.toml
+++ b/substrate/frame/identity/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 enumflags2 = { version = "0.6.2" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
@@ -30,6 +31,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-io/std",
 	"sp-runtime/std",
diff --git a/substrate/frame/identity/src/lib.rs b/substrate/frame/identity/src/lib.rs
index b56df59e113c020cc345d48f9c41d460ba87ef76..a91381f1edd8b57a5f8b3243f8e06756c3d1f433 100644
--- a/substrate/frame/identity/src/lib.rs
+++ b/substrate/frame/identity/src/lib.rs
@@ -240,10 +240,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(
-		T::AccountId = "AccountId",
-		BalanceOf<T> = "Balance"
-	)]
 	pub enum Event<T: Config> {
 		/// A name was set or reset (which will remove all judgements). \[who\]
 		IdentitySet(T::AccountId),
diff --git a/substrate/frame/identity/src/types.rs b/substrate/frame/identity/src/types.rs
index 86e461c644d10b215efc31ad00ae0f50fb0fda93..ed6aeb18e96a1ef88202baa0c582357984710553 100644
--- a/substrate/frame/identity/src/types.rs
+++ b/substrate/frame/identity/src/types.rs
@@ -22,6 +22,10 @@ use frame_support::{
 	traits::{ConstU32, Get},
 	BoundedVec, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound,
 };
+use scale_info::{
+	build::{Fields, Variants},
+	meta_type, Path, Type, TypeInfo, TypeParameter,
+};
 use sp_runtime::{traits::Zero, RuntimeDebug};
 use sp_std::{fmt::Debug, iter::once, ops::Add, prelude::*};
 
@@ -89,6 +93,81 @@ impl Encode for Data {
 }
 impl codec::EncodeLike for Data {}
 
+/// Add a Raw variant with the given index and a fixed sized byte array
+macro_rules! data_raw_variants {
+    ($variants:ident, $(($index:literal, $size:literal)),* ) => {
+		$variants
+		$(
+			.variant(concat!("Raw", stringify!($size)), |v| v
+				.index($index)
+				.fields(Fields::unnamed().field(|f| f.ty::<[u8; $size]>()))
+			)
+		)*
+    }
+}
+
+impl TypeInfo for Data {
+	type Identity = Self;
+
+	fn type_info() -> Type {
+		let variants = Variants::new().variant("None", |v| v.index(0));
+
+		// create a variant for all sizes of Raw data from 0-32
+		let variants = data_raw_variants!(
+			variants,
+			(1, 0),
+			(2, 1),
+			(3, 2),
+			(4, 3),
+			(5, 4),
+			(6, 5),
+			(7, 6),
+			(8, 7),
+			(9, 8),
+			(10, 9),
+			(11, 10),
+			(12, 11),
+			(13, 12),
+			(14, 13),
+			(15, 14),
+			(16, 15),
+			(17, 16),
+			(18, 17),
+			(19, 18),
+			(20, 19),
+			(21, 20),
+			(22, 21),
+			(23, 22),
+			(24, 23),
+			(25, 24),
+			(26, 25),
+			(27, 26),
+			(28, 27),
+			(29, 28),
+			(30, 29),
+			(31, 30),
+			(32, 31),
+			(33, 32)
+		);
+
+		let variants = variants
+			.variant("BlakeTwo256", |v| {
+				v.index(34).fields(Fields::unnamed().field(|f| f.ty::<[u8; 32]>()))
+			})
+			.variant("Sha256", |v| {
+				v.index(35).fields(Fields::unnamed().field(|f| f.ty::<[u8; 32]>()))
+			})
+			.variant("Keccak256", |v| {
+				v.index(36).fields(Fields::unnamed().field(|f| f.ty::<[u8; 32]>()))
+			})
+			.variant("ShaThree256", |v| {
+				v.index(37).fields(Fields::unnamed().field(|f| f.ty::<[u8; 32]>()))
+			});
+
+		Type::builder().path(Path::new("Data", module_path!())).variant(variants)
+	}
+}
+
 impl Default for Data {
 	fn default() -> Self {
 		Self::None
@@ -102,7 +181,7 @@ pub type RegistrarIndex = u32;
 ///
 /// NOTE: Registrars may pay little attention to some fields. Registrars may want to make clear
 /// which fields their attestation is relevant for by off-chain means.
-#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen)]
+#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 pub enum Judgement<Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq>
 {
 	/// The default value; no opinion is held.
@@ -152,7 +231,7 @@ impl<Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + Part
 /// The fields that we use to identify the owner of an account with. Each corresponds to a field
 /// in the `IdentityInfo` struct.
 #[repr(u64)]
-#[derive(Clone, Copy, PartialEq, Eq, BitFlags, RuntimeDebug)]
+#[derive(Clone, Copy, PartialEq, Eq, BitFlags, RuntimeDebug, TypeInfo)]
 pub enum IdentityField {
 	Display = 0b0000000000000000000000000000000000000000000000000000000000000001,
 	Legal = 0b0000000000000000000000000000000000000000000000000000000000000010,
@@ -186,16 +265,27 @@ impl Decode for IdentityFields {
 		Ok(Self(<BitFlags<IdentityField>>::from_bits(field as u64).map_err(|_| "invalid value")?))
 	}
 }
+impl TypeInfo for IdentityFields {
+	type Identity = Self;
+
+	fn type_info() -> Type {
+		Type::builder()
+			.path(Path::new("BitFlags", module_path!()))
+			.type_params(vec![TypeParameter::new("T", Some(meta_type::<IdentityField>()))])
+			.composite(Fields::unnamed().field(|f| f.ty::<u64>().type_name("IdentityField")))
+	}
+}
 
 /// Information concerning the identity of the controller of an account.
 ///
 /// NOTE: This should be stored at the end of the storage item to facilitate the addition of extra
 /// fields in a backwards compatible way through a specialized `Decode` impl.
 #[derive(
-	CloneNoBound, Encode, Decode, Eq, MaxEncodedLen, PartialEqNoBound, RuntimeDebugNoBound,
+	CloneNoBound, Encode, Decode, Eq, MaxEncodedLen, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo,
 )]
 #[codec(mel_bound(FieldLimit: Get<u32>))]
 #[cfg_attr(test, derive(frame_support::DefaultNoBound))]
+#[scale_info(skip_type_params(FieldLimit))]
 pub struct IdentityInfo<FieldLimit: Get<u32>> {
 	/// Additional fields of the identity that are not catered for with the struct's explicit
 	/// fields.
@@ -246,12 +336,15 @@ pub struct IdentityInfo<FieldLimit: Get<u32>> {
 ///
 /// NOTE: This is stored separately primarily to facilitate the addition of extra fields in a
 /// backwards compatible way through a specialized `Decode` impl.
-#[derive(CloneNoBound, Encode, Eq, MaxEncodedLen, PartialEqNoBound, RuntimeDebugNoBound)]
+#[derive(
+	CloneNoBound, Encode, Eq, MaxEncodedLen, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo,
+)]
 #[codec(mel_bound(
 	Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq + Zero + Add,
 	MaxJudgements: Get<u32>,
 	MaxAdditionalFields: Get<u32>,
 ))]
+#[scale_info(skip_type_params(MaxJudgements, MaxAdditionalFields))]
 pub struct Registration<
 	Balance: Encode + Decode + MaxEncodedLen + Copy + Clone + Debug + Eq + PartialEq,
 	MaxJudgements: Get<u32>,
@@ -296,7 +389,7 @@ impl<
 }
 
 /// Information concerning a registrar.
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen)]
+#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 pub struct RegistrarInfo<
 	Balance: Encode + Decode + Clone + Debug + Eq + PartialEq,
 	AccountId: Encode + Decode + Clone + Debug + Eq + PartialEq,
@@ -311,3 +404,70 @@ pub struct RegistrarInfo<
 	/// these fields.
 	pub fields: IdentityFields,
 }
+
+#[cfg(test)]
+mod tests {
+	use super::*;
+
+	#[test]
+	fn manual_data_type_info() {
+		let mut registry = scale_info::Registry::new();
+		let type_id = registry.register_type(&scale_info::meta_type::<Data>());
+		let registry: scale_info::PortableRegistry = registry.into();
+		let type_info = registry.resolve(type_id.id()).unwrap();
+
+		let check_type_info = |data: &Data| {
+			let variant_name = match data {
+				Data::None => "None".to_string(),
+				Data::BlakeTwo256(_) => "BlakeTwo256".to_string(),
+				Data::Sha256(_) => "Sha256".to_string(),
+				Data::Keccak256(_) => "Keccak256".to_string(),
+				Data::ShaThree256(_) => "ShaThree256".to_string(),
+				Data::Raw(bytes) => format!("Raw{}", bytes.len()),
+			};
+			if let scale_info::TypeDef::Variant(variant) = type_info.type_def() {
+				let variant = variant
+					.variants()
+					.iter()
+					.find(|v| v.name() == &variant_name)
+					.expect(&format!("Expected to find variant {}", variant_name));
+
+				let field_arr_len = variant
+					.fields()
+					.first()
+					.and_then(|f| registry.resolve(f.ty().id()))
+					.map(|ty| {
+						if let scale_info::TypeDef::Array(arr) = ty.type_def() {
+							arr.len()
+						} else {
+							panic!("Should be an array type")
+						}
+					})
+					.unwrap_or(0);
+
+				let encoded = data.encode();
+				assert_eq!(encoded[0], variant.index());
+				assert_eq!(encoded.len() as u32 - 1, field_arr_len);
+			} else {
+				panic!("Should be a variant type")
+			};
+		};
+
+		let mut data = vec![
+			Data::None,
+			Data::BlakeTwo256(Default::default()),
+			Data::Sha256(Default::default()),
+			Data::Keccak256(Default::default()),
+			Data::ShaThree256(Default::default()),
+		];
+
+		// A Raw instance for all possible sizes of the Raw data
+		for n in 0..32 {
+			data.push(Data::Raw(vec![0u8; n as usize].try_into().unwrap()))
+		}
+
+		for d in data.iter() {
+			check_type_info(d);
+		}
+	}
+}
diff --git a/substrate/frame/im-online/Cargo.toml b/substrate/frame/im-online/Cargo.toml
index 1208da3b3f3d5634ad46fb67b6f13e0cdc9d5e14..a1efd626c0690821d55578d2f267e9a1ce192484 100644
--- a/substrate/frame/im-online/Cargo.toml
+++ b/substrate/frame/im-online/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../primitives/application-crypto" }
 pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../authorship" }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
@@ -36,6 +37,7 @@ std = [
 	"sp-application-crypto/std",
 	"pallet-authorship/std",
 	"codec/std",
+	"scale-info/std",
 	"sp-core/std",
 	"sp-std/std",
 	"sp-io/std",
diff --git a/substrate/frame/im-online/src/benchmarking.rs b/substrate/frame/im-online/src/benchmarking.rs
index 2a2d837a4bd58a094fc1bf2d7b72d931b1f5a1ad..1043a97f67defdf4f2e7aeababc7c6808e7e3f76 100644
--- a/substrate/frame/im-online/src/benchmarking.rs
+++ b/substrate/frame/im-online/src/benchmarking.rs
@@ -80,7 +80,7 @@ benchmarks! {
 		let k in 1 .. MAX_KEYS;
 		let e in 1 .. MAX_EXTERNAL_ADDRESSES;
 		let (input_heartbeat, signature) = create_heartbeat::<T>(k, e)?;
-		let call = Call::heartbeat(input_heartbeat, signature);
+		let call = Call::heartbeat { heartbeat: input_heartbeat, signature };
 	}: {
 		ImOnline::<T>::validate_unsigned(TransactionSource::InBlock, &call)
 			.map_err(<&str>::from)?;
@@ -90,7 +90,7 @@ benchmarks! {
 		let k in 1 .. MAX_KEYS;
 		let e in 1 .. MAX_EXTERNAL_ADDRESSES;
 		let (input_heartbeat, signature) = create_heartbeat::<T>(k, e)?;
-		let call = Call::heartbeat(input_heartbeat, signature);
+		let call = Call::heartbeat { heartbeat: input_heartbeat, signature };
 	}: {
 		ImOnline::<T>::validate_unsigned(TransactionSource::InBlock, &call)
 			.map_err(<&str>::from)?;
diff --git a/substrate/frame/im-online/src/lib.rs b/substrate/frame/im-online/src/lib.rs
index 3a040c7b5e21d0f96d946455a6a408b4e7dc9c80..ab4f7001574e55b4798e24ecf8f9eb9320affe5d 100644
--- a/substrate/frame/im-online/src/lib.rs
+++ b/substrate/frame/im-online/src/lib.rs
@@ -80,6 +80,7 @@ use frame_support::traits::{
 };
 use frame_system::offchain::{SendTransactionTypes, SubmitTransaction};
 pub use pallet::*;
+use scale_info::TypeInfo;
 use sp_application_crypto::RuntimeAppPublic;
 use sp_core::offchain::OpaqueNetworkState;
 use sp_runtime::{
@@ -140,7 +141,7 @@ const INCLUDE_THRESHOLD: u32 = 3;
 /// This stores the block number at which heartbeat was requested and when the worker
 /// has actually managed to produce it.
 /// Note we store such status for every `authority_index` separately.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 struct HeartbeatStatus<BlockNumber> {
 	/// An index of the session that we are supposed to send heartbeat for.
 	pub session_index: SessionIndex,
@@ -202,7 +203,7 @@ impl<BlockNumber: sp_std::fmt::Debug> sp_std::fmt::Debug for OffchainErr<BlockNu
 pub type AuthIndex = u32;
 
 /// Heartbeat which is sent/received.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub struct Heartbeat<BlockNumber>
 where
 	BlockNumber: PartialEq + Eq + Decode + Encode,
@@ -297,7 +298,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AuthorityId = "AuthorityId", Vec<IdentificationTuple<T>> = "Vec<IdentificationTuple>")]
 	pub enum Event<T: Config> {
 		/// A new heartbeat was received from `AuthorityId` \[authority_id\]
 		HeartbeatReceived(T::AuthorityId),
@@ -459,7 +459,7 @@ pub mod pallet {
 		type Call = Call<T>;
 
 		fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
-			if let Call::heartbeat(heartbeat, signature) = call {
+			if let Call::heartbeat { heartbeat, signature } = call {
 				if <Pallet<T>>::is_online(heartbeat.authority_index) {
 					// we already received a heartbeat for this authority
 					return InvalidTransaction::Stale.into()
@@ -631,7 +631,7 @@ impl<T: Config> Pallet<T> {
 		let prepare_heartbeat = || -> OffchainResult<T, Call<T>> {
 			let network_state =
 				sp_io::offchain::network_state().map_err(|_| OffchainErr::NetworkState)?;
-			let heartbeat_data = Heartbeat {
+			let heartbeat = Heartbeat {
 				block_number,
 				network_state,
 				session_index,
@@ -639,9 +639,9 @@ impl<T: Config> Pallet<T> {
 				validators_len,
 			};
 
-			let signature = key.sign(&heartbeat_data.encode()).ok_or(OffchainErr::FailedSigning)?;
+			let signature = key.sign(&heartbeat.encode()).ok_or(OffchainErr::FailedSigning)?;
 
-			Ok(Call::heartbeat(heartbeat_data, signature))
+			Ok(Call::heartbeat { heartbeat, signature })
 		};
 
 		if Self::is_online(authority_index) {
@@ -820,7 +820,7 @@ impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T> {
 }
 
 /// An offence that is filed if a validator didn't send a heartbeat message.
-#[derive(RuntimeDebug)]
+#[derive(RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Clone, PartialEq, Eq))]
 pub struct UnresponsivenessOffence<Offender> {
 	/// The current session index in which we report the unresponsive validators.
diff --git a/substrate/frame/im-online/src/tests.rs b/substrate/frame/im-online/src/tests.rs
index 2492e46ef18a074f871e88f3e1ebf5d8fbb4546e..bb2c4c7cae54896115304a19242dac26172084a2 100644
--- a/substrate/frame/im-online/src/tests.rs
+++ b/substrate/frame/im-online/src/tests.rs
@@ -130,14 +130,15 @@ fn heartbeat(
 	};
 	let signature = id.sign(&heartbeat.encode()).unwrap();
 
-	ImOnline::pre_dispatch(&crate::Call::heartbeat(heartbeat.clone(), signature.clone())).map_err(
-		|e| match e {
-			TransactionValidityError::Invalid(InvalidTransaction::Custom(
-				INVALID_VALIDATORS_LEN,
-			)) => "invalid validators len",
-			e @ _ => <&'static str>::from(e),
-		},
-	)?;
+	ImOnline::pre_dispatch(&crate::Call::heartbeat {
+		heartbeat: heartbeat.clone(),
+		signature: signature.clone(),
+	})
+	.map_err(|e| match e {
+		TransactionValidityError::Invalid(InvalidTransaction::Custom(INVALID_VALIDATORS_LEN)) =>
+			"invalid validators len",
+		e @ _ => <&'static str>::from(e),
+	})?;
 	ImOnline::heartbeat(Origin::none(), heartbeat, signature)
 }
 
@@ -237,7 +238,7 @@ fn should_generate_heartbeats() {
 		// check stuff about the transaction.
 		let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap();
 		let heartbeat = match ex.call {
-			crate::mock::Call::ImOnline(crate::Call::heartbeat(h, ..)) => h,
+			crate::mock::Call::ImOnline(crate::Call::heartbeat { heartbeat, .. }) => heartbeat,
 			e => panic!("Unexpected call: {:?}", e),
 		};
 
@@ -352,7 +353,7 @@ fn should_not_send_a_report_if_already_online() {
 		// check stuff about the transaction.
 		let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap();
 		let heartbeat = match ex.call {
-			crate::mock::Call::ImOnline(crate::Call::heartbeat(h, ..)) => h,
+			crate::mock::Call::ImOnline(crate::Call::heartbeat { heartbeat, .. }) => heartbeat,
 			e => panic!("Unexpected call: {:?}", e),
 		};
 
diff --git a/substrate/frame/indices/Cargo.toml b/substrate/frame/indices/Cargo.toml
index c226ea2cf23502f30e8574ed2dd3cefd77a47c6a..17d04c43fa5d9cd84e86ddada476c9617144c51a 100644
--- a/substrate/frame/indices/Cargo.toml
+++ b/substrate/frame/indices/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-keyring = { version = "4.0.0-dev", optional = true, path = "../../primitives/keyring" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
@@ -32,6 +33,7 @@ default = ["std"]
 std = [
 	"sp-keyring",
 	"codec/std",
+	"scale-info/std",
 	"sp-core/std",
 	"sp-std/std",
 	"sp-io/std",
diff --git a/substrate/frame/indices/src/lib.rs b/substrate/frame/indices/src/lib.rs
index 331873d42451cc98580d0c401d1afb14ebfe7a51..0901a89d41ad61feb5c79f12c39710d199ba9777 100644
--- a/substrate/frame/indices/src/lib.rs
+++ b/substrate/frame/indices/src/lib.rs
@@ -260,7 +260,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId", T::AccountIndex = "AccountIndex")]
 	pub enum Event<T: Config> {
 		/// A account index was assigned. \[index, who\]
 		IndexAssigned(T::AccountId, T::AccountIndex),
diff --git a/substrate/frame/lottery/Cargo.toml b/substrate/frame/lottery/Cargo.toml
index 351e72a77a5556ec13effddef0cf48aaa4a03fe1..f14d65310cc7003aa07d35b0c8d697d414449188 100644
--- a/substrate/frame/lottery/Cargo.toml
+++ b/substrate/frame/lottery/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
@@ -33,6 +34,7 @@ sp-io = { version = "4.0.0-dev", path = "../../primitives/io" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"frame-support/std",
 	"sp-runtime/std",
diff --git a/substrate/frame/lottery/src/benchmarking.rs b/substrate/frame/lottery/src/benchmarking.rs
index 706561471ee5d57801e5f20d944540696c5c96ec..3b7035c72deb037d67490208d7f28288e45fbb93 100644
--- a/substrate/frame/lottery/src/benchmarking.rs
+++ b/substrate/frame/lottery/src/benchmarking.rs
@@ -35,11 +35,11 @@ fn setup_lottery<T: Config>(repeat: bool) -> Result<(), &'static str> {
 	let delay = 5u32.into();
 	// Calls will be maximum length...
 	let mut calls = vec![
-		frame_system::Call::<T>::set_code(vec![]).into();
+		frame_system::Call::<T>::set_code { code: vec![] }.into();
 		T::MaxCalls::get().saturating_sub(1) as usize
 	];
 	// Last call will be the match for worst case scenario.
-	calls.push(frame_system::Call::<T>::remark(vec![]).into());
+	calls.push(frame_system::Call::<T>::remark { remark: vec![] }.into());
 	let origin = T::ManagerOrigin::successful_origin();
 	Lottery::<T>::set_calls(origin.clone(), calls)?;
 	Lottery::<T>::start_lottery(origin, price, length, delay, repeat)?;
@@ -53,7 +53,7 @@ benchmarks! {
 		setup_lottery::<T>(false)?;
 		// force user to have a long vec of calls participating
 		let set_code_index: CallIndex = Lottery::<T>::call_to_index(
-			&frame_system::Call::<T>::set_code(vec![]).into()
+			&frame_system::Call::<T>::set_code{ code: vec![] }.into()
 		)?;
 		let already_called: (u32, Vec<CallIndex>) = (
 			LotteryIndex::<T>::get(),
@@ -64,7 +64,7 @@ benchmarks! {
 		);
 		Participants::<T>::insert(&caller, already_called);
 
-		let call = frame_system::Call::<T>::remark(vec![]);
+		let call = frame_system::Call::<T>::remark { remark: vec![] };
 	}: _(RawOrigin::Signed(caller), Box::new(call.into()))
 	verify {
 		assert_eq!(TicketsCount::<T>::get(), 1);
@@ -72,9 +72,9 @@ benchmarks! {
 
 	set_calls {
 		let n in 0 .. T::MaxCalls::get() as u32;
-		let calls = vec![frame_system::Call::<T>::remark(vec![]).into(); n as usize];
+		let calls = vec![frame_system::Call::<T>::remark { remark: vec![] }.into(); n as usize];
 
-		let call = Call::<T>::set_calls(calls);
+		let call = Call::<T>::set_calls { calls };
 		let origin = T::ManagerOrigin::successful_origin();
 		assert!(CallIndices::<T>::get().is_empty());
 	}: { call.dispatch_bypass_filter(origin)? }
@@ -89,7 +89,7 @@ benchmarks! {
 		let end = 10u32.into();
 		let payout = 5u32.into();
 
-		let call = Call::<T>::start_lottery(price, end, payout, true);
+		let call = Call::<T>::start_lottery { price, length: end, delay: payout, repeat: true };
 		let origin = T::ManagerOrigin::successful_origin();
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
@@ -99,7 +99,7 @@ benchmarks! {
 	stop_repeat {
 		setup_lottery::<T>(true)?;
 		assert_eq!(crate::Lottery::<T>::get().unwrap().repeat, true);
-		let call = Call::<T>::stop_repeat();
+		let call = Call::<T>::stop_repeat {};
 		let origin = T::ManagerOrigin::successful_origin();
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
@@ -115,7 +115,7 @@ benchmarks! {
 		let lottery_account = Lottery::<T>::account_id();
 		T::Currency::make_free_balance_be(&lottery_account, T::Currency::minimum_balance() * 10u32.into());
 		// Buy a ticket
-		let call = frame_system::Call::<T>::remark(vec![]);
+		let call = frame_system::Call::<T>::remark { remark: vec![] };
 		Lottery::<T>::buy_ticket(RawOrigin::Signed(winner.clone()).into(), Box::new(call.into()))?;
 		// Kill user account for worst case
 		T::Currency::make_free_balance_be(&winner, 0u32.into());
@@ -146,7 +146,7 @@ benchmarks! {
 		let lottery_account = Lottery::<T>::account_id();
 		T::Currency::make_free_balance_be(&lottery_account, T::Currency::minimum_balance() * 10u32.into());
 		// Buy a ticket
-		let call = frame_system::Call::<T>::remark(vec![]);
+		let call = frame_system::Call::<T>::remark { remark: vec![] };
 		Lottery::<T>::buy_ticket(RawOrigin::Signed(winner.clone()).into(), Box::new(call.into()))?;
 		// Kill user account for worst case
 		T::Currency::make_free_balance_be(&winner, 0u32.into());
diff --git a/substrate/frame/lottery/src/lib.rs b/substrate/frame/lottery/src/lib.rs
index c879a819b0b79279288a0ee95703048b244f91f0..260b4c2d76ae9f8e32cbcd15f82aa2a6f7e2fcb9 100644
--- a/substrate/frame/lottery/src/lib.rs
+++ b/substrate/frame/lottery/src/lib.rs
@@ -76,7 +76,7 @@ type BalanceOf<T> =
 // We use this to uniquely match someone's incoming call with the calls configured for the lottery.
 type CallIndex = (u8, u8);
 
-#[derive(Encode, Decode, Default, Eq, PartialEq, RuntimeDebug)]
+#[derive(Encode, Decode, Default, Eq, PartialEq, RuntimeDebug, scale_info::TypeInfo)]
 pub struct LotteryConfig<BlockNumber, Balance> {
 	/// Price per entry.
 	price: Balance,
@@ -170,7 +170,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId", BalanceOf<T> = "Balance")]
 	pub enum Event<T: Config> {
 		/// A lottery has been started!
 		LotteryStarted,
diff --git a/substrate/frame/lottery/src/tests.rs b/substrate/frame/lottery/src/tests.rs
index 9cc4c582943e38d50e8ff51c903ab7efa1fae760..623beea4a6b5bb635c8a15cd417ee8181299adb1 100644
--- a/substrate/frame/lottery/src/tests.rs
+++ b/substrate/frame/lottery/src/tests.rs
@@ -43,8 +43,8 @@ fn basic_end_to_end_works() {
 		let length = 20;
 		let delay = 5;
 		let calls = vec![
-			Call::Balances(BalancesCall::force_transfer(0, 0, 0)),
-			Call::Balances(BalancesCall::transfer(0, 0)),
+			Call::Balances(BalancesCall::force_transfer { source: 0, dest: 0, value: 0 }),
+			Call::Balances(BalancesCall::transfer { dest: 0, value: 0 }),
 		];
 
 		// Set calls for the lottery
@@ -55,7 +55,7 @@ fn basic_end_to_end_works() {
 		assert!(crate::Lottery::<Test>::get().is_some());
 
 		assert_eq!(Balances::free_balance(&1), 100);
-		let call = Box::new(Call::Balances(BalancesCall::transfer(2, 20)));
+		let call = Box::new(Call::Balances(BalancesCall::transfer { dest: 2, value: 20 }));
 		assert_ok!(Lottery::buy_ticket(Origin::signed(1), call.clone()));
 		// 20 from the transfer, 10 from buying a ticket
 		assert_eq!(Balances::free_balance(&1), 100 - 20 - 10);
@@ -96,17 +96,17 @@ fn set_calls_works() {
 		assert!(!CallIndices::<Test>::exists());
 
 		let calls = vec![
-			Call::Balances(BalancesCall::force_transfer(0, 0, 0)),
-			Call::Balances(BalancesCall::transfer(0, 0)),
+			Call::Balances(BalancesCall::force_transfer { source: 0, dest: 0, value: 0 }),
+			Call::Balances(BalancesCall::transfer { dest: 0, value: 0 }),
 		];
 
 		assert_ok!(Lottery::set_calls(Origin::root(), calls));
 		assert!(CallIndices::<Test>::exists());
 
 		let too_many_calls = vec![
-			Call::Balances(BalancesCall::force_transfer(0, 0, 0)),
-			Call::Balances(BalancesCall::transfer(0, 0)),
-			Call::System(SystemCall::remark(vec![])),
+			Call::Balances(BalancesCall::force_transfer { source: 0, dest: 0, value: 0 }),
+			Call::Balances(BalancesCall::transfer { dest: 0, value: 0 }),
+			Call::System(SystemCall::remark { remark: vec![] }),
 		];
 
 		assert_noop!(
@@ -150,7 +150,7 @@ fn buy_ticket_works_as_simple_passthrough() {
 	// as a simple passthrough to the real call.
 	new_test_ext().execute_with(|| {
 		// No lottery set up
-		let call = Box::new(Call::Balances(BalancesCall::transfer(2, 20)));
+		let call = Box::new(Call::Balances(BalancesCall::transfer { dest: 2, value: 20 }));
 		// This is just a basic transfer then
 		assert_ok!(Lottery::buy_ticket(Origin::signed(1), call.clone()));
 		assert_eq!(Balances::free_balance(&1), 100 - 20);
@@ -158,8 +158,8 @@ fn buy_ticket_works_as_simple_passthrough() {
 
 		// Lottery is set up, but too expensive to enter, so `do_buy_ticket` fails.
 		let calls = vec![
-			Call::Balances(BalancesCall::force_transfer(0, 0, 0)),
-			Call::Balances(BalancesCall::transfer(0, 0)),
+			Call::Balances(BalancesCall::force_transfer { source: 0, dest: 0, value: 0 }),
+			Call::Balances(BalancesCall::transfer { dest: 0, value: 0 }),
 		];
 		assert_ok!(Lottery::set_calls(Origin::root(), calls));
 
@@ -170,21 +170,24 @@ fn buy_ticket_works_as_simple_passthrough() {
 		assert_eq!(TicketsCount::<Test>::get(), 0);
 
 		// If call would fail, the whole thing still fails the same
-		let fail_call = Box::new(Call::Balances(BalancesCall::transfer(2, 1000)));
+		let fail_call = Box::new(Call::Balances(BalancesCall::transfer { dest: 2, value: 1000 }));
 		assert_noop!(
 			Lottery::buy_ticket(Origin::signed(1), fail_call),
 			BalancesError::<Test, _>::InsufficientBalance,
 		);
 
-		let bad_origin_call = Box::new(Call::Balances(BalancesCall::force_transfer(0, 0, 0)));
-		assert_noop!(Lottery::buy_ticket(Origin::signed(1), bad_origin_call), BadOrigin);
+		let bad_origin_call =
+			Box::new(Call::Balances(BalancesCall::force_transfer { source: 0, dest: 0, value: 0 }));
+		assert_noop!(Lottery::buy_ticket(Origin::signed(1), bad_origin_call), BadOrigin,);
 
 		// User can call other txs, but doesn't get a ticket
-		let remark_call = Box::new(Call::System(SystemCall::remark(b"hello, world!".to_vec())));
+		let remark_call =
+			Box::new(Call::System(SystemCall::remark { remark: b"hello, world!".to_vec() }));
 		assert_ok!(Lottery::buy_ticket(Origin::signed(2), remark_call));
 		assert_eq!(TicketsCount::<Test>::get(), 0);
 
-		let successful_call = Box::new(Call::Balances(BalancesCall::transfer(2, 1)));
+		let successful_call =
+			Box::new(Call::Balances(BalancesCall::transfer { dest: 2, value: 1 }));
 		assert_ok!(Lottery::buy_ticket(Origin::signed(2), successful_call));
 		assert_eq!(TicketsCount::<Test>::get(), 1);
 	});
@@ -195,13 +198,13 @@ fn buy_ticket_works() {
 	new_test_ext().execute_with(|| {
 		// Set calls for the lottery.
 		let calls = vec![
-			Call::System(SystemCall::remark(vec![])),
-			Call::Balances(BalancesCall::transfer(0, 0)),
+			Call::System(SystemCall::remark { remark: vec![] }),
+			Call::Balances(BalancesCall::transfer { dest: 0, value: 0 }),
 		];
 		assert_ok!(Lottery::set_calls(Origin::root(), calls));
 
 		// Can't buy ticket before start
-		let call = Box::new(Call::Balances(BalancesCall::transfer(2, 1)));
+		let call = Box::new(Call::Balances(BalancesCall::transfer { dest: 2, value: 1 }));
 		assert_ok!(Lottery::buy_ticket(Origin::signed(1), call.clone()));
 		assert_eq!(TicketsCount::<Test>::get(), 0);
 
@@ -214,12 +217,12 @@ fn buy_ticket_works() {
 		assert_eq!(TicketsCount::<Test>::get(), 1);
 
 		// Can't buy another of the same ticket (even if call is slightly changed)
-		let call = Box::new(Call::Balances(BalancesCall::transfer(3, 30)));
+		let call = Box::new(Call::Balances(BalancesCall::transfer { dest: 3, value: 30 }));
 		assert_ok!(Lottery::buy_ticket(Origin::signed(1), call));
 		assert_eq!(TicketsCount::<Test>::get(), 1);
 
 		// Buy ticket for remark
-		let call = Box::new(Call::System(SystemCall::remark(b"hello, world!".to_vec())));
+		let call = Box::new(Call::System(SystemCall::remark { remark: b"hello, world!".to_vec() }));
 		assert_ok!(Lottery::buy_ticket(Origin::signed(1), call.clone()));
 		assert_eq!(TicketsCount::<Test>::get(), 2);
 
diff --git a/substrate/frame/membership/Cargo.toml b/substrate/frame/membership/Cargo.toml
index 8136b818eac8ef46263c0f1a61ad4d3813848e02..acc82f7678de64313d828edae3ad412fbd31ccda 100644
--- a/substrate/frame/membership/Cargo.toml
+++ b/substrate/frame/membership/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 log = { version = "0.4.0", default-features = false }
 
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
@@ -29,6 +30,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"log/std",
 	"sp-core/std",
 	"sp-io/std",
diff --git a/substrate/frame/membership/src/lib.rs b/substrate/frame/membership/src/lib.rs
index b66dc51b3b0ec50ab2e2ea3f7f6a594c0f7c2c87..7922d9efaf5699baae322f67353af3ff2818335d 100644
--- a/substrate/frame/membership/src/lib.rs
+++ b/substrate/frame/membership/src/lib.rs
@@ -131,9 +131,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(
-		PhantomData<(T::AccountId, <T as Config<I>>::Event)> = "sp_std::marker::PhantomData<(AccountId, Event)>",
-	)]
 	pub enum Event<T: Config<I>, I: 'static = ()> {
 		/// The given member was added; see the transaction for who.
 		MemberAdded,
diff --git a/substrate/frame/merkle-mountain-range/Cargo.toml b/substrate/frame/merkle-mountain-range/Cargo.toml
index eecdfd7a9e841252557f8a7ec849843356bef5fa..02b4be182ef82035c27488d79e9a52f0b71c4e3a 100644
--- a/substrate/frame/merkle-mountain-range/Cargo.toml
+++ b/substrate/frame/merkle-mountain-range/Cargo.toml
@@ -13,6 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 mmr-lib = { package = "ckb-merkle-mountain-range", default-features = false, version = "0.3.1" }
 
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
@@ -34,6 +35,7 @@ hex-literal = "0.3"
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"mmr-lib/std",
 	"sp-core/std",
 	"sp-io/std",
diff --git a/substrate/frame/merkle-mountain-range/src/lib.rs b/substrate/frame/merkle-mountain-range/src/lib.rs
index 83fdc5b1715c915a375ce4dbb216d0d4ecc6a074..01bf1b2254f09f5286f8763e8d9c0aa36bc85f0e 100644
--- a/substrate/frame/merkle-mountain-range/src/lib.rs
+++ b/substrate/frame/merkle-mountain-range/src/lib.rs
@@ -124,7 +124,8 @@ pub mod pallet {
 			+ Copy
 			+ Default
 			+ codec::Codec
-			+ codec::EncodeLike;
+			+ codec::EncodeLike
+			+ scale_info::TypeInfo;
 
 		/// Data stored in the leaf nodes.
 		///
diff --git a/substrate/frame/metadata/Cargo.toml b/substrate/frame/metadata/Cargo.toml
deleted file mode 100644
index 332ce5b70c26eadcf9c378ff6b7be53ae441e1ab..0000000000000000000000000000000000000000
--- a/substrate/frame/metadata/Cargo.toml
+++ /dev/null
@@ -1,28 +0,0 @@
-[package]
-name = "frame-metadata"
-version = "14.0.0-dev"
-authors = ["Parity Technologies <admin@parity.io>"]
-edition = "2018"
-license = "Apache-2.0"
-homepage = "https://substrate.dev"
-repository = "https://github.com/paritytech/substrate/"
-description = "Decodable variant of the RuntimeMetadata."
-readme = "README.md"
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
-
-[dependencies]
-codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
-serde = { version = "1.0.126", optional = true, features = ["derive"] }
-sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
-sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
-
-[features]
-default = ["std"]
-std = [
-	"codec/std",
-	"sp-std/std",
-	"sp-core/std",
-	"serde",
-]
diff --git a/substrate/frame/metadata/README.md b/substrate/frame/metadata/README.md
deleted file mode 100644
index 423af8602e3f013fa4632e62da9399bd1901806e..0000000000000000000000000000000000000000
--- a/substrate/frame/metadata/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-Decodable variant of the RuntimeMetadata.
-
-This really doesn't belong here, but is necessary for the moment. In the future
-it should be removed entirely to an external module for shimming on to the
-codec-encoded metadata.
-
-License: Apache-2.0
\ No newline at end of file
diff --git a/substrate/frame/metadata/src/lib.rs b/substrate/frame/metadata/src/lib.rs
deleted file mode 100644
index 7dcf5932df28361b5e6d19c268ef35cba43e5ef0..0000000000000000000000000000000000000000
--- a/substrate/frame/metadata/src/lib.rs
+++ /dev/null
@@ -1,466 +0,0 @@
-// This file is part of Substrate.
-
-// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd.
-// SPDX-License-Identifier: Apache-2.0
-
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// 	http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//! Decodable variant of the RuntimeMetadata.
-//!
-//! This really doesn't belong here, but is necessary for the moment. In the future
-//! it should be removed entirely to an external module for shimming on to the
-//! codec-encoded metadata.
-
-#![cfg_attr(not(feature = "std"), no_std)]
-
-#[cfg(feature = "std")]
-use codec::{Decode, Error, Input};
-use codec::{Encode, Output};
-#[cfg(feature = "std")]
-use serde::Serialize;
-use sp_core::RuntimeDebug;
-use sp_std::vec::Vec;
-
-#[cfg(feature = "std")]
-type StringBuf = String;
-
-/// Current prefix of metadata
-pub const META_RESERVED: u32 = 0x6174656d; // 'meta' warn endianness
-
-/// On `no_std` we do not support `Decode` and thus `StringBuf` is just `&'static str`.
-/// So, if someone tries to decode this stuff on `no_std`, they will get a compilation error.
-#[cfg(not(feature = "std"))]
-type StringBuf = &'static str;
-
-/// A type that decodes to a different type than it encodes.
-/// The user needs to make sure that both types use the same encoding.
-///
-/// For example a `&'static [ &'static str ]` can be decoded to a `Vec<String>`.
-#[derive(Clone)]
-pub enum DecodeDifferent<B, O>
-where
-	B: 'static,
-	O: 'static,
-{
-	Encode(B),
-	Decoded(O),
-}
-
-impl<B, O> Encode for DecodeDifferent<B, O>
-where
-	B: Encode + 'static,
-	O: Encode + 'static,
-{
-	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
-		match self {
-			DecodeDifferent::Encode(b) => b.encode_to(dest),
-			DecodeDifferent::Decoded(o) => o.encode_to(dest),
-		}
-	}
-}
-
-impl<B, O> codec::EncodeLike for DecodeDifferent<B, O>
-where
-	B: Encode + 'static,
-	O: Encode + 'static,
-{
-}
-
-#[cfg(feature = "std")]
-impl<B, O> Decode for DecodeDifferent<B, O>
-where
-	B: 'static,
-	O: Decode + 'static,
-{
-	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
-		<O>::decode(input).map(|val| DecodeDifferent::Decoded(val))
-	}
-}
-
-impl<B, O> PartialEq for DecodeDifferent<B, O>
-where
-	B: Encode + Eq + PartialEq + 'static,
-	O: Encode + Eq + PartialEq + 'static,
-{
-	fn eq(&self, other: &Self) -> bool {
-		self.encode() == other.encode()
-	}
-}
-
-impl<B, O> Eq for DecodeDifferent<B, O>
-where
-	B: Encode + Eq + PartialEq + 'static,
-	O: Encode + Eq + PartialEq + 'static,
-{
-}
-
-impl<B, O> sp_std::fmt::Debug for DecodeDifferent<B, O>
-where
-	B: sp_std::fmt::Debug + Eq + 'static,
-	O: sp_std::fmt::Debug + Eq + 'static,
-{
-	fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
-		match self {
-			DecodeDifferent::Encode(b) => b.fmt(f),
-			DecodeDifferent::Decoded(o) => o.fmt(f),
-		}
-	}
-}
-
-#[cfg(feature = "std")]
-impl<B, O> serde::Serialize for DecodeDifferent<B, O>
-where
-	B: serde::Serialize + 'static,
-	O: serde::Serialize + 'static,
-{
-	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-	where
-		S: serde::Serializer,
-	{
-		match self {
-			DecodeDifferent::Encode(b) => b.serialize(serializer),
-			DecodeDifferent::Decoded(o) => o.serialize(serializer),
-		}
-	}
-}
-
-pub type DecodeDifferentArray<B, O = B> = DecodeDifferent<&'static [B], Vec<O>>;
-
-type DecodeDifferentStr = DecodeDifferent<&'static str, StringBuf>;
-
-/// All the metadata about a function.
-#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub struct FunctionMetadata {
-	pub name: DecodeDifferentStr,
-	pub arguments: DecodeDifferentArray<FunctionArgumentMetadata>,
-	pub documentation: DecodeDifferentArray<&'static str, StringBuf>,
-}
-
-/// All the metadata about a function argument.
-#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub struct FunctionArgumentMetadata {
-	pub name: DecodeDifferentStr,
-	pub ty: DecodeDifferentStr,
-}
-
-/// Newtype wrapper for support encoding functions (actual the result of the function).
-#[derive(Clone, Eq)]
-pub struct FnEncode<E>(pub fn() -> E)
-where
-	E: Encode + 'static;
-
-impl<E: Encode> Encode for FnEncode<E> {
-	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
-		self.0().encode_to(dest);
-	}
-}
-
-impl<E: Encode> codec::EncodeLike for FnEncode<E> {}
-
-impl<E: Encode + PartialEq> PartialEq for FnEncode<E> {
-	fn eq(&self, other: &Self) -> bool {
-		self.0().eq(&other.0())
-	}
-}
-
-impl<E: Encode + sp_std::fmt::Debug> sp_std::fmt::Debug for FnEncode<E> {
-	fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
-		self.0().fmt(f)
-	}
-}
-
-#[cfg(feature = "std")]
-impl<E: Encode + serde::Serialize> serde::Serialize for FnEncode<E> {
-	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-	where
-		S: serde::Serializer,
-	{
-		self.0().serialize(serializer)
-	}
-}
-
-/// All the metadata about an outer event.
-#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub struct OuterEventMetadata {
-	pub name: DecodeDifferentStr,
-	pub events: DecodeDifferentArray<
-		(&'static str, FnEncode<&'static [EventMetadata]>),
-		(StringBuf, Vec<EventMetadata>),
-	>,
-}
-
-/// All the metadata about an event.
-#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub struct EventMetadata {
-	pub name: DecodeDifferentStr,
-	pub arguments: DecodeDifferentArray<&'static str, StringBuf>,
-	pub documentation: DecodeDifferentArray<&'static str, StringBuf>,
-}
-
-/// All the metadata about one storage entry.
-#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub struct StorageEntryMetadata {
-	pub name: DecodeDifferentStr,
-	pub modifier: StorageEntryModifier,
-	pub ty: StorageEntryType,
-	pub default: ByteGetter,
-	pub documentation: DecodeDifferentArray<&'static str, StringBuf>,
-}
-
-/// All the metadata about one module constant.
-#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub struct ModuleConstantMetadata {
-	pub name: DecodeDifferentStr,
-	pub ty: DecodeDifferentStr,
-	pub value: ByteGetter,
-	pub documentation: DecodeDifferentArray<&'static str, StringBuf>,
-}
-
-/// All the metadata about a module error.
-#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub struct ErrorMetadata {
-	pub name: DecodeDifferentStr,
-	pub documentation: DecodeDifferentArray<&'static str, StringBuf>,
-}
-
-/// All the metadata about errors in a module.
-pub trait ModuleErrorMetadata {
-	fn metadata() -> &'static [ErrorMetadata];
-}
-
-impl ModuleErrorMetadata for &'static str {
-	fn metadata() -> &'static [ErrorMetadata] {
-		&[]
-	}
-}
-
-/// A technical trait to store lazy initiated vec value as static dyn pointer.
-pub trait DefaultByte: Send + Sync {
-	fn default_byte(&self) -> Vec<u8>;
-}
-
-/// Wrapper over dyn pointer for accessing a cached once byte value.
-#[derive(Clone)]
-pub struct DefaultByteGetter(pub &'static dyn DefaultByte);
-
-/// Decode different for static lazy initiated byte value.
-pub type ByteGetter = DecodeDifferent<DefaultByteGetter, Vec<u8>>;
-
-impl Encode for DefaultByteGetter {
-	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
-		self.0.default_byte().encode_to(dest)
-	}
-}
-
-impl codec::EncodeLike for DefaultByteGetter {}
-
-impl PartialEq<DefaultByteGetter> for DefaultByteGetter {
-	fn eq(&self, other: &DefaultByteGetter) -> bool {
-		let left = self.0.default_byte();
-		let right = other.0.default_byte();
-		left.eq(&right)
-	}
-}
-
-impl Eq for DefaultByteGetter {}
-
-#[cfg(feature = "std")]
-impl serde::Serialize for DefaultByteGetter {
-	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-	where
-		S: serde::Serializer,
-	{
-		self.0.default_byte().serialize(serializer)
-	}
-}
-
-impl sp_std::fmt::Debug for DefaultByteGetter {
-	fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
-		self.0.default_byte().fmt(f)
-	}
-}
-
-/// Hasher used by storage maps
-#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub enum StorageHasher {
-	Blake2_128,
-	Blake2_256,
-	Blake2_128Concat,
-	Twox128,
-	Twox256,
-	Twox64Concat,
-	Identity,
-}
-
-/// A storage entry type.
-#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub enum StorageEntryType {
-	Plain(DecodeDifferentStr),
-	Map {
-		hasher: StorageHasher,
-		key: DecodeDifferentStr,
-		value: DecodeDifferentStr,
-		// is_linked flag previously, unused now to keep backwards compat
-		unused: bool,
-	},
-	DoubleMap {
-		hasher: StorageHasher,
-		key1: DecodeDifferentStr,
-		key2: DecodeDifferentStr,
-		value: DecodeDifferentStr,
-		key2_hasher: StorageHasher,
-	},
-	NMap {
-		keys: DecodeDifferentArray<&'static str, StringBuf>,
-		hashers: DecodeDifferentArray<StorageHasher>,
-		value: DecodeDifferentStr,
-	},
-}
-
-/// A storage entry modifier.
-#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub enum StorageEntryModifier {
-	Optional,
-	Default,
-}
-
-/// All metadata of the storage.
-#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub struct StorageMetadata {
-	/// The common prefix used by all storage entries.
-	pub prefix: DecodeDifferent<&'static str, StringBuf>,
-	pub entries: DecodeDifferent<&'static [StorageEntryMetadata], Vec<StorageEntryMetadata>>,
-}
-
-/// Metadata prefixed by a u32 for reserved usage
-#[derive(Eq, Encode, PartialEq, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub struct RuntimeMetadataPrefixed(pub u32, pub RuntimeMetadata);
-
-/// Metadata of the extrinsic used by the runtime.
-#[derive(Eq, Encode, PartialEq, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub struct ExtrinsicMetadata {
-	/// Extrinsic version.
-	pub version: u8,
-	/// The signed extensions in the order they appear in the extrinsic.
-	pub signed_extensions: Vec<DecodeDifferentStr>,
-}
-
-/// The metadata of a runtime.
-/// The version ID encoded/decoded through
-/// the enum nature of `RuntimeMetadata`.
-#[derive(Eq, Encode, PartialEq, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub enum RuntimeMetadata {
-	/// Unused; enum filler.
-	V0(RuntimeMetadataDeprecated),
-	/// Version 1 for runtime metadata. No longer used.
-	V1(RuntimeMetadataDeprecated),
-	/// Version 2 for runtime metadata. No longer used.
-	V2(RuntimeMetadataDeprecated),
-	/// Version 3 for runtime metadata. No longer used.
-	V3(RuntimeMetadataDeprecated),
-	/// Version 4 for runtime metadata. No longer used.
-	V4(RuntimeMetadataDeprecated),
-	/// Version 5 for runtime metadata. No longer used.
-	V5(RuntimeMetadataDeprecated),
-	/// Version 6 for runtime metadata. No longer used.
-	V6(RuntimeMetadataDeprecated),
-	/// Version 7 for runtime metadata. No longer used.
-	V7(RuntimeMetadataDeprecated),
-	/// Version 8 for runtime metadata. No longer used.
-	V8(RuntimeMetadataDeprecated),
-	/// Version 9 for runtime metadata. No longer used.
-	V9(RuntimeMetadataDeprecated),
-	/// Version 10 for runtime metadata. No longer used.
-	V10(RuntimeMetadataDeprecated),
-	/// Version 11 for runtime metadata. No longer used.
-	V11(RuntimeMetadataDeprecated),
-	/// Version 12 for runtime metadata. No longer used.
-	V12(RuntimeMetadataDeprecated),
-	/// Version 13 for runtime metadata.
-	V13(RuntimeMetadataV13),
-}
-
-/// Enum that should fail.
-#[derive(Eq, PartialEq, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Serialize))]
-pub enum RuntimeMetadataDeprecated {}
-
-impl Encode for RuntimeMetadataDeprecated {
-	fn encode_to<W: Output + ?Sized>(&self, _dest: &mut W) {}
-}
-
-impl codec::EncodeLike for RuntimeMetadataDeprecated {}
-
-#[cfg(feature = "std")]
-impl Decode for RuntimeMetadataDeprecated {
-	fn decode<I: Input>(_input: &mut I) -> Result<Self, Error> {
-		Err("Decoding is not supported".into())
-	}
-}
-
-/// The metadata of a runtime.
-#[derive(Eq, Encode, PartialEq, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub struct RuntimeMetadataV13 {
-	/// Metadata of all the modules.
-	pub modules: DecodeDifferentArray<ModuleMetadata>,
-	/// Metadata of the extrinsic.
-	pub extrinsic: ExtrinsicMetadata,
-}
-
-/// The latest version of the metadata.
-pub type RuntimeMetadataLastVersion = RuntimeMetadataV13;
-
-/// All metadata about an runtime module.
-#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)]
-#[cfg_attr(feature = "std", derive(Decode, Serialize))]
-pub struct ModuleMetadata {
-	pub name: DecodeDifferentStr,
-	pub storage: Option<DecodeDifferent<FnEncode<StorageMetadata>, StorageMetadata>>,
-	pub calls: ODFnA<FunctionMetadata>,
-	pub event: ODFnA<EventMetadata>,
-	pub constants: DFnA<ModuleConstantMetadata>,
-	pub errors: DFnA<ErrorMetadata>,
-	/// Define the index of the module, this index will be used for the encoding of module event,
-	/// call and origin variants.
-	pub index: u8,
-}
-
-type ODFnA<T> = Option<DFnA<T>>;
-type DFnA<T> = DecodeDifferent<FnEncode<&'static [T]>, Vec<T>>;
-
-impl Into<sp_core::OpaqueMetadata> for RuntimeMetadataPrefixed {
-	fn into(self) -> sp_core::OpaqueMetadata {
-		sp_core::OpaqueMetadata::new(self.encode())
-	}
-}
-
-impl Into<RuntimeMetadataPrefixed> for RuntimeMetadataLastVersion {
-	fn into(self) -> RuntimeMetadataPrefixed {
-		RuntimeMetadataPrefixed(META_RESERVED, RuntimeMetadata::V13(self))
-	}
-}
diff --git a/substrate/frame/multisig/Cargo.toml b/substrate/frame/multisig/Cargo.toml
index 84314256499a30e4160527c0b7a9094c04e532ee..177334d4ccf8de32dae498c9f63d60ae689d9181 100644
--- a/substrate/frame/multisig/Cargo.toml
+++ b/substrate/frame/multisig/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -30,6 +31,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-runtime/std",
 	"frame-support/std",
 	"frame-system/std",
diff --git a/substrate/frame/multisig/src/benchmarking.rs b/substrate/frame/multisig/src/benchmarking.rs
index 6847036ce4716497925c0b5513a5a1a7fa7a384d..2e23dff156e0774e7a2b6230c68b2f495a031c5e 100644
--- a/substrate/frame/multisig/src/benchmarking.rs
+++ b/substrate/frame/multisig/src/benchmarking.rs
@@ -40,7 +40,8 @@ fn setup_multi<T: Config>(s: u32, z: u32) -> Result<(Vec<T::AccountId>, Vec<u8>)
 	}
 	signatories.sort();
 	// Must first convert to outer call type.
-	let call: <T as Config>::Call = frame_system::Call::<T>::remark(vec![0; z as usize]).into();
+	let call: <T as Config>::Call =
+		frame_system::Call::<T>::remark { remark: vec![0; z as usize] }.into();
 	let call_data = call.encode();
 	return Ok((signatories, call_data))
 }
@@ -51,7 +52,9 @@ benchmarks! {
 		let z in 0 .. 10_000;
 		let max_signatories = T::MaxSignatories::get().into();
 		let (mut signatories, _) = setup_multi::<T>(max_signatories, z)?;
-		let call: <T as Config>::Call = frame_system::Call::<T>::remark(vec![0; z as usize]).into();
+		let call: <T as Config>::Call = frame_system::Call::<T>::remark {
+			remark: vec![0; z as usize]
+		}.into();
 		let call_hash = call.using_encoded(blake2_256);
 		let multi_account_id = Multisig::<T>::multi_account_id(&signatories, 1);
 		let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
diff --git a/substrate/frame/multisig/src/lib.rs b/substrate/frame/multisig/src/lib.rs
index b1ef5f11a5e36ad6ccecb3e60efe94f55fb468e5..43040ada45a98e7223e76acf212f061c20d53df2 100644
--- a/substrate/frame/multisig/src/lib.rs
+++ b/substrate/frame/multisig/src/lib.rs
@@ -61,6 +61,7 @@ use frame_support::{
 	RuntimeDebug,
 };
 use frame_system::{self as system, RawOrigin};
+use scale_info::TypeInfo;
 use sp_io::hashing::blake2_256;
 use sp_runtime::{
 	traits::{Dispatchable, Zero},
@@ -79,7 +80,7 @@ pub type OpaqueCall = Vec<u8>;
 /// A global extrinsic index, formed as the extrinsic index within a block, together with that
 /// block's height. This allows a transaction in which a multisig operation of a particular
 /// composite was created to be uniquely identified.
-#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug)]
+#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo)]
 pub struct Timepoint<BlockNumber> {
 	/// The height of the chain at the point in time.
 	height: BlockNumber,
@@ -88,7 +89,7 @@ pub struct Timepoint<BlockNumber> {
 }
 
 /// An open multisig operation.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo)]
 pub struct Multisig<BlockNumber, Balance, AccountId> {
 	/// The extrinsic when the multisig operation was opened.
 	when: Timepoint<BlockNumber>,
@@ -203,11 +204,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(
-		T::AccountId = "AccountId",
-		T::BlockNumber = "BlockNumber",
-		Timepoint<T::BlockNumber> = "Timepoint<BlockNumber>"
-	)]
 	pub enum Event<T: Config> {
 		/// A new multisig operation has begun. \[approving, multisig, call_hash\]
 		NewMultisig(T::AccountId, T::AccountId, CallHash),
diff --git a/substrate/frame/multisig/src/tests.rs b/substrate/frame/multisig/src/tests.rs
index 2809a106d66ea9872ff047f9103f10d013903e3a..3d311cf5d3dc800263d1c2598192bfa7af183f6b 100644
--- a/substrate/frame/multisig/src/tests.rs
+++ b/substrate/frame/multisig/src/tests.rs
@@ -99,7 +99,7 @@ impl Contains<Call> for TestBaseCallFilter {
 		match *c {
 			Call::Balances(_) => true,
 			// Needed for benchmarking
-			Call::System(frame_system::Call::remark(_)) => true,
+			Call::System(frame_system::Call::remark { .. }) => true,
 			_ => false,
 		}
 	}
@@ -132,6 +132,10 @@ fn now() -> Timepoint<u64> {
 	Multisig::timepoint()
 }
 
+fn call_transfer(dest: u64, value: u64) -> Call {
+	Call::Balances(BalancesCall::transfer { dest, value })
+}
+
 #[test]
 fn multisig_deposit_is_taken_and_returned() {
 	new_test_ext().execute_with(|| {
@@ -140,7 +144,7 @@ fn multisig_deposit_is_taken_and_returned() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call = Call::Balances(BalancesCall::transfer(6, 15));
+		let call = call_transfer(6, 15);
 		let call_weight = call.get_dispatch_info().weight;
 		let data = call.encode();
 		assert_ok!(Multisig::as_multi(
@@ -177,7 +181,7 @@ fn multisig_deposit_is_taken_and_returned_with_call_storage() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call = Call::Balances(BalancesCall::transfer(6, 15));
+		let call = call_transfer(6, 15);
 		let call_weight = call.get_dispatch_info().weight;
 		let data = call.encode();
 		let hash = blake2_256(&data);
@@ -206,7 +210,7 @@ fn multisig_deposit_is_taken_and_returned_with_alt_call_storage() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call = Call::Balances(BalancesCall::transfer(6, 15));
+		let call = call_transfer(6, 15);
 		let call_weight = call.get_dispatch_info().weight;
 		let data = call.encode();
 		let hash = blake2_256(&data);
@@ -254,7 +258,7 @@ fn multisig_deposit_is_taken_and_returned_with_alt_call_storage() {
 #[test]
 fn cancel_multisig_returns_deposit() {
 	new_test_ext().execute_with(|| {
-		let call = Call::Balances(BalancesCall::transfer(6, 15)).encode();
+		let call = call_transfer(6, 15).encode();
 		let hash = blake2_256(&call);
 		assert_ok!(Multisig::approve_as_multi(
 			Origin::signed(1),
@@ -294,7 +298,7 @@ fn timepoint_checking_works() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call = Call::Balances(BalancesCall::transfer(6, 15)).encode();
+		let call = call_transfer(6, 15).encode();
 		let hash = blake2_256(&call);
 
 		assert_noop!(
@@ -339,7 +343,7 @@ fn multisig_2_of_3_works_with_call_storing() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call = Call::Balances(BalancesCall::transfer(6, 15));
+		let call = call_transfer(6, 15);
 		let call_weight = call.get_dispatch_info().weight;
 		let data = call.encode();
 		let hash = blake2_256(&data);
@@ -366,7 +370,7 @@ fn multisig_2_of_3_works() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call = Call::Balances(BalancesCall::transfer(6, 15));
+		let call = call_transfer(6, 15);
 		let call_weight = call.get_dispatch_info().weight;
 		let data = call.encode();
 		let hash = blake2_256(&data);
@@ -394,7 +398,7 @@ fn multisig_3_of_3_works() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call = Call::Balances(BalancesCall::transfer(6, 15));
+		let call = call_transfer(6, 15);
 		let call_weight = call.get_dispatch_info().weight;
 		let data = call.encode();
 		let hash = blake2_256(&data);
@@ -432,7 +436,7 @@ fn multisig_3_of_3_works() {
 #[test]
 fn cancel_multisig_works() {
 	new_test_ext().execute_with(|| {
-		let call = Call::Balances(BalancesCall::transfer(6, 15)).encode();
+		let call = call_transfer(6, 15).encode();
 		let hash = blake2_256(&call);
 		assert_ok!(Multisig::approve_as_multi(
 			Origin::signed(1),
@@ -467,7 +471,7 @@ fn cancel_multisig_works() {
 #[test]
 fn cancel_multisig_with_call_storage_works() {
 	new_test_ext().execute_with(|| {
-		let call = Call::Balances(BalancesCall::transfer(6, 15)).encode();
+		let call = call_transfer(6, 15).encode();
 		let hash = blake2_256(&call);
 		assert_ok!(Multisig::as_multi(Origin::signed(1), 3, vec![2, 3], None, call, true, 0));
 		assert_eq!(Balances::free_balance(1), 4);
@@ -497,7 +501,7 @@ fn cancel_multisig_with_call_storage_works() {
 #[test]
 fn cancel_multisig_with_alt_call_storage_works() {
 	new_test_ext().execute_with(|| {
-		let call = Call::Balances(BalancesCall::transfer(6, 15)).encode();
+		let call = call_transfer(6, 15).encode();
 		let hash = blake2_256(&call);
 		assert_ok!(Multisig::approve_as_multi(
 			Origin::signed(1),
@@ -532,7 +536,7 @@ fn multisig_2_of_3_as_multi_works() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call = Call::Balances(BalancesCall::transfer(6, 15));
+		let call = call_transfer(6, 15);
 		let call_weight = call.get_dispatch_info().weight;
 		let data = call.encode();
 		assert_ok!(Multisig::as_multi(
@@ -567,10 +571,10 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call1 = Call::Balances(BalancesCall::transfer(6, 10));
+		let call1 = call_transfer(6, 10);
 		let call1_weight = call1.get_dispatch_info().weight;
 		let data1 = call1.encode();
-		let call2 = Call::Balances(BalancesCall::transfer(7, 5));
+		let call2 = call_transfer(7, 5);
 		let call2_weight = call2.get_dispatch_info().weight;
 		let data2 = call2.encode();
 
@@ -624,7 +628,7 @@ fn multisig_2_of_3_cannot_reissue_same_call() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call = Call::Balances(BalancesCall::transfer(6, 10));
+		let call = call_transfer(6, 10);
 		let call_weight = call.get_dispatch_info().weight;
 		let data = call.encode();
 		let hash = blake2_256(&data);
@@ -677,7 +681,7 @@ fn multisig_2_of_3_cannot_reissue_same_call() {
 #[test]
 fn minimum_threshold_check_works() {
 	new_test_ext().execute_with(|| {
-		let call = Call::Balances(BalancesCall::transfer(6, 15)).encode();
+		let call = call_transfer(6, 15).encode();
 		assert_noop!(
 			Multisig::as_multi(Origin::signed(1), 0, vec![2], None, call.clone(), false, 0),
 			Error::<Test>::MinimumThreshold,
@@ -692,7 +696,7 @@ fn minimum_threshold_check_works() {
 #[test]
 fn too_many_signatories_fails() {
 	new_test_ext().execute_with(|| {
-		let call = Call::Balances(BalancesCall::transfer(6, 15)).encode();
+		let call = call_transfer(6, 15).encode();
 		assert_noop!(
 			Multisig::as_multi(Origin::signed(1), 2, vec![2, 3, 4], None, call.clone(), false, 0),
 			Error::<Test>::TooManySignatories,
@@ -703,7 +707,7 @@ fn too_many_signatories_fails() {
 #[test]
 fn duplicate_approvals_are_ignored() {
 	new_test_ext().execute_with(|| {
-		let call = Call::Balances(BalancesCall::transfer(6, 15)).encode();
+		let call = call_transfer(6, 15).encode();
 		let hash = blake2_256(&call);
 		assert_ok!(Multisig::approve_as_multi(
 			Origin::signed(1),
@@ -754,7 +758,7 @@ fn multisig_1_of_3_works() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call = Call::Balances(BalancesCall::transfer(6, 15)).encode();
+		let call = call_transfer(6, 15).encode();
 		let hash = blake2_256(&call);
 		assert_noop!(
 			Multisig::approve_as_multi(Origin::signed(1), 1, vec![2, 3], None, hash.clone(), 0),
@@ -764,7 +768,7 @@ fn multisig_1_of_3_works() {
 			Multisig::as_multi(Origin::signed(1), 1, vec![2, 3], None, call.clone(), false, 0),
 			Error::<Test>::MinimumThreshold,
 		);
-		let boxed_call = Box::new(Call::Balances(BalancesCall::transfer(6, 15)));
+		let boxed_call = Box::new(call_transfer(6, 15));
 		assert_ok!(Multisig::as_multi_threshold_1(Origin::signed(1), vec![2, 3], boxed_call));
 
 		assert_eq!(Balances::free_balance(6), 15);
@@ -774,7 +778,7 @@ fn multisig_1_of_3_works() {
 #[test]
 fn multisig_filters() {
 	new_test_ext().execute_with(|| {
-		let call = Box::new(Call::System(frame_system::Call::set_code(vec![])));
+		let call = Box::new(Call::System(frame_system::Call::set_code { code: vec![] }));
 		assert_noop!(
 			Multisig::as_multi_threshold_1(Origin::signed(1), vec![2], call.clone()),
 			DispatchError::BadOrigin,
@@ -790,7 +794,7 @@ fn weight_check_works() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call = Call::Balances(BalancesCall::transfer(6, 15));
+		let call = call_transfer(6, 15);
 		let data = call.encode();
 		assert_ok!(Multisig::as_multi(
 			Origin::signed(1),
@@ -821,7 +825,7 @@ fn multisig_handles_no_preimage_after_all_approve() {
 		assert_ok!(Balances::transfer(Origin::signed(2), multi, 5));
 		assert_ok!(Balances::transfer(Origin::signed(3), multi, 5));
 
-		let call = Call::Balances(BalancesCall::transfer(6, 15));
+		let call = call_transfer(6, 15);
 		let call_weight = call.get_dispatch_info().weight;
 		let data = call.encode();
 		let hash = blake2_256(&data);
diff --git a/substrate/frame/nicks/Cargo.toml b/substrate/frame/nicks/Cargo.toml
index 02e64491650cd093b0b22727700127c0caf4615f..431ee2c84157cce61a01b3a137f238c5fa5e2294 100644
--- a/substrate/frame/nicks/Cargo.toml
+++ b/substrate/frame/nicks/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -28,6 +29,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-io/std",
 	"sp-runtime/std",
diff --git a/substrate/frame/nicks/src/lib.rs b/substrate/frame/nicks/src/lib.rs
index a5c22b619a5eb7142419fa7e8f9779b46e7b286d..16c7e2042dda059a1efd5e978e99d955f107c8d5 100644
--- a/substrate/frame/nicks/src/lib.rs
+++ b/substrate/frame/nicks/src/lib.rs
@@ -91,7 +91,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId", BalanceOf<T> = "Balance")]
 	pub enum Event<T: Config> {
 		/// A name was set. \[who\]
 		NameSet(T::AccountId),
diff --git a/substrate/frame/node-authorization/Cargo.toml b/substrate/frame/node-authorization/Cargo.toml
index 35b02747e40068a2ab52cf091ce40fad23c149c7..635e72e3a8b8a1b6fb774b6157a6f7dc11cf51b3 100644
--- a/substrate/frame/node-authorization/Cargo.toml
+++ b/substrate/frame/node-authorization/Cargo.toml
@@ -13,6 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
@@ -25,6 +26,7 @@ log = { version = "0.4.14", default-features = false }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"frame-support/std",
 	"frame-system/std",
 	"sp-core/std",
diff --git a/substrate/frame/node-authorization/src/lib.rs b/substrate/frame/node-authorization/src/lib.rs
index 5551ec2ad2c40da704ccd9429db47fd9b725ef28..016f12d2eb8381d5736cb97ca941b4bcd1efa204 100644
--- a/substrate/frame/node-authorization/src/lib.rs
+++ b/substrate/frame/node-authorization/src/lib.rs
@@ -126,7 +126,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId")]
 	pub enum Event<T: Config> {
 		/// The given well known node was added.
 		NodeAdded(PeerId, T::AccountId),
diff --git a/substrate/frame/offences/Cargo.toml b/substrate/frame/offences/Cargo.toml
index c4295747d649f1cad813886669d0a3f770644d5b..8fdcbf46fa3e122b9704ce83ad8c4827d89decbf 100644
--- a/substrate/frame/offences/Cargo.toml
+++ b/substrate/frame/offences/Cargo.toml
@@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 serde = { version = "1.0.126", optional = true }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -32,6 +33,7 @@ default = ["std"]
 std = [
 	"pallet-balances/std",
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"serde",
 	"sp-runtime/std",
diff --git a/substrate/frame/offences/benchmarking/Cargo.toml b/substrate/frame/offences/benchmarking/Cargo.toml
index dc408ee8121dd3d09d25962d6071b6b493bc7902..b21e6cf9b7e13bc5ffecbda7e6b39e025a712d86 100644
--- a/substrate/frame/offences/benchmarking/Cargo.toml
+++ b/substrate/frame/offences/benchmarking/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" }
@@ -57,4 +58,5 @@ std = [
 	"frame-election-provider-support/std",
 	"sp-std/std",
 	"codec/std",
+	"scale-info/std",
 ]
diff --git a/substrate/frame/proxy/Cargo.toml b/substrate/frame/proxy/Cargo.toml
index 22edf1f3c20ac85622562e8b4fae7989a53635e6..83db82990d105b33b5d24b4d5456df385a3ac5ce 100644
--- a/substrate/frame/proxy/Cargo.toml
+++ b/substrate/frame/proxy/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["max-encoded-len"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
@@ -31,6 +32,7 @@ pallet-utility = { version = "4.0.0-dev", path = "../utility" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-runtime/std",
 	"frame-support/std",
 	"frame-system/std",
diff --git a/substrate/frame/proxy/src/benchmarking.rs b/substrate/frame/proxy/src/benchmarking.rs
index 77cdff11de9ce32ce94a595be63a79ce2b186435..e66f6782c19e1f0120d28324268854ca33b046ff 100644
--- a/substrate/frame/proxy/src/benchmarking.rs
+++ b/substrate/frame/proxy/src/benchmarking.rs
@@ -83,7 +83,7 @@ benchmarks! {
 		T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
 		// ... and "real" is the traditional caller. This is not a typo.
 		let real: T::AccountId = whitelisted_caller();
-		let call: <T as Config>::Call = frame_system::Call::<T>::remark(vec![]).into();
+		let call: <T as Config>::Call = frame_system::Call::<T>::remark { remark: vec![] }.into();
 	}: _(RawOrigin::Signed(caller), real, Some(T::ProxyType::default()), Box::new(call))
 	verify {
 		assert_last_event::<T>(Event::ProxyExecuted(Ok(())).into())
@@ -98,7 +98,7 @@ benchmarks! {
 		T::Currency::make_free_balance_be(&delegate, BalanceOf::<T>::max_value());
 		// ... and "real" is the traditional caller. This is not a typo.
 		let real: T::AccountId = whitelisted_caller();
-		let call: <T as Config>::Call = frame_system::Call::<T>::remark(vec![]).into();
+		let call: <T as Config>::Call = frame_system::Call::<T>::remark { remark: vec![] }.into();
 		Proxy::<T>::announce(
 			RawOrigin::Signed(delegate.clone()).into(),
 			real.clone(),
@@ -118,7 +118,7 @@ benchmarks! {
 		T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
 		// ... and "real" is the traditional caller. This is not a typo.
 		let real: T::AccountId = whitelisted_caller();
-		let call: <T as Config>::Call = frame_system::Call::<T>::remark(vec![]).into();
+		let call: <T as Config>::Call = frame_system::Call::<T>::remark { remark: vec![] }.into();
 		Proxy::<T>::announce(
 			RawOrigin::Signed(caller.clone()).into(),
 			real.clone(),
@@ -139,7 +139,7 @@ benchmarks! {
 		T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
 		// ... and "real" is the traditional caller. This is not a typo.
 		let real: T::AccountId = whitelisted_caller();
-		let call: <T as Config>::Call = frame_system::Call::<T>::remark(vec![]).into();
+		let call: <T as Config>::Call = frame_system::Call::<T>::remark { remark: vec![] }.into();
 		Proxy::<T>::announce(
 			RawOrigin::Signed(caller.clone()).into(),
 			real.clone(),
@@ -161,7 +161,7 @@ benchmarks! {
 		// ... and "real" is the traditional caller. This is not a typo.
 		let real: T::AccountId = whitelisted_caller();
 		add_announcements::<T>(a, Some(caller.clone()), None)?;
-		let call: <T as Config>::Call = frame_system::Call::<T>::remark(vec![]).into();
+		let call: <T as Config>::Call = frame_system::Call::<T>::remark { remark: vec![] }.into();
 		let call_hash = T::CallHasher::hash_of(&call);
 	}: _(RawOrigin::Signed(caller.clone()), real.clone(), call_hash)
 	verify {
diff --git a/substrate/frame/proxy/src/lib.rs b/substrate/frame/proxy/src/lib.rs
index 0537ed4a323929bf00b3a680e3a824e29261a5f3..b73101fa73486e34d343fde51256aa1d4ad1a822 100644
--- a/substrate/frame/proxy/src/lib.rs
+++ b/substrate/frame/proxy/src/lib.rs
@@ -42,6 +42,7 @@ use frame_support::{
 	RuntimeDebug,
 };
 use frame_system::{self as system};
+use scale_info::TypeInfo;
 use sp_io::hashing::blake2_256;
 use sp_runtime::{
 	traits::{Dispatchable, Hash, Saturating, Zero},
@@ -60,7 +61,17 @@ type BalanceOf<T> =
 /// The parameters under which a particular account has a proxy relationship with some other
 /// account.
 #[derive(
-	Encode, Decode, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug, MaxEncodedLen,
+	Encode,
+	Decode,
+	Clone,
+	Copy,
+	Eq,
+	PartialEq,
+	Ord,
+	PartialOrd,
+	RuntimeDebug,
+	MaxEncodedLen,
+	TypeInfo,
 )]
 pub struct ProxyDefinition<AccountId, ProxyType, BlockNumber> {
 	/// The account which may act on behalf of another.
@@ -73,7 +84,7 @@ pub struct ProxyDefinition<AccountId, ProxyType, BlockNumber> {
 }
 
 /// Details surrounding a specific instance of an announcement to make a call.
-#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, RuntimeDebug, MaxEncodedLen)]
+#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 pub struct Announcement<AccountId, Hash, BlockNumber> {
 	/// The account which made the announcement.
 	real: AccountId,
@@ -534,12 +545,6 @@ pub mod pallet {
 	}
 
 	#[pallet::event]
-	#[pallet::metadata(
-		T::AccountId = "AccountId",
-		T::ProxyType = "ProxyType",
-		CallHashOf<T> = "Hash",
-		T::BlockNumber = "BlockNumber",
-	)]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
 		/// A proxy was executed correctly, with the given \[result\].
@@ -782,12 +787,13 @@ impl<T: Config> Pallet<T> {
 			match c.is_sub_type() {
 				// Proxy call cannot add or remove a proxy with more permissions than it already
 				// has.
-				Some(Call::add_proxy(_, ref pt, _)) | Some(Call::remove_proxy(_, ref pt, _))
-					if !def.proxy_type.is_superset(&pt) =>
+				Some(Call::add_proxy { ref proxy_type, .. }) |
+				Some(Call::remove_proxy { ref proxy_type, .. })
+					if !def.proxy_type.is_superset(&proxy_type) =>
 					false,
 				// Proxy call cannot remove all proxies or kill anonymous proxies unless it has full
 				// permissions.
-				Some(Call::remove_proxies(..)) | Some(Call::kill_anonymous(..))
+				Some(Call::remove_proxies { .. }) | Some(Call::kill_anonymous { .. })
 					if def.proxy_type != T::ProxyType::default() =>
 					false,
 				_ => def.proxy_type.filter(c),
diff --git a/substrate/frame/proxy/src/tests.rs b/substrate/frame/proxy/src/tests.rs
index eb4193a18d9355b0cb57f1cd9534e2aff47607a6..d319ebb1a5ab0f486be786c80f7dd5178c10355b 100644
--- a/substrate/frame/proxy/src/tests.rs
+++ b/substrate/frame/proxy/src/tests.rs
@@ -107,7 +107,17 @@ parameter_types! {
 	pub const AnnouncementDepositFactor: u64 = 1;
 }
 #[derive(
-	Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen,
+	Copy,
+	Clone,
+	Eq,
+	PartialEq,
+	Ord,
+	PartialOrd,
+	Encode,
+	Decode,
+	RuntimeDebug,
+	MaxEncodedLen,
+	scale_info::TypeInfo,
 )]
 pub enum ProxyType {
 	Any,
@@ -124,9 +134,9 @@ impl InstanceFilter<Call> for ProxyType {
 		match self {
 			ProxyType::Any => true,
 			ProxyType::JustTransfer => {
-				matches!(c, Call::Balances(pallet_balances::Call::transfer(..)))
+				matches!(c, Call::Balances(pallet_balances::Call::transfer { .. }))
 			},
-			ProxyType::JustUtility => matches!(c, Call::Utility(..)),
+			ProxyType::JustUtility => matches!(c, Call::Utility { .. }),
 		}
 	}
 	fn is_superset(&self, o: &Self) -> bool {
@@ -138,7 +148,7 @@ impl Contains<Call> for BaseFilter {
 	fn contains(c: &Call) -> bool {
 		match *c {
 			// Remark is used as a no-op call in the benchmarking
-			Call::System(SystemCall::remark(_)) => true,
+			Call::System(SystemCall::remark { .. }) => true,
 			Call::System(_) => false,
 			_ => true,
 		}
@@ -190,6 +200,10 @@ fn expect_events(e: Vec<Event>) {
 	assert_eq!(last_events(e.len()), e);
 }
 
+fn call_transfer(dest: u64, value: u64) -> Call {
+	Call::Balances(BalancesCall::transfer { dest, value })
+}
+
 #[test]
 fn announcement_works() {
 	new_test_ext().execute_with(|| {
@@ -272,7 +286,7 @@ fn announcer_must_be_proxy() {
 fn delayed_requires_pre_announcement() {
 	new_test_ext().execute_with(|| {
 		assert_ok!(Proxy::add_proxy(Origin::signed(1), 2, ProxyType::Any, 1));
-		let call = Box::new(Call::Balances(BalancesCall::transfer(6, 1)));
+		let call = Box::new(call_transfer(6, 1));
 		let e = Error::<Test>::Unannounced;
 		assert_noop!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()), e);
 		let e = Error::<Test>::Unannounced;
@@ -289,7 +303,7 @@ fn proxy_announced_removes_announcement_and_returns_deposit() {
 	new_test_ext().execute_with(|| {
 		assert_ok!(Proxy::add_proxy(Origin::signed(1), 3, ProxyType::Any, 1));
 		assert_ok!(Proxy::add_proxy(Origin::signed(2), 3, ProxyType::Any, 1));
-		let call = Box::new(Call::Balances(BalancesCall::transfer(6, 1)));
+		let call = Box::new(call_transfer(6, 1));
 		let call_hash = BlakeTwo256::hash_of(&call);
 		assert_ok!(Proxy::announce(Origin::signed(3), 1, call_hash));
 		assert_ok!(Proxy::announce(Origin::signed(3), 2, call_hash));
@@ -313,7 +327,7 @@ fn filtering_works() {
 		assert_ok!(Proxy::add_proxy(Origin::signed(1), 3, ProxyType::JustTransfer, 0));
 		assert_ok!(Proxy::add_proxy(Origin::signed(1), 4, ProxyType::JustUtility, 0));
 
-		let call = Box::new(Call::Balances(BalancesCall::transfer(6, 1)));
+		let call = Box::new(call_transfer(6, 1));
 		assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
 		System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into());
 		assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
@@ -323,9 +337,10 @@ fn filtering_works() {
 
 		let derivative_id = Utility::derivative_account_id(1, 0);
 		assert!(Balances::mutate_account(&derivative_id, |a| a.free = 1000).is_ok());
-		let inner = Box::new(Call::Balances(BalancesCall::transfer(6, 1)));
+		let inner = Box::new(call_transfer(6, 1));
 
-		let call = Box::new(Call::Utility(UtilityCall::as_derivative(0, inner.clone())));
+		let call =
+			Box::new(Call::Utility(UtilityCall::as_derivative { index: 0, call: inner.clone() }));
 		assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
 		System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into());
 		assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
@@ -333,7 +348,7 @@ fn filtering_works() {
 		assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
 		System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into());
 
-		let call = Box::new(Call::Utility(UtilityCall::batch(vec![*inner])));
+		let call = Box::new(Call::Utility(UtilityCall::batch { calls: vec![*inner] }));
 		assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
 		expect_events(vec![
 			UtilityEvent::BatchCompleted.into(),
@@ -347,8 +362,9 @@ fn filtering_works() {
 			ProxyEvent::ProxyExecuted(Ok(())).into(),
 		]);
 
-		let inner = Box::new(Call::Proxy(ProxyCall::add_proxy(5, ProxyType::Any, 0)));
-		let call = Box::new(Call::Utility(UtilityCall::batch(vec![*inner])));
+		let inner =
+			Box::new(Call::Proxy(ProxyCall::new_call_variant_add_proxy(5, ProxyType::Any, 0)));
+		let call = Box::new(Call::Utility(UtilityCall::batch { calls: vec![*inner] }));
 		assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
 		expect_events(vec![
 			UtilityEvent::BatchCompleted.into(),
@@ -362,7 +378,7 @@ fn filtering_works() {
 			ProxyEvent::ProxyExecuted(Ok(())).into(),
 		]);
 
-		let call = Box::new(Call::Proxy(ProxyCall::remove_proxies()));
+		let call = Box::new(Call::Proxy(ProxyCall::remove_proxies {}));
 		assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
 		System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into());
 		assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
@@ -431,7 +447,7 @@ fn proxying_works() {
 		assert_ok!(Proxy::add_proxy(Origin::signed(1), 2, ProxyType::JustTransfer, 0));
 		assert_ok!(Proxy::add_proxy(Origin::signed(1), 3, ProxyType::Any, 0));
 
-		let call = Box::new(Call::Balances(BalancesCall::transfer(6, 1)));
+		let call = Box::new(call_transfer(6, 1));
 		assert_noop!(
 			Proxy::proxy(Origin::signed(4), 1, None, call.clone()),
 			Error::<Test>::NotProxy
@@ -444,14 +460,14 @@ fn proxying_works() {
 		System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into());
 		assert_eq!(Balances::free_balance(6), 1);
 
-		let call = Box::new(Call::System(SystemCall::set_code(vec![])));
+		let call = Box::new(Call::System(SystemCall::set_code { code: vec![] }));
 		assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
 		System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into());
 
-		let call = Box::new(Call::Balances(BalancesCall::transfer_keep_alive(6, 1)));
-		assert_ok!(
-			Call::Proxy(super::Call::proxy(1, None, call.clone())).dispatch(Origin::signed(2))
-		);
+		let call =
+			Box::new(Call::Balances(BalancesCall::transfer_keep_alive { dest: 6, value: 1 }));
+		assert_ok!(Call::Proxy(super::Call::new_call_variant_proxy(1, None, call.clone()))
+			.dispatch(Origin::signed(2)));
 		System::assert_last_event(ProxyEvent::ProxyExecuted(Err(DispatchError::BadOrigin)).into());
 		assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
 		System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into());
@@ -483,13 +499,19 @@ fn anonymous_works() {
 		System::set_block_number(2);
 		assert_ok!(Proxy::anonymous(Origin::signed(1), ProxyType::Any, 0, 0));
 
-		let call = Box::new(Call::Balances(BalancesCall::transfer(6, 1)));
+		let call = Box::new(call_transfer(6, 1));
 		assert_ok!(Balances::transfer(Origin::signed(3), anon, 5));
 		assert_ok!(Proxy::proxy(Origin::signed(1), anon, None, call));
 		System::assert_last_event(ProxyEvent::ProxyExecuted(Ok(())).into());
 		assert_eq!(Balances::free_balance(6), 1);
 
-		let call = Box::new(Call::Proxy(ProxyCall::kill_anonymous(1, ProxyType::Any, 0, 1, 0)));
+		let call = Box::new(Call::Proxy(ProxyCall::new_call_variant_kill_anonymous(
+			1,
+			ProxyType::Any,
+			0,
+			1,
+			0,
+		)));
 		assert_ok!(Proxy::proxy(Origin::signed(2), anon2, None, call.clone()));
 		let de = DispatchError::from(Error::<Test>::NoPermission).stripped();
 		System::assert_last_event(ProxyEvent::ProxyExecuted(Err(de)).into());
diff --git a/substrate/frame/randomness-collective-flip/Cargo.toml b/substrate/frame/randomness-collective-flip/Cargo.toml
index 016d56142ecad73dd1e1fd5af008f11816b72abe..5e8eb6b0828794df5267ad88a3832e8dbdb11279 100644
--- a/substrate/frame/randomness-collective-flip/Cargo.toml
+++ b/substrate/frame/randomness-collective-flip/Cargo.toml
@@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 safe-mix = { version = "1.0", default-features = false }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 
@@ -30,6 +31,7 @@ default = ["std"]
 std = [
 	"safe-mix/std",
 	"codec/std",
+	"scale-info/std",
 	"sp-runtime/std",
 	"sp-std/std",
 	"frame-system/std",
diff --git a/substrate/frame/recovery/Cargo.toml b/substrate/frame/recovery/Cargo.toml
index b8601d0852f6305c650d2c1081575a6653c3a2dd..40a89e9b59f895d0d509d1abd665d1492cbe7f4e 100644
--- a/substrate/frame/recovery/Cargo.toml
+++ b/substrate/frame/recovery/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -28,6 +29,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-io/std",
 	"sp-runtime/std",
diff --git a/substrate/frame/recovery/src/lib.rs b/substrate/frame/recovery/src/lib.rs
index ad61baae60c9698ba65a01959a733dc597ede1db..797581788077bf6b576bd0357b5e0e3c21bf9592 100644
--- a/substrate/frame/recovery/src/lib.rs
+++ b/substrate/frame/recovery/src/lib.rs
@@ -155,6 +155,7 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 use sp_runtime::traits::{CheckedAdd, CheckedMul, Dispatchable, SaturatedConversion};
 use sp_std::prelude::*;
 
@@ -176,7 +177,7 @@ type BalanceOf<T> =
 	<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
 
 /// An active recovery process.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo)]
 pub struct ActiveRecovery<BlockNumber, Balance, AccountId> {
 	/// The block number when the recovery process started.
 	created: BlockNumber,
@@ -188,7 +189,7 @@ pub struct ActiveRecovery<BlockNumber, Balance, AccountId> {
 }
 
 /// Configuration for recovering an account.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo)]
 pub struct RecoveryConfig<BlockNumber, Balance, AccountId> {
 	/// The minimum number of blocks since the start of the recovery process before the account
 	/// can be recovered.
@@ -260,7 +261,6 @@ pub mod pallet {
 	/// Events type.
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId")]
 	pub enum Event<T: Config> {
 		/// A recovery process has been set up for an \[account\].
 		RecoveryCreated(T::AccountId),
diff --git a/substrate/frame/recovery/src/tests.rs b/substrate/frame/recovery/src/tests.rs
index 122088bf5ed6342d5a4941b5c8170c23bc80e3cb..fe971319bc97cc6cc13b5f9c1cf9dd90f313f4bc 100644
--- a/substrate/frame/recovery/src/tests.rs
+++ b/substrate/frame/recovery/src/tests.rs
@@ -44,7 +44,7 @@ fn set_recovered_works() {
 		// Root can set a recovered account though
 		assert_ok!(Recovery::set_recovered(Origin::root(), 5, 1));
 		// Account 1 should now be able to make a call through account 5
-		let call = Box::new(Call::Balances(BalancesCall::transfer(1, 100)));
+		let call = Box::new(Call::Balances(BalancesCall::transfer { dest: 1, value: 100 }));
 		assert_ok!(Recovery::as_recovered(Origin::signed(1), 5, call));
 		// Account 1 has successfully drained the funds from account 5
 		assert_eq!(Balances::free_balance(1), 200);
@@ -76,15 +76,15 @@ fn recovery_life_cycle_works() {
 		assert_ok!(Recovery::claim_recovery(Origin::signed(1), 5));
 		// Account 1 can use account 5 to close the active recovery process, claiming the deposited
 		// funds used to initiate the recovery process into account 5.
-		let call = Box::new(Call::Recovery(RecoveryCall::close_recovery(1)));
+		let call = Box::new(Call::Recovery(RecoveryCall::close_recovery { rescuer: 1 }));
 		assert_ok!(Recovery::as_recovered(Origin::signed(1), 5, call));
 		// Account 1 can then use account 5 to remove the recovery configuration, claiming the
 		// deposited funds used to create the recovery configuration into account 5.
-		let call = Box::new(Call::Recovery(RecoveryCall::remove_recovery()));
+		let call = Box::new(Call::Recovery(RecoveryCall::remove_recovery {}));
 		assert_ok!(Recovery::as_recovered(Origin::signed(1), 5, call));
 		// Account 1 should now be able to make a call through account 5 to get all of their funds
 		assert_eq!(Balances::free_balance(5), 110);
-		let call = Box::new(Call::Balances(BalancesCall::transfer(1, 110)));
+		let call = Box::new(Call::Balances(BalancesCall::transfer { dest: 1, value: 110 }));
 		assert_ok!(Recovery::as_recovered(Origin::signed(1), 5, call));
 		// All funds have been fully recovered!
 		assert_eq!(Balances::free_balance(1), 200);
diff --git a/substrate/frame/scheduler/Cargo.toml b/substrate/frame/scheduler/Cargo.toml
index 93f76b2369f2c670f5eb698b6911af2fa8665194..62b21fe04c9dfa11293e0c789547ad61756513cc 100644
--- a/substrate/frame/scheduler/Cargo.toml
+++ b/substrate/frame/scheduler/Cargo.toml
@@ -11,6 +11,7 @@ readme = "README.md"
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -28,6 +29,7 @@ substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-runtime/std",
 	"frame-benchmarking/std",
 	"frame-support/std",
diff --git a/substrate/frame/scheduler/src/benchmarking.rs b/substrate/frame/scheduler/src/benchmarking.rs
index c122bed71b1fd2c5b870b7d755ce8ce281eaf643..2c164eaede22987f633b6d3230f8de2242431b4b 100644
--- a/substrate/frame/scheduler/src/benchmarking.rs
+++ b/substrate/frame/scheduler/src/benchmarking.rs
@@ -33,7 +33,7 @@ const BLOCK_NUMBER: u32 = 2;
 // Add `n` named items to the schedule
 fn fill_schedule<T: Config>(when: T::BlockNumber, n: u32) -> Result<(), &'static str> {
 	// Essentially a no-op call.
-	let call = frame_system::Call::set_storage(vec![]);
+	let call = frame_system::Call::set_storage { items: vec![] };
 	for i in 0..n {
 		// Named schedule is strictly heavier than anonymous
 		Scheduler::<T>::do_schedule_named(
@@ -58,7 +58,7 @@ benchmarks! {
 		let periodic = Some((T::BlockNumber::one(), 100));
 		let priority = 0;
 		// Essentially a no-op call.
-		let call = Box::new(frame_system::Call::set_storage(vec![]).into());
+		let call = Box::new(frame_system::Call::set_storage { items: vec![] }.into());
 
 		fill_schedule::<T>(when, s)?;
 	}: _(RawOrigin::Root, when, periodic, priority, call)
@@ -95,7 +95,7 @@ benchmarks! {
 		let periodic = Some((T::BlockNumber::one(), 100));
 		let priority = 0;
 		// Essentially a no-op call.
-		let call = Box::new(frame_system::Call::set_storage(vec![]).into());
+		let call = Box::new(frame_system::Call::set_storage { items: vec![] }.into());
 
 		fill_schedule::<T>(when, s)?;
 	}: _(RawOrigin::Root, id, when, periodic, priority, call)
diff --git a/substrate/frame/scheduler/src/lib.rs b/substrate/frame/scheduler/src/lib.rs
index ceb163a432e7b8cfdb2cbd1ce2d3b95951013912..ca9e15812a76d4a2d4e7bfff7967e72a878166c8 100644
--- a/substrate/frame/scheduler/src/lib.rs
+++ b/substrate/frame/scheduler/src/lib.rs
@@ -64,6 +64,7 @@ use frame_support::{
 };
 use frame_system::{self as system, ensure_signed};
 pub use pallet::*;
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{BadOrigin, One, Saturating, Zero},
 	RuntimeDebug,
@@ -87,7 +88,7 @@ struct ScheduledV1<Call, BlockNumber> {
 
 /// Information regarding an item to be executed in the future.
 #[cfg_attr(any(feature = "std", test), derive(PartialEq, Eq))]
-#[derive(Clone, RuntimeDebug, Encode, Decode)]
+#[derive(Clone, RuntimeDebug, Encode, Decode, TypeInfo)]
 pub struct ScheduledV2<Call, BlockNumber, PalletsOrigin, AccountId> {
 	/// The unique identity for this task, if there is one.
 	maybe_id: Option<Vec<u8>>,
@@ -109,7 +110,7 @@ pub type Scheduled<Call, BlockNumber, PalletsOrigin, AccountId> =
 // A value placed in storage that represents the current version of the Scheduler storage.
 // This value is used by the `on_runtime_upgrade` logic to determine whether we run
 // storage migration logic.
-#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 enum Releases {
 	V1,
 	V2,
@@ -143,7 +144,7 @@ pub mod pallet {
 			+ IsType<<Self as system::Config>::Origin>;
 
 		/// The caller origin, overarching type of all pallets origins.
-		type PalletsOrigin: From<system::RawOrigin<Self::AccountId>> + Codec + Clone + Eq;
+		type PalletsOrigin: From<system::RawOrigin<Self::AccountId>> + Codec + Clone + Eq + TypeInfo;
 
 		/// The aggregated call type.
 		type Call: Parameter
@@ -192,7 +193,6 @@ pub mod pallet {
 	/// Events type.
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::BlockNumber = "BlockNumber", TaskAddress<T::BlockNumber> = "TaskAddress<BlockNumber>")]
 	pub enum Event<T: Config> {
 		/// Scheduled some task. \[when, index\]
 		Scheduled(T::BlockNumber, u32),
@@ -926,7 +926,7 @@ mod tests {
 	pub struct BaseFilter;
 	impl Contains<Call> for BaseFilter {
 		fn contains(call: &Call) -> bool {
-			!matches!(call, Call::Logger(LoggerCall::log(_, _)))
+			!matches!(call, Call::Logger(LoggerCall::log { .. }))
 		}
 	}
 
@@ -1004,7 +1004,7 @@ mod tests {
 	#[test]
 	fn basic_scheduling_works() {
 		new_test_ext().execute_with(|| {
-			let call = Call::Logger(LoggerCall::log(42, 1000));
+			let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 });
 			assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));
 			assert_ok!(Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call));
 			run_to_block(3);
@@ -1020,7 +1020,7 @@ mod tests {
 	fn schedule_after_works() {
 		new_test_ext().execute_with(|| {
 			run_to_block(2);
-			let call = Call::Logger(LoggerCall::log(42, 1000));
+			let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 });
 			assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));
 			// This will schedule the call 3 blocks after the next block... so block 3 + 3 = 6
 			assert_ok!(Scheduler::do_schedule(DispatchTime::After(3), None, 127, root(), call));
@@ -1037,7 +1037,7 @@ mod tests {
 	fn schedule_after_zero_works() {
 		new_test_ext().execute_with(|| {
 			run_to_block(2);
-			let call = Call::Logger(LoggerCall::log(42, 1000));
+			let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 });
 			assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));
 			assert_ok!(Scheduler::do_schedule(DispatchTime::After(0), None, 127, root(), call));
 			// Will trigger on the next block.
@@ -1057,7 +1057,7 @@ mod tests {
 				Some((3, 3)),
 				127,
 				root(),
-				Call::Logger(logger::Call::log(42, 1000))
+				Call::Logger(logger::Call::log { i: 42, weight: 1000 })
 			));
 			run_to_block(3);
 			assert!(logger::log().is_empty());
@@ -1079,7 +1079,7 @@ mod tests {
 	#[test]
 	fn reschedule_works() {
 		new_test_ext().execute_with(|| {
-			let call = Call::Logger(LoggerCall::log(42, 1000));
+			let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 });
 			assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));
 			assert_eq!(
 				Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call).unwrap(),
@@ -1110,7 +1110,7 @@ mod tests {
 	#[test]
 	fn reschedule_named_works() {
 		new_test_ext().execute_with(|| {
-			let call = Call::Logger(LoggerCall::log(42, 1000));
+			let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 });
 			assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));
 			assert_eq!(
 				Scheduler::do_schedule_named(
@@ -1152,7 +1152,7 @@ mod tests {
 	#[test]
 	fn reschedule_named_perodic_works() {
 		new_test_ext().execute_with(|| {
-			let call = Call::Logger(LoggerCall::log(42, 1000));
+			let call = Call::Logger(LoggerCall::log { i: 42, weight: 1000 });
 			assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));
 			assert_eq!(
 				Scheduler::do_schedule_named(
@@ -1214,7 +1214,7 @@ mod tests {
 				None,
 				127,
 				root(),
-				Call::Logger(LoggerCall::log(69, 1000)),
+				Call::Logger(LoggerCall::log { i: 69, weight: 1000 }),
 			)
 			.unwrap();
 			let i = Scheduler::do_schedule(
@@ -1222,7 +1222,7 @@ mod tests {
 				None,
 				127,
 				root(),
-				Call::Logger(LoggerCall::log(42, 1000)),
+				Call::Logger(LoggerCall::log { i: 42, weight: 1000 }),
 			)
 			.unwrap();
 			run_to_block(3);
@@ -1244,7 +1244,7 @@ mod tests {
 				Some((3, 3)),
 				127,
 				root(),
-				Call::Logger(LoggerCall::log(42, 1000)),
+				Call::Logger(LoggerCall::log { i: 42, weight: 1000 }),
 			)
 			.unwrap();
 			// same id results in error.
@@ -1254,7 +1254,7 @@ mod tests {
 				None,
 				127,
 				root(),
-				Call::Logger(LoggerCall::log(69, 1000))
+				Call::Logger(LoggerCall::log { i: 69, weight: 1000 })
 			)
 			.is_err());
 			// different id is ok.
@@ -1264,7 +1264,7 @@ mod tests {
 				None,
 				127,
 				root(),
-				Call::Logger(LoggerCall::log(69, 1000)),
+				Call::Logger(LoggerCall::log { i: 69, weight: 1000 }),
 			)
 			.unwrap();
 			run_to_block(3);
@@ -1286,14 +1286,14 @@ mod tests {
 				None,
 				127,
 				root(),
-				Call::Logger(LoggerCall::log(42, MaximumSchedulerWeight::get() / 2))
+				Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 2 })
 			));
 			assert_ok!(Scheduler::do_schedule(
 				DispatchTime::At(4),
 				None,
 				127,
 				root(),
-				Call::Logger(LoggerCall::log(69, MaximumSchedulerWeight::get() / 2))
+				Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 })
 			));
 			// 69 and 42 do not fit together
 			run_to_block(4);
@@ -1311,14 +1311,14 @@ mod tests {
 				None,
 				0,
 				root(),
-				Call::Logger(LoggerCall::log(42, MaximumSchedulerWeight::get() / 2))
+				Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 2 })
 			));
 			assert_ok!(Scheduler::do_schedule(
 				DispatchTime::At(4),
 				None,
 				0,
 				root(),
-				Call::Logger(LoggerCall::log(69, MaximumSchedulerWeight::get() / 2))
+				Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 })
 			));
 			// With base weights, 69 and 42 should not fit together, but do because of hard
 			// deadlines
@@ -1335,14 +1335,14 @@ mod tests {
 				None,
 				1,
 				root(),
-				Call::Logger(LoggerCall::log(42, MaximumSchedulerWeight::get() / 2))
+				Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 2 })
 			));
 			assert_ok!(Scheduler::do_schedule(
 				DispatchTime::At(4),
 				None,
 				0,
 				root(),
-				Call::Logger(LoggerCall::log(69, MaximumSchedulerWeight::get() / 2))
+				Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 })
 			));
 			run_to_block(4);
 			assert_eq!(logger::log(), vec![(root(), 69u32), (root(), 42u32)]);
@@ -1357,21 +1357,24 @@ mod tests {
 				None,
 				255,
 				root(),
-				Call::Logger(LoggerCall::log(42, MaximumSchedulerWeight::get() / 3))
+				Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 3 })
 			));
 			assert_ok!(Scheduler::do_schedule(
 				DispatchTime::At(4),
 				None,
 				127,
 				root(),
-				Call::Logger(LoggerCall::log(69, MaximumSchedulerWeight::get() / 2))
+				Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 })
 			));
 			assert_ok!(Scheduler::do_schedule(
 				DispatchTime::At(4),
 				None,
 				126,
 				root(),
-				Call::Logger(LoggerCall::log(2600, MaximumSchedulerWeight::get() / 2))
+				Call::Logger(LoggerCall::log {
+					i: 2600,
+					weight: MaximumSchedulerWeight::get() / 2
+				})
 			));
 
 			// 2600 does not fit with 69 or 42, but has higher priority, so will go through
@@ -1400,7 +1403,7 @@ mod tests {
 				None,
 				255,
 				root(),
-				Call::Logger(LoggerCall::log(3, MaximumSchedulerWeight::get() / 3))
+				Call::Logger(LoggerCall::log { i: 3, weight: MaximumSchedulerWeight::get() / 3 })
 			));
 			// Anon Periodic
 			assert_ok!(Scheduler::do_schedule(
@@ -1408,7 +1411,7 @@ mod tests {
 				Some((1000, 3)),
 				128,
 				root(),
-				Call::Logger(LoggerCall::log(42, MaximumSchedulerWeight::get() / 3))
+				Call::Logger(LoggerCall::log { i: 42, weight: MaximumSchedulerWeight::get() / 3 })
 			));
 			// Anon
 			assert_ok!(Scheduler::do_schedule(
@@ -1416,7 +1419,7 @@ mod tests {
 				None,
 				127,
 				root(),
-				Call::Logger(LoggerCall::log(69, MaximumSchedulerWeight::get() / 2))
+				Call::Logger(LoggerCall::log { i: 69, weight: MaximumSchedulerWeight::get() / 2 })
 			));
 			// Named Periodic
 			assert_ok!(Scheduler::do_schedule_named(
@@ -1425,7 +1428,10 @@ mod tests {
 				Some((1000, 3)),
 				126,
 				root(),
-				Call::Logger(LoggerCall::log(2600, MaximumSchedulerWeight::get() / 2))
+				Call::Logger(LoggerCall::log {
+					i: 2600,
+					weight: MaximumSchedulerWeight::get() / 2
+				})
 			));
 
 			// Will include the named periodic only
@@ -1469,8 +1475,8 @@ mod tests {
 	#[test]
 	fn root_calls_works() {
 		new_test_ext().execute_with(|| {
-			let call = Box::new(Call::Logger(LoggerCall::log(69, 1000)));
-			let call2 = Box::new(Call::Logger(LoggerCall::log(42, 1000)));
+			let call = Box::new(Call::Logger(LoggerCall::log { i: 69, weight: 1000 }));
+			let call2 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 }));
 			assert_ok!(Scheduler::schedule_named(
 				Origin::root(),
 				1u32.encode(),
@@ -1497,8 +1503,8 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			run_to_block(3);
 
-			let call = Box::new(Call::Logger(LoggerCall::log(69, 1000)));
-			let call2 = Box::new(Call::Logger(LoggerCall::log(42, 1000)));
+			let call = Box::new(Call::Logger(LoggerCall::log { i: 69, weight: 1000 }));
+			let call2 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 }));
 
 			assert_err!(
 				Scheduler::schedule_named(Origin::root(), 1u32.encode(), 2, None, 127, call),
@@ -1520,8 +1526,8 @@ mod tests {
 	#[test]
 	fn should_use_orign() {
 		new_test_ext().execute_with(|| {
-			let call = Box::new(Call::Logger(LoggerCall::log(69, 1000)));
-			let call2 = Box::new(Call::Logger(LoggerCall::log(42, 1000)));
+			let call = Box::new(Call::Logger(LoggerCall::log { i: 69, weight: 1000 }));
+			let call2 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 }));
 			assert_ok!(Scheduler::schedule_named(
 				system::RawOrigin::Signed(1).into(),
 				1u32.encode(),
@@ -1552,8 +1558,8 @@ mod tests {
 	#[test]
 	fn should_check_orign() {
 		new_test_ext().execute_with(|| {
-			let call = Box::new(Call::Logger(LoggerCall::log(69, 1000)));
-			let call2 = Box::new(Call::Logger(LoggerCall::log(42, 1000)));
+			let call = Box::new(Call::Logger(LoggerCall::log { i: 69, weight: 1000 }));
+			let call2 = Box::new(Call::Logger(LoggerCall::log { i: 42, weight: 1000 }));
 			assert_noop!(
 				Scheduler::schedule_named(
 					system::RawOrigin::Signed(2).into(),
@@ -1575,8 +1581,10 @@ mod tests {
 	#[test]
 	fn should_check_orign_for_cancel() {
 		new_test_ext().execute_with(|| {
-			let call = Box::new(Call::Logger(LoggerCall::log_without_filter(69, 1000)));
-			let call2 = Box::new(Call::Logger(LoggerCall::log_without_filter(42, 1000)));
+			let call =
+				Box::new(Call::Logger(LoggerCall::log_without_filter { i: 69, weight: 1000 }));
+			let call2 =
+				Box::new(Call::Logger(LoggerCall::log_without_filter { i: 42, weight: 1000 }));
 			assert_ok!(Scheduler::schedule_named(
 				system::RawOrigin::Signed(1).into(),
 				1u32.encode(),
@@ -1626,14 +1634,14 @@ mod tests {
 					Some(ScheduledV1 {
 						maybe_id: None,
 						priority: i as u8 + 10,
-						call: Call::Logger(LoggerCall::log(96, 100)),
+						call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }),
 						maybe_periodic: None,
 					}),
 					None,
 					Some(ScheduledV1 {
 						maybe_id: Some(b"test".to_vec()),
 						priority: 123,
-						call: Call::Logger(LoggerCall::log(69, 1000)),
+						call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }),
 						maybe_periodic: Some((456u64, 10)),
 					}),
 				];
@@ -1653,7 +1661,7 @@ mod tests {
 							Some(ScheduledV2 {
 								maybe_id: None,
 								priority: 10,
-								call: Call::Logger(LoggerCall::log(96, 100)),
+								call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }),
 								maybe_periodic: None,
 								origin: root(),
 								_phantom: PhantomData::<u64>::default(),
@@ -1662,7 +1670,7 @@ mod tests {
 							Some(ScheduledV2 {
 								maybe_id: Some(b"test".to_vec()),
 								priority: 123,
-								call: Call::Logger(LoggerCall::log(69, 1000)),
+								call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }),
 								maybe_periodic: Some((456u64, 10)),
 								origin: root(),
 								_phantom: PhantomData::<u64>::default(),
@@ -1675,7 +1683,7 @@ mod tests {
 							Some(ScheduledV2 {
 								maybe_id: None,
 								priority: 11,
-								call: Call::Logger(LoggerCall::log(96, 100)),
+								call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }),
 								maybe_periodic: None,
 								origin: root(),
 								_phantom: PhantomData::<u64>::default(),
@@ -1684,7 +1692,7 @@ mod tests {
 							Some(ScheduledV2 {
 								maybe_id: Some(b"test".to_vec()),
 								priority: 123,
-								call: Call::Logger(LoggerCall::log(69, 1000)),
+								call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }),
 								maybe_periodic: Some((456u64, 10)),
 								origin: root(),
 								_phantom: PhantomData::<u64>::default(),
@@ -1697,7 +1705,7 @@ mod tests {
 							Some(ScheduledV2 {
 								maybe_id: None,
 								priority: 12,
-								call: Call::Logger(LoggerCall::log(96, 100)),
+								call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }),
 								maybe_periodic: None,
 								origin: root(),
 								_phantom: PhantomData::<u64>::default(),
@@ -1706,7 +1714,7 @@ mod tests {
 							Some(ScheduledV2 {
 								maybe_id: Some(b"test".to_vec()),
 								priority: 123,
-								call: Call::Logger(LoggerCall::log(69, 1000)),
+								call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }),
 								maybe_periodic: Some((456u64, 10)),
 								origin: root(),
 								_phantom: PhantomData::<u64>::default(),
@@ -1729,7 +1737,7 @@ mod tests {
 					Some(Scheduled {
 						maybe_id: None,
 						priority: i as u8 + 10,
-						call: Call::Logger(LoggerCall::log(96, 100)),
+						call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }),
 						origin: 3u32,
 						maybe_periodic: None,
 						_phantom: Default::default(),
@@ -1739,7 +1747,7 @@ mod tests {
 						maybe_id: Some(b"test".to_vec()),
 						priority: 123,
 						origin: 2u32,
-						call: Call::Logger(LoggerCall::log(69, 1000)),
+						call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }),
 						maybe_periodic: Some((456u64, 10)),
 						_phantom: Default::default(),
 					}),
@@ -1768,7 +1776,7 @@ mod tests {
 							Some(ScheduledV2::<_, _, OriginCaller, u64> {
 								maybe_id: None,
 								priority: 10,
-								call: Call::Logger(LoggerCall::log(96, 100)),
+								call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }),
 								maybe_periodic: None,
 								origin: system::RawOrigin::Root.into(),
 								_phantom: PhantomData::<u64>::default(),
@@ -1777,7 +1785,7 @@ mod tests {
 							Some(ScheduledV2 {
 								maybe_id: Some(b"test".to_vec()),
 								priority: 123,
-								call: Call::Logger(LoggerCall::log(69, 1000)),
+								call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }),
 								maybe_periodic: Some((456u64, 10)),
 								origin: system::RawOrigin::None.into(),
 								_phantom: PhantomData::<u64>::default(),
@@ -1790,7 +1798,7 @@ mod tests {
 							Some(ScheduledV2 {
 								maybe_id: None,
 								priority: 11,
-								call: Call::Logger(LoggerCall::log(96, 100)),
+								call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }),
 								maybe_periodic: None,
 								origin: system::RawOrigin::Root.into(),
 								_phantom: PhantomData::<u64>::default(),
@@ -1799,7 +1807,7 @@ mod tests {
 							Some(ScheduledV2 {
 								maybe_id: Some(b"test".to_vec()),
 								priority: 123,
-								call: Call::Logger(LoggerCall::log(69, 1000)),
+								call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }),
 								maybe_periodic: Some((456u64, 10)),
 								origin: system::RawOrigin::None.into(),
 								_phantom: PhantomData::<u64>::default(),
@@ -1812,7 +1820,7 @@ mod tests {
 							Some(ScheduledV2 {
 								maybe_id: None,
 								priority: 12,
-								call: Call::Logger(LoggerCall::log(96, 100)),
+								call: Call::Logger(LoggerCall::log { i: 96, weight: 100 }),
 								maybe_periodic: None,
 								origin: system::RawOrigin::Root.into(),
 								_phantom: PhantomData::<u64>::default(),
@@ -1821,7 +1829,7 @@ mod tests {
 							Some(ScheduledV2 {
 								maybe_id: Some(b"test".to_vec()),
 								priority: 123,
-								call: Call::Logger(LoggerCall::log(69, 1000)),
+								call: Call::Logger(LoggerCall::log { i: 69, weight: 1000 }),
 								maybe_periodic: Some((456u64, 10)),
 								origin: system::RawOrigin::None.into(),
 								_phantom: PhantomData::<u64>::default(),
diff --git a/substrate/frame/scored-pool/Cargo.toml b/substrate/frame/scored-pool/Cargo.toml
index dc85e8d2ca811614be7981ed61f808c9199f43bf..9d5f156c175d5423fb1040033303b6c85e0a32e6 100644
--- a/substrate/frame/scored-pool/Cargo.toml
+++ b/substrate/frame/scored-pool/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
@@ -28,6 +29,7 @@ sp-core = { version = "4.0.0-dev", path = "../../primitives/core" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-io/std",
 	"sp-runtime/std",
 	"sp-std/std",
diff --git a/substrate/frame/scored-pool/src/lib.rs b/substrate/frame/scored-pool/src/lib.rs
index fc25004eda68d19f678e6783a4f802ce5c91121c..a5cdb6274f9956270de41142da2ca2a87f06f9ce 100644
--- a/substrate/frame/scored-pool/src/lib.rs
+++ b/substrate/frame/scored-pool/src/lib.rs
@@ -136,7 +136,8 @@ pub mod pallet {
 			+ Default
 			+ FullCodec
 			+ MaybeSerializeDeserialize
-			+ Debug;
+			+ Debug
+			+ scale_info::TypeInfo;
 
 		/// The overarching event type.
 		type Event: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::Event>;
diff --git a/substrate/frame/session/Cargo.toml b/substrate/frame/session/Cargo.toml
index b5841319000b7cd1a86aa1508184e26c2de58404..8f07de2e7a6dbf3047787e89ad24249789fc038c 100644
--- a/substrate/frame/session/Cargo.toml
+++ b/substrate/frame/session/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
@@ -34,6 +35,7 @@ default = ["std", "historical"]
 historical = ["sp-trie"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-io/std",
 	"frame-support/std",
diff --git a/substrate/frame/session/benchmarking/Cargo.toml b/substrate/frame/session/benchmarking/Cargo.toml
index c559b29f14eec5562a00a451521cc6ceb903bdbe..cc242085bf5e47b7479d5e6ffeadb7787b1892e9 100644
--- a/substrate/frame/session/benchmarking/Cargo.toml
+++ b/substrate/frame/session/benchmarking/Cargo.toml
@@ -29,6 +29,7 @@ rand = { version = "0.7.2", default-features = false }
 codec = { package = "parity-scale-codec", version = "2.0.0", features = [
 	"derive",
 ] }
+scale-info = "1.0"
 sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" }
 pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../../staking/reward-curve" }
 sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" }
diff --git a/substrate/frame/society/Cargo.toml b/substrate/frame/society/Cargo.toml
index b058733b3ce4070355b02c283c6fc061ed27ceac..942b2844195f21ad0619c24198cfd9f9e19c5a3d 100644
--- a/substrate/frame/society/Cargo.toml
+++ b/substrate/frame/society/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
@@ -30,6 +31,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-runtime/std",
 	"rand_chacha/std",
 	"sp-std/std",
diff --git a/substrate/frame/society/src/lib.rs b/substrate/frame/society/src/lib.rs
index c19cd35ae7db63bf0ab6e18c5736a0af7a3bfa7a..c6d63eed20ac05d76079d5347da441e35865c207 100644
--- a/substrate/frame/society/src/lib.rs
+++ b/substrate/frame/society/src/lib.rs
@@ -268,6 +268,7 @@ use rand_chacha::{
 	rand_core::{RngCore, SeedableRng},
 	ChaChaRng,
 };
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{
 		AccountIdConversion, CheckedSub, Hash, IntegerSquareRoot, Saturating, StaticLookup,
@@ -334,7 +335,7 @@ pub trait Config<I = DefaultInstance>: system::Config {
 }
 
 /// A vote by a member on a candidate application.
-#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub enum Vote {
 	/// The member has been chosen to be skeptic and has not yet taken any action.
 	Skeptic,
@@ -345,7 +346,7 @@ pub enum Vote {
 }
 
 /// A judgement by the suspension judgement origin on a suspended candidate.
-#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub enum Judgement {
 	/// The suspension judgement origin takes no direct judgment
 	/// and places the candidate back into the bid pool.
@@ -357,7 +358,7 @@ pub enum Judgement {
 }
 
 /// Details of a payout given as a per-block linear "trickle".
-#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, Default)]
+#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, Default, TypeInfo)]
 pub struct Payout<Balance, BlockNumber> {
 	/// Total value of the payout.
 	value: Balance,
@@ -370,7 +371,7 @@ pub struct Payout<Balance, BlockNumber> {
 }
 
 /// Status of a vouching member.
-#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub enum VouchingStatus {
 	/// Member is currently vouching for a user.
 	Vouching,
@@ -382,7 +383,7 @@ pub enum VouchingStatus {
 pub type StrikeCount = u32;
 
 /// A bid for entry into society.
-#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub struct Bid<AccountId, Balance> {
 	/// The bidder/candidate trying to enter society
 	who: AccountId,
@@ -393,7 +394,7 @@ pub struct Bid<AccountId, Balance> {
 }
 
 /// A vote by a member on a candidate application.
-#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub enum BidKind<AccountId, Balance> {
 	/// The CandidateDeposit was paid for this bid.
 	Deposit(Balance),
diff --git a/substrate/frame/staking/Cargo.toml b/substrate/frame/staking/Cargo.toml
index 5859cf27788f6e2d6c202424ef9995f6aaa51282..aba19ba56357a9d732b6830f1ca5366c10dc076b 100644
--- a/substrate/frame/staking/Cargo.toml
+++ b/substrate/frame/staking/Cargo.toml
@@ -17,6 +17,7 @@ serde = { version = "1.0.126", optional = true }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -51,6 +52,7 @@ default = ["std"]
 std = [
 	"serde",
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-io/std",
 	"frame-support/std",
diff --git a/substrate/frame/staking/src/lib.rs b/substrate/frame/staking/src/lib.rs
index e424b724b4c25be20d18dc47e22260379fa916ca..31b35acdd99aa90e2d8906d697d4fb290f950683 100644
--- a/substrate/frame/staking/src/lib.rs
+++ b/substrate/frame/staking/src/lib.rs
@@ -288,6 +288,7 @@ use frame_support::{
 	traits::{Currency, Get},
 	weights::Weight,
 };
+use scale_info::TypeInfo;
 use sp_runtime::{
 	curve::PiecewiseLinear,
 	traits::{AtLeast32BitUnsigned, Convert, Saturating, Zero},
@@ -333,7 +334,7 @@ type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<
 >>::NegativeImbalance;
 
 /// Information regarding the active era (era in used in session).
-#[derive(Encode, Decode, RuntimeDebug)]
+#[derive(Encode, Decode, RuntimeDebug, TypeInfo)]
 pub struct ActiveEraInfo {
 	/// Index of era.
 	pub index: EraIndex,
@@ -347,7 +348,7 @@ pub struct ActiveEraInfo {
 /// Reward points of an era. Used to split era total payout between validators.
 ///
 /// This points will be used to reward validators and their respective nominators.
-#[derive(PartialEq, Encode, Decode, Default, RuntimeDebug)]
+#[derive(PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo)]
 pub struct EraRewardPoints<AccountId: Ord> {
 	/// Total number of points. Equals the sum of reward points for each validator.
 	total: RewardPoint,
@@ -356,7 +357,7 @@ pub struct EraRewardPoints<AccountId: Ord> {
 }
 
 /// Indicates the initial status of the staker.
-#[derive(RuntimeDebug)]
+#[derive(RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
 pub enum StakerStatus<AccountId> {
 	/// Chilling.
@@ -368,7 +369,7 @@ pub enum StakerStatus<AccountId> {
 }
 
 /// A destination account for payment.
-#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug)]
+#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
 pub enum RewardDestination<AccountId> {
 	/// Pay into the stash account, increasing the amount at stake accordingly.
 	Staked,
@@ -389,7 +390,7 @@ impl<AccountId> Default for RewardDestination<AccountId> {
 }
 
 /// Preference of what happens regarding validation.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
 pub struct ValidatorPrefs {
 	/// Reward that validator takes up-front; only the rest is split between themselves and
 	/// nominators.
@@ -408,7 +409,7 @@ impl Default for ValidatorPrefs {
 }
 
 /// Just a Balance/BlockNumber tuple to encode when a chunk of funds will be unlocked.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
 pub struct UnlockChunk<Balance: HasCompact> {
 	/// Amount of funds to be unlocked.
 	#[codec(compact)]
@@ -419,7 +420,7 @@ pub struct UnlockChunk<Balance: HasCompact> {
 }
 
 /// The ledger of a (bonded) stash.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
 pub struct StakingLedger<AccountId, Balance: HasCompact> {
 	/// The stash account whose balance is actually locked and at stake.
 	pub stash: AccountId,
@@ -547,7 +548,7 @@ where
 }
 
 /// A record of the nominations made by a specific account.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
 pub struct Nominations<AccountId> {
 	/// The targets of nomination.
 	pub targets: Vec<AccountId>,
@@ -563,7 +564,7 @@ pub struct Nominations<AccountId> {
 }
 
 /// The amount of exposure (to slashing) than an individual nominator has.
-#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug)]
+#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
 pub struct IndividualExposure<AccountId, Balance: HasCompact> {
 	/// The stash account of the nominator in question.
 	pub who: AccountId,
@@ -573,7 +574,9 @@ pub struct IndividualExposure<AccountId, Balance: HasCompact> {
 }
 
 /// A snapshot of the stake backing a single validator in the system.
-#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default, RuntimeDebug)]
+#[derive(
+	PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo,
+)]
 pub struct Exposure<AccountId, Balance: HasCompact> {
 	/// The total balance backing this validator.
 	#[codec(compact)]
@@ -587,7 +590,7 @@ pub struct Exposure<AccountId, Balance: HasCompact> {
 
 /// A pending slash record. The value of the slash has been computed but not applied yet,
 /// rather deferred for several eras.
-#[derive(Encode, Decode, Default, RuntimeDebug)]
+#[derive(Encode, Decode, Default, RuntimeDebug, TypeInfo)]
 pub struct UnappliedSlash<AccountId, Balance: HasCompact> {
 	/// The stash ID of the offending validator.
 	validator: AccountId,
@@ -691,7 +694,7 @@ impl<Balance: AtLeast32BitUnsigned + Clone, T: Get<&'static PiecewiseLinear<'sta
 }
 
 /// Mode of era-forcing.
-#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
+#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
 pub enum Forcing {
 	/// Not forcing anything - just let whatever happen.
@@ -715,7 +718,7 @@ impl Default for Forcing {
 // A value placed in storage that represents the current version of the Staking storage. This value
 // is used by the `on_runtime_upgrade` logic to determine whether we run storage migration logic.
 // This should match directly with the semantic versions of the Rust crate.
-#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 enum Releases {
 	V1_0_0Ancient,
 	V2_0_0,
diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs
index 091dd7817676d3869a5deacb6804dc614b94a590..d99cd89f3b06ceb5dd3485b424791a5c3ba6f129 100644
--- a/substrate/frame/staking/src/pallet/mod.rs
+++ b/substrate/frame/staking/src/pallet/mod.rs
@@ -519,7 +519,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(crate) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId", BalanceOf<T> = "Balance")]
 	pub enum Event<T: Config> {
 		/// The era payout has been set; the first balance is the validator-payout; the second is
 		/// the remainder from the maximum amount of reward.
diff --git a/substrate/frame/staking/src/slashing.rs b/substrate/frame/staking/src/slashing.rs
index 3da79924d0a0e3af624455155a659ff74179bd45..15ca85b4d046f1c0a50228fbcc800a2b436c3795 100644
--- a/substrate/frame/staking/src/slashing.rs
+++ b/substrate/frame/staking/src/slashing.rs
@@ -58,6 +58,7 @@ use frame_support::{
 	ensure,
 	traits::{Currency, Imbalance, OnUnbalanced},
 };
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{Saturating, Zero},
 	DispatchResult, RuntimeDebug,
@@ -72,7 +73,7 @@ const REWARD_F1: Perbill = Perbill::from_percent(50);
 pub type SpanIndex = u32;
 
 // A range of start..end eras for a slashing span.
-#[derive(Encode, Decode)]
+#[derive(Encode, Decode, TypeInfo)]
 #[cfg_attr(test, derive(Debug, PartialEq))]
 pub(crate) struct SlashingSpan {
 	pub(crate) index: SpanIndex,
@@ -87,7 +88,7 @@ impl SlashingSpan {
 }
 
 /// An encoding of all of a nominator's slashing spans.
-#[derive(Encode, Decode, RuntimeDebug)]
+#[derive(Encode, Decode, RuntimeDebug, TypeInfo)]
 pub struct SlashingSpans {
 	// the index of the current slashing span of the nominator. different for
 	// every stash, resets when the account hits free balance 0.
@@ -180,7 +181,7 @@ impl SlashingSpans {
 }
 
 /// A slashing-span record for a particular stash.
-#[derive(Encode, Decode, Default)]
+#[derive(Encode, Decode, Default, TypeInfo)]
 pub(crate) struct SpanRecord<Balance> {
 	slashed: Balance,
 	paid_out: Balance,
diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs
index 931ffaa10386c4700d2955ca0e152d4c6350e9c6..97dfaa39c84a9c3f62ca48ca5104cc0c231c29f8 100644
--- a/substrate/frame/staking/src/tests.rs
+++ b/substrate/frame/staking/src/tests.rs
@@ -3355,7 +3355,8 @@ fn payout_stakers_handles_weight_refund() {
 		start_active_era(2);
 
 		// Collect payouts when there are no nominators
-		let call = TestRuntimeCall::Staking(StakingCall::payout_stakers(11, 1));
+		let call =
+			TestRuntimeCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 1 });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(20));
 		assert_ok!(result);
@@ -3368,7 +3369,8 @@ fn payout_stakers_handles_weight_refund() {
 		start_active_era(3);
 
 		// Collect payouts for an era where the validator did not receive any points.
-		let call = TestRuntimeCall::Staking(StakingCall::payout_stakers(11, 2));
+		let call =
+			TestRuntimeCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 2 });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(20));
 		assert_ok!(result);
@@ -3381,7 +3383,8 @@ fn payout_stakers_handles_weight_refund() {
 		start_active_era(4);
 
 		// Collect payouts when the validator has `half_max_nom_rewarded` nominators.
-		let call = TestRuntimeCall::Staking(StakingCall::payout_stakers(11, 3));
+		let call =
+			TestRuntimeCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 3 });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(20));
 		assert_ok!(result);
@@ -3404,14 +3407,16 @@ fn payout_stakers_handles_weight_refund() {
 		start_active_era(6);
 
 		// Collect payouts when the validator had `half_max_nom_rewarded` nominators.
-		let call = TestRuntimeCall::Staking(StakingCall::payout_stakers(11, 5));
+		let call =
+			TestRuntimeCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 5 });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(20));
 		assert_ok!(result);
 		assert_eq!(extract_actual_weight(&result, &info), max_nom_rewarded_weight);
 
 		// Try and collect payouts for an era that has already been collected.
-		let call = TestRuntimeCall::Staking(StakingCall::payout_stakers(11, 5));
+		let call =
+			TestRuntimeCall::Staking(StakingCall::payout_stakers { validator_stash: 11, era: 5 });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(20));
 		assert!(result.is_err());
diff --git a/substrate/frame/sudo/Cargo.toml b/substrate/frame/sudo/Cargo.toml
index f19afd2d61a0b1aba1b1c5fd1b968fb3e65d3f50..baacb66d5c751af08869ec8bc95fecd29e71fa0b 100644
--- a/substrate/frame/sudo/Cargo.toml
+++ b/substrate/frame/sudo/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -27,6 +28,7 @@ sp-core = { version = "4.0.0-dev", path = "../../primitives/core" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-io/std",
 	"sp-runtime/std",
diff --git a/substrate/frame/sudo/src/lib.rs b/substrate/frame/sudo/src/lib.rs
index 6dcb3bf5e44ce8d4c528c4fe70185629ed34e1ef..bab93ffcee16275d1e896b9b6b98313aaa45bac3 100644
--- a/substrate/frame/sudo/src/lib.rs
+++ b/substrate/frame/sudo/src/lib.rs
@@ -249,7 +249,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId")]
 	pub enum Event<T: Config> {
 		/// A sudo just took place. \[result\]
 		Sudid(DispatchResult),
diff --git a/substrate/frame/sudo/src/mock.rs b/substrate/frame/sudo/src/mock.rs
index 7fd55a618a6b5848ec26cf6372e9b62f888206c8..dad17384d5603458d86719896091d54280444a17 100644
--- a/substrate/frame/sudo/src/mock.rs
+++ b/substrate/frame/sudo/src/mock.rs
@@ -79,7 +79,6 @@ pub mod logger {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId")]
 	pub enum Event<T: Config> {
 		AppendI32(i32, Weight),
 		AppendI32AndAccount(T::AccountId, i32, Weight),
diff --git a/substrate/frame/sudo/src/tests.rs b/substrate/frame/sudo/src/tests.rs
index ebd7a11a70f1e60ab9a0422ce552bd369a2aed14..2eb558e9471c43f5e49df6aaa2202e8b24a867c3 100644
--- a/substrate/frame/sudo/src/tests.rs
+++ b/substrate/frame/sudo/src/tests.rs
@@ -39,12 +39,12 @@ fn sudo_basics() {
 	// Configure a default test environment and set the root `key` to 1.
 	new_test_ext(1).execute_with(|| {
 		// A privileged function should work when `sudo` is passed the root `key` as `origin`.
-		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000)));
+		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log { i: 42, weight: 1_000 }));
 		assert_ok!(Sudo::sudo(Origin::signed(1), call));
 		assert_eq!(Logger::i32_log(), vec![42i32]);
 
 		// A privileged function should not work when `sudo` is passed a non-root `key` as `origin`.
-		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000)));
+		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log { i: 42, weight: 1_000 }));
 		assert_noop!(Sudo::sudo(Origin::signed(2), call), Error::<Test>::RequireSudo);
 	});
 }
@@ -56,7 +56,7 @@ fn sudo_emits_events_correctly() {
 		System::set_block_number(1);
 
 		// Should emit event to indicate success when called with the root `key` and `call` is `Ok`.
-		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1)));
+		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log { i: 42, weight: 1 }));
 		assert_ok!(Sudo::sudo(Origin::signed(1), call));
 		System::assert_has_event(TestEvent::Sudo(Event::Sudid(Ok(()))));
 	})
@@ -66,12 +66,12 @@ fn sudo_emits_events_correctly() {
 fn sudo_unchecked_weight_basics() {
 	new_test_ext(1).execute_with(|| {
 		// A privileged function should work when `sudo` is passed the root `key` as origin.
-		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000)));
+		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log { i: 42, weight: 1_000 }));
 		assert_ok!(Sudo::sudo_unchecked_weight(Origin::signed(1), call, 1_000));
 		assert_eq!(Logger::i32_log(), vec![42i32]);
 
 		// A privileged function should not work when called with a non-root `key`.
-		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000)));
+		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log { i: 42, weight: 1_000 }));
 		assert_noop!(
 			Sudo::sudo_unchecked_weight(Origin::signed(2), call, 1_000),
 			Error::<Test>::RequireSudo,
@@ -80,8 +80,8 @@ fn sudo_unchecked_weight_basics() {
 		assert_eq!(Logger::i32_log(), vec![42i32]);
 
 		// Controls the dispatched weight.
-		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1)));
-		let sudo_unchecked_weight_call = SudoCall::sudo_unchecked_weight(call, 1_000);
+		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log { i: 42, weight: 1 }));
+		let sudo_unchecked_weight_call = SudoCall::sudo_unchecked_weight { call, weight: 1_000 };
 		let info = sudo_unchecked_weight_call.get_dispatch_info();
 		assert_eq!(info.weight, 1_000);
 	});
@@ -94,7 +94,7 @@ fn sudo_unchecked_weight_emits_events_correctly() {
 		System::set_block_number(1);
 
 		// Should emit event to indicate success when called with the root `key` and `call` is `Ok`.
-		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1)));
+		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log { i: 42, weight: 1 }));
 		assert_ok!(Sudo::sudo_unchecked_weight(Origin::signed(1), call, 1_000));
 		System::assert_has_event(TestEvent::Sudo(Event::Sudid(Ok(()))));
 	})
@@ -134,17 +134,17 @@ fn set_key_emits_events_correctly() {
 fn sudo_as_basics() {
 	new_test_ext(1).execute_with(|| {
 		// A privileged function will not work when passed to `sudo_as`.
-		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000)));
+		let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log { i: 42, weight: 1_000 }));
 		assert_ok!(Sudo::sudo_as(Origin::signed(1), 2, call));
 		assert!(Logger::i32_log().is_empty());
 		assert!(Logger::account_log().is_empty());
 
 		// A non-privileged function should not work when called with a non-root `key`.
-		let call = Box::new(Call::Logger(LoggerCall::non_privileged_log(42, 1)));
+		let call = Box::new(Call::Logger(LoggerCall::non_privileged_log { i: 42, weight: 1 }));
 		assert_noop!(Sudo::sudo_as(Origin::signed(3), 2, call), Error::<Test>::RequireSudo);
 
 		// A non-privileged function will work when passed to `sudo_as` with the root `key`.
-		let call = Box::new(Call::Logger(LoggerCall::non_privileged_log(42, 1)));
+		let call = Box::new(Call::Logger(LoggerCall::non_privileged_log { i: 42, weight: 1 }));
 		assert_ok!(Sudo::sudo_as(Origin::signed(1), 2, call));
 		assert_eq!(Logger::i32_log(), vec![42i32]);
 		// The correct user makes the call within `sudo_as`.
@@ -159,7 +159,7 @@ fn sudo_as_emits_events_correctly() {
 		System::set_block_number(1);
 
 		// A non-privileged function will work when passed to `sudo_as` with the root `key`.
-		let call = Box::new(Call::Logger(LoggerCall::non_privileged_log(42, 1)));
+		let call = Box::new(Call::Logger(LoggerCall::non_privileged_log { i: 42, weight: 1 }));
 		assert_ok!(Sudo::sudo_as(Origin::signed(1), 2, call));
 		System::assert_has_event(TestEvent::Sudo(Event::SudoAsDone(Ok(()))));
 	});
diff --git a/substrate/frame/support/Cargo.toml b/substrate/frame/support/Cargo.toml
index 9b515c3aa84ab010a444fae4cf87c1da6460f51f..b09ed65a114dc8afbf2ab5c1161848651a08a944 100644
--- a/substrate/frame/support/Cargo.toml
+++ b/substrate/frame/support/Cargo.toml
@@ -15,7 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 serde = { version = "1.0.126", optional = true, features = ["derive"] }
 codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] }
-frame-metadata = { version = "14.0.0-dev", default-features = false, path = "../metadata" }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
+frame-metadata = { version = "14.0.0", default-features = false, features = ["v14"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -34,6 +35,7 @@ smallvec = "1.4.1"
 log = { version = "0.4.14", default-features = false }
 
 [dev-dependencies]
+assert_matches = "1.3.0"
 pretty_assertions = "0.6.1"
 frame-system = { version = "4.0.0-dev", path = "../system" }
 parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] }
@@ -45,6 +47,7 @@ std = [
 	"serde",
 	"sp-io/std",
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-runtime/std",
 	"sp-tracing/std",
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs
index f847bc6dbfbdd70fb6355b3a3464ced8ce77ddfc..2532a680e21bead6d708513c60b1fb12bf97dc68 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs
@@ -54,6 +54,7 @@ pub fn expand_outer_dispatch(
 			Clone, PartialEq, Eq,
 			#scrate::codec::Encode,
 			#scrate::codec::Decode,
+			#scrate::scale_info::TypeInfo,
 			#scrate::RuntimeDebug,
 		)]
 		pub enum Call {
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/event.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/event.rs
index a04759ec972b68df097bdcc25d298d8de7366cc4..798646bf273345b252a3c9818e87286e59917b0c 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/event.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/event.rs
@@ -75,6 +75,7 @@ pub fn expand_outer_event(
 			Clone, PartialEq, Eq,
 			#scrate::codec::Encode,
 			#scrate::codec::Decode,
+			#scrate::scale_info::TypeInfo,
 			#scrate::RuntimeDebug,
 		)]
 		#[allow(non_camel_case_types)]
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs
index fa12242f4fcd651be83fe644dde1c330326881fe..c8445e0bbc255500732c61adb93fb3a7aad46946 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs
@@ -26,7 +26,7 @@ pub fn expand_runtime_metadata(
 	scrate: &TokenStream,
 	extrinsic: &TypePath,
 ) -> TokenStream {
-	let modules = pallet_declarations
+	let pallets = pallet_declarations
 		.iter()
 		.filter_map(|pallet_declaration| {
 			pallet_declaration.find_part("Pallet").map(|_| {
@@ -42,21 +42,21 @@ pub fn expand_runtime_metadata(
 		.map(|(decl, filtered_names)| {
 			let name = &decl.name;
 			let index = &decl.index;
-			let storage = expand_pallet_metadata_storage(&filtered_names, runtime, scrate, decl);
-			let calls = expand_pallet_metadata_calls(&filtered_names, runtime, scrate, decl);
+			let storage = expand_pallet_metadata_storage(&filtered_names, runtime, decl);
+			let calls = expand_pallet_metadata_calls(&filtered_names, runtime, decl);
 			let event = expand_pallet_metadata_events(&filtered_names, runtime, scrate, decl);
-			let constants = expand_pallet_metadata_constants(runtime, scrate, decl);
-			let errors = expand_pallet_metadata_errors(runtime, scrate, decl);
+			let constants = expand_pallet_metadata_constants(runtime, decl);
+			let errors = expand_pallet_metadata_errors(runtime, decl);
 
 			quote! {
-				#scrate::metadata::ModuleMetadata {
-					name: #scrate::metadata::DecodeDifferent::Encode(stringify!(#name)),
+				#scrate::metadata::PalletMetadata {
+					name: stringify!(#name),
 					index: #index,
 					storage: #storage,
 					calls: #calls,
 					event: #event,
 					constants: #constants,
-					errors: #errors,
+					error: #errors,
 				}
 			}
 		})
@@ -65,20 +65,26 @@ pub fn expand_runtime_metadata(
 	quote! {
 		impl #runtime {
 			pub fn metadata() -> #scrate::metadata::RuntimeMetadataPrefixed {
-				#scrate::metadata::RuntimeMetadataLastVersion {
-					modules: #scrate::metadata::DecodeDifferent::Encode(&[ #(#modules),* ]),
-					extrinsic: #scrate::metadata::ExtrinsicMetadata {
+				#scrate::metadata::RuntimeMetadataLastVersion::new(
+					#scrate::sp_std::vec![ #(#pallets),* ],
+					#scrate::metadata::ExtrinsicMetadata {
+						ty: #scrate::scale_info::meta_type::<#extrinsic>(),
 						version: <#extrinsic as #scrate::sp_runtime::traits::ExtrinsicMetadata>::VERSION,
 						signed_extensions: <
 								<
 									#extrinsic as #scrate::sp_runtime::traits::ExtrinsicMetadata
 								>::SignedExtensions as #scrate::sp_runtime::traits::SignedExtension
-							>::identifier()
+							>::metadata()
 								.into_iter()
-								.map(#scrate::metadata::DecodeDifferent::Encode)
+								.map(|meta| #scrate::metadata::SignedExtensionMetadata {
+									identifier: meta.identifier,
+									ty: meta.ty,
+									additional_signed: meta.additional_signed,
+								})
 								.collect(),
 					},
-				}.into()
+					#scrate::scale_info::meta_type::<#runtime>()
+				).into()
 			}
 		}
 	}
@@ -87,7 +93,6 @@ pub fn expand_runtime_metadata(
 fn expand_pallet_metadata_storage(
 	filtered_names: &[&'static str],
 	runtime: &Ident,
-	scrate: &TokenStream,
 	decl: &Pallet,
 ) -> TokenStream {
 	if filtered_names.contains(&"Storage") {
@@ -95,11 +100,7 @@ fn expand_pallet_metadata_storage(
 		let path = &decl.path;
 
 		quote! {
-			Some(#scrate::metadata::DecodeDifferent::Encode(
-				#scrate::metadata::FnEncode(
-					#path::Pallet::<#runtime #(, #path::#instance)*>::storage_metadata
-				)
-			))
+			Some(#path::Pallet::<#runtime #(, #path::#instance)*>::storage_metadata())
 		}
 	} else {
 		quote!(None)
@@ -109,7 +110,6 @@ fn expand_pallet_metadata_storage(
 fn expand_pallet_metadata_calls(
 	filtered_names: &[&'static str],
 	runtime: &Ident,
-	scrate: &TokenStream,
 	decl: &Pallet,
 ) -> TokenStream {
 	if filtered_names.contains(&"Call") {
@@ -117,11 +117,7 @@ fn expand_pallet_metadata_calls(
 		let path = &decl.path;
 
 		quote! {
-			Some(#scrate::metadata::DecodeDifferent::Encode(
-				#scrate::metadata::FnEncode(
-					#path::Pallet::<#runtime #(, #path::#instance)*>::call_functions
-				)
-			))
+			Some(#path::Pallet::<#runtime #(, #path::#instance)*>::call_functions())
 		}
 	} else {
 		quote!(None)
@@ -150,45 +146,31 @@ fn expand_pallet_metadata_events(
 		};
 
 		quote! {
-			Some(#scrate::metadata::DecodeDifferent::Encode(
-				#scrate::metadata::FnEncode(#pallet_event::metadata)
-			))
+			Some(
+				#scrate::metadata::PalletEventMetadata {
+					ty: #scrate::scale_info::meta_type::<#pallet_event>()
+				}
+			)
 		}
 	} else {
 		quote!(None)
 	}
 }
 
-fn expand_pallet_metadata_constants(
-	runtime: &Ident,
-	scrate: &TokenStream,
-	decl: &Pallet,
-) -> TokenStream {
+fn expand_pallet_metadata_constants(runtime: &Ident, decl: &Pallet) -> TokenStream {
 	let path = &decl.path;
 	let instance = decl.instance.as_ref().into_iter();
 
 	quote! {
-		#scrate::metadata::DecodeDifferent::Encode(
-			#scrate::metadata::FnEncode(
-				#path::Pallet::<#runtime #(, #path::#instance)*>::module_constants_metadata
-			)
-		)
+		#path::Pallet::<#runtime #(, #path::#instance)*>::pallet_constants_metadata()
 	}
 }
 
-fn expand_pallet_metadata_errors(
-	runtime: &Ident,
-	scrate: &TokenStream,
-	decl: &Pallet,
-) -> TokenStream {
+fn expand_pallet_metadata_errors(runtime: &Ident, decl: &Pallet) -> TokenStream {
 	let path = &decl.path;
 	let instance = decl.instance.as_ref().into_iter();
 
 	quote! {
-		#scrate::metadata::DecodeDifferent::Encode(
-			#scrate::metadata::FnEncode(
-				<#path::Pallet::<#runtime #(, #path::#instance)*> as #scrate::metadata::ModuleErrorMetadata>::metadata
-			)
-		)
+		#path::Pallet::<#runtime #(, #path::#instance)*>::error_metadata()
 	}
 }
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs
index 10ab9e9347eb589cffbf30b4d557ca6dd31a56b5..a65ad78527ff76ead50016c718076fc8ff4c817f 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs
@@ -171,7 +171,10 @@ pub fn expand_outer_origin(
 			}
 		}
 
-		#[derive(Clone, PartialEq, Eq, #scrate::RuntimeDebug, #scrate::codec::Encode, #scrate::codec::Decode)]
+		#[derive(
+			Clone, PartialEq, Eq, #scrate::RuntimeDebug, #scrate::codec::Encode,
+			#scrate::codec::Decode, #scrate::scale_info::TypeInfo,
+		)]
 		#[allow(non_camel_case_types)]
 		pub enum OriginCaller {
 			#[codec(index = #system_index)]
diff --git a/substrate/frame/support/procedural/src/construct_runtime/mod.rs b/substrate/frame/support/procedural/src/construct_runtime/mod.rs
index 402cb5458851d67a42804f55299e7b5e6a419a9a..8aacd8f0aa810efc764bf9fc0f35fc49f000f7fd 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/mod.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/mod.rs
@@ -151,7 +151,10 @@ fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream
 			type __hidden_use_of_unchecked_extrinsic = #unchecked_extrinsic;
 		};
 
-		#[derive(Clone, Copy, PartialEq, Eq, #scrate::sp_runtime::RuntimeDebug)]
+		#[derive(
+			Clone, Copy, PartialEq, Eq, #scrate::sp_runtime::RuntimeDebug,
+			#scrate::scale_info::TypeInfo
+		)]
 		pub struct #name;
 		impl #scrate::sp_runtime::traits::GetNodeBlockType for #name {
 			type NodeBlock = #node_block;
diff --git a/substrate/frame/support/procedural/src/key_prefix.rs b/substrate/frame/support/procedural/src/key_prefix.rs
index c4683bc456daf9b46d95639ddc36dec718ae3173..3f424e8b8b8dd19b8c9177a313a2d0e047a8e5b6 100644
--- a/substrate/frame/support/procedural/src/key_prefix.rs
+++ b/substrate/frame/support/procedural/src/key_prefix.rs
@@ -48,7 +48,7 @@ pub fn impl_key_prefix_for_tuples(input: proc_macro::TokenStream) -> Result<Toke
 
 			let trait_impls = quote! {
 				impl<
-					#(#current_tuple: FullCodec,)*
+					#(#current_tuple: FullCodec + StaticTypeInfo,)*
 					#(#hashers: StorageHasher,)*
 					#(#kargs: EncodeLike<#prefixes>),*
 				> HasKeyPrefix<( #( #kargs, )* )> for ( #( Key<#hashers, #current_tuple>, )* ) {
@@ -60,7 +60,7 @@ pub fn impl_key_prefix_for_tuples(input: proc_macro::TokenStream) -> Result<Toke
 				}
 
 				impl<
-					#(#current_tuple: FullCodec,)*
+					#(#current_tuple: FullCodec + StaticTypeInfo,)*
 					#(#hashers: ReversibleStorageHasher,)*
 					#(#kargs: EncodeLike<#prefixes>),*
 				> HasReversibleKeyPrefix<( #( #kargs, )* )> for ( #( Key<#hashers, #current_tuple>, )* ) {
diff --git a/substrate/frame/support/procedural/src/pallet/expand/call.rs b/substrate/frame/support/procedural/src/pallet/expand/call.rs
index 23ea9be9eac7fccdeba0f46258d807d9a0ed5f2f..8f7bcdccaf22d5cb1390c9b62eb5fa52cd0999e8 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/call.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/call.rs
@@ -16,7 +16,6 @@
 // limitations under the License.
 
 use crate::{pallet::Def, COUNTER};
-use frame_support_procedural_tools::clean_type_string;
 use syn::spanned::Spanned;
 
 ///
@@ -43,6 +42,15 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
 	let pallet_ident = &def.pallet_struct.pallet;
 
 	let fn_name = methods.iter().map(|method| &method.name).collect::<Vec<_>>();
+	let new_call_variant_fn_name = fn_name
+		.iter()
+		.map(|fn_name| quote::format_ident!("new_call_variant_{}", fn_name))
+		.collect::<Vec<_>>();
+
+	let new_call_variant_doc = fn_name
+		.iter()
+		.map(|fn_name| format!("Create a call with the variant `{}`.", fn_name))
+		.collect::<Vec<_>>();
 
 	let fn_weight = methods.iter().map(|method| &method.weight);
 
@@ -53,6 +61,42 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
 		.map(|method| method.args.iter().map(|(_, name, _)| name.clone()).collect::<Vec<_>>())
 		.collect::<Vec<_>>();
 
+	let args_name_stripped = methods
+		.iter()
+		.map(|method| {
+			method
+				.args
+				.iter()
+				.map(|(_, name, _)| {
+					syn::Ident::new(&name.to_string().trim_start_matches('_'), name.span())
+				})
+				.collect::<Vec<_>>()
+		})
+		.collect::<Vec<_>>();
+
+	let make_args_name_pattern = |ref_tok| {
+		args_name
+			.iter()
+			.zip(args_name_stripped.iter())
+			.map(|(args_name, args_name_stripped)| {
+				args_name
+					.iter()
+					.zip(args_name_stripped)
+					.map(|(args_name, args_name_stripped)| {
+						if args_name == args_name_stripped {
+							quote::quote!( #ref_tok #args_name )
+						} else {
+							quote::quote!( #args_name_stripped: #ref_tok #args_name )
+						}
+					})
+					.collect::<Vec<_>>()
+			})
+			.collect::<Vec<_>>()
+	};
+
+	let args_name_pattern = make_args_name_pattern(None);
+	let args_name_pattern_ref = make_args_name_pattern(Some(quote::quote!(ref)));
+
 	let args_type = methods
 		.iter()
 		.map(|method| method.args.iter().map(|(_, _, type_)| type_.clone()).collect::<Vec<_>>())
@@ -72,21 +116,6 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
 			.collect::<Vec<_>>()
 	});
 
-	let args_metadata_type = methods.iter().map(|method| {
-		method
-			.args
-			.iter()
-			.map(|(is_compact, _, type_)| {
-				let final_type = if *is_compact {
-					quote::quote_spanned!(type_.span() => Compact<#type_>)
-				} else {
-					quote::quote!(#type_)
-				};
-				clean_type_string(&final_type.to_string())
-			})
-			.collect::<Vec<_>>()
-	});
-
 	let default_docs = [syn::parse_quote!(
 		r"Contains one variant per dispatchable that can be called by an extrinsic."
 	)];
@@ -131,9 +160,11 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
 			#frame_support::PartialEqNoBound,
 			#frame_support::codec::Encode,
 			#frame_support::codec::Decode,
+			#frame_support::scale_info::TypeInfo,
 		)]
 		#[codec(encode_bound())]
 		#[codec(decode_bound())]
+		#[scale_info(skip_type_params(#type_use_gen), capture_docs = "always")]
 		#[allow(non_camel_case_types)]
 		pub enum #call_ident<#type_decl_bounded_gen> #where_clause {
 			#[doc(hidden)]
@@ -142,7 +173,25 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
 				#frame_support::sp_std::marker::PhantomData<(#type_use_gen,)>,
 				#frame_support::Never,
 			),
-			#( #( #[doc = #fn_doc] )* #fn_name( #( #args_compact_attr #args_type ),* ), )*
+			#(
+				#( #[doc = #fn_doc] )*
+				#fn_name {
+					#( #args_compact_attr #args_name_stripped: #args_type ),*
+				},
+			)*
+		}
+
+		impl<#type_impl_gen> #call_ident<#type_use_gen> #where_clause {
+			#(
+				#[doc = #new_call_variant_doc]
+				pub fn #new_call_variant_fn_name(
+					#( #args_name_stripped: #args_type ),*
+				) -> Self {
+					Self::#fn_name {
+						#( #args_name_stripped ),*
+					}
+				}
+			)*
 		}
 
 		impl<#type_impl_gen> #frame_support::dispatch::GetDispatchInfo
@@ -152,7 +201,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
 			fn get_dispatch_info(&self) -> #frame_support::dispatch::DispatchInfo {
 				match *self {
 					#(
-						Self::#fn_name ( #( ref #args_name, )* ) => {
+						Self::#fn_name { #( #args_name_pattern_ref, )* } => {
 							let __pallet_base_weight = #fn_weight;
 
 							let __pallet_weight = <
@@ -186,7 +235,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
 		{
 			fn get_call_name(&self) -> &'static str {
 				match *self {
-					#( Self::#fn_name(..) => stringify!(#fn_name), )*
+					#( Self::#fn_name { .. } => stringify!(#fn_name), )*
 					Self::__Ignore(_, _) => unreachable!("__PhantomItem cannot be used."),
 				}
 			}
@@ -207,7 +256,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
 			) -> #frame_support::dispatch::DispatchResultWithPostInfo {
 				match self {
 					#(
-						Self::#fn_name( #( #args_name, )* ) => {
+						Self::#fn_name { #( #args_name_pattern, )* } => {
 							#frame_support::sp_tracing::enter_span!(
 								#frame_support::sp_tracing::trace_span!(stringify!(#fn_name))
 							);
@@ -231,30 +280,8 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
 
 		impl<#type_impl_gen> #pallet_ident<#type_use_gen> #where_clause {
 			#[doc(hidden)]
-			#[allow(dead_code)]
-			pub fn call_functions() -> &'static [#frame_support::dispatch::FunctionMetadata] {
-				&[ #(
-					#frame_support::dispatch::FunctionMetadata {
-						name: #frame_support::dispatch::DecodeDifferent::Encode(
-							stringify!(#fn_name)
-						),
-						arguments: #frame_support::dispatch::DecodeDifferent::Encode(
-							&[ #(
-								#frame_support::dispatch::FunctionArgumentMetadata {
-									name: #frame_support::dispatch::DecodeDifferent::Encode(
-										stringify!(#args_name)
-									),
-									ty: #frame_support::dispatch::DecodeDifferent::Encode(
-										#args_metadata_type
-									),
-								},
-							)* ]
-						),
-						documentation: #frame_support::dispatch::DecodeDifferent::Encode(
-							&[ #( #fn_doc ),* ]
-						),
-					},
-				)* ]
+			pub fn call_functions() -> #frame_support::metadata::PalletCallMetadata {
+				#frame_support::scale_info::meta_type::<#call_ident<#type_use_gen>>().into()
 			}
 		}
 	)
diff --git a/substrate/frame/support/procedural/src/pallet/expand/config.rs b/substrate/frame/support/procedural/src/pallet/expand/config.rs
index 17101b0be8f53e18d3d9bb71ab8b1493dd848d61..dad26ccad6dc1de516d80eb4e5f818eca2bda807 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/config.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/config.rs
@@ -15,7 +15,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use crate::pallet::{parse::helper::get_doc_literals, Def};
+use crate::pallet::Def;
+use frame_support_procedural_tools::get_doc_literals;
 
 ///
 /// * Generate default rust doc
diff --git a/substrate/frame/support/procedural/src/pallet/expand/constants.rs b/substrate/frame/support/procedural/src/pallet/expand/constants.rs
index fcf77ae8e4b7f88c422f91aa971b126c0aed114c..7cc245e8089dfd97a050025672392dda19f04ae7 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/constants.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/constants.rs
@@ -16,8 +16,6 @@
 // limitations under the License.
 
 use crate::pallet::Def;
-use frame_support_procedural_tools::clean_type_string;
-use quote::ToTokens;
 
 struct ConstDef {
 	/// Name of the associated type.
@@ -35,7 +33,6 @@ struct ConstDef {
 pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream {
 	let frame_support = &def.frame_support;
 	let type_impl_gen = &def.type_impl_generics(proc_macro2::Span::call_site());
-	let type_decl_gen = &def.type_decl_generics(proc_macro2::Span::call_site());
 	let type_use_gen = &def.type_use_generics(proc_macro2::Span::call_site());
 	let pallet_ident = &def.pallet_struct.pallet;
 
@@ -74,50 +71,17 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream {
 
 	let consts = config_consts.chain(extra_consts).map(|const_| {
 		let const_type = &const_.type_;
-		let const_type_str = clean_type_string(&const_type.to_token_stream().to_string());
 		let ident = &const_.ident;
 		let ident_str = format!("{}", ident);
 		let doc = const_.doc.clone().into_iter();
 		let default_byte_impl = &const_.default_byte_impl;
-		let default_byte_getter =
-			syn::Ident::new(&format!("{}DefaultByteGetter", ident), ident.span());
 
 		quote::quote!({
-			#[allow(non_upper_case_types)]
-			#[allow(non_camel_case_types)]
-			struct #default_byte_getter<#type_decl_gen>(
-				#frame_support::sp_std::marker::PhantomData<(#type_use_gen)>
-			);
-
-			impl<#type_impl_gen> #frame_support::dispatch::DefaultByte for
-				#default_byte_getter<#type_use_gen>
-				#completed_where_clause
-			{
-				fn default_byte(&self) -> #frame_support::sp_std::vec::Vec<u8> {
-					#default_byte_impl
-				}
-			}
-
-			unsafe impl<#type_impl_gen> Send for #default_byte_getter<#type_use_gen>
-				#completed_where_clause
-			{}
-			unsafe impl<#type_impl_gen> Sync for #default_byte_getter<#type_use_gen>
-				#completed_where_clause
-			{}
-
-			#frame_support::dispatch::ModuleConstantMetadata {
-				name: #frame_support::dispatch::DecodeDifferent::Encode(#ident_str),
-				ty: #frame_support::dispatch::DecodeDifferent::Encode(#const_type_str),
-				value: #frame_support::dispatch::DecodeDifferent::Encode(
-					#frame_support::dispatch::DefaultByteGetter(
-						&#default_byte_getter::<#type_use_gen>(
-							#frame_support::sp_std::marker::PhantomData
-						)
-					)
-				),
-				documentation: #frame_support::dispatch::DecodeDifferent::Encode(
-					&[ #( #doc ),* ]
-				),
+			#frame_support::metadata::PalletConstantMetadata {
+				name: #ident_str,
+				ty: #frame_support::scale_info::meta_type::<#const_type>(),
+				value: { #default_byte_impl },
+				docs: #frame_support::sp_std::vec![ #( #doc ),* ],
 			}
 		})
 	});
@@ -126,10 +90,10 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream {
 		impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause{
 
 			#[doc(hidden)]
-			pub fn module_constants_metadata()
-				-> &'static [#frame_support::dispatch::ModuleConstantMetadata]
+			pub fn pallet_constants_metadata()
+				-> #frame_support::sp_std::vec::Vec<#frame_support::metadata::PalletConstantMetadata>
 			{
-				&[ #( #consts ),* ]
+				#frame_support::sp_std::vec![ #( #consts ),* ]
 			}
 		}
 	)
diff --git a/substrate/frame/support/procedural/src/pallet/expand/error.rs b/substrate/frame/support/procedural/src/pallet/expand/error.rs
index 19c4296ad02f50d302ea88ec08ccd78882c64970..7a058bb32c922d9cd5cab3a33dcc48559ec563a9 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/error.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/error.rs
@@ -15,11 +15,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use crate::pallet::{parse::helper::get_doc_literals, Def};
+use crate::pallet::Def;
+use frame_support_procedural_tools::get_doc_literals;
 
 ///
 /// * impl various trait on Error
-/// * impl ModuleErrorMetadata for Error
 pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream {
 	let error = if let Some(error) = &def.error { error } else { return Default::default() };
 
@@ -32,6 +32,7 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream {
 
 	let phantom_variant: syn::Variant = syn::parse_quote!(
 		#[doc(hidden)]
+		#[codec(skip)]
 		__Ignore(
 			#frame_support::sp_std::marker::PhantomData<(#type_use_gen)>,
 			#frame_support::Never,
@@ -47,16 +48,6 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream {
 		quote::quote_spanned!(error.attr_span => Self::#variant => #variant_str,)
 	});
 
-	let metadata = error.variants.iter().map(|(variant, doc)| {
-		let variant_str = format!("{}", variant);
-		quote::quote_spanned!(error.attr_span =>
-			#frame_support::error::ErrorMetadata {
-				name: #frame_support::error::DecodeDifferent::Encode(#variant_str),
-				documentation: #frame_support::error::DecodeDifferent::Encode(&[ #( #doc, )* ]),
-			},
-		)
-	});
-
 	let error_item = {
 		let item = &mut def.item.content.as_mut().expect("Checked by def parser").1[error.index];
 		if let syn::Item::Enum(item) = item {
@@ -67,6 +58,13 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream {
 	};
 
 	error_item.variants.insert(0, phantom_variant);
+	// derive TypeInfo for error metadata
+	error_item
+		.attrs
+		.push(syn::parse_quote!( #[derive(#frame_support::scale_info::TypeInfo)] ));
+	error_item.attrs.push(syn::parse_quote!(
+		#[scale_info(skip_type_params(#type_use_gen), capture_docs = "always")]
+	));
 
 	if get_doc_literals(&error_item.attrs).is_empty() {
 		error_item.attrs.push(syn::parse_quote!(
@@ -130,14 +128,5 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream {
 				}
 			}
 		}
-
-		impl<#type_impl_gen> #frame_support::error::ModuleErrorMetadata
-			for #error_ident<#type_use_gen>
-			#config_where_clause
-		{
-			fn metadata() -> &'static [#frame_support::error::ErrorMetadata] {
-				&[ #( #metadata )* ]
-			}
-		}
 	)
 }
diff --git a/substrate/frame/support/procedural/src/pallet/expand/event.rs b/substrate/frame/support/procedural/src/pallet/expand/event.rs
index 2a2a3020a96b816c6fe90164811b003f0de1a2a5..ebd2d7aeabaffbbbca32e5ed1555e546308a765e 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/event.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/event.rs
@@ -16,9 +16,10 @@
 // limitations under the License.
 
 use crate::{
-	pallet::{parse::helper::get_doc_literals, Def},
+	pallet::{parse::event::PalletEventDepositAttr, Def},
 	COUNTER,
 };
+use frame_support_procedural_tools::get_doc_literals;
 use syn::{spanned::Spanned, Ident};
 
 ///
@@ -69,20 +70,6 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream {
 	let frame_support = &def.frame_support;
 	let event_use_gen = &event.gen_kind.type_use_gen(event.attr_span);
 	let event_impl_gen = &event.gen_kind.type_impl_gen(event.attr_span);
-	let metadata = event.metadata.iter().map(|(ident, args, docs)| {
-		let name = format!("{}", ident);
-		quote::quote_spanned!(event.attr_span =>
-			#frame_support::event::EventMetadata {
-				name: #frame_support::event::DecodeDifferent::Encode(#name),
-				arguments: #frame_support::event::DecodeDifferent::Encode(&[
-					#( #args, )*
-				]),
-				documentation: #frame_support::event::DecodeDifferent::Encode(&[
-					#( #docs, )*
-				]),
-			},
-		)
-	});
 
 	let event_item = {
 		let item = &mut def.item.content.as_mut().expect("Checked by def parser").1[event.index];
@@ -126,15 +113,23 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream {
 			#frame_support::RuntimeDebugNoBound,
 			#frame_support::codec::Encode,
 			#frame_support::codec::Decode,
+			#frame_support::scale_info::TypeInfo,
 		)]
 	));
 
-	let deposit_event = if let Some((fn_vis, fn_span)) = &event.deposit_event {
+	// skip requirement for type params to implement `TypeInfo`, and require docs capture
+	event_item.attrs.push(syn::parse_quote!(
+		#[scale_info(skip_type_params(#event_use_gen), capture_docs = "always")]
+	));
+
+	let deposit_event = if let Some(deposit_event) = &event.deposit_event {
 		let event_use_gen = &event.gen_kind.type_use_gen(event.attr_span);
 		let trait_use_gen = &def.trait_use_generics(event.attr_span);
 		let type_impl_gen = &def.type_impl_generics(event.attr_span);
 		let type_use_gen = &def.type_use_generics(event.attr_span);
 
+		let PalletEventDepositAttr { fn_vis, fn_span, .. } = deposit_event;
+
 		quote::quote_spanned!(*fn_span =>
 			impl<#type_impl_gen> Pallet<#type_use_gen> #completed_where_clause {
 				#fn_vis fn deposit_event(event: Event<#event_use_gen>) {
@@ -174,13 +169,5 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream {
 		impl<#event_impl_gen> From<#event_ident<#event_use_gen>> for () #event_where_clause {
 			fn from(_: #event_ident<#event_use_gen>) {}
 		}
-
-		impl<#event_impl_gen> #event_ident<#event_use_gen> #event_where_clause {
-			#[allow(dead_code)]
-			#[doc(hidden)]
-			pub fn metadata() -> &'static [#frame_support::event::EventMetadata] {
-				&[ #( #metadata )* ]
-			}
-		}
 	)
 }
diff --git a/substrate/frame/support/procedural/src/pallet/expand/genesis_config.rs b/substrate/frame/support/procedural/src/pallet/expand/genesis_config.rs
index 8c540209f40c2e8ebf64b15c2f3f7edce1e7bc22..4bbba2c05908e6e94f8b43fe2aa6427d92b1e1c2 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/genesis_config.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/genesis_config.rs
@@ -15,10 +15,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use crate::{
-	pallet::{parse::helper::get_doc_literals, Def},
-	COUNTER,
-};
+use crate::{pallet::Def, COUNTER};
+use frame_support_procedural_tools::get_doc_literals;
 use syn::{spanned::Spanned, Ident};
 
 ///
diff --git a/substrate/frame/support/procedural/src/pallet/expand/mod.rs b/substrate/frame/support/procedural/src/pallet/expand/mod.rs
index cfb61e700ac293641e6a3d5b03fc4fd80482ed72..1c8883977c765f351beabd321161e0e889417501 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/mod.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/mod.rs
@@ -32,7 +32,8 @@ mod store_trait;
 mod type_value;
 mod validate_unsigned;
 
-use crate::pallet::{parse::helper::get_doc_literals, Def};
+use crate::pallet::Def;
+use frame_support_procedural_tools::get_doc_literals;
 use quote::ToTokens;
 
 /// Merge where clause together, `where` token span is taken from the first not none one.
diff --git a/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs
index 40fc39b161f150047299fcfdedf19a63f58cb781..a217742fec55d25a81dcec93c63273b2d6e5fccc 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs
@@ -15,13 +15,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use crate::pallet::{expand::merge_where_clauses, parse::helper::get_doc_literals, Def};
+use crate::pallet::{expand::merge_where_clauses, Def};
+use frame_support_procedural_tools::get_doc_literals;
 
 ///
 /// * Add derive trait on Pallet
 /// * Implement GetStorageVersion on Pallet
 /// * Implement OnGenesis on Pallet
-/// * Implement ModuleErrorMetadata on Pallet
+/// * Implement `fn error_metadata` on Pallet
 /// * declare Module type alias for construct_runtime
 /// * replace the first field type of `struct Pallet` with `PhantomData` if it is `_`
 /// * implementation of `PalletInfoAccess` information
@@ -76,28 +77,22 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream {
 		)]
 	));
 
-	let module_error_metadata = if let Some(error_def) = &def.error {
+	let pallet_error_metadata = if let Some(error_def) = &def.error {
 		let error_ident = &error_def.error;
 		quote::quote_spanned!(def.pallet_struct.attr_span =>
-			impl<#type_impl_gen> #frame_support::error::ModuleErrorMetadata
-				for #pallet_ident<#type_use_gen>
-				#config_where_clause
-			{
-				fn metadata() -> &'static [#frame_support::error::ErrorMetadata] {
-					<
-						#error_ident<#type_use_gen> as #frame_support::error::ModuleErrorMetadata
-					>::metadata()
+			impl<#type_impl_gen> #pallet_ident<#type_use_gen> #config_where_clause {
+				pub fn error_metadata() -> Option<#frame_support::metadata::PalletErrorMetadata> {
+					Some(#frame_support::metadata::PalletErrorMetadata {
+						ty: #frame_support::scale_info::meta_type::<#error_ident<#type_use_gen>>()
+					})
 				}
 			}
 		)
 	} else {
 		quote::quote_spanned!(def.pallet_struct.attr_span =>
-			impl<#type_impl_gen> #frame_support::error::ModuleErrorMetadata
-				for #pallet_ident<#type_use_gen>
-				#config_where_clause
-			{
-				fn metadata() -> &'static [#frame_support::error::ErrorMetadata] {
-					&[]
+			impl<#type_impl_gen> #pallet_ident<#type_use_gen> #config_where_clause {
+				pub fn error_metadata() -> Option<#frame_support::metadata::PalletErrorMetadata> {
+					None
 				}
 			}
 		)
@@ -159,7 +154,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream {
 	};
 
 	quote::quote_spanned!(def.pallet_struct.attr_span =>
-		#module_error_metadata
+		#pallet_error_metadata
 
 		/// Type alias to `Pallet`, to be used by `construct_runtime`.
 		///
diff --git a/substrate/frame/support/procedural/src/pallet/expand/storage.rs b/substrate/frame/support/procedural/src/pallet/expand/storage.rs
index ac03a41deb995b2d327c333abb36f7675a7d408e..0f7133f10dd47a84956a2af2bd770ffa18772bba 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/storage.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/storage.rs
@@ -19,7 +19,6 @@ use crate::pallet::{
 	parse::storage::{Metadata, QueryKind, StorageDef, StorageGenerics},
 	Def,
 };
-use frame_support_procedural_tools::clean_type_string;
 use std::collections::HashSet;
 
 /// Generate the prefix_ident related the the storage.
@@ -176,89 +175,15 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
 
 		let cfg_attrs = &storage.cfg_attrs;
 
-		let metadata_trait = match &storage.metadata {
-			Metadata::Value { .. } => quote::quote_spanned!(storage.attr_span =>
-				#frame_support::storage::types::StorageValueMetadata
-			),
-			Metadata::Map { .. } => quote::quote_spanned!(storage.attr_span =>
-				#frame_support::storage::types::StorageMapMetadata
-			),
-			Metadata::DoubleMap { .. } => quote::quote_spanned!(storage.attr_span =>
-				#frame_support::storage::types::StorageDoubleMapMetadata
-			),
-			Metadata::NMap { .. } => quote::quote_spanned!(storage.attr_span =>
-				#frame_support::storage::types::StorageNMapMetadata
-			),
-		};
-
-		let ty = match &storage.metadata {
-			Metadata::Value { value } => {
-				let value = clean_type_string(&quote::quote!(#value).to_string());
-				quote::quote_spanned!(storage.attr_span =>
-					#frame_support::metadata::StorageEntryType::Plain(
-						#frame_support::metadata::DecodeDifferent::Encode(#value)
-					)
-				)
-			},
-			Metadata::Map { key, value } => {
-				let value = clean_type_string(&quote::quote!(#value).to_string());
-				let key = clean_type_string(&quote::quote!(#key).to_string());
-				quote::quote_spanned!(storage.attr_span =>
-					#frame_support::metadata::StorageEntryType::Map {
-						hasher: <#full_ident as #metadata_trait>::HASHER,
-						key: #frame_support::metadata::DecodeDifferent::Encode(#key),
-						value: #frame_support::metadata::DecodeDifferent::Encode(#value),
-						unused: false,
-					}
-				)
-			},
-			Metadata::DoubleMap { key1, key2, value } => {
-				let value = clean_type_string(&quote::quote!(#value).to_string());
-				let key1 = clean_type_string(&quote::quote!(#key1).to_string());
-				let key2 = clean_type_string(&quote::quote!(#key2).to_string());
-				quote::quote_spanned!(storage.attr_span =>
-					#frame_support::metadata::StorageEntryType::DoubleMap {
-						hasher: <#full_ident as #metadata_trait>::HASHER1,
-						key2_hasher: <#full_ident as #metadata_trait>::HASHER2,
-						key1: #frame_support::metadata::DecodeDifferent::Encode(#key1),
-						key2: #frame_support::metadata::DecodeDifferent::Encode(#key2),
-						value: #frame_support::metadata::DecodeDifferent::Encode(#value),
-					}
-				)
-			},
-			Metadata::NMap { keys, value, .. } => {
-				let keys = keys
-					.iter()
-					.map(|key| clean_type_string(&quote::quote!(#key).to_string()))
-					.collect::<Vec<_>>();
-				let value = clean_type_string(&quote::quote!(#value).to_string());
-				quote::quote_spanned!(storage.attr_span =>
-					#frame_support::metadata::StorageEntryType::NMap {
-						keys: #frame_support::metadata::DecodeDifferent::Encode(&[
-							#( #keys, )*
-						]),
-						hashers: #frame_support::metadata::DecodeDifferent::Encode(
-							<#full_ident as #metadata_trait>::HASHERS,
-						),
-						value: #frame_support::metadata::DecodeDifferent::Encode(#value),
-					}
-				)
-			},
-		};
-
 		quote::quote_spanned!(storage.attr_span =>
 			#(#cfg_attrs)* #frame_support::metadata::StorageEntryMetadata {
-				name: #frame_support::metadata::DecodeDifferent::Encode(
-					<#full_ident as #metadata_trait>::NAME
-				),
-				modifier: <#full_ident as #metadata_trait>::MODIFIER,
-				ty: #ty,
-				default: #frame_support::metadata::DecodeDifferent::Encode(
-					<#full_ident as #metadata_trait>::DEFAULT
-				),
-				documentation: #frame_support::metadata::DecodeDifferent::Encode(&[
+				name: <#full_ident as #frame_support::storage::StorageEntryMetadata>::NAME,
+				modifier: <#full_ident as #frame_support::storage::StorageEntryMetadata>::MODIFIER,
+				ty: <#full_ident as #frame_support::storage::StorageEntryMetadata>::ty(),
+				default: <#full_ident as #frame_support::storage::StorageEntryMetadata>::default(),
+				docs: #frame_support::sp_std::vec![
 					#( #docs, )*
-				]),
+				],
 			}
 		)
 	});
@@ -419,18 +344,16 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
 			#completed_where_clause
 		{
 			#[doc(hidden)]
-			pub fn storage_metadata() -> #frame_support::metadata::StorageMetadata {
-				#frame_support::metadata::StorageMetadata {
-					prefix: #frame_support::metadata::DecodeDifferent::Encode(
-						<
-							<T as #frame_system::Config>::PalletInfo as
-							#frame_support::traits::PalletInfo
-						>::name::<#pallet_ident<#type_use_gen>>()
-							.expect("Every active pallet has a name in the runtime; qed")
-					),
-					entries: #frame_support::metadata::DecodeDifferent::Encode(
-						&[ #( #entries, )* ]
-					),
+			pub fn storage_metadata() -> #frame_support::metadata::PalletStorageMetadata {
+				#frame_support::metadata::PalletStorageMetadata {
+					prefix: <
+						<T as #frame_system::Config>::PalletInfo as
+						#frame_support::traits::PalletInfo
+					>::name::<#pallet_ident<#type_use_gen>>()
+						.expect("Every active pallet has a name in the runtime; qed"),
+					entries: #frame_support::sp_std::vec![
+						#( #entries, )*
+					],
 				}
 			}
 		}
diff --git a/substrate/frame/support/procedural/src/pallet/parse/call.rs b/substrate/frame/support/procedural/src/pallet/parse/call.rs
index d022e8025aab24fb544071546cf2a2b3037c05da..0563568f333114ea041b2503eb12ad79e46758b6 100644
--- a/substrate/frame/support/procedural/src/pallet/parse/call.rs
+++ b/substrate/frame/support/procedural/src/pallet/parse/call.rs
@@ -16,6 +16,7 @@
 // limitations under the License.
 
 use super::helper;
+use frame_support_procedural_tools::get_doc_literals;
 use quote::ToTokens;
 use syn::spanned::Spanned;
 
@@ -219,7 +220,7 @@ impl CallDef {
 					args.push((!arg_attrs.is_empty(), arg_ident, arg.ty.clone()));
 				}
 
-				let docs = helper::get_doc_literals(&method.attrs);
+				let docs = get_doc_literals(&method.attrs);
 
 				methods.push(CallVariantDef { name: method.sig.ident.clone(), weight, args, docs });
 			} else {
@@ -234,7 +235,7 @@ impl CallDef {
 			instances,
 			methods,
 			where_clause: item.generics.where_clause.clone(),
-			docs: helper::get_doc_literals(&item.attrs),
+			docs: get_doc_literals(&item.attrs),
 		})
 	}
 }
diff --git a/substrate/frame/support/procedural/src/pallet/parse/config.rs b/substrate/frame/support/procedural/src/pallet/parse/config.rs
index b006aadf51a072cbe5f5b7440b8e6f556b1a9cd4..712c20ffc7b4c921ab20b3df0b0c885d368486df 100644
--- a/substrate/frame/support/procedural/src/pallet/parse/config.rs
+++ b/substrate/frame/support/procedural/src/pallet/parse/config.rs
@@ -17,6 +17,7 @@
 
 use super::helper;
 use core::convert::TryFrom;
+use frame_support_procedural_tools::get_doc_literals;
 use quote::ToTokens;
 use syn::spanned::Spanned;
 
@@ -69,7 +70,7 @@ impl TryFrom<&syn::TraitItemType> for ConstMetadataDef {
 		let err = |span, msg| {
 			syn::Error::new(span, format!("Invalid usage of `#[pallet::constant]`: {}", msg))
 		};
-		let doc = helper::get_doc_literals(&trait_ty.attrs);
+		let doc = get_doc_literals(&trait_ty.attrs);
 		let ident = trait_ty.ident.clone();
 		let bound = trait_ty
 			.bounds
diff --git a/substrate/frame/support/procedural/src/pallet/parse/error.rs b/substrate/frame/support/procedural/src/pallet/parse/error.rs
index 9b96a1876917d4e2cf797424da37e98057e60173..9c9a95105c53cf00ceda0019b4ed7c77727322e3 100644
--- a/substrate/frame/support/procedural/src/pallet/parse/error.rs
+++ b/substrate/frame/support/procedural/src/pallet/parse/error.rs
@@ -16,6 +16,7 @@
 // limitations under the License.
 
 use super::helper;
+use frame_support_procedural_tools::get_doc_literals;
 use quote::ToTokens;
 use syn::spanned::Spanned;
 
@@ -80,7 +81,7 @@ impl ErrorDef {
 					return Err(syn::Error::new(span, msg))
 				}
 
-				Ok((variant.ident.clone(), helper::get_doc_literals(&variant.attrs)))
+				Ok((variant.ident.clone(), get_doc_literals(&variant.attrs)))
 			})
 			.collect::<Result<_, _>>()?;
 
diff --git a/substrate/frame/support/procedural/src/pallet/parse/event.rs b/substrate/frame/support/procedural/src/pallet/parse/event.rs
index d66e35e09025b4777ef02a0e323c4beb35daff2a..33de4aca8b599ad7303d29f8fa15905a00f9b0e0 100644
--- a/substrate/frame/support/procedural/src/pallet/parse/event.rs
+++ b/substrate/frame/support/procedural/src/pallet/parse/event.rs
@@ -16,13 +16,11 @@
 // limitations under the License.
 
 use super::helper;
-use frame_support_procedural_tools::clean_type_string;
 use quote::ToTokens;
 use syn::spanned::Spanned;
 
 /// List of additional token to be used for parsing.
 mod keyword {
-	syn::custom_keyword!(metadata);
 	syn::custom_keyword!(Event);
 	syn::custom_keyword!(pallet);
 	syn::custom_keyword!(generate_deposit);
@@ -35,60 +33,31 @@ pub struct EventDef {
 	pub index: usize,
 	/// The keyword Event used (contains span).
 	pub event: keyword::Event,
-	/// Event metadatas: `(name, args, docs)`.
-	pub metadata: Vec<(syn::Ident, Vec<String>, Vec<syn::Lit>)>,
 	/// A set of usage of instance, must be check for consistency with trait.
 	pub instances: Vec<helper::InstanceUsage>,
 	/// The kind of generic the type `Event` has.
 	pub gen_kind: super::GenericKind,
 	/// Whether the function `deposit_event` must be generated.
-	pub deposit_event: Option<(syn::Visibility, proc_macro2::Span)>,
+	pub deposit_event: Option<PalletEventDepositAttr>,
 	/// Where clause used in event definition.
 	pub where_clause: Option<syn::WhereClause>,
 	/// The span of the pallet::event attribute.
 	pub attr_span: proc_macro2::Span,
 }
 
-/// Attribute for Event: defines metadata name to use.
+/// Attribute for a pallet's Event.
 ///
 /// Syntax is:
-/// * `#[pallet::metadata(SomeType = MetadataName, ...)]`
 /// * `#[pallet::generate_deposit($vis fn deposit_event)]`
-enum PalletEventAttr {
-	Metadata {
-		metadata: Vec<(syn::Type, String)>,
-		// Span of the attribute
-		span: proc_macro2::Span,
-	},
-	DepositEvent {
-		fn_vis: syn::Visibility,
-		// Span for the keyword deposit_event
-		fn_span: proc_macro2::Span,
-		// Span of the attribute
-		span: proc_macro2::Span,
-	},
+pub struct PalletEventDepositAttr {
+	pub fn_vis: syn::Visibility,
+	// Span for the keyword deposit_event
+	pub fn_span: proc_macro2::Span,
+	// Span of the attribute
+	pub span: proc_macro2::Span,
 }
 
-impl PalletEventAttr {
-	fn span(&self) -> proc_macro2::Span {
-		match self {
-			Self::Metadata { span, .. } => *span,
-			Self::DepositEvent { span, .. } => *span,
-		}
-	}
-}
-
-/// Parse for syntax `$Type = "$SomeString"`.
-fn parse_event_metadata_element(
-	input: syn::parse::ParseStream,
-) -> syn::Result<(syn::Type, String)> {
-	let typ = input.parse::<syn::Type>()?;
-	input.parse::<syn::Token![=]>()?;
-	let ident = input.parse::<syn::LitStr>()?;
-	Ok((typ, ident.value()))
-}
-
-impl syn::parse::Parse for PalletEventAttr {
+impl syn::parse::Parse for PalletEventDepositAttr {
 	fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
 		input.parse::<syn::Token![#]>()?;
 		let content;
@@ -96,56 +65,33 @@ impl syn::parse::Parse for PalletEventAttr {
 		content.parse::<keyword::pallet>()?;
 		content.parse::<syn::Token![::]>()?;
 
-		let lookahead = content.lookahead1();
-		if lookahead.peek(keyword::metadata) {
-			let span = content.parse::<keyword::metadata>()?.span();
-			let metadata_content;
-			syn::parenthesized!(metadata_content in content);
-
-			let metadata = metadata_content
-				.parse_terminated::<_, syn::Token![,]>(parse_event_metadata_element)?
-				.into_pairs()
-				.map(syn::punctuated::Pair::into_value)
-				.collect();
-
-			Ok(PalletEventAttr::Metadata { metadata, span })
-		} else if lookahead.peek(keyword::generate_deposit) {
-			let span = content.parse::<keyword::generate_deposit>()?.span();
-
-			let generate_content;
-			syn::parenthesized!(generate_content in content);
-			let fn_vis = generate_content.parse::<syn::Visibility>()?;
-			generate_content.parse::<syn::Token![fn]>()?;
-			let fn_span = generate_content.parse::<keyword::deposit_event>()?.span();
-
-			Ok(PalletEventAttr::DepositEvent { fn_vis, span, fn_span })
-		} else {
-			Err(lookahead.error())
-		}
+		let span = content.parse::<keyword::generate_deposit>()?.span();
+		let generate_content;
+		syn::parenthesized!(generate_content in content);
+		let fn_vis = generate_content.parse::<syn::Visibility>()?;
+		generate_content.parse::<syn::Token![fn]>()?;
+		let fn_span = generate_content.parse::<keyword::deposit_event>()?.span();
+
+		Ok(PalletEventDepositAttr { fn_vis, span, fn_span })
 	}
 }
 
 struct PalletEventAttrInfo {
-	metadata: Option<Vec<(syn::Type, String)>>,
-	deposit_event: Option<(syn::Visibility, proc_macro2::Span)>,
+	deposit_event: Option<PalletEventDepositAttr>,
 }
 
 impl PalletEventAttrInfo {
-	fn from_attrs(attrs: Vec<PalletEventAttr>) -> syn::Result<Self> {
-		let mut metadata = None;
+	fn from_attrs(attrs: Vec<PalletEventDepositAttr>) -> syn::Result<Self> {
 		let mut deposit_event = None;
 		for attr in attrs {
-			match attr {
-				PalletEventAttr::Metadata { metadata: m, .. } if metadata.is_none() =>
-					metadata = Some(m),
-				PalletEventAttr::DepositEvent { fn_vis, fn_span, .. }
-					if deposit_event.is_none() =>
-					deposit_event = Some((fn_vis, fn_span)),
-				attr => return Err(syn::Error::new(attr.span(), "Duplicate attribute")),
+			if deposit_event.is_none() {
+				deposit_event = Some(attr)
+			} else {
+				return Err(syn::Error::new(attr.span, "Duplicate attribute"))
 			}
 		}
 
-		Ok(PalletEventAttrInfo { metadata, deposit_event })
+		Ok(PalletEventAttrInfo { deposit_event })
 	}
 }
 
@@ -161,9 +107,9 @@ impl EventDef {
 			return Err(syn::Error::new(item.span(), "Invalid pallet::event, expected item enum"))
 		};
 
-		let event_attrs: Vec<PalletEventAttr> = helper::take_item_pallet_attrs(&mut item.attrs)?;
+		let event_attrs: Vec<PalletEventDepositAttr> =
+			helper::take_item_pallet_attrs(&mut item.attrs)?;
 		let attr_info = PalletEventAttrInfo::from_attrs(event_attrs)?;
-		let metadata = attr_info.metadata.unwrap_or_else(Vec::new);
 		let deposit_event = attr_info.deposit_event;
 
 		if !matches!(item.vis, syn::Visibility::Public(_)) {
@@ -190,39 +136,6 @@ impl EventDef {
 
 		let event = syn::parse2::<keyword::Event>(item.ident.to_token_stream())?;
 
-		let metadata = item
-			.variants
-			.iter()
-			.map(|variant| {
-				let name = variant.ident.clone();
-				let docs = helper::get_doc_literals(&variant.attrs);
-				let args = variant
-					.fields
-					.iter()
-					.map(|field| {
-						metadata
-							.iter()
-							.find(|m| m.0 == field.ty)
-							.map(|m| m.1.clone())
-							.unwrap_or_else(|| {
-								clean_type_string(&field.ty.to_token_stream().to_string())
-							})
-					})
-					.collect();
-
-				(name, args, docs)
-			})
-			.collect();
-
-		Ok(EventDef {
-			attr_span,
-			index,
-			metadata,
-			instances,
-			deposit_event,
-			event,
-			gen_kind,
-			where_clause,
-		})
+		Ok(EventDef { attr_span, index, instances, deposit_event, event, gen_kind, where_clause })
 	}
 }
diff --git a/substrate/frame/support/procedural/src/pallet/parse/extra_constants.rs b/substrate/frame/support/procedural/src/pallet/parse/extra_constants.rs
index 71208f3329a107872e5e6189fb107f1c378fb5d9..c1324df6c22f15e1c438712f89c9b55895dbeb92 100644
--- a/substrate/frame/support/procedural/src/pallet/parse/extra_constants.rs
+++ b/substrate/frame/support/procedural/src/pallet/parse/extra_constants.rs
@@ -16,6 +16,7 @@
 // limitations under the License.
 
 use super::helper;
+use frame_support_procedural_tools::get_doc_literals;
 use syn::spanned::Spanned;
 
 /// List of additional token to be used for parsing.
@@ -104,7 +105,7 @@ impl ExtraConstantsDef {
 			extra_constants.push(ExtraConstantDef {
 				ident: method.sig.ident.clone(),
 				type_,
-				doc: helper::get_doc_literals(&method.attrs),
+				doc: get_doc_literals(&method.attrs),
 			});
 		}
 
diff --git a/substrate/frame/support/procedural/src/pallet/parse/helper.rs b/substrate/frame/support/procedural/src/pallet/parse/helper.rs
index 211f1ed5ee428d8bc3905619879900a84e46212b..2590e86b58b0eac5b6a571c049f710017fba688d 100644
--- a/substrate/frame/support/procedural/src/pallet/parse/helper.rs
+++ b/substrate/frame/support/procedural/src/pallet/parse/helper.rs
@@ -139,24 +139,6 @@ impl MutItemAttrs for syn::ItemMod {
 	}
 }
 
-/// Return all doc attributes literals found.
-pub fn get_doc_literals(attrs: &Vec<syn::Attribute>) -> Vec<syn::Lit> {
-	attrs
-		.iter()
-		.filter_map(|attr| {
-			if let Ok(syn::Meta::NameValue(meta)) = attr.parse_meta() {
-				if meta.path.get_ident().map_or(false, |ident| ident == "doc") {
-					Some(meta.lit)
-				} else {
-					None
-				}
-			} else {
-				None
-			}
-		})
-		.collect()
-}
-
 /// Parse for `()`
 struct Unit;
 impl syn::parse::Parse for Unit {
diff --git a/substrate/frame/support/procedural/src/pallet/parse/storage.rs b/substrate/frame/support/procedural/src/pallet/parse/storage.rs
index 5df7bc132dff4cea138f6803c5ebaf67547edcbf..e58b5d204886393c045d1f7780f8154cab0e174a 100644
--- a/substrate/frame/support/procedural/src/pallet/parse/storage.rs
+++ b/substrate/frame/support/procedural/src/pallet/parse/storage.rs
@@ -16,6 +16,7 @@
 // limitations under the License.
 
 use super::helper;
+use frame_support_procedural_tools::get_doc_literals;
 use quote::ToTokens;
 use std::collections::HashMap;
 use syn::spanned::Spanned;
@@ -609,7 +610,7 @@ impl StorageDef {
 		instances.push(helper::check_type_def_gen(&item.generics, item.ident.span())?);
 
 		let where_clause = item.generics.where_clause.clone();
-		let docs = helper::get_doc_literals(&item.attrs);
+		let docs = get_doc_literals(&item.attrs);
 
 		let typ = if let syn::Type::Path(typ) = &*item.ty {
 			typ
diff --git a/substrate/frame/support/procedural/src/storage/instance_trait.rs b/substrate/frame/support/procedural/src/storage/instance_trait.rs
index 4f55d38596666f2ae11ef16475a5023a9238ffd2..00a73d6fbd6e7ef43a4f614d4d1d028e8442d412 100644
--- a/substrate/frame/support/procedural/src/storage/instance_trait.rs
+++ b/substrate/frame/support/procedural/src/storage/instance_trait.rs
@@ -126,6 +126,7 @@ fn create_and_impl_instance_struct(
 			Clone, Eq, PartialEq,
 			#scrate::codec::Encode,
 			#scrate::codec::Decode,
+			#scrate::scale_info::TypeInfo,
 			#scrate::RuntimeDebug,
 		)]
 		#doc
diff --git a/substrate/frame/support/procedural/src/storage/metadata.rs b/substrate/frame/support/procedural/src/storage/metadata.rs
index ca7dd97c155f399d66e062b8c132cae6b007b98f..a90e5051c5b2e6180b6b448782d519695eb8da4a 100644
--- a/substrate/frame/support/procedural/src/storage/metadata.rs
+++ b/substrate/frame/support/procedural/src/storage/metadata.rs
@@ -18,31 +18,28 @@
 //! Implementation of `storage_metadata` on module structure, used by construct_runtime.
 
 use super::{DeclStorageDefExt, StorageLineDefExt, StorageLineTypeDef};
-use frame_support_procedural_tools::clean_type_string;
+use frame_support_procedural_tools::get_doc_literals;
 use proc_macro2::TokenStream;
 use quote::quote;
 
 fn storage_line_metadata_type(scrate: &TokenStream, line: &StorageLineDefExt) -> TokenStream {
 	let value_type = &line.value_type;
-	let value_type = clean_type_string(&quote!( #value_type ).to_string());
 	match &line.storage_type {
 		StorageLineTypeDef::Simple(_) => {
 			quote! {
 				#scrate::metadata::StorageEntryType::Plain(
-					#scrate::metadata::DecodeDifferent::Encode(#value_type),
+					#scrate::scale_info::meta_type::<#value_type>()
 				)
 			}
 		},
 		StorageLineTypeDef::Map(map) => {
 			let hasher = map.hasher.into_metadata();
 			let key = &map.key;
-			let key = clean_type_string(&quote!(#key).to_string());
 			quote! {
 				#scrate::metadata::StorageEntryType::Map {
-					hasher: #scrate::metadata::#hasher,
-					key: #scrate::metadata::DecodeDifferent::Encode(#key),
-					value: #scrate::metadata::DecodeDifferent::Encode(#value_type),
-					unused: false,
+					hashers: #scrate::sp_std::vec! [ #scrate::metadata::#hasher ],
+					key: #scrate::scale_info::meta_type::<#key>(),
+					value: #scrate::scale_info::meta_type::<#value_type>(),
 				}
 			}
 		},
@@ -50,39 +47,32 @@ fn storage_line_metadata_type(scrate: &TokenStream, line: &StorageLineDefExt) ->
 			let hasher1 = map.hasher1.into_metadata();
 			let hasher2 = map.hasher2.into_metadata();
 			let key1 = &map.key1;
-			let key1 = clean_type_string(&quote!(#key1).to_string());
 			let key2 = &map.key2;
-			let key2 = clean_type_string(&quote!(#key2).to_string());
 			quote! {
-				#scrate::metadata::StorageEntryType::DoubleMap {
-					hasher: #scrate::metadata::#hasher1,
-					key1: #scrate::metadata::DecodeDifferent::Encode(#key1),
-					key2: #scrate::metadata::DecodeDifferent::Encode(#key2),
-					value: #scrate::metadata::DecodeDifferent::Encode(#value_type),
-					key2_hasher: #scrate::metadata::#hasher2,
+				#scrate::metadata::StorageEntryType::Map {
+					hashers: #scrate::sp_std::vec! [
+						#scrate::metadata::#hasher1,
+						#scrate::metadata::#hasher2,
+					],
+					key: #scrate::scale_info::meta_type::<(#key1, #key2)>(),
+					value: #scrate::scale_info::meta_type::<#value_type>(),
 				}
 			}
 		},
 		StorageLineTypeDef::NMap(map) => {
-			let keys = map
-				.keys
-				.iter()
-				.map(|key| clean_type_string(&quote!(#key).to_string()))
-				.collect::<Vec<_>>();
+			let key_tuple = &map.to_key_tuple();
 			let hashers = map
 				.hashers
 				.iter()
 				.map(|hasher| hasher.to_storage_hasher_struct())
 				.collect::<Vec<_>>();
 			quote! {
-				#scrate::metadata::StorageEntryType::NMap {
-					keys: #scrate::metadata::DecodeDifferent::Encode(&[
-						#( #keys, )*
-					]),
-					hashers: #scrate::metadata::DecodeDifferent::Encode(&[
+				#scrate::metadata::StorageEntryType::Map {
+					hashers: #scrate::sp_std::vec! [
 						#( #scrate::metadata::StorageHasher::#hashers, )*
-					]),
-					value: #scrate::metadata::DecodeDifferent::Encode(#value_type),
+					],
+					key: #scrate::scale_info::meta_type::<#key_tuple>(),
+					value: #scrate::scale_info::meta_type::<#value_type>(),
 				}
 			}
 		},
@@ -129,8 +119,7 @@ fn default_byte_getter(
 
 		#[cfg(feature = "std")]
 		impl<#runtime_generic: #runtime_trait, #optional_instance_bound>
-			#scrate::metadata::DefaultByte
-			for #struct_name<#runtime_generic, #optional_instance>
+			#struct_name<#runtime_generic, #optional_instance>
 			#where_clause
 		{
 			fn default_byte(&self) -> #scrate::sp_std::vec::Vec<u8> {
@@ -142,16 +131,9 @@ fn default_byte_getter(
 			}
 		}
 
-		unsafe impl<#runtime_generic: #runtime_trait, #optional_instance_bound> Send
-			for #struct_name<#runtime_generic, #optional_instance> #where_clause {}
-
-		unsafe impl<#runtime_generic: #runtime_trait, #optional_instance_bound> Sync
-			for #struct_name<#runtime_generic, #optional_instance> #where_clause {}
-
 		#[cfg(not(feature = "std"))]
 		impl<#runtime_generic: #runtime_trait, #optional_instance_bound>
-			#scrate::metadata::DefaultByte
-			for #struct_name<#runtime_generic, #optional_instance>
+			#struct_name<#runtime_generic, #optional_instance>
 			#where_clause
 		{
 			fn default_byte(&self) -> #scrate::sp_std::vec::Vec<u8> {
@@ -187,25 +169,15 @@ pub fn impl_metadata(def: &DeclStorageDefExt) -> TokenStream {
 		let (default_byte_getter_struct_def, default_byte_getter_struct_instance) =
 			default_byte_getter(scrate, line, def);
 
-		let mut docs = TokenStream::new();
-		for attr in line.attrs.iter().filter_map(|v| v.parse_meta().ok()) {
-			if let syn::Meta::NameValue(meta) = attr {
-				if meta.path.is_ident("doc") {
-					let lit = meta.lit;
-					docs.extend(quote!(#lit,));
-				}
-			}
-		}
+		let docs = get_doc_literals(&line.attrs);
 
 		let entry = quote! {
 			#scrate::metadata::StorageEntryMetadata {
-				name: #scrate::metadata::DecodeDifferent::Encode(#str_name),
+				name: #str_name,
 				modifier: #modifier,
 				ty: #ty,
-				default: #scrate::metadata::DecodeDifferent::Encode(
-					#scrate::metadata::DefaultByteGetter(&#default_byte_getter_struct_instance)
-				),
-				documentation: #scrate::metadata::DecodeDifferent::Encode(&[ #docs ]),
+				default: #default_byte_getter_struct_instance.default_byte(),
+				docs: #scrate::sp_std::vec![ #( #docs ),* ],
 			},
 		};
 
@@ -222,9 +194,9 @@ pub fn impl_metadata(def: &DeclStorageDefExt) -> TokenStream {
 	};
 
 	let store_metadata = quote!(
-		#scrate::metadata::StorageMetadata {
-			prefix: #scrate::metadata::DecodeDifferent::Encode(#prefix),
-			entries: #scrate::metadata::DecodeDifferent::Encode(&[ #entries ][..]),
+		#scrate::metadata::PalletStorageMetadata {
+			prefix: #prefix,
+			entries: #scrate::sp_std::vec![ #entries ],
 		}
 	);
 
@@ -237,7 +209,7 @@ pub fn impl_metadata(def: &DeclStorageDefExt) -> TokenStream {
 
 		impl#module_impl #module_struct #where_clause {
 			#[doc(hidden)]
-			pub fn storage_metadata() -> #scrate::metadata::StorageMetadata {
+			pub fn storage_metadata() -> #scrate::metadata::PalletStorageMetadata {
 				#store_metadata
 			}
 		}
diff --git a/substrate/frame/support/procedural/tools/src/lib.rs b/substrate/frame/support/procedural/tools/src/lib.rs
index 19242db4594c0318d1e7b0e8a9836e696a74aca2..d7aba4c7cbf1cc6f83d1ac3f7a9f2d745ebca344 100644
--- a/substrate/frame/support/procedural/tools/src/lib.rs
+++ b/substrate/frame/support/procedural/tools/src/lib.rs
@@ -100,3 +100,21 @@ pub fn clean_type_string(input: &str) -> String {
 		.replace("< ", "<")
 		.replace(" >", ">")
 }
+
+/// Return all doc attributes literals found.
+pub fn get_doc_literals(attrs: &[syn::Attribute]) -> Vec<syn::Lit> {
+	attrs
+		.iter()
+		.filter_map(|attr| {
+			if let Ok(syn::Meta::NameValue(meta)) = attr.parse_meta() {
+				if meta.path.get_ident().map_or(false, |ident| ident == "doc") {
+					Some(meta.lit)
+				} else {
+					None
+				}
+			} else {
+				None
+			}
+		})
+		.collect()
+}
diff --git a/substrate/frame/support/src/dispatch.rs b/substrate/frame/support/src/dispatch.rs
index a4644cebeeb55d3bdb455ba7cfb29baf3fedb19d..2e6777fee2af25ef1b30aba8bd163a15ca173b48 100644
--- a/substrate/frame/support/src/dispatch.rs
+++ b/substrate/frame/support/src/dispatch.rs
@@ -33,10 +33,6 @@ pub use crate::{
 		TransactionPriority, WeighData, Weight, WithPostDispatchInfo,
 	},
 };
-pub use frame_metadata::{
-	DecodeDifferent, DecodeDifferentArray, DefaultByte, DefaultByteGetter, ErrorMetadata,
-	FunctionArgumentMetadata, FunctionMetadata, ModuleConstantMetadata, ModuleErrorMetadata,
-};
 pub use sp_runtime::{traits::Dispatchable, DispatchError};
 
 /// The return type of a `Dispatchable` in frame. When returned explicitly from
@@ -67,8 +63,8 @@ pub type CallableCallFor<A, R> = <A as Callable<R>>::Call;
 /// A type that can be used as a parameter in a dispatchable function.
 ///
 /// When using `decl_module` all arguments for call functions must implement this trait.
-pub trait Parameter: Codec + EncodeLike + Clone + Eq + fmt::Debug {}
-impl<T> Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {}
+pub trait Parameter: Codec + EncodeLike + Clone + Eq + fmt::Debug + scale_info::TypeInfo {}
+impl<T> Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug + scale_info::TypeInfo {}
 
 /// Declares a `Module` struct and a `Call` enum, which implements the dispatch logic.
 ///
@@ -1169,7 +1165,7 @@ macro_rules! decl_module {
 			{ $( $on_finalize )* }
 			{ $( $offchain )* }
 			{ $( $constants )* }
-			{ &'static str }
+			{ __NO_ERROR_DEFINED }
 			{ $( $integrity_test )* }
 			{ $( $storage_version )* }
 			[ $($t)* ]
@@ -1239,7 +1235,7 @@ macro_rules! decl_module {
 		{ $( $on_finalize:tt )* }
 		{ $( $offchain:tt )* }
 		{ $( $constants:tt )* }
-		{ $error_type:ty }
+		{ $( $error_type:tt )* }
 		{ $( $integrity_test:tt )* }
 		{ $( $storage_version:tt )* }
 		[ $( $dispatchables:tt )* ]
@@ -1265,8 +1261,8 @@ macro_rules! decl_module {
 			{ $( $on_finalize )* }
 			{ $( $offchain )* }
 			{ $( $constants )* }
-			{ $error_type }
-			{ $( $integrity_test )* }
+			{ $( $error_type )* }
+			{ $( $integrity_test)* }
 			{ $( $storage_version )* }
 			[
 				$( $dispatchables )*
@@ -1750,7 +1746,6 @@ macro_rules! decl_module {
 	(@impl_function
 		$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
 		$origin_ty:ty;
-		$error_type:ty;
 		$ignore:ident;
 		$(#[$fn_attr:meta])*
 		$vis:vis fn $name:ident (
@@ -1772,7 +1767,6 @@ macro_rules! decl_module {
 	(@impl_function
 		$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
 		$origin_ty:ty;
-		$error_type:ty;
 		$ignore:ident;
 		$(#[$fn_attr:meta])*
 		$vis:vis fn $name:ident (
@@ -1796,7 +1790,7 @@ macro_rules! decl_module {
 		variant $fn_name:ident;
 		$( #[doc = $doc_attr:tt] )*
 		#[compact]
-		$type:ty;
+		$name:ident : $type:ty;
 		$( $rest:tt )*
 	) => {
 		$crate::decl_module! {
@@ -1808,7 +1802,7 @@ macro_rules! decl_module {
 			{
 				$( $current_params )*
 				#[codec(compact)]
-				$type,
+				$name: $type,
 			}
 			variant $fn_name;
 			$( #[doc = $doc_attr] )*
@@ -1825,7 +1819,7 @@ macro_rules! decl_module {
 		{ $( $current_params:tt )* }
 		variant $fn_name:ident;
 		$(#[doc = $doc_attr:tt])*
-		$type:ty;
+		$name:ident : $type:ty;
 		$( $rest:tt )*
 	) => {
 		$crate::decl_module! {
@@ -1836,7 +1830,7 @@ macro_rules! decl_module {
 			{ $( $generated_variants )* }
 			{
 				$( $current_params )*
-				$type,
+				$name: $type,
 			}
 			variant $fn_name;
 			$( #[doc = $doc_attr] )*
@@ -1866,9 +1860,9 @@ macro_rules! decl_module {
 				$( $generated_variants )*
 				#[allow(non_camel_case_types)]
 				$(#[doc = $doc_attr])*
-				$fn_name (
+				$fn_name {
 					$( $current_params )*
-				),
+				},
 			}
 			{}
 			$(
@@ -1888,7 +1882,8 @@ macro_rules! decl_module {
 		/// Dispatchable calls.
 		///
 		/// Each variant of this enum maps to a dispatchable function from the associated module.
-		#[derive($crate::codec::Encode, $crate::codec::Decode)]
+		#[derive($crate::codec::Encode, $crate::codec::Decode, $crate::scale_info::TypeInfo)]
+		#[scale_info(skip_type_params($trait_instance $(, $instance)?), capture_docs = "always")]
 		pub enum $call_type<$trait_instance: $trait_name$(<I>, $instance: $instantiable $( = $module_default_instance)?)?>
 			where $( $other_where_bounds )*
 		{
@@ -1965,7 +1960,7 @@ macro_rules! decl_module {
 		{ $( $on_finalize:tt )* }
 		{ $( $offchain:tt )* }
 		{ $( $constants:tt )* }
-		{ $error_type:ty }
+		{ $( $error_type:tt )* }
 		{ $( $integrity_test:tt )* }
 		{ $( $storage_version:tt )* }
 	) => {
@@ -2051,7 +2046,6 @@ macro_rules! decl_module {
 					@impl_function
 					$mod_type<$trait_instance: $trait_name $(<I>, $fn_instance: $fn_instantiable)?>;
 					$origin_type;
-					$error_type;
 					$from;
 					$(#[doc = $doc_attr])*
 					///
@@ -2076,11 +2070,28 @@ macro_rules! decl_module {
 				$(#[doc = $doc_attr])*
 				$(
 					$(#[$codec_attr])*
-					$param;
+					$param_name : $param;
 				)*
 			)*
 		}
 
+		$crate::paste::paste! {
+			impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>
+				$call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
+			{
+				$(
+					#[doc = "Create a call with the variant `" $fn_name "`."]
+					pub fn [< new_call_variant_ $fn_name >](
+						$( $param_name: $param ),*
+					) -> Self {
+						Self::$fn_name {
+							$( $param_name ),*
+						}
+					}
+				)*
+			}
+		}
+
 		$crate::decl_module! {
 			@impl_get_storage_version
 			$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
@@ -2095,7 +2106,7 @@ macro_rules! decl_module {
 			fn get_dispatch_info(&self) -> $crate::dispatch::DispatchInfo {
 				match *self {
 					$(
-						$call_type::$fn_name( $( ref $param_name ),* ) => {
+						$call_type::$fn_name { $( ref $param_name ),* } => {
 							let __pallet_base_weight = $weight;
 							let __pallet_weight = <dyn $crate::dispatch::WeighData<( $( & $param, )* )>>::weigh_data(
 								&__pallet_base_weight,
@@ -2149,7 +2160,7 @@ macro_rules! decl_module {
 			fn get_call_name(&self) -> &'static str {
 				match *self {
 					$(
-						$call_type::$fn_name( $( ref $param_name ),* ) => {
+						$call_type::$fn_name { $( ref $param_name ),* } => {
 							// Don't generate any warnings for unused variables
 							let _ = ( $( $param_name ),* );
 							stringify!($fn_name)
@@ -2186,8 +2197,8 @@ macro_rules! decl_module {
 			fn clone(&self) -> Self {
 				match *self {
 					$(
-						$call_type::$fn_name( $( ref $param_name ),* ) =>
-							$call_type::$fn_name( $( (*$param_name).clone() ),* )
+						$call_type::$fn_name { $( ref $param_name ),* } =>
+							$call_type::$fn_name { $( $param_name: (*$param_name).clone() ),* }
 					,)*
 					_ => unreachable!(),
 				}
@@ -2200,9 +2211,9 @@ macro_rules! decl_module {
 			fn eq(&self, _other: &Self) -> bool {
 				match *self {
 					$(
-						$call_type::$fn_name( $( ref $param_name ),* ) => {
+						$call_type::$fn_name { $( ref $param_name ),* } => {
 							let self_params = ( $( $param_name, )* );
-							if let $call_type::$fn_name( $( ref $param_name ),* ) = *_other {
+							if let $call_type::$fn_name { $( ref $param_name ),* } = *_other {
 								self_params == ( $( $param_name, )* )
 							} else {
 								match *_other {
@@ -2230,7 +2241,7 @@ macro_rules! decl_module {
 			) -> $crate::dispatch::result::Result<(), $crate::dispatch::fmt::Error> {
 				match *self {
 					$(
-						$call_type::$fn_name( $( ref $param_name ),* ) =>
+						$call_type::$fn_name { $( ref $param_name ),* } =>
 							write!(_f, "{}{:?}",
 								stringify!($fn_name),
 								( $( $param_name.clone(), )* )
@@ -2248,7 +2259,7 @@ macro_rules! decl_module {
 			fn dispatch_bypass_filter(self, _origin: Self::Origin) -> $crate::dispatch::DispatchResultWithPostInfo {
 				match self {
 					$(
-						$call_type::$fn_name( $( $param_name ),* ) => {
+						$call_type::$fn_name { $( $param_name ),* } => {
 							$crate::decl_module!(
 								@call
 								$from
@@ -2277,20 +2288,17 @@ macro_rules! decl_module {
 				)*
 			}
 		}
+		$crate::__impl_error_metadata! {
+			$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>
+			{ $( $other_where_bounds )* }
+			$( $error_type )*
+		}
 		$crate::__impl_module_constants_metadata ! {
 			$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>
 			{ $( $other_where_bounds )* }
 			$( $constants )*
 		}
 
-		impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::ModuleErrorMetadata
-			for $mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
-		{
-			fn metadata() -> &'static [$crate::dispatch::ErrorMetadata] {
-				<$error_type as $crate::dispatch::ModuleErrorMetadata>::metadata()
-			}
-		}
-
 		$crate::__generate_dummy_part_checker!();
 	}
 }
@@ -2302,6 +2310,7 @@ macro_rules! __dispatch_impl_metadata {
 	(
 		$mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>
 		{ $( $other_where_bounds:tt )* }
+		$call_type:ident
 		$($rest:tt)*
 	) => {
 		impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?>
@@ -2309,13 +2318,51 @@ macro_rules! __dispatch_impl_metadata {
 		{
 			#[doc(hidden)]
 			#[allow(dead_code)]
-			pub fn call_functions() -> &'static [$crate::dispatch::FunctionMetadata] {
-				$crate::__call_to_functions!($($rest)*)
+			pub fn call_functions() -> $crate::metadata::PalletCallMetadata {
+				$crate::scale_info::meta_type::<$call_type<$trait_instance $(, $instance)?>>().into()
 			}
 		}
 	}
 }
 
+/// Implement metadata for pallet error.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! __impl_error_metadata {
+	(
+		$mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>
+		{ $( $other_where_bounds:tt )* }
+		__NO_ERROR_DEFINED
+	) => {
+		impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?>
+			where $( $other_where_bounds )*
+		{
+			#[doc(hidden)]
+			#[allow(dead_code)]
+			pub fn error_metadata() -> Option<$crate::metadata::PalletErrorMetadata> {
+				None
+			}
+		}
+	};
+	(
+		$mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>
+		{ $( $other_where_bounds:tt )* }
+		$( $error_type:tt )*
+	) => {
+		impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?>
+			where $( $other_where_bounds )*
+		{
+			#[doc(hidden)]
+			#[allow(dead_code)]
+			pub fn error_metadata() -> Option<$crate::metadata::PalletErrorMetadata> {
+				Some($crate::metadata::PalletErrorMetadata {
+					ty: $crate::scale_info::meta_type::<$( $error_type )*>()
+				})
+			}
+		}
+	};
+}
+
 /// Implement metadata for module constants.
 #[macro_export]
 #[doc(hidden)]
@@ -2383,7 +2430,7 @@ macro_rules! __impl_module_constants_metadata {
 		{
 			#[doc(hidden)]
 			#[allow(dead_code)]
-			pub fn module_constants_metadata() -> &'static [$crate::dispatch::ModuleConstantMetadata] {
+			pub fn pallet_constants_metadata() -> $crate::sp_std::vec::Vec<$crate::metadata::PalletConstantMetadata> {
 				// Create the `ByteGetter`s
 				$(
 					#[allow(non_upper_case_types)]
@@ -2397,40 +2444,23 @@ macro_rules! __impl_module_constants_metadata {
 					>);
 					impl<$const_trait_instance: 'static + $const_trait_name $(
 						<I>, $const_instance: $const_instantiable)?
-					> $crate::dispatch::DefaultByte
-						for $default_byte_name <$const_trait_instance $(, $const_instance)?>
+					> $default_byte_name <$const_trait_instance $(, $const_instance)?>
 					{
 						fn default_byte(&self) -> $crate::dispatch::Vec<u8> {
 							let value: $type = $value;
 							$crate::dispatch::Encode::encode(&value)
 						}
 					}
-
-					unsafe impl<$const_trait_instance: 'static + $const_trait_name $(
-						<I>, $const_instance: $const_instantiable)?
-					> Send for $default_byte_name <$const_trait_instance $(, $const_instance)?> {}
-
-					unsafe impl<$const_trait_instance: 'static + $const_trait_name $(
-						<I>, $const_instance: $const_instantiable)?
-					> Sync for $default_byte_name <$const_trait_instance $(, $const_instance)?> {}
 				)*
-				&[
+				$crate::sp_std::vec![
 					$(
-						$crate::dispatch::ModuleConstantMetadata {
-							name: $crate::dispatch::DecodeDifferent::Encode(stringify!($name)),
-							ty: $crate::dispatch::DecodeDifferent::Encode(stringify!($type)),
-							value: $crate::dispatch::DecodeDifferent::Encode(
-								$crate::dispatch::DefaultByteGetter(
-									&$default_byte_name::<
-										$const_trait_instance $(, $const_instance)?
-									>(
-										$crate::dispatch::marker::PhantomData
-									)
-								)
-							),
-							documentation: $crate::dispatch::DecodeDifferent::Encode(
-								&[ $( $doc_attr ),* ]
-							),
+						$crate::metadata::PalletConstantMetadata {
+							name: stringify!($name),
+							ty: $crate::scale_info::meta_type::<$type>(),
+							value: $default_byte_name::<$const_trait_instance $(, $const_instance)?>(
+								Default::default()
+							).default_byte(),
+							docs: $crate::sp_std::vec![ $( $doc_attr ),* ],
 						}
 					),*
 				]
@@ -2439,106 +2469,6 @@ macro_rules! __impl_module_constants_metadata {
 	}
 }
 
-/// Convert the list of calls into their JSON representation, joined by ",".
-#[macro_export]
-#[doc(hidden)]
-macro_rules! __call_to_functions {
-	(
-		$call_type:ident $origin_type:ty
-		{
-			$(
-				$(#[doc = $doc_attr:tt])*
-				fn $fn_name:ident($from:ident
-					$(
-						, $(#[$codec_attr:ident])* $param_name:ident : $param:ty
-					)*
-				);
-			)*
-		}
-	) => {
-		$crate::__functions_to_metadata!(0; $origin_type;; $(
-			fn $fn_name( $($(#[$codec_attr])* $param_name: $param ),* );
-			$( $doc_attr ),*;
-		)*)
-	};
-}
-
-/// Convert a list of functions into a list of `FunctionMetadata` items.
-#[macro_export]
-#[doc(hidden)]
-macro_rules! __functions_to_metadata{
-	(
-		$fn_id:expr;
-		$origin_type:ty;
-		$( $function_metadata:expr ),*;
-		fn $fn_name:ident(
-			$(
-				$(#[$codec_attr:ident])* $param_name:ident : $param:ty
-			),*
-		);
-		$( $fn_doc:expr ),*;
-		$( $rest:tt )*
-	) => {
-		$crate::__functions_to_metadata!(
-			$fn_id + 1; $origin_type;
-			$( $function_metadata, )* $crate::__function_to_metadata!(
-				fn $fn_name($( $(#[$codec_attr])* $param_name : $param ),*); $( $fn_doc ),*; $fn_id;
-			);
-			$($rest)*
-		)
-	};
-	(
-		$fn_id:expr;
-		$origin_type:ty;
-		$( $function_metadata:expr ),*;
-	) => {
-		&[ $( $function_metadata ),* ]
-	}
-}
-
-/// Convert a function into its metadata representation.
-#[macro_export]
-#[doc(hidden)]
-macro_rules! __function_to_metadata {
-	(
-		fn $fn_name:ident(
-			$( $(#[$codec_attr:ident])* $param_name:ident : $param:ty),*
-		);
-		$( $fn_doc:expr ),*;
-		$fn_id:expr;
-	) => {
-		$crate::dispatch::FunctionMetadata {
-			name: $crate::dispatch::DecodeDifferent::Encode(stringify!($fn_name)),
-			arguments: $crate::dispatch::DecodeDifferent::Encode(&[
-				$(
-					$crate::dispatch::FunctionArgumentMetadata {
-						name: $crate::dispatch::DecodeDifferent::Encode(stringify!($param_name)),
-						ty: $crate::dispatch::DecodeDifferent::Encode(
-							$crate::__function_to_metadata!(@stringify_expand_attr
-								$(#[$codec_attr])* $param_name: $param
-							)
-						),
-					}
-				),*
-			]),
-			documentation: $crate::dispatch::DecodeDifferent::Encode(&[ $( $fn_doc ),* ]),
-		}
-	};
-
-	(@stringify_expand_attr #[compact] $param_name:ident : $param:ty) => {
-		concat!("Compact<", stringify!($param), ">")
-	};
-
-	(@stringify_expand_attr $param_name:ident : $param:ty) => { stringify!($param) };
-
-	(@stringify_expand_attr $(#[codec_attr:ident])* $param_name:ident : $param:ty) => {
-		compile_error!(concat!(
-			"Invalid attribute for parameter `", stringify!($param_name),
-			"`, the following attributes are supported: `#[compact]`"
-		));
-	}
-}
-
 #[macro_export]
 #[doc(hidden)]
 macro_rules! __check_reserved_fn_name {
@@ -2597,6 +2527,7 @@ macro_rules! __check_reserved_fn_name {
 mod tests {
 	use super::*;
 	use crate::{
+		metadata::*,
 		traits::{
 			Get, GetCallName, IntegrityTest, OnFinalize, OnIdle, OnInitialize, OnRuntimeUpgrade,
 			PalletInfo,
@@ -2623,7 +2554,7 @@ mod tests {
 			type DbWeight: Get<RuntimeDbWeight>;
 		}
 
-		#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
+		#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode, scale_info::TypeInfo)]
 		pub enum RawOrigin<AccountId> {
 			Root,
 			Signed(AccountId),
@@ -2679,68 +2610,7 @@ mod tests {
 		}
 	}
 
-	const EXPECTED_METADATA: &'static [FunctionMetadata] = &[
-		FunctionMetadata {
-			name: DecodeDifferent::Encode("aux_0"),
-			arguments: DecodeDifferent::Encode(&[]),
-			documentation: DecodeDifferent::Encode(&[" Hi, this is a comment."]),
-		},
-		FunctionMetadata {
-			name: DecodeDifferent::Encode("aux_1"),
-			arguments: DecodeDifferent::Encode(&[FunctionArgumentMetadata {
-				name: DecodeDifferent::Encode("_data"),
-				ty: DecodeDifferent::Encode("Compact<u32>"),
-			}]),
-			documentation: DecodeDifferent::Encode(&[]),
-		},
-		FunctionMetadata {
-			name: DecodeDifferent::Encode("aux_2"),
-			arguments: DecodeDifferent::Encode(&[
-				FunctionArgumentMetadata {
-					name: DecodeDifferent::Encode("_data"),
-					ty: DecodeDifferent::Encode("i32"),
-				},
-				FunctionArgumentMetadata {
-					name: DecodeDifferent::Encode("_data2"),
-					ty: DecodeDifferent::Encode("String"),
-				},
-			]),
-			documentation: DecodeDifferent::Encode(&[]),
-		},
-		FunctionMetadata {
-			name: DecodeDifferent::Encode("aux_3"),
-			arguments: DecodeDifferent::Encode(&[]),
-			documentation: DecodeDifferent::Encode(&[]),
-		},
-		FunctionMetadata {
-			name: DecodeDifferent::Encode("aux_4"),
-			arguments: DecodeDifferent::Encode(&[FunctionArgumentMetadata {
-				name: DecodeDifferent::Encode("_data"),
-				ty: DecodeDifferent::Encode("i32"),
-			}]),
-			documentation: DecodeDifferent::Encode(&[]),
-		},
-		FunctionMetadata {
-			name: DecodeDifferent::Encode("aux_5"),
-			arguments: DecodeDifferent::Encode(&[
-				FunctionArgumentMetadata {
-					name: DecodeDifferent::Encode("_data"),
-					ty: DecodeDifferent::Encode("i32"),
-				},
-				FunctionArgumentMetadata {
-					name: DecodeDifferent::Encode("_data2"),
-					ty: DecodeDifferent::Encode("Compact<u32>"),
-				},
-			]),
-			documentation: DecodeDifferent::Encode(&[]),
-		},
-		FunctionMetadata {
-			name: DecodeDifferent::Encode("operational"),
-			arguments: DecodeDifferent::Encode(&[]),
-			documentation: DecodeDifferent::Encode(&[]),
-		},
-	];
-
+	#[derive(scale_info::TypeInfo)]
 	pub struct TraitImpl {}
 	impl Config for TraitImpl {}
 
@@ -2823,17 +2693,19 @@ mod tests {
 	#[test]
 	fn module_json_metadata() {
 		let metadata = Module::<TraitImpl>::call_functions();
-		assert_eq!(EXPECTED_METADATA, metadata);
+		let expected_metadata =
+			PalletCallMetadata { ty: scale_info::meta_type::<Call<TraitImpl>>() };
+		assert_eq!(expected_metadata, metadata);
 	}
 
 	#[test]
 	fn compact_attr() {
-		let call: Call<TraitImpl> = Call::aux_1(1);
+		let call: Call<TraitImpl> = Call::aux_1 { _data: 1 };
 		let encoded = call.encode();
 		assert_eq!(2, encoded.len());
 		assert_eq!(vec![1, 4], encoded);
 
-		let call: Call<TraitImpl> = Call::aux_5(1, 2);
+		let call: Call<TraitImpl> = Call::aux_5 { _data: 1, _data2: 2 };
 		let encoded = call.encode();
 		assert_eq!(6, encoded.len());
 		assert_eq!(vec![5, 1, 0, 0, 0, 8], encoded);
@@ -2841,13 +2713,13 @@ mod tests {
 
 	#[test]
 	fn encode_is_correct_and_decode_works() {
-		let call: Call<TraitImpl> = Call::aux_0();
+		let call: Call<TraitImpl> = Call::aux_0 {};
 		let encoded = call.encode();
 		assert_eq!(vec![0], encoded);
 		let decoded = Call::<TraitImpl>::decode(&mut &encoded[..]).unwrap();
 		assert_eq!(decoded, call);
 
-		let call: Call<TraitImpl> = Call::aux_2(32, "hello".into());
+		let call: Call<TraitImpl> = Call::aux_2 { _data: 32, _data2: "hello".into() };
 		let encoded = call.encode();
 		assert_eq!(vec![2, 32, 0, 0, 0, 20, 104, 101, 108, 108, 111], encoded);
 		let decoded = Call::<TraitImpl>::decode(&mut &encoded[..]).unwrap();
@@ -2899,19 +2771,19 @@ mod tests {
 	fn weight_should_attach_to_call_enum() {
 		// operational.
 		assert_eq!(
-			Call::<TraitImpl>::operational().get_dispatch_info(),
+			Call::<TraitImpl>::operational {}.get_dispatch_info(),
 			DispatchInfo { weight: 5, class: DispatchClass::Operational, pays_fee: Pays::Yes },
 		);
 		// custom basic
 		assert_eq!(
-			Call::<TraitImpl>::aux_3().get_dispatch_info(),
+			Call::<TraitImpl>::aux_3 {}.get_dispatch_info(),
 			DispatchInfo { weight: 3, class: DispatchClass::Normal, pays_fee: Pays::Yes },
 		);
 	}
 
 	#[test]
 	fn call_name() {
-		let name = Call::<TraitImpl>::aux_3().get_call_name();
+		let name = Call::<TraitImpl>::aux_3 {}.get_call_name();
 		assert_eq!("aux_3", name);
 	}
 
@@ -2929,4 +2801,9 @@ mod tests {
 	fn integrity_test_should_work() {
 		<Module<TraitImpl> as IntegrityTest>::integrity_test();
 	}
+
+	#[test]
+	fn test_new_call_variant() {
+		Call::<TraitImpl>::new_call_variant_aux_0();
+	}
 }
diff --git a/substrate/frame/support/src/error.rs b/substrate/frame/support/src/error.rs
index f0c6ba0f3b1c79c27d7527bbb43fd7ee850f9640..836428c6bc7db6d27dee43ef1254d514ed238b91 100644
--- a/substrate/frame/support/src/error.rs
+++ b/substrate/frame/support/src/error.rs
@@ -17,8 +17,6 @@
 
 //! Macro for declaring a module error.
 
-#[doc(hidden)]
-pub use frame_metadata::{DecodeDifferent, ErrorMetadata, ModuleErrorMetadata};
 #[doc(hidden)]
 pub use sp_runtime::traits::{BadOrigin, LookupError};
 
@@ -87,10 +85,13 @@ macro_rules! decl_error {
 		}
 	) => {
 		$(#[$attr])*
+		#[derive($crate::scale_info::TypeInfo)]
+		#[scale_info(skip_type_params($generic $(, $inst_generic)?), capture_docs = "always")]
 		pub enum $error<$generic: $trait $(, $inst_generic: $instance)?>
 		$( where $( $where_ty: $where_bound ),* )?
 		{
 			#[doc(hidden)]
+			#[codec(skip)]
 			__Ignore(
 				$crate::sp_std::marker::PhantomData<($generic, $( $inst_generic)?)>,
 				$crate::Never,
@@ -159,24 +160,6 @@ macro_rules! decl_error {
 				}
 			}
 		}
-
-		impl<$generic: $trait $(, $inst_generic: $instance)?> $crate::error::ModuleErrorMetadata
-			for $error<$generic $(, $inst_generic)?>
-		$( where $( $where_ty: $where_bound ),* )?
-		{
-			fn metadata() -> &'static [$crate::error::ErrorMetadata] {
-				&[
-					$(
-						$crate::error::ErrorMetadata {
-							name: $crate::error::DecodeDifferent::Encode(stringify!($name)),
-							documentation: $crate::error::DecodeDifferent::Encode(&[
-								$( $doc_attr ),*
-							]),
-						}
-					),*
-				]
-			}
-		}
 	};
 	(@GENERATE_AS_U8
 		$self:ident
diff --git a/substrate/frame/support/src/event.rs b/substrate/frame/support/src/event.rs
index 6e0d4ba6b47bd0c58b27d7308338be24bde8f0e6..3d042a3122db86b8886bbb02070767f40843f395 100644
--- a/substrate/frame/support/src/event.rs
+++ b/substrate/frame/support/src/event.rs
@@ -21,8 +21,6 @@
 // You should have received a copy of the GNU General Public License
 // along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
 
-pub use frame_metadata::{DecodeDifferent, EventMetadata, FnEncode, OuterEventMetadata};
-
 /// Implement the `Event` for a module.
 ///
 /// # Simple Event Example:
@@ -129,8 +127,10 @@ macro_rules! decl_event {
 			Clone, PartialEq, Eq,
 			$crate::codec::Encode,
 			$crate::codec::Decode,
+			$crate::scale_info::TypeInfo,
 			$crate::RuntimeDebug,
 		)]
+		#[scale_info(capture_docs = "always")]
 		/// Events for this module.
 		///
 		$(#[$attr])*
@@ -142,13 +142,6 @@ macro_rules! decl_event {
 		impl From<Event> for () {
 			fn from(_: Event) -> () { () }
 		}
-		impl Event {
-			#[allow(dead_code)]
-			#[doc(hidden)]
-			pub fn metadata() -> &'static [ $crate::event::EventMetadata ] {
-				$crate::__events_to_metadata!(; $( $events )* )
-			}
-		}
 	}
 }
 
@@ -272,8 +265,10 @@ macro_rules! __decl_generic_event {
 			Clone, PartialEq, Eq,
 			$crate::codec::Encode,
 			$crate::codec::Decode,
+			$crate::scale_info::TypeInfo,
 			$crate::RuntimeDebug,
 		)]
+		#[scale_info(capture_docs = "always")]
 		/// Events for this module.
 		///
 		$(#[$attr])*
@@ -290,263 +285,8 @@ macro_rules! __decl_generic_event {
 		impl<$( $generic_param ),* $(, $instance)? > From<RawEvent<$( $generic_param ),* $(, $instance)?>> for () {
 			fn from(_: RawEvent<$( $generic_param ),* $(, $instance)?>) -> () { () }
 		}
-		impl<$( $generic_param ),* $(, $instance)?> RawEvent<$( $generic_param ),* $(, $instance)?> {
-			#[allow(dead_code)]
-			#[doc(hidden)]
-			pub fn metadata() -> &'static [$crate::event::EventMetadata] {
-				$crate::__events_to_metadata!(; $( $events )* )
-			}
-		}
 	};
 	(@cannot_parse $ty:ty) => {
 		compile_error!(concat!("The type `", stringify!($ty), "` can't be parsed as an unnamed one, please name it `Name = ", stringify!($ty), "`"));
 	}
 }
-
-#[macro_export]
-#[doc(hidden)]
-macro_rules! __events_to_metadata {
-	(
-		$( $metadata:expr ),*;
-		$( #[doc = $doc_attr:tt] )*
-		$event:ident $( ( $( $param:path ),* $(,)? ) )*,
-		$( $rest:tt )*
-	) => {
-		$crate::__events_to_metadata!(
-			$( $metadata, )*
-			$crate::event::EventMetadata {
-				name: $crate::event::DecodeDifferent::Encode(stringify!($event)),
-				arguments: $crate::event::DecodeDifferent::Encode(&[
-					$( $( stringify!($param) ),* )*
-				]),
-				documentation: $crate::event::DecodeDifferent::Encode(&[
-					$( $doc_attr ),*
-				]),
-			};
-			$( $rest )*
-		)
-	};
-	(
-		$( $metadata:expr ),*;
-	) => {
-		&[ $( $metadata ),* ]
-	}
-}
-
-#[cfg(test)]
-#[allow(dead_code)]
-mod tests {
-	use super::*;
-	use codec::{Decode, Encode};
-	use serde::Serialize;
-
-	mod system {
-		pub trait Config: 'static {
-			type Origin;
-			type BlockNumber;
-			type PalletInfo: crate::traits::PalletInfo;
-			type DbWeight: crate::traits::Get<crate::weights::RuntimeDbWeight>;
-		}
-
-		decl_module! {
-			pub struct Module<T: Config> for enum Call where origin: T::Origin, system=self {}
-		}
-
-		decl_event!(
-			pub enum Event {
-				SystemEvent,
-			}
-		);
-	}
-
-	mod system_renamed {
-		pub trait Config: 'static {
-			type Origin;
-			type BlockNumber;
-			type PalletInfo: crate::traits::PalletInfo;
-			type DbWeight: crate::traits::Get<crate::weights::RuntimeDbWeight>;
-		}
-
-		decl_module! {
-			pub struct Module<T: Config> for enum Call where origin: T::Origin, system=self {}
-		}
-
-		decl_event!(
-			pub enum Event {
-				SystemEvent,
-			}
-		);
-	}
-
-	mod event_module {
-		use super::system;
-
-		pub trait Config: system::Config {
-			type Balance;
-		}
-
-		decl_module! {
-			pub struct Module<T: Config> for enum Call where origin: T::Origin, system=system {}
-		}
-
-		decl_event!(
-			/// Event without renaming the generic parameter `Balance` and `Origin`.
-			pub enum Event<T> where <T as Config>::Balance, <T as system::Config>::Origin
-			{
-				/// Hi, I am a comment.
-				TestEvent(Balance, Origin),
-				/// Dog
-				EventWithoutParams,
-			}
-		);
-	}
-
-	mod event_module2 {
-		use super::system;
-
-		pub trait Config: system::Config {
-			type Balance;
-		}
-
-		decl_module! {
-			pub struct Module<T: Config> for enum Call where origin: T::Origin, system=system {}
-		}
-
-		decl_event!(
-			/// Event with renamed generic parameter
-			pub enum Event<T>
-			where
-				BalanceRenamed = <T as Config>::Balance,
-				OriginRenamed = <T as system::Config>::Origin,
-			{
-				TestEvent(BalanceRenamed),
-				TestOrigin(OriginRenamed),
-			}
-		);
-	}
-
-	mod event_module3 {
-		decl_event!(
-			pub enum Event {
-				HiEvent,
-			}
-		);
-	}
-
-	mod event_module4 {
-		use super::system;
-
-		pub trait Config: system::Config {
-			type Balance;
-		}
-
-		decl_module! {
-			pub struct Module<T: Config> for enum Call where origin: T::Origin, system=system {}
-		}
-
-		decl_event!(
-			/// Event finish formatting on an unnamed one with trailing comma
-			pub enum Event<T> where
-				<T as Config>::Balance,
-				<T as system::Config>::Origin,
-			{
-				TestEvent(Balance, Origin),
-			}
-		);
-	}
-
-	mod event_module5 {
-		use super::system;
-
-		pub trait Config: system::Config {
-			type Balance;
-		}
-
-		decl_module! {
-			pub struct Module<T: Config> for enum Call where origin: T::Origin, system=system {}
-		}
-
-		decl_event!(
-			/// Event finish formatting on an named one with trailing comma
-			pub enum Event<T>
-			where
-				BalanceRenamed = <T as Config>::Balance,
-				OriginRenamed = <T as system::Config>::Origin,
-			{
-				TestEvent(BalanceRenamed, OriginRenamed),
-				TrailingCommaInArgs(u32, u32),
-			}
-		);
-	}
-
-	#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Serialize)]
-	pub struct TestRuntime;
-
-	#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Serialize)]
-	pub struct TestRuntime2;
-
-	impl event_module::Config for TestRuntime {
-		type Balance = u32;
-	}
-
-	impl event_module2::Config for TestRuntime {
-		type Balance = u32;
-	}
-
-	impl system::Config for TestRuntime {
-		type Origin = u32;
-		type BlockNumber = u32;
-		type PalletInfo = crate::tests::PanicPalletInfo;
-		type DbWeight = ();
-	}
-
-	#[test]
-	fn event_metadata() {
-		assert_eq!(
-			system_renamed::Event::metadata(),
-			&[EventMetadata {
-				name: DecodeDifferent::Encode("SystemEvent"),
-				arguments: DecodeDifferent::Encode(&[]),
-				documentation: DecodeDifferent::Encode(&[]),
-			},]
-		);
-		assert_eq!(
-			event_module::Event::<TestRuntime>::metadata(),
-			&[
-				EventMetadata {
-					name: DecodeDifferent::Encode("TestEvent"),
-					arguments: DecodeDifferent::Encode(&["Balance", "Origin"]),
-					documentation: DecodeDifferent::Encode(&[" Hi, I am a comment."])
-				},
-				EventMetadata {
-					name: DecodeDifferent::Encode("EventWithoutParams"),
-					arguments: DecodeDifferent::Encode(&[]),
-					documentation: DecodeDifferent::Encode(&[" Dog"]),
-				},
-			]
-		);
-		assert_eq!(
-			event_module2::Event::<TestRuntime>::metadata(),
-			&[
-				EventMetadata {
-					name: DecodeDifferent::Encode("TestEvent"),
-					arguments: DecodeDifferent::Encode(&["BalanceRenamed"]),
-					documentation: DecodeDifferent::Encode(&[])
-				},
-				EventMetadata {
-					name: DecodeDifferent::Encode("TestOrigin"),
-					arguments: DecodeDifferent::Encode(&["OriginRenamed"]),
-					documentation: DecodeDifferent::Encode(&[]),
-				},
-			]
-		);
-		assert_eq!(
-			event_module3::Event::metadata(),
-			&[EventMetadata {
-				name: DecodeDifferent::Encode("HiEvent"),
-				arguments: DecodeDifferent::Encode(&[]),
-				documentation: DecodeDifferent::Encode(&[])
-			}],
-		);
-	}
-}
diff --git a/substrate/frame/support/src/hash.rs b/substrate/frame/support/src/hash.rs
index 4136bd518f4c2d2eb677e71a682c7bdf3b303985..f943bcf323090d623c96433cf4a1f5bf6a4042ac 100644
--- a/substrate/frame/support/src/hash.rs
+++ b/substrate/frame/support/src/hash.rs
@@ -17,6 +17,7 @@
 
 //! Hash utilities.
 
+use crate::metadata;
 use codec::{Codec, MaxEncodedLen};
 use sp_io::hashing::{blake2_128, blake2_256, twox_128, twox_256, twox_64};
 use sp_std::prelude::Vec;
@@ -58,7 +59,7 @@ impl<T: Codec> Hashable for T {
 
 /// Hasher to use to hash keys to insert to storage.
 pub trait StorageHasher: 'static {
-	const METADATA: frame_metadata::StorageHasher;
+	const METADATA: metadata::StorageHasher;
 	type Output: AsRef<[u8]>;
 	fn hash(x: &[u8]) -> Self::Output;
 
@@ -79,7 +80,7 @@ pub trait ReversibleStorageHasher: StorageHasher {
 /// Store the key directly.
 pub struct Identity;
 impl StorageHasher for Identity {
-	const METADATA: frame_metadata::StorageHasher = frame_metadata::StorageHasher::Identity;
+	const METADATA: metadata::StorageHasher = metadata::StorageHasher::Identity;
 	type Output = Vec<u8>;
 	fn hash(x: &[u8]) -> Vec<u8> {
 		x.to_vec()
@@ -97,7 +98,7 @@ impl ReversibleStorageHasher for Identity {
 /// Hash storage keys with `concat(twox64(key), key)`
 pub struct Twox64Concat;
 impl StorageHasher for Twox64Concat {
-	const METADATA: frame_metadata::StorageHasher = frame_metadata::StorageHasher::Twox64Concat;
+	const METADATA: metadata::StorageHasher = metadata::StorageHasher::Twox64Concat;
 	type Output = Vec<u8>;
 	fn hash(x: &[u8]) -> Vec<u8> {
 		twox_64(x).iter().chain(x.into_iter()).cloned().collect::<Vec<_>>()
@@ -119,7 +120,7 @@ impl ReversibleStorageHasher for Twox64Concat {
 /// Hash storage keys with `concat(blake2_128(key), key)`
 pub struct Blake2_128Concat;
 impl StorageHasher for Blake2_128Concat {
-	const METADATA: frame_metadata::StorageHasher = frame_metadata::StorageHasher::Blake2_128Concat;
+	const METADATA: metadata::StorageHasher = metadata::StorageHasher::Blake2_128Concat;
 	type Output = Vec<u8>;
 	fn hash(x: &[u8]) -> Vec<u8> {
 		blake2_128(x).iter().chain(x.into_iter()).cloned().collect::<Vec<_>>()
@@ -141,7 +142,7 @@ impl ReversibleStorageHasher for Blake2_128Concat {
 /// Hash storage keys with blake2 128
 pub struct Blake2_128;
 impl StorageHasher for Blake2_128 {
-	const METADATA: frame_metadata::StorageHasher = frame_metadata::StorageHasher::Blake2_128;
+	const METADATA: metadata::StorageHasher = metadata::StorageHasher::Blake2_128;
 	type Output = [u8; 16];
 	fn hash(x: &[u8]) -> [u8; 16] {
 		blake2_128(x)
@@ -154,7 +155,7 @@ impl StorageHasher for Blake2_128 {
 /// Hash storage keys with blake2 256
 pub struct Blake2_256;
 impl StorageHasher for Blake2_256 {
-	const METADATA: frame_metadata::StorageHasher = frame_metadata::StorageHasher::Blake2_256;
+	const METADATA: metadata::StorageHasher = metadata::StorageHasher::Blake2_256;
 	type Output = [u8; 32];
 	fn hash(x: &[u8]) -> [u8; 32] {
 		blake2_256(x)
@@ -167,7 +168,7 @@ impl StorageHasher for Blake2_256 {
 /// Hash storage keys with twox 128
 pub struct Twox128;
 impl StorageHasher for Twox128 {
-	const METADATA: frame_metadata::StorageHasher = frame_metadata::StorageHasher::Twox128;
+	const METADATA: metadata::StorageHasher = metadata::StorageHasher::Twox128;
 	type Output = [u8; 16];
 	fn hash(x: &[u8]) -> [u8; 16] {
 		twox_128(x)
@@ -180,7 +181,7 @@ impl StorageHasher for Twox128 {
 /// Hash storage keys with twox 256
 pub struct Twox256;
 impl StorageHasher for Twox256 {
-	const METADATA: frame_metadata::StorageHasher = frame_metadata::StorageHasher::Twox256;
+	const METADATA: metadata::StorageHasher = metadata::StorageHasher::Twox256;
 	type Output = [u8; 32];
 	fn hash(x: &[u8]) -> [u8; 32] {
 		twox_256(x)
diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs
index 9dee6da89b25675aa73de8e46bdda2be51d6b0d4..cce03f1e8ce6c9e739a710a3a653a59ccfacd311 100644
--- a/substrate/frame/support/src/lib.rs
+++ b/substrate/frame/support/src/lib.rs
@@ -36,6 +36,8 @@ pub use log;
 pub use once_cell;
 #[doc(hidden)]
 pub use paste;
+#[doc(hidden)]
+pub use scale_info;
 #[cfg(feature = "std")]
 pub use serde;
 pub use sp_core::Void;
@@ -90,17 +92,18 @@ pub use self::{
 pub use sp_runtime::{self, print, traits::Printable, ConsensusEngineId};
 
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 use sp_runtime::TypeId;
 
 /// A unified log target for support operations.
 pub const LOG_TARGET: &'static str = "runtime::frame-support";
 
 /// A type that cannot be instantiated.
-#[derive(Debug, PartialEq, Eq, Clone)]
+#[derive(Debug, PartialEq, Eq, Clone, TypeInfo)]
 pub enum Never {}
 
 /// A pallet identifier. These are per pallet and should be stored in a registry somewhere.
-#[derive(Clone, Copy, Eq, PartialEq, Encode, Decode)]
+#[derive(Clone, Copy, Eq, PartialEq, Encode, Decode, TypeInfo)]
 pub struct PalletId(pub [u8; 8]);
 
 impl TypeId for PalletId {
@@ -811,13 +814,13 @@ pub use serde::{Deserialize, Serialize};
 #[cfg(test)]
 pub mod tests {
 	use super::*;
-	use codec::{Codec, EncodeLike};
-	use frame_metadata::{
-		DecodeDifferent, DefaultByteGetter, StorageEntryMetadata, StorageEntryModifier,
-		StorageEntryType, StorageHasher, StorageMetadata,
+	use crate::metadata::{
+		PalletStorageMetadata, StorageEntryMetadata, StorageEntryModifier, StorageEntryType,
+		StorageHasher,
 	};
+	use codec::{Codec, EncodeLike};
 	use sp_io::TestExternalities;
-	use sp_std::{marker::PhantomData, result};
+	use sp_std::result;
 
 	/// A PalletInfo implementation which just panics.
 	pub struct PanicPalletInfo;
@@ -832,7 +835,7 @@ pub mod tests {
 	}
 
 	pub trait Config: 'static {
-		type BlockNumber: Codec + EncodeLike + Default;
+		type BlockNumber: Codec + EncodeLike + Default + TypeInfo;
 		type Origin;
 		type PalletInfo: crate::traits::PalletInfo;
 		type DbWeight: crate::traits::Get<crate::weights::RuntimeDbWeight>;
@@ -1150,132 +1153,109 @@ pub mod tests {
 		});
 	}
 
-	const EXPECTED_METADATA: StorageMetadata = StorageMetadata {
-		prefix: DecodeDifferent::Encode("Test"),
-		entries: DecodeDifferent::Encode(&[
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("Data"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Map {
-					hasher: StorageHasher::Twox64Concat,
-					key: DecodeDifferent::Encode("u32"),
-					value: DecodeDifferent::Encode("u64"),
-					unused: false,
+	fn expected_metadata() -> PalletStorageMetadata {
+		PalletStorageMetadata {
+			prefix: "Test",
+			entries: vec![
+				StorageEntryMetadata {
+					name: "Data",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Twox64Concat],
+						key: scale_info::meta_type::<u32>(),
+						value: scale_info::meta_type::<u64>(),
+					},
+					default: vec![0, 0, 0, 0, 0, 0, 0, 0],
+					docs: vec![],
 				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructData(
-					PhantomData::<Test>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("OptionLinkedMap"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::Map {
-					hasher: StorageHasher::Blake2_128Concat,
-					key: DecodeDifferent::Encode("u32"),
-					value: DecodeDifferent::Encode("u32"),
-					unused: false,
+				StorageEntryMetadata {
+					name: "OptionLinkedMap",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Blake2_128Concat],
+						key: scale_info::meta_type::<u32>(),
+						value: scale_info::meta_type::<u32>(),
+					},
+					default: vec![0],
+					docs: vec![],
 				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructOptionLinkedMap(PhantomData::<Test>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GenericData"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Map {
-					hasher: StorageHasher::Identity,
-					key: DecodeDifferent::Encode("T::BlockNumber"),
-					value: DecodeDifferent::Encode("T::BlockNumber"),
-					unused: false,
+				StorageEntryMetadata {
+					name: "GenericData",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Identity],
+						key: scale_info::meta_type::<u32>(),
+						value: scale_info::meta_type::<u32>(),
+					},
+					default: vec![0, 0, 0, 0],
+					docs: vec![],
 				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructGenericData(
-					PhantomData::<Test>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GenericData2"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::Map {
-					hasher: StorageHasher::Blake2_128Concat,
-					key: DecodeDifferent::Encode("T::BlockNumber"),
-					value: DecodeDifferent::Encode("T::BlockNumber"),
-					unused: false,
+				StorageEntryMetadata {
+					name: "GenericData2",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Blake2_128Concat],
+						key: scale_info::meta_type::<u32>(),
+						value: scale_info::meta_type::<u32>(),
+					},
+					default: vec![0],
+					docs: vec![],
 				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructGenericData2(
-					PhantomData::<Test>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("DataDM"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::DoubleMap {
-					hasher: StorageHasher::Twox64Concat,
-					key1: DecodeDifferent::Encode("u32"),
-					key2: DecodeDifferent::Encode("u32"),
-					value: DecodeDifferent::Encode("u64"),
-					key2_hasher: StorageHasher::Blake2_128Concat,
+				StorageEntryMetadata {
+					name: "DataDM",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Twox64Concat, StorageHasher::Blake2_128Concat],
+						key: scale_info::meta_type::<(u32, u32)>(),
+						value: scale_info::meta_type::<u64>(),
+					},
+					default: vec![0, 0, 0, 0, 0, 0, 0, 0],
+					docs: vec![],
 				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructDataDM(
-					PhantomData::<Test>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GenericDataDM"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::DoubleMap {
-					hasher: StorageHasher::Blake2_128Concat,
-					key1: DecodeDifferent::Encode("T::BlockNumber"),
-					key2: DecodeDifferent::Encode("T::BlockNumber"),
-					value: DecodeDifferent::Encode("T::BlockNumber"),
-					key2_hasher: StorageHasher::Identity,
+				StorageEntryMetadata {
+					name: "GenericDataDM",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Blake2_128Concat, StorageHasher::Identity],
+						key: scale_info::meta_type::<(u32, u32)>(),
+						value: scale_info::meta_type::<u32>(),
+					},
+					default: vec![0, 0, 0, 0],
+					docs: vec![],
 				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructGenericDataDM(
-					PhantomData::<Test>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GenericData2DM"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::DoubleMap {
-					hasher: StorageHasher::Blake2_128Concat,
-					key1: DecodeDifferent::Encode("T::BlockNumber"),
-					key2: DecodeDifferent::Encode("T::BlockNumber"),
-					value: DecodeDifferent::Encode("T::BlockNumber"),
-					key2_hasher: StorageHasher::Twox64Concat,
+				StorageEntryMetadata {
+					name: "GenericData2DM",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat],
+						key: scale_info::meta_type::<(u32, u32)>(),
+						value: scale_info::meta_type::<u32>(),
+					},
+					default: vec![0],
+					docs: vec![],
 				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructGenericData2DM(PhantomData::<Test>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("AppendableDM"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::DoubleMap {
-					hasher: StorageHasher::Blake2_128Concat,
-					key1: DecodeDifferent::Encode("u32"),
-					key2: DecodeDifferent::Encode("T::BlockNumber"),
-					value: DecodeDifferent::Encode("Vec<u32>"),
-					key2_hasher: StorageHasher::Blake2_128Concat,
+				StorageEntryMetadata {
+					name: "AppendableDM",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Map {
+						hashers: vec![
+							StorageHasher::Blake2_128Concat,
+							StorageHasher::Blake2_128Concat,
+						],
+						key: scale_info::meta_type::<(u32, u32)>(),
+						value: scale_info::meta_type::<Vec<u32>>(),
+					},
+					default: vec![0],
+					docs: vec![],
 				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructGenericData2DM(PhantomData::<Test>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-		]),
-	};
+			],
+		}
+	}
 
 	#[test]
 	fn store_metadata() {
 		let metadata = Module::<Test>::storage_metadata();
-		pretty_assertions::assert_eq!(EXPECTED_METADATA, metadata);
+		pretty_assertions::assert_eq!(expected_metadata(), metadata);
 	}
 
 	parameter_types! {
@@ -1470,7 +1450,7 @@ pub mod pallet_prelude {
 /// It implements on pallet:
 /// * [`traits::GetStorageVersion`]
 /// * [`traits::OnGenesis`]: contains some logic to write pallet version into storage.
-/// * `ModuleErrorMetadata`: using error declared or no metadata.
+/// * `PalletErrorTypeInfo`: provides the type information for the pallet error, if defined.
 ///
 /// It declare `type Module` type alias for `Pallet`, used by [`construct_runtime`].
 ///
@@ -1623,9 +1603,6 @@ pub mod pallet_prelude {
 /// The macro implements `From<Error<T>>` for `&'static str`.
 /// The macro implements `From<Error<T>>` for `DispatchError`.
 ///
-/// The macro implements `ModuleErrorMetadata` on `Pallet` defining the `ErrorMetadata` of the
-/// pallet.
-///
 /// # Event: `#[pallet::event]` optional
 ///
 /// Allow to define pallet events, pallet events are stored in the block when they deposited
@@ -1634,7 +1611,6 @@ pub mod pallet_prelude {
 /// Item is defined as:
 /// ```ignore
 /// #[pallet::event]
-/// #[pallet::metadata($SomeType = "$Metadata", $SomeOtherType = "$Metadata", ..)] // Optional
 /// #[pallet::generate_deposit($visibility fn deposit_event)] // Optional
 /// pub enum Event<$some_generic> $optional_where_clause {
 /// 	/// Some doc
@@ -1649,24 +1625,6 @@ pub mod pallet_prelude {
 /// std only).
 /// For ease of use, bound the trait `Member` available in frame_support::pallet_prelude.
 ///
-/// Variant documentations and field types are put into metadata.
-/// The attribute `#[pallet::metadata(..)]` allows to specify the metadata to put for some
-/// types.
-///
-/// The metadata of a type is defined by:
-/// * if matching a type in `#[pallet::metadata(..)]`, then the corresponding metadata.
-/// * otherwise the type stringified.
-///
-/// E.g.:
-/// ```ignore
-/// #[pallet::event]
-/// #[pallet::metadata(u32 = "SpecialU32")]
-/// pub enum Event<T: Config> {
-/// 	Proposed(u32, T::AccountId),
-/// }
-/// ```
-/// will write in event variant metadata `"SpecialU32"` and `"T::AccountId"`.
-///
 /// The attribute `#[pallet::generate_deposit($visibility fn deposit_event)]` generate a helper
 /// function on `Pallet` to deposit event.
 ///
@@ -2027,8 +1985,6 @@ pub mod pallet_prelude {
 /// 	//
 /// 	// The macro generates event metadata, and derive Clone, Debug, Eq, PartialEq and Codec
 /// 	#[pallet::event]
-/// 	// Additional argument to specify the metadata to use for given type.
-/// 	#[pallet::metadata(BalanceOf<T> = "Balance", u32 = "Other")]
 /// 	// Generate a funciton on Pallet to deposit an event.
 /// 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 /// 	pub enum Event<T: Config> {
@@ -2192,7 +2148,6 @@ pub mod pallet_prelude {
 /// 	}
 ///
 /// 	#[pallet::event]
-/// 	#[pallet::metadata(BalanceOf<T> = "Balance", u32 = "Other")]
 /// 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 /// 	pub enum Event<T: Config<I>, I: 'static = ()> {
 /// 		/// doc comment put in metadata
@@ -2342,8 +2297,7 @@ pub mod pallet_prelude {
 /// 7. **migrate event**:
 /// 	rewrite as a simple enum under with the attribute `#[pallet::event]`,
 /// 	use `#[pallet::generate_deposit($vis fn deposit_event)]` to generate deposit_event,
-/// 	use `#[pallet::metadata(...)]` to configure the metadata for types in order not to break
-/// them. 8. **migrate error**: rewrite it with attribute `#[pallet::error]`.
+/// 8. **migrate error**: rewrite it with attribute `#[pallet::error]`.
 /// 9. **migrate storage**:
 /// 	decl_storage provide an upgrade template (see 3.). All storages, genesis config, genesis
 /// 	build and default implementation of genesis config can be taken from it directly.
diff --git a/substrate/frame/support/src/storage/bounded_btree_map.rs b/substrate/frame/support/src/storage/bounded_btree_map.rs
index 737c8953d29ebbf21867ee73b03f2d3cabb32698..d0c0aa7c4f15587c2dd640f44f5c59179bbc3cc5 100644
--- a/substrate/frame/support/src/storage/bounded_btree_map.rs
+++ b/substrate/frame/support/src/storage/bounded_btree_map.rs
@@ -31,7 +31,8 @@ use sp_std::{
 ///
 /// Unlike a standard `BTreeMap`, there is an enforced upper limit to the number of items in the
 /// map. All internal operations ensure this bound is respected.
-#[derive(Encode)]
+#[derive(Encode, scale_info::TypeInfo)]
+#[scale_info(skip_type_params(S))]
 pub struct BoundedBTreeMap<K, V, S>(BTreeMap<K, V>, PhantomData<S>);
 
 impl<K, V, S> Decode for BoundedBTreeMap<K, V, S>
diff --git a/substrate/frame/support/src/storage/bounded_vec.rs b/substrate/frame/support/src/storage/bounded_vec.rs
index 0f56511e6edd82d2d30586b5b00cb7d0fb53a84c..b45c294f8d4a4e21eb413444020e13222924f85f 100644
--- a/substrate/frame/support/src/storage/bounded_vec.rs
+++ b/substrate/frame/support/src/storage/bounded_vec.rs
@@ -37,7 +37,8 @@ use sp_std::{convert::TryFrom, fmt, marker::PhantomData, prelude::*};
 ///
 /// As the name suggests, the length of the queue is always bounded. All internal operations ensure
 /// this bound is respected.
-#[derive(Encode)]
+#[derive(Encode, scale_info::TypeInfo)]
+#[scale_info(skip_type_params(S))]
 pub struct BoundedVec<T, S>(Vec<T>, PhantomData<S>);
 
 /// A bounded slice.
diff --git a/substrate/frame/support/src/storage/mod.rs b/substrate/frame/support/src/storage/mod.rs
index 8cee9faf6e81d3f4b96d02988b681e6a43b63e68..e57a876bf983141d2078774d10687f59d2c3a793 100644
--- a/substrate/frame/support/src/storage/mod.rs
+++ b/substrate/frame/support/src/storage/mod.rs
@@ -17,6 +17,7 @@
 
 //! Stuff to do with the runtime's storage.
 
+pub use self::types::StorageEntryMetadata;
 use crate::{
 	hash::{ReversibleStorageHasher, StorageHasher},
 	storage::types::{
diff --git a/substrate/frame/support/src/storage/types/double_map.rs b/substrate/frame/support/src/storage/types/double_map.rs
index 2db8a845c568cbfbfd496db7436e6efd3185bb1b..7750110050868ce9f1a62497417d45b8cf45b55d 100644
--- a/substrate/frame/support/src/storage/types/double_map.rs
+++ b/substrate/frame/support/src/storage/types/double_map.rs
@@ -19,14 +19,14 @@
 //! StoragePrefixedDoubleMap traits and their methods directly.
 
 use crate::{
+	metadata::{StorageEntryModifier, StorageEntryType},
 	storage::{
-		types::{OnEmptyGetter, OptionQuery, QueryKindTrait},
+		types::{OptionQuery, QueryKindTrait, StorageEntryMetadata},
 		StorageAppend, StorageDecodeLength, StoragePrefixedMap, StorageTryAppend,
 	},
 	traits::{Get, GetDefault, StorageInfo, StorageInstance},
 };
 use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
-use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
 use sp_arithmetic::traits::SaturatedConversion;
 use sp_std::prelude::*;
 
@@ -511,37 +511,34 @@ where
 	}
 }
 
-/// Part of storage metadata for a storage double map.
-///
-/// NOTE: Generic hashers is supported.
-pub trait StorageDoubleMapMetadata {
-	const MODIFIER: StorageEntryModifier;
-	const NAME: &'static str;
-	const DEFAULT: DefaultByteGetter;
-	const HASHER1: frame_metadata::StorageHasher;
-	const HASHER2: frame_metadata::StorageHasher;
-}
-
 impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
-	StorageDoubleMapMetadata
+	StorageEntryMetadata
 	for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
 where
 	Prefix: StorageInstance,
 	Hasher1: crate::hash::StorageHasher,
 	Hasher2: crate::hash::StorageHasher,
-	Key1: FullCodec,
-	Key2: FullCodec,
-	Value: FullCodec,
+	Key1: FullCodec + scale_info::StaticTypeInfo,
+	Key2: FullCodec + scale_info::StaticTypeInfo,
+	Value: FullCodec + scale_info::StaticTypeInfo,
 	QueryKind: QueryKindTrait<Value, OnEmpty>,
 	OnEmpty: Get<QueryKind::Query> + 'static,
 	MaxValues: Get<Option<u32>>,
 {
 	const MODIFIER: StorageEntryModifier = QueryKind::METADATA;
-	const HASHER1: frame_metadata::StorageHasher = Hasher1::METADATA;
-	const HASHER2: frame_metadata::StorageHasher = Hasher2::METADATA;
 	const NAME: &'static str = Prefix::STORAGE_PREFIX;
-	const DEFAULT: DefaultByteGetter =
-		DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
+
+	fn ty() -> StorageEntryType {
+		StorageEntryType::Map {
+			hashers: vec![Hasher1::METADATA, Hasher2::METADATA],
+			key: scale_info::meta_type::<(Key1, Key2)>(),
+			value: scale_info::meta_type::<Value>(),
+		}
+	}
+
+	fn default() -> Vec<u8> {
+		OnEmpty::get().encode()
+	}
 }
 
 impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
@@ -603,8 +600,12 @@ where
 #[cfg(test)]
 mod test {
 	use super::*;
-	use crate::{hash::*, storage::types::ValueQuery};
-	use frame_metadata::StorageEntryModifier;
+	use crate::{
+		hash::*,
+		metadata::{StorageEntryModifier, StorageEntryType, StorageHasher},
+		storage::types::ValueQuery,
+	};
+	use assert_matches::assert_matches;
 	use sp_io::{hashing::twox_128, TestExternalities};
 
 	struct Prefix;
@@ -768,19 +769,27 @@ mod test {
 
 			assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
 			assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
-			assert_eq!(A::HASHER1, frame_metadata::StorageHasher::Blake2_128Concat);
-			assert_eq!(A::HASHER2, frame_metadata::StorageHasher::Twox64Concat);
-			assert_eq!(
-				AValueQueryWithAnOnEmpty::HASHER1,
-				frame_metadata::StorageHasher::Blake2_128Concat
+
+			let assert_map_hashers = |ty, expected_hashers| {
+				if let StorageEntryType::Map { hashers, .. } = ty {
+					assert_eq!(hashers, expected_hashers)
+				} else {
+					assert_matches!(ty, StorageEntryType::Map { .. })
+				}
+			};
+
+			assert_map_hashers(
+				A::ty(),
+				vec![StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat],
 			);
-			assert_eq!(
-				AValueQueryWithAnOnEmpty::HASHER2,
-				frame_metadata::StorageHasher::Twox64Concat
+			assert_map_hashers(
+				AValueQueryWithAnOnEmpty::ty(),
+				vec![StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat],
 			);
+
 			assert_eq!(A::NAME, "foo");
-			assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 97u32.encode());
-			assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
+			assert_eq!(AValueQueryWithAnOnEmpty::default(), 97u32.encode());
+			assert_eq!(A::default(), Option::<u32>::None.encode());
 
 			WithLen::remove_all(None);
 			assert_eq!(WithLen::decode_len(3, 30), None);
diff --git a/substrate/frame/support/src/storage/types/key.rs b/substrate/frame/support/src/storage/types/key.rs
index db66838e3ff1ea45b0da0091216457c658e0ba29..da265fd6e6c87971b4f10a4ec107d84514f10812 100755
--- a/substrate/frame/support/src/storage/types/key.rs
+++ b/substrate/frame/support/src/storage/types/key.rs
@@ -20,6 +20,7 @@
 use crate::hash::{ReversibleStorageHasher, StorageHasher};
 use codec::{Encode, EncodeLike, FullCodec, MaxEncodedLen};
 use paste::paste;
+use scale_info::StaticTypeInfo;
 use sp_std::prelude::*;
 
 /// A type used exclusively by storage maps as their key type.
@@ -35,14 +36,14 @@ pub struct Key<Hasher, KeyType>(core::marker::PhantomData<(Hasher, KeyType)>);
 
 /// A trait that contains the current key as an associated type.
 pub trait KeyGenerator {
-	type Key: EncodeLike<Self::Key>;
+	type Key: EncodeLike<Self::Key> + StaticTypeInfo;
 	type KArg: Encode;
 	type HashFn: FnOnce(&[u8]) -> Vec<u8>;
 	type HArg;
 
-	const HASHER_METADATA: &'static [frame_metadata::StorageHasher];
+	const HASHER_METADATA: &'static [crate::metadata::StorageHasher];
 
-	/// Given a `key` tuple, calculate the final key by encoding each element individuallly and
+	/// Given a `key` tuple, calculate the final key by encoding each element individually and
 	/// hashing them using the corresponding hasher in the `KeyGenerator`.
 	fn final_key<KArg: EncodeLikeTuple<Self::KArg> + TupleToEncodedIter>(key: KArg) -> Vec<u8>;
 	/// Given a `key` tuple, migrate the keys from using the old hashers as given by `hash_fns`
@@ -67,13 +68,13 @@ pub trait KeyGeneratorInner: KeyGenerator {
 	fn final_hash(encoded: &[u8]) -> Vec<u8>;
 }
 
-impl<H: StorageHasher, K: FullCodec> KeyGenerator for Key<H, K> {
+impl<H: StorageHasher, K: FullCodec + StaticTypeInfo> KeyGenerator for Key<H, K> {
 	type Key = K;
 	type KArg = (K,);
 	type HashFn = Box<dyn FnOnce(&[u8]) -> Vec<u8>>;
 	type HArg = (Self::HashFn,);
 
-	const HASHER_METADATA: &'static [frame_metadata::StorageHasher] = &[H::METADATA];
+	const HASHER_METADATA: &'static [crate::metadata::StorageHasher] = &[H::METADATA];
 
 	fn final_key<KArg: EncodeLikeTuple<Self::KArg> + TupleToEncodedIter>(key: KArg) -> Vec<u8> {
 		H::hash(&key.to_encoded_iter().next().expect("should have at least one element!"))
@@ -89,13 +90,15 @@ impl<H: StorageHasher, K: FullCodec> KeyGenerator for Key<H, K> {
 	}
 }
 
-impl<H: StorageHasher, K: FullCodec + MaxEncodedLen> KeyGeneratorMaxEncodedLen for Key<H, K> {
+impl<H: StorageHasher, K: FullCodec + MaxEncodedLen + StaticTypeInfo> KeyGeneratorMaxEncodedLen
+	for Key<H, K>
+{
 	fn key_max_encoded_len() -> usize {
 		H::max_len::<K>()
 	}
 }
 
-impl<H: StorageHasher, K: FullCodec> KeyGeneratorInner for Key<H, K> {
+impl<H: StorageHasher, K: FullCodec + StaticTypeInfo> KeyGeneratorInner for Key<H, K> {
 	type Hasher = H;
 
 	fn final_hash(encoded: &[u8]) -> Vec<u8> {
@@ -111,7 +114,7 @@ impl KeyGenerator for Tuple {
 	for_tuples!( type HArg = ( #(Tuple::HashFn),* ); );
 	type HashFn = Box<dyn FnOnce(&[u8]) -> Vec<u8>>;
 
-	const HASHER_METADATA: &'static [frame_metadata::StorageHasher] =
+	const HASHER_METADATA: &'static [crate::metadata::StorageHasher] =
 		&[for_tuples!( #(Tuple::Hasher::METADATA),* )];
 
 	fn final_key<KArg: EncodeLikeTuple<Self::KArg> + TupleToEncodedIter>(key: KArg) -> Vec<u8> {
@@ -218,7 +221,9 @@ pub trait ReversibleKeyGenerator: KeyGenerator {
 	fn decode_final_key(key_material: &[u8]) -> Result<(Self::Key, &[u8]), codec::Error>;
 }
 
-impl<H: ReversibleStorageHasher, K: FullCodec> ReversibleKeyGenerator for Key<H, K> {
+impl<H: ReversibleStorageHasher, K: FullCodec + StaticTypeInfo> ReversibleKeyGenerator
+	for Key<H, K>
+{
 	type ReversibleHasher = H;
 
 	fn decode_final_key(key_material: &[u8]) -> Result<(Self::Key, &[u8]), codec::Error> {
diff --git a/substrate/frame/support/src/storage/types/map.rs b/substrate/frame/support/src/storage/types/map.rs
index 6b3cfe64eaec050db52cb92f1ad27d6f0d91a09f..a31224f15c80f8df89a214bbf3d1565aba5f0aac 100644
--- a/substrate/frame/support/src/storage/types/map.rs
+++ b/substrate/frame/support/src/storage/types/map.rs
@@ -19,14 +19,14 @@
 //! methods directly.
 
 use crate::{
+	metadata::{StorageEntryModifier, StorageEntryType},
 	storage::{
-		types::{OnEmptyGetter, OptionQuery, QueryKindTrait},
+		types::{OptionQuery, QueryKindTrait, StorageEntryMetadata},
 		StorageAppend, StorageDecodeLength, StoragePrefixedMap, StorageTryAppend,
 	},
 	traits::{Get, GetDefault, StorageInfo, StorageInstance},
 };
 use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
-use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
 use sp_arithmetic::traits::SaturatedConversion;
 use sp_std::prelude::*;
 
@@ -336,32 +336,31 @@ where
 	}
 }
 
-/// Part of storage metadata for a storage map.
-///
-/// NOTE: Generic hasher is supported.
-pub trait StorageMapMetadata {
-	const MODIFIER: StorageEntryModifier;
-	const NAME: &'static str;
-	const DEFAULT: DefaultByteGetter;
-	const HASHER: frame_metadata::StorageHasher;
-}
-
-impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> StorageMapMetadata
+impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> StorageEntryMetadata
 	for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
 where
 	Prefix: StorageInstance,
 	Hasher: crate::hash::StorageHasher,
-	Key: FullCodec,
-	Value: FullCodec,
+	Key: FullCodec + scale_info::StaticTypeInfo,
+	Value: FullCodec + scale_info::StaticTypeInfo,
 	QueryKind: QueryKindTrait<Value, OnEmpty>,
 	OnEmpty: Get<QueryKind::Query> + 'static,
 	MaxValues: Get<Option<u32>>,
 {
 	const MODIFIER: StorageEntryModifier = QueryKind::METADATA;
-	const HASHER: frame_metadata::StorageHasher = Hasher::METADATA;
 	const NAME: &'static str = Prefix::STORAGE_PREFIX;
-	const DEFAULT: DefaultByteGetter =
-		DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
+
+	fn ty() -> StorageEntryType {
+		StorageEntryType::Map {
+			hashers: vec![Hasher::METADATA],
+			key: scale_info::meta_type::<Key>(),
+			value: scale_info::meta_type::<Value>(),
+		}
+	}
+
+	fn default() -> Vec<u8> {
+		OnEmpty::get().encode()
+	}
 }
 
 impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> crate::traits::StorageInfoTrait
@@ -417,8 +416,12 @@ where
 #[cfg(test)]
 mod test {
 	use super::*;
-	use crate::{hash::*, storage::types::ValueQuery};
-	use frame_metadata::StorageEntryModifier;
+	use crate::{
+		hash::*,
+		metadata::{StorageEntryModifier, StorageEntryType, StorageHasher},
+		storage::types::ValueQuery,
+	};
+	use assert_matches::assert_matches;
 	use sp_io::{hashing::twox_128, TestExternalities};
 
 	struct Prefix;
@@ -572,14 +575,23 @@ mod test {
 
 			assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
 			assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
-			assert_eq!(A::HASHER, frame_metadata::StorageHasher::Blake2_128Concat);
-			assert_eq!(
-				AValueQueryWithAnOnEmpty::HASHER,
-				frame_metadata::StorageHasher::Blake2_128Concat
+
+			let assert_map_hashers = |ty, expected_hashers| {
+				if let StorageEntryType::Map { hashers, .. } = ty {
+					assert_eq!(hashers, expected_hashers)
+				} else {
+					assert_matches!(ty, StorageEntryType::Map { .. })
+				}
+			};
+
+			assert_map_hashers(A::ty(), vec![StorageHasher::Blake2_128Concat]);
+			assert_map_hashers(
+				AValueQueryWithAnOnEmpty::ty(),
+				vec![StorageHasher::Blake2_128Concat],
 			);
 			assert_eq!(A::NAME, "foo");
-			assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 97u32.encode());
-			assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
+			assert_eq!(AValueQueryWithAnOnEmpty::default(), 97u32.encode());
+			assert_eq!(A::default(), Option::<u32>::None.encode());
 
 			WithLen::remove_all(None);
 			assert_eq!(WithLen::decode_len(3), None);
diff --git a/substrate/frame/support/src/storage/types/mod.rs b/substrate/frame/support/src/storage/types/mod.rs
index d61ca6813c9dd31aa12122414ec1ee5a752e2b8a..76fed0b8cb320e4f01ae9b958784aa2bcfaea6e5 100644
--- a/substrate/frame/support/src/storage/types/mod.rs
+++ b/substrate/frame/support/src/storage/types/mod.rs
@@ -18,8 +18,9 @@
 //! Storage types to build abstraction on storage, they implements storage traits such as
 //! StorageMap and others.
 
+use crate::metadata::{StorageEntryModifier, StorageEntryType};
 use codec::FullCodec;
-use frame_metadata::{DefaultByte, StorageEntryModifier};
+use sp_std::prelude::*;
 
 mod double_map;
 mod key;
@@ -27,14 +28,14 @@ mod map;
 mod nmap;
 mod value;
 
-pub use double_map::{StorageDoubleMap, StorageDoubleMapMetadata};
+pub use double_map::StorageDoubleMap;
 pub use key::{
 	EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, Key, KeyGenerator,
 	KeyGeneratorMaxEncodedLen, ReversibleKeyGenerator, TupleToEncodedIter,
 };
-pub use map::{StorageMap, StorageMapMetadata};
-pub use nmap::{StorageNMap, StorageNMapMetadata};
-pub use value::{StorageValue, StorageValueMetadata};
+pub use map::StorageMap;
+pub use nmap::StorageNMap;
+pub use value::StorageValue;
 
 /// Trait implementing how the storage optional value is converted into the queried type.
 ///
@@ -102,14 +103,13 @@ where
 	}
 }
 
-/// A helper struct which implements DefaultByte using `Get<Value>` and encode it.
-struct OnEmptyGetter<Value, OnEmpty>(core::marker::PhantomData<(Value, OnEmpty)>);
-impl<Value: FullCodec, OnEmpty: crate::traits::Get<Value>> DefaultByte
-	for OnEmptyGetter<Value, OnEmpty>
-{
-	fn default_byte(&self) -> sp_std::vec::Vec<u8> {
-		OnEmpty::get().encode()
-	}
+/// Provide metadata for a storage entry.
+///
+/// Implemented by each of the storage entry kinds: value, map, doublemap and nmap.
+pub trait StorageEntryMetadata {
+	const MODIFIER: StorageEntryModifier;
+	const NAME: &'static str;
+
+	fn ty() -> StorageEntryType;
+	fn default() -> Vec<u8>;
 }
-unsafe impl<Value, OnEmpty: crate::traits::Get<Value>> Send for OnEmptyGetter<Value, OnEmpty> {}
-unsafe impl<Value, OnEmpty: crate::traits::Get<Value>> Sync for OnEmptyGetter<Value, OnEmpty> {}
diff --git a/substrate/frame/support/src/storage/types/nmap.rs b/substrate/frame/support/src/storage/types/nmap.rs
index 149872ccba9ab5f3ab2ca233338e89074850138a..7048a69d59c2c09bed08abb6d011998644042729 100755
--- a/substrate/frame/support/src/storage/types/nmap.rs
+++ b/substrate/frame/support/src/storage/types/nmap.rs
@@ -19,17 +19,17 @@
 //! StoragePrefixedDoubleMap traits and their methods directly.
 
 use crate::{
+	metadata::{StorageEntryModifier, StorageEntryType},
 	storage::{
 		types::{
-			EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, OnEmptyGetter, OptionQuery,
-			QueryKindTrait, TupleToEncodedIter,
+			EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, OptionQuery, QueryKindTrait,
+			StorageEntryMetadata, TupleToEncodedIter,
 		},
 		KeyGenerator, PrefixIterator, StorageAppend, StorageDecodeLength, StoragePrefixedMap,
 	},
 	traits::{Get, GetDefault, StorageInfo, StorageInstance},
 };
 use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
-use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
 use sp_runtime::SaturatedConversion;
 use sp_std::prelude::*;
 
@@ -440,31 +440,30 @@ where
 	}
 }
 
-/// Part of storage metadata for a storage n map.
-///
-/// NOTE: Generic hashers is supported.
-pub trait StorageNMapMetadata {
-	const MODIFIER: StorageEntryModifier;
-	const NAME: &'static str;
-	const DEFAULT: DefaultByteGetter;
-	const HASHERS: &'static [frame_metadata::StorageHasher];
-}
-
-impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues> StorageNMapMetadata
+impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues> StorageEntryMetadata
 	for StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
 where
 	Prefix: StorageInstance,
 	Key: super::key::KeyGenerator,
-	Value: FullCodec,
+	Value: FullCodec + scale_info::StaticTypeInfo,
 	QueryKind: QueryKindTrait<Value, OnEmpty>,
 	OnEmpty: Get<QueryKind::Query> + 'static,
 	MaxValues: Get<Option<u32>>,
 {
 	const MODIFIER: StorageEntryModifier = QueryKind::METADATA;
 	const NAME: &'static str = Prefix::STORAGE_PREFIX;
-	const DEFAULT: DefaultByteGetter =
-		DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
-	const HASHERS: &'static [frame_metadata::StorageHasher] = Key::HASHER_METADATA;
+
+	fn ty() -> StorageEntryType {
+		StorageEntryType::Map {
+			key: scale_info::meta_type::<Key::Key>(),
+			hashers: Key::HASHER_METADATA.iter().cloned().collect(),
+			value: scale_info::meta_type::<Value>(),
+		}
+	}
+
+	fn default() -> Vec<u8> {
+		OnEmpty::get().encode()
+	}
 }
 
 impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues> crate::traits::StorageInfoTrait
@@ -518,9 +517,9 @@ mod test {
 	use super::*;
 	use crate::{
 		hash::*,
+		metadata::StorageEntryModifier,
 		storage::types::{Key, ValueQuery},
 	};
-	use frame_metadata::StorageEntryModifier;
 	use sp_io::{hashing::twox_128, TestExternalities};
 
 	struct Prefix;
@@ -688,8 +687,8 @@ mod test {
 			assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
 			assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
 			assert_eq!(A::NAME, "Foo");
-			assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 98u32.encode());
-			assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
+			assert_eq!(AValueQueryWithAnOnEmpty::default(), 98u32.encode());
+			assert_eq!(A::default(), Option::<u32>::None.encode());
 
 			WithLen::remove_all(None);
 			assert_eq!(WithLen::decode_len((3,)), None);
@@ -856,8 +855,8 @@ mod test {
 			assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
 			assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
 			assert_eq!(A::NAME, "Foo");
-			assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 98u32.encode());
-			assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
+			assert_eq!(AValueQueryWithAnOnEmpty::default(), 98u32.encode());
+			assert_eq!(A::default(), Option::<u32>::None.encode());
 
 			WithLen::remove_all(None);
 			assert_eq!(WithLen::decode_len((3, 30)), None);
@@ -1046,8 +1045,8 @@ mod test {
 			assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
 			assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
 			assert_eq!(A::NAME, "Foo");
-			assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 98u32.encode());
-			assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
+			assert_eq!(AValueQueryWithAnOnEmpty::default(), 98u32.encode());
+			assert_eq!(A::default(), Option::<u32>::None.encode());
 
 			WithLen::remove_all(None);
 			assert_eq!(WithLen::decode_len((3, 30, 300)), None);
diff --git a/substrate/frame/support/src/storage/types/value.rs b/substrate/frame/support/src/storage/types/value.rs
index ad835e928bdd6cb828e77f2169a6890d56f0b031..d7f15487592b1b643bf85a6c9fa1dbf14d1e256a 100644
--- a/substrate/frame/support/src/storage/types/value.rs
+++ b/substrate/frame/support/src/storage/types/value.rs
@@ -18,15 +18,15 @@
 //! Storage value type. Implements StorageValue trait and its method directly.
 
 use crate::{
+	metadata::{StorageEntryModifier, StorageEntryType},
 	storage::{
 		generator::StorageValue as StorageValueT,
-		types::{OnEmptyGetter, OptionQuery, QueryKindTrait},
+		types::{OptionQuery, QueryKindTrait, StorageEntryMetadata},
 		StorageAppend, StorageDecodeLength, StorageTryAppend,
 	},
 	traits::{GetDefault, StorageInfo, StorageInstance},
 };
 use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
-use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
 use sp_arithmetic::traits::SaturatedConversion;
 use sp_std::prelude::*;
 
@@ -201,25 +201,24 @@ where
 	}
 }
 
-/// Part of storage metadata for storage value.
-pub trait StorageValueMetadata {
-	const MODIFIER: StorageEntryModifier;
-	const NAME: &'static str;
-	const DEFAULT: DefaultByteGetter;
-}
-
-impl<Prefix, Value, QueryKind, OnEmpty> StorageValueMetadata
+impl<Prefix, Value, QueryKind, OnEmpty> StorageEntryMetadata
 	for StorageValue<Prefix, Value, QueryKind, OnEmpty>
 where
 	Prefix: StorageInstance,
-	Value: FullCodec,
+	Value: FullCodec + scale_info::StaticTypeInfo,
 	QueryKind: QueryKindTrait<Value, OnEmpty>,
 	OnEmpty: crate::traits::Get<QueryKind::Query> + 'static,
 {
 	const MODIFIER: StorageEntryModifier = QueryKind::METADATA;
 	const NAME: &'static str = Prefix::STORAGE_PREFIX;
-	const DEFAULT: DefaultByteGetter =
-		DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
+
+	fn ty() -> StorageEntryType {
+		StorageEntryType::Plain(scale_info::meta_type::<Value>())
+	}
+
+	fn default() -> Vec<u8> {
+		OnEmpty::get().encode()
+	}
 }
 
 impl<Prefix, Value, QueryKind, OnEmpty> crate::traits::StorageInfoTrait
@@ -264,8 +263,7 @@ where
 #[cfg(test)]
 mod test {
 	use super::*;
-	use crate::storage::types::ValueQuery;
-	use frame_metadata::StorageEntryModifier;
+	use crate::{metadata::StorageEntryModifier, storage::types::ValueQuery};
 	use sp_io::{hashing::twox_128, TestExternalities};
 
 	struct Prefix;
@@ -347,8 +345,8 @@ mod test {
 			assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
 			assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
 			assert_eq!(A::NAME, "foo");
-			assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
-			assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 97u32.encode());
+			assert_eq!(A::default(), Option::<u32>::None.encode());
+			assert_eq!(AValueQueryWithAnOnEmpty::default(), 97u32.encode());
 
 			WithLen::kill();
 			assert_eq!(WithLen::decode_len(), None);
diff --git a/substrate/frame/support/src/storage/weak_bounded_vec.rs b/substrate/frame/support/src/storage/weak_bounded_vec.rs
index f60e4d87bde85f815cf3954295cbbb7ba70ae8bd..9c30c45c3e2e1d8c7c01591934fc5f3eb2120dcf 100644
--- a/substrate/frame/support/src/storage/weak_bounded_vec.rs
+++ b/substrate/frame/support/src/storage/weak_bounded_vec.rs
@@ -36,7 +36,8 @@ use sp_std::{convert::TryFrom, fmt, marker::PhantomData, prelude::*};
 ///
 /// The length of the vec is not strictly bounded. Decoding a vec with more element that the bound
 /// is accepted, and some method allow to bypass the restriction with warnings.
-#[derive(Encode)]
+#[derive(Encode, scale_info::TypeInfo)]
+#[scale_info(skip_type_params(S))]
 pub struct WeakBoundedVec<T, S>(Vec<T>, PhantomData<S>);
 
 impl<T: Decode, S: Get<u32>> Decode for WeakBoundedVec<T, S> {
diff --git a/substrate/frame/support/src/traits/tokens/misc.rs b/substrate/frame/support/src/traits/tokens/misc.rs
index bea6e664cf2cdca9d2a75ecae179532053659b5c..214c28708a19680a6c6a1af0dc5fb5a051422c06 100644
--- a/substrate/frame/support/src/traits/tokens/misc.rs
+++ b/substrate/frame/support/src/traits/tokens/misc.rs
@@ -116,7 +116,7 @@ pub enum ExistenceRequirement {
 }
 
 /// Status of funds.
-#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)]
 pub enum BalanceStatus {
 	/// Funds are free, as corresponding to `free` item in Balances.
 	Free,
@@ -165,8 +165,14 @@ pub trait AssetId: FullCodec + Copy + Eq + PartialEq + Debug {}
 impl<T: FullCodec + Copy + Eq + PartialEq + Debug> AssetId for T {}
 
 /// Simple amalgamation trait to collect together properties for a Balance under one roof.
-pub trait Balance: AtLeast32BitUnsigned + FullCodec + Copy + Default + Debug {}
-impl<T: AtLeast32BitUnsigned + FullCodec + Copy + Default + Debug> Balance for T {}
+pub trait Balance:
+	AtLeast32BitUnsigned + FullCodec + Copy + Default + Debug + scale_info::TypeInfo
+{
+}
+impl<T: AtLeast32BitUnsigned + FullCodec + Copy + Default + Debug + scale_info::TypeInfo> Balance
+	for T
+{
+}
 
 /// Converts a balance value into an asset balance.
 pub trait BalanceConversion<InBalance, AssetId, OutBalance> {
diff --git a/substrate/frame/support/src/weights.rs b/substrate/frame/support/src/weights.rs
index 7af6d440aa40cec9f780b2972a0d1f99c1600348..115470a9bf0349bc26d7f966799fe57fa5d4de95 100644
--- a/substrate/frame/support/src/weights.rs
+++ b/substrate/frame/support/src/weights.rs
@@ -129,6 +129,7 @@
 
 use crate::dispatch::{DispatchError, DispatchErrorWithPostInfo, DispatchResultWithPostInfo};
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
 use smallvec::{smallvec, SmallVec};
@@ -201,7 +202,7 @@ pub trait PaysFee<T> {
 }
 
 /// Explicit enum to denote if a transaction pays fee or not.
-#[derive(Clone, Copy, Eq, PartialEq, RuntimeDebug, Encode, Decode)]
+#[derive(Clone, Copy, Eq, PartialEq, RuntimeDebug, Encode, Decode, TypeInfo)]
 pub enum Pays {
 	/// Transactor will pay related fees.
 	Yes,
@@ -221,7 +222,7 @@ impl Default for Pays {
 /// [DispatchClass::all] and [DispatchClass::non_mandatory] helper functions.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
-#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)]
 pub enum DispatchClass {
 	/// A normal dispatch.
 	Normal,
@@ -311,7 +312,7 @@ pub mod priority {
 }
 
 /// A bundle of static information collected from the `#[weight = $x]` attributes.
-#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)]
+#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
 pub struct DispatchInfo {
 	/// Weight of this transaction.
 	pub weight: Weight,
@@ -338,7 +339,7 @@ impl GetDispatchInfo for () {
 
 /// Weight information that is only available post dispatch.
 /// NOTE: This can only be used to reduce the weight or fee, not increase it.
-#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)]
+#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
 pub struct PostDispatchInfo {
 	/// Actual weight consumed by a call or `None` which stands for the worst case static weight.
 	pub actual_weight: Option<Weight>,
@@ -627,7 +628,7 @@ impl<Call: Encode, Extra: Encode> GetDispatchInfo for sp_runtime::testing::TestX
 }
 
 /// The weight of database operations that the runtime can invoke.
-#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)]
+#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
 pub struct RuntimeDbWeight {
 	pub read: Weight,
 	pub write: Weight,
@@ -659,7 +660,7 @@ impl RuntimeDbWeight {
 ///
 /// The `negative` value encodes whether the term is added or substracted from the
 /// overall polynomial result.
-#[derive(Clone, Encode, Decode)]
+#[derive(Clone, Encode, Decode, TypeInfo)]
 pub struct WeightToFeeCoefficient<Balance> {
 	/// The integral part of the coefficient.
 	pub coeff_integer: Balance,
@@ -737,7 +738,7 @@ where
 }
 
 /// A struct holding value for each `DispatchClass`.
-#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)]
+#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
 pub struct PerDispatchClass<T> {
 	/// Value for `Normal` extrinsics.
 	normal: T,
@@ -882,49 +883,49 @@ mod tests {
 	#[test]
 	fn weights_are_correct() {
 		// #[weight = 1000]
-		let info = Call::<TraitImpl>::f00().get_dispatch_info();
+		let info = Call::<TraitImpl>::f00 {}.get_dispatch_info();
 		assert_eq!(info.weight, 1000);
 		assert_eq!(info.class, DispatchClass::Normal);
 		assert_eq!(info.pays_fee, Pays::Yes);
 
 		// #[weight = (1000, DispatchClass::Mandatory)]
-		let info = Call::<TraitImpl>::f01().get_dispatch_info();
+		let info = Call::<TraitImpl>::f01 {}.get_dispatch_info();
 		assert_eq!(info.weight, 1000);
 		assert_eq!(info.class, DispatchClass::Mandatory);
 		assert_eq!(info.pays_fee, Pays::Yes);
 
 		// #[weight = (1000, Pays::No)]
-		let info = Call::<TraitImpl>::f02().get_dispatch_info();
+		let info = Call::<TraitImpl>::f02 {}.get_dispatch_info();
 		assert_eq!(info.weight, 1000);
 		assert_eq!(info.class, DispatchClass::Normal);
 		assert_eq!(info.pays_fee, Pays::No);
 
 		// #[weight = (1000, DispatchClass::Operational, Pays::No)]
-		let info = Call::<TraitImpl>::f03().get_dispatch_info();
+		let info = Call::<TraitImpl>::f03 {}.get_dispatch_info();
 		assert_eq!(info.weight, 1000);
 		assert_eq!(info.class, DispatchClass::Operational);
 		assert_eq!(info.pays_fee, Pays::No);
 
 		// #[weight = ((_a * 10 + _eb * 1) as Weight, DispatchClass::Normal, Pays::Yes)]
-		let info = Call::<TraitImpl>::f11(13, 20).get_dispatch_info();
+		let info = Call::<TraitImpl>::f11 { _a: 13, _eb: 20 }.get_dispatch_info();
 		assert_eq!(info.weight, 150); // 13*10 + 20
 		assert_eq!(info.class, DispatchClass::Normal);
 		assert_eq!(info.pays_fee, Pays::Yes);
 
 		// #[weight = (0, DispatchClass::Operational, Pays::Yes)]
-		let info = Call::<TraitImpl>::f12(10, 20).get_dispatch_info();
+		let info = Call::<TraitImpl>::f12 { _a: 10, _eb: 20 }.get_dispatch_info();
 		assert_eq!(info.weight, 0);
 		assert_eq!(info.class, DispatchClass::Operational);
 		assert_eq!(info.pays_fee, Pays::Yes);
 
 		// #[weight = T::DbWeight::get().reads(3) + T::DbWeight::get().writes(2) + 10_000]
-		let info = Call::<TraitImpl>::f20().get_dispatch_info();
+		let info = Call::<TraitImpl>::f20 {}.get_dispatch_info();
 		assert_eq!(info.weight, 12300); // 100*3 + 1000*2 + 10_1000
 		assert_eq!(info.class, DispatchClass::Normal);
 		assert_eq!(info.pays_fee, Pays::Yes);
 
 		// #[weight = T::DbWeight::get().reads_writes(6, 5) + 40_000]
-		let info = Call::<TraitImpl>::f21().get_dispatch_info();
+		let info = Call::<TraitImpl>::f21 {}.get_dispatch_info();
 		assert_eq!(info.weight, 45600); // 100*6 + 1000*5 + 40_1000
 		assert_eq!(info.class, DispatchClass::Normal);
 		assert_eq!(info.pays_fee, Pays::Yes);
diff --git a/substrate/frame/support/test/Cargo.toml b/substrate/frame/support/test/Cargo.toml
index c8f746c7cb9d46f1a91f40a5293acf9bf3fb580d..e12880871e5c28f81bbacaac2ece4c957f097811 100644
--- a/substrate/frame/support/test/Cargo.toml
+++ b/substrate/frame/support/test/Cargo.toml
@@ -14,16 +14,18 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 serde = { version = "1.0.126", default-features = false, features = ["derive"] }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
+sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/arithmetic" }
 sp-io = { version = "4.0.0-dev", path = "../../../primitives/io", default-features = false }
 sp-state-machine = { version = "0.10.0-dev", optional = true, path = "../../../primitives/state-machine" }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/core" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" }
+sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" }
 trybuild = "1.0.43"
 pretty_assertions = "0.6.1"
 rustversion = "1.0.0"
-frame-metadata = { version = "14.0.0-dev", default-features = false, path = "../../metadata" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" }
 # The "std" feature for this pallet is never activated on purpose, in order to test construct_runtime error message
 test-pallet = { package = "frame-support-test-pallet", default-features = false, path = "pallet" }
@@ -33,6 +35,7 @@ default = ["std"]
 std = [
 	"serde/std",
 	"codec/std",
+	"scale-info/std",
 	"sp-io/std",
 	"frame-support/std",
 	"frame-system/std",
diff --git a/substrate/frame/support/test/pallet/Cargo.toml b/substrate/frame/support/test/pallet/Cargo.toml
index 3a421ecc461fe5183f4b6e3b594f15f3aa0bbd9d..35eb4f34acae10bb40fbdfad9ecadd8528facb9f 100644
--- a/substrate/frame/support/test/pallet/Cargo.toml
+++ b/substrate/frame/support/test/pallet/Cargo.toml
@@ -13,6 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../../" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../system" }
 
@@ -20,6 +21,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../../
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"frame-support/std",
 	"frame-system/std",
 ]
diff --git a/substrate/frame/support/test/src/lib.rs b/substrate/frame/support/test/src/lib.rs
index 78317a1a2f9072c59167e7f7b046d83aa52a4729..52c0a6270d47fcb300ed90a8a2efed72fa85e1bb 100644
--- a/substrate/frame/support/test/src/lib.rs
+++ b/substrate/frame/support/test/src/lib.rs
@@ -25,9 +25,9 @@
 /// The configuration trait
 pub trait Config: 'static {
 	/// The runtime origin type.
-	type Origin: codec::Codec + codec::EncodeLike + Default;
+	type Origin: codec::Codec + codec::EncodeLike + Default + scale_info::TypeInfo;
 	/// The block number type.
-	type BlockNumber: codec::Codec + codec::EncodeLike + Default;
+	type BlockNumber: codec::Codec + codec::EncodeLike + Default + scale_info::TypeInfo;
 	/// The information about the pallet setup in the runtime.
 	type PalletInfo: frame_support::traits::PalletInfo;
 	/// The db weights.
diff --git a/substrate/frame/support/test/tests/construct_runtime.rs b/substrate/frame/support/test/tests/construct_runtime.rs
index 5ddcb89a7dca279dd69d34a63eaa1256222906c7..062993fe10fbb29ebee751a14e3161fc9433bfb8 100644
--- a/substrate/frame/support/test/tests/construct_runtime.rs
+++ b/substrate/frame/support/test/tests/construct_runtime.rs
@@ -22,6 +22,7 @@
 #![recursion_limit = "128"]
 
 use frame_support::traits::PalletInfo as _;
+use scale_info::TypeInfo;
 use sp_core::{sr25519, H256};
 use sp_runtime::{
 	generic,
@@ -54,7 +55,7 @@ mod module1 {
 		}
 	}
 
-	#[derive(Clone, PartialEq, Eq, Debug, codec::Encode, codec::Decode)]
+	#[derive(Clone, PartialEq, Eq, Debug, codec::Encode, codec::Decode, TypeInfo)]
 	pub struct Origin<T, I: Instance = DefaultInstance>(pub core::marker::PhantomData<(T, I)>);
 
 	frame_support::decl_event! {
@@ -96,7 +97,7 @@ mod module2 {
 		}
 	}
 
-	#[derive(Clone, PartialEq, Eq, Debug, codec::Encode, codec::Decode)]
+	#[derive(Clone, PartialEq, Eq, Debug, codec::Encode, codec::Decode, TypeInfo)]
 	pub struct Origin;
 
 	frame_support::decl_event! {
@@ -139,7 +140,7 @@ mod nested {
 			}
 		}
 
-		#[derive(Clone, PartialEq, Eq, Debug, codec::Encode, codec::Decode)]
+		#[derive(Clone, PartialEq, Eq, Debug, codec::Encode, codec::Decode, TypeInfo)]
 		pub struct Origin;
 
 		frame_support::decl_event! {
@@ -195,7 +196,7 @@ pub mod module3 {
 		}
 	}
 
-	#[derive(Clone, PartialEq, Eq, Debug, codec::Encode, codec::Decode)]
+	#[derive(Clone, PartialEq, Eq, Debug, codec::Encode, codec::Decode, TypeInfo)]
 	pub struct Origin<T>(pub core::marker::PhantomData<T>);
 
 	frame_support::decl_event! {
@@ -309,8 +310,8 @@ mod origin_test {
 
 	#[test]
 	fn origin_default_filter() {
-		let accepted_call = nested::module3::Call::fail().into();
-		let rejected_call = module3::Call::fail().into();
+		let accepted_call = nested::module3::Call::fail {}.into();
+		let rejected_call = module3::Call::fail {}.into();
 
 		assert_eq!(Origin::root().filter_call(&accepted_call), true);
 		assert_eq!(Origin::root().filter_call(&rejected_call), true);
@@ -472,28 +473,28 @@ fn event_codec() {
 #[test]
 fn call_codec() {
 	use codec::Encode;
-	assert_eq!(Call::System(system::Call::noop()).encode()[0], 30);
-	assert_eq!(Call::Module1_1(module1::Call::fail()).encode()[0], 31);
-	assert_eq!(Call::Module2(module2::Call::fail()).encode()[0], 32);
-	assert_eq!(Call::Module1_2(module1::Call::fail()).encode()[0], 33);
-	assert_eq!(Call::NestedModule3(nested::module3::Call::fail()).encode()[0], 34);
-	assert_eq!(Call::Module3(module3::Call::fail()).encode()[0], 35);
-	assert_eq!(Call::Module1_4(module1::Call::fail()).encode()[0], 3);
-	assert_eq!(Call::Module1_6(module1::Call::fail()).encode()[0], 1);
-	assert_eq!(Call::Module1_7(module1::Call::fail()).encode()[0], 2);
-	assert_eq!(Call::Module1_8(module1::Call::fail()).encode()[0], 12);
-	assert_eq!(Call::Module1_9(module1::Call::fail()).encode()[0], 13);
+	assert_eq!(Call::System(system::Call::noop {}).encode()[0], 30);
+	assert_eq!(Call::Module1_1(module1::Call::fail {}).encode()[0], 31);
+	assert_eq!(Call::Module2(module2::Call::fail {}).encode()[0], 32);
+	assert_eq!(Call::Module1_2(module1::Call::fail {}).encode()[0], 33);
+	assert_eq!(Call::NestedModule3(nested::module3::Call::fail {}).encode()[0], 34);
+	assert_eq!(Call::Module3(module3::Call::fail {}).encode()[0], 35);
+	assert_eq!(Call::Module1_4(module1::Call::fail {}).encode()[0], 3);
+	assert_eq!(Call::Module1_6(module1::Call::fail {}).encode()[0], 1);
+	assert_eq!(Call::Module1_7(module1::Call::fail {}).encode()[0], 2);
+	assert_eq!(Call::Module1_8(module1::Call::fail {}).encode()[0], 12);
+	assert_eq!(Call::Module1_9(module1::Call::fail {}).encode()[0], 13);
 }
 
 #[test]
 fn call_compact_attr() {
 	use codec::Encode;
-	let call: module3::Call<Runtime> = module3::Call::aux_1(1);
+	let call: module3::Call<Runtime> = module3::Call::aux_1 { _data: 1 };
 	let encoded = call.encode();
 	assert_eq!(2, encoded.len());
 	assert_eq!(vec![1, 4], encoded);
 
-	let call: module3::Call<Runtime> = module3::Call::aux_2(1, 2);
+	let call: module3::Call<Runtime> = module3::Call::aux_2 { _data: 1, _data2: 2 };
 	let encoded = call.encode();
 	assert_eq!(6, encoded.len());
 	assert_eq!(vec![2, 1, 0, 0, 0, 8], encoded);
@@ -502,13 +503,13 @@ fn call_compact_attr() {
 #[test]
 fn call_encode_is_correct_and_decode_works() {
 	use codec::{Decode, Encode};
-	let call: module3::Call<Runtime> = module3::Call::fail();
+	let call: module3::Call<Runtime> = module3::Call::fail {};
 	let encoded = call.encode();
 	assert_eq!(vec![0], encoded);
 	let decoded = module3::Call::<Runtime>::decode(&mut &encoded[..]).unwrap();
 	assert_eq!(decoded, call);
 
-	let call: module3::Call<Runtime> = module3::Call::aux_3(32, "hello".into());
+	let call: module3::Call<Runtime> = module3::Call::aux_3 { _data: 32, _data2: "hello".into() };
 	let encoded = call.encode();
 	assert_eq!(vec![3, 32, 0, 0, 0, 20, 104, 101, 108, 108, 111], encoded);
 	let decoded = module3::Call::<Runtime>::decode(&mut &encoded[..]).unwrap();
@@ -523,12 +524,12 @@ fn call_weight_should_attach_to_call_enum() {
 	};
 	// operational.
 	assert_eq!(
-		module3::Call::<Runtime>::operational().get_dispatch_info(),
+		module3::Call::<Runtime>::operational {}.get_dispatch_info(),
 		DispatchInfo { weight: 5, class: DispatchClass::Operational, pays_fee: Pays::Yes },
 	);
 	// custom basic
 	assert_eq!(
-		module3::Call::<Runtime>::aux_4().get_dispatch_info(),
+		module3::Call::<Runtime>::aux_4 {}.get_dispatch_info(),
 		DispatchInfo { weight: 3, class: DispatchClass::Normal, pays_fee: Pays::Yes },
 	);
 }
@@ -536,14 +537,14 @@ fn call_weight_should_attach_to_call_enum() {
 #[test]
 fn call_name() {
 	use frame_support::dispatch::GetCallName;
-	let name = module3::Call::<Runtime>::aux_4().get_call_name();
+	let name = module3::Call::<Runtime>::aux_4 {}.get_call_name();
 	assert_eq!("aux_4", name);
 }
 
 #[test]
 fn call_metadata() {
 	use frame_support::dispatch::{CallMetadata, GetCallMetadata};
-	let call = Call::Module3(module3::Call::<Runtime>::aux_4());
+	let call = Call::Module3(module3::Call::<Runtime>::aux_4 {});
 	let metadata = call.get_call_metadata();
 	let expected = CallMetadata { function_name: "aux_4".into(), pallet_name: "Module3".into() };
 	assert_eq!(metadata, expected);
@@ -581,10 +582,10 @@ fn get_module_names() {
 #[test]
 fn call_subtype_conversion() {
 	use frame_support::{dispatch::CallableCallFor, traits::IsSubType};
-	let call = Call::Module3(module3::Call::<Runtime>::fail());
+	let call = Call::Module3(module3::Call::<Runtime>::fail {});
 	let subcall: Option<&CallableCallFor<Module3, Runtime>> = call.is_sub_type();
 	let subcall_none: Option<&CallableCallFor<Module2, Runtime>> = call.is_sub_type();
-	assert_eq!(Some(&module3::Call::<Runtime>::fail()), subcall);
+	assert_eq!(Some(&module3::Call::<Runtime>::fail {}), subcall);
 	assert_eq!(None, subcall_none);
 
 	let from = Call::from(subcall.unwrap().clone());
@@ -593,355 +594,145 @@ fn call_subtype_conversion() {
 
 #[test]
 fn test_metadata() {
-	use frame_metadata::*;
-	let expected_metadata: RuntimeMetadataLastVersion = RuntimeMetadataLastVersion {
-		modules: DecodeDifferent::Encode(&[
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("System"),
-				storage: None,
-				calls: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[FunctionMetadata {
-						name: DecodeDifferent::Encode("noop"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				event: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[
-						EventMetadata {
-							name: DecodeDifferent::Encode("ExtrinsicSuccess"),
-							arguments: DecodeDifferent::Encode(&[]),
-							documentation: DecodeDifferent::Encode(&[]),
-						},
-						EventMetadata {
-							name: DecodeDifferent::Encode("ExtrinsicFailed"),
-							arguments: DecodeDifferent::Encode(&[]),
-							documentation: DecodeDifferent::Encode(&[]),
-						},
-						EventMetadata {
-							name: DecodeDifferent::Encode("Ignore"),
-							arguments: DecodeDifferent::Encode(&["BlockNumber"]),
-							documentation: DecodeDifferent::Encode(&[]),
-						},
-					]
-				}))),
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 30,
-			},
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("Module1_1"),
-				storage: Some(DecodeDifferent::Encode(FnEncode(|| StorageMetadata {
-					prefix: DecodeDifferent::Encode("Instance1Module"),
-					entries: DecodeDifferent::Encode(&[]),
-				}))),
-				calls: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[FunctionMetadata {
-						name: DecodeDifferent::Encode("fail"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				event: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[EventMetadata {
-						name: DecodeDifferent::Encode("A"),
-						arguments: DecodeDifferent::Encode(&["AccountId"]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 31,
-			},
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("Module2"),
-				storage: Some(DecodeDifferent::Encode(FnEncode(|| StorageMetadata {
-					prefix: DecodeDifferent::Encode("Module"),
-					entries: DecodeDifferent::Encode(&[]),
-				}))),
-				calls: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[FunctionMetadata {
-						name: DecodeDifferent::Encode("fail"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				event: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[EventMetadata {
-						name: DecodeDifferent::Encode("A"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 32,
-			},
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("Module1_2"),
-				storage: Some(DecodeDifferent::Encode(FnEncode(|| StorageMetadata {
-					prefix: DecodeDifferent::Encode("Instance2Module"),
-					entries: DecodeDifferent::Encode(&[]),
-				}))),
-				calls: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[FunctionMetadata {
-						name: DecodeDifferent::Encode("fail"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				event: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[EventMetadata {
-						name: DecodeDifferent::Encode("A"),
-						arguments: DecodeDifferent::Encode(&["AccountId"]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 33,
-			},
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("NestedModule3"),
-				storage: Some(DecodeDifferent::Encode(FnEncode(|| StorageMetadata {
-					prefix: DecodeDifferent::Encode("Module"),
-					entries: DecodeDifferent::Encode(&[]),
-				}))),
-				calls: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[FunctionMetadata {
-						name: DecodeDifferent::Encode("fail"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				event: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[EventMetadata {
-						name: DecodeDifferent::Encode("A"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 34,
-			},
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("Module3"),
-				storage: Some(DecodeDifferent::Encode(FnEncode(|| StorageMetadata {
-					prefix: DecodeDifferent::Encode("Module"),
-					entries: DecodeDifferent::Encode(&[]),
-				}))),
-				calls: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[
-						FunctionMetadata {
-							name: DecodeDifferent::Encode("fail"),
-							arguments: DecodeDifferent::Encode(&[]),
-							documentation: DecodeDifferent::Encode(&[]),
-						},
-						FunctionMetadata {
-							name: DecodeDifferent::Encode("aux_1"),
-							arguments: DecodeDifferent::Encode(&[FunctionArgumentMetadata {
-								name: DecodeDifferent::Encode("_data"),
-								ty: DecodeDifferent::Encode("Compact<u32>"),
-							}]),
-							documentation: DecodeDifferent::Encode(&[]),
-						},
-						FunctionMetadata {
-							name: DecodeDifferent::Encode("aux_2"),
-							arguments: DecodeDifferent::Encode(&[
-								FunctionArgumentMetadata {
-									name: DecodeDifferent::Encode("_data"),
-									ty: DecodeDifferent::Encode("i32"),
-								},
-								FunctionArgumentMetadata {
-									name: DecodeDifferent::Encode("_data2"),
-									ty: DecodeDifferent::Encode("Compact<u32>"),
-								},
-							]),
-							documentation: DecodeDifferent::Encode(&[]),
-						},
-						FunctionMetadata {
-							name: DecodeDifferent::Encode("aux_3"),
-							arguments: DecodeDifferent::Encode(&[
-								FunctionArgumentMetadata {
-									name: DecodeDifferent::Encode("_data"),
-									ty: DecodeDifferent::Encode("i32"),
-								},
-								FunctionArgumentMetadata {
-									name: DecodeDifferent::Encode("_data2"),
-									ty: DecodeDifferent::Encode("String"),
-								},
-							]),
-							documentation: DecodeDifferent::Encode(&[]),
-						},
-						FunctionMetadata {
-							name: DecodeDifferent::Encode("aux_4"),
-							arguments: DecodeDifferent::Encode(&[]),
-							documentation: DecodeDifferent::Encode(&[]),
-						},
-						FunctionMetadata {
-							name: DecodeDifferent::Encode("operational"),
-							arguments: DecodeDifferent::Encode(&[]),
-							documentation: DecodeDifferent::Encode(&[]),
-						},
-					]
-				}))),
-				event: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[EventMetadata {
-						name: DecodeDifferent::Encode("A"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 35,
-			},
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("Module1_3"),
-				storage: Some(DecodeDifferent::Encode(FnEncode(|| StorageMetadata {
-					prefix: DecodeDifferent::Encode("Instance3Module"),
-					entries: DecodeDifferent::Encode(&[]),
-				}))),
-				calls: None,
-				event: None,
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 6,
-			},
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("Module1_4"),
-				storage: None,
-				calls: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[FunctionMetadata {
-						name: DecodeDifferent::Encode("fail"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				event: None,
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 3,
-			},
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("Module1_5"),
-				storage: None,
-				calls: None,
-				event: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[EventMetadata {
-						name: DecodeDifferent::Encode("A"),
-						arguments: DecodeDifferent::Encode(&["AccountId"]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 4,
-			},
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("Module1_6"),
-				storage: Some(DecodeDifferent::Encode(FnEncode(|| StorageMetadata {
-					prefix: DecodeDifferent::Encode("Instance6Module"),
-					entries: DecodeDifferent::Encode(&[]),
-				}))),
-				calls: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[FunctionMetadata {
-						name: DecodeDifferent::Encode("fail"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				event: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[EventMetadata {
-						name: DecodeDifferent::Encode("A"),
-						arguments: DecodeDifferent::Encode(&["AccountId"]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 1,
-			},
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("Module1_7"),
-				storage: Some(DecodeDifferent::Encode(FnEncode(|| StorageMetadata {
-					prefix: DecodeDifferent::Encode("Instance7Module"),
-					entries: DecodeDifferent::Encode(&[]),
-				}))),
-				calls: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[FunctionMetadata {
-						name: DecodeDifferent::Encode("fail"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				event: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[EventMetadata {
-						name: DecodeDifferent::Encode("A"),
-						arguments: DecodeDifferent::Encode(&["AccountId"]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 2,
-			},
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("Module1_8"),
-				storage: Some(DecodeDifferent::Encode(FnEncode(|| StorageMetadata {
-					prefix: DecodeDifferent::Encode("Instance8Module"),
-					entries: DecodeDifferent::Encode(&[]),
-				}))),
-				calls: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[FunctionMetadata {
-						name: DecodeDifferent::Encode("fail"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				event: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[EventMetadata {
-						name: DecodeDifferent::Encode("A"),
-						arguments: DecodeDifferent::Encode(&["AccountId"]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 12,
-			},
-			ModuleMetadata {
-				name: DecodeDifferent::Encode("Module1_9"),
-				storage: Some(DecodeDifferent::Encode(FnEncode(|| StorageMetadata {
-					prefix: DecodeDifferent::Encode("Instance9Module"),
-					entries: DecodeDifferent::Encode(&[]),
-				}))),
-				calls: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[FunctionMetadata {
-						name: DecodeDifferent::Encode("fail"),
-						arguments: DecodeDifferent::Encode(&[]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				event: Some(DecodeDifferent::Encode(FnEncode(|| {
-					&[EventMetadata {
-						name: DecodeDifferent::Encode("A"),
-						arguments: DecodeDifferent::Encode(&["AccountId"]),
-						documentation: DecodeDifferent::Encode(&[]),
-					}]
-				}))),
-				constants: DecodeDifferent::Encode(FnEncode(|| &[])),
-				errors: DecodeDifferent::Encode(FnEncode(|| &[])),
-				index: 13,
-			},
-		]),
-		extrinsic: ExtrinsicMetadata {
-			version: 4,
-			signed_extensions: vec![DecodeDifferent::Encode("UnitSignedExtension")],
+	use frame_support::metadata::*;
+	use scale_info::meta_type;
+
+	let pallets = vec![
+		PalletMetadata {
+			name: "System",
+			storage: None,
+			calls: Some(meta_type::<system::Call<Runtime>>().into()),
+			event: Some(meta_type::<system::Event<Runtime>>().into()),
+			constants: vec![],
+			error: None,
+			index: 30,
 		},
+		PalletMetadata {
+			name: "Module1_1",
+			storage: Some(PalletStorageMetadata { prefix: "Instance1Module", entries: vec![] }),
+			calls: Some(meta_type::<module1::Call<Runtime, module1::Instance1>>().into()),
+			event: Some(meta_type::<module1::Event<Runtime, module1::Instance1>>().into()),
+			constants: vec![],
+			error: None,
+			index: 31,
+		},
+		PalletMetadata {
+			name: "Module2",
+			storage: Some(PalletStorageMetadata { prefix: "Module", entries: vec![] }),
+			calls: Some(meta_type::<module2::Call<Runtime>>().into()),
+			event: Some(meta_type::<module2::Event>().into()),
+			constants: vec![],
+			error: None,
+			index: 32,
+		},
+		PalletMetadata {
+			name: "Module1_2",
+			storage: Some(PalletStorageMetadata { prefix: "Instance2Module", entries: vec![] }),
+			calls: Some(meta_type::<module1::Call<Runtime, module1::Instance2>>().into()),
+			event: Some(meta_type::<module1::Event<Runtime, module1::Instance2>>().into()),
+			constants: vec![],
+			error: None,
+			index: 33,
+		},
+		PalletMetadata {
+			name: "NestedModule3",
+			storage: Some(PalletStorageMetadata { prefix: "Module", entries: vec![] }),
+			calls: Some(meta_type::<nested::module3::Call<Runtime>>().into()),
+			event: Some(meta_type::<nested::module3::Event>().into()),
+			constants: vec![],
+			error: None,
+			index: 34,
+		},
+		PalletMetadata {
+			name: "Module3",
+			storage: Some(PalletStorageMetadata { prefix: "Module", entries: vec![] }),
+			calls: Some(meta_type::<module3::Call<Runtime>>().into()),
+			event: Some(meta_type::<module3::Event>().into()),
+			constants: vec![],
+			error: None,
+			index: 35,
+		},
+		PalletMetadata {
+			name: "Module1_3",
+			storage: Some(PalletStorageMetadata { prefix: "Instance3Module", entries: vec![] }),
+			calls: None,
+			event: None,
+			constants: vec![],
+			error: None,
+			index: 6,
+		},
+		PalletMetadata {
+			name: "Module1_4",
+			storage: None,
+			calls: Some(meta_type::<module1::Call<Runtime, module1::Instance4>>().into()),
+			event: None,
+			constants: vec![],
+			error: None,
+			index: 3,
+		},
+		PalletMetadata {
+			name: "Module1_5",
+			storage: None,
+			calls: None,
+			event: Some(meta_type::<module1::Event<Runtime, module1::Instance5>>().into()),
+			constants: vec![],
+			error: None,
+			index: 4,
+		},
+		PalletMetadata {
+			name: "Module1_6",
+			storage: Some(PalletStorageMetadata { prefix: "Instance6Module", entries: vec![] }),
+			calls: Some(meta_type::<module1::Call<Runtime, module1::Instance6>>().into()),
+			event: Some(meta_type::<module1::Event<Runtime, module1::Instance6>>().into()),
+			constants: vec![],
+			error: None,
+			index: 1,
+		},
+		PalletMetadata {
+			name: "Module1_7",
+			storage: Some(PalletStorageMetadata { prefix: "Instance7Module", entries: vec![] }),
+			calls: Some(meta_type::<module1::Call<Runtime, module1::Instance7>>().into()),
+			event: Some(PalletEventMetadata {
+				ty: meta_type::<module1::Event<Runtime, module1::Instance7>>(),
+			}),
+			constants: vec![],
+			error: None,
+			index: 2,
+		},
+		PalletMetadata {
+			name: "Module1_8",
+			storage: Some(PalletStorageMetadata { prefix: "Instance8Module", entries: vec![] }),
+			calls: Some(meta_type::<module1::Call<Runtime, module1::Instance8>>().into()),
+			event: Some(meta_type::<module1::Event<Runtime, module1::Instance8>>().into()),
+			constants: vec![],
+			error: None,
+			index: 12,
+		},
+		PalletMetadata {
+			name: "Module1_9",
+			storage: Some(PalletStorageMetadata { prefix: "Instance9Module", entries: vec![] }),
+			calls: Some(meta_type::<module1::Call<Runtime, module1::Instance9>>().into()),
+			event: Some(meta_type::<module1::Event<Runtime, module1::Instance9>>().into()),
+			constants: vec![],
+			error: None,
+			index: 13,
+		},
+	];
+
+	let extrinsic = ExtrinsicMetadata {
+		ty: meta_type::<UncheckedExtrinsic>(),
+		version: 4,
+		signed_extensions: vec![SignedExtensionMetadata {
+			identifier: "UnitSignedExtension",
+			ty: meta_type::<()>(),
+			additional_signed: meta_type::<()>(),
+		}],
 	};
-	pretty_assertions::assert_eq!(Runtime::metadata().1, RuntimeMetadata::V13(expected_metadata));
+
+	let expected_metadata: RuntimeMetadataPrefixed =
+		RuntimeMetadataLastVersion::new(pallets, extrinsic, meta_type::<Runtime>()).into();
+	let actual_metadata = Runtime::metadata();
+	pretty_assertions::assert_eq!(actual_metadata, expected_metadata);
 }
 
 #[test]
diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.stderr
index 6ae37ccf9b92d103372d44652dd390027576fd26..5bc831f58988bac376a1f0c8aade3a84e58654f4 100644
--- a/substrate/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.stderr
+++ b/substrate/frame/support/test/tests/construct_runtime_ui/no_std_genesis_config.stderr
@@ -36,6 +36,28 @@ help: consider importing this enum
 1  | use frame_system::RawOrigin;
    |
 
+error[E0433]: failed to resolve: use of undeclared crate or module `system`
+  --> $DIR/no_std_genesis_config.rs:13:1
+   |
+13 | / construct_runtime! {
+14 | |     pub enum Runtime where
+15 | |         Block = Block,
+16 | |         NodeBlock = Block,
+...  |
+21 | |     }
+22 | | }
+   | |_^ not found in `system`
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider importing one of these items
+   |
+1  | use frame_support_test::Pallet;
+   |
+1  | use frame_system::Pallet;
+   |
+1  | use test_pallet::Pallet;
+   |
+
 error[E0412]: cannot find type `GenesisConfig` in crate `test_pallet`
   --> $DIR/no_std_genesis_config.rs:13:1
    |
diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_call_part.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_call_part.stderr
index 201609b2abaf616beb8572e2948960d799e45a24..8781fe0df201a715bc171a4452b64dd4104c6d2f 100644
--- a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_call_part.stderr
+++ b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_call_part.stderr
@@ -39,6 +39,30 @@ help: consider importing this enum
 1  | use frame_system::RawOrigin;
    |
 
+error[E0433]: failed to resolve: use of undeclared crate or module `system`
+  --> $DIR/undefined_call_part.rs:22:1
+   |
+22 | / construct_runtime! {
+23 | |     pub enum Runtime where
+24 | |         Block = Block,
+25 | |         NodeBlock = Block,
+...  |
+30 | |     }
+31 | | }
+   | |_^ not found in `system`
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider importing one of these items
+   |
+1  | use crate::pallet::Pallet;
+   |
+1  | use frame_support_test::Pallet;
+   |
+1  | use frame_system::Pallet;
+   |
+1  | use test_pallet::Pallet;
+   |
+
 error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied
   --> $DIR/undefined_call_part.rs:20:6
    |
diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_event_part.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_event_part.stderr
index b68beb2b3fc65613ac9a3641f992c42ca6aa6f91..fa837698aa6420a3800b38237b29371320ae8d75 100644
--- a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_event_part.stderr
+++ b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_event_part.stderr
@@ -21,7 +21,7 @@ error[E0433]: failed to resolve: use of undeclared crate or module `system`
 28 |         System: system::{Pallet, Call, Storage, Config, Event<T>},
    |                 ^^^^^^ use of undeclared crate or module `system`
 
-error[E0433]: failed to resolve: could not find `Event` in `pallet`
+error[E0412]: cannot find type `Event` in module `pallet`
   --> $DIR/undefined_event_part.rs:22:1
    |
 22 | / construct_runtime! {
@@ -31,9 +31,13 @@ error[E0433]: failed to resolve: could not find `Event` in `pallet`
 ...  |
 30 | |     }
 31 | | }
-   | |_^ could not find `Event` in `pallet`
+   | |_^ not found in `pallet`
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider importing this enum
+   |
+1  | use frame_system::Event;
+   |
 
 error[E0412]: cannot find type `Event` in module `pallet`
   --> $DIR/undefined_event_part.rs:22:1
@@ -48,12 +52,14 @@ error[E0412]: cannot find type `Event` in module `pallet`
    | |_^ not found in `pallet`
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider importing this enum
+help: consider importing one of these items
+   |
+1  | use crate::Event;
    |
 1  | use frame_system::Event;
    |
 
-error[E0412]: cannot find type `Event` in module `pallet`
+error[E0433]: failed to resolve: use of undeclared crate or module `system`
   --> $DIR/undefined_event_part.rs:22:1
    |
 22 | / construct_runtime! {
@@ -63,14 +69,12 @@ error[E0412]: cannot find type `Event` in module `pallet`
 ...  |
 30 | |     }
 31 | | }
-   | |_^ not found in `pallet`
+   | |_^ not found in `system`
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider importing one of these items
-   |
-1  | use crate::Event;
+help: consider importing this enum
    |
-1  | use frame_system::Event;
+1  | use frame_system::RawOrigin;
    |
 
 error[E0433]: failed to resolve: use of undeclared crate or module `system`
@@ -86,9 +90,15 @@ error[E0433]: failed to resolve: use of undeclared crate or module `system`
    | |_^ not found in `system`
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider importing this enum
+help: consider importing one of these items
    |
-1  | use frame_system::RawOrigin;
+1  | use crate::pallet::Pallet;
+   |
+1  | use frame_support_test::Pallet;
+   |
+1  | use frame_system::Pallet;
+   |
+1  | use test_pallet::Pallet;
    |
 
 error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied
diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.stderr
index 686875d83a4f46b222a3aa046d50bd4cd323003f..699f66a414ed298b272724bfc729bc0ce0c19889 100644
--- a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.stderr
+++ b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_genesis_config_part.stderr
@@ -39,6 +39,30 @@ help: consider importing this enum
 1  | use frame_system::RawOrigin;
    |
 
+error[E0433]: failed to resolve: use of undeclared crate or module `system`
+  --> $DIR/undefined_genesis_config_part.rs:22:1
+   |
+22 | / construct_runtime! {
+23 | |     pub enum Runtime where
+24 | |         Block = Block,
+25 | |         NodeBlock = Block,
+...  |
+30 | |     }
+31 | | }
+   | |_^ not found in `system`
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider importing one of these items
+   |
+1  | use crate::pallet::Pallet;
+   |
+1  | use frame_support_test::Pallet;
+   |
+1  | use frame_system::Pallet;
+   |
+1  | use test_pallet::Pallet;
+   |
+
 error[E0412]: cannot find type `GenesisConfig` in module `pallet`
   --> $DIR/undefined_genesis_config_part.rs:22:1
    |
diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr
index 303819b45dd7cc4f86ba385ecafcce037ee3eec4..88ff9ee910937987857949995f0ad12cc40f39ba 100644
--- a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr
+++ b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr
@@ -39,6 +39,30 @@ help: consider importing this enum
 1  | use frame_system::RawOrigin;
    |
 
+error[E0433]: failed to resolve: use of undeclared crate or module `system`
+  --> $DIR/undefined_inherent_part.rs:22:1
+   |
+22 | / construct_runtime! {
+23 | |     pub enum Runtime where
+24 | |         Block = Block,
+25 | |         NodeBlock = Block,
+...  |
+30 | |     }
+31 | | }
+   | |_^ not found in `system`
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider importing one of these items
+   |
+1  | use crate::pallet::Pallet;
+   |
+1  | use frame_support_test::Pallet;
+   |
+1  | use frame_system::Pallet;
+   |
+1  | use test_pallet::Pallet;
+   |
+
 error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied
   --> $DIR/undefined_inherent_part.rs:20:6
    |
diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.stderr
index f49dcf5783e744b0731eacf703c801ff49c973d1..3b3aa75c1ea088628c6a5362a0b3a1f95dc9445c 100644
--- a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.stderr
+++ b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_origin_part.stderr
@@ -77,6 +77,30 @@ help: consider importing one of these items
 1  | use frame_system::Origin;
    |
 
+error[E0433]: failed to resolve: use of undeclared crate or module `system`
+  --> $DIR/undefined_origin_part.rs:22:1
+   |
+22 | / construct_runtime! {
+23 | |     pub enum Runtime where
+24 | |         Block = Block,
+25 | |         NodeBlock = Block,
+...  |
+30 | |     }
+31 | | }
+   | |_^ not found in `system`
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider importing one of these items
+   |
+1  | use crate::pallet::Pallet;
+   |
+1  | use frame_support_test::Pallet;
+   |
+1  | use frame_system::Pallet;
+   |
+1  | use test_pallet::Pallet;
+   |
+
 error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied
   --> $DIR/undefined_origin_part.rs:20:6
    |
diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.stderr
index 41202c3b005b74b4ae50c5429b85579ac241caf1..ac12c56d5c279e8478a34276673aa9bafa0ade7c 100644
--- a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.stderr
+++ b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_validate_unsigned_part.stderr
@@ -39,6 +39,30 @@ help: consider importing this enum
 1  | use frame_system::RawOrigin;
    |
 
+error[E0433]: failed to resolve: use of undeclared crate or module `system`
+  --> $DIR/undefined_validate_unsigned_part.rs:22:1
+   |
+22 | / construct_runtime! {
+23 | |     pub enum Runtime where
+24 | |         Block = Block,
+25 | |         NodeBlock = Block,
+...  |
+30 | |     }
+31 | | }
+   | |_^ not found in `system`
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider importing one of these items
+   |
+1  | use crate::pallet::Pallet;
+   |
+1  | use frame_support_test::Pallet;
+   |
+1  | use frame_system::Pallet;
+   |
+1  | use test_pallet::Pallet;
+   |
+
 error[E0277]: the trait bound `Runtime: frame_system::Config` is not satisfied
   --> $DIR/undefined_validate_unsigned_part.rs:20:6
    |
diff --git a/substrate/frame/support/test/tests/decl_storage.rs b/substrate/frame/support/test/tests/decl_storage.rs
index 50c8387bca555eb663bbc58ee859c6fd408d1ffc..347a3130daa79cba5cfb0ace090719f49f4f8c06 100644
--- a/substrate/frame/support/test/tests/decl_storage.rs
+++ b/substrate/frame/support/test/tests/decl_storage.rs
@@ -21,14 +21,17 @@
 mod tests {
 	use frame_support::metadata::*;
 	use sp_io::TestExternalities;
-	use std::marker::PhantomData;
 
 	frame_support::decl_module! {
 		pub struct Module<T: Config> for enum Call where origin: T::Origin, system=frame_support_test {}
 	}
 
 	pub trait Config: frame_support_test::Config {
-		type Origin2: codec::Codec + codec::EncodeLike + Default + codec::MaxEncodedLen;
+		type Origin2: codec::Codec
+			+ codec::EncodeLike
+			+ Default
+			+ codec::MaxEncodedLen
+			+ scale_info::TypeInfo;
 	}
 
 	frame_support::decl_storage! {
@@ -101,329 +104,265 @@ mod tests {
 		type Origin2 = u32;
 	}
 
-	const EXPECTED_METADATA: StorageMetadata = StorageMetadata {
-		prefix: DecodeDifferent::Encode("TestStorage"),
-		entries: DecodeDifferent::Encode(&[
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("U32"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructU32(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[" Hello, this is doc!"]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("PUBU32"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructPUBU32(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("U32MYDEF"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructU32MYDEF(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("PUBU32MYDEF"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructPUBU32MYDEF(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GETU32"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("T::Origin2")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructGETU32(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("PUBGETU32"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructPUBGETU32(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GETU32WITHCONFIG"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructGETU32WITHCONFIG(PhantomData::<TraitImpl>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("PUBGETU32WITHCONFIG"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructPUBGETU32WITHCONFIG(PhantomData::<TraitImpl>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GETU32MYDEF"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructGETU32MYDEF(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("PUBGETU32MYDEF"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructPUBGETU32MYDEF(PhantomData::<TraitImpl>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GETU32WITHCONFIGMYDEF"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructGETU32WITHCONFIGMYDEF(PhantomData::<TraitImpl>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("PUBGETU32WITHCONFIGMYDEF"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructPUBGETU32WITHCONFIGMYDEF(PhantomData::<TraitImpl>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("PUBGETU32WITHCONFIGMYDEFOPT"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructPUBGETU32WITHCONFIGMYDEFOPT(PhantomData::<TraitImpl>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GetU32WithBuilder"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructGetU32WithBuilder(PhantomData::<TraitImpl>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GetOptU32WithBuilderSome"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructGetOptU32WithBuilderSome(PhantomData::<TraitImpl>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GetOptU32WithBuilderNone"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructGetOptU32WithBuilderNone(PhantomData::<TraitImpl>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("MAPU32"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::Map {
-					hasher: StorageHasher::Blake2_128Concat,
-					key: DecodeDifferent::Encode("u32"),
-					value: DecodeDifferent::Encode("[u8; 4]"),
-					unused: false,
-				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructMAPU32(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("PUBMAPU32"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::Map {
-					hasher: StorageHasher::Blake2_128Concat,
-					key: DecodeDifferent::Encode("u32"),
-					value: DecodeDifferent::Encode("[u8; 4]"),
-					unused: false,
-				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructPUBMAPU32(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GETMAPU32"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Map {
-					hasher: StorageHasher::Blake2_128Concat,
-					key: DecodeDifferent::Encode("u32"),
-					value: DecodeDifferent::Encode("[u8; 4]"),
-					unused: false,
-				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructGETMAPU32(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("PUBGETMAPU32"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Map {
-					hasher: StorageHasher::Blake2_128Concat,
-					key: DecodeDifferent::Encode("u32"),
-					value: DecodeDifferent::Encode("[u8; 4]"),
-					unused: false,
-				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructPUBGETMAPU32(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("GETMAPU32MYDEF"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Map {
-					hasher: StorageHasher::Blake2_128Concat,
-					key: DecodeDifferent::Encode("u32"),
-					value: DecodeDifferent::Encode("[u8; 4]"),
-					unused: false,
-				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructGETMAPU32MYDEF(PhantomData::<TraitImpl>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("PUBGETMAPU32MYDEF"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Map {
-					hasher: StorageHasher::Blake2_128Concat,
-					key: DecodeDifferent::Encode("u32"),
-					value: DecodeDifferent::Encode("[u8; 4]"),
-					unused: false,
-				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(
-					&__GetByteStructPUBGETMAPU32MYDEF(PhantomData::<TraitImpl>),
-				)),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("DOUBLEMAP"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::DoubleMap {
-					hasher: StorageHasher::Blake2_128Concat,
-					key1: DecodeDifferent::Encode("u32"),
-					key2: DecodeDifferent::Encode("u32"),
-					value: DecodeDifferent::Encode("[u8; 4]"),
-					key2_hasher: StorageHasher::Blake2_128Concat,
-				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructDOUBLEMAP(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("DOUBLEMAP2"),
-				modifier: StorageEntryModifier::Optional,
-				ty: StorageEntryType::DoubleMap {
-					hasher: StorageHasher::Blake2_128Concat,
-					key1: DecodeDifferent::Encode("u32"),
-					key2: DecodeDifferent::Encode("u32"),
-					value: DecodeDifferent::Encode("[u8; 4]"),
-					key2_hasher: StorageHasher::Blake2_128Concat,
-				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructDOUBLEMAP2(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("COMPLEXTYPE1"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode(
-					"(::std::option::Option<T::Origin2>,)",
-				)),
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructCOMPLEXTYPE1(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("COMPLEXTYPE2"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode(
-					"([[(u16, Option<()>); 32]; 12], u32)",
-				)),
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructCOMPLEXTYPE2(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("COMPLEXTYPE3"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::Plain(DecodeDifferent::Encode("[u32; 25]")),
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructCOMPLEXTYPE3(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("NMAP"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::NMap {
-					keys: DecodeDifferent::Encode(&["u32", "u16"]),
-					hashers: DecodeDifferent::Encode(&[
-						StorageHasher::Blake2_128Concat,
-						StorageHasher::Twox64Concat,
-					]),
-					value: DecodeDifferent::Encode("u8"),
-				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructNMAP(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-			StorageEntryMetadata {
-				name: DecodeDifferent::Encode("NMAP2"),
-				modifier: StorageEntryModifier::Default,
-				ty: StorageEntryType::NMap {
-					keys: DecodeDifferent::Encode(&["u32"]),
-					hashers: DecodeDifferent::Encode(&[StorageHasher::Blake2_128Concat]),
-					value: DecodeDifferent::Encode("u8"),
-				},
-				default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructNMAP(
-					PhantomData::<TraitImpl>,
-				))),
-				documentation: DecodeDifferent::Encode(&[]),
-			},
-		]),
-	};
+	fn expected_metadata() -> PalletStorageMetadata {
+		PalletStorageMetadata {
+			prefix: "TestStorage",
+			entries: vec![
+				StorageEntryMetadata {
+					name: "U32",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0],
+					docs: vec![" Hello, this is doc!"],
+				},
+				StorageEntryMetadata {
+					name: "PUBU32",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "U32MYDEF",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "PUBU32MYDEF",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "GETU32",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0, 0, 0, 0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "PUBGETU32",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0, 0, 0, 0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "GETU32WITHCONFIG",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0, 0, 0, 0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "PUBGETU32WITHCONFIG",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0, 0, 0, 0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "GETU32MYDEF",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "PUBGETU32MYDEF",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![3, 0, 0, 0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "GETU32WITHCONFIGMYDEF",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![2, 0, 0, 0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "PUBGETU32WITHCONFIGMYDEF",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![1, 0, 0, 0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "PUBGETU32WITHCONFIGMYDEFOPT",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "GetU32WithBuilder",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0, 0, 0, 0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "GetOptU32WithBuilderSome",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "GetOptU32WithBuilderNone",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "MAPU32",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Blake2_128Concat],
+						key: scale_info::meta_type::<u32>(),
+						value: scale_info::meta_type::<[u8; 4]>(),
+					},
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "PUBMAPU32",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Blake2_128Concat],
+						key: scale_info::meta_type::<u32>(),
+						value: scale_info::meta_type::<[u8; 4]>(),
+					},
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "GETMAPU32",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Blake2_128Concat],
+						key: scale_info::meta_type::<u32>(),
+						value: scale_info::meta_type::<[u8; 4]>(),
+					},
+					default: vec![0, 0, 0, 0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "PUBGETMAPU32",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Blake2_128Concat],
+						key: scale_info::meta_type::<u32>(),
+						value: scale_info::meta_type::<[u8; 4]>(),
+					},
+					default: vec![0, 0, 0, 0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "GETMAPU32MYDEF",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Blake2_128Concat],
+						key: scale_info::meta_type::<u32>(),
+						value: scale_info::meta_type::<[u8; 4]>(),
+					},
+					default: vec![109, 97, 112, 100], // "map"
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "PUBGETMAPU32MYDEF",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Map {
+						hashers: vec![StorageHasher::Blake2_128Concat],
+						key: scale_info::meta_type::<u32>(),
+						value: scale_info::meta_type::<[u8; 4]>(),
+					},
+					default: vec![112, 117, 98, 109], // "pubmap"
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "DOUBLEMAP",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Map {
+						hashers: vec![
+							StorageHasher::Blake2_128Concat,
+							StorageHasher::Blake2_128Concat,
+						],
+						key: scale_info::meta_type::<(u32, u32)>(),
+						value: scale_info::meta_type::<[u8; 4]>(),
+					},
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "DOUBLEMAP2",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Map {
+						hashers: vec![
+							StorageHasher::Blake2_128Concat,
+							StorageHasher::Blake2_128Concat,
+						],
+						key: scale_info::meta_type::<(u32, u32)>(),
+						value: scale_info::meta_type::<[u8; 4]>(),
+					},
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "COMPLEXTYPE1",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<(Option<u32>,)>()),
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "COMPLEXTYPE2",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<(
+						[[(u16, Option<()>); 32]; 12],
+						u32,
+					)>()),
+					default: [0u8; 1156].to_vec(),
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "COMPLEXTYPE3",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Plain(scale_info::meta_type::<[u32; 25]>()),
+					default: [0u8; 100].to_vec(),
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "NMAP",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Map {
+						key: scale_info::meta_type::<(u32, u16)>(),
+						hashers: vec![StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat],
+						value: scale_info::meta_type::<u8>(),
+					},
+					default: vec![0],
+					docs: vec![],
+				},
+				StorageEntryMetadata {
+					name: "NMAP2",
+					modifier: StorageEntryModifier::Default,
+					ty: StorageEntryType::Map {
+						key: scale_info::meta_type::<u32>(),
+						hashers: vec![StorageHasher::Blake2_128Concat],
+						value: scale_info::meta_type::<u8>(),
+					},
+					default: vec![0],
+					docs: vec![],
+				},
+			],
+		}
+	}
 
 	#[test]
 	fn storage_info() {
@@ -645,7 +584,7 @@ mod tests {
 	#[test]
 	fn store_metadata() {
 		let metadata = Module::<TraitImpl>::storage_metadata();
-		pretty_assertions::assert_eq!(EXPECTED_METADATA, metadata);
+		pretty_assertions::assert_eq!(expected_metadata(), metadata);
 	}
 
 	#[test]
@@ -790,7 +729,7 @@ mod test_append_and_len {
 		pub struct Module<T: Config> for enum Call where origin: T::Origin, system=frame_support_test {}
 	}
 
-	#[derive(PartialEq, Eq, Clone, Encode, Decode)]
+	#[derive(PartialEq, Eq, Clone, Encode, Decode, scale_info::TypeInfo)]
 	struct NoDef(u32);
 
 	frame_support::decl_storage! {
diff --git a/substrate/frame/support/test/tests/instance.rs b/substrate/frame/support/test/tests/instance.rs
index a948853ff2a440b36d2d687e26957c1aa4aefdc4..809edae14f80cb9ce9fec13c334ffa4d29d555e8 100644
--- a/substrate/frame/support/test/tests/instance.rs
+++ b/substrate/frame/support/test/tests/instance.rs
@@ -21,13 +21,14 @@ use codec::{Codec, Decode, Encode, EncodeLike};
 use frame_support::{
 	inherent::{InherentData, InherentIdentifier, MakeFatalError, ProvideInherent},
 	metadata::{
-		DecodeDifferent, DefaultByteGetter, StorageEntryMetadata, StorageEntryModifier,
-		StorageEntryType, StorageHasher, StorageMetadata,
+		PalletStorageMetadata, StorageEntryMetadata, StorageEntryModifier, StorageEntryType,
+		StorageHasher,
 	},
 	parameter_types,
 	traits::Get,
 	Parameter, StorageDoubleMap, StorageMap, StorageValue,
 };
+use scale_info::TypeInfo;
 use sp_core::{sr25519, H256};
 use sp_runtime::{
 	generic,
@@ -53,7 +54,7 @@ mod module1 {
 		type Event: From<Event<Self, I>> + Into<<Self as system::Config>::Event>;
 		type Origin: From<Origin<Self, I>>;
 		type SomeParameter: Get<u32>;
-		type GenericType: Default + Clone + Codec + EncodeLike;
+		type GenericType: Default + Clone + Codec + EncodeLike + TypeInfo;
 	}
 
 	frame_support::decl_module! {
@@ -108,7 +109,7 @@ mod module1 {
 		}
 	}
 
-	#[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug, Encode, Decode)]
+	#[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug, Encode, Decode, TypeInfo)]
 	pub enum Origin<T: Config<I>, I>
 	where
 		T::BlockNumber: From<u32>,
@@ -181,7 +182,7 @@ mod module2 {
 		}
 	}
 
-	#[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug, Encode, Decode)]
+	#[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug, Encode, Decode, TypeInfo)]
 	pub enum Origin<T: Config<I>, I = DefaultInstance> {
 		Members(u32),
 		_Phantom(std::marker::PhantomData<(T, I)>),
@@ -410,54 +411,45 @@ fn storage_with_instance_basic_operation() {
 	});
 }
 
-const EXPECTED_METADATA: StorageMetadata = StorageMetadata {
-	prefix: DecodeDifferent::Encode("Instance2Module2"),
-	entries: DecodeDifferent::Encode(&[
-		StorageEntryMetadata {
-			name: DecodeDifferent::Encode("Value"),
-			modifier: StorageEntryModifier::Default,
-			ty: StorageEntryType::Plain(DecodeDifferent::Encode("T::Amount")),
-			default: DecodeDifferent::Encode(DefaultByteGetter(&module2::__GetByteStructValue(
-				std::marker::PhantomData::<(Runtime, module2::Instance2)>,
-			))),
-			documentation: DecodeDifferent::Encode(&[]),
-		},
-		StorageEntryMetadata {
-			name: DecodeDifferent::Encode("Map"),
-			modifier: StorageEntryModifier::Default,
-			ty: StorageEntryType::Map {
-				hasher: StorageHasher::Identity,
-				key: DecodeDifferent::Encode("u64"),
-				value: DecodeDifferent::Encode("u64"),
-				unused: false,
+fn expected_metadata() -> PalletStorageMetadata {
+	PalletStorageMetadata {
+		prefix: "Instance2Module2",
+		entries: vec![
+			StorageEntryMetadata {
+				name: "Value",
+				modifier: StorageEntryModifier::Default,
+				ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+				default: vec![0, 0, 0, 0],
+				docs: vec![],
 			},
-			default: DecodeDifferent::Encode(DefaultByteGetter(&module2::__GetByteStructMap(
-				std::marker::PhantomData::<(Runtime, module2::Instance2)>,
-			))),
-			documentation: DecodeDifferent::Encode(&[]),
-		},
-		StorageEntryMetadata {
-			name: DecodeDifferent::Encode("DoubleMap"),
-			modifier: StorageEntryModifier::Default,
-			ty: StorageEntryType::DoubleMap {
-				hasher: StorageHasher::Identity,
-				key2_hasher: StorageHasher::Identity,
-				key1: DecodeDifferent::Encode("u64"),
-				key2: DecodeDifferent::Encode("u64"),
-				value: DecodeDifferent::Encode("u64"),
+			StorageEntryMetadata {
+				name: "Map",
+				modifier: StorageEntryModifier::Default,
+				ty: StorageEntryType::Map {
+					hashers: vec![StorageHasher::Identity],
+					key: scale_info::meta_type::<u64>(),
+					value: scale_info::meta_type::<u64>(),
+				},
+				default: [0u8; 8].to_vec(),
+				docs: vec![],
 			},
-			default: DecodeDifferent::Encode(DefaultByteGetter(
-				&module2::__GetByteStructDoubleMap(
-					std::marker::PhantomData::<(Runtime, module2::Instance2)>,
-				),
-			)),
-			documentation: DecodeDifferent::Encode(&[]),
-		},
-	]),
-};
+			StorageEntryMetadata {
+				name: "DoubleMap",
+				modifier: StorageEntryModifier::Default,
+				ty: StorageEntryType::Map {
+					hashers: vec![StorageHasher::Identity, StorageHasher::Identity],
+					key: scale_info::meta_type::<(u64, u64)>(),
+					value: scale_info::meta_type::<u64>(),
+				},
+				default: [0u8; 8].to_vec(),
+				docs: vec![],
+			},
+		],
+	}
+}
 
 #[test]
 fn test_instance_storage_metadata() {
 	let metadata = Module2_2::storage_metadata();
-	pretty_assertions::assert_eq!(EXPECTED_METADATA, metadata);
+	pretty_assertions::assert_eq!(expected_metadata(), metadata);
 }
diff --git a/substrate/frame/support/test/tests/issue2219.rs b/substrate/frame/support/test/tests/issue2219.rs
index 17eebf2d1022ea83f6be57abbb606e976064099d..68ad2a50a21bcff3198369ed4514f63327e7a24e 100644
--- a/substrate/frame/support/test/tests/issue2219.rs
+++ b/substrate/frame/support/test/tests/issue2219.rs
@@ -17,6 +17,7 @@
 
 use frame_support::{
 	codec::{Decode, Encode},
+	scale_info::TypeInfo,
 	sp_runtime::{
 		generic,
 		traits::{BlakeTwo256, Verify},
@@ -34,12 +35,12 @@ mod module {
 		(<T as system::Config>::AccountId, Role, <T as system::Config>::BlockNumber);
 	pub type Requests<T> = Vec<Request<T>>;
 
-	#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Debug)]
+	#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Debug, TypeInfo)]
 	pub enum Role {
 		Storage,
 	}
 
-	#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Debug)]
+	#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Debug, TypeInfo)]
 	pub struct RoleParameters<T: Config> {
 		// minimum actors to maintain - if role is unstaking
 		// and remaining actors would be less that this value - prevent or punish for unstaking
@@ -82,7 +83,7 @@ mod module {
 		}
 	}
 
-	pub trait Config: system::Config {}
+	pub trait Config: system::Config + TypeInfo {}
 
 	frame_support::decl_module! {
 		pub struct Module<T: Config> for enum Call where origin: T::Origin, system=system {}
diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs
index 80bae000b6c77dc4dffd81da74ce4a7e90ee0fb0..2874ef6bd7685507125e86140ba98d0dde2333a0 100644
--- a/substrate/frame/support/test/tests/pallet.rs
+++ b/substrate/frame/support/test/tests/pallet.rs
@@ -24,6 +24,7 @@ use frame_support::{
 	},
 	weights::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays, RuntimeDbWeight},
 };
+use scale_info::{meta_type, TypeInfo};
 use sp_io::{
 	hashing::{blake2_128, twox_128, twox_64},
 	TestExternalities,
@@ -80,14 +81,14 @@ impl From<SomeType7> for u64 {
 }
 
 pub trait SomeAssociation1 {
-	type _1: Parameter + codec::MaxEncodedLen;
+	type _1: Parameter + codec::MaxEncodedLen + TypeInfo;
 }
 impl SomeAssociation1 for u64 {
 	type _1 = u64;
 }
 
 pub trait SomeAssociation2 {
-	type _2: Parameter + codec::MaxEncodedLen;
+	type _2: Parameter + codec::MaxEncodedLen + TypeInfo;
 }
 impl SomeAssociation2 for u64 {
 	type _2 = u64;
@@ -101,6 +102,7 @@ pub mod pallet {
 	};
 	use frame_support::pallet_prelude::*;
 	use frame_system::pallet_prelude::*;
+	use scale_info::TypeInfo;
 
 	type BalanceOf<T> = <T as Config>::Balance;
 
@@ -124,7 +126,7 @@ pub mod pallet {
 		#[pallet::constant]
 		type MyGetParam3: Get<<Self::AccountId as SomeAssociation1>::_1>;
 
-		type Balance: Parameter + Default;
+		type Balance: Parameter + Default + TypeInfo;
 
 		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
 	}
@@ -228,7 +230,6 @@ pub mod pallet {
 	}
 
 	#[pallet::event]
-	#[pallet::metadata(BalanceOf<T> = "Balance", u32 = "Other")]
 	#[pallet::generate_deposit(fn deposit_event)]
 	pub enum Event<T: Config>
 	where
@@ -340,7 +341,9 @@ pub mod pallet {
 	}
 
 	#[pallet::origin]
-	#[derive(EqNoBound, RuntimeDebugNoBound, CloneNoBound, PartialEqNoBound, Encode, Decode)]
+	#[derive(
+		EqNoBound, RuntimeDebugNoBound, CloneNoBound, PartialEqNoBound, Encode, Decode, TypeInfo,
+	)]
 	pub struct Origin<T>(PhantomData<T>);
 
 	#[pallet::validate_unsigned]
@@ -352,7 +355,7 @@ pub mod pallet {
 		fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
 			T::AccountId::from(SomeType1); // Test for where clause
 			T::AccountId::from(SomeType5); // Test for where clause
-			if matches!(call, Call::foo_transactional(_)) {
+			if matches!(call, Call::foo_transactional { .. }) {
 				return Ok(ValidTransaction::default())
 			}
 			Err(TransactionValidityError::Invalid(InvalidTransaction::Call))
@@ -372,18 +375,18 @@ pub mod pallet {
 		fn create_inherent(_data: &InherentData) -> Option<Self::Call> {
 			T::AccountId::from(SomeType1); // Test for where clause
 			T::AccountId::from(SomeType6); // Test for where clause
-			Some(Call::foo_no_post_info())
+			Some(Call::foo_no_post_info {})
 		}
 
 		fn is_inherent(call: &Self::Call) -> bool {
-			matches!(call, Call::foo_no_post_info() | Call::foo(..))
+			matches!(call, Call::foo_no_post_info {} | Call::foo { .. })
 		}
 
 		fn check_inherent(call: &Self::Call, _: &InherentData) -> Result<(), Self::Error> {
 			match call {
-				Call::foo_no_post_info() => Ok(()),
-				Call::foo(0, 0) => Err(InherentError::Fatal),
-				Call::foo(..) => Ok(()),
+				Call::foo_no_post_info {} => Ok(()),
+				Call::foo { foo: 0, bar: 0 } => Err(InherentError::Fatal),
+				Call::foo { .. } => Ok(()),
 				_ => unreachable!("other calls are not inherents"),
 			}
 		}
@@ -550,13 +553,13 @@ fn transactional_works() {
 	TestExternalities::default().execute_with(|| {
 		frame_system::Pallet::<Runtime>::set_block_number(1);
 
-		pallet::Call::<Runtime>::foo_transactional(0)
+		pallet::Call::<Runtime>::foo_transactional { foo: 0 }
 			.dispatch_bypass_filter(None.into())
 			.err()
 			.unwrap();
 		assert!(frame_system::Pallet::<Runtime>::events().is_empty());
 
-		pallet::Call::<Runtime>::foo_transactional(1)
+		pallet::Call::<Runtime>::foo_transactional { foo: 1 }
 			.dispatch_bypass_filter(None.into())
 			.unwrap();
 		assert_eq!(
@@ -571,7 +574,7 @@ fn transactional_works() {
 
 #[test]
 fn call_expand() {
-	let call_foo = pallet::Call::<Runtime>::foo(3, 0);
+	let call_foo = pallet::Call::<Runtime>::foo { foo: 3, bar: 0 };
 	assert_eq!(
 		call_foo.get_dispatch_info(),
 		DispatchInfo { weight: 3, class: DispatchClass::Normal, pays_fee: Pays::Yes }
@@ -620,7 +623,7 @@ fn inherent_expand() {
 	let inherents = InherentData::new().create_extrinsics();
 
 	let expected = vec![UncheckedExtrinsic {
-		function: Call::Example(pallet::Call::foo_no_post_info()),
+		function: Call::Example(pallet::Call::foo_no_post_info {}),
 		signature: None,
 	}];
 	assert_eq!(expected, inherents);
@@ -635,11 +638,11 @@ fn inherent_expand() {
 		),
 		vec![
 			UncheckedExtrinsic {
-				function: Call::Example(pallet::Call::foo_no_post_info()),
+				function: Call::Example(pallet::Call::foo_no_post_info {}),
 				signature: None,
 			},
 			UncheckedExtrinsic {
-				function: Call::Example(pallet::Call::foo(1, 0)),
+				function: Call::Example(pallet::Call::foo { foo: 1, bar: 0 }),
 				signature: None,
 			},
 		],
@@ -657,11 +660,11 @@ fn inherent_expand() {
 		),
 		vec![
 			UncheckedExtrinsic {
-				function: Call::Example(pallet::Call::foo_no_post_info()),
+				function: Call::Example(pallet::Call::foo_no_post_info {}),
 				signature: None,
 			},
 			UncheckedExtrinsic {
-				function: Call::Example(pallet::Call::foo(0, 0)),
+				function: Call::Example(pallet::Call::foo { foo: 0, bar: 0 }),
 				signature: None,
 			},
 		],
@@ -678,7 +681,7 @@ fn inherent_expand() {
 			Digest::default(),
 		),
 		vec![UncheckedExtrinsic {
-			function: Call::Example(pallet::Call::foo_transactional(0)),
+			function: Call::Example(pallet::Call::foo_transactional { foo: 0 }),
 			signature: None,
 		}],
 	);
@@ -696,7 +699,7 @@ fn inherent_expand() {
 			Digest::default(),
 		),
 		vec![UncheckedExtrinsic {
-			function: Call::Example(pallet::Call::foo_no_post_info()),
+			function: Call::Example(pallet::Call::foo_no_post_info {}),
 			signature: Some((1, (), ())),
 		}],
 	);
@@ -715,11 +718,11 @@ fn inherent_expand() {
 		),
 		vec![
 			UncheckedExtrinsic {
-				function: Call::Example(pallet::Call::foo(1, 1)),
+				function: Call::Example(pallet::Call::foo { foo: 1, bar: 1 }),
 				signature: None,
 			},
 			UncheckedExtrinsic {
-				function: Call::Example(pallet::Call::foo_transactional(0)),
+				function: Call::Example(pallet::Call::foo_transactional { foo: 0 }),
 				signature: None,
 			},
 		],
@@ -737,15 +740,15 @@ fn inherent_expand() {
 		),
 		vec![
 			UncheckedExtrinsic {
-				function: Call::Example(pallet::Call::foo(1, 1)),
+				function: Call::Example(pallet::Call::foo { foo: 1, bar: 1 }),
 				signature: None,
 			},
 			UncheckedExtrinsic {
-				function: Call::Example(pallet::Call::foo_transactional(0)),
+				function: Call::Example(pallet::Call::foo_transactional { foo: 0 }),
 				signature: None,
 			},
 			UncheckedExtrinsic {
-				function: Call::Example(pallet::Call::foo_no_post_info()),
+				function: Call::Example(pallet::Call::foo_no_post_info {}),
 				signature: None,
 			},
 		],
@@ -763,15 +766,15 @@ fn inherent_expand() {
 		),
 		vec![
 			UncheckedExtrinsic {
-				function: Call::Example(pallet::Call::foo(1, 1)),
+				function: Call::Example(pallet::Call::foo { foo: 1, bar: 1 }),
 				signature: None,
 			},
 			UncheckedExtrinsic {
-				function: Call::Example(pallet::Call::foo(1, 0)),
+				function: Call::Example(pallet::Call::foo { foo: 1, bar: 0 }),
 				signature: Some((1, (), ())),
 			},
 			UncheckedExtrinsic {
-				function: Call::Example(pallet::Call::foo_no_post_info()),
+				function: Call::Example(pallet::Call::foo_no_post_info {}),
 				signature: None,
 			},
 		],
@@ -786,12 +789,12 @@ fn validate_unsigned_expand() {
 		InvalidTransaction, TransactionSource, TransactionValidityError, ValidTransaction,
 		ValidateUnsigned,
 	};
-	let call = pallet::Call::<Runtime>::foo_no_post_info();
+	let call = pallet::Call::<Runtime>::foo_no_post_info {};
 
 	let validity = pallet::Pallet::validate_unsigned(TransactionSource::Local, &call).unwrap_err();
 	assert_eq!(validity, TransactionValidityError::Invalid(InvalidTransaction::Call));
 
-	let call = pallet::Call::<Runtime>::foo_transactional(0);
+	let call = pallet::Call::<Runtime>::foo_transactional { foo: 0 };
 
 	let validity = pallet::Pallet::validate_unsigned(TransactionSource::External, &call).unwrap();
 	assert_eq!(validity, ValidTransaction::default());
@@ -810,7 +813,9 @@ fn trait_store_expand() {
 fn pallet_expand_deposit_event() {
 	TestExternalities::default().execute_with(|| {
 		frame_system::Pallet::<Runtime>::set_block_number(1);
-		pallet::Call::<Runtime>::foo(3, 0).dispatch_bypass_filter(None.into()).unwrap();
+		pallet::Call::<Runtime>::foo { foo: 3, bar: 0 }
+			.dispatch_bypass_filter(None.into())
+			.unwrap();
 		assert_eq!(
 			frame_system::Pallet::<Runtime>::events()[0].event,
 			Event::Example(pallet::Event::Something(3)),
@@ -818,6 +823,11 @@ fn pallet_expand_deposit_event() {
 	})
 }
 
+#[test]
+fn pallet_new_call_variant() {
+	Call::Example(pallet::Call::new_call_variant_foo(3, 4));
+}
+
 #[test]
 fn storage_expand() {
 	use frame_support::{pallet_prelude::*, storage::StoragePrefixedMap};
@@ -969,288 +979,478 @@ fn migrate_from_pallet_version_to_storage_version() {
 
 #[test]
 fn metadata() {
-	use codec::{Decode, Encode};
-	use frame_metadata::*;
-
-	let expected_pallet_metadata = ModuleMetadata {
-		index: 1,
-		name: DecodeDifferent::Decoded("Example".to_string()),
-		storage: Some(DecodeDifferent::Decoded(StorageMetadata {
-			prefix: DecodeDifferent::Decoded("Example".to_string()),
-			entries: DecodeDifferent::Decoded(vec![
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("ValueWhereClause".to_string()),
-					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::Plain(DecodeDifferent::Decoded(
-						"<T::AccountId as SomeAssociation2>::_2".to_string(),
-					)),
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+	use frame_support::metadata::*;
+
+	let pallets = vec![
+		PalletMetadata {
+			index: 0,
+			name: "System",
+			storage: None,
+			calls: Some(meta_type::<frame_system::Call<Runtime>>().into()),
+			event: Some(meta_type::<frame_system::Event<Runtime>>().into()),
+			constants: vec![
+				PalletConstantMetadata {
+					name: "BlockWeights",
+					ty: meta_type::<frame_system::limits::BlockWeights>(),
+					value: vec![],
+					docs: vec![],
 				},
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("Value".to_string()),
-					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::Plain(DecodeDifferent::Decoded("u32".to_string())),
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+				PalletConstantMetadata {
+					name: "BlockLength",
+					ty: meta_type::<frame_system::limits::BlockLength>(),
+					value: vec![],
+					docs: vec![],
 				},
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("Value2".to_string()),
-					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::Plain(DecodeDifferent::Decoded("u64".to_string())),
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+				PalletConstantMetadata {
+					name: "BlockHashCount",
+					ty: meta_type::<u32>(),
+					value: vec![],
+					docs: vec![],
 				},
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("Map".to_string()),
-					modifier: StorageEntryModifier::Default,
-					ty: StorageEntryType::Map {
-						key: DecodeDifferent::Decoded("u8".to_string()),
-						value: DecodeDifferent::Decoded("u16".to_string()),
-						hasher: StorageHasher::Blake2_128Concat,
-						unused: false,
-					},
-					default: DecodeDifferent::Decoded(vec![4, 0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+				PalletConstantMetadata {
+					name: "DbWeight",
+					ty: meta_type::<frame_support::weights::RuntimeDbWeight>(),
+					value: vec![],
+					docs: vec![],
 				},
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("Map2".to_string()),
-					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::Map {
-						key: DecodeDifferent::Decoded("u16".to_string()),
-						value: DecodeDifferent::Decoded("u32".to_string()),
-						hasher: StorageHasher::Twox64Concat,
-						unused: false,
-					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+				PalletConstantMetadata {
+					name: "Version",
+					ty: meta_type::<sp_version::RuntimeVersion>(),
+					value: vec![],
+					docs: vec![],
 				},
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("DoubleMap".to_string()),
-					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::DoubleMap {
-						value: DecodeDifferent::Decoded("u32".to_string()),
-						key1: DecodeDifferent::Decoded("u8".to_string()),
-						key2: DecodeDifferent::Decoded("u16".to_string()),
-						hasher: StorageHasher::Blake2_128Concat,
-						key2_hasher: StorageHasher::Twox64Concat,
-					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+				PalletConstantMetadata {
+					name: "SS58Prefix",
+					ty: meta_type::<u16>(),
+					value: vec![],
+					docs: vec![],
 				},
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("DoubleMap2".to_string()),
-					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::DoubleMap {
-						value: DecodeDifferent::Decoded("u64".to_string()),
-						key1: DecodeDifferent::Decoded("u16".to_string()),
-						key2: DecodeDifferent::Decoded("u32".to_string()),
-						hasher: StorageHasher::Twox64Concat,
-						key2_hasher: StorageHasher::Blake2_128Concat,
+			],
+			error: Some(meta_type::<frame_system::Error<Runtime>>().into()),
+		},
+		PalletMetadata {
+			index: 1,
+			name: "Example",
+			storage: Some(PalletStorageMetadata {
+				prefix: "Example",
+				entries: vec![
+					StorageEntryMetadata {
+						name: "ValueWhereClause",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Plain(meta_type::<u64>()),
+						default: vec![0],
+						docs: vec![],
 					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
-				},
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("NMap".to_string()),
-					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::NMap {
-						keys: DecodeDifferent::Decoded(vec!["u8".to_string()]),
-						hashers: DecodeDifferent::Decoded(vec![StorageHasher::Blake2_128Concat]),
-						value: DecodeDifferent::Decoded("u32".to_string()),
+					StorageEntryMetadata {
+						name: "Value",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Plain(meta_type::<u32>()),
+						default: vec![0],
+						docs: vec![],
 					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
-				},
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("NMap2".to_string()),
-					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::NMap {
-						keys: DecodeDifferent::Decoded(vec!["u16".to_string(), "u32".to_string()]),
-						hashers: DecodeDifferent::Decoded(vec![
-							StorageHasher::Twox64Concat,
-							StorageHasher::Blake2_128Concat,
-						]),
-						value: DecodeDifferent::Decoded("u64".to_string()),
+					StorageEntryMetadata {
+						name: "Value2",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Plain(meta_type::<u64>()),
+						default: vec![0],
+						docs: vec![],
+					},
+					StorageEntryMetadata {
+						name: "Map",
+						modifier: StorageEntryModifier::Default,
+						ty: StorageEntryType::Map {
+							key: meta_type::<u8>(),
+							value: meta_type::<u16>(),
+							hashers: vec![StorageHasher::Blake2_128Concat],
+						},
+						default: vec![4, 0],
+						docs: vec![],
+					},
+					StorageEntryMetadata {
+						name: "Map2",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							key: meta_type::<u16>(),
+							value: meta_type::<u32>(),
+							hashers: vec![StorageHasher::Twox64Concat],
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					StorageEntryMetadata {
+						name: "DoubleMap",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							value: meta_type::<u32>(),
+							hashers: vec![
+								StorageHasher::Blake2_128Concat,
+								StorageHasher::Twox64Concat,
+							],
+							key: meta_type::<(u8, u16)>(),
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					StorageEntryMetadata {
+						name: "DoubleMap2",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							value: meta_type::<u64>(),
+							key: meta_type::<(u16, u32)>(),
+							hashers: vec![
+								StorageHasher::Twox64Concat,
+								StorageHasher::Blake2_128Concat,
+							],
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					StorageEntryMetadata {
+						name: "NMap",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							key: meta_type::<u8>(),
+							hashers: vec![StorageHasher::Blake2_128Concat],
+							value: meta_type::<u32>(),
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					StorageEntryMetadata {
+						name: "NMap2",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							key: meta_type::<(u16, u32)>(),
+							hashers: vec![
+								StorageHasher::Twox64Concat,
+								StorageHasher::Blake2_128Concat,
+							],
+							value: meta_type::<u64>(),
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					#[cfg(feature = "conditional-storage")]
+					StorageEntryMetadata {
+						name: "ConditionalValue",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Plain(meta_type::<u32>()),
+						default: vec![0],
+						docs: vec![],
 					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+					#[cfg(feature = "conditional-storage")]
+					StorageEntryMetadata {
+						name: "ConditionalMap",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							key: meta_type::<u16>(),
+							value: meta_type::<u32>(),
+							hashers: vec![StorageHasher::Twox64Concat],
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					#[cfg(feature = "conditional-storage")]
+					StorageEntryMetadata {
+						name: "ConditionalDoubleMap",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							value: meta_type::<u32>(),
+							key: meta_type::<(u8, u16)>(),
+							hashers: vec![
+								StorageHasher::Blake2_128Concat,
+								StorageHasher::Twox64Concat,
+							],
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					#[cfg(feature = "conditional-storage")]
+					StorageEntryMetadata {
+						name: "ConditionalNMap",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							key: meta_type::<(u8, u16)>(),
+							hashers: vec![
+								StorageHasher::Blake2_128Concat,
+								StorageHasher::Twox64Concat,
+							],
+							value: meta_type::<u32>(),
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+				],
+			}),
+			calls: Some(meta_type::<pallet::Call<Runtime>>().into()),
+			event: Some(meta_type::<pallet::Event<Runtime>>().into()),
+			constants: vec![
+				PalletConstantMetadata {
+					name: "MyGetParam",
+					ty: meta_type::<u32>(),
+					value: vec![10, 0, 0, 0],
+					docs: vec![" Some comment", " Some comment"],
 				},
-				#[cfg(feature = "conditional-storage")]
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("ConditionalValue".to_string()),
-					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::Plain(DecodeDifferent::Decoded("u32".to_string())),
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+				PalletConstantMetadata {
+					name: "MyGetParam2",
+					ty: meta_type::<u32>(),
+					value: vec![11, 0, 0, 0],
+					docs: vec![" Some comment", " Some comment"],
 				},
-				#[cfg(feature = "conditional-storage")]
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("ConditionalMap".to_string()),
-					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::Map {
-						key: DecodeDifferent::Decoded("u16".to_string()),
-						value: DecodeDifferent::Decoded("u32".to_string()),
-						hasher: StorageHasher::Twox64Concat,
-						unused: false,
-					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+				PalletConstantMetadata {
+					name: "MyGetParam3",
+					ty: meta_type::<u64>(),
+					value: vec![12, 0, 0, 0, 0, 0, 0, 0],
+					docs: vec![],
 				},
-				#[cfg(feature = "conditional-storage")]
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("ConditionalDoubleMap".to_string()),
-					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::DoubleMap {
-						value: DecodeDifferent::Decoded("u32".to_string()),
-						key1: DecodeDifferent::Decoded("u8".to_string()),
-						key2: DecodeDifferent::Decoded("u16".to_string()),
-						hasher: StorageHasher::Blake2_128Concat,
-						key2_hasher: StorageHasher::Twox64Concat,
-					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+				PalletConstantMetadata {
+					name: "some_extra",
+					ty: meta_type::<u64>(),
+					value: vec![100, 0, 0, 0, 0, 0, 0, 0],
+					docs: vec![" Some doc", " Some doc"],
 				},
-				#[cfg(feature = "conditional-storage")]
-				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("ConditionalNMap".to_string()),
-					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::NMap {
-						keys: DecodeDifferent::Decoded(vec!["u8".to_string(), "u16".to_string()]),
-						hashers: DecodeDifferent::Decoded(vec![
-							StorageHasher::Blake2_128Concat,
-							StorageHasher::Twox64Concat,
-						]),
-						value: DecodeDifferent::Decoded("u32".to_string()),
-					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+				PalletConstantMetadata {
+					name: "some_extra_extra",
+					ty: meta_type::<u64>(),
+					value: vec![0, 0, 0, 0, 0, 0, 0, 0],
+					docs: vec![" Some doc"],
 				},
-			]),
-		})),
-		calls: Some(DecodeDifferent::Decoded(vec![
-			FunctionMetadata {
-				name: DecodeDifferent::Decoded("foo".to_string()),
-				arguments: DecodeDifferent::Decoded(vec![
-					FunctionArgumentMetadata {
-						name: DecodeDifferent::Decoded("_foo".to_string()),
-						ty: DecodeDifferent::Decoded("Compact<u32>".to_string()),
+			],
+			error: Some(PalletErrorMetadata { ty: meta_type::<pallet::Error<Runtime>>() }),
+		},
+		PalletMetadata {
+			index: 1,
+			name: "Example",
+			storage: Some(PalletStorageMetadata {
+				prefix: "Example",
+				entries: vec![
+					StorageEntryMetadata {
+						name: "ValueWhereClause",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Plain(meta_type::<u64>()),
+						default: vec![0],
+						docs: vec![],
 					},
-					FunctionArgumentMetadata {
-						name: DecodeDifferent::Decoded("_bar".to_string()),
-						ty: DecodeDifferent::Decoded("u32".to_string()),
+					StorageEntryMetadata {
+						name: "Value",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Plain(meta_type::<u32>()),
+						default: vec![0],
+						docs: vec![],
 					},
-				]),
-				documentation: DecodeDifferent::Decoded(vec![
-					" Doc comment put in metadata".to_string()
-				]),
-			},
-			FunctionMetadata {
-				name: DecodeDifferent::Decoded("foo_transactional".to_string()),
-				arguments: DecodeDifferent::Decoded(vec![FunctionArgumentMetadata {
-					name: DecodeDifferent::Decoded("foo".to_string()),
-					ty: DecodeDifferent::Decoded("Compact<u32>".to_string()),
-				}]),
-				documentation: DecodeDifferent::Decoded(vec![
-					" Doc comment put in metadata".to_string()
-				]),
-			},
-			FunctionMetadata {
-				name: DecodeDifferent::Decoded("foo_no_post_info".to_string()),
-				arguments: DecodeDifferent::Decoded(vec![]),
-				documentation: DecodeDifferent::Decoded(vec![]),
-			},
-		])),
-		event: Some(DecodeDifferent::Decoded(vec![
-			EventMetadata {
-				name: DecodeDifferent::Decoded("Proposed".to_string()),
-				arguments: DecodeDifferent::Decoded(vec![
-					"<T as frame_system::Config>::AccountId".to_string()
-				]),
-				documentation: DecodeDifferent::Decoded(vec![
-					" doc comment put in metadata".to_string()
-				]),
-			},
-			EventMetadata {
-				name: DecodeDifferent::Decoded("Spending".to_string()),
-				arguments: DecodeDifferent::Decoded(vec!["Balance".to_string()]),
-				documentation: DecodeDifferent::Decoded(vec![" doc".to_string()]),
-			},
-			EventMetadata {
-				name: DecodeDifferent::Decoded("Something".to_string()),
-				arguments: DecodeDifferent::Decoded(vec!["Other".to_string()]),
-				documentation: DecodeDifferent::Decoded(vec![]),
-			},
-			EventMetadata {
-				name: DecodeDifferent::Decoded("SomethingElse".to_string()),
-				arguments: DecodeDifferent::Decoded(vec![
-					"<T::AccountId as SomeAssociation1>::_1".to_string()
-				]),
-				documentation: DecodeDifferent::Decoded(vec![]),
-			},
-		])),
-		constants: DecodeDifferent::Decoded(vec![
-			ModuleConstantMetadata {
-				name: DecodeDifferent::Decoded("MyGetParam".to_string()),
-				ty: DecodeDifferent::Decoded("u32".to_string()),
-				value: DecodeDifferent::Decoded(vec![10, 0, 0, 0]),
-				documentation: DecodeDifferent::Decoded(vec![
-					" Some comment".to_string(),
-					" Some comment".to_string(),
-				]),
-			},
-			ModuleConstantMetadata {
-				name: DecodeDifferent::Decoded("MyGetParam2".to_string()),
-				ty: DecodeDifferent::Decoded("u32".to_string()),
-				value: DecodeDifferent::Decoded(vec![11, 0, 0, 0]),
-				documentation: DecodeDifferent::Decoded(vec![
-					" Some comment".to_string(),
-					" Some comment".to_string(),
-				]),
-			},
-			ModuleConstantMetadata {
-				name: DecodeDifferent::Decoded("MyGetParam3".to_string()),
-				ty: DecodeDifferent::Decoded("<T::AccountId as SomeAssociation1>::_1".to_string()),
-				value: DecodeDifferent::Decoded(vec![12, 0, 0, 0, 0, 0, 0, 0]),
-				documentation: DecodeDifferent::Decoded(vec![]),
-			},
-			ModuleConstantMetadata {
-				name: DecodeDifferent::Decoded("some_extra".to_string()),
-				ty: DecodeDifferent::Decoded("T::AccountId".to_string()),
-				value: DecodeDifferent::Decoded(vec![100, 0, 0, 0, 0, 0, 0, 0]),
-				documentation: DecodeDifferent::Decoded(vec![
-					" Some doc".to_string(),
-					" Some doc".to_string(),
-				]),
-			},
-			ModuleConstantMetadata {
-				name: DecodeDifferent::Decoded("some_extra_extra".to_string()),
-				ty: DecodeDifferent::Decoded("T::AccountId".to_string()),
-				value: DecodeDifferent::Decoded(vec![0, 0, 0, 0, 0, 0, 0, 0]),
-				documentation: DecodeDifferent::Decoded(vec![" Some doc".to_string()]),
-			},
-		]),
-		errors: DecodeDifferent::Decoded(vec![ErrorMetadata {
-			name: DecodeDifferent::Decoded("InsufficientProposersBalance".to_string()),
-			documentation: DecodeDifferent::Decoded(vec![
-				" doc comment put into metadata".to_string()
-			]),
-		}]),
+					StorageEntryMetadata {
+						name: "Value2",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Plain(meta_type::<u64>()),
+						default: vec![0],
+						docs: vec![],
+					},
+					StorageEntryMetadata {
+						name: "Map",
+						modifier: StorageEntryModifier::Default,
+						ty: StorageEntryType::Map {
+							key: meta_type::<u8>(),
+							value: meta_type::<u16>(),
+							hashers: vec![StorageHasher::Blake2_128Concat],
+						},
+						default: vec![4, 0],
+						docs: vec![],
+					},
+					StorageEntryMetadata {
+						name: "Map2",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							key: meta_type::<u16>(),
+							value: meta_type::<u32>(),
+							hashers: vec![StorageHasher::Twox64Concat],
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					StorageEntryMetadata {
+						name: "DoubleMap",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							value: meta_type::<u32>(),
+							key: meta_type::<(u8, u16)>(),
+							hashers: vec![
+								StorageHasher::Blake2_128Concat,
+								StorageHasher::Twox64Concat,
+							],
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					StorageEntryMetadata {
+						name: "DoubleMap2",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							value: meta_type::<u64>(),
+							key: meta_type::<(u16, u32)>(),
+							hashers: vec![
+								StorageHasher::Twox64Concat,
+								StorageHasher::Blake2_128Concat,
+							],
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					StorageEntryMetadata {
+						name: "NMap",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							key: meta_type::<u8>(),
+							hashers: vec![StorageHasher::Blake2_128Concat],
+							value: meta_type::<u32>(),
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					StorageEntryMetadata {
+						name: "NMap2",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							key: meta_type::<(u16, u32)>(),
+							hashers: vec![
+								StorageHasher::Twox64Concat,
+								StorageHasher::Blake2_128Concat,
+							],
+							value: meta_type::<u64>(),
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					#[cfg(feature = "conditional-storage")]
+					StorageEntryMetadata {
+						name: "ConditionalValue",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Plain(meta_type::<u32>()),
+						default: vec![0],
+						docs: vec![],
+					},
+					#[cfg(feature = "conditional-storage")]
+					StorageEntryMetadata {
+						name: "ConditionalMap",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							key: meta_type::<u16>(),
+							value: meta_type::<u32>(),
+							hashers: vec![StorageHasher::Twox64Concat],
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					#[cfg(feature = "conditional-storage")]
+					StorageEntryMetadata {
+						name: "ConditionalDoubleMap",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							value: meta_type::<u32>(),
+							key: meta_type::<(u8, u16)>(),
+							hashers: vec![
+								StorageHasher::Blake2_128Concat,
+								StorageHasher::Twox64Concat,
+							],
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+					#[cfg(feature = "conditional-storage")]
+					StorageEntryMetadata {
+						name: "ConditionalNMap",
+						modifier: StorageEntryModifier::Optional,
+						ty: StorageEntryType::Map {
+							key: meta_type::<(u8, u16)>(),
+							hashers: vec![
+								StorageHasher::Blake2_128Concat,
+								StorageHasher::Twox64Concat,
+							],
+							value: meta_type::<u32>(),
+						},
+						default: vec![0],
+						docs: vec![],
+					},
+				],
+			}),
+			calls: Some(meta_type::<pallet::Call<Runtime>>().into()),
+			event: Some(meta_type::<pallet::Event<Runtime>>().into()),
+			constants: vec![
+				PalletConstantMetadata {
+					name: "MyGetParam",
+					ty: meta_type::<u32>(),
+					value: vec![10, 0, 0, 0],
+					docs: vec![" Some comment", " Some comment"],
+				},
+				PalletConstantMetadata {
+					name: "MyGetParam2",
+					ty: meta_type::<u32>(),
+					value: vec![11, 0, 0, 0],
+					docs: vec![" Some comment", " Some comment"],
+				},
+				PalletConstantMetadata {
+					name: "MyGetParam3",
+					ty: meta_type::<u64>(),
+					value: vec![12, 0, 0, 0, 0, 0, 0, 0],
+					docs: vec![],
+				},
+				PalletConstantMetadata {
+					name: "some_extra",
+					ty: meta_type::<u64>(),
+					value: vec![100, 0, 0, 0, 0, 0, 0, 0],
+					docs: vec![" Some doc", " Some doc"],
+				},
+				PalletConstantMetadata {
+					name: "some_extra_extra",
+					ty: meta_type::<u64>(),
+					value: vec![0, 0, 0, 0, 0, 0, 0, 0],
+					docs: vec![" Some doc"],
+				},
+			],
+			error: Some(PalletErrorMetadata { ty: meta_type::<pallet::Error<Runtime>>() }),
+		},
+		PalletMetadata {
+			index: 2,
+			name: "Example2",
+			storage: Some(PalletStorageMetadata {
+				prefix: "Example2",
+				entries: vec![StorageEntryMetadata {
+					name: "SomeValue",
+					modifier: StorageEntryModifier::Optional,
+					ty: StorageEntryType::Plain(meta_type::<Vec<u32>>()),
+					default: vec![0],
+					docs: vec![],
+				}],
+			}),
+			calls: Some(meta_type::<pallet2::Call<Runtime>>().into()),
+			event: Some(PalletEventMetadata { ty: meta_type::<pallet2::Event>() }),
+			constants: vec![],
+			error: None,
+		},
+	];
+
+	let extrinsic = ExtrinsicMetadata {
+		ty: meta_type::<UncheckedExtrinsic>(),
+		version: 4,
+		signed_extensions: vec![SignedExtensionMetadata {
+			identifier: "UnitSignedExtension",
+			ty: meta_type::<()>(),
+			additional_signed: meta_type::<()>(),
+		}],
 	};
 
-	let metadata = match Runtime::metadata().1 {
-		RuntimeMetadata::V13(metadata) => metadata,
-		_ => panic!("metadata has been bump, test needs to be updated"),
+	let expected_metadata: RuntimeMetadataPrefixed =
+		RuntimeMetadataLastVersion::new(pallets, extrinsic, meta_type::<Runtime>()).into();
+	let expected_metadata = match expected_metadata.1 {
+		RuntimeMetadata::V14(metadata) => metadata,
+		_ => panic!("metadata has been bumped, test needs to be updated"),
 	};
 
-	let modules_metadata = match metadata.modules {
-		DecodeDifferent::Encode(modules_metadata) => modules_metadata,
-		_ => unreachable!(),
+	let actual_metadata = match Runtime::metadata().1 {
+		RuntimeMetadata::V14(metadata) => metadata,
+		_ => panic!("metadata has been bumped, test needs to be updated"),
 	};
 
-	let pallet_metadata = ModuleMetadata::decode(&mut &modules_metadata[1].encode()[..]).unwrap();
-
-	pretty_assertions::assert_eq!(pallet_metadata, expected_pallet_metadata);
+	pretty_assertions::assert_eq!(actual_metadata.pallets[1], expected_metadata.pallets[1]);
 }
 
 #[test]
diff --git a/substrate/frame/support/test/tests/pallet_compatibility.rs b/substrate/frame/support/test/tests/pallet_compatibility.rs
index 9814fcb392b508e23b1dc0e909b257d8c86713f1..4523063252ab9331921b177d9bac1dc697c81335 100644
--- a/substrate/frame/support/test/tests/pallet_compatibility.rs
+++ b/substrate/frame/support/test/tests/pallet_compatibility.rs
@@ -99,7 +99,7 @@ mod pallet_old {
 #[frame_support::pallet]
 pub mod pallet {
 	use super::SomeAssociation;
-	use frame_support::pallet_prelude::*;
+	use frame_support::{pallet_prelude::*, scale_info};
 	use frame_system::{ensure_root, pallet_prelude::*};
 
 	#[pallet::config]
@@ -110,7 +110,8 @@ pub mod pallet {
 			+ Into<Weight>
 			+ Default
 			+ MaybeSerializeDeserialize
-			+ SomeAssociation;
+			+ SomeAssociation
+			+ scale_info::StaticTypeInfo;
 		#[pallet::constant]
 		type SomeConst: Get<Self::Balance>;
 		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
@@ -155,7 +156,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(fn deposit_event)]
-	#[pallet::metadata(T::Balance = "Balance")]
 	pub enum Event<T: Config> {
 		/// Dummy event, just here so there's a generic type that's used.
 		Dummy(T::Balance),
@@ -279,22 +279,71 @@ frame_support::construct_runtime!(
 mod test {
 	use super::{pallet, pallet_old, Runtime};
 	use codec::{Decode, Encode};
+	use scale_info::{form::PortableForm, Variant};
 
 	#[test]
 	fn metadata() {
 		let metadata = Runtime::metadata();
-		let modules = match metadata.1 {
-			frame_metadata::RuntimeMetadata::V13(frame_metadata::RuntimeMetadataV13 {
-				modules: frame_metadata::DecodeDifferent::Encode(m),
-				..
-			}) => m,
+		let (pallets, types) = match metadata.1 {
+			frame_support::metadata::RuntimeMetadata::V14(metadata) =>
+				(metadata.pallets, metadata.types),
 			_ => unreachable!(),
 		};
-		pretty_assertions::assert_eq!(modules[1].storage, modules[2].storage);
-		pretty_assertions::assert_eq!(modules[1].calls, modules[2].calls);
-		pretty_assertions::assert_eq!(modules[1].event, modules[2].event);
-		pretty_assertions::assert_eq!(modules[1].constants, modules[2].constants);
-		pretty_assertions::assert_eq!(modules[1].errors, modules[2].errors);
+
+		let assert_meta_types = |ty_id1, ty_id2| {
+			let ty1 = types.resolve(ty_id1).map(|ty| ty.type_def());
+			let ty2 = types.resolve(ty_id2).map(|ty| ty.type_def());
+			pretty_assertions::assert_eq!(ty1, ty2);
+		};
+
+		let get_enum_variants = |ty_id| match types.resolve(ty_id).map(|ty| ty.type_def()) {
+			Some(ty) => match ty {
+				scale_info::TypeDef::Variant(var) => var.variants(),
+				_ => panic!("Expected variant type"),
+			},
+			_ => panic!("No type found"),
+		};
+
+		let assert_enum_variants = |vs1: &[Variant<PortableForm>],
+		                            vs2: &[Variant<PortableForm>]| {
+			assert_eq!(vs1.len(), vs2.len());
+			for i in 0..vs1.len() {
+				let v1 = &vs2[i];
+				let v2 = &vs2[i];
+				assert_eq!(v1.fields().len(), v2.fields().len());
+				for f in 0..v1.fields().len() {
+					let f1 = &v1.fields()[f];
+					let f2 = &v2.fields()[f];
+					pretty_assertions::assert_eq!(f1.name(), f2.name());
+					pretty_assertions::assert_eq!(f1.ty(), f2.ty());
+				}
+			}
+		};
+
+		pretty_assertions::assert_eq!(pallets[1].storage, pallets[2].storage);
+
+		let calls1 = pallets[1].calls.as_ref().unwrap();
+		let calls2 = pallets[2].calls.as_ref().unwrap();
+		assert_meta_types(calls1.ty.id(), calls2.ty.id());
+
+		// event: check variants and fields but ignore the type name which will be different
+		let event1_variants = get_enum_variants(pallets[1].event.as_ref().unwrap().ty.id());
+		let event2_variants = get_enum_variants(pallets[2].event.as_ref().unwrap().ty.id());
+		assert_enum_variants(event1_variants, event2_variants);
+
+		let err1 = get_enum_variants(pallets[1].error.as_ref().unwrap().ty.id())
+			.iter()
+			.filter(|v| v.name() == "__Ignore")
+			.cloned()
+			.collect::<Vec<_>>();
+		let err2 = get_enum_variants(pallets[2].error.as_ref().unwrap().ty.id())
+			.iter()
+			.filter(|v| v.name() == "__Ignore")
+			.cloned()
+			.collect::<Vec<_>>();
+		assert_enum_variants(&err1, &err2);
+
+		pretty_assertions::assert_eq!(pallets[1].constants, pallets[2].constants);
 	}
 
 	#[test]
@@ -309,10 +358,10 @@ mod test {
 
 		assert_eq!(
 			pallet_old::Call::<Runtime>::decode(
-				&mut &pallet::Call::<Runtime>::set_dummy(10).encode()[..]
+				&mut &pallet::Call::<Runtime>::set_dummy { new_value: 10 }.encode()[..]
 			)
 			.unwrap(),
-			pallet_old::Call::<Runtime>::set_dummy(10),
+			pallet_old::Call::<Runtime>::set_dummy { new_value: 10 },
 		);
 	}
 }
diff --git a/substrate/frame/support/test/tests/pallet_compatibility_instance.rs b/substrate/frame/support/test/tests/pallet_compatibility_instance.rs
index b8d43b5e32bfb784480d110472015ca24140311d..768b9f28d35f3440d315cefbff8f12748954b106 100644
--- a/substrate/frame/support/test/tests/pallet_compatibility_instance.rs
+++ b/substrate/frame/support/test/tests/pallet_compatibility_instance.rs
@@ -85,7 +85,7 @@ mod pallet_old {
 
 #[frame_support::pallet]
 pub mod pallet {
-	use frame_support::pallet_prelude::*;
+	use frame_support::{pallet_prelude::*, scale_info};
 	use frame_system::{ensure_root, pallet_prelude::*};
 
 	#[pallet::config]
@@ -95,7 +95,8 @@ pub mod pallet {
 			+ From<u32>
 			+ Into<Weight>
 			+ Default
-			+ MaybeSerializeDeserialize;
+			+ MaybeSerializeDeserialize
+			+ scale_info::StaticTypeInfo;
 		#[pallet::constant]
 		type SomeConst: Get<Self::Balance>;
 		type Event: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::Event>;
@@ -140,7 +141,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(fn deposit_event)]
-	#[pallet::metadata(T::Balance = "Balance")]
 	pub enum Event<T: Config<I>, I: 'static = ()> {
 		/// Dummy event, just here so there's a generic type that's used.
 		Dummy(T::Balance),
@@ -282,23 +282,66 @@ frame_support::construct_runtime!(
 mod test {
 	use super::{pallet, pallet_old, Runtime};
 	use codec::{Decode, Encode};
+	use scale_info::{form::PortableForm, Variant};
 
 	#[test]
 	fn metadata() {
 		let metadata = Runtime::metadata();
-		let modules = match metadata.1 {
-			frame_metadata::RuntimeMetadata::V13(frame_metadata::RuntimeMetadataV13 {
-				modules: frame_metadata::DecodeDifferent::Encode(m),
-				..
-			}) => m,
+		let (pallets, types) = match metadata.1 {
+			frame_support::metadata::RuntimeMetadata::V14(metadata) =>
+				(metadata.pallets, metadata.types),
 			_ => unreachable!(),
 		};
+
+		let get_enum_variants = |ty_id| match types.resolve(ty_id).map(|ty| ty.type_def()) {
+			Some(ty) => match ty {
+				scale_info::TypeDef::Variant(var) => var.variants(),
+				_ => panic!("Expected variant type"),
+			},
+			_ => panic!("No type found"),
+		};
+
+		let assert_enum_variants = |vs1: &[Variant<PortableForm>],
+		                            vs2: &[Variant<PortableForm>]| {
+			assert_eq!(vs1.len(), vs2.len());
+			for i in 0..vs1.len() {
+				let v1 = &vs2[i];
+				let v2 = &vs2[i];
+				assert_eq!(v1.fields().len(), v2.fields().len());
+				for f in 0..v1.fields().len() {
+					let f1 = &v1.fields()[f];
+					let f2 = &v2.fields()[f];
+					pretty_assertions::assert_eq!(f1.name(), f2.name());
+					pretty_assertions::assert_eq!(f1.ty(), f2.ty());
+				}
+			}
+		};
+
 		for i in vec![1, 3, 5].into_iter() {
-			pretty_assertions::assert_eq!(modules[i].storage, modules[i + 1].storage);
-			pretty_assertions::assert_eq!(modules[i].calls, modules[i + 1].calls);
-			pretty_assertions::assert_eq!(modules[i].event, modules[i + 1].event);
-			pretty_assertions::assert_eq!(modules[i].constants, modules[i + 1].constants);
-			pretty_assertions::assert_eq!(modules[i].errors, modules[i + 1].errors);
+			pretty_assertions::assert_eq!(pallets[i].storage, pallets[i + 1].storage);
+
+			let call1_variants = get_enum_variants(pallets[i].calls.as_ref().unwrap().ty.id());
+			let call2_variants = get_enum_variants(pallets[i + 1].calls.as_ref().unwrap().ty.id());
+			assert_enum_variants(call1_variants, call2_variants);
+
+			// event: check variants and fields but ignore the type name which will be different
+			let event1_variants = get_enum_variants(pallets[i].event.as_ref().unwrap().ty.id());
+			let event2_variants = get_enum_variants(pallets[i + 1].event.as_ref().unwrap().ty.id());
+			assert_enum_variants(event1_variants, event2_variants);
+
+			let err1 = get_enum_variants(pallets[i].error.as_ref().unwrap().ty.id())
+				.iter()
+				.filter(|v| v.name() == "__Ignore")
+				.cloned()
+				.collect::<Vec<_>>();
+			let err2 = get_enum_variants(pallets[i + 1].error.as_ref().unwrap().ty.id())
+				.iter()
+				.filter(|v| v.name() == "__Ignore")
+				.cloned()
+				.collect::<Vec<_>>();
+			assert_enum_variants(&err1, &err2);
+
+			pretty_assertions::assert_eq!(pallets[i].constants, pallets[i + 1].constants);
 		}
 	}
 
@@ -314,10 +357,10 @@ mod test {
 
 		assert_eq!(
 			pallet_old::Call::<Runtime>::decode(
-				&mut &pallet::Call::<Runtime>::set_dummy(10).encode()[..]
+				&mut &pallet::Call::<Runtime>::set_dummy { new_value: 10 }.encode()[..]
 			)
 			.unwrap(),
-			pallet_old::Call::<Runtime>::set_dummy(10),
+			pallet_old::Call::<Runtime>::set_dummy { new_value: 10 },
 		);
 	}
 }
diff --git a/substrate/frame/support/test/tests/pallet_instance.rs b/substrate/frame/support/test/tests/pallet_instance.rs
index adfbc7a64f0ede05e85637cafcdab7e96875e47e..34586e841421618031bbb57d7ef04e405374e8fe 100644
--- a/substrate/frame/support/test/tests/pallet_instance.rs
+++ b/substrate/frame/support/test/tests/pallet_instance.rs
@@ -29,7 +29,7 @@ use sp_runtime::DispatchError;
 
 #[frame_support::pallet]
 pub mod pallet {
-	use frame_support::pallet_prelude::*;
+	use frame_support::{pallet_prelude::*, scale_info};
 	use frame_system::pallet_prelude::*;
 	use sp_std::any::TypeId;
 
@@ -39,7 +39,7 @@ pub mod pallet {
 	pub trait Config<I: 'static = ()>: frame_system::Config {
 		#[pallet::constant]
 		type MyGetParam: Get<u32>;
-		type Balance: Parameter + Default;
+		type Balance: Parameter + Default + scale_info::StaticTypeInfo;
 		type Event: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::Event>;
 	}
 
@@ -109,7 +109,6 @@ pub mod pallet {
 	}
 
 	#[pallet::event]
-	#[pallet::metadata(BalanceOf<T, I> = "Balance", u32 = "Other")]
 	#[pallet::generate_deposit(fn deposit_event)]
 	pub enum Event<T: Config<I>, I: 'static = ()> {
 		/// doc comment put in metadata
@@ -157,7 +156,16 @@ pub mod pallet {
 	}
 
 	#[pallet::origin]
-	#[derive(EqNoBound, RuntimeDebugNoBound, CloneNoBound, PartialEqNoBound, Encode, Decode)]
+	#[derive(
+		EqNoBound,
+		RuntimeDebugNoBound,
+		CloneNoBound,
+		PartialEqNoBound,
+		Encode,
+		Decode,
+		scale_info::TypeInfo,
+	)]
+	#[scale_info(skip_type_params(T, I))]
 	pub struct Origin<T, I = ()>(PhantomData<(T, I)>);
 
 	#[pallet::validate_unsigned]
@@ -306,7 +314,7 @@ frame_support::construct_runtime!(
 
 #[test]
 fn call_expand() {
-	let call_foo = pallet::Call::<Runtime>::foo(3);
+	let call_foo = pallet::Call::<Runtime>::foo { foo: 3 };
 	assert_eq!(
 		call_foo.get_dispatch_info(),
 		DispatchInfo { weight: 3, class: DispatchClass::Normal, pays_fee: Pays::Yes }
@@ -314,7 +322,7 @@ fn call_expand() {
 	assert_eq!(call_foo.get_call_name(), "foo");
 	assert_eq!(pallet::Call::<Runtime>::get_call_names(), &["foo", "foo_transactional"]);
 
-	let call_foo = pallet::Call::<Runtime, pallet::Instance1>::foo(3);
+	let call_foo = pallet::Call::<Runtime, pallet::Instance1>::foo { foo: 3 };
 	assert_eq!(
 		call_foo.get_dispatch_info(),
 		DispatchInfo { weight: 3, class: DispatchClass::Normal, pays_fee: Pays::Yes }
@@ -369,7 +377,9 @@ fn instance_expand() {
 fn pallet_expand_deposit_event() {
 	TestExternalities::default().execute_with(|| {
 		frame_system::Pallet::<Runtime>::set_block_number(1);
-		pallet::Call::<Runtime>::foo(3).dispatch_bypass_filter(None.into()).unwrap();
+		pallet::Call::<Runtime>::foo { foo: 3 }
+			.dispatch_bypass_filter(None.into())
+			.unwrap();
 		assert_eq!(
 			frame_system::Pallet::<Runtime>::events()[0].event,
 			Event::Example(pallet::Event::Something(3)),
@@ -378,7 +388,7 @@ fn pallet_expand_deposit_event() {
 
 	TestExternalities::default().execute_with(|| {
 		frame_system::Pallet::<Runtime>::set_block_number(1);
-		pallet::Call::<Runtime, pallet::Instance1>::foo(3)
+		pallet::Call::<Runtime, pallet::Instance1>::foo { foo: 3 }
 			.dispatch_bypass_filter(None.into())
 			.unwrap();
 		assert_eq!(
@@ -544,183 +554,207 @@ fn pallet_on_genesis() {
 
 #[test]
 fn metadata() {
-	use codec::{Decode, Encode};
-	use frame_metadata::*;
+	use frame_support::metadata::*;
+
+	let system_pallet_metadata = PalletMetadata {
+		index: 0,
+		name: "System",
+		storage: None,
+		calls: Some(scale_info::meta_type::<frame_system::Call<Runtime>>().into()),
+		event: Some(PalletEventMetadata {
+			ty: scale_info::meta_type::<frame_system::Event<Runtime>>(),
+		}),
+		constants: vec![
+			PalletConstantMetadata {
+				name: "BlockWeights",
+				ty: scale_info::meta_type::<frame_system::limits::BlockWeights>(),
+				value: vec![],
+				docs: vec![],
+			},
+			PalletConstantMetadata {
+				name: "BlockLength",
+				ty: scale_info::meta_type::<frame_system::limits::BlockLength>(),
+				value: vec![],
+				docs: vec![],
+			},
+			PalletConstantMetadata {
+				name: "BlockHashCount",
+				ty: scale_info::meta_type::<u32>(),
+				value: vec![],
+				docs: vec![],
+			},
+			PalletConstantMetadata {
+				name: "DbWeight",
+				ty: scale_info::meta_type::<frame_support::weights::RuntimeDbWeight>(),
+				value: vec![],
+				docs: vec![],
+			},
+			PalletConstantMetadata {
+				name: "Version",
+				ty: scale_info::meta_type::<sp_version::RuntimeVersion>(),
+				value: vec![],
+				docs: vec![],
+			},
+			PalletConstantMetadata {
+				name: "SS58Prefix",
+				ty: scale_info::meta_type::<u16>(),
+				value: vec![],
+				docs: vec![],
+			},
+		],
+		error: Some(PalletErrorMetadata {
+			ty: scale_info::meta_type::<frame_system::Error<Runtime>>(),
+		}),
+	};
 
-	let expected_pallet_metadata = ModuleMetadata {
+	let example_pallet_metadata = PalletMetadata {
 		index: 1,
-		name: DecodeDifferent::Decoded("Example".to_string()),
-		storage: Some(DecodeDifferent::Decoded(StorageMetadata {
-			prefix: DecodeDifferent::Decoded("Example".to_string()),
-			entries: DecodeDifferent::Decoded(vec![
+		name: "Example",
+		storage: Some(PalletStorageMetadata {
+			prefix: "Example",
+			entries: vec![
 				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("Value".to_string()),
+					name: "Value",
 					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::Plain(DecodeDifferent::Decoded("u32".to_string())),
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+					ty: StorageEntryType::Plain(scale_info::meta_type::<u32>()),
+					default: vec![0],
+					docs: vec![],
 				},
 				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("Map".to_string()),
+					name: "Map",
 					modifier: StorageEntryModifier::Optional,
 					ty: StorageEntryType::Map {
-						key: DecodeDifferent::Decoded("u8".to_string()),
-						value: DecodeDifferent::Decoded("u16".to_string()),
-						hasher: StorageHasher::Blake2_128Concat,
-						unused: false,
+						key: scale_info::meta_type::<u8>(),
+						value: scale_info::meta_type::<u16>(),
+						hashers: vec![StorageHasher::Blake2_128Concat],
 					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+					default: vec![0],
+					docs: vec![],
 				},
 				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("Map2".to_string()),
+					name: "Map2",
 					modifier: StorageEntryModifier::Optional,
 					ty: StorageEntryType::Map {
-						key: DecodeDifferent::Decoded("u16".to_string()),
-						value: DecodeDifferent::Decoded("u32".to_string()),
-						hasher: StorageHasher::Twox64Concat,
-						unused: false,
+						key: scale_info::meta_type::<u16>(),
+						value: scale_info::meta_type::<u32>(),
+						hashers: vec![StorageHasher::Twox64Concat],
 					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+					default: vec![0],
+					docs: vec![],
 				},
 				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("DoubleMap".to_string()),
+					name: "DoubleMap",
 					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::DoubleMap {
-						value: DecodeDifferent::Decoded("u32".to_string()),
-						key1: DecodeDifferent::Decoded("u8".to_string()),
-						key2: DecodeDifferent::Decoded("u16".to_string()),
-						hasher: StorageHasher::Blake2_128Concat,
-						key2_hasher: StorageHasher::Twox64Concat,
+					ty: StorageEntryType::Map {
+						value: scale_info::meta_type::<u32>(),
+						key: scale_info::meta_type::<(u8, u16)>(),
+						hashers: vec![StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat],
 					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+					default: vec![0],
+					docs: vec![],
 				},
 				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("DoubleMap2".to_string()),
+					name: "DoubleMap2",
 					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::DoubleMap {
-						value: DecodeDifferent::Decoded("u64".to_string()),
-						key1: DecodeDifferent::Decoded("u16".to_string()),
-						key2: DecodeDifferent::Decoded("u32".to_string()),
-						hasher: StorageHasher::Twox64Concat,
-						key2_hasher: StorageHasher::Blake2_128Concat,
+					ty: StorageEntryType::Map {
+						value: scale_info::meta_type::<u64>(),
+						key: scale_info::meta_type::<(u16, u32)>(),
+						hashers: vec![StorageHasher::Twox64Concat, StorageHasher::Blake2_128Concat],
 					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+					default: vec![0],
+					docs: vec![],
 				},
 				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("NMap".to_string()),
+					name: "NMap",
 					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::NMap {
-						keys: DecodeDifferent::Decoded(vec!["u8".to_string()]),
-						hashers: DecodeDifferent::Decoded(vec![StorageHasher::Blake2_128Concat]),
-						value: DecodeDifferent::Decoded("u32".to_string()),
+					ty: StorageEntryType::Map {
+						key: scale_info::meta_type::<u8>(),
+						hashers: vec![StorageHasher::Blake2_128Concat],
+						value: scale_info::meta_type::<u32>(),
 					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+					default: vec![0],
+					docs: vec![],
 				},
 				StorageEntryMetadata {
-					name: DecodeDifferent::Decoded("NMap2".to_string()),
+					name: "NMap2",
 					modifier: StorageEntryModifier::Optional,
-					ty: StorageEntryType::NMap {
-						keys: DecodeDifferent::Decoded(vec!["u16".to_string(), "u32".to_string()]),
-						hashers: DecodeDifferent::Decoded(vec![
-							StorageHasher::Twox64Concat,
-							StorageHasher::Blake2_128Concat,
-						]),
-						value: DecodeDifferent::Decoded("u64".to_string()),
+					ty: StorageEntryType::Map {
+						key: scale_info::meta_type::<(u16, u32)>(),
+						hashers: vec![StorageHasher::Twox64Concat, StorageHasher::Blake2_128Concat],
+						value: scale_info::meta_type::<u64>(),
 					},
-					default: DecodeDifferent::Decoded(vec![0]),
-					documentation: DecodeDifferent::Decoded(vec![]),
+					default: vec![0],
+					docs: vec![],
 				},
-			]),
-		})),
-		calls: Some(DecodeDifferent::Decoded(vec![
-			FunctionMetadata {
-				name: DecodeDifferent::Decoded("foo".to_string()),
-				arguments: DecodeDifferent::Decoded(vec![FunctionArgumentMetadata {
-					name: DecodeDifferent::Decoded("_foo".to_string()),
-					ty: DecodeDifferent::Decoded("Compact<u32>".to_string()),
-				}]),
-				documentation: DecodeDifferent::Decoded(vec![
-					" Doc comment put in metadata".to_string()
-				]),
-			},
-			FunctionMetadata {
-				name: DecodeDifferent::Decoded("foo_transactional".to_string()),
-				arguments: DecodeDifferent::Decoded(vec![FunctionArgumentMetadata {
-					name: DecodeDifferent::Decoded("_foo".to_string()),
-					ty: DecodeDifferent::Decoded("Compact<u32>".to_string()),
-				}]),
-				documentation: DecodeDifferent::Decoded(vec![
-					" Doc comment put in metadata".to_string()
-				]),
-			},
-		])),
-		event: Some(DecodeDifferent::Decoded(vec![
-			EventMetadata {
-				name: DecodeDifferent::Decoded("Proposed".to_string()),
-				arguments: DecodeDifferent::Decoded(vec![
-					"<T as frame_system::Config>::AccountId".to_string()
-				]),
-				documentation: DecodeDifferent::Decoded(vec![
-					" doc comment put in metadata".to_string()
-				]),
-			},
-			EventMetadata {
-				name: DecodeDifferent::Decoded("Spending".to_string()),
-				arguments: DecodeDifferent::Decoded(vec!["Balance".to_string()]),
-				documentation: DecodeDifferent::Decoded(vec![" doc".to_string()]),
-			},
-			EventMetadata {
-				name: DecodeDifferent::Decoded("Something".to_string()),
-				arguments: DecodeDifferent::Decoded(vec!["Other".to_string()]),
-				documentation: DecodeDifferent::Decoded(vec![]),
-			},
-		])),
-		constants: DecodeDifferent::Decoded(vec![ModuleConstantMetadata {
-			name: DecodeDifferent::Decoded("MyGetParam".to_string()),
-			ty: DecodeDifferent::Decoded("u32".to_string()),
-			value: DecodeDifferent::Decoded(vec![10, 0, 0, 0]),
-			documentation: DecodeDifferent::Decoded(vec![]),
-		}]),
-		errors: DecodeDifferent::Decoded(vec![ErrorMetadata {
-			name: DecodeDifferent::Decoded("InsufficientProposersBalance".to_string()),
-			documentation: DecodeDifferent::Decoded(vec![
-				" doc comment put into metadata".to_string()
-			]),
-		}]),
+			],
+		}),
+		calls: Some(scale_info::meta_type::<pallet::Call<Runtime>>().into()),
+		event: Some(PalletEventMetadata { ty: scale_info::meta_type::<pallet::Event<Runtime>>() }),
+		constants: vec![PalletConstantMetadata {
+			name: "MyGetParam",
+			ty: scale_info::meta_type::<u32>(),
+			value: vec![10, 0, 0, 0],
+			docs: vec![],
+		}],
+		error: Some(PalletErrorMetadata { ty: scale_info::meta_type::<pallet::Error<Runtime>>() }),
 	};
 
-	let mut expected_pallet_instance1_metadata = expected_pallet_metadata.clone();
-	expected_pallet_instance1_metadata.name =
-		DecodeDifferent::Decoded("Instance1Example".to_string());
-	expected_pallet_instance1_metadata.index = 2;
-	match expected_pallet_instance1_metadata.storage {
-		Some(DecodeDifferent::Decoded(ref mut storage_meta)) => {
-			storage_meta.prefix = DecodeDifferent::Decoded("Instance1Example".to_string());
+	let mut example_pallet_instance1_metadata = example_pallet_metadata.clone();
+	example_pallet_instance1_metadata.name = "Instance1Example";
+	example_pallet_instance1_metadata.index = 2;
+	match example_pallet_instance1_metadata.calls {
+		Some(ref mut calls_meta) => {
+			calls_meta.ty = scale_info::meta_type::<pallet::Call<Runtime, pallet::Instance1>>();
+		},
+		_ => unreachable!(),
+	}
+	match example_pallet_instance1_metadata.event {
+		Some(ref mut event_meta) => {
+			event_meta.ty = scale_info::meta_type::<pallet::Event<Runtime, pallet::Instance1>>();
+		},
+		_ => unreachable!(),
+	}
+	match example_pallet_instance1_metadata.error {
+		Some(ref mut error_meta) => {
+			error_meta.ty = scale_info::meta_type::<pallet::Error<Runtime, pallet::Instance1>>();
+		},
+		_ => unreachable!(),
+	}
+	match example_pallet_instance1_metadata.storage {
+		Some(ref mut storage_meta) => {
+			storage_meta.prefix = "Instance1Example";
 		},
 		_ => unreachable!(),
 	}
 
-	let metadata = match Runtime::metadata().1 {
-		RuntimeMetadata::V13(metadata) => metadata,
-		_ => panic!("metadata has been bump, test needs to be updated"),
+	let pallets =
+		vec![system_pallet_metadata, example_pallet_metadata, example_pallet_instance1_metadata];
+
+	let extrinsic = ExtrinsicMetadata {
+		ty: scale_info::meta_type::<UncheckedExtrinsic>(),
+		version: 4,
+		signed_extensions: vec![SignedExtensionMetadata {
+			identifier: "UnitSignedExtension",
+			ty: scale_info::meta_type::<()>(),
+			additional_signed: scale_info::meta_type::<()>(),
+		}],
 	};
 
-	let modules_metadata = match metadata.modules {
-		DecodeDifferent::Encode(modules_metadata) => modules_metadata,
-		_ => unreachable!(),
+	let expected_metadata: RuntimeMetadataPrefixed =
+		RuntimeMetadataLastVersion::new(pallets, extrinsic, scale_info::meta_type::<Runtime>())
+			.into();
+	let expected_metadata = match expected_metadata.1 {
+		RuntimeMetadata::V14(metadata) => metadata,
+		_ => panic!("metadata has been bumped, test needs to be updated"),
 	};
 
-	let pallet_metadata = ModuleMetadata::decode(&mut &modules_metadata[1].encode()[..]).unwrap();
-	let pallet_instance1_metadata =
-		ModuleMetadata::decode(&mut &modules_metadata[2].encode()[..]).unwrap();
+	let actual_metadata = match Runtime::metadata().1 {
+		RuntimeMetadata::V14(metadata) => metadata,
+		_ => panic!("metadata has been bumped, test needs to be updated"),
+	};
 
-	pretty_assertions::assert_eq!(pallet_metadata, expected_pallet_metadata);
-	pretty_assertions::assert_eq!(pallet_instance1_metadata, expected_pallet_instance1_metadata);
+	pretty_assertions::assert_eq!(actual_metadata.pallets[1], expected_metadata.pallets[1]);
+	pretty_assertions::assert_eq!(actual_metadata.pallets[2], expected_metadata.pallets[2]);
 }
 
 #[test]
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.rs b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.rs
index 0f58187f73ebe443c69397abdab7fdb328dac920..ee9d692eba9b3537430e2dcb83b7660a5c67ca74 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.rs
@@ -5,7 +5,7 @@ mod pallet {
 
 	#[pallet::config]
 	pub trait Config: frame_system::Config {
-		type Bar: codec::Codec;
+		type Bar: codec::Codec + scale_info::TypeInfo;
 	}
 
 	#[pallet::pallet]
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr
index d32d8ada7a11a463bb24abcc8170f6cc5be1bbe0..d1b040c16091fae7eb8c020f8e9c9eb06b9cad91 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr
@@ -1,26 +1,26 @@
 error[E0277]: `<T as pallet::Config>::Bar` doesn't implement `std::fmt::Debug`
-  --> $DIR/call_argument_invalid_bound.rs:20:41
+  --> $DIR/call_argument_invalid_bound.rs:20:36
    |
 20 |         pub fn foo(origin: OriginFor<T>, bar: T::Bar) -> DispatchResultWithPostInfo {
-   |                                               ^ `<T as pallet::Config>::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+   |                                          ^^^ `<T as pallet::Config>::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
    |
    = help: the trait `std::fmt::Debug` is not implemented for `<T as pallet::Config>::Bar`
    = note: required because of the requirements on the impl of `std::fmt::Debug` for `&<T as pallet::Config>::Bar`
    = note: required for the cast to the object type `dyn std::fmt::Debug`
 
 error[E0277]: the trait bound `<T as pallet::Config>::Bar: Clone` is not satisfied
-  --> $DIR/call_argument_invalid_bound.rs:20:41
+  --> $DIR/call_argument_invalid_bound.rs:20:36
    |
 20 |         pub fn foo(origin: OriginFor<T>, bar: T::Bar) -> DispatchResultWithPostInfo {
-   |                                               ^ the trait `Clone` is not implemented for `<T as pallet::Config>::Bar`
+   |                                          ^^^ the trait `Clone` is not implemented for `<T as pallet::Config>::Bar`
    |
    = note: required by `clone`
 
 error[E0369]: binary operation `==` cannot be applied to type `&<T as pallet::Config>::Bar`
-  --> $DIR/call_argument_invalid_bound.rs:20:41
+  --> $DIR/call_argument_invalid_bound.rs:20:36
    |
 20 |         pub fn foo(origin: OriginFor<T>, bar: T::Bar) -> DispatchResultWithPostInfo {
-   |                                               ^
+   |                                          ^^^
    |
 help: consider further restricting this bound
    |
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.rs b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.rs
index da87046822eb70e53a144cd5d130686d99df141c..d981b55c486209ba39f9f00f81dbce54d22d101e 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.rs
@@ -5,7 +5,7 @@ mod pallet {
 
 	#[pallet::config]
 	pub trait Config: frame_system::Config {
-		type Bar;
+		type Bar: scale_info::TypeInfo;
 	}
 
 	#[pallet::pallet]
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr
index 0e1ebbf525257a45f9257ab729cd0e38fd16f434..84d48636729577086e43ce1406cfdb4ba36a54c1 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr
@@ -1,26 +1,26 @@
 error[E0277]: `<T as pallet::Config>::Bar` doesn't implement `std::fmt::Debug`
-  --> $DIR/call_argument_invalid_bound_2.rs:20:41
+  --> $DIR/call_argument_invalid_bound_2.rs:20:36
    |
 20 |         pub fn foo(origin: OriginFor<T>, bar: T::Bar) -> DispatchResultWithPostInfo {
-   |                                               ^ `<T as pallet::Config>::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+   |                                          ^^^ `<T as pallet::Config>::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
    |
    = help: the trait `std::fmt::Debug` is not implemented for `<T as pallet::Config>::Bar`
    = note: required because of the requirements on the impl of `std::fmt::Debug` for `&<T as pallet::Config>::Bar`
    = note: required for the cast to the object type `dyn std::fmt::Debug`
 
 error[E0277]: the trait bound `<T as pallet::Config>::Bar: Clone` is not satisfied
-  --> $DIR/call_argument_invalid_bound_2.rs:20:41
+  --> $DIR/call_argument_invalid_bound_2.rs:20:36
    |
 20 |         pub fn foo(origin: OriginFor<T>, bar: T::Bar) -> DispatchResultWithPostInfo {
-   |                                               ^ the trait `Clone` is not implemented for `<T as pallet::Config>::Bar`
+   |                                          ^^^ the trait `Clone` is not implemented for `<T as pallet::Config>::Bar`
    |
    = note: required by `clone`
 
 error[E0369]: binary operation `==` cannot be applied to type `&<T as pallet::Config>::Bar`
-  --> $DIR/call_argument_invalid_bound_2.rs:20:41
+  --> $DIR/call_argument_invalid_bound_2.rs:20:36
    |
 20 |         pub fn foo(origin: OriginFor<T>, bar: T::Bar) -> DispatchResultWithPostInfo {
-   |                                               ^
+   |                                          ^^^
    |
 help: consider further restricting this bound
    |
@@ -28,23 +28,23 @@ help: consider further restricting this bound
    |                    ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `<T as pallet::Config>::Bar: WrapperTypeEncode` is not satisfied
-   --> $DIR/call_argument_invalid_bound_2.rs:20:41
+   --> $DIR/call_argument_invalid_bound_2.rs:20:36
     |
 20  |         pub fn foo(origin: OriginFor<T>, bar: T::Bar) -> DispatchResultWithPostInfo {
-    |                                               ^ the trait `WrapperTypeEncode` is not implemented for `<T as pallet::Config>::Bar`
+    |                                          ^^^ the trait `WrapperTypeEncode` is not implemented for `<T as pallet::Config>::Bar`
     |
    ::: $CARGO/parity-scale-codec-2.2.0/src/codec.rs
     |
     |     fn encode_to<T: Output + ?Sized>(&self, dest: &mut T) {
     |                     ------ required by this bound in `encode_to`
     |
-    = note: required because of the requirements on the impl of `pallet::_::_parity_scale_codec::Encode` for `<T as pallet::Config>::Bar`
+    = note: required because of the requirements on the impl of `Encode` for `<T as pallet::Config>::Bar`
 
 error[E0277]: the trait bound `<T as pallet::Config>::Bar: WrapperTypeDecode` is not satisfied
-   --> $DIR/call_argument_invalid_bound_2.rs:20:41
+   --> $DIR/call_argument_invalid_bound_2.rs:20:36
     |
 20  |         pub fn foo(origin: OriginFor<T>, bar: T::Bar) -> DispatchResultWithPostInfo {
-    |                                               ^ the trait `WrapperTypeDecode` is not implemented for `<T as pallet::Config>::Bar`
+    |                                          ^^^ the trait `WrapperTypeDecode` is not implemented for `<T as pallet::Config>::Bar`
     |
    ::: $CARGO/parity-scale-codec-2.2.0/src/codec.rs
     |
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.rs b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.rs
index 4a6a781ff44a798b1dfc52713c48ba58f146efe7..e7f99d7ca4f2db482bdfa8912e5f67d835e1183c 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.rs
@@ -13,7 +13,7 @@ mod pallet {
 	#[pallet::hooks]
 	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
 
-	#[derive(Encode, Decode)]
+	#[derive(Encode, Decode, scale_info::TypeInfo)]
 	struct Bar;
 
 	#[pallet::call]
diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr
index b6f4494033f7b89e19d3d9d605a38582ee71bb54..73513907e85f365f17039985cec2494d2e6d6019 100644
--- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr
@@ -1,8 +1,8 @@
 error[E0277]: `Bar` doesn't implement `std::fmt::Debug`
-  --> $DIR/call_argument_invalid_bound_3.rs:22:41
+  --> $DIR/call_argument_invalid_bound_3.rs:22:36
    |
 22 |         pub fn foo(origin: OriginFor<T>, bar: Bar) -> DispatchResultWithPostInfo {
-   |                                               ^^^ `Bar` cannot be formatted using `{:?}`
+   |                                          ^^^ `Bar` cannot be formatted using `{:?}`
    |
    = help: the trait `std::fmt::Debug` is not implemented for `Bar`
    = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
@@ -10,17 +10,17 @@ error[E0277]: `Bar` doesn't implement `std::fmt::Debug`
    = note: required for the cast to the object type `dyn std::fmt::Debug`
 
 error[E0277]: the trait bound `Bar: Clone` is not satisfied
-  --> $DIR/call_argument_invalid_bound_3.rs:22:41
+  --> $DIR/call_argument_invalid_bound_3.rs:22:36
    |
 22 |         pub fn foo(origin: OriginFor<T>, bar: Bar) -> DispatchResultWithPostInfo {
-   |                                               ^^^ the trait `Clone` is not implemented for `Bar`
+   |                                          ^^^ the trait `Clone` is not implemented for `Bar`
    |
    = note: required by `clone`
 
 error[E0369]: binary operation `==` cannot be applied to type `&Bar`
-  --> $DIR/call_argument_invalid_bound_3.rs:22:41
+  --> $DIR/call_argument_invalid_bound_3.rs:22:36
    |
 22 |         pub fn foo(origin: OriginFor<T>, bar: Bar) -> DispatchResultWithPostInfo {
-   |                                               ^^^
+   |                                          ^^^
    |
    = note: an implementation of `std::cmp::PartialEq` might be missing for `&Bar`
diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr
index aff86e333457c55306a10ad30ccf79bcfe5ff51a..e78eb7ff9537b03ad5403ea6711fb584a536a641 100644
--- a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr
@@ -1,3 +1,13 @@
+error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied
+  --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:20:12
+   |
+20 |     #[pallet::storage]
+   |               ^^^^^^^ the trait `TypeInfo` is not implemented for `Bar`
+   |
+   = note: required because of the requirements on the impl of `StaticTypeInfo` for `Bar`
+   = note: required because of the requirements on the impl of `frame_support::storage::StorageEntryMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
+   = note: required by `NAME`
+
 error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
   --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:20:12
    |
@@ -6,8 +16,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
    |
    = note: required because of the requirements on the impl of `Decode` for `Bar`
    = note: required because of the requirements on the impl of `FullCodec` for `Bar`
-   = note: required because of the requirements on the impl of `StorageValueMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
-   = note: required by `frame_support::storage::types::StorageValueMetadata::NAME`
+   = note: required because of the requirements on the impl of `frame_support::storage::StorageEntryMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
+   = note: required by `NAME`
 
 error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
   --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:20:12
@@ -17,8 +27,8 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
    |
    = note: required because of the requirements on the impl of `FullEncode` for `Bar`
    = note: required because of the requirements on the impl of `FullCodec` for `Bar`
-   = note: required because of the requirements on the impl of `StorageValueMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
-   = note: required by `frame_support::storage::types::StorageValueMetadata::NAME`
+   = note: required because of the requirements on the impl of `frame_support::storage::StorageEntryMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
+   = note: required by `NAME`
 
 error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied
   --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:20:12
@@ -26,11 +36,11 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied
 20 |     #[pallet::storage]
    |               ^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar`
    |
-   = note: required because of the requirements on the impl of `pallet::_::_parity_scale_codec::Encode` for `Bar`
+   = note: required because of the requirements on the impl of `Encode` for `Bar`
    = note: required because of the requirements on the impl of `FullEncode` for `Bar`
    = note: required because of the requirements on the impl of `FullCodec` for `Bar`
-   = note: required because of the requirements on the impl of `StorageValueMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
-   = note: required by `frame_support::storage::types::StorageValueMetadata::NAME`
+   = note: required because of the requirements on the impl of `frame_support::storage::StorageEntryMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
+   = note: required by `NAME`
 
 error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
  --> $DIR/storage_ensure_span_are_ok_on_wrong_gen.rs:9:12
@@ -60,7 +70,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied
 9 |     #[pallet::pallet]
   |               ^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar`
   |
-  = note: required because of the requirements on the impl of `pallet::_::_parity_scale_codec::Encode` for `Bar`
+  = note: required because of the requirements on the impl of `Encode` for `Bar`
   = note: required because of the requirements on the impl of `FullEncode` for `Bar`
   = note: required because of the requirements on the impl of `FullCodec` for `Bar`
   = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr
index 2f4876554aa54a2f43f6b822e76687c12c6067e6..d9a7ddbf3443e2dc56c5fa15ab3f504d52b78336 100644
--- a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr
@@ -1,3 +1,13 @@
+error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied
+  --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:20:12
+   |
+20 |     #[pallet::storage]
+   |               ^^^^^^^ the trait `TypeInfo` is not implemented for `Bar`
+   |
+   = note: required because of the requirements on the impl of `StaticTypeInfo` for `Bar`
+   = note: required because of the requirements on the impl of `frame_support::storage::StorageEntryMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
+   = note: required by `NAME`
+
 error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
   --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:20:12
    |
@@ -6,8 +16,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
    |
    = note: required because of the requirements on the impl of `Decode` for `Bar`
    = note: required because of the requirements on the impl of `FullCodec` for `Bar`
-   = note: required because of the requirements on the impl of `StorageValueMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
-   = note: required by `frame_support::storage::types::StorageValueMetadata::NAME`
+   = note: required because of the requirements on the impl of `frame_support::storage::StorageEntryMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
+   = note: required by `NAME`
 
 error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
   --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:20:12
@@ -17,8 +27,8 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
    |
    = note: required because of the requirements on the impl of `FullEncode` for `Bar`
    = note: required because of the requirements on the impl of `FullCodec` for `Bar`
-   = note: required because of the requirements on the impl of `StorageValueMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
-   = note: required by `frame_support::storage::types::StorageValueMetadata::NAME`
+   = note: required because of the requirements on the impl of `frame_support::storage::StorageEntryMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
+   = note: required by `NAME`
 
 error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied
   --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:20:12
@@ -26,11 +36,11 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied
 20 |     #[pallet::storage]
    |               ^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar`
    |
-   = note: required because of the requirements on the impl of `pallet::_::_parity_scale_codec::Encode` for `Bar`
+   = note: required because of the requirements on the impl of `Encode` for `Bar`
    = note: required because of the requirements on the impl of `FullEncode` for `Bar`
    = note: required because of the requirements on the impl of `FullCodec` for `Bar`
-   = note: required because of the requirements on the impl of `StorageValueMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
-   = note: required by `frame_support::storage::types::StorageValueMetadata::NAME`
+   = note: required because of the requirements on the impl of `frame_support::storage::StorageEntryMetadata` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
+   = note: required by `NAME`
 
 error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
  --> $DIR/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:9:12
@@ -60,7 +70,7 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied
 9 |     #[pallet::pallet]
   |               ^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar`
   |
-  = note: required because of the requirements on the impl of `pallet::_::_parity_scale_codec::Encode` for `Bar`
+  = note: required because of the requirements on the impl of `Encode` for `Bar`
   = note: required because of the requirements on the impl of `FullEncode` for `Bar`
   = note: required because of the requirements on the impl of `FullCodec` for `Bar`
   = note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs
index 569e59ef6ec27d1d12606048aca631235e99e4c6..76e356610064019671fd2ea5da329173da56ca31 100644
--- a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.rs
@@ -16,7 +16,7 @@ mod pallet {
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {}
 
-	#[derive(codec::Encode, codec::Decode)]
+	#[derive(codec::Encode, codec::Decode, scale_info::TypeInfo)]
 	struct Bar;
 
 	#[pallet::storage]
diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs
index 3d03099c3c4b69acdbb9273916199a61144b775c..c5d773d7161166ce4f9f9a2780269590531cb29c 100644
--- a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs
+++ b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.rs
@@ -16,7 +16,7 @@ mod pallet {
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {}
 
-	#[derive(codec::Encode, codec::Decode)]
+	#[derive(codec::Encode, codec::Decode, scale_info::TypeInfo)]
 	struct Bar;
 
 	#[pallet::storage]
diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr
index 6c92423c6a7fec9f0296abe7b23c4c8bbfc16712..545520124bfee5a486e8c2e54a361050bfb88858 100644
--- a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr
@@ -4,6 +4,6 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied
 10 |     #[pallet::generate_storage_info]
    |               ^^^^^^^^^^^^^^^^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar`
    |
-   = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `Key<frame_support::Twox64Concat, Bar>`
-   = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo<T>, Key<frame_support::Twox64Concat, Bar>, u32>`
+   = note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `NMapKey<frame_support::Twox64Concat, Bar>`
+   = note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo<T>, NMapKey<frame_support::Twox64Concat, Bar>, u32>`
    = note: required by `storage_info`
diff --git a/substrate/frame/support/test/tests/system.rs b/substrate/frame/support/test/tests/system.rs
index 04193262992641463bafa3869b59770b81673b22..4acc248d25f203d35960971f3da17b22216440da 100644
--- a/substrate/frame/support/test/tests/system.rs
+++ b/substrate/frame/support/test/tests/system.rs
@@ -26,9 +26,9 @@ pub trait Config: 'static + Eq + Clone {
 		+ From<RawOrigin<Self::AccountId>>;
 
 	type BaseCallFilter: frame_support::traits::Contains<Self::Call>;
-	type BlockNumber: Decode + Encode + EncodeLike + Clone + Default;
+	type BlockNumber: Decode + Encode + EncodeLike + Clone + Default + scale_info::TypeInfo;
 	type Hash;
-	type AccountId: Encode + EncodeLike + Decode;
+	type AccountId: Encode + EncodeLike + Decode + scale_info::TypeInfo;
 	type Call;
 	type Event: From<Event<Self>>;
 	type PalletInfo: frame_support::traits::PalletInfo;
@@ -68,7 +68,7 @@ frame_support::decl_error! {
 }
 
 /// Origin for the system module.
-#[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug, Encode, Decode)]
+#[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug, Encode, Decode, scale_info::TypeInfo)]
 pub enum RawOrigin<AccountId> {
 	Root,
 	Signed(AccountId),
diff --git a/substrate/frame/system/Cargo.toml b/substrate/frame/system/Cargo.toml
index d6e34de2a08242c6391027157b387a09338d21be..389730107b43937f3aee0072fa058b6cc85ac972 100644
--- a/substrate/frame/system/Cargo.toml
+++ b/substrate/frame/system/Cargo.toml
@@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 serde = { version = "1.0.126", optional = true, features = ["derive"] }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", path = "../../primitives/io", default-features = false }
@@ -33,6 +34,7 @@ default = ["std"]
 std = [
 	"serde",
 	"codec/std",
+	"scale-info/std",
 	"sp-core/std",
 	"sp-std/std",
 	"sp-io/std",
diff --git a/substrate/frame/system/benchmarking/Cargo.toml b/substrate/frame/system/benchmarking/Cargo.toml
index d7e4e2641d393ee33461696595107336bb5d8a73..29bcccfd7d8309b03531ad2ab6ffc358068eb321 100644
--- a/substrate/frame/system/benchmarking/Cargo.toml
+++ b/substrate/frame/system/benchmarking/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" }
 frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" }
@@ -28,6 +29,7 @@ sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-runtime/std",
 	"sp-std/std",
 	"frame-benchmarking/std",
diff --git a/substrate/frame/system/src/extensions/check_genesis.rs b/substrate/frame/system/src/extensions/check_genesis.rs
index 4f561f17c356408b956159c019e9fa5df25b0e00..6f409d5d3d4adff60e38eb1af0e59aab0445601c 100644
--- a/substrate/frame/system/src/extensions/check_genesis.rs
+++ b/substrate/frame/system/src/extensions/check_genesis.rs
@@ -17,13 +17,15 @@
 
 use crate::{Config, Pallet};
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{SignedExtension, Zero},
 	transaction_validity::TransactionValidityError,
 };
 
 /// Genesis hash check to provide replay protection between different networks.
-#[derive(Encode, Decode, Clone, Eq, PartialEq)]
+#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct CheckGenesis<T: Config + Send + Sync>(sp_std::marker::PhantomData<T>);
 
 impl<T: Config + Send + Sync> sp_std::fmt::Debug for CheckGenesis<T> {
diff --git a/substrate/frame/system/src/extensions/check_mortality.rs b/substrate/frame/system/src/extensions/check_mortality.rs
index 6596939eb9d684c7b1d2f5021bc587b40dd7fe66..69cca765efea96c8af6354c7639269084cf7d8e5 100644
--- a/substrate/frame/system/src/extensions/check_mortality.rs
+++ b/substrate/frame/system/src/extensions/check_mortality.rs
@@ -17,6 +17,7 @@
 
 use crate::{BlockHash, Config, Pallet};
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 use sp_runtime::{
 	generic::Era,
 	traits::{DispatchInfoOf, SaturatedConversion, SignedExtension},
@@ -26,7 +27,8 @@ use sp_runtime::{
 };
 
 /// Check for transaction mortality.
-#[derive(Encode, Decode, Clone, Eq, PartialEq)]
+#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct CheckMortality<T: Config + Send + Sync>(Era, sp_std::marker::PhantomData<T>);
 
 impl<T: Config + Send + Sync> CheckMortality<T> {
diff --git a/substrate/frame/system/src/extensions/check_nonce.rs b/substrate/frame/system/src/extensions/check_nonce.rs
index 6eaa9f9e02a4b308cb3a5eb3a37c91e3fa010ad3..081a0efa3db712c187a5cbb2dee3aca50c06539a 100644
--- a/substrate/frame/system/src/extensions/check_nonce.rs
+++ b/substrate/frame/system/src/extensions/check_nonce.rs
@@ -18,6 +18,7 @@
 use crate::Config;
 use codec::{Decode, Encode};
 use frame_support::weights::DispatchInfo;
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{DispatchInfoOf, Dispatchable, One, SignedExtension},
 	transaction_validity::{
@@ -31,7 +32,8 @@ use sp_std::vec;
 ///
 /// Note that this does not set any priority by default. Make sure that AT LEAST one of the signed
 /// extension sets some kind of priority upon validating transactions.
-#[derive(Encode, Decode, Clone, Eq, PartialEq)]
+#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct CheckNonce<T: Config>(#[codec(compact)] T::Index);
 
 impl<T: Config> CheckNonce<T> {
diff --git a/substrate/frame/system/src/extensions/check_spec_version.rs b/substrate/frame/system/src/extensions/check_spec_version.rs
index 7f5629fefa924c0a8f8146d1e57f8b95e82b1a3f..0217aefae6b9d49d0ca8f382cf5750b411422e83 100644
--- a/substrate/frame/system/src/extensions/check_spec_version.rs
+++ b/substrate/frame/system/src/extensions/check_spec_version.rs
@@ -17,10 +17,12 @@
 
 use crate::{Config, Pallet};
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 use sp_runtime::{traits::SignedExtension, transaction_validity::TransactionValidityError};
 
 /// Ensure the runtime version registered in the transaction is the same as at present.
-#[derive(Encode, Decode, Clone, Eq, PartialEq)]
+#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct CheckSpecVersion<T: Config + Send + Sync>(sp_std::marker::PhantomData<T>);
 
 impl<T: Config + Send + Sync> sp_std::fmt::Debug for CheckSpecVersion<T> {
diff --git a/substrate/frame/system/src/extensions/check_tx_version.rs b/substrate/frame/system/src/extensions/check_tx_version.rs
index badf0292601b67277924d28ca6f1f97f7158e721..9418d3ff5d937b31e890da1f6dd546f67d5930b2 100644
--- a/substrate/frame/system/src/extensions/check_tx_version.rs
+++ b/substrate/frame/system/src/extensions/check_tx_version.rs
@@ -17,10 +17,12 @@
 
 use crate::{Config, Pallet};
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 use sp_runtime::{traits::SignedExtension, transaction_validity::TransactionValidityError};
 
 /// Ensure the transaction version registered in the transaction is the same as at present.
-#[derive(Encode, Decode, Clone, Eq, PartialEq)]
+#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct CheckTxVersion<T: Config + Send + Sync>(sp_std::marker::PhantomData<T>);
 
 impl<T: Config + Send + Sync> sp_std::fmt::Debug for CheckTxVersion<T> {
diff --git a/substrate/frame/system/src/extensions/check_weight.rs b/substrate/frame/system/src/extensions/check_weight.rs
index 1e7ad9454b4c90d99054dc8042b7cbe33b08f5ea..92dc7382fa2d5488edad43702496dc806ceb49d9 100644
--- a/substrate/frame/system/src/extensions/check_weight.rs
+++ b/substrate/frame/system/src/extensions/check_weight.rs
@@ -21,6 +21,7 @@ use frame_support::{
 	traits::Get,
 	weights::{priority::FrameTransactionPriority, DispatchClass, DispatchInfo, PostDispatchInfo},
 };
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension},
 	transaction_validity::{
@@ -31,7 +32,8 @@ use sp_runtime::{
 };
 
 /// Block resource (weight) limit check.
-#[derive(Encode, Decode, Clone, Eq, PartialEq, Default)]
+#[derive(Encode, Decode, Clone, Eq, PartialEq, Default, TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct CheckWeight<T: Config + Send + Sync>(sp_std::marker::PhantomData<T>);
 
 impl<T: Config + Send + Sync> CheckWeight<T>
diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs
index 3d89e09a25a7ed01e9fd21920d91cbf75e5183e4..2e7f26eef16f45f27d55c50ab23d8e19164eb5ff 100644
--- a/substrate/frame/system/src/lib.rs
+++ b/substrate/frame/system/src/lib.rs
@@ -94,6 +94,7 @@ use frame_support::{
 	},
 	Parameter,
 };
+use scale_info::TypeInfo;
 use sp_core::{storage::well_known_keys, ChangesTrieConfiguration};
 
 #[cfg(feature = "std")]
@@ -204,7 +205,8 @@ pub mod pallet {
 			+ sp_std::hash::Hash
 			+ sp_std::str::FromStr
 			+ MaybeMallocSizeOf
-			+ MaxEncodedLen;
+			+ MaxEncodedLen
+			+ TypeInfo;
 
 		/// The output of the `Hashing` function.
 		type Hash: Parameter
@@ -224,7 +226,7 @@ pub mod pallet {
 			+ MaxEncodedLen;
 
 		/// The hashing system (algorithm) being used in the runtime (e.g. Blake2).
-		type Hashing: Hash<Output = Self::Hash>;
+		type Hashing: Hash<Output = Self::Hash> + TypeInfo;
 
 		/// The user account identifier type for the runtime.
 		type AccountId: Parameter
@@ -276,7 +278,7 @@ pub mod pallet {
 
 		/// Data to be associated with an account (other than nonce/transaction counter, which this
 		/// pallet does regardless).
-		type AccountData: Member + FullCodec + Clone + Default;
+		type AccountData: Member + FullCodec + Clone + Default + TypeInfo;
 
 		/// Handler for when a new account has just been created.
 		type OnNewAccount: OnNewAccount<Self::AccountId>;
@@ -522,7 +524,6 @@ pub mod pallet {
 
 	/// Event for the System pallet.
 	#[pallet::event]
-	#[pallet::metadata(T::AccountId = "AccountId", T::Hash = "Hash")]
 	pub enum Event<T: Config> {
 		/// An extrinsic completed successfully. \[info\]
 		ExtrinsicSuccess(DispatchInfo),
@@ -763,7 +764,7 @@ pub type Key = Vec<u8>;
 pub type KeyValue = (Vec<u8>, Vec<u8>);
 
 /// A phase of a block's execution.
-#[derive(Encode, Decode, RuntimeDebug)]
+#[derive(Encode, Decode, RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone))]
 pub enum Phase {
 	/// Applying an extrinsic.
@@ -781,7 +782,7 @@ impl Default for Phase {
 }
 
 /// Record of an event happening.
-#[derive(Encode, Decode, RuntimeDebug)]
+#[derive(Encode, Decode, RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone))]
 pub struct EventRecord<E: Parameter + Member, T> {
 	/// The phase of the block it happened in.
@@ -793,7 +794,7 @@ pub struct EventRecord<E: Parameter + Member, T> {
 }
 
 /// Origin for the System pallet.
-#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode)]
+#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo)]
 pub enum RawOrigin<AccountId> {
 	/// The system itself ordained this dispatch to happen: this is the highest privilege level.
 	Root,
@@ -833,7 +834,7 @@ type EventIndex = u32;
 pub type RefCount = u32;
 
 /// Information of an account.
-#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)]
+#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
 pub struct AccountInfo<Index, AccountData> {
 	/// The number of transactions this account has sent.
 	pub nonce: Index,
@@ -853,7 +854,7 @@ pub struct AccountInfo<Index, AccountData> {
 
 /// Stores the `spec_version` and `spec_name` of when the last runtime upgrade
 /// happened.
-#[derive(sp_runtime::RuntimeDebug, Encode, Decode)]
+#[derive(sp_runtime::RuntimeDebug, Encode, Decode, TypeInfo)]
 #[cfg_attr(feature = "std", derive(PartialEq))]
 pub struct LastRuntimeUpgradeInfo {
 	pub spec_version: codec::Compact<u32>,
diff --git a/substrate/frame/system/src/limits.rs b/substrate/frame/system/src/limits.rs
index 74ffc828314b883a7f113f9dda0b9fe46d781622..687fb6f3dd3673e61984e0f08ff9dd8e19ce6bb7 100644
--- a/substrate/frame/system/src/limits.rs
+++ b/substrate/frame/system/src/limits.rs
@@ -26,10 +26,11 @@
 //! which should be passed to `frame_system` configuration when runtime is being set up.
 
 use frame_support::weights::{constants, DispatchClass, OneOrMany, PerDispatchClass, Weight};
+use scale_info::TypeInfo;
 use sp_runtime::{Perbill, RuntimeDebug};
 
 /// Block length limit configuration.
-#[derive(RuntimeDebug, Clone, codec::Encode, codec::Decode)]
+#[derive(RuntimeDebug, Clone, codec::Encode, codec::Decode, TypeInfo)]
 pub struct BlockLength {
 	/// Maximal total length in bytes for each extrinsic class.
 	///
@@ -91,7 +92,7 @@ pub type ValidationResult = Result<BlockWeights, ValidationErrors>;
 const DEFAULT_NORMAL_RATIO: Perbill = Perbill::from_percent(75);
 
 /// `DispatchClass`-specific weight configuration.
-#[derive(RuntimeDebug, Clone, codec::Encode, codec::Decode)]
+#[derive(RuntimeDebug, Clone, codec::Encode, codec::Decode, TypeInfo)]
 pub struct WeightsPerClass {
 	/// Base weight of single extrinsic of given class.
 	pub base_extrinsic: Weight,
@@ -191,7 +192,7 @@ pub struct WeightsPerClass {
 ///
 /// As a consequence of `reserved` space, total consumed block weight might exceed `max_block`
 /// value, so this parameter should rather be thought of as "target block weight" than a hard limit.
-#[derive(RuntimeDebug, Clone, codec::Encode, codec::Decode)]
+#[derive(RuntimeDebug, Clone, codec::Encode, codec::Decode, TypeInfo)]
 pub struct BlockWeights {
 	/// Base weight of block execution.
 	pub base_block: Weight,
diff --git a/substrate/frame/system/src/mock.rs b/substrate/frame/system/src/mock.rs
index 8039b73445ae665438ddc65e264f40755fa709fb..9dd35691cab84eb9d61f3d378cff74362e649402 100644
--- a/substrate/frame/system/src/mock.rs
+++ b/substrate/frame/system/src/mock.rs
@@ -116,7 +116,8 @@ impl Config for Test {
 pub type SysEvent = frame_system::Event<Test>;
 
 /// A simple call, which one doesn't matter.
-pub const CALL: &<Test as Config>::Call = &Call::System(frame_system::Call::set_heap_pages(0u64));
+pub const CALL: &<Test as Config>::Call =
+	&Call::System(frame_system::Call::set_heap_pages { pages: 0u64 });
 
 /// Create new externalities for `System` module tests.
 pub fn new_test_ext() -> sp_io::TestExternalities {
diff --git a/substrate/frame/system/src/offchain.rs b/substrate/frame/system/src/offchain.rs
index e9f3d82ea3c289e4b49883650a86af69b530670b..ed758a2556b7787d1b55c8bb21e455ebf7047d8b 100644
--- a/substrate/frame/system/src/offchain.rs
+++ b/substrate/frame/system/src/offchain.rs
@@ -453,10 +453,11 @@ pub trait SigningTypes: crate::Config {
 		+ IdentifyAccount<AccountId = Self::AccountId>
 		+ core::fmt::Debug
 		+ codec::Codec
-		+ Ord;
+		+ Ord
+		+ scale_info::TypeInfo;
 
 	/// A matching `Signature` type.
-	type Signature: Clone + PartialEq + core::fmt::Debug + codec::Codec;
+	type Signature: Clone + PartialEq + core::fmt::Debug + codec::Codec + scale_info::TypeInfo;
 }
 
 /// A definition of types required to submit transactions from within the runtime.
diff --git a/substrate/frame/timestamp/Cargo.toml b/substrate/frame/timestamp/Cargo.toml
index cdf31b1e7ae2d1924f9e5a94c784d956a86a94fc..1c95c4782b5c46865fd06307bf604ff1ce0ae6b3 100644
--- a/substrate/frame/timestamp/Cargo.toml
+++ b/substrate/frame/timestamp/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io", optional = true }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
@@ -35,6 +36,7 @@ default = ["std"]
 std = [
 	"sp-inherents/std",
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-runtime/std",
 	"frame-benchmarking/std",
diff --git a/substrate/frame/timestamp/src/lib.rs b/substrate/frame/timestamp/src/lib.rs
index a1ff8d37ff8812ae97b5707df1dd3d2969d0f2a2..153606bedbacfa5408fe67f91db06fe21d69a96b 100644
--- a/substrate/frame/timestamp/src/lib.rs
+++ b/substrate/frame/timestamp/src/lib.rs
@@ -120,7 +120,8 @@ pub mod pallet {
 			+ AtLeast32Bit
 			+ Scale<Self::BlockNumber, Output = Self::Moment>
 			+ Copy
-			+ MaxEncodedLen;
+			+ MaxEncodedLen
+			+ scale_info::StaticTypeInfo;
 
 		/// Something which can be notified when the timestamp is set. Set this to `()` if not
 		/// needed.
@@ -221,7 +222,7 @@ pub mod pallet {
 			let data = (*inherent_data).saturated_into::<T::Moment>();
 
 			let next_time = cmp::max(data, Self::now() + T::MinimumPeriod::get());
-			Some(Call::set(next_time.into()))
+			Some(Call::set { now: next_time.into() })
 		}
 
 		fn check_inherent(
@@ -232,7 +233,7 @@ pub mod pallet {
 				sp_timestamp::Timestamp::new(30 * 1000);
 
 			let t: u64 = match call {
-				Call::set(ref t) => t.clone().saturated_into::<u64>(),
+				Call::set { ref now } => now.clone().saturated_into::<u64>(),
 				_ => return Ok(()),
 			};
 
@@ -252,7 +253,7 @@ pub mod pallet {
 		}
 
 		fn is_inherent(call: &Self::Call) -> bool {
-			matches!(call, Call::set(_))
+			matches!(call, Call::set { .. })
 		}
 	}
 }
diff --git a/substrate/frame/tips/Cargo.toml b/substrate/frame/tips/Cargo.toml
index d706552393e6e3984bdcd06692636042ca31fc10..8ca395e1c5416fd7c3756bfcbc92eab13358379c 100644
--- a/substrate/frame/tips/Cargo.toml
+++ b/substrate/frame/tips/Cargo.toml
@@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
 log = { version = "0.4.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 serde = { version = "1.0.126", features = ["derive"], optional = true }
 
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
@@ -37,6 +38,7 @@ default = ["std"]
 std = [
 	"codec/std",
 	"log/std",
+	"scale-info/std",
 	"serde",
 
 	"sp-core/std",
diff --git a/substrate/frame/tips/src/lib.rs b/substrate/frame/tips/src/lib.rs
index 50abe4684cdedd50ad287c35d2c2245796a03941..f4a4edb7b399954c92d2fd78717e130ae4e8e46a 100644
--- a/substrate/frame/tips/src/lib.rs
+++ b/substrate/frame/tips/src/lib.rs
@@ -83,7 +83,7 @@ pub type NegativeImbalanceOf<T> = pallet_treasury::NegativeImbalanceOf<T>;
 
 /// An open tipping "motion". Retains all details of a tip including information on the finder
 /// and the members who have voted.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)]
 pub struct OpenTip<
 	AccountId: Parameter,
 	Balance: Parameter,
@@ -177,7 +177,6 @@ pub mod pallet {
 	pub type Reasons<T: Config> = StorageMap<_, Identity, T::Hash, Vec<u8>, OptionQuery>;
 
 	#[pallet::event]
-	#[pallet::metadata(T::Hash = "Hash", T::AccountId = "AccountId", BalanceOf<T> = "Balance")]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
 		/// A new tip suggestion has been opened. \[tip_hash\]
diff --git a/substrate/frame/transaction-payment/Cargo.toml b/substrate/frame/transaction-payment/Cargo.toml
index 0bcc422bb8476baaec606665ca7914ac0dd801da..546939692bbafa499f7579a82fe7c30d836cc148 100644
--- a/substrate/frame/transaction-payment/Cargo.toml
+++ b/substrate/frame/transaction-payment/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 serde = { version = "1.0.126", optional = true }
 smallvec = "1.4.1"
 
@@ -36,6 +37,7 @@ default = ["std"]
 std = [
 	"serde",
 	"codec/std",
+	"scale-info/std",
 	"sp-core/std",
 	"sp-io/std",
 	"sp-runtime/std",
diff --git a/substrate/frame/transaction-payment/src/lib.rs b/substrate/frame/transaction-payment/src/lib.rs
index 9e8dbf6cb5d1d763784438e5e887b39eab568499..e3a3bccc3d39a98590ef193444fb176a2783112e 100644
--- a/substrate/frame/transaction-payment/src/lib.rs
+++ b/substrate/frame/transaction-payment/src/lib.rs
@@ -48,6 +48,7 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 
 use sp_runtime::{
 	traits::{
@@ -225,7 +226,7 @@ where
 }
 
 /// Storage releases of the pallet.
-#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 enum Releases {
 	/// Original version of the pallet.
 	V1Ancient,
@@ -522,7 +523,8 @@ where
 
 /// Require the transactor pay for themselves and maybe include a tip to gain additional priority
 /// in the queue.
-#[derive(Encode, Decode, Clone, Eq, PartialEq)]
+#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
+#[scale_info(skip_type_params(T))]
 pub struct ChargeTransactionPayment<T: Config>(#[codec(compact)] BalanceOf<T>);
 
 impl<T: Config> ChargeTransactionPayment<T>
@@ -714,7 +716,7 @@ mod tests {
 	);
 
 	const CALL: &<Runtime as frame_system::Config>::Call =
-		&Call::Balances(BalancesCall::transfer(2, 69));
+		&Call::Balances(BalancesCall::transfer { dest: 2, value: 69 });
 
 	thread_local! {
 		static EXTRINSIC_BASE_WEIGHT: RefCell<u64> = RefCell::new(0);
@@ -1054,7 +1056,7 @@ mod tests {
 
 	#[test]
 	fn query_info_works() {
-		let call = Call::Balances(BalancesCall::transfer(2, 69));
+		let call = Call::Balances(BalancesCall::transfer { dest: 2, value: 69 });
 		let origin = 111111;
 		let extra = ();
 		let xt = TestXt::new(call, Some((origin, extra)));
diff --git a/substrate/frame/transaction-payment/src/payment.rs b/substrate/frame/transaction-payment/src/payment.rs
index 832e4d5359a1c612990bdd1ddd7fb7d2326d68e6..58e6ef63109a3b05442c0628321779eaea4c4dde 100644
--- a/substrate/frame/transaction-payment/src/payment.rs
+++ b/substrate/frame/transaction-payment/src/payment.rs
@@ -27,7 +27,8 @@ pub trait OnChargeTransaction<T: Config> {
 		+ Copy
 		+ MaybeSerializeDeserialize
 		+ Debug
-		+ Default;
+		+ Default
+		+ scale_info::TypeInfo;
 	type LiquidityInfo: Default;
 
 	/// Before the transaction is executed the payment of the transaction fees
diff --git a/substrate/frame/transaction-storage/Cargo.toml b/substrate/frame/transaction-storage/Cargo.toml
index 74f31ffed4b37d72d140940bd9e8552135b9dde9..a4ebd5cfbc87615fc219e8754a05c2ca94f63127 100644
--- a/substrate/frame/transaction-storage/Cargo.toml
+++ b/substrate/frame/transaction-storage/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 serde = { version = "1.0.126", optional = true }
 hex-literal = { version = "0.3.1", optional = true }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
 pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" }
@@ -36,6 +37,7 @@ runtime-benchmarks = ["frame-benchmarking", "hex-literal"]
 std = [
 	"serde",
 	"codec/std",
+	"scale-info/std",
 	"sp-runtime/std",
 	"frame-support/std",
 	"frame-system/std",
diff --git a/substrate/frame/transaction-storage/src/lib.rs b/substrate/frame/transaction-storage/src/lib.rs
index 1b751f3b214cdc4698377c29b4caca41593a5abd..2fe3c04e0229f4ba03bc40d65c34c54afc5e76e4 100644
--- a/substrate/frame/transaction-storage/src/lib.rs
+++ b/substrate/frame/transaction-storage/src/lib.rs
@@ -57,7 +57,7 @@ pub const DEFAULT_MAX_TRANSACTION_SIZE: u32 = 8 * 1024 * 1024;
 pub const DEFAULT_MAX_BLOCK_TRANSACTIONS: u32 = 512;
 
 /// State data for a stored transaction.
-#[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq, Eq)]
+#[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq, Eq, scale_info::TypeInfo)]
 pub struct TransactionInfo {
 	/// Chunk trie root.
 	chunk_root: <BlakeTwo256 as Hash>::Output,
@@ -408,7 +408,7 @@ pub mod pallet {
 			let proof = data
 				.get_data::<TransactionStorageProof>(&Self::INHERENT_IDENTIFIER)
 				.unwrap_or(None);
-			proof.map(Call::check_proof)
+			proof.map(|proof| Call::check_proof { proof })
 		}
 
 		fn check_inherent(
@@ -419,7 +419,7 @@ pub mod pallet {
 		}
 
 		fn is_inherent(call: &Self::Call) -> bool {
-			matches!(call, Call::check_proof(_))
+			matches!(call, Call::check_proof { .. })
 		}
 	}
 
diff --git a/substrate/frame/treasury/Cargo.toml b/substrate/frame/treasury/Cargo.toml
index c670cc1e439fc9e0230834eae1af49aa7ce9ad30..b2991f3febcada6a3a80f42b82141d071c5ac2c3 100644
--- a/substrate/frame/treasury/Cargo.toml
+++ b/substrate/frame/treasury/Cargo.toml
@@ -17,6 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features =
 	"derive",
 	"max-encoded-len",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 serde = { version = "1.0.126", features = ["derive"], optional = true }
 impl-trait-for-tuples = "0.2.1"
 
@@ -37,6 +38,7 @@ sp-core = { version = "4.0.0-dev", path = "../../primitives/core" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"serde",
 	"sp-std/std",
 	"sp-runtime/std",
diff --git a/substrate/frame/treasury/src/lib.rs b/substrate/frame/treasury/src/lib.rs
index 965f06731c9456c330669e56decbdf0f22d92d85..646baa99b99b05b0674d5d1c61e3aaa43540b241 100644
--- a/substrate/frame/treasury/src/lib.rs
+++ b/substrate/frame/treasury/src/lib.rs
@@ -63,6 +63,7 @@ mod tests;
 pub mod weights;
 
 use codec::{Decode, Encode, MaxEncodedLen};
+use scale_info::TypeInfo;
 
 use sp_runtime::{
 	traits::{AccountIdConversion, Saturating, StaticLookup, Zero},
@@ -118,7 +119,7 @@ pub type ProposalIndex = u32;
 
 /// A spending proposal.
 #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
-#[derive(Encode, Decode, Clone, PartialEq, Eq, MaxEncodedLen, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, PartialEq, Eq, MaxEncodedLen, RuntimeDebug, TypeInfo)]
 pub struct Proposal<AccountId, Balance> {
 	/// The account proposing it.
 	proposer: AccountId,
@@ -253,7 +254,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(T::AccountId = "AccountId", BalanceOf<T, I> = "Balance")]
 	pub enum Event<T: Config<I>, I: 'static = ()> {
 		/// New proposal. \[proposal_index\]
 		Proposed(ProposalIndex),
diff --git a/substrate/frame/uniques/Cargo.toml b/substrate/frame/uniques/Cargo.toml
index 32a283fc36d25dd9eecb7e6d77fef9b24bf9be7e..4f664ecc2b6a94c0f51b50630d29b181e449c33c 100644
--- a/substrate/frame/uniques/Cargo.toml
+++ b/substrate/frame/uniques/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
@@ -30,6 +31,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-runtime/std",
 	"frame-support/std",
diff --git a/substrate/frame/uniques/src/benchmarking.rs b/substrate/frame/uniques/src/benchmarking.rs
index 20ddbb15d53609c3e1fb75910681a28887e21fff..5c777dc961e9e61bc0cf925f87f3d7a4cabe5899 100644
--- a/substrate/frame/uniques/src/benchmarking.rs
+++ b/substrate/frame/uniques/src/benchmarking.rs
@@ -286,15 +286,15 @@ benchmarks_instance_pallet! {
 	force_asset_status {
 		let (class, caller, caller_lookup) = create_class::<T, I>();
 		let origin = T::ForceOrigin::successful_origin();
-		let call = Call::<T, I>::force_asset_status(
+		let call = Call::<T, I>::force_asset_status {
 			class,
-			caller_lookup.clone(),
-			caller_lookup.clone(),
-			caller_lookup.clone(),
-			caller_lookup.clone(),
-			true,
-			false,
-		);
+			owner: caller_lookup.clone(),
+			issuer: caller_lookup.clone(),
+			admin: caller_lookup.clone(),
+			freezer: caller_lookup.clone(),
+			free_holding: true,
+			is_frozen: false,
+		};
 	}: { call.dispatch_bypass_filter(origin)? }
 	verify {
 		assert_last_event::<T, I>(Event::AssetStatusChanged(class).into());
diff --git a/substrate/frame/uniques/src/lib.rs b/substrate/frame/uniques/src/lib.rs
index b4a0b9821683a8ea6d125896a668df35e694b252..8c716694051b528eba4fe74d2560ee70c7f700b6 100644
--- a/substrate/frame/uniques/src/lib.rs
+++ b/substrate/frame/uniques/src/lib.rs
@@ -190,11 +190,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(
-		T::AccountId = "AccountId",
-		T::ClassId = "ClassId",
-		T::InstanceId = "InstanceId"
-	)]
 	pub enum Event<T: Config<I>, I: 'static = ()> {
 		/// An asset class was created. \[ class, creator, owner \]
 		Created(T::ClassId, T::AccountId, T::AccountId),
diff --git a/substrate/frame/uniques/src/types.rs b/substrate/frame/uniques/src/types.rs
index ae61b6b5e1fd3d628de875f0cd6ce88b0babc4a7..1e4405aa09c84ddacb315df78e56928bf59671ad 100644
--- a/substrate/frame/uniques/src/types.rs
+++ b/substrate/frame/uniques/src/types.rs
@@ -19,6 +19,7 @@
 
 use super::*;
 use frame_support::{traits::Get, BoundedVec};
+use scale_info::TypeInfo;
 
 pub(super) type DepositBalanceOf<T, I = ()> =
 	<<T as Config<I>>::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance;
@@ -27,7 +28,7 @@ pub(super) type ClassDetailsFor<T, I> =
 pub(super) type InstanceDetailsFor<T, I> =
 	InstanceDetails<<T as SystemConfig>::AccountId, DepositBalanceOf<T, I>>;
 
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)]
+#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct ClassDetails<AccountId, DepositBalance> {
 	/// Can change `owner`, `issuer`, `freezer` and `admin` accounts.
 	pub(super) owner: AccountId,
@@ -53,7 +54,7 @@ pub struct ClassDetails<AccountId, DepositBalance> {
 }
 
 /// Witness data for the destroy transactions.
-#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)]
+#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct DestroyWitness {
 	/// The total number of outstanding instances of this asset class.
 	#[codec(compact)]
@@ -77,7 +78,7 @@ impl<AccountId, DepositBalance> ClassDetails<AccountId, DepositBalance> {
 }
 
 /// Information concerning the ownership of a single unique asset.
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default)]
+#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo)]
 pub struct InstanceDetails<AccountId, DepositBalance> {
 	/// The owner of this asset.
 	pub(super) owner: AccountId,
@@ -90,7 +91,8 @@ pub struct InstanceDetails<AccountId, DepositBalance> {
 	pub(super) deposit: DepositBalance,
 }
 
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default)]
+#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo)]
+#[scale_info(skip_type_params(StringLimit))]
 pub struct ClassMetadata<DepositBalance, StringLimit: Get<u32>> {
 	/// The balance deposited for this metadata.
 	///
@@ -104,7 +106,8 @@ pub struct ClassMetadata<DepositBalance, StringLimit: Get<u32>> {
 	pub(super) is_frozen: bool,
 }
 
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default)]
+#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo)]
+#[scale_info(skip_type_params(StringLimit))]
 pub struct InstanceMetadata<DepositBalance, StringLimit: Get<u32>> {
 	/// The balance deposited for this metadata.
 	///
diff --git a/substrate/frame/utility/Cargo.toml b/substrate/frame/utility/Cargo.toml
index d3e2933faf9a9c1ec93c1479b231eecddb2b6f7e..b5b8eab9cdbf35e7e83ba7ca6c44c96bd665719e 100644
--- a/substrate/frame/utility/Cargo.toml
+++ b/substrate/frame/utility/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
@@ -31,6 +32,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-runtime/std",
 	"frame-support/std",
 	"frame-system/std",
diff --git a/substrate/frame/utility/src/benchmarking.rs b/substrate/frame/utility/src/benchmarking.rs
index 9fd0184b8fa3de8ef81a00e9db9269bd73d01146..210a6156499cf18317180df9eb528ece19c7fc97 100644
--- a/substrate/frame/utility/src/benchmarking.rs
+++ b/substrate/frame/utility/src/benchmarking.rs
@@ -34,7 +34,7 @@ benchmarks! {
 		let c in 0 .. 1000;
 		let mut calls: Vec<<T as Config>::Call> = Vec::new();
 		for i in 0 .. c {
-			let call = frame_system::Call::remark(vec![]).into();
+			let call = frame_system::Call::remark { remark: vec![] }.into();
 			calls.push(call);
 		}
 		let caller = whitelisted_caller();
@@ -45,7 +45,7 @@ benchmarks! {
 
 	as_derivative {
 		let caller = account("caller", SEED, SEED);
-		let call = Box::new(frame_system::Call::remark(vec![]).into());
+		let call = Box::new(frame_system::Call::remark { remark: vec![] }.into());
 		// Whitelist caller account from further DB operations.
 		let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
 		frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
@@ -55,7 +55,7 @@ benchmarks! {
 		let c in 0 .. 1000;
 		let mut calls: Vec<<T as Config>::Call> = Vec::new();
 		for i in 0 .. c {
-			let call = frame_system::Call::remark(vec![]).into();
+			let call = frame_system::Call::remark { remark: vec![] }.into();
 			calls.push(call);
 		}
 		let caller = whitelisted_caller();
diff --git a/substrate/frame/utility/src/lib.rs b/substrate/frame/utility/src/lib.rs
index 2e34502494c7da790c7cdecdddb7465007a2d0fb..54de87c4740c85ce511d206ae8a9f9f69c75e951 100644
--- a/substrate/frame/utility/src/lib.rs
+++ b/substrate/frame/utility/src/lib.rs
@@ -304,7 +304,7 @@ pub mod pallet {
 					// Don't allow users to nest `batch_all` calls.
 					filtered_origin.add_filter(move |c: &<T as frame_system::Config>::Call| {
 						let c = <T as Config>::Call::from_ref(c);
-						!matches!(c.is_sub_type(), Some(Call::batch_all(_)))
+						!matches!(c.is_sub_type(), Some(Call::batch_all { .. }))
 					});
 					call.dispatch(filtered_origin)
 				};
diff --git a/substrate/frame/utility/src/tests.rs b/substrate/frame/utility/src/tests.rs
index 0a780550f3556e60e21d21e9b41e7aa754e73505..bbfbb417e23d1ff53435939951e231e9a6479eb2 100644
--- a/substrate/frame/utility/src/tests.rs
+++ b/substrate/frame/utility/src/tests.rs
@@ -155,10 +155,10 @@ impl Contains<Call> for TestBaseCallFilter {
 	fn contains(c: &Call) -> bool {
 		match *c {
 			// Transfer works. Use `transfer_keep_alive` for a call that doesn't pass the filter.
-			Call::Balances(pallet_balances::Call::transfer(..)) => true,
+			Call::Balances(pallet_balances::Call::transfer { .. }) => true,
 			Call::Utility(_) => true,
 			// For benchmarking, this acts as a noop call
-			Call::System(frame_system::Call::remark(..)) => true,
+			Call::System(frame_system::Call::remark { .. }) => true,
 			// For tests
 			Call::Example(_) => true,
 			_ => false,
@@ -189,24 +189,24 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
 	ext
 }
 
+fn call_transfer(dest: u64, value: u64) -> Call {
+	Call::Balances(BalancesCall::transfer { dest, value })
+}
+
+fn call_foobar(err: bool, start_weight: u64, end_weight: Option<u64>) -> Call {
+	Call::Example(ExampleCall::foobar { err, start_weight, end_weight })
+}
+
 #[test]
 fn as_derivative_works() {
 	new_test_ext().execute_with(|| {
 		let sub_1_0 = Utility::derivative_account_id(1, 0);
 		assert_ok!(Balances::transfer(Origin::signed(1), sub_1_0, 5));
 		assert_err_ignore_postinfo!(
-			Utility::as_derivative(
-				Origin::signed(1),
-				1,
-				Box::new(Call::Balances(BalancesCall::transfer(6, 3))),
-			),
+			Utility::as_derivative(Origin::signed(1), 1, Box::new(call_transfer(6, 3)),),
 			BalancesError::<Test, _>::InsufficientBalance
 		);
-		assert_ok!(Utility::as_derivative(
-			Origin::signed(1),
-			0,
-			Box::new(Call::Balances(BalancesCall::transfer(2, 3))),
-		));
+		assert_ok!(Utility::as_derivative(Origin::signed(1), 0, Box::new(call_transfer(2, 3)),));
 		assert_eq!(Balances::free_balance(sub_1_0), 2);
 		assert_eq!(Balances::free_balance(2), 13);
 	});
@@ -220,16 +220,18 @@ fn as_derivative_handles_weight_refund() {
 		let diff = start_weight - end_weight;
 
 		// Full weight when ok
-		let inner_call = Call::Example(ExampleCall::foobar(false, start_weight, None));
-		let call = Call::Utility(UtilityCall::as_derivative(0, Box::new(inner_call)));
+		let inner_call = call_foobar(false, start_weight, None);
+		let call =
+			Call::Utility(UtilityCall::as_derivative { index: 0, call: Box::new(inner_call) });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_ok!(result);
 		assert_eq!(extract_actual_weight(&result, &info), info.weight);
 
 		// Refund weight when ok
-		let inner_call = Call::Example(ExampleCall::foobar(false, start_weight, Some(end_weight)));
-		let call = Call::Utility(UtilityCall::as_derivative(0, Box::new(inner_call)));
+		let inner_call = call_foobar(false, start_weight, Some(end_weight));
+		let call =
+			Call::Utility(UtilityCall::as_derivative { index: 0, call: Box::new(inner_call) });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_ok!(result);
@@ -237,8 +239,9 @@ fn as_derivative_handles_weight_refund() {
 		assert_eq!(extract_actual_weight(&result, &info), info.weight - diff);
 
 		// Full weight when err
-		let inner_call = Call::Example(ExampleCall::foobar(true, start_weight, None));
-		let call = Call::Utility(UtilityCall::as_derivative(0, Box::new(inner_call)));
+		let inner_call = call_foobar(true, start_weight, None);
+		let call =
+			Call::Utility(UtilityCall::as_derivative { index: 0, call: Box::new(inner_call) });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_noop!(
@@ -254,8 +257,9 @@ fn as_derivative_handles_weight_refund() {
 		);
 
 		// Refund weight when err
-		let inner_call = Call::Example(ExampleCall::foobar(true, start_weight, Some(end_weight)));
-		let call = Call::Utility(UtilityCall::as_derivative(0, Box::new(inner_call)));
+		let inner_call = call_foobar(true, start_weight, Some(end_weight));
+		let call =
+			Call::Utility(UtilityCall::as_derivative { index: 0, call: Box::new(inner_call) });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_noop!(
@@ -279,7 +283,10 @@ fn as_derivative_filters() {
 			Utility::as_derivative(
 				Origin::signed(1),
 				1,
-				Box::new(Call::Balances(pallet_balances::Call::transfer_keep_alive(2, 1))),
+				Box::new(Call::Balances(pallet_balances::Call::transfer_keep_alive {
+					dest: 2,
+					value: 1
+				})),
 			),
 			DispatchError::BadOrigin
 		);
@@ -290,15 +297,16 @@ fn as_derivative_filters() {
 fn batch_with_root_works() {
 	new_test_ext().execute_with(|| {
 		let k = b"a".to_vec();
-		let call = Call::System(frame_system::Call::set_storage(vec![(k.clone(), k.clone())]));
+		let call =
+			Call::System(frame_system::Call::set_storage { items: vec![(k.clone(), k.clone())] });
 		assert!(!TestBaseCallFilter::contains(&call));
 		assert_eq!(Balances::free_balance(1), 10);
 		assert_eq!(Balances::free_balance(2), 10);
 		assert_ok!(Utility::batch(
 			Origin::root(),
 			vec![
-				Call::Balances(BalancesCall::force_transfer(1, 2, 5)),
-				Call::Balances(BalancesCall::force_transfer(1, 2, 5)),
+				Call::Balances(BalancesCall::force_transfer { source: 1, dest: 2, value: 5 }),
+				Call::Balances(BalancesCall::force_transfer { source: 1, dest: 2, value: 5 }),
 				call, // Check filters are correctly bypassed
 			]
 		));
@@ -315,10 +323,7 @@ fn batch_with_signed_works() {
 		assert_eq!(Balances::free_balance(2), 10);
 		assert_ok!(Utility::batch(
 			Origin::signed(1),
-			vec![
-				Call::Balances(BalancesCall::transfer(2, 5)),
-				Call::Balances(BalancesCall::transfer(2, 5))
-			]
+			vec![call_transfer(2, 5), call_transfer(2, 5)]
 		),);
 		assert_eq!(Balances::free_balance(1), 0);
 		assert_eq!(Balances::free_balance(2), 20);
@@ -330,7 +335,7 @@ fn batch_with_signed_filters() {
 	new_test_ext().execute_with(|| {
 		assert_ok!(Utility::batch(
 			Origin::signed(1),
-			vec![Call::Balances(pallet_balances::Call::transfer_keep_alive(2, 1))]
+			vec![Call::Balances(pallet_balances::Call::transfer_keep_alive { dest: 2, value: 1 })]
 		),);
 		System::assert_last_event(
 			utility::Event::BatchInterrupted(0, DispatchError::BadOrigin).into(),
@@ -345,11 +350,7 @@ fn batch_early_exit_works() {
 		assert_eq!(Balances::free_balance(2), 10);
 		assert_ok!(Utility::batch(
 			Origin::signed(1),
-			vec![
-				Call::Balances(BalancesCall::transfer(2, 5)),
-				Call::Balances(BalancesCall::transfer(2, 10)),
-				Call::Balances(BalancesCall::transfer(2, 5)),
-			]
+			vec![call_transfer(2, 5), call_transfer(2, 10), call_transfer(2, 5),]
 		),);
 		assert_eq!(Balances::free_balance(1), 5);
 		assert_eq!(Balances::free_balance(2), 15);
@@ -360,15 +361,13 @@ fn batch_early_exit_works() {
 fn batch_weight_calculation_doesnt_overflow() {
 	use sp_runtime::Perbill;
 	new_test_ext().execute_with(|| {
-		let big_call = Call::System(SystemCall::fill_block(Perbill::from_percent(50)));
+		let big_call = Call::System(SystemCall::fill_block { ratio: Perbill::from_percent(50) });
 		assert_eq!(big_call.get_dispatch_info().weight, Weight::max_value() / 2);
 
 		// 3 * 50% saturates to 100%
-		let batch_call = Call::Utility(crate::Call::batch(vec![
-			big_call.clone(),
-			big_call.clone(),
-			big_call.clone(),
-		]));
+		let batch_call = Call::Utility(crate::Call::batch {
+			calls: vec![big_call.clone(), big_call.clone(), big_call.clone()],
+		});
 
 		assert_eq!(batch_call.get_dispatch_info().weight, Weight::max_value());
 	});
@@ -383,18 +382,18 @@ fn batch_handles_weight_refund() {
 		let batch_len: Weight = 4;
 
 		// Full weight when ok
-		let inner_call = Call::Example(ExampleCall::foobar(false, start_weight, None));
+		let inner_call = call_foobar(false, start_weight, None);
 		let batch_calls = vec![inner_call; batch_len as usize];
-		let call = Call::Utility(UtilityCall::batch(batch_calls));
+		let call = Call::Utility(UtilityCall::batch { calls: batch_calls });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_ok!(result);
 		assert_eq!(extract_actual_weight(&result, &info), info.weight);
 
 		// Refund weight when ok
-		let inner_call = Call::Example(ExampleCall::foobar(false, start_weight, Some(end_weight)));
+		let inner_call = call_foobar(false, start_weight, Some(end_weight));
 		let batch_calls = vec![inner_call; batch_len as usize];
-		let call = Call::Utility(UtilityCall::batch(batch_calls));
+		let call = Call::Utility(UtilityCall::batch { calls: batch_calls });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_ok!(result);
@@ -402,10 +401,10 @@ fn batch_handles_weight_refund() {
 		assert_eq!(extract_actual_weight(&result, &info), info.weight - diff * batch_len);
 
 		// Full weight when err
-		let good_call = Call::Example(ExampleCall::foobar(false, start_weight, None));
-		let bad_call = Call::Example(ExampleCall::foobar(true, start_weight, None));
+		let good_call = call_foobar(false, start_weight, None);
+		let bad_call = call_foobar(true, start_weight, None);
 		let batch_calls = vec![good_call, bad_call];
-		let call = Call::Utility(UtilityCall::batch(batch_calls));
+		let call = Call::Utility(UtilityCall::batch { calls: batch_calls });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_ok!(result);
@@ -416,11 +415,11 @@ fn batch_handles_weight_refund() {
 		assert_eq!(extract_actual_weight(&result, &info), info.weight);
 
 		// Refund weight when err
-		let good_call = Call::Example(ExampleCall::foobar(false, start_weight, Some(end_weight)));
-		let bad_call = Call::Example(ExampleCall::foobar(true, start_weight, Some(end_weight)));
+		let good_call = call_foobar(false, start_weight, Some(end_weight));
+		let bad_call = call_foobar(true, start_weight, Some(end_weight));
 		let batch_calls = vec![good_call, bad_call];
 		let batch_len = batch_calls.len() as Weight;
-		let call = Call::Utility(UtilityCall::batch(batch_calls));
+		let call = Call::Utility(UtilityCall::batch { calls: batch_calls });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_ok!(result);
@@ -430,10 +429,10 @@ fn batch_handles_weight_refund() {
 		assert_eq!(extract_actual_weight(&result, &info), info.weight - diff * batch_len);
 
 		// Partial batch completion
-		let good_call = Call::Example(ExampleCall::foobar(false, start_weight, Some(end_weight)));
-		let bad_call = Call::Example(ExampleCall::foobar(true, start_weight, Some(end_weight)));
+		let good_call = call_foobar(false, start_weight, Some(end_weight));
+		let bad_call = call_foobar(true, start_weight, Some(end_weight));
 		let batch_calls = vec![good_call, bad_call.clone(), bad_call];
-		let call = Call::Utility(UtilityCall::batch(batch_calls));
+		let call = Call::Utility(UtilityCall::batch { calls: batch_calls });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_ok!(result);
@@ -455,10 +454,7 @@ fn batch_all_works() {
 		assert_eq!(Balances::free_balance(2), 10);
 		assert_ok!(Utility::batch_all(
 			Origin::signed(1),
-			vec![
-				Call::Balances(BalancesCall::transfer(2, 5)),
-				Call::Balances(BalancesCall::transfer(2, 5))
-			]
+			vec![call_transfer(2, 5), call_transfer(2, 5)]
 		),);
 		assert_eq!(Balances::free_balance(1), 0);
 		assert_eq!(Balances::free_balance(2), 20);
@@ -468,7 +464,7 @@ fn batch_all_works() {
 #[test]
 fn batch_all_revert() {
 	new_test_ext().execute_with(|| {
-		let call = Call::Balances(BalancesCall::transfer(2, 5));
+		let call = call_transfer(2, 5);
 		let info = call.get_dispatch_info();
 
 		assert_eq!(Balances::free_balance(1), 10);
@@ -476,11 +472,7 @@ fn batch_all_revert() {
 		assert_noop!(
 			Utility::batch_all(
 				Origin::signed(1),
-				vec![
-					Call::Balances(BalancesCall::transfer(2, 5)),
-					Call::Balances(BalancesCall::transfer(2, 10)),
-					Call::Balances(BalancesCall::transfer(2, 5)),
-				]
+				vec![call_transfer(2, 5), call_transfer(2, 10), call_transfer(2, 5),]
 			),
 			DispatchErrorWithPostInfo {
 				post_info: PostDispatchInfo {
@@ -506,18 +498,18 @@ fn batch_all_handles_weight_refund() {
 		let batch_len: Weight = 4;
 
 		// Full weight when ok
-		let inner_call = Call::Example(ExampleCall::foobar(false, start_weight, None));
+		let inner_call = call_foobar(false, start_weight, None);
 		let batch_calls = vec![inner_call; batch_len as usize];
-		let call = Call::Utility(UtilityCall::batch_all(batch_calls));
+		let call = Call::Utility(UtilityCall::batch_all { calls: batch_calls });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_ok!(result);
 		assert_eq!(extract_actual_weight(&result, &info), info.weight);
 
 		// Refund weight when ok
-		let inner_call = Call::Example(ExampleCall::foobar(false, start_weight, Some(end_weight)));
+		let inner_call = call_foobar(false, start_weight, Some(end_weight));
 		let batch_calls = vec![inner_call; batch_len as usize];
-		let call = Call::Utility(UtilityCall::batch_all(batch_calls));
+		let call = Call::Utility(UtilityCall::batch_all { calls: batch_calls });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_ok!(result);
@@ -525,10 +517,10 @@ fn batch_all_handles_weight_refund() {
 		assert_eq!(extract_actual_weight(&result, &info), info.weight - diff * batch_len);
 
 		// Full weight when err
-		let good_call = Call::Example(ExampleCall::foobar(false, start_weight, None));
-		let bad_call = Call::Example(ExampleCall::foobar(true, start_weight, None));
+		let good_call = call_foobar(false, start_weight, None);
+		let bad_call = call_foobar(true, start_weight, None);
 		let batch_calls = vec![good_call, bad_call];
-		let call = Call::Utility(UtilityCall::batch_all(batch_calls));
+		let call = Call::Utility(UtilityCall::batch_all { calls: batch_calls });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_err_ignore_postinfo!(result, "The cake is a lie.");
@@ -536,21 +528,21 @@ fn batch_all_handles_weight_refund() {
 		assert_eq!(extract_actual_weight(&result, &info), info.weight);
 
 		// Refund weight when err
-		let good_call = Call::Example(ExampleCall::foobar(false, start_weight, Some(end_weight)));
-		let bad_call = Call::Example(ExampleCall::foobar(true, start_weight, Some(end_weight)));
+		let good_call = call_foobar(false, start_weight, Some(end_weight));
+		let bad_call = call_foobar(true, start_weight, Some(end_weight));
 		let batch_calls = vec![good_call, bad_call];
 		let batch_len = batch_calls.len() as Weight;
-		let call = Call::Utility(UtilityCall::batch_all(batch_calls));
+		let call = Call::Utility(UtilityCall::batch_all { calls: batch_calls });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_err_ignore_postinfo!(result, "The cake is a lie.");
 		assert_eq!(extract_actual_weight(&result, &info), info.weight - diff * batch_len);
 
 		// Partial batch completion
-		let good_call = Call::Example(ExampleCall::foobar(false, start_weight, Some(end_weight)));
-		let bad_call = Call::Example(ExampleCall::foobar(true, start_weight, Some(end_weight)));
+		let good_call = call_foobar(false, start_weight, Some(end_weight));
+		let bad_call = call_foobar(true, start_weight, Some(end_weight));
 		let batch_calls = vec![good_call, bad_call.clone(), bad_call];
-		let call = Call::Utility(UtilityCall::batch_all(batch_calls));
+		let call = Call::Utility(UtilityCall::batch_all { calls: batch_calls });
 		let info = call.get_dispatch_info();
 		let result = call.dispatch(Origin::signed(1));
 		assert_err_ignore_postinfo!(result, "The cake is a lie.");
@@ -565,11 +557,9 @@ fn batch_all_handles_weight_refund() {
 #[test]
 fn batch_all_does_not_nest() {
 	new_test_ext().execute_with(|| {
-		let batch_all = Call::Utility(UtilityCall::batch_all(vec![
-			Call::Balances(BalancesCall::transfer(2, 1)),
-			Call::Balances(BalancesCall::transfer(2, 1)),
-			Call::Balances(BalancesCall::transfer(2, 1)),
-		]));
+		let batch_all = Call::Utility(UtilityCall::batch_all {
+			calls: vec![call_transfer(2, 1), call_transfer(2, 1), call_transfer(2, 1)],
+		});
 
 		let info = batch_all.get_dispatch_info();
 
@@ -590,7 +580,7 @@ fn batch_all_does_not_nest() {
 		// And for those who want to get a little fancy, we check that the filter persists across
 		// other kinds of dispatch wrapping functions... in this case
 		// `batch_all(batch(batch_all(..)))`
-		let batch_nested = Call::Utility(UtilityCall::batch(vec![batch_all]));
+		let batch_nested = Call::Utility(UtilityCall::batch { calls: vec![batch_all] });
 		// Batch will end with `Ok`, but does not actually execute as we can see from the event
 		// and balances.
 		assert_ok!(Utility::batch_all(Origin::signed(1), vec![batch_nested]));
@@ -605,7 +595,7 @@ fn batch_all_does_not_nest() {
 #[test]
 fn batch_limit() {
 	new_test_ext().execute_with(|| {
-		let calls = vec![Call::System(SystemCall::remark(vec![])); 40_000];
+		let calls = vec![Call::System(SystemCall::remark { remark: vec![] }); 40_000];
 		assert_noop!(Utility::batch(Origin::signed(1), calls.clone()), Error::<Test>::TooManyCalls);
 		assert_noop!(Utility::batch_all(Origin::signed(1), calls), Error::<Test>::TooManyCalls);
 	});
diff --git a/substrate/frame/vesting/Cargo.toml b/substrate/frame/vesting/Cargo.toml
index 96af259959c3ee76c3e36a7eb95c0c7c0482f0c0..806e0e6036862dbf4794f1993d33df3b947e5eeb 100644
--- a/substrate/frame/vesting/Cargo.toml
+++ b/substrate/frame/vesting/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
 frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
@@ -32,6 +33,7 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-runtime/std",
 	"frame-support/std",
diff --git a/substrate/frame/vesting/src/lib.rs b/substrate/frame/vesting/src/lib.rs
index 7e4a11fbd5c361a3670c7ee062ca406e46b290fd..27862a5ca4b72c7b680b960afafa166382517281 100644
--- a/substrate/frame/vesting/src/lib.rs
+++ b/substrate/frame/vesting/src/lib.rs
@@ -65,6 +65,7 @@ use frame_support::{
 };
 use frame_system::{ensure_root, ensure_signed, pallet_prelude::*};
 pub use pallet::*;
+use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{
 		AtLeast32BitUnsigned, Bounded, Convert, MaybeSerializeDeserialize, One, Saturating,
@@ -85,7 +86,7 @@ const VESTING_ID: LockIdentifier = *b"vesting ";
 
 // A value placed in storage that represents the current version of the Vesting storage.
 // This value is used by `on_runtime_upgrade` to determine whether we run storage migration logic.
-#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, MaxEncodedLen)]
+#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 enum Releases {
 	V0,
 	V1,
@@ -271,9 +272,6 @@ pub mod pallet {
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
-	#[pallet::metadata(
-		T::AccountId = "AccountId", BalanceOf<T> = "Balance", T::BlockNumber = "BlockNumber"
-	)]
 	pub enum Event<T: Config> {
 		/// The amount vested has been updated. This could indicate a change in funds available.
 		/// The balance given is the amount which is left unvested (and thus locked).
diff --git a/substrate/frame/vesting/src/vesting_info.rs b/substrate/frame/vesting/src/vesting_info.rs
index 72171910086cda547eeb8bc63f143aa853aa276b..81bffa199fd724617343dc47d949a7c9032b07dc 100644
--- a/substrate/frame/vesting/src/vesting_info.rs
+++ b/substrate/frame/vesting/src/vesting_info.rs
@@ -20,7 +20,7 @@
 use super::*;
 
 /// Struct to encode the vesting schedule of an individual account.
-#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen)]
+#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 pub struct VestingInfo<Balance, BlockNumber> {
 	/// Locked amount at genesis.
 	locked: Balance,
diff --git a/substrate/primitives/application-crypto/Cargo.toml b/substrate/primitives/application-crypto/Cargo.toml
index dd9d7f22d242fe1e521d55f3e85fd3155f615170..6849dc25f85612a652c86f08ad8f97291d2fd8d7 100644
--- a/substrate/primitives/application-crypto/Cargo.toml
+++ b/substrate/primitives/application-crypto/Cargo.toml
@@ -17,6 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 serde = { version = "1.0.126", optional = true, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 sp-io = { version = "4.0.0-dev", default-features = false, path = "../io" }
@@ -27,6 +28,7 @@ std = [
 	"full_crypto",
 	"sp-core/std",
 	"codec/std",
+	"scale-info/std",
 	"serde",
 	"sp-std/std",
 	"sp-io/std",
diff --git a/substrate/primitives/application-crypto/src/lib.rs b/substrate/primitives/application-crypto/src/lib.rs
index 43a14e29f4ee505736f1dc9a5b8e3eadbafba856..baa65606670596fc60593c6cf4eab6ce32c920c5 100644
--- a/substrate/primitives/application-crypto/src/lib.rs
+++ b/substrate/primitives/application-crypto/src/lib.rs
@@ -34,6 +34,8 @@ pub use sp_core::{
 #[doc(hidden)]
 pub use codec;
 #[doc(hidden)]
+pub use scale_info;
+#[doc(hidden)]
 #[cfg(feature = "std")]
 pub use serde;
 #[doc(hidden)]
@@ -224,6 +226,7 @@ macro_rules! app_crypto_public_full_crypto {
 				$crate::codec::Decode,
 				$crate::RuntimeDebug,
 				$crate::codec::MaxEncodedLen,
+				$crate::scale_info::TypeInfo,
 			)]
 			#[codec(crate = $crate::codec)]
 			pub struct Public($public);
@@ -260,6 +263,7 @@ macro_rules! app_crypto_public_not_full_crypto {
 				$crate::codec::Decode,
 				$crate::RuntimeDebug,
 				$crate::codec::MaxEncodedLen,
+				$crate::scale_info::TypeInfo,
 			)]
 			pub struct Public($public);
 		}
@@ -435,6 +439,7 @@ macro_rules! app_crypto_signature_full_crypto {
 				$crate::codec::Encode,
 				$crate::codec::Decode,
 				$crate::RuntimeDebug,
+				$crate::scale_info::TypeInfo,
 			)]
 			#[derive(Hash)]
 			pub struct Signature($sig);
@@ -468,6 +473,7 @@ macro_rules! app_crypto_signature_not_full_crypto {
 			#[derive(Clone, Default, Eq, PartialEq,
 				$crate::codec::Encode,
 				$crate::codec::Decode,
+				$crate::scale_info::TypeInfo,
 				$crate::RuntimeDebug,
 			)]
 			pub struct Signature($sig);
diff --git a/substrate/primitives/application-crypto/src/traits.rs b/substrate/primitives/application-crypto/src/traits.rs
index 2f7fd139c018742c666310bd35143200adafc5c8..376d12f0c7a3eb394f64c1f76e58b62f1e58ca78 100644
--- a/substrate/primitives/application-crypto/src/traits.rs
+++ b/substrate/primitives/application-crypto/src/traits.rs
@@ -130,7 +130,7 @@ pub trait RuntimeAppPublic: Sized {
 	const CRYPTO_ID: CryptoTypeId;
 
 	/// The signature that will be generated when signing with the corresponding private key.
-	type Signature: Codec + Debug + MaybeHash + Eq + PartialEq + Clone;
+	type Signature: Codec + Debug + MaybeHash + Eq + PartialEq + Clone + scale_info::TypeInfo;
 
 	/// Returns all public keys for this application in the keystore.
 	fn all() -> crate::Vec<Self>;
diff --git a/substrate/primitives/arithmetic/Cargo.toml b/substrate/primitives/arithmetic/Cargo.toml
index 8a97f7ce5042be66c21d0bfa445c0cb5eb3315a8..abdbd4e60d041752e072eba5eb7e5f1613fb3f60 100644
--- a/substrate/primitives/arithmetic/Cargo.toml
+++ b/substrate/primitives/arithmetic/Cargo.toml
@@ -18,6 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 integer-sqrt = "0.1.2"
 static_assertions = "1.1.0"
 num-traits = { version = "0.2.8", default-features = false }
@@ -34,6 +35,7 @@ primitive-types = "0.10.1"
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"num-traits/std",
 	"sp-std/std",
 	"serde",
diff --git a/substrate/primitives/arithmetic/src/fixed_point.rs b/substrate/primitives/arithmetic/src/fixed_point.rs
index 1515573b46742fa4069c196bcea52c9a901bd584..7a81f222c49262b77d807c928e8098886d9c7337 100644
--- a/substrate/primitives/arithmetic/src/fixed_point.rs
+++ b/substrate/primitives/arithmetic/src/fixed_point.rs
@@ -363,7 +363,17 @@ macro_rules! implement_fixed {
 		/// A fixed point number representation in the range.
 		#[doc = $title]
 		#[derive(
-			Encode, Decode, CompactAs, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord,
+			Encode,
+			Decode,
+			CompactAs,
+			Default,
+			Copy,
+			Clone,
+			PartialEq,
+			Eq,
+			PartialOrd,
+			Ord,
+			scale_info::TypeInfo,
 		)]
 		pub struct $name($inner_type);
 
diff --git a/substrate/primitives/arithmetic/src/per_things.rs b/substrate/primitives/arithmetic/src/per_things.rs
index f9c048e55b6f764bfec291abfb88ca34ee33f35a..f388c19de6b43c27aad030947824485c5e8dec7a 100644
--- a/substrate/primitives/arithmetic/src/per_things.rs
+++ b/substrate/primitives/arithmetic/src/per_things.rs
@@ -425,7 +425,7 @@ macro_rules! implement_per_thing {
 		///
 		#[doc = $title]
 		#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-		#[derive(Encode, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug)]
+		#[derive(Encode, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, scale_info::TypeInfo)]
 		pub struct $name($type);
 
 		/// Implementation makes any compact encoding of `PerThing::Inner` valid,
diff --git a/substrate/primitives/authority-discovery/Cargo.toml b/substrate/primitives/authority-discovery/Cargo.toml
index c900324d85510a04b4cd452996cadd1704ab55a8..6638e478b4cd7e2dcd7bcb1b1160c52e7de10f39 100644
--- a/substrate/primitives/authority-discovery/Cargo.toml
+++ b/substrate/primitives/authority-discovery/Cargo.toml
@@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" }
 codec = { package = "parity-scale-codec", default-features = false, version = "2.0.0" }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" }
@@ -24,6 +25,7 @@ default = ["std"]
 std = [
 	"sp-application-crypto/std",
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-api/std",
 	"sp-runtime/std"
diff --git a/substrate/primitives/consensus/aura/Cargo.toml b/substrate/primitives/consensus/aura/Cargo.toml
index 1feb04b5bc574d89e19f8a69fb2736dfd5d6915d..c228b88fd657025e8e4a819763092763c73f96ab 100644
--- a/substrate/primitives/consensus/aura/Cargo.toml
+++ b/substrate/primitives/consensus/aura/Cargo.toml
@@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../application-crypto" }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../std" }
 sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" }
@@ -29,6 +30,7 @@ default = ["std"]
 std = [
 	"sp-application-crypto/std",
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-api/std",
 	"sp-runtime/std",
diff --git a/substrate/primitives/consensus/babe/Cargo.toml b/substrate/primitives/consensus/babe/Cargo.toml
index 0428d8e222881194c30cee37e234e992eb18f2d5..5f6bfec2197392081787af3e6b8f6b98268ce083 100644
--- a/substrate/primitives/consensus/babe/Cargo.toml
+++ b/substrate/primitives/consensus/babe/Cargo.toml
@@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../../application-crypto" }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 merlin = { version = "2.0", default-features = false }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../../std" }
 sp-api = { version = "4.0.0-dev", default-features = false, path = "../../api" }
@@ -34,6 +35,7 @@ default = ["std"]
 std = [
 	"sp-application-crypto/std",
 	"codec/std",
+	"scale-info/std",
 	"merlin/std",
 	"sp-std/std",
 	"sp-api/std",
diff --git a/substrate/primitives/consensus/babe/src/digests.rs b/substrate/primitives/consensus/babe/src/digests.rs
index 682894f5837b19193dfa03661cfe7c0cf3b002e6..470a028021ca14a27a81b7912b9cc6b8f425b39e 100644
--- a/substrate/primitives/consensus/babe/src/digests.rs
+++ b/substrate/primitives/consensus/babe/src/digests.rs
@@ -134,7 +134,7 @@ pub struct NextEpochDescriptor {
 
 /// Information about the next epoch config, if changed. This is broadcast in the first
 /// block of the epoch, and applies using the same rules as `NextEpochDescriptor`.
-#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug)]
+#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug, scale_info::TypeInfo)]
 pub enum NextConfigDescriptor {
 	/// Version 1.
 	#[codec(index = 1)]
diff --git a/substrate/primitives/consensus/babe/src/lib.rs b/substrate/primitives/consensus/babe/src/lib.rs
index 3f2fc7e1f5e6ac2fcce65071bbf47250f3e88138..4417670f4144b568982034e6ad8a14452b6dcc48 100644
--- a/substrate/primitives/consensus/babe/src/lib.rs
+++ b/substrate/primitives/consensus/babe/src/lib.rs
@@ -29,6 +29,7 @@ pub use sp_consensus_vrf::schnorrkel::{
 };
 
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
 #[cfg(feature = "std")]
@@ -213,7 +214,7 @@ pub struct BabeGenesisConfiguration {
 }
 
 /// Types of allowed slots.
-#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub enum AllowedSlots {
 	/// Only allow primary slots.
@@ -246,7 +247,7 @@ impl sp_consensus::SlotData for BabeGenesisConfiguration {
 }
 
 /// Configuration data used by the BABE consensus engine.
-#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
+#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub struct BabeEpochConfiguration {
 	/// A constant value that is used in the threshold calculation formula.
diff --git a/substrate/primitives/consensus/slots/Cargo.toml b/substrate/primitives/consensus/slots/Cargo.toml
index 2718158cfb7d66bbad6b9eec565551b5a996e0c6..3ad204f973961283df6ee1f21a4994dff387a6be 100644
--- a/substrate/primitives/consensus/slots/Cargo.toml
+++ b/substrate/primitives/consensus/slots/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../runtime" }
 sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../arithmetic" }
 
@@ -21,6 +22,7 @@ sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../..
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-runtime/std",
 	"sp-arithmetic/std",
 ]
diff --git a/substrate/primitives/consensus/slots/src/lib.rs b/substrate/primitives/consensus/slots/src/lib.rs
index 0b66ac8c9cb6f847c49e49365375c557e2b7e9fd..89b57dca83082aa5cac4d914c35e7bd8dec81043 100644
--- a/substrate/primitives/consensus/slots/src/lib.rs
+++ b/substrate/primitives/consensus/slots/src/lib.rs
@@ -20,9 +20,10 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
 use codec::{Decode, Encode, MaxEncodedLen};
+use scale_info::TypeInfo;
 
 /// Unit type wrapper that represents a slot.
-#[derive(Debug, Encode, MaxEncodedLen, Decode, Eq, Clone, Copy, Default, Ord)]
+#[derive(Debug, Encode, MaxEncodedLen, Decode, Eq, Clone, Copy, Default, Ord, TypeInfo)]
 pub struct Slot(u64);
 
 impl core::ops::Deref for Slot {
@@ -96,7 +97,7 @@ impl From<Slot> for u64 {
 /// produces more than one block on the same slot. The proof of equivocation
 /// are the given distinct headers that were signed by the validator and which
 /// include the slot number.
-#[derive(Clone, Debug, Decode, Encode, PartialEq)]
+#[derive(Clone, Debug, Decode, Encode, PartialEq, TypeInfo)]
 pub struct EquivocationProof<Header, Id> {
 	/// Returns the authority id of the equivocator.
 	pub offender: Id,
diff --git a/substrate/primitives/core/Cargo.toml b/substrate/primitives/core/Cargo.toml
index b2c5230975ec4d4d2bc097d9487cc72a97d814b3..73c3d454ed584dee5914f37c72ad179384a630ca 100644
--- a/substrate/primitives/core/Cargo.toml
+++ b/substrate/primitives/core/Cargo.toml
@@ -18,11 +18,13 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features =
 	"derive",
 	"max-encoded-len",
 ] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 log = { version = "0.4.11", default-features = false }
 serde = { version = "1.0.126", optional = true, features = ["derive"] }
 byteorder = { version = "1.3.2", default-features = false }
 primitive-types = { version = "0.10.1", default-features = false, features = [
 	"codec",
+	"scale-info"
 ] }
 impl-serde = { version = "0.3.0", optional = true }
 wasmi = { version = "0.9.0", optional = true }
@@ -96,6 +98,7 @@ std = [
 	"primitive-types/rustc-hex",
 	"impl-serde",
 	"codec/std",
+	"scale-info/std",
 	"hash256-std-hasher/std",
 	"hash-db/std",
 	"sp-std/std",
diff --git a/substrate/primitives/core/src/changes_trie.rs b/substrate/primitives/core/src/changes_trie.rs
index dd99a5f769ce9e853f5bcf1cb3de6c859d810759..f4ce83dc2c8778e0ac526f2cd0090a99911e9ea9 100644
--- a/substrate/primitives/core/src/changes_trie.rs
+++ b/substrate/primitives/core/src/changes_trie.rs
@@ -27,7 +27,7 @@ use serde::{Deserialize, Serialize};
 	any(feature = "std", test),
 	derive(Serialize, Deserialize, parity_util_mem::MallocSizeOf)
 )]
-#[derive(Debug, Clone, PartialEq, Eq, Default, Encode, Decode)]
+#[derive(Debug, Clone, PartialEq, Eq, Default, Encode, Decode, scale_info::TypeInfo)]
 pub struct ChangesTrieConfiguration {
 	/// Interval (in blocks) at which level1-digests are created. Digests are not
 	/// created when this is less or equal to 1.
diff --git a/substrate/primitives/core/src/crypto.rs b/substrate/primitives/core/src/crypto.rs
index b866639565491ef29e424610c6f6d895929c2e32..4764a0cac1b140e909ffb2707f1d259b4f84fb9e 100644
--- a/substrate/primitives/core/src/crypto.rs
+++ b/substrate/primitives/core/src/crypto.rs
@@ -31,6 +31,7 @@ use parking_lot::Mutex;
 use rand::{rngs::OsRng, RngCore};
 #[cfg(feature = "std")]
 use regex::Regex;
+use scale_info::TypeInfo;
 /// Trait for accessing reference to `SecretString`.
 pub use secrecy::ExposeSecret;
 /// A store for sensitive data.
@@ -715,7 +716,9 @@ pub trait Public:
 }
 
 /// An opaque 32-byte cryptographic identifier.
-#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Default, Encode, Decode, MaxEncodedLen)]
+#[derive(
+	Clone, Eq, PartialEq, Ord, PartialOrd, Default, Encode, Decode, MaxEncodedLen, TypeInfo,
+)]
 #[cfg_attr(feature = "std", derive(Hash))]
 pub struct AccountId32([u8; 32]);
 
@@ -1175,6 +1178,7 @@ pub trait CryptoType {
 	Decode,
 	PassByInner,
 	crate::RuntimeDebug,
+	TypeInfo,
 )]
 #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
 pub struct KeyTypeId(pub [u8; 4]);
diff --git a/substrate/primitives/core/src/ecdsa.rs b/substrate/primitives/core/src/ecdsa.rs
index 147569d52b89f0d6d1fbad72023d01d82c3c9c05..11e9b9d71d80e4407e6a07dd4b220fff2426d1d1 100644
--- a/substrate/primitives/core/src/ecdsa.rs
+++ b/substrate/primitives/core/src/ecdsa.rs
@@ -20,6 +20,7 @@
 // end::description[]
 
 use codec::{Decode, Encode, MaxEncodedLen};
+use scale_info::TypeInfo;
 use sp_runtime_interface::pass_by::PassByInner;
 use sp_std::cmp::Ordering;
 
@@ -54,7 +55,7 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecds");
 type Seed = [u8; 32];
 
 /// The ECDSA compressed public key.
-#[derive(Clone, Encode, Decode, PassByInner, MaxEncodedLen)]
+#[derive(Clone, Encode, Decode, PassByInner, MaxEncodedLen, TypeInfo)]
 pub struct Public(pub [u8; 33]);
 
 impl PartialOrd for Public {
@@ -234,7 +235,7 @@ impl sp_std::hash::Hash for Public {
 }
 
 /// A signature (a 512-bit value, plus 8 bits for recovery ID).
-#[derive(Encode, Decode, PassByInner)]
+#[derive(Encode, Decode, PassByInner, TypeInfo)]
 pub struct Signature(pub [u8; 65]);
 
 impl sp_std::convert::TryFrom<&[u8]> for Signature {
diff --git a/substrate/primitives/core/src/ed25519.rs b/substrate/primitives/core/src/ed25519.rs
index be70da31e641de0d9dd6096e6bfbf20f2026d96a..d786ee9d255ff609ab6d475c089e459abebb90c0 100644
--- a/substrate/primitives/core/src/ed25519.rs
+++ b/substrate/primitives/core/src/ed25519.rs
@@ -24,6 +24,7 @@ use sp_std::vec::Vec;
 
 use crate::hash::{H256, H512};
 use codec::{Decode, Encode, MaxEncodedLen};
+use scale_info::TypeInfo;
 
 #[cfg(feature = "std")]
 use crate::crypto::Ss58Codec;
@@ -57,7 +58,18 @@ type Seed = [u8; 32];
 /// A public key.
 #[cfg_attr(feature = "full_crypto", derive(Hash))]
 #[derive(
-	PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Encode, Decode, Default, PassByInner, MaxEncodedLen,
+	PartialEq,
+	Eq,
+	PartialOrd,
+	Ord,
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	Default,
+	PassByInner,
+	MaxEncodedLen,
+	TypeInfo,
 )]
 pub struct Public(pub [u8; 32]);
 
@@ -198,7 +210,7 @@ impl<'de> Deserialize<'de> for Public {
 }
 
 /// A signature (a 512-bit value).
-#[derive(Encode, Decode, PassByInner)]
+#[derive(Encode, Decode, PassByInner, TypeInfo)]
 pub struct Signature(pub [u8; 64]);
 
 impl sp_std::convert::TryFrom<&[u8]> for Signature {
diff --git a/substrate/primitives/core/src/lib.rs b/substrate/primitives/core/src/lib.rs
index 0a61c90d71357914fc181a6cd8844fd6bf5d84df..a6229fe43a1a56bc206848914e7ff50541a9c1d7 100644
--- a/substrate/primitives/core/src/lib.rs
+++ b/substrate/primitives/core/src/lib.rs
@@ -33,6 +33,7 @@ macro_rules! map {
 
 #[doc(hidden)]
 pub use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 #[cfg(feature = "std")]
 pub use serde;
 #[cfg(feature = "std")]
@@ -191,7 +192,17 @@ impl sp_std::ops::Deref for OpaqueMetadata {
 
 /// Simple blob to hold a `PeerId` without committing to its format.
 #[derive(
-	Default, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, PassByInner,
+	Default,
+	Clone,
+	Eq,
+	PartialEq,
+	Ord,
+	PartialOrd,
+	Encode,
+	Decode,
+	RuntimeDebug,
+	PassByInner,
+	TypeInfo,
 )]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub struct OpaquePeerId(pub Vec<u8>);
@@ -414,7 +425,7 @@ pub fn to_substrate_wasm_fn_return_value(value: &impl Encode) -> u64 {
 
 /// The void type - it cannot exist.
 // Oh rust, you crack me up...
-#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug)]
+#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
 pub enum Void {}
 
 /// Macro for creating `Maybe*` marker traits.
diff --git a/substrate/primitives/core/src/offchain/mod.rs b/substrate/primitives/core/src/offchain/mod.rs
index 59c92f540badf3c937e4ede1b8b5eec661bcb054..640f4d2583b7902e4643487c0f97cf740b6f33c3 100644
--- a/substrate/primitives/core/src/offchain/mod.rs
+++ b/substrate/primitives/core/src/offchain/mod.rs
@@ -19,6 +19,7 @@
 
 use crate::{OpaquePeerId, RuntimeDebug};
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 use sp_runtime_interface::pass_by::{PassByCodec, PassByEnum, PassByInner};
 use sp_std::{
 	convert::TryFrom,
@@ -186,7 +187,7 @@ impl TryFrom<u32> for HttpRequestStatus {
 
 /// A blob to hold information about the local node's network state
 /// without committing to its format.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, PassByCodec)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, PassByCodec, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Default))]
 pub struct OpaqueNetworkState {
 	/// PeerId of the local node in SCALE encoded.
@@ -196,7 +197,7 @@ pub struct OpaqueNetworkState {
 }
 
 /// Simple blob to hold a `Multiaddr` without committing to its format.
-#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, PassByInner)]
+#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, PassByInner, TypeInfo)]
 pub struct OpaqueMultiaddr(pub Vec<u8>);
 
 impl OpaqueMultiaddr {
diff --git a/substrate/primitives/core/src/sr25519.rs b/substrate/primitives/core/src/sr25519.rs
index 4c5122162d65d035b4b6f510043dea555c20feb0..4787c2d9d13ee2f156553283ebfb488fdeb705ec 100644
--- a/substrate/primitives/core/src/sr25519.rs
+++ b/substrate/primitives/core/src/sr25519.rs
@@ -47,6 +47,7 @@ use crate::{
 	hash::{H256, H512},
 };
 use codec::{Decode, Encode, MaxEncodedLen};
+use scale_info::TypeInfo;
 use sp_std::ops::Deref;
 
 #[cfg(feature = "full_crypto")]
@@ -65,7 +66,18 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"sr25");
 /// An Schnorrkel/Ristretto x25519 ("sr25519") public key.
 #[cfg_attr(feature = "full_crypto", derive(Hash))]
 #[derive(
-	PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Encode, Decode, Default, PassByInner, MaxEncodedLen,
+	PartialEq,
+	Eq,
+	PartialOrd,
+	Ord,
+	Clone,
+	Copy,
+	Encode,
+	Decode,
+	Default,
+	PassByInner,
+	MaxEncodedLen,
+	TypeInfo,
 )]
 pub struct Public(pub [u8; 32]);
 
@@ -201,7 +213,7 @@ impl<'de> Deserialize<'de> for Public {
 /// An Schnorrkel/Ristretto x25519 ("sr25519") signature.
 ///
 /// Instead of importing it for the local module, alias it to be available as a public type
-#[derive(Encode, Decode, PassByInner)]
+#[derive(Encode, Decode, PassByInner, TypeInfo)]
 pub struct Signature(pub [u8; 64]);
 
 impl sp_std::convert::TryFrom<&[u8]> for Signature {
diff --git a/substrate/primitives/finality-grandpa/Cargo.toml b/substrate/primitives/finality-grandpa/Cargo.toml
index 895270d012192382622e99045a79478b74f951f3..c0c2a654270f7847513821531cfcc09400c0d75b 100644
--- a/substrate/primitives/finality-grandpa/Cargo.toml
+++ b/substrate/primitives/finality-grandpa/Cargo.toml
@@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 grandpa = { package = "finality-grandpa", version = "0.14.1", default-features = false, features = ["derive-codec"] }
 log = { version = "0.4.8", optional = true }
 serde = { version = "1.0.126", optional = true, features = ["derive"] }
@@ -32,6 +33,7 @@ std = [
 	"log",
 	"serde",
 	"codec/std",
+	"scale-info/std",
 	"grandpa/std",
 	"sp-api/std",
 	"sp-application-crypto/std",
diff --git a/substrate/primitives/finality-grandpa/src/lib.rs b/substrate/primitives/finality-grandpa/src/lib.rs
index 353a3cd07822b84690e13fa8c7881060868e342a..d99a4c1882222059b3e70013baf3333bb699316a 100644
--- a/substrate/primitives/finality-grandpa/src/lib.rs
+++ b/substrate/primitives/finality-grandpa/src/lib.rs
@@ -26,6 +26,7 @@ extern crate alloc;
 use serde::Serialize;
 
 use codec::{Codec, Decode, Encode, Input};
+use scale_info::TypeInfo;
 #[cfg(feature = "std")]
 use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr};
 use sp_runtime::{traits::NumberFor, ConsensusEngineId, RuntimeDebug};
@@ -170,7 +171,7 @@ impl<N: Codec> ConsensusLog<N> {
 /// GRANDPA happens when a voter votes on the same round (either at prevote or
 /// precommit stage) for different blocks. Proving is achieved by collecting the
 /// signed messages of conflicting votes.
-#[derive(Clone, Debug, Decode, Encode, PartialEq)]
+#[derive(Clone, Debug, Decode, Encode, PartialEq, TypeInfo)]
 pub struct EquivocationProof<H, N> {
 	set_id: SetId,
 	equivocation: Equivocation<H, N>,
@@ -204,7 +205,7 @@ impl<H, N> EquivocationProof<H, N> {
 
 /// Wrapper object for GRANDPA equivocation proofs, useful for unifying prevote
 /// and precommit equivocations under a common type.
-#[derive(Clone, Debug, Decode, Encode, PartialEq)]
+#[derive(Clone, Debug, Decode, Encode, PartialEq, TypeInfo)]
 pub enum Equivocation<H, N> {
 	/// Proof of equivocation at prevote stage.
 	Prevote(grandpa::Equivocation<AuthorityId, grandpa::Prevote<H, N>, AuthoritySignature>),
diff --git a/substrate/primitives/npos-elections/Cargo.toml b/substrate/primitives/npos-elections/Cargo.toml
index 5c6e5c1b13d536671bab1a3ac313b98f4f253443..b277df8f58f128894d4e1d670d918d8fb0390574 100644
--- a/substrate/primitives/npos-elections/Cargo.toml
+++ b/substrate/primitives/npos-elections/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 serde = { version = "1.0.126", optional = true, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 sp-npos-elections-solution-type = { version = "4.0.0-dev", path = "./solution-type" }
@@ -30,6 +31,7 @@ default = ["std"]
 bench = []
 std = [
 	"codec/std",
+	"scale-info/std",
 	"serde",
 	"sp-std/std",
 	"sp-arithmetic/std",
diff --git a/substrate/primitives/npos-elections/fuzzer/Cargo.toml b/substrate/primitives/npos-elections/fuzzer/Cargo.toml
index a8d0524fb87170292b97b67dbd00173a236cf428..d6fcc09c8b586d3feea04d827fcc3a926a74f72c 100644
--- a/substrate/primitives/npos-elections/fuzzer/Cargo.toml
+++ b/substrate/primitives/npos-elections/fuzzer/Cargo.toml
@@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 honggfuzz = "0.5"
 rand = { version = "0.7.3", features = ["std", "small_rng"] }
 sp-npos-elections = { version = "4.0.0-dev", path = ".." }
diff --git a/substrate/primitives/npos-elections/solution-type/Cargo.toml b/substrate/primitives/npos-elections/solution-type/Cargo.toml
index a061cedc923184283133bcddc2d6f20651623254..cbe6750266f017628429f403101894a18861bbf3 100644
--- a/substrate/primitives/npos-elections/solution-type/Cargo.toml
+++ b/substrate/primitives/npos-elections/solution-type/Cargo.toml
@@ -22,6 +22,7 @@ proc-macro-crate = "1.0.0"
 
 [dev-dependencies]
 parity-scale-codec = "2.0.1"
+scale-info = "1.0"
 sp-arithmetic = { path = "../../arithmetic", version = "4.0.0-dev" }
 # used by generate_solution_type:
 sp-npos-elections = { path = "..", version = "4.0.0-dev" }
diff --git a/substrate/primitives/npos-elections/solution-type/src/codec.rs b/substrate/primitives/npos-elections/solution-type/src/codec.rs
index 21688c03ace53088720cdea9a4daad8ff3b70639..2dac076fcde4211eb5ee423618af2c44e636daf3 100644
--- a/substrate/primitives/npos-elections/solution-type/src/codec.rs
+++ b/substrate/primitives/npos-elections/solution-type/src/codec.rs
@@ -15,33 +15,35 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//! Code generation for the ratio assignment type' encode/decode impl.
+//! Code generation for the ratio assignment type' encode/decode/info impl.
 
 use crate::vote_field;
 use proc_macro2::TokenStream as TokenStream2;
 use quote::quote;
 
-pub(crate) fn codec_impl(
+pub(crate) fn codec_and_info_impl(
 	ident: syn::Ident,
 	voter_type: syn::Type,
 	target_type: syn::Type,
 	weight_type: syn::Type,
 	count: usize,
 ) -> TokenStream2 {
-	let encode = encode_impl(ident.clone(), count);
-	let decode = decode_impl(ident, voter_type, target_type, weight_type, count);
+	let encode = encode_impl(&ident, count);
+	let decode = decode_impl(&ident, &voter_type, &target_type, &weight_type, count);
+	let scale_info = scale_info_impl(&ident, &voter_type, &target_type, &weight_type, count);
 
 	quote! {
 		#encode
 		#decode
+		#scale_info
 	}
 }
 
 fn decode_impl(
-	ident: syn::Ident,
-	voter_type: syn::Type,
-	target_type: syn::Type,
-	weight_type: syn::Type,
+	ident: &syn::Ident,
+	voter_type: &syn::Type,
+	target_type: &syn::Type,
+	weight_type: &syn::Type,
 	count: usize,
 ) -> TokenStream2 {
 	let decode_impl_single = {
@@ -114,7 +116,7 @@ fn decode_impl(
 
 // General attitude is that we will convert inner values to `Compact` and then use the normal
 // `Encode` implementation.
-fn encode_impl(ident: syn::Ident, count: usize) -> TokenStream2 {
+fn encode_impl(ident: &syn::Ident, count: usize) -> TokenStream2 {
 	let encode_impl_single = {
 		let name = vote_field(1);
 		quote! {
@@ -168,3 +170,73 @@ fn encode_impl(ident: syn::Ident, count: usize) -> TokenStream2 {
 		}
 	)
 }
+
+fn scale_info_impl(
+	ident: &syn::Ident,
+	voter_type: &syn::Type,
+	target_type: &syn::Type,
+	weight_type: &syn::Type,
+	count: usize,
+) -> TokenStream2 {
+	let scale_info_impl_single = {
+		let name = format!("{}", vote_field(1));
+		quote! {
+			.field(|f|
+				f.ty::<_npos::sp_std::prelude::Vec<
+				   (_npos::codec::Compact<#voter_type>, _npos::codec::Compact<#target_type>)
+				>>()
+				.name(#name)
+			)
+		}
+	};
+
+	let scale_info_impl_double = {
+		let name = format!("{}", vote_field(2));
+		quote! {
+			.field(|f|
+				f.ty::<_npos::sp_std::prelude::Vec<(
+					_npos::codec::Compact<#voter_type>,
+					(_npos::codec::Compact<#target_type>, _npos::codec::Compact<#weight_type>),
+					_npos::codec::Compact<#target_type>
+				)>>()
+				.name(#name)
+			)
+		}
+	};
+
+	let scale_info_impl_rest = (3..=count)
+		.map(|c| {
+			let name = format!("{}", vote_field(c));
+			quote! {
+				.field(|f|
+					f.ty::<_npos::sp_std::prelude::Vec<(
+						_npos::codec::Compact<#voter_type>,
+						[
+							(_npos::codec::Compact<#target_type>, _npos::codec::Compact<#weight_type>);
+							#c - 1
+						],
+						_npos::codec::Compact<#target_type>
+					)>>()
+					.name(#name)
+				)
+			}
+		})
+		.collect::<TokenStream2>();
+
+	quote!(
+		 impl _npos::scale_info::TypeInfo for #ident {
+			 type Identity = Self;
+
+			 fn type_info() -> _npos::scale_info::Type<_npos::scale_info::form::MetaForm> {
+				 _npos::scale_info::Type::builder()
+					 .path(_npos::scale_info::Path::new(stringify!(#ident), module_path!()))
+					 .composite(
+						 _npos::scale_info::build::Fields::named()
+						 #scale_info_impl_single
+						 #scale_info_impl_double
+						 #scale_info_impl_rest
+					 )
+			 }
+		 }
+	)
+}
diff --git a/substrate/primitives/npos-elections/solution-type/src/single_page.rs b/substrate/primitives/npos-elections/solution-type/src/single_page.rs
index 7dfd0e56618f9cdc56bd83a7cb97559dc5ba5380..33017d558331ad1c72fa031387b332dbfebeb677 100644
--- a/substrate/primitives/npos-elections/solution-type/src/single_page.rs
+++ b/substrate/primitives/npos-elections/solution-type/src/single_page.rs
@@ -64,7 +64,7 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result<TokenStream2> {
 
 	let derives_and_maybe_compact_encoding = if compact_encoding {
 		// custom compact encoding.
-		let compact_impl = crate::codec::codec_impl(
+		let compact_impl = crate::codec::codec_and_info_impl(
 			ident.clone(),
 			voter_type.clone(),
 			target_type.clone(),
@@ -77,7 +77,16 @@ pub(crate) fn generate(def: crate::SolutionDef) -> Result<TokenStream2> {
 		}
 	} else {
 		// automatically derived.
-		quote!(#[derive(Default, PartialEq, Eq, Clone, Debug, _npos::codec::Encode, _npos::codec::Decode)])
+		quote!(#[derive(
+			Default,
+			PartialEq,
+			Eq,
+			Clone,
+			Debug,
+			_npos::codec::Encode,
+			_npos::codec::Decode,
+			_npos::scale_info::TypeInfo,
+		)])
 	};
 
 	let struct_name = syn::Ident::new("solution", proc_macro2::Span::call_site());
diff --git a/substrate/primitives/npos-elections/src/lib.rs b/substrate/primitives/npos-elections/src/lib.rs
index 84b5d480bef01006213cc809c447ea36a986538d..afe85ef53b3a71b2cef6c88c53245aaa0341b3c3 100644
--- a/substrate/primitives/npos-elections/src/lib.rs
+++ b/substrate/primitives/npos-elections/src/lib.rs
@@ -110,6 +110,8 @@ pub use traits::{IdentifierT, NposSolution, PerThing128, __OrInvalidIndex};
 #[doc(hidden)]
 pub use codec;
 #[doc(hidden)]
+pub use scale_info;
+#[doc(hidden)]
 pub use sp_arithmetic;
 #[doc(hidden)]
 pub use sp_std;
@@ -337,7 +339,7 @@ pub struct ElectionResult<AccountId, P: PerThing> {
 ///
 /// This, at the current version, resembles the `Exposure` defined in the Staking pallet, yet they
 /// do not necessarily have to be the same.
-#[derive(Default, RuntimeDebug, Encode, Decode, Clone, Eq, PartialEq)]
+#[derive(Default, RuntimeDebug, Encode, Decode, Clone, Eq, PartialEq, scale_info::TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub struct Support<AccountId> {
 	/// Total support.
diff --git a/substrate/primitives/runtime/Cargo.toml b/substrate/primitives/runtime/Cargo.toml
index 017c6a75efd9931755127876fb0710cd54efe15d..5ac5bcf1963e0f11681aa8d26d2ca9923250d5f3 100644
--- a/substrate/primitives/runtime/Cargo.toml
+++ b/substrate/primitives/runtime/Cargo.toml
@@ -17,6 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 serde = { version = "1.0.126", optional = true, features = ["derive"] }
 codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" }
 sp-application-crypto = { version = "4.0.0-dev", default-features = false, path = "../application-crypto" }
 sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../arithmetic" }
@@ -46,6 +47,7 @@ std = [
 	"sp-application-crypto/std",
 	"sp-arithmetic/std",
 	"codec/std",
+	"scale-info/std",
 	"log/std",
 	"sp-core/std",
 	"rand",
diff --git a/substrate/primitives/runtime/src/curve.rs b/substrate/primitives/runtime/src/curve.rs
index 72d64cf4b8e17547fa159f085cd20488abacae00..d6bd94c2bff70512491ae45ac98a1e98f203806b 100644
--- a/substrate/primitives/runtime/src/curve.rs
+++ b/substrate/primitives/runtime/src/curve.rs
@@ -24,7 +24,7 @@ use crate::{
 use core::ops::Sub;
 
 /// Piecewise Linear function in [0, 1] -> [0, 1].
-#[derive(PartialEq, Eq, sp_core::RuntimeDebug)]
+#[derive(PartialEq, Eq, sp_core::RuntimeDebug, scale_info::TypeInfo)]
 pub struct PiecewiseLinear<'a> {
 	/// Array of points. Must be in order from the lowest abscissas to the highest.
 	pub points: &'a [(Perbill, Perbill)],
diff --git a/substrate/primitives/runtime/src/generic/digest.rs b/substrate/primitives/runtime/src/generic/digest.rs
index 99d27ad5826c408c6edb202b5d44fa20dead0f6c..87af9bc77a5fab96ea71ad3fbea563c56daa3e5d 100644
--- a/substrate/primitives/runtime/src/generic/digest.rs
+++ b/substrate/primitives/runtime/src/generic/digest.rs
@@ -24,12 +24,16 @@ use sp_std::prelude::*;
 
 use crate::{
 	codec::{Decode, Encode, Error, Input},
+	scale_info::{
+		build::{Fields, Variants},
+		meta_type, Path, Type, TypeInfo, TypeParameter,
+	},
 	ConsensusEngineId,
 };
 use sp_core::{ChangesTrieConfiguration, RuntimeDebug};
 
 /// Generic header digest.
-#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, parity_util_mem::MallocSizeOf))]
 pub struct Digest<Hash> {
 	/// A list of logs in the digest.
@@ -129,7 +133,7 @@ pub enum DigestItem<Hash> {
 }
 
 /// Available changes trie signals.
-#[derive(PartialEq, Eq, Clone, Encode, Decode)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Debug, parity_util_mem::MallocSizeOf))]
 pub enum ChangesTrieSignal {
 	/// New changes trie configuration is enacted, starting from **next block**.
@@ -167,6 +171,69 @@ impl<'a, Hash: Decode> serde::Deserialize<'a> for DigestItem<Hash> {
 	}
 }
 
+impl<Hash> TypeInfo for DigestItem<Hash>
+where
+	Hash: TypeInfo + 'static,
+{
+	type Identity = Self;
+
+	fn type_info() -> Type {
+		Type::builder()
+			.path(Path::new("DigestItem", module_path!()))
+			.type_params(vec![TypeParameter::new("Hash", Some(meta_type::<Hash>()))])
+			.variant(
+				Variants::new()
+					.variant("ChangesTrieRoot", |v| {
+						v.index(DigestItemType::ChangesTrieRoot as u8)
+							.fields(Fields::unnamed().field(|f| f.ty::<Hash>().type_name("Hash")))
+					})
+					.variant("PreRuntime", |v| {
+						v.index(DigestItemType::PreRuntime as u8).fields(
+							Fields::unnamed()
+								.field(|f| {
+									f.ty::<ConsensusEngineId>().type_name("ConsensusEngineId")
+								})
+								.field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
+						)
+					})
+					.variant("Consensus", |v| {
+						v.index(DigestItemType::Consensus as u8).fields(
+							Fields::unnamed()
+								.field(|f| {
+									f.ty::<ConsensusEngineId>().type_name("ConsensusEngineId")
+								})
+								.field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
+						)
+					})
+					.variant("Seal", |v| {
+						v.index(DigestItemType::Seal as u8).fields(
+							Fields::unnamed()
+								.field(|f| {
+									f.ty::<ConsensusEngineId>().type_name("ConsensusEngineId")
+								})
+								.field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
+						)
+					})
+					.variant("ChangesTrieSignal", |v| {
+						v.index(DigestItemType::ChangesTrieSignal as u8).fields(
+							Fields::unnamed().field(|f| {
+								f.ty::<ChangesTrieSignal>().type_name("ChangesTrieSignal")
+							}),
+						)
+					})
+					.variant("Other", |v| {
+						v.index(DigestItemType::Other as u8).fields(
+							Fields::unnamed().field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
+						)
+					})
+					.variant("RuntimeEnvironmentUpdated", |v| {
+						v.index(DigestItemType::RuntimeEnvironmentUpdated as u8)
+							.fields(Fields::unit())
+					}),
+			)
+	}
+}
+
 /// A 'referencing view' for digest item. Does not own its contents. Used by
 /// final runtime implementations for encoding/decoding its log items.
 #[derive(PartialEq, Eq, Clone, RuntimeDebug)]
@@ -509,4 +576,52 @@ mod tests {
 			r#"{"logs":["0x0204000000","0x000c010203","0x05746573740c010203"]}"#
 		);
 	}
+
+	#[test]
+	fn digest_item_type_info() {
+		let type_info = DigestItem::<u32>::type_info();
+		let variants = if let scale_info::TypeDef::Variant(variant) = type_info.type_def() {
+			variant.variants()
+		} else {
+			panic!("Should be a TypeDef::TypeDefVariant")
+		};
+
+		// ensure that all variants are covered by manual TypeInfo impl
+		let check = |digest_item_type: DigestItemType| {
+			let (variant_name, digest_item) = match digest_item_type {
+				DigestItemType::Other => ("Other", DigestItem::<u32>::Other(Default::default())),
+				DigestItemType::ChangesTrieRoot =>
+					("ChangesTrieRoot", DigestItem::ChangesTrieRoot(Default::default())),
+				DigestItemType::Consensus =>
+					("Consensus", DigestItem::Consensus(Default::default(), Default::default())),
+				DigestItemType::Seal =>
+					("Seal", DigestItem::Seal(Default::default(), Default::default())),
+				DigestItemType::PreRuntime =>
+					("PreRuntime", DigestItem::PreRuntime(Default::default(), Default::default())),
+				DigestItemType::ChangesTrieSignal => (
+					"ChangesTrieSignal",
+					DigestItem::ChangesTrieSignal(ChangesTrieSignal::NewConfiguration(
+						Default::default(),
+					)),
+				),
+				DigestItemType::RuntimeEnvironmentUpdated =>
+					("RuntimeEnvironmentUpdated", DigestItem::RuntimeEnvironmentUpdated),
+			};
+			let encoded = digest_item.encode();
+			let variant = variants
+				.iter()
+				.find(|v| v.name() == &variant_name)
+				.expect(&format!("Variant {} not found", variant_name));
+
+			assert_eq!(encoded[0], variant.index())
+		};
+
+		check(DigestItemType::Other);
+		check(DigestItemType::ChangesTrieRoot);
+		check(DigestItemType::Consensus);
+		check(DigestItemType::Seal);
+		check(DigestItemType::PreRuntime);
+		check(DigestItemType::ChangesTrieSignal);
+		check(DigestItemType::RuntimeEnvironmentUpdated);
+	}
 }
diff --git a/substrate/primitives/runtime/src/generic/era.rs b/substrate/primitives/runtime/src/generic/era.rs
index 1a7239ab6e3eb1172d12cdaa243e65ab25d48854..9d831b679c5e48e8633433f1ce6790c57f08fe60 100644
--- a/substrate/primitives/runtime/src/generic/era.rs
+++ b/substrate/primitives/runtime/src/generic/era.rs
@@ -134,6 +134,50 @@ impl Decode for Era {
 	}
 }
 
+/// Add Mortal{N}(u8) variants with the given indices, to describe custom encoding.
+macro_rules! mortal_variants {
+    ($variants:ident, $($index:literal),* ) => {
+		$variants
+		$(
+			.variant(concat!(stringify!(Mortal), stringify!($index)), |v| v
+				.index($index)
+				.fields(scale_info::build::Fields::unnamed().field(|f| f.ty::<u8>()))
+			)
+		)*
+    }
+}
+
+impl scale_info::TypeInfo for Era {
+	type Identity = Self;
+
+	fn type_info() -> scale_info::Type {
+		let variants = scale_info::build::Variants::new().variant("Immortal", |v| v.index(0));
+
+		// this is necessary since the size of the encoded Mortal variant is `u16`, conditional on
+		// the value of the first byte being > 0.
+		let variants = mortal_variants!(
+			variants, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+			22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+			44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+			66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+			88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+			108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+			125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+			142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+			159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+			176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
+			193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+			210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+			227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+			244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
+		);
+
+		scale_info::Type::builder()
+			.path(scale_info::Path::new("Era", module_path!()))
+			.variant(variants)
+	}
+}
+
 #[cfg(test)]
 mod tests {
 	use super::*;
diff --git a/substrate/primitives/runtime/src/generic/header.rs b/substrate/primitives/runtime/src/generic/header.rs
index d28f663db003d2dedaccbdccc7c42b58a5d76ffa..82f081c0d70b078abb8c20179f35333fd9c4700b 100644
--- a/substrate/primitives/runtime/src/generic/header.rs
+++ b/substrate/primitives/runtime/src/generic/header.rs
@@ -20,6 +20,7 @@
 use crate::{
 	codec::{Codec, Decode, Encode},
 	generic::Digest,
+	scale_info::TypeInfo,
 	traits::{
 		self, AtLeast32BitUnsigned, Hash as HashT, MaybeDisplay, MaybeMallocSizeOf, MaybeSerialize,
 		MaybeSerializeDeserialize, Member, SimpleBitOps,
@@ -31,7 +32,7 @@ use sp_core::U256;
 use sp_std::{convert::TryFrom, fmt::Debug};
 
 /// Abstraction over a block header for a substrate chain.
-#[derive(Encode, Decode, PartialEq, Eq, Clone, sp_core::RuntimeDebug)]
+#[derive(Encode, Decode, PartialEq, Eq, Clone, sp_core::RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
 #[cfg_attr(feature = "std", serde(deny_unknown_fields))]
diff --git a/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs b/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs
index f0e00b7b82971fda3d69add40f2b683cc1b8aceb..95f4f2f3584d9db0b09859c708eb51bf5d52c474 100644
--- a/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs
+++ b/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs
@@ -27,6 +27,7 @@ use crate::{
 	OpaqueExtrinsic,
 };
 use codec::{Compact, Decode, Encode, EncodeLike, Error, Input};
+use scale_info::{build::Fields, meta_type, Path, StaticTypeInfo, Type, TypeInfo, TypeParameter};
 use sp_io::hashing::blake2_256;
 use sp_std::{fmt, prelude::*};
 
@@ -48,6 +49,40 @@ where
 	pub function: Call,
 }
 
+/// Manual [`TypeInfo`] implementation because of custom encoding. The data is a valid encoded
+/// `Vec<u8>`, but requires some logic to extract the signature and payload.
+///
+/// See [`UncheckedExtrinsic::encode`] and [`UncheckedExtrinsic::decode`].
+impl<Address, Call, Signature, Extra> TypeInfo
+	for UncheckedExtrinsic<Address, Call, Signature, Extra>
+where
+	Address: StaticTypeInfo,
+	Call: StaticTypeInfo,
+	Signature: StaticTypeInfo,
+	Extra: SignedExtension + StaticTypeInfo,
+{
+	type Identity = UncheckedExtrinsic<Address, Call, Signature, Extra>;
+
+	fn type_info() -> Type {
+		Type::builder()
+			.path(Path::new("UncheckedExtrinsic", module_path!()))
+			// Include the type parameter types, even though they are not used directly in any of
+			// the described fields. These type definitions can be used by downstream consumers
+			// to help construct the custom decoding from the opaque bytes (see below).
+			.type_params(vec![
+				TypeParameter::new("Address", Some(meta_type::<Address>())),
+				TypeParameter::new("Call", Some(meta_type::<Call>())),
+				TypeParameter::new("Signature", Some(meta_type::<Signature>())),
+				TypeParameter::new("Extra", Some(meta_type::<Extra>())),
+			])
+			.docs(&["UncheckedExtrinsic raw bytes, requires custom decoding routine"])
+			// Because of the custom encoding, we can only accurately describe the encoding as an
+			// opaque `Vec<u8>`. Downstream consumers will need to manually implement the codec to
+			// encode/decode the `signature` and `function` fields.
+			.composite(Fields::unnamed().field(|f| f.ty::<Vec<u8>>()))
+	}
+}
+
 #[cfg(feature = "std")]
 impl<Address, Call, Signature, Extra> parity_util_mem::MallocSizeOf
 	for UncheckedExtrinsic<Address, Call, Signature, Extra>
@@ -340,7 +375,7 @@ mod tests {
 	const TEST_ACCOUNT: TestAccountId = 0;
 
 	// NOTE: this is demonstration. One can simply use `()` for testing.
-	#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd)]
+	#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd, TypeInfo)]
 	struct TestExtra;
 	impl SignedExtension for TestExtra {
 		const IDENTIFIER: &'static str = "TestExtra";
diff --git a/substrate/primitives/runtime/src/lib.rs b/substrate/primitives/runtime/src/lib.rs
index 4a9c6087fa5cccc9fe1d68c8f3cfc92aef21e585..80293fe734844063169969356f6f429db01574fa 100644
--- a/substrate/primitives/runtime/src/lib.rs
+++ b/substrate/primitives/runtime/src/lib.rs
@@ -26,6 +26,8 @@ extern crate test;
 
 #[doc(hidden)]
 pub use codec;
+#[doc(hidden)]
+pub use scale_info;
 #[cfg(feature = "std")]
 #[doc(hidden)]
 pub use serde;
@@ -50,6 +52,7 @@ use sp_core::{
 use sp_std::{convert::TryFrom, prelude::*};
 
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 
 pub mod curve;
 pub mod generic;
@@ -220,7 +223,7 @@ pub type ConsensusEngineId = [u8; 4];
 
 /// Signature verify that can work with any known signature types..
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Eq, PartialEq, Clone, Encode, Decode, RuntimeDebug)]
+#[derive(Eq, PartialEq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
 pub enum MultiSignature {
 	/// An Ed25519 signature.
 	Ed25519(ed25519::Signature),
@@ -288,7 +291,7 @@ impl Default for MultiSignature {
 }
 
 /// Public key for any known crypto algorithm.
-#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, RuntimeDebug)]
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub enum MultiSigner {
 	/// An Ed25519 identity.
@@ -463,7 +466,7 @@ pub type DispatchResult = sp_std::result::Result<(), DispatchError>;
 pub type DispatchResultWithInfo<T> = sp_std::result::Result<T, DispatchErrorWithPostInfo<T>>;
 
 /// Reason why a dispatch call failed.
-#[derive(Eq, Clone, Copy, Encode, Decode, Debug)]
+#[derive(Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub enum DispatchError {
 	/// Some error occurred.
@@ -544,7 +547,7 @@ impl From<crate::traits::BadOrigin> for DispatchError {
 }
 
 /// Description of what went wrong when trying to complete an operation on a token.
-#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug)]
+#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub enum TokenError {
 	/// Funds are unavailable.
@@ -584,7 +587,7 @@ impl From<TokenError> for DispatchError {
 }
 
 /// Arithmetic errors.
-#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug)]
+#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Debug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub enum ArithmeticError {
 	/// Underflow.
diff --git a/substrate/primitives/runtime/src/multiaddress.rs b/substrate/primitives/runtime/src/multiaddress.rs
index 28031461cf323f0d0219813d04682f9194cf760b..46d80608352dc0c9ebe9ac5ad43b102652d23735 100644
--- a/substrate/primitives/runtime/src/multiaddress.rs
+++ b/substrate/primitives/runtime/src/multiaddress.rs
@@ -21,7 +21,7 @@ use codec::{Decode, Encode};
 use sp_std::vec::Vec;
 
 /// A multi-format address wrapper for on-chain accounts.
-#[derive(Encode, Decode, PartialEq, Eq, Clone, crate::RuntimeDebug)]
+#[derive(Encode, Decode, PartialEq, Eq, Clone, crate::RuntimeDebug, scale_info::TypeInfo)]
 #[cfg_attr(feature = "std", derive(Hash))]
 pub enum MultiAddress<AccountId, AccountIndex> {
 	/// It's an account ID (pubkey).
diff --git a/substrate/primitives/runtime/src/runtime_string.rs b/substrate/primitives/runtime/src/runtime_string.rs
index 273a22e98f33d54f19036fd887857881cf681e69..179e88145181314ec4cd8b7caadf8b27c954fd8f 100644
--- a/substrate/primitives/runtime/src/runtime_string.rs
+++ b/substrate/primitives/runtime/src/runtime_string.rs
@@ -32,6 +32,14 @@ pub enum RuntimeString {
 	Owned(Vec<u8>),
 }
 
+impl scale_info::TypeInfo for RuntimeString {
+	type Identity = str;
+
+	fn type_info() -> scale_info::Type {
+		Self::Identity::type_info()
+	}
+}
+
 /// Convenience macro to use the format! interface to get a `RuntimeString::Owned`
 #[macro_export]
 macro_rules! format_runtime_string {
diff --git a/substrate/primitives/runtime/src/testing.rs b/substrate/primitives/runtime/src/testing.rs
index 60dc54e09534f18d42777fef07a51db0dd4f578c..781f342d43c1e1c8ba5c2f31c3127c0ad799ed65 100644
--- a/substrate/primitives/runtime/src/testing.rs
+++ b/substrate/primitives/runtime/src/testing.rs
@@ -20,6 +20,7 @@
 use crate::{
 	codec::{Codec, Decode, Encode},
 	generic,
+	scale_info::TypeInfo,
 	traits::{
 		self, Applyable, BlakeTwo256, Checkable, DispatchInfoOf, Dispatchable, OpaqueKeys,
 		PostDispatchInfoOf, SignedExtension, ValidateUnsigned,
@@ -58,6 +59,7 @@ use std::{
 	Deserialize,
 	PartialOrd,
 	Ord,
+	TypeInfo,
 )]
 pub struct UintAuthorityId(pub u64);
 
@@ -167,7 +169,7 @@ impl traits::IdentifyAccount for UintAuthorityId {
 }
 
 /// A dummy signature type, to match `UintAuthorityId`.
-#[derive(Eq, PartialEq, Clone, Debug, Hash, Serialize, Deserialize, Encode, Decode)]
+#[derive(Eq, PartialEq, Clone, Debug, Hash, Serialize, Deserialize, Encode, Decode, TypeInfo)]
 pub struct TestSignature(pub u64, pub Vec<u8>);
 
 impl traits::Verify for TestSignature {
@@ -288,7 +290,7 @@ where
 /// with index only used if sender is some.
 ///
 /// If sender is some then the transaction is signed otherwise it is unsigned.
-#[derive(PartialEq, Eq, Clone, Encode, Decode)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)]
 pub struct TestXt<Call, Extra> {
 	/// Signature of the extrinsic.
 	pub signature: Option<(u64, Extra)>,
diff --git a/substrate/primitives/runtime/src/traits.rs b/substrate/primitives/runtime/src/traits.rs
index 312a9f6331bf108847ce95d54a5f3ec72a33efb7..65c063fde169614d028159f67b26510dcd490a76 100644
--- a/substrate/primitives/runtime/src/traits.rs
+++ b/substrate/primitives/runtime/src/traits.rs
@@ -20,6 +20,7 @@
 use crate::{
 	codec::{Codec, Decode, Encode, MaxEncodedLen},
 	generic::{Digest, DigestItem},
+	scale_info::{MetaType, StaticTypeInfo, TypeInfo},
 	transaction_validity::{
 		TransactionSource, TransactionValidity, TransactionValidityError, UnknownTransaction,
 		ValidTransaction,
@@ -210,7 +211,7 @@ pub trait Lookup {
 /// context.
 pub trait StaticLookup {
 	/// Type to lookup from.
-	type Source: Codec + Clone + PartialEq + Debug;
+	type Source: Codec + Clone + PartialEq + Debug + TypeInfo;
 	/// Type to lookup into.
 	type Target;
 	/// Attempt a lookup.
@@ -222,7 +223,7 @@ pub trait StaticLookup {
 /// A lookup implementation returning the input value.
 #[derive(Default)]
 pub struct IdentityLookup<T>(PhantomData<T>);
-impl<T: Codec + Clone + PartialEq + Debug> StaticLookup for IdentityLookup<T> {
+impl<T: Codec + Clone + PartialEq + Debug + TypeInfo> StaticLookup for IdentityLookup<T> {
 	type Source = T;
 	type Target = T;
 	fn lookup(x: T) -> Result<T, LookupError> {
@@ -247,7 +248,7 @@ impl<AccountId, AccountIndex> StaticLookup for AccountIdLookup<AccountId, Accoun
 where
 	AccountId: Codec + Clone + PartialEq + Debug,
 	AccountIndex: Codec + Clone + PartialEq + Debug,
-	crate::MultiAddress<AccountId, AccountIndex>: Codec,
+	crate::MultiAddress<AccountId, AccountIndex>: Codec + StaticTypeInfo,
 {
 	type Source = crate::MultiAddress<AccountId, AccountIndex>;
 	type Target = AccountId;
@@ -444,7 +445,8 @@ pub trait Hash:
 		+ Default
 		+ Encode
 		+ Decode
-		+ MaxEncodedLen;
+		+ MaxEncodedLen
+		+ TypeInfo;
 
 	/// Produce the hash of some byte-slice.
 	fn hash(s: &[u8]) -> Self::Output {
@@ -464,7 +466,7 @@ pub trait Hash:
 }
 
 /// Blake2-256 Hash implementation.
-#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub struct BlakeTwo256;
 
@@ -491,7 +493,7 @@ impl Hash for BlakeTwo256 {
 }
 
 /// Keccak-256 Hash implementation.
-#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
+#[derive(PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub struct Keccak256;
 
@@ -629,7 +631,8 @@ pub trait Header:
 		+ Codec
 		+ AsRef<[u8]>
 		+ AsMut<[u8]>
-		+ MaybeMallocSizeOf;
+		+ MaybeMallocSizeOf
+		+ TypeInfo;
 	/// Hashing algorithm
 	type Hashing: Hash<Output = Self::Hash>;
 
@@ -697,7 +700,8 @@ pub trait Block:
 		+ Codec
 		+ AsRef<[u8]>
 		+ AsMut<[u8]>
-		+ MaybeMallocSizeOf;
+		+ MaybeMallocSizeOf
+		+ TypeInfo;
 
 	/// Returns a reference to the header.
 	fn header(&self) -> &Self::Header;
@@ -833,7 +837,9 @@ impl Dispatchable for () {
 
 /// Means by which a transaction may be extended. This type embodies both the data and the logic
 /// that should be additionally associated with the transaction. It should be plain old data.
-pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq {
+pub trait SignedExtension:
+	Codec + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo
+{
 	/// Unique identifier of this signed extension.
 	///
 	/// This will be exposed in the metadata to identify the signed extension used
@@ -848,7 +854,7 @@ pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq
 
 	/// Any additional data that will go into the signed payload. This may be created dynamically
 	/// from the transaction using the `additional_signed` function.
-	type AdditionalSigned: Encode;
+	type AdditionalSigned: Encode + TypeInfo;
 
 	/// The type that encodes information that can be passed from pre_dispatch to post-dispatch.
 	type Pre: Default;
@@ -953,18 +959,33 @@ pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq
 		Ok(())
 	}
 
-	/// Returns the list of unique identifier for this signed extension.
+	/// Returns the metadata for this signed extension.
 	///
 	/// As a [`SignedExtension`] can be a tuple of [`SignedExtension`]s we need to return a `Vec`
-	/// that holds all the unique identifiers. Each individual `SignedExtension` must return
-	/// *exactly* one identifier.
+	/// that holds the metadata of each one. Each individual `SignedExtension` must return
+	/// *exactly* one [`SignedExtensionMetadata`].
 	///
-	/// This method provides a default implementation that returns `vec![SELF::IDENTIFIER]`.
-	fn identifier() -> Vec<&'static str> {
-		sp_std::vec![Self::IDENTIFIER]
+	/// This method provides a default implementation that returns a vec containing a single
+	/// [`SignedExtensionMetadata`].
+	fn metadata() -> Vec<SignedExtensionMetadata> {
+		sp_std::vec![SignedExtensionMetadata {
+			identifier: Self::IDENTIFIER,
+			ty: scale_info::meta_type::<Self>(),
+			additional_signed: scale_info::meta_type::<Self::AdditionalSigned>()
+		}]
 	}
 }
 
+/// Information about a [`SignedExtension`] for the runtime metadata.
+pub struct SignedExtensionMetadata {
+	/// The unique identifier of the [`SignedExtension`].
+	pub identifier: &'static str,
+	/// The type of the [`SignedExtension`].
+	pub ty: MetaType,
+	/// The type of the [`SignedExtension`] additional signed data for the payload.
+	pub additional_signed: MetaType,
+}
+
 #[impl_for_tuples(1, 12)]
 impl<AccountId, Call: Dispatchable> SignedExtension for Tuple {
 	for_tuples!( where #( Tuple: SignedExtension<AccountId=AccountId, Call=Call,> )* );
@@ -1029,9 +1050,9 @@ impl<AccountId, Call: Dispatchable> SignedExtension for Tuple {
 		Ok(())
 	}
 
-	fn identifier() -> Vec<&'static str> {
+	fn metadata() -> Vec<SignedExtensionMetadata> {
 		let mut ids = Vec::new();
-		for_tuples!( #( ids.extend(Tuple::identifier()); )* );
+		for_tuples!( #( ids.extend(Tuple::metadata()); )* );
 		ids
 	}
 }
@@ -1305,6 +1326,7 @@ macro_rules! impl_opaque_keys_inner {
 			Default, Clone, PartialEq, Eq,
 			$crate::codec::Encode,
 			$crate::codec::Decode,
+			$crate::scale_info::TypeInfo,
 			$crate::RuntimeDebug,
 		)]
 		pub struct $name {
diff --git a/substrate/primitives/session/Cargo.toml b/substrate/primitives/session/Cargo.toml
index 91677b474d9541380b73f212fe0f79a232a1c61c..8e1e2464e49ecd62d972fe942d8ee6f62fe5f596 100644
--- a/substrate/primitives/session/Cargo.toml
+++ b/substrate/primitives/session/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-api = { version = "4.0.0-dev", default-features = false, path = "../api" }
 sp-core = { version = "4.0.0-dev", default-features = false, path = "../core" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
@@ -24,6 +25,7 @@ sp-runtime = { version = "4.0.0-dev", optional = true, path = "../runtime" }
 default = [ "std" ]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-api/std",
 	"sp-core/std",
 	"sp-std/std",
diff --git a/substrate/primitives/session/src/lib.rs b/substrate/primitives/session/src/lib.rs
index 22d6b0b4a5920591c0d298d40a120e49d82d0fd5..d85b6af4349e4716a9fc14b802c450ea3978cdfd 100644
--- a/substrate/primitives/session/src/lib.rs
+++ b/substrate/primitives/session/src/lib.rs
@@ -53,7 +53,7 @@ sp_api::decl_runtime_apis! {
 pub type ValidatorCount = u32;
 
 /// Proof of membership of a specific key in a given session.
-#[derive(Encode, Decode, Clone, Eq, PartialEq, Default, RuntimeDebug)]
+#[derive(Encode, Decode, Clone, Eq, PartialEq, Default, RuntimeDebug, scale_info::TypeInfo)]
 pub struct MembershipProof {
 	/// The session index on which the specific key is a member.
 	pub session: SessionIndex,
diff --git a/substrate/primitives/staking/Cargo.toml b/substrate/primitives/staking/Cargo.toml
index 85f5487da884cf461ebff8d6eee355106ec675a8..9e852319ede42c03fb5fe6fcc60c513784c8037f 100644
--- a/substrate/primitives/staking/Cargo.toml
+++ b/substrate/primitives/staking/Cargo.toml
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 
@@ -21,6 +22,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 default = ["std"]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-runtime/std",
 	"sp-std/std",
 ]
diff --git a/substrate/primitives/staking/src/offence.rs b/substrate/primitives/staking/src/offence.rs
index b9afda41c5e7788a925eb02ffd382340c038104b..a91cb47c117b675e324b3d812155b34eb773d451 100644
--- a/substrate/primitives/staking/src/offence.rs
+++ b/substrate/primitives/staking/src/offence.rs
@@ -170,7 +170,7 @@ impl<Reporter, Offender, Res: Default> OnOffenceHandler<Reporter, Offender, Res>
 }
 
 /// A details about an offending authority for a particular kind of offence.
-#[derive(Clone, PartialEq, Eq, Encode, Decode, sp_runtime::RuntimeDebug)]
+#[derive(Clone, PartialEq, Eq, Encode, Decode, sp_runtime::RuntimeDebug, scale_info::TypeInfo)]
 pub struct OffenceDetails<Reporter, Offender> {
 	/// The offending authority id
 	pub offender: Offender,
diff --git a/substrate/primitives/transaction-storage-proof/Cargo.toml b/substrate/primitives/transaction-storage-proof/Cargo.toml
index 0b5065be8219f5f24f47fadb1038989d88cdb322..8a41105b20b74ab29a6821865583e7e5e1fade12 100644
--- a/substrate/primitives/transaction-storage-proof/Cargo.toml
+++ b/substrate/primitives/transaction-storage-proof/Cargo.toml
@@ -19,6 +19,7 @@ sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 sp-trie = { version = "4.0.0-dev", optional = true, path = "../trie" }
 sp-core = { version = "4.0.0-dev", path = "../core", optional = true }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 log = { version = "0.4.8", optional = true }
 async-trait = { version = "0.1.50", optional = true }
 
@@ -26,6 +27,7 @@ async-trait = { version = "0.1.50", optional = true }
 default = [ "std" ]
 std = [
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-inherents/std",
 	"sp-runtime/std",
diff --git a/substrate/primitives/transaction-storage-proof/src/lib.rs b/substrate/primitives/transaction-storage-proof/src/lib.rs
index d159aa735c2666c0a4b238b64ac56fb5732ba616..4b01a8d45d4541526ad00f7f521a7f7a04090ff7 100644
--- a/substrate/primitives/transaction-storage-proof/src/lib.rs
+++ b/substrate/primitives/transaction-storage-proof/src/lib.rs
@@ -51,7 +51,7 @@ impl IsFatalError for InherentError {
 
 /// Holds a chunk of data retrieved from storage along with
 /// a proof that the data was stored at that location in the trie.
-#[derive(Encode, Decode, Clone, PartialEq, Debug)]
+#[derive(Encode, Decode, Clone, PartialEq, Debug, scale_info::TypeInfo)]
 pub struct TransactionStorageProof {
 	/// Data chunk that is proved to exist.
 	pub chunk: Vec<u8>,
diff --git a/substrate/primitives/trie/Cargo.toml b/substrate/primitives/trie/Cargo.toml
index 60356e0a8d6d35fcbf194ea7a0bd590035e7138d..5a2de4f16f9a4b58c00b3e3bac2fe669a94626e4 100644
--- a/substrate/primitives/trie/Cargo.toml
+++ b/substrate/primitives/trie/Cargo.toml
@@ -19,6 +19,7 @@ harness = false
 
 [dependencies]
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 hash-db = { version = "0.15.2", default-features = false }
 trie-db = { version = "0.22.6", default-features = false }
@@ -38,6 +39,7 @@ default = ["std"]
 std = [
 	"sp-std/std",
 	"codec/std",
+	"scale-info/std",
 	"hash-db/std",
 	"memory-db/std",
 	"trie-db/std",
diff --git a/substrate/primitives/trie/src/storage_proof.rs b/substrate/primitives/trie/src/storage_proof.rs
index 410ad44e75a63694cb56bcc256f8c624f4a25cde..cfdb8566ea75f48ff7524ab9f3095eb353553ed8 100644
--- a/substrate/primitives/trie/src/storage_proof.rs
+++ b/substrate/primitives/trie/src/storage_proof.rs
@@ -17,6 +17,7 @@
 
 use codec::{Decode, Encode};
 use hash_db::{HashDB, Hasher};
+use scale_info::TypeInfo;
 use sp_std::vec::Vec;
 
 /// A proof that some set of key-value pairs are included in the storage trie. The proof contains
@@ -26,13 +27,13 @@ use sp_std::vec::Vec;
 /// The proof consists of the set of serialized nodes in the storage trie accessed when looking up
 /// the keys covered by the proof. Verifying the proof requires constructing the partial trie from
 /// the serialized nodes and performing the key lookups.
-#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
+#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)]
 pub struct StorageProof {
 	trie_nodes: Vec<Vec<u8>>,
 }
 
 /// Storage proof in compact form.
-#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
+#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)]
 pub struct CompactProof {
 	pub encoded_nodes: Vec<Vec<u8>>,
 }
diff --git a/substrate/primitives/version/Cargo.toml b/substrate/primitives/version/Cargo.toml
index 1cd3e7c724750f64b3f3c192304e59265ada2bde..fcab1eeabcaf4a863ab5f6f0c93d1931d107a391 100644
--- a/substrate/primitives/version/Cargo.toml
+++ b/substrate/primitives/version/Cargo.toml
@@ -18,6 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 impl-serde = { version = "0.3.1", optional = true }
 serde = { version = "1.0.126", optional = true, features = ["derive"] }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-std = { version = "4.0.0-dev", default-features = false, path = "../std" }
 sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../runtime" }
 sp-version-proc-macro = { version = "4.0.0-dev", default-features = false, path = "proc-macro" }
@@ -30,6 +31,7 @@ std = [
 	"impl-serde",
 	"serde",
 	"codec/std",
+	"scale-info/std",
 	"sp-std/std",
 	"sp-runtime/std",
 	"parity-wasm",
diff --git a/substrate/primitives/version/src/lib.rs b/substrate/primitives/version/src/lib.rs
index 65b22436a5ba18c5033e85e3cd54643f513721d3..58216bc494dd719d0a87fa3afe68179bb1f53340 100644
--- a/substrate/primitives/version/src/lib.rs
+++ b/substrate/primitives/version/src/lib.rs
@@ -27,6 +27,7 @@ use std::collections::HashSet;
 use std::fmt;
 
 use codec::{Decode, Encode};
+use scale_info::TypeInfo;
 pub use sp_runtime::create_runtime_str;
 use sp_runtime::RuntimeString;
 #[doc(hidden)]
@@ -123,7 +124,7 @@ macro_rules! create_apis_vec {
 /// In particular: bug fixes should result in an increment of `spec_version` and possibly
 /// `authoring_version`, absolutely not `impl_version` since they change the semantics of the
 /// runtime.
-#[derive(Clone, PartialEq, Eq, Encode, Decode, Default, sp_runtime::RuntimeDebug)]
+#[derive(Clone, PartialEq, Eq, Encode, Decode, Default, sp_runtime::RuntimeDebug, TypeInfo)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
 pub struct RuntimeVersion {
diff --git a/substrate/test-utils/runtime/Cargo.toml b/substrate/test-utils/runtime/Cargo.toml
index cc57f12ea31a3d9779cfa050bd6a213d11411cd8..24f4d404c18bde1b613e15bb2cbeadfc856d36cf 100644
--- a/substrate/test-utils/runtime/Cargo.toml
+++ b/substrate/test-utils/runtime/Cargo.toml
@@ -18,6 +18,7 @@ sp-consensus-aura = { version = "0.10.0-dev", default-features = false, path = "
 sp-consensus-babe = { version = "0.10.0-dev", default-features = false, path = "../../primitives/consensus/babe" }
 sp-block-builder = { version = "4.0.0-dev", default-features = false, path = "../../primitives/block-builder" }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
 sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" }
 sp-keyring = { version = "4.0.0-dev", optional = true, path = "../../primitives/keyring" }
 memory-db = { version = "0.27.0", default-features = false }
@@ -69,6 +70,7 @@ std = [
 	"sp-consensus-babe/std",
 	"sp-block-builder/std",
 	"codec/std",
+	"scale-info/std",
 	"sp-inherents/std",
 	"sp-keyring",
 	"log/std",
diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs
index bdb87241208130f6e4398225a0ede589fc203c15..0d880d508ef38c5eeccd9af32b205d9c83aee7a8 100644
--- a/substrate/test-utils/runtime/src/lib.rs
+++ b/substrate/test-utils/runtime/src/lib.rs
@@ -24,6 +24,7 @@ pub mod genesismap;
 pub mod system;
 
 use codec::{Decode, Encode, Error, Input};
+use scale_info::TypeInfo;
 use sp_std::{marker::PhantomData, prelude::*};
 
 use sp_application_crypto::{ecdsa, ed25519, sr25519, RuntimeAppPublic};
@@ -415,7 +416,7 @@ cfg_if! {
 	}
 }
 
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone, Eq, PartialEq, TypeInfo)]
 pub struct Runtime;
 
 impl GetNodeBlockType for Runtime {
@@ -483,7 +484,7 @@ impl frame_support::traits::OriginTrait for Origin {
 	}
 }
 
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)]
+#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
 pub struct Event;
 
 impl From<frame_system::Event<Runtime>> for Event {
diff --git a/substrate/utils/frame/rpc/support/Cargo.toml b/substrate/utils/frame/rpc/support/Cargo.toml
index aa9f1bbef8024e2eb50fc1a880df0007c76867df..a94f18d0e89253cf5f0bf437921a5b3e39983d00 100644
--- a/substrate/utils/frame/rpc/support/Cargo.toml
+++ b/substrate/utils/frame/rpc/support/Cargo.toml
@@ -25,4 +25,5 @@ sc-rpc-api = { version = "0.10.0-dev", path = "../../../../client/rpc-api" }
 
 [dev-dependencies]
 frame-system = { version = "4.0.0-dev", path = "../../../../frame/system" }
+scale-info = "1.0"
 tokio = "1.10"