diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock
index 39cb42be7a857660e99892c081e91709fb05c005..a8092fffa7c07b8b5357a1e3b6f5024d07c7411d 100644
--- a/substrate/Cargo.lock
+++ b/substrate/Cargo.lock
@@ -520,7 +520,6 @@ version = "4.0.0-dev"
 dependencies = [
  "beefy-gadget",
  "beefy-primitives",
- "derive_more",
  "futures 0.3.16",
  "jsonrpc-core",
  "jsonrpc-core-client",
@@ -4710,7 +4709,6 @@ name = "node-inspect"
 version = "0.9.0-dev"
 dependencies = [
  "clap 3.0.7",
- "derive_more",
  "parity-scale-codec",
  "sc-cli",
  "sc-client-api",
@@ -4719,6 +4717,7 @@ dependencies = [
  "sp-blockchain",
  "sp-core",
  "sp-runtime",
+ "thiserror",
 ]
 
 [[package]]
@@ -7647,7 +7646,6 @@ name = "sc-authority-discovery"
 version = "0.10.0-dev"
 dependencies = [
  "async-trait",
- "derive_more",
  "futures 0.3.16",
  "futures-timer",
  "ip_network",
@@ -7669,6 +7667,7 @@ dependencies = [
  "sp-tracing",
  "substrate-prometheus-endpoint",
  "substrate-test-runtime-client",
+ "thiserror",
 ]
 
 [[package]]
@@ -7863,7 +7862,6 @@ name = "sc-consensus-aura"
 version = "0.10.0-dev"
 dependencies = [
  "async-trait",
- "derive_more",
  "futures 0.3.16",
  "getrandom 0.2.3",
  "log 0.4.14",
@@ -7894,6 +7892,7 @@ dependencies = [
  "substrate-prometheus-endpoint",
  "substrate-test-runtime-client",
  "tempfile",
+ "thiserror",
 ]
 
 [[package]]
@@ -7901,7 +7900,6 @@ name = "sc-consensus-babe"
 version = "0.10.0-dev"
 dependencies = [
  "async-trait",
- "derive_more",
  "fork-tree",
  "futures 0.3.16",
  "log 0.4.14",
@@ -7944,13 +7942,13 @@ dependencies = [
  "substrate-prometheus-endpoint",
  "substrate-test-runtime-client",
  "tempfile",
+ "thiserror",
 ]
 
 [[package]]
 name = "sc-consensus-babe-rpc"
 version = "0.10.0-dev"
 dependencies = [
- "derive_more",
  "futures 0.3.16",
  "jsonrpc-core",
  "jsonrpc-core-client",
@@ -7973,6 +7971,7 @@ dependencies = [
  "sp-runtime",
  "substrate-test-runtime-client",
  "tempfile",
+ "thiserror",
 ]
 
 [[package]]
@@ -7993,7 +7992,6 @@ version = "0.10.0-dev"
 dependencies = [
  "assert_matches",
  "async-trait",
- "derive_more",
  "futures 0.3.16",
  "jsonrpc-core",
  "jsonrpc-core-client",
@@ -8023,6 +8021,7 @@ dependencies = [
  "substrate-prometheus-endpoint",
  "substrate-test-runtime-client",
  "substrate-test-runtime-transaction-pool",
+ "thiserror",
  "tokio",
 ]
 
@@ -8031,7 +8030,6 @@ name = "sc-consensus-pow"
 version = "0.10.0-dev"
 dependencies = [
  "async-trait",
- "derive_more",
  "futures 0.3.16",
  "futures-timer",
  "log 0.4.14",
@@ -8048,6 +8046,7 @@ dependencies = [
  "sp-inherents",
  "sp-runtime",
  "substrate-prometheus-endpoint",
+ "thiserror",
 ]
 
 [[package]]
@@ -8128,7 +8127,6 @@ dependencies = [
 name = "sc-executor-common"
 version = "0.10.0-dev"
 dependencies = [
- "derive_more",
  "environmental",
  "parity-scale-codec",
  "sc-allocator",
@@ -8184,7 +8182,6 @@ version = "0.10.0-dev"
 dependencies = [
  "assert_matches",
  "async-trait",
- "derive_more",
  "dyn-clone",
  "finality-grandpa",
  "fork-tree",
@@ -8219,6 +8216,7 @@ dependencies = [
  "substrate-prometheus-endpoint",
  "substrate-test-runtime-client",
  "tempfile",
+ "thiserror",
  "tokio",
 ]
 
@@ -8226,7 +8224,6 @@ dependencies = [
 name = "sc-finality-grandpa-rpc"
 version = "0.10.0-dev"
 dependencies = [
- "derive_more",
  "finality-grandpa",
  "futures 0.3.16",
  "jsonrpc-core",
@@ -8247,6 +8244,7 @@ dependencies = [
  "sp-keyring",
  "sp-runtime",
  "substrate-test-runtime-client",
+ "thiserror",
 ]
 
 [[package]]
@@ -8270,7 +8268,6 @@ name = "sc-keystore"
 version = "4.0.0-dev"
 dependencies = [
  "async-trait",
- "derive_more",
  "hex",
  "parking_lot 0.11.2",
  "serde_json",
@@ -8278,6 +8275,7 @@ dependencies = [
  "sp-core",
  "sp-keystore",
  "tempfile",
+ "thiserror",
 ]
 
 [[package]]
@@ -8291,7 +8289,6 @@ dependencies = [
  "bitflags",
  "bytes 1.1.0",
  "cid",
- "derive_more",
  "either",
  "fnv",
  "fork-tree",
@@ -8762,7 +8759,6 @@ dependencies = [
 name = "sc-transaction-pool-api"
 version = "4.0.0-dev"
 dependencies = [
- "derive_more",
  "futures 0.3.16",
  "log 0.4.14",
  "serde",
@@ -9632,7 +9628,6 @@ name = "sp-keystore"
 version = "0.10.0"
 dependencies = [
  "async-trait",
- "derive_more",
  "futures 0.3.16",
  "merlin",
  "parity-scale-codec",
@@ -9643,6 +9638,7 @@ dependencies = [
  "serde",
  "sp-core",
  "sp-externalities",
+ "thiserror",
 ]
 
 [[package]]
@@ -10211,11 +10207,11 @@ name = "substrate-prometheus-endpoint"
 version = "0.10.0-dev"
 dependencies = [
  "async-std",
- "derive_more",
  "futures-util",
  "hyper 0.14.16",
  "log 0.4.14",
  "prometheus",
+ "thiserror",
  "tokio",
 ]
 
@@ -10312,7 +10308,6 @@ dependencies = [
 name = "substrate-test-runtime-transaction-pool"
 version = "2.0.0"
 dependencies = [
- "derive_more",
  "futures 0.3.16",
  "parity-scale-codec",
  "parking_lot 0.11.2",
@@ -10321,6 +10316,7 @@ dependencies = [
  "sp-blockchain",
  "sp-runtime",
  "substrate-test-runtime-client",
+ "thiserror",
 ]
 
 [[package]]
diff --git a/substrate/bin/node/inspect/Cargo.toml b/substrate/bin/node/inspect/Cargo.toml
index 49470a7e7b058a5b70c4184450d221ebe76283a8..bb9af8c66988e8129964fdd892d95ac3efc44445 100644
--- a/substrate/bin/node/inspect/Cargo.toml
+++ b/substrate/bin/node/inspect/Cargo.toml
@@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 clap = { version = "3.0", features = ["derive"] }
 codec = { package = "parity-scale-codec", version = "2.0.0" }
-derive_more = "0.99"
+thiserror = "1.0"
 sc-cli = { version = "0.10.0-dev", path = "../../../client/cli" }
 sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" }
 sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" }
diff --git a/substrate/bin/node/inspect/src/lib.rs b/substrate/bin/node/inspect/src/lib.rs
index ff1eecd219a97ee66abd2213fec83b8aca9b1b99..b37c5aa7ca2e8ebbb04d00b596e2bbe6e078a611 100644
--- a/substrate/bin/node/inspect/src/lib.rs
+++ b/substrate/bin/node/inspect/src/lib.rs
@@ -78,26 +78,19 @@ impl<TBlock: Block> PrettyPrinter<TBlock> for DebugPrinter {
 }
 
 /// Aggregated error for `Inspector` operations.
-#[derive(Debug, derive_more::From, derive_more::Display)]
+#[derive(Debug, thiserror::Error)]
 pub enum Error {
 	/// Could not decode Block or Extrinsic.
-	Codec(codec::Error),
+	#[error(transparent)]
+	Codec(#[from] codec::Error),
 	/// Error accessing blockchain DB.
-	Blockchain(sp_blockchain::Error),
+	#[error(transparent)]
+	Blockchain(#[from] sp_blockchain::Error),
 	/// Given block has not been found.
+	#[error("{0}")]
 	NotFound(String),
 }
 
-impl std::error::Error for Error {
-	fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-		match *self {
-			Self::Codec(ref e) => Some(e),
-			Self::Blockchain(ref e) => Some(e),
-			Self::NotFound(_) => None,
-		}
-	}
-}
-
 /// A helper trait to access block headers and bodies.
 pub trait ChainAccess<TBlock: Block>: HeaderBackend<TBlock> + BlockBackend<TBlock> {}
 
diff --git a/substrate/client/authority-discovery/Cargo.toml b/substrate/client/authority-discovery/Cargo.toml
index c6c523fa5eec7e2a3e143a156cc7779095f7d8ac..ec43112a714506734601958832234f10a3401972 100644
--- a/substrate/client/authority-discovery/Cargo.toml
+++ b/substrate/client/authority-discovery/Cargo.toml
@@ -19,7 +19,7 @@ prost-build = "0.9"
 [dependencies]
 async-trait = "0.1"
 codec = { package = "parity-scale-codec", default-features = false, version = "2.0.0" }
-derive_more = "0.99.16"
+thiserror = "1.0"
 futures = "0.3.9"
 futures-timer = "3.0.1"
 ip_network = "0.4.1"
diff --git a/substrate/client/authority-discovery/src/error.rs b/substrate/client/authority-discovery/src/error.rs
index 26ee02ef85321a6e6c3aeb6d1e4bb5a7c1841235..bad53e905cb93772913c9daac2e7a6cbf799217a 100644
--- a/substrate/client/authority-discovery/src/error.rs
+++ b/substrate/client/authority-discovery/src/error.rs
@@ -24,40 +24,56 @@ use sp_core::crypto::CryptoTypePublicPair;
 pub type Result<T> = std::result::Result<T, Error>;
 
 /// Error type for the authority discovery module.
-#[derive(Debug, derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 pub enum Error {
-	/// Received dht value found event with records with different keys.
+	#[error("Received dht value found event with records with different keys.")]
 	ReceivingDhtValueFoundEventWithDifferentKeys,
-	/// Received dht value found event with no records.
+
+	#[error("Received dht value found event with no records.")]
 	ReceivingDhtValueFoundEventWithNoRecords,
-	/// Failed to verify a dht payload with the given signature.
+
+	#[error("Failed to verify a dht payload with the given signature.")]
 	VerifyingDhtPayload,
-	/// Failed to hash the authority id to be used as a dht key.
-	HashingAuthorityId(libp2p::core::multiaddr::multihash::Error),
-	/// Failed calling into the Substrate runtime.
-	CallingRuntime(sp_blockchain::Error),
-	/// Received a dht record with a key that does not match any in-flight awaited keys.
+
+	#[error("Failed to hash the authority id to be used as a dht key.")]
+	HashingAuthorityId(#[from] libp2p::core::multiaddr::multihash::Error),
+
+	#[error("Failed calling into the Substrate runtime.")]
+	CallingRuntime(#[from] sp_blockchain::Error),
+
+	#[error("Received a dht record with a key that does not match any in-flight awaited keys.")]
 	ReceivingUnexpectedRecord,
-	/// Failed to encode a protobuf payload.
-	EncodingProto(prost::EncodeError),
-	/// Failed to decode a protobuf payload.
-	DecodingProto(prost::DecodeError),
-	/// Failed to encode or decode scale payload.
-	EncodingDecodingScale(codec::Error),
-	/// Failed to parse a libp2p multi address.
-	ParsingMultiaddress(libp2p::core::multiaddr::Error),
-	/// Failed to parse a libp2p key.
-	ParsingLibp2pIdentity(sc_network::DecodingError),
-	/// Failed to sign using a specific public key.
+
+	#[error("Failed to encode a protobuf payload.")]
+	EncodingProto(#[from] prost::EncodeError),
+
+	#[error("Failed to decode a protobuf payload.")]
+	DecodingProto(#[from] prost::DecodeError),
+
+	#[error("Failed to encode or decode scale payload.")]
+	EncodingDecodingScale(#[from] codec::Error),
+
+	#[error("Failed to parse a libp2p multi address.")]
+	ParsingMultiaddress(#[from] libp2p::core::multiaddr::Error),
+
+	#[error("Failed to parse a libp2p key.")]
+	ParsingLibp2pIdentity(#[from] sc_network::DecodingError),
+
+	#[error("Failed to sign using a specific public key.")]
 	MissingSignature(CryptoTypePublicPair),
-	/// Failed to sign using all public keys.
+
+	#[error("Failed to sign using all public keys.")]
 	Signing,
-	/// Failed to register Prometheus metric.
-	Prometheus(prometheus_endpoint::PrometheusError),
-	/// Received authority record that contains addresses with multiple peer ids
+
+	#[error("Failed to register Prometheus metric.")]
+	Prometheus(#[from] prometheus_endpoint::PrometheusError),
+
+	#[error("Received authority record that contains addresses with multiple peer ids")]
 	ReceivingDhtValueFoundEventWithDifferentPeerIds,
-	/// Received authority record without any addresses having a peer id
+
+	#[error("Received authority record without any addresses having a peer id")]
 	ReceivingDhtValueFoundEventWithNoPeerIds,
-	/// Received authority record without a valid signature for the remote peer id.
+
+	#[error("Received authority record without a valid signature for the remote peer id.")]
 	MissingPeerIdSignature,
 }
diff --git a/substrate/client/beefy/rpc/Cargo.toml b/substrate/client/beefy/rpc/Cargo.toml
index a72af62fdeeacfd01dcb891144d9fbe04d0e8429..444f1ff4aaf9edef9e1560509b96d063a83f8489 100644
--- a/substrate/client/beefy/rpc/Cargo.toml
+++ b/substrate/client/beefy/rpc/Cargo.toml
@@ -8,7 +8,6 @@ repository = "https://github.com/paritytech/substrate"
 description = "RPC for the BEEFY Client gadget for substrate"
 
 [dependencies]
-derive_more = "0.99"
 futures = "0.3.16"
 log = "0.4"
 parking_lot = "0.11"
diff --git a/substrate/client/beefy/rpc/src/lib.rs b/substrate/client/beefy/rpc/src/lib.rs
index dc9ee8b94701b72729dc4daaa101433a49a40df1..4c1bc03e222e7093cd402517c3c7a306805a0583 100644
--- a/substrate/client/beefy/rpc/src/lib.rs
+++ b/substrate/client/beefy/rpc/src/lib.rs
@@ -36,15 +36,15 @@ mod notification;
 
 type FutureResult<T> = jsonrpc_core::BoxFuture<Result<T, jsonrpc_core::Error>>;
 
-#[derive(Debug, derive_more::Display, derive_more::From, thiserror::Error)]
+#[derive(Debug, thiserror::Error)]
 /// Top-level error type for the RPC handler
 pub enum Error {
 	/// The BEEFY RPC endpoint is not ready.
-	#[display(fmt = "BEEFY RPC endpoint not ready")]
+	#[error("BEEFY RPC endpoint not ready")]
 	EndpointNotReady,
 	/// The BEEFY RPC background task failed to spawn.
-	#[display(fmt = "BEEFY RPC background task failed to spawn")]
-	RpcTaskFailure(SpawnError),
+	#[error("BEEFY RPC background task failed to spawn")]
+	RpcTaskFailure(#[from] SpawnError),
 }
 
 /// The error codes returned by jsonrpc.
diff --git a/substrate/client/consensus/aura/Cargo.toml b/substrate/client/consensus/aura/Cargo.toml
index 97409c5944dbb06a96e3ee94f55584c2051e207d..bcae7648ce2e86bc5c4476e99a65a314ae8c0b4f 100644
--- a/substrate/client/consensus/aura/Cargo.toml
+++ b/substrate/client/consensus/aura/Cargo.toml
@@ -22,7 +22,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" }
 sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" }
 sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" }
 sp-consensus-slots = { version = "0.10.0-dev", path = "../../../primitives/consensus/slots" }
-derive_more = "0.99.16"
+thiserror = "1.0"
 futures = "0.3.9"
 sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" }
 log = "0.4.8"
diff --git a/substrate/client/consensus/aura/src/lib.rs b/substrate/client/consensus/aura/src/lib.rs
index d7fe6131393827de62f3463e1f71831419bf8751..61c5610883149ac9f1c695c88128763671d30c04 100644
--- a/substrate/client/consensus/aura/src/lib.rs
+++ b/substrate/client/consensus/aura/src/lib.rs
@@ -491,33 +491,34 @@ fn aura_err<B: BlockT>(error: Error<B>) -> Error<B> {
 }
 
 /// Aura Errors
-#[derive(derive_more::Display, Debug)]
+#[derive(Debug, thiserror::Error)]
 pub enum Error<B: BlockT> {
 	/// Multiple Aura pre-runtime headers
-	#[display(fmt = "Multiple Aura pre-runtime headers")]
+	#[error("Multiple Aura pre-runtime headers")]
 	MultipleHeaders,
 	/// No Aura pre-runtime digest found
-	#[display(fmt = "No Aura pre-runtime digest found")]
+	#[error("No Aura pre-runtime digest found")]
 	NoDigestFound,
 	/// Header is unsealed
-	#[display(fmt = "Header {:?} is unsealed", _0)]
+	#[error("Header {0:?} is unsealed")]
 	HeaderUnsealed(B::Hash),
 	/// Header has a bad seal
-	#[display(fmt = "Header {:?} has a bad seal", _0)]
+	#[error("Header {0:?} has a bad seal")]
 	HeaderBadSeal(B::Hash),
 	/// Slot Author not found
-	#[display(fmt = "Slot Author not found")]
+	#[error("Slot Author not found")]
 	SlotAuthorNotFound,
 	/// Bad signature
-	#[display(fmt = "Bad signature on {:?}", _0)]
+	#[error("Bad signature on {0:?}")]
 	BadSignature(B::Hash),
 	/// Client Error
+	#[error(transparent)]
 	Client(sp_blockchain::Error),
 	/// Unknown inherent error for identifier
-	#[display(fmt = "Unknown inherent error for identifier: {}", "String::from_utf8_lossy(_0)")]
+	#[error("Unknown inherent error for identifier: {}", String::from_utf8_lossy(.0))]
 	UnknownInherentError(sp_inherents::InherentIdentifier),
-	#[display(fmt = "Inherent error: {}", _0)]
 	/// Inherents Error
+	#[error("Inherent error: {0}")]
 	Inherent(sp_inherents::Error),
 }
 
diff --git a/substrate/client/consensus/babe/Cargo.toml b/substrate/client/consensus/babe/Cargo.toml
index e4d66fcad87ccfda9664d04619af0999969a2d36..5dd029f0ad4a9f4f805bedd693d271882ba78ddc 100644
--- a/substrate/client/consensus/babe/Cargo.toml
+++ b/substrate/client/consensus/babe/Cargo.toml
@@ -49,7 +49,7 @@ log = "0.4.8"
 schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated"] }
 rand = "0.7.2"
 merlin = "2.0"
-derive_more = "0.99.16"
+thiserror = "1.0"
 retain_mut = "0.1.4"
 async-trait = "0.1.50"
 
diff --git a/substrate/client/consensus/babe/rpc/Cargo.toml b/substrate/client/consensus/babe/rpc/Cargo.toml
index 93be56b9d3601b04f59b4d586fc42af450b0a36f..4997cfdd1eec076e58b0cbf77031e3335c1eb8f1 100644
--- a/substrate/client/consensus/babe/rpc/Cargo.toml
+++ b/substrate/client/consensus/babe/rpc/Cargo.toml
@@ -19,12 +19,12 @@ jsonrpc-core = "18.0.0"
 jsonrpc-core-client = "18.0.0"
 jsonrpc-derive = "18.0.0"
 sp-consensus-babe = { version = "0.10.0-dev", path = "../../../../primitives/consensus/babe" }
-serde = { version = "1.0.132", features=["derive"] }
+serde = { version = "1.0.132", features = ["derive"] }
 sp-blockchain = { version = "4.0.0-dev", path = "../../../../primitives/blockchain" }
 sp-runtime = { version = "4.1.0-dev", path = "../../../../primitives/runtime" }
 sc-consensus-epochs = { version = "0.10.0-dev", path = "../../epochs" }
 futures = "0.3.16"
-derive_more = "0.99.16"
+thiserror = "1.0"
 sp-api = { version = "4.0.0-dev", path = "../../../../primitives/api" }
 sp-consensus = { version = "0.10.0-dev", path = "../../../../primitives/consensus/common" }
 sp-core = { version = "4.1.0-dev", path = "../../../../primitives/core" }
diff --git a/substrate/client/consensus/babe/rpc/src/lib.rs b/substrate/client/consensus/babe/rpc/src/lib.rs
index c9d2f9b76c2a2dc0524001a7d7176c14e931e6bb..462620f26e5bff35f4ff2cb7a01abb42ff336060 100644
--- a/substrate/client/consensus/babe/rpc/src/lib.rs
+++ b/substrate/client/consensus/babe/rpc/src/lib.rs
@@ -166,11 +166,13 @@ pub struct EpochAuthorship {
 }
 
 /// Errors encountered by the RPC
-#[derive(Debug, derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 pub enum Error {
 	/// Consensus error
-	Consensus(ConsensusError),
+	#[error(transparent)]
+	Consensus(#[from] ConsensusError),
 	/// Errors that can be formatted as a String
+	#[error("{0}")]
 	StringError(String),
 }
 
diff --git a/substrate/client/consensus/babe/src/lib.rs b/substrate/client/consensus/babe/src/lib.rs
index a86eac35a10001a25595b5f77f598aea1058e29c..3e9cf5aab649420ac88ff7a6601a7a65eefeb2b5 100644
--- a/substrate/client/consensus/babe/src/lib.rs
+++ b/substrate/client/consensus/babe/src/lib.rs
@@ -217,95 +217,94 @@ impl Epoch {
 }
 
 /// Errors encountered by the babe authorship task.
-#[derive(derive_more::Display, Debug)]
+#[derive(Debug, thiserror::Error)]
 pub enum Error<B: BlockT> {
 	/// Multiple BABE pre-runtime digests
-	#[display(fmt = "Multiple BABE pre-runtime digests, rejecting!")]
+	#[error("Multiple BABE pre-runtime digests, rejecting!")]
 	MultiplePreRuntimeDigests,
 	/// No BABE pre-runtime digest found
-	#[display(fmt = "No BABE pre-runtime digest found")]
+	#[error("No BABE pre-runtime digest found")]
 	NoPreRuntimeDigest,
 	/// Multiple BABE epoch change digests
-	#[display(fmt = "Multiple BABE epoch change digests, rejecting!")]
+	#[error("Multiple BABE epoch change digests, rejecting!")]
 	MultipleEpochChangeDigests,
 	/// Multiple BABE config change digests
-	#[display(fmt = "Multiple BABE config change digests, rejecting!")]
+	#[error("Multiple BABE config change digests, rejecting!")]
 	MultipleConfigChangeDigests,
 	/// Could not extract timestamp and slot
-	#[display(fmt = "Could not extract timestamp and slot: {:?}", _0)]
+	#[error("Could not extract timestamp and slot: {0:?}")]
 	Extraction(sp_consensus::Error),
 	/// Could not fetch epoch
-	#[display(fmt = "Could not fetch epoch at {:?}", _0)]
+	#[error("Could not fetch epoch at {0:?}")]
 	FetchEpoch(B::Hash),
 	/// Header rejected: too far in the future
-	#[display(fmt = "Header {:?} rejected: too far in the future", _0)]
+	#[error("Header {0:?} rejected: too far in the future")]
 	TooFarInFuture(B::Hash),
 	/// Parent unavailable. Cannot import
-	#[display(fmt = "Parent ({}) of {} unavailable. Cannot import", _0, _1)]
+	#[error("Parent ({0}) of {1} unavailable. Cannot import")]
 	ParentUnavailable(B::Hash, B::Hash),
 	/// Slot number must increase
-	#[display(fmt = "Slot number must increase: parent slot: {}, this slot: {}", _0, _1)]
+	#[error("Slot number must increase: parent slot: {0}, this slot: {1}")]
 	SlotMustIncrease(Slot, Slot),
 	/// Header has a bad seal
-	#[display(fmt = "Header {:?} has a bad seal", _0)]
+	#[error("Header {0:?} has a bad seal")]
 	HeaderBadSeal(B::Hash),
 	/// Header is unsealed
-	#[display(fmt = "Header {:?} is unsealed", _0)]
+	#[error("Header {0:?} is unsealed")]
 	HeaderUnsealed(B::Hash),
 	/// Slot author not found
-	#[display(fmt = "Slot author not found")]
+	#[error("Slot author not found")]
 	SlotAuthorNotFound,
 	/// Secondary slot assignments are disabled for the current epoch.
-	#[display(fmt = "Secondary slot assignments are disabled for the current epoch.")]
+	#[error("Secondary slot assignments are disabled for the current epoch.")]
 	SecondarySlotAssignmentsDisabled,
 	/// Bad signature
-	#[display(fmt = "Bad signature on {:?}", _0)]
+	#[error("Bad signature on {0:?}")]
 	BadSignature(B::Hash),
 	/// Invalid author: Expected secondary author
-	#[display(fmt = "Invalid author: Expected secondary author: {:?}, got: {:?}.", _0, _1)]
+	#[error("Invalid author: Expected secondary author: {0:?}, got: {1:?}.")]
 	InvalidAuthor(AuthorityId, AuthorityId),
 	/// No secondary author expected.
-	#[display(fmt = "No secondary author expected.")]
+	#[error("No secondary author expected.")]
 	NoSecondaryAuthorExpected,
 	/// VRF verification of block by author failed
-	#[display(
-		fmt = "VRF verification of block by author {:?} failed: threshold {} exceeded",
-		_0,
-		_1
-	)]
+	#[error("VRF verification of block by author {0:?} failed: threshold {1} exceeded")]
 	VRFVerificationOfBlockFailed(AuthorityId, u128),
 	/// VRF verification failed
-	#[display(fmt = "VRF verification failed: {:?}", _0)]
+	#[error("VRF verification failed: {0:?}")]
 	VRFVerificationFailed(SignatureError),
 	/// Could not fetch parent header
-	#[display(fmt = "Could not fetch parent header: {:?}", _0)]
+	#[error("Could not fetch parent header: {0:?}")]
 	FetchParentHeader(sp_blockchain::Error),
 	/// Expected epoch change to happen.
-	#[display(fmt = "Expected epoch change to happen at {:?}, s{}", _0, _1)]
+	#[error("Expected epoch change to happen at {0:?}, s{1}")]
 	ExpectedEpochChange(B::Hash, Slot),
 	/// Unexpected config change.
-	#[display(fmt = "Unexpected config change")]
+	#[error("Unexpected config change")]
 	UnexpectedConfigChange,
 	/// Unexpected epoch change
-	#[display(fmt = "Unexpected epoch change")]
+	#[error("Unexpected epoch change")]
 	UnexpectedEpochChange,
 	/// Parent block has no associated weight
-	#[display(fmt = "Parent block of {} has no associated weight", _0)]
+	#[error("Parent block of {0} has no associated weight")]
 	ParentBlockNoAssociatedWeight(B::Hash),
 	/// Check inherents error
-	#[display(fmt = "Checking inherents failed: {}", _0)]
+	#[error("Checking inherents failed: {0}")]
 	CheckInherents(sp_inherents::Error),
 	/// Unhandled check inherents error
-	#[display(fmt = "Checking inherents unhandled error: {}", "String::from_utf8_lossy(_0)")]
+	#[error("Checking inherents unhandled error: {}", String::from_utf8_lossy(.0))]
 	CheckInherentsUnhandled(sp_inherents::InherentIdentifier),
 	/// Create inherents error.
-	#[display(fmt = "Creating inherents failed: {}", _0)]
+	#[error("Creating inherents failed: {0}")]
 	CreateInherents(sp_inherents::Error),
 	/// Client error
+	#[error(transparent)]
 	Client(sp_blockchain::Error),
 	/// Runtime Api error.
+	#[error(transparent)]
 	RuntimeApi(sp_api::ApiError),
 	/// Fork tree error
+	#[error(transparent)]
 	ForkTree(Box<fork_tree::Error<sp_blockchain::Error>>),
 }
 
diff --git a/substrate/client/consensus/manual-seal/Cargo.toml b/substrate/client/consensus/manual-seal/Cargo.toml
index 89f3335899f1b43f0f58a14c5fde12e071c772c7..ff2264e641740ab0df002e9d9aef4c708fa209b4 100644
--- a/substrate/client/consensus/manual-seal/Cargo.toml
+++ b/substrate/client/consensus/manual-seal/Cargo.toml
@@ -13,7 +13,7 @@ readme = "README.md"
 targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
-derive_more = "0.99.16"
+thiserror = "1.0"
 futures = "0.3.9"
 jsonrpc-core = "18.0.0"
 jsonrpc-core-client = "18.0.0"
diff --git a/substrate/client/consensus/manual-seal/src/error.rs b/substrate/client/consensus/manual-seal/src/error.rs
index 3a67b36bc62bc45f755d48753991fdf14742a2a0..2f946f3de3ccc62e926b64819164a1757fc0e121 100644
--- a/substrate/client/consensus/manual-seal/src/error.rs
+++ b/substrate/client/consensus/manual-seal/src/error.rs
@@ -38,40 +38,52 @@ mod codes {
 }
 
 /// errors encountered by background block authorship task
-#[derive(Debug, derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 pub enum Error {
 	/// An error occurred while importing the block
-	#[display(fmt = "Block import failed: {:?}", _0)]
+	#[error("Block import failed: {0:?}")]
 	BlockImportError(ImportResult),
 	/// Transaction pool is empty, cannot create a block
-	#[display(fmt = "Transaction pool is empty, set create_empty to true,\
-	if you want to create empty blocks")]
+	#[error(
+		"Transaction pool is empty, set create_empty to true, if you want to create empty blocks"
+	)]
 	EmptyTransactionPool,
 	/// encountered during creation of Proposer.
-	#[display(fmt = "Consensus Error: {}", _0)]
-	ConsensusError(ConsensusError),
+	#[error("Consensus Error: {0}")]
+	ConsensusError(#[from] ConsensusError),
 	/// Failed to create Inherents data
-	#[display(fmt = "Inherents Error: {}", _0)]
-	InherentError(InherentsError),
+	#[error("Inherents Error: {0}")]
+	InherentError(#[from] InherentsError),
 	/// error encountered during finalization
-	#[display(fmt = "Finalization Error: {}", _0)]
-	BlockchainError(BlockchainError),
+	#[error("Finalization Error: {0}")]
+	BlockchainError(#[from] BlockchainError),
 	/// Supplied parent_hash doesn't exist in chain
-	#[display(fmt = "Supplied parent_hash: {} doesn't exist in chain", _0)]
-	#[from(ignore)]
+	#[error("Supplied parent_hash: {0} doesn't exist in chain")]
 	BlockNotFound(String),
 	/// Some string error
-	#[display(fmt = "{}", _0)]
+	#[error("{0}")]
 	StringError(String),
 	/// send error
-	#[display(fmt = "Consensus process is terminating")]
-	Canceled(oneshot::Canceled),
+	#[error("Consensus process is terminating")]
+	Canceled(#[from] oneshot::Canceled),
 	/// send error
-	#[display(fmt = "Consensus process is terminating")]
-	SendError(SendError),
+	#[error("Consensus process is terminating")]
+	SendError(#[from] SendError),
 	/// Some other error.
-	#[display(fmt = "Other error: {}", _0)]
-	Other(Box<dyn std::error::Error + Send>),
+	#[error("Other error: {0}")]
+	Other(#[from] Box<dyn std::error::Error + Send>),
+}
+
+impl From<ImportResult> for Error {
+	fn from(err: ImportResult) -> Self {
+		Error::BlockImportError(err)
+	}
+}
+
+impl From<String> for Error {
+	fn from(s: String) -> Self {
+		Error::StringError(s)
+	}
 }
 
 impl Error {
diff --git a/substrate/client/consensus/pow/Cargo.toml b/substrate/client/consensus/pow/Cargo.toml
index db9e4e164e4e9cf1970e2b85e7397ab9fc457ea4..e5bf87487c71b1b83fde3d2faaef2e4c74575927 100644
--- a/substrate/client/consensus/pow/Cargo.toml
+++ b/substrate/client/consensus/pow/Cargo.toml
@@ -28,6 +28,6 @@ log = "0.4.8"
 futures = "0.3.16"
 futures-timer = "3.0.1"
 parking_lot = "0.11.2"
-derive_more = "0.99.16"
+thiserror = "1.0"
 prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.10.0-dev"}
 async-trait = "0.1.50"
diff --git a/substrate/client/consensus/pow/src/lib.rs b/substrate/client/consensus/pow/src/lib.rs
index 0bcb9f3d00a545b5c2318ab850d0c90f4047519a..ef81faff46a93a2e4b86a42aafd29a60f9559094 100644
--- a/substrate/client/consensus/pow/src/lib.rs
+++ b/substrate/client/consensus/pow/src/lib.rs
@@ -72,45 +72,50 @@ use std::{
 	time::Duration,
 };
 
-#[derive(derive_more::Display, Debug)]
+#[derive(Debug, thiserror::Error)]
 pub enum Error<B: BlockT> {
-	#[display(fmt = "Header uses the wrong engine {:?}", _0)]
+	#[error("Header uses the wrong engine {0:?}")]
 	WrongEngine([u8; 4]),
-	#[display(fmt = "Header {:?} is unsealed", _0)]
+	#[error("Header {0:?} is unsealed")]
 	HeaderUnsealed(B::Hash),
-	#[display(fmt = "PoW validation error: invalid seal")]
+	#[error("PoW validation error: invalid seal")]
 	InvalidSeal,
-	#[display(fmt = "PoW validation error: preliminary verification failed")]
+	#[error("PoW validation error: preliminary verification failed")]
 	FailedPreliminaryVerify,
-	#[display(fmt = "Rejecting block too far in future")]
+	#[error("Rejecting block too far in future")]
 	TooFarInFuture,
-	#[display(fmt = "Fetching best header failed using select chain: {:?}", _0)]
+	#[error("Fetching best header failed using select chain: {0:?}")]
 	BestHeaderSelectChain(ConsensusError),
-	#[display(fmt = "Fetching best header failed: {:?}", _0)]
+	#[error("Fetching best header failed: {0:?}")]
 	BestHeader(sp_blockchain::Error),
-	#[display(fmt = "Best header does not exist")]
+	#[error("Best header does not exist")]
 	NoBestHeader,
-	#[display(fmt = "Block proposing error: {:?}", _0)]
+	#[error("Block proposing error: {0:?}")]
 	BlockProposingError(String),
-	#[display(fmt = "Fetch best hash failed via select chain: {:?}", _0)]
+	#[error("Fetch best hash failed via select chain: {0:?}")]
 	BestHashSelectChain(ConsensusError),
-	#[display(fmt = "Error with block built on {:?}: {:?}", _0, _1)]
+	#[error("Error with block built on {0:?}: {1:?}")]
 	BlockBuiltError(B::Hash, ConsensusError),
-	#[display(fmt = "Creating inherents failed: {}", _0)]
+	#[error("Creating inherents failed: {0}")]
 	CreateInherents(sp_inherents::Error),
-	#[display(fmt = "Checking inherents failed: {}", _0)]
+	#[error("Checking inherents failed: {0}")]
 	CheckInherents(sp_inherents::Error),
-	#[display(
-		fmt = "Checking inherents unknown error for identifier: {:?}",
-		"String::from_utf8_lossy(_0)"
+	#[error(
+		"Checking inherents unknown error for identifier: {:?}",
+		String::from_utf8_lossy(.0)
 	)]
 	CheckInherentsUnknownError(sp_inherents::InherentIdentifier),
-	#[display(fmt = "Multiple pre-runtime digests")]
+	#[error("Multiple pre-runtime digests")]
 	MultiplePreRuntimeDigests,
+	#[error(transparent)]
 	Client(sp_blockchain::Error),
+	#[error(transparent)]
 	Codec(codec::Error),
+	#[error("{0}")]
 	Environment(String),
+	#[error("{0}")]
 	Runtime(RuntimeString),
+	#[error("{0}")]
 	Other(String),
 }
 
diff --git a/substrate/client/executor/common/Cargo.toml b/substrate/client/executor/common/Cargo.toml
index 8e4b11f8f8fae0e0429f97545a80aa0a80511bf1..104d24876d9a5d24f378349499af7b5a83fec2f9 100644
--- a/substrate/client/executor/common/Cargo.toml
+++ b/substrate/client/executor/common/Cargo.toml
@@ -14,7 +14,6 @@ readme = "README.md"
 targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
-derive_more = "0.99.16"
 wasm-instrument = "0.1"
 codec = { package = "parity-scale-codec", version = "2.0.0" }
 wasmi = "0.9.1"
diff --git a/substrate/client/executor/common/src/error.rs b/substrate/client/executor/common/src/error.rs
index 90e658a89628144979dde3d0af3ccba8d8f83d1e..606f97317b9a8083431d71993f3a507323bec577 100644
--- a/substrate/client/executor/common/src/error.rs
+++ b/substrate/client/executor/common/src/error.rs
@@ -125,28 +125,38 @@ impl From<String> for Error {
 }
 
 /// Type for errors occurring during Wasm runtime construction.
-#[derive(Debug, derive_more::Display)]
+#[derive(Debug, thiserror::Error)]
+#[allow(missing_docs)]
 pub enum WasmError {
-	/// Code could not be read from the state.
+	#[error("Code could not be read from the state.")]
 	CodeNotFound,
-	/// Failure to reinitialize runtime instance from snapshot.
+
+	#[error("Failure to reinitialize runtime instance from snapshot.")]
 	ApplySnapshotFailed,
+
 	/// Failure to erase the wasm memory.
 	///
 	/// Depending on the implementation might mean failure of allocating memory.
+	#[error("Failure to erase the wasm memory: {0}")]
 	ErasingFailed(String),
-	/// Wasm code failed validation.
+
+	#[error("Wasm code failed validation.")]
 	InvalidModule,
-	/// Wasm code could not be deserialized.
+
+	#[error("Wasm code could not be deserialized.")]
 	CantDeserializeWasm,
-	/// The module does not export a linear memory named `memory`.
+
+	#[error("The module does not export a linear memory named `memory`.")]
 	InvalidMemory,
-	/// The number of heap pages requested is disallowed by the module.
+
+	#[error("The number of heap pages requested is disallowed by the module.")]
 	InvalidHeapPages,
+
 	/// Instantiation error.
+	#[error("{0}")]
 	Instantiation(String),
+
 	/// Other error happenend.
+	#[error("{0}")]
 	Other(String),
 }
-
-impl std::error::Error for WasmError {}
diff --git a/substrate/client/finality-grandpa/Cargo.toml b/substrate/client/finality-grandpa/Cargo.toml
index 3f9261c0c17af02f2494dddb70a0dccdbcb0c62a..2e6d3407a191fe6b950cc8a1d9df3623e12bfbc0 100644
--- a/substrate/client/finality-grandpa/Cargo.toml
+++ b/substrate/client/finality-grandpa/Cargo.toml
@@ -13,9 +13,8 @@ readme = "README.md"
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
 
-
 [dependencies]
-derive_more = "0.99.16"
+thiserror = "1.0"
 dyn-clone = "1.0"
 fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" }
 futures = "0.3.9"
diff --git a/substrate/client/finality-grandpa/rpc/Cargo.toml b/substrate/client/finality-grandpa/rpc/Cargo.toml
index be6dfc371e4add35b4d9ef2b91a6eeeb08d3c4f3..39bf398fe3129d1be7b854422a72fa39347f1a98 100644
--- a/substrate/client/finality-grandpa/rpc/Cargo.toml
+++ b/substrate/client/finality-grandpa/rpc/Cargo.toml
@@ -23,7 +23,7 @@ futures = "0.3.16"
 serde = { version = "1.0.105", features = ["derive"] }
 serde_json = "1.0.50"
 log = "0.4.8"
-derive_more = "0.99.2"
+thiserror = "1.0"
 parity-scale-codec = { version = "2.0.0", features = ["derive"] }
 sc-client-api = { version = "4.0.0-dev", path = "../../api" }
 
diff --git a/substrate/client/finality-grandpa/rpc/src/error.rs b/substrate/client/finality-grandpa/rpc/src/error.rs
index 1c1361bcaeda7fc59cc6eba0c934b7ecbfb42c2f..845b4d99dcc1a87935026fc50f60a40d767524c4 100644
--- a/substrate/client/finality-grandpa/rpc/src/error.rs
+++ b/substrate/client/finality-grandpa/rpc/src/error.rs
@@ -16,21 +16,21 @@
 // You should have received a copy of the GNU General Public License
 // along with this program. If not, see <https://www.gnu.org/licenses/>.
 
-#[derive(derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 /// Top-level error type for the RPC handler
 pub enum Error {
 	/// The GRANDPA RPC endpoint is not ready.
-	#[display(fmt = "GRANDPA RPC endpoint not ready")]
+	#[error("GRANDPA RPC endpoint not ready")]
 	EndpointNotReady,
 	/// GRANDPA reports the authority set id to be larger than 32-bits.
-	#[display(fmt = "GRANDPA reports authority set id unreasonably large")]
+	#[error("GRANDPA reports authority set id unreasonably large")]
 	AuthoritySetIdReportedAsUnreasonablyLarge,
 	/// GRANDPA reports voter state with round id or weights larger than 32-bits.
-	#[display(fmt = "GRANDPA reports voter state as unreasonably large")]
+	#[error("GRANDPA reports voter state as unreasonably large")]
 	VoterStateReportsUnreasonablyLargeNumbers,
 	/// GRANDPA prove finality failed.
-	#[display(fmt = "GRANDPA prove finality rpc failed: {}", _0)]
-	ProveFinalityFailed(sc_finality_grandpa::FinalityProofError),
+	#[error("GRANDPA prove finality rpc failed: {0}")]
+	ProveFinalityFailed(#[from] sc_finality_grandpa::FinalityProofError),
 }
 
 /// The error codes returned by jsonrpc.
diff --git a/substrate/client/finality-grandpa/src/authorities.rs b/substrate/client/finality-grandpa/src/authorities.rs
index aa8be83b9529aa60ba51fc90a4ffe9b2d4bd3970..033a1c4bbb2390ff96885d070f0cc3e0fdddd984 100644
--- a/substrate/client/finality-grandpa/src/authorities.rs
+++ b/substrate/client/finality-grandpa/src/authorities.rs
@@ -32,23 +32,22 @@ use sp_finality_grandpa::{AuthorityId, AuthorityList};
 use crate::SetId;
 
 /// Error type returned on operations on the `AuthoritySet`.
-#[derive(Debug, derive_more::Display)]
+#[derive(Debug, thiserror::Error)]
 pub enum Error<N, E> {
-	#[display(fmt = "Invalid authority set, either empty or with an authority weight set to 0.")]
+	#[error("Invalid authority set, either empty or with an authority weight set to 0.")]
 	InvalidAuthoritySet,
-	#[display(fmt = "Client error during ancestry lookup: {}", _0)]
+	#[error("Client error during ancestry lookup: {0}")]
 	Client(E),
-	#[display(fmt = "Duplicate authority set change.")]
+	#[error("Duplicate authority set change.")]
 	DuplicateAuthoritySetChange,
-	#[display(fmt = "Multiple pending forced authority set changes are not allowed.")]
+	#[error("Multiple pending forced authority set changes are not allowed.")]
 	MultiplePendingForcedAuthoritySetChanges,
-	#[display(
-		fmt = "A pending forced authority set change could not be applied since it must be applied \
-		after the pending standard change at #{}",
-		_0
+	#[error(
+		"A pending forced authority set change could not be applied since it must be applied \
+		after the pending standard change at #{0}"
 	)]
 	ForcedAuthoritySetChangeDependencyUnsatisfied(N),
-	#[display(fmt = "Invalid operation in the pending changes tree: {}", _0)]
+	#[error("Invalid operation in the pending changes tree: {0}")]
 	ForkTree(fork_tree::Error<E>),
 }
 
diff --git a/substrate/client/finality-grandpa/src/finality_proof.rs b/substrate/client/finality-grandpa/src/finality_proof.rs
index cc6853bee3b0757988ec4caf18fcec3fd5d2cab1..03a4f2ff450a3e0d47ba218641b37df7b28ad34f 100644
--- a/substrate/client/finality-grandpa/src/finality_proof.rs
+++ b/substrate/client/finality-grandpa/src/finality_proof.rs
@@ -132,17 +132,18 @@ pub struct FinalityProof<Header: HeaderT> {
 }
 
 /// Errors occurring when trying to prove finality
-#[derive(Debug, derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 pub enum FinalityProofError {
 	/// The requested block has not yet been finalized.
-	#[display(fmt = "Block not yet finalized")]
+	#[error("Block not yet finalized")]
 	BlockNotYetFinalized,
 	/// The requested block is not covered by authority set changes. Likely this means the block is
 	/// in the latest authority set, and the subscription API is more appropriate.
-	#[display(fmt = "Block not covered by authority set changes")]
+	#[error("Block not covered by authority set changes")]
 	BlockNotInAuthoritySetChanges,
 	/// Errors originating from the client.
-	Client(sp_blockchain::Error),
+	#[error(transparent)]
+	Client(#[from] sp_blockchain::Error),
 }
 
 fn prove_finality<Block, B>(
diff --git a/substrate/client/finality-grandpa/src/warp_proof.rs b/substrate/client/finality-grandpa/src/warp_proof.rs
index 39d570d22bd7d4e719d11ba41b1c5da2e685c61f..bdb8e36373de3f4bc20ed28b44ec294fe3bbf62b 100644
--- a/substrate/client/finality-grandpa/src/warp_proof.rs
+++ b/substrate/client/finality-grandpa/src/warp_proof.rs
@@ -34,26 +34,25 @@ use sp_runtime::{
 use std::{collections::HashMap, sync::Arc};
 
 /// Warp proof processing error.
-#[derive(Debug, derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 pub enum Error {
 	/// Decoding error.
-	#[display(fmt = "Failed to decode block hash: {}.", _0)]
-	DecodeScale(codec::Error),
+	#[error("Failed to decode block hash: {0}.")]
+	DecodeScale(#[from] codec::Error),
 	/// Client backend error.
-	Client(sp_blockchain::Error),
+	#[error("{0}")]
+	Client(#[from] sp_blockchain::Error),
 	/// Invalid request data.
-	#[from(ignore)]
+	#[error("{0}")]
 	InvalidRequest(String),
 	/// Invalid warp proof.
-	#[from(ignore)]
+	#[error("{0}")]
 	InvalidProof(String),
 	/// Missing header or authority set change data.
-	#[display(fmt = "Missing required data to be able to answer request.")]
+	#[error("Missing required data to be able to answer request.")]
 	MissingData,
 }
 
-impl std::error::Error for Error {}
-
 /// The maximum size in bytes of the `WarpSyncProof`.
 pub(super) const MAX_WARP_SYNC_PROOF_SIZE: usize = 8 * 1024 * 1024;
 
diff --git a/substrate/client/keystore/Cargo.toml b/substrate/client/keystore/Cargo.toml
index 7fe9e182efbdff08a7349f316dfd1ec54ce717bd..56d4ee0d556fa80263d4b111479de221381c1c1b 100644
--- a/substrate/client/keystore/Cargo.toml
+++ b/substrate/client/keystore/Cargo.toml
@@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 async-trait = "0.1.50"
-derive_more = "0.99.16"
+thiserror = "1.0"
 sp-application-crypto = { version = "4.0.0", path = "../../primitives/application-crypto" }
 sp-core = { version = "4.1.0-dev", path = "../../primitives/core" }
 sp-keystore = { version = "0.10.0", path = "../../primitives/keystore" }
diff --git a/substrate/client/keystore/src/lib.rs b/substrate/client/keystore/src/lib.rs
index 359326bb4cae0cd59452abdd49da0c15659c87bd..cf94a16f08d8659e7554f164f483cecf89db72b9 100644
--- a/substrate/client/keystore/src/lib.rs
+++ b/substrate/client/keystore/src/lib.rs
@@ -28,29 +28,31 @@ mod local;
 pub use local::LocalKeystore;
 
 /// Keystore error.
-#[derive(Debug, derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 pub enum Error {
 	/// IO error.
-	Io(io::Error),
+	#[error(transparent)]
+	Io(#[from] io::Error),
 	/// JSON error.
-	Json(serde_json::Error),
+	#[error(transparent)]
+	Json(#[from] serde_json::Error),
 	/// Invalid password.
-	#[display(
-		fmt = "Requested public key and public key of the loaded private key do not match. \n
+	#[error(
+		"Requested public key and public key of the loaded private key do not match. \n
 			This means either that the keystore password is incorrect or that the private key was stored under a wrong public key."
 	)]
 	PublicKeyMismatch,
 	/// Invalid BIP39 phrase
-	#[display(fmt = "Invalid recovery phrase (BIP39) data")]
+	#[error("Invalid recovery phrase (BIP39) data")]
 	InvalidPhrase,
 	/// Invalid seed
-	#[display(fmt = "Invalid seed")]
+	#[error("Invalid seed")]
 	InvalidSeed,
 	/// Public key type is not supported
-	#[display(fmt = "Key crypto type is not supported")]
+	#[error("Key crypto type is not supported")]
 	KeyNotSupported(KeyTypeId),
 	/// Keystore unavailable
-	#[display(fmt = "Keystore unavailable")]
+	#[error("Keystore unavailable")]
 	Unavailable,
 }
 
@@ -69,13 +71,3 @@ impl From<Error> for TraitError {
 		}
 	}
 }
-
-impl std::error::Error for Error {
-	fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-		match self {
-			Error::Io(ref err) => Some(err),
-			Error::Json(ref err) => Some(err),
-			_ => None,
-		}
-	}
-}
diff --git a/substrate/client/network/Cargo.toml b/substrate/client/network/Cargo.toml
index f378b75990cb9940c38888a49446b306f422f857..354991b32ba5b54fa1ed16ae4b3388a0a686048b 100644
--- a/substrate/client/network/Cargo.toml
+++ b/substrate/client/network/Cargo.toml
@@ -25,7 +25,6 @@ bytes = "1"
 codec = { package = "parity-scale-codec", version = "2.0.0", features = [
     "derive",
 ] }
-derive_more = "0.99.16"
 either = "1.5.3"
 fnv = "1.0.6"
 fork-tree = { version = "3.0.0", path = "../../utils/fork-tree" }
@@ -57,7 +56,7 @@ sp-core = { version = "4.1.0-dev", path = "../../primitives/core" }
 sp-runtime = { version = "4.1.0-dev", path = "../../primitives/runtime" }
 sc-utils = { version = "4.0.0-dev", path = "../utils" }
 sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" }
-thiserror = "1"
+thiserror = "1.0"
 unsigned-varint = { version = "0.6.0", features = [
     "futures",
     "asynchronous_codec",
diff --git a/substrate/client/network/src/bitswap.rs b/substrate/client/network/src/bitswap.rs
index e6cb1d9d79e3ab584146713d43fd6a627178d02e..e7c37968b5f99dccd61fc65449c5f076eb7ad18a 100644
--- a/substrate/client/network/src/bitswap.rs
+++ b/substrate/client/network/src/bitswap.rs
@@ -313,21 +313,29 @@ impl<B: BlockT> NetworkBehaviour for Bitswap<B> {
 }
 
 /// Bitswap protocol error.
-#[derive(derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 pub enum BitswapError {
 	/// Protobuf decoding error.
-	#[display(fmt = "Failed to decode request: {}.", _0)]
-	DecodeProto(prost::DecodeError),
+	#[error("Failed to decode request: {0}.")]
+	DecodeProto(#[from] prost::DecodeError),
+
 	/// Protobuf encoding error.
-	#[display(fmt = "Failed to encode response: {}.", _0)]
-	EncodeProto(prost::EncodeError),
+	#[error("Failed to encode response: {0}.")]
+	EncodeProto(#[from] prost::EncodeError),
+
 	/// Client backend error.
-	Client(sp_blockchain::Error),
+	#[error(transparent)]
+	Client(#[from] sp_blockchain::Error),
+
 	/// Error parsing CID
-	BadCid(cid::Error),
+	#[error(transparent)]
+	BadCid(#[from] cid::Error),
+
 	/// Packet read error.
-	Read(io::Error),
+	#[error(transparent)]
+	Read(#[from] io::Error),
+
 	/// Error sending response.
-	#[display(fmt = "Failed to send response.")]
+	#[error("Failed to send response.")]
 	SendResponse,
 }
diff --git a/substrate/client/network/src/block_request_handler.rs b/substrate/client/network/src/block_request_handler.rs
index 9d963480a7e014495b2a6f27e184853a432f84e7..2f17cdac0744b4b93fdc6b788e21ddf87e6bdaf8 100644
--- a/substrate/client/network/src/block_request_handler.rs
+++ b/substrate/client/network/src/block_request_handler.rs
@@ -379,19 +379,20 @@ impl<B: BlockT> BlockRequestHandler<B> {
 	}
 }
 
-#[derive(derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 enum HandleRequestError {
-	#[display(fmt = "Failed to decode request: {}.", _0)]
-	DecodeProto(prost::DecodeError),
-	#[display(fmt = "Failed to encode response: {}.", _0)]
-	EncodeProto(prost::EncodeError),
-	#[display(fmt = "Failed to decode block hash: {}.", _0)]
-	DecodeScale(codec::Error),
-	#[display(fmt = "Missing `BlockRequest::from_block` field.")]
+	#[error("Failed to decode request: {0}.")]
+	DecodeProto(#[from] prost::DecodeError),
+	#[error("Failed to encode response: {0}.")]
+	EncodeProto(#[from] prost::EncodeError),
+	#[error("Failed to decode block hash: {0}.")]
+	DecodeScale(#[from] codec::Error),
+	#[error("Missing `BlockRequest::from_block` field.")]
 	MissingFromField,
-	#[display(fmt = "Failed to parse BlockRequest::direction.")]
+	#[error("Failed to parse BlockRequest::direction.")]
 	ParseDirection,
-	Client(sp_blockchain::Error),
-	#[display(fmt = "Failed to send response.")]
+	#[error(transparent)]
+	Client(#[from] sp_blockchain::Error),
+	#[error("Failed to send response.")]
 	SendResponse,
 }
diff --git a/substrate/client/network/src/error.rs b/substrate/client/network/src/error.rs
index 1dafddd7bcc551b858810c5e4d26cc0843d7192f..716235193a80fb47d004ac55d30c6488a01c11eb 100644
--- a/substrate/client/network/src/error.rs
+++ b/substrate/client/network/src/error.rs
@@ -27,18 +27,18 @@ use std::{borrow::Cow, fmt};
 pub type Result<T> = std::result::Result<T, Error>;
 
 /// Error type for the network.
-#[derive(derive_more::Display, derive_more::From)]
+#[derive(thiserror::Error)]
 pub enum Error {
 	/// Io error
-	Io(std::io::Error),
+	#[error(transparent)]
+	Io(#[from] std::io::Error),
+
 	/// Client error
-	Client(Box<sp_blockchain::Error>),
+	#[error(transparent)]
+	Client(#[from] Box<sp_blockchain::Error>),
 	/// The same bootnode (based on address) is registered with two different peer ids.
-	#[display(
-		fmt = "The same bootnode (`{}`) is registered with two different peer ids: `{}` and `{}`",
-		address,
-		first_id,
-		second_id
+	#[error(
+		"The same bootnode (`{address}`) is registered with two different peer ids: `{first_id}` and `{second_id}`"
 	)]
 	DuplicateBootnode {
 		/// The address of the bootnode.
@@ -49,11 +49,11 @@ pub enum Error {
 		second_id: PeerId,
 	},
 	/// Prometheus metrics error.
-	Prometheus(prometheus_endpoint::PrometheusError),
+	#[error(transparent)]
+	Prometheus(#[from] prometheus_endpoint::PrometheusError),
 	/// The network addresses are invalid because they don't match the transport.
-	#[display(
-		fmt = "The following addresses are invalid because they don't match the transport: {:?}",
-		addresses
+	#[error(
+		"The following addresses are invalid because they don't match the transport: {addresses:?}"
 	)]
 	AddressesForAnotherTransport {
 		/// Transport used.
@@ -62,7 +62,7 @@ pub enum Error {
 		addresses: Vec<Multiaddr>,
 	},
 	/// The same request-response protocol has been registered multiple times.
-	#[display(fmt = "Request-response protocol registered multiple times: {}", protocol)]
+	#[error("Request-response protocol registered multiple times: {protocol}")]
 	DuplicateRequestResponseProtocol {
 		/// Name of the protocol registered multiple times.
 		protocol: Cow<'static, str>,
@@ -75,16 +75,3 @@ impl fmt::Debug for Error {
 		fmt::Display::fmt(self, f)
 	}
 }
-
-impl std::error::Error for Error {
-	fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-		match self {
-			Self::Io(ref err) => Some(err),
-			Self::Client(ref err) => Some(err),
-			Self::Prometheus(ref err) => Some(err),
-			Self::DuplicateBootnode { .. } |
-			Self::AddressesForAnotherTransport { .. } |
-			Self::DuplicateRequestResponseProtocol { .. } => None,
-		}
-	}
-}
diff --git a/substrate/client/network/src/light_client_requests/handler.rs b/substrate/client/network/src/light_client_requests/handler.rs
index b5c6ccb196d5bb413629333af23a39b470fe5c4c..fb258304f2e8f0fd3902649496897c5f8a4eea5f 100644
--- a/substrate/client/network/src/light_client_requests/handler.rs
+++ b/substrate/client/network/src/light_client_requests/handler.rs
@@ -284,20 +284,20 @@ impl<B: Block> LightClientRequestHandler<B> {
 	}
 }
 
-#[derive(derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 enum HandleRequestError {
-	#[display(fmt = "Failed to decode request: {}.", _0)]
-	DecodeProto(prost::DecodeError),
-	#[display(fmt = "Failed to encode response: {}.", _0)]
-	EncodeProto(prost::EncodeError),
-	#[display(fmt = "Failed to send response.")]
+	#[error("Failed to decode request: {0}.")]
+	DecodeProto(#[from] prost::DecodeError),
+	#[error("Failed to encode response: {0}.")]
+	EncodeProto(#[from] prost::EncodeError),
+	#[error("Failed to send response.")]
 	SendResponse,
 	/// A bad request has been received.
-	#[display(fmt = "bad request: {}", _0)]
+	#[error("bad request: {0}")]
 	BadRequest(&'static str),
 	/// Encoding or decoding of some data failed.
-	#[display(fmt = "codec error: {}", _0)]
-	Codec(codec::Error),
+	#[error("codec error: {0}")]
+	Codec(#[from] codec::Error),
 }
 
 fn fmt_keys(first: Option<&Vec<u8>>, last: Option<&Vec<u8>>) -> String {
diff --git a/substrate/client/network/src/protocol/notifications/handler.rs b/substrate/client/network/src/protocol/notifications/handler.rs
index 158ab2ae379c6641a55ccff3785c9cc1d1542cbf..91225f54203af442a140391b45b5545e4249ce99 100644
--- a/substrate/client/network/src/protocol/notifications/handler.rs
+++ b/substrate/client/network/src/protocol/notifications/handler.rs
@@ -457,9 +457,9 @@ impl<'a> Ready<'a> {
 }
 
 /// Error specific to the collection of protocols.
-#[derive(Debug, derive_more::Display, derive_more::Error)]
+#[derive(Debug, thiserror::Error)]
 pub enum NotifsHandlerError {
-	/// Channel of synchronous notifications is full.
+	#[error("Channel of synchronous notifications is full.")]
 	SyncNotificationsClogged,
 }
 
diff --git a/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs b/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs
index 5171d459fa4005886be6b0ec94943a88d066e87c..53270975a5b0dfb56663342a1ce4c322defd40e3 100644
--- a/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs
+++ b/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs
@@ -457,13 +457,14 @@ where
 }
 
 /// Error generated by sending on a notifications out substream.
-#[derive(Debug, derive_more::From, derive_more::Display)]
+#[derive(Debug, thiserror::Error)]
 pub enum NotificationsHandshakeError {
 	/// I/O error on the substream.
-	Io(io::Error),
+	#[error(transparent)]
+	Io(#[from] io::Error),
 
 	/// Initial message or handshake was too large.
-	#[display(fmt = "Initial message or handshake was too large: {}", requested)]
+	#[error("Initial message or handshake was too large: {requested}")]
 	TooLarge {
 		/// Size requested by the remote.
 		requested: usize,
@@ -472,7 +473,8 @@ pub enum NotificationsHandshakeError {
 	},
 
 	/// Error while decoding the variable-length integer.
-	VarintDecode(unsigned_varint::decode::Error),
+	#[error(transparent)]
+	VarintDecode(#[from] unsigned_varint::decode::Error),
 }
 
 impl From<unsigned_varint::io::ReadError> for NotificationsHandshakeError {
@@ -489,10 +491,11 @@ impl From<unsigned_varint::io::ReadError> for NotificationsHandshakeError {
 }
 
 /// Error generated by sending on a notifications out substream.
-#[derive(Debug, derive_more::From, derive_more::Display)]
+#[derive(Debug, thiserror::Error)]
 pub enum NotificationsOutError {
 	/// I/O error on the substream.
-	Io(io::Error),
+	#[error(transparent)]
+	Io(#[from] io::Error),
 }
 
 #[cfg(test)]
diff --git a/substrate/client/network/src/request_responses.rs b/substrate/client/network/src/request_responses.rs
index 24b3d3df00b2d2931416f81431776ef5a713ff05..58007c7bc5ce1c2f204c09802b60f6f4040591eb 100644
--- a/substrate/client/network/src/request_responses.rs
+++ b/substrate/client/network/src/request_responses.rs
@@ -884,34 +884,35 @@ impl NetworkBehaviour for RequestResponsesBehaviour {
 }
 
 /// Error when registering a protocol.
-#[derive(Debug, derive_more::Display, derive_more::Error)]
+#[derive(Debug, thiserror::Error)]
 pub enum RegisterError {
 	/// A protocol has been specified multiple times.
-	DuplicateProtocol(#[error(ignore)] Cow<'static, str>),
+	#[error("{0}")]
+	DuplicateProtocol(Cow<'static, str>),
 }
 
 /// Error in a request.
-#[derive(Debug, derive_more::Display, derive_more::Error)]
+#[derive(Debug, thiserror::Error)]
+#[allow(missing_docs)]
 pub enum RequestFailure {
-	/// We are not currently connected to the requested peer.
+	#[error("We are not currently connected to the requested peer.")]
 	NotConnected,
-	/// Given protocol hasn't been registered.
+	#[error("Given protocol hasn't been registered.")]
 	UnknownProtocol,
-	/// Remote has closed the substream before answering, thereby signaling that it considers the
-	/// request as valid, but refused to answer it.
+	#[error("Remote has closed the substream before answering, thereby signaling that it considers the request as valid, but refused to answer it.")]
 	Refused,
-	/// The remote replied, but the local node is no longer interested in the response.
+	#[error("The remote replied, but the local node is no longer interested in the response.")]
 	Obsolete,
 	/// Problem on the network.
-	#[display(fmt = "Problem on the network: {}", _0)]
+	#[error("Problem on the network: {0}")]
 	Network(OutboundFailure),
 }
 
 /// Error when processing a request sent by a remote.
-#[derive(Debug, derive_more::Display, derive_more::Error)]
+#[derive(Debug, thiserror::Error)]
 pub enum ResponseFailure {
 	/// Problem on the network.
-	#[display(fmt = "Problem on the network: {}", _0)]
+	#[error("Problem on the network: {0}")]
 	Network(InboundFailure),
 }
 
diff --git a/substrate/client/network/src/service.rs b/substrate/client/network/src/service.rs
index 9c8c58ef49e4d8e41f470c5ee43a428a35fa727c..b6a1d3c88e7f37eb79c8d99362ce87bc5bcd8abc 100644
--- a/substrate/client/network/src/service.rs
+++ b/substrate/client/network/src/service.rs
@@ -1391,7 +1391,7 @@ impl<'a> NotificationSenderReady<'a> {
 }
 
 /// Error returned by [`NetworkService::send_notification`].
-#[derive(Debug, derive_more::Display, derive_more::Error)]
+#[derive(Debug, thiserror::Error)]
 pub enum NotificationSenderError {
 	/// The notification receiver has been closed, usually because the underlying connection
 	/// closed.
@@ -1399,8 +1399,10 @@ pub enum NotificationSenderError {
 	/// Some of the notifications most recently sent may not have been received. However,
 	/// the peer may still be connected and a new `NotificationSender` for the same
 	/// protocol obtained from [`NetworkService::notification_sender`].
+	#[error("The notification receiver has been closed")]
 	Closed,
 	/// Protocol name hasn't been registered.
+	#[error("Protocol name hasn't been registered")]
 	BadProtocol,
 }
 
diff --git a/substrate/client/network/src/state_request_handler.rs b/substrate/client/network/src/state_request_handler.rs
index 89f1f2b363c4c0363de2b89be8090c8da77082b3..10a77061a031d1b9f55d3aa105dbc0a91dba502e 100644
--- a/substrate/client/network/src/state_request_handler.rs
+++ b/substrate/client/network/src/state_request_handler.rs
@@ -241,15 +241,20 @@ impl<B: BlockT> StateRequestHandler<B> {
 	}
 }
 
-#[derive(derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 enum HandleRequestError {
-	#[display(fmt = "Failed to decode request: {}.", _0)]
-	DecodeProto(prost::DecodeError),
-	#[display(fmt = "Failed to encode response: {}.", _0)]
-	EncodeProto(prost::EncodeError),
-	#[display(fmt = "Failed to decode block hash: {}.", _0)]
-	InvalidHash(codec::Error),
-	Client(sp_blockchain::Error),
-	#[display(fmt = "Failed to send response.")]
+	#[error("Failed to decode request: {0}.")]
+	DecodeProto(#[from] prost::DecodeError),
+
+	#[error("Failed to encode response: {0}.")]
+	EncodeProto(#[from] prost::EncodeError),
+
+	#[error("Failed to decode block hash: {0}.")]
+	InvalidHash(#[from] codec::Error),
+
+	#[error(transparent)]
+	Client(#[from] sp_blockchain::Error),
+
+	#[error("Failed to send response.")]
 	SendResponse,
 }
diff --git a/substrate/client/network/src/warp_request_handler.rs b/substrate/client/network/src/warp_request_handler.rs
index ca5a93b752b62b7d915f5d8f2f3c073f1e3b034c..4c839825ff5ec4b2614e66b9e0f74b58970624c5 100644
--- a/substrate/client/network/src/warp_request_handler.rs
+++ b/substrate/client/network/src/warp_request_handler.rs
@@ -149,18 +149,23 @@ impl<TBlock: BlockT> RequestHandler<TBlock> {
 	}
 }
 
-#[derive(Debug, derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 enum HandleRequestError {
-	#[display(fmt = "Failed to decode request: {}.", _0)]
-	DecodeProto(prost::DecodeError),
-	#[display(fmt = "Failed to encode response: {}.", _0)]
-	EncodeProto(prost::EncodeError),
-	#[display(fmt = "Failed to decode block hash: {}.", _0)]
-	DecodeScale(codec::Error),
-	Client(sp_blockchain::Error),
-	#[from(ignore)]
-	#[display(fmt = "Invalid request {}.", _0)]
-	InvalidRequest(Box<dyn std::error::Error + Send + Sync>),
-	#[display(fmt = "Failed to send response.")]
+	#[error("Failed to decode request: {0}.")]
+	DecodeProto(#[from] prost::DecodeError),
+
+	#[error("Failed to encode response: {0}.")]
+	EncodeProto(#[from] prost::EncodeError),
+
+	#[error("Failed to decode block hash: {0}.")]
+	DecodeScale(#[from] codec::Error),
+
+	#[error(transparent)]
+	Client(#[from] sp_blockchain::Error),
+
+	#[error("Invalid request {0}.")]
+	InvalidRequest(#[from] Box<dyn std::error::Error + Send + Sync>),
+
+	#[error("Failed to send response.")]
 	SendResponse,
 }
diff --git a/substrate/client/transaction-pool/api/Cargo.toml b/substrate/client/transaction-pool/api/Cargo.toml
index 95b82e26fc5d76889b817b6c8d0e3c6c3e6e2160..a544248a4f2cc0091ff7c61ca76bcfa30a5784bf 100644
--- a/substrate/client/transaction-pool/api/Cargo.toml
+++ b/substrate/client/transaction-pool/api/Cargo.toml
@@ -9,11 +9,10 @@ repository = "https://github.com/paritytech/substrate/"
 description = "Transaction pool client facing API."
 
 [dependencies]
-futures = { version = "0.3.1"  }
-log = { version = "0.4.8" }
+futures = "0.3.1"
+log = "0.4.8"
 serde = { version = "1.0.132", features = ["derive"] }
-thiserror = { version = "1.0.30" }
-sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" }
+thiserror = "1.0.30"
 
-derive_more = { version = "0.99.16" }
+sp-runtime = { version = "4.1.0-dev", default-features = false, path = "../../../primitives/runtime" }
 sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" }
diff --git a/substrate/client/transaction-pool/api/src/error.rs b/substrate/client/transaction-pool/api/src/error.rs
index f1ac2798e62d33a1afb18cdaaed01af04c0680a6..b093657f739b1bb23b882446331d17e2f6a69833 100644
--- a/substrate/client/transaction-pool/api/src/error.rs
+++ b/substrate/client/transaction-pool/api/src/error.rs
@@ -26,7 +26,7 @@ use sp_runtime::transaction_validity::{
 pub type Result<T> = std::result::Result<T, Error>;
 
 /// Transaction pool error type.
-#[derive(Debug, thiserror::Error, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 #[allow(missing_docs)]
 pub enum Error {
 	#[error("Unknown transaction validity: {0:?}")]
@@ -64,7 +64,6 @@ pub enum Error {
 	#[error("Transaction cannot be propagated and the local node does not author blocks")]
 	Unactionable,
 
-	#[from(ignore)]
 	#[error("{0}")]
 	InvalidBlockId(String),
 
diff --git a/substrate/client/transaction-pool/src/lib.rs b/substrate/client/transaction-pool/src/lib.rs
index 2d07815e4baace24fcc3751976bdca10f1e126a7..b5af2d12d65c927033524df841b8fc847f7dc64b 100644
--- a/substrate/client/transaction-pool/src/lib.rs
+++ b/substrate/client/transaction-pool/src/lib.rs
@@ -47,8 +47,8 @@ use std::{
 
 use graph::{ExtrinsicHash, IsValidator};
 use sc_transaction_pool_api::{
-	ChainEvent, ImportNotificationStream, MaintainedTransactionPool, PoolFuture, PoolStatus,
-	ReadyTransactions, TransactionFor, TransactionPool, TransactionSource,
+	error::Error as TxPoolError, ChainEvent, ImportNotificationStream, MaintainedTransactionPool,
+	PoolFuture, PoolStatus, ReadyTransactions, TransactionFor, TransactionPool, TransactionSource,
 	TransactionStatusStreamFor, TxHash,
 };
 use sp_core::traits::SpawnEssentialNamed;
@@ -418,8 +418,8 @@ where
 			.validate_transaction_blocking(at, TransactionSource::Local, xt.clone())?
 			.map_err(|e| {
 				Self::Error::Pool(match e {
-					TransactionValidityError::Invalid(i) => i.into(),
-					TransactionValidityError::Unknown(u) => u.into(),
+					TransactionValidityError::Invalid(i) => TxPoolError::InvalidTransaction(i),
+					TransactionValidityError::Unknown(u) => TxPoolError::UnknownTransaction(u),
 				})
 			})?;
 
diff --git a/substrate/primitives/keystore/Cargo.toml b/substrate/primitives/keystore/Cargo.toml
index e918f5d2c6d750842d877e925407157aee9f99d4..28802cbec35e7e06920c866d5a790f02e5831a73 100644
--- a/substrate/primitives/keystore/Cargo.toml
+++ b/substrate/primitives/keystore/Cargo.toml
@@ -14,13 +14,14 @@ targets = ["x86_64-unknown-linux-gnu"]
 
 [dependencies]
 async-trait = "0.1.50"
-derive_more = "0.99.16"
+futures = "0.3.1"
+parking_lot = { version = "0.11.2", default-features = false }
+serde = { version = "1.0", optional = true }
+thiserror = "1.0"
+
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
-futures = { version = "0.3.1" }
 schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false }
 merlin = { version = "2.0", default-features = false }
-parking_lot = { version = "0.11.2", default-features = false }
-serde = { version = "1.0", optional = true}
 sp-core = { version = "4.1.0-dev", path = "../core" }
 sp-externalities = { version = "0.10.0", path = "../externalities", default-features = false }
 
@@ -28,7 +29,6 @@ sp-externalities = { version = "0.10.0", path = "../externalities", default-feat
 rand = "0.7.2"
 rand_chacha = "0.2.2"
 
-
 [features]
 default = ["std"]
 std = [
diff --git a/substrate/primitives/keystore/src/lib.rs b/substrate/primitives/keystore/src/lib.rs
index 6c27e3df7ce0d5fa80bc19002e342fc06ea23fe2..6540e71bc3fe0e9927db33cf2dd0e8b73545aeea 100644
--- a/substrate/primitives/keystore/src/lib.rs
+++ b/substrate/primitives/keystore/src/lib.rs
@@ -29,19 +29,19 @@ use sp_core::{
 use std::sync::Arc;
 
 /// CryptoStore error
-#[derive(Debug, derive_more::Display)]
+#[derive(Debug, thiserror::Error)]
 pub enum Error {
 	/// Public key type is not supported
-	#[display(fmt = "Key not supported: {:?}", _0)]
+	#[error("Key not supported: {0:?}")]
 	KeyNotSupported(KeyTypeId),
 	/// Validation error
-	#[display(fmt = "Validation error: {}", _0)]
+	#[error("Validation error: {0}")]
 	ValidationError(String),
 	/// Keystore unavailable
-	#[display(fmt = "Keystore unavailable")]
+	#[error("Keystore unavailable")]
 	Unavailable,
 	/// Programming errors
-	#[display(fmt = "An unknown keystore error occurred: {}", _0)]
+	#[error("An unknown keystore error occurred: {0}")]
 	Other(String),
 }
 
diff --git a/substrate/test-utils/runtime/transaction-pool/Cargo.toml b/substrate/test-utils/runtime/transaction-pool/Cargo.toml
index 39221a2d157948d7edd4c1faf6870f651c2e9f71..2a94f24845871bd642df47a1bbd4515ccb2e0530 100644
--- a/substrate/test-utils/runtime/transaction-pool/Cargo.toml
+++ b/substrate/test-utils/runtime/transaction-pool/Cargo.toml
@@ -20,4 +20,4 @@ sp-runtime = { version = "4.1.0-dev", path = "../../../primitives/runtime" }
 sc-transaction-pool = { version = "4.0.0-dev", path = "../../../client/transaction-pool" }
 sc-transaction-pool-api = { version = "4.0.0-dev", path = "../../../client/transaction-pool/api" }
 futures = "0.3.16"
-derive_more = "0.99.16"
+thiserror = "1.0"
diff --git a/substrate/test-utils/runtime/transaction-pool/src/lib.rs b/substrate/test-utils/runtime/transaction-pool/src/lib.rs
index ba317f57f531a3046efa20139023093082fa77be..40084276234997d93fe19c3acc9dc505e23f59b6 100644
--- a/substrate/test-utils/runtime/transaction-pool/src/lib.rs
+++ b/substrate/test-utils/runtime/transaction-pool/src/lib.rs
@@ -40,8 +40,9 @@ use substrate_test_runtime_client::{
 };
 
 /// Error type used by [`TestApi`].
-#[derive(Debug, derive_more::From, derive_more::Display)]
-pub struct Error(sc_transaction_pool_api::error::Error);
+#[derive(Debug, thiserror::Error)]
+#[error(transparent)]
+pub struct Error(#[from] sc_transaction_pool_api::error::Error);
 
 impl sc_transaction_pool_api::error::IntoPoolError for Error {
 	fn into_pool_error(self) -> Result<sc_transaction_pool_api::error::Error, Self> {
@@ -49,12 +50,6 @@ impl sc_transaction_pool_api::error::IntoPoolError for Error {
 	}
 }
 
-impl std::error::Error for Error {
-	fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-		Some(&self.0)
-	}
-}
-
 pub enum IsBestBlock {
 	Yes,
 	No,
diff --git a/substrate/utils/prometheus/Cargo.toml b/substrate/utils/prometheus/Cargo.toml
index 4ae38f64553274edd403336e3c9e8d99329364fb..27b5f94305fdd0fd184cf7314a968d9e00fd2529 100644
--- a/substrate/utils/prometheus/Cargo.toml
+++ b/substrate/utils/prometheus/Cargo.toml
@@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 log = "0.4.8"
 prometheus = { version = "0.13.0", default-features = false }
 futures-util = { version = "0.3.19", default-features = false, features = ["io"] }
-derive_more = "0.99"
+thiserror = "1.0"
 async-std = { version = "1.10.0", features = ["unstable"] }
 tokio = "1.15"
 hyper = { version = "0.14.16", default-features = false, features = ["http1", "server", "tcp"] }
diff --git a/substrate/utils/prometheus/src/lib.rs b/substrate/utils/prometheus/src/lib.rs
index f1d87ac9f729c323d7dec10537eb15e9efe3fea8..3d28d9cd6f1c8a0565db3dbfb8dc1a0738d8bc2f 100644
--- a/substrate/utils/prometheus/src/lib.rs
+++ b/substrate/utils/prometheus/src/lib.rs
@@ -47,27 +47,22 @@ pub fn register<T: Clone + Collector + 'static>(
 	Ok(metric)
 }
 
-#[derive(Debug, derive_more::Display, derive_more::From)]
+#[derive(Debug, thiserror::Error)]
 pub enum Error {
 	/// Hyper internal error.
-	Hyper(hyper::Error),
+	#[error(transparent)]
+	Hyper(#[from] hyper::Error),
+
 	/// Http request error.
-	Http(hyper::http::Error),
+	#[error(transparent)]
+	Http(#[from] hyper::http::Error),
+
 	/// i/o error.
-	Io(std::io::Error),
-	#[display(fmt = "Prometheus port {} already in use.", _0)]
-	PortInUse(SocketAddr),
-}
+	#[error(transparent)]
+	Io(#[from] std::io::Error),
 
-impl std::error::Error for Error {
-	fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-		match self {
-			Error::Hyper(error) => Some(error),
-			Error::Http(error) => Some(error),
-			Error::Io(error) => Some(error),
-			Error::PortInUse(_) => None,
-		}
-	}
+	#[error("Prometheus port {0} already in use.")]
+	PortInUse(SocketAddr),
 }
 
 async fn request_metrics(req: Request<Body>, registry: Registry) -> Result<Response<Body>, Error> {