From 8ea89a45d648a1b8118989651bc410e39cf16893 Mon Sep 17 00:00:00 2001
From: Xavier Lau <xavier@inv.cafe>
Date: Wed, 23 Nov 2022 23:49:10 +0800
Subject: [PATCH 1/3] Use `array-bytes` for array/bytes/hex operations

---
 .github/workflows/ci.yml   |  10 +--
 ethbloom/Cargo.toml        |  21 +++--
 ethbloom/src/lib.rs        |  10 ++-
 ethereum-types/Cargo.toml  |   4 +-
 fixed-hash/Cargo.toml      |  18 ++--
 fixed-hash/README.md       |   3 +-
 fixed-hash/src/hash.rs     |  27 ++----
 fixed-hash/src/lib.rs      |   4 +-
 fixed-hash/src/tests.rs    |   2 +-
 primitive-types/Cargo.toml |  11 +--
 rlp/Cargo.toml             |   6 +-
 rlp/src/rlpin.rs           |   4 +-
 rlp/tests/tests.rs         | 163 +++++++++++++++++++------------------
 uint/README.md             |   2 +-
 14 files changed, 149 insertions(+), 136 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6af8dc363..938b2051a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -66,7 +66,7 @@ jobs:
           args: -p uint --all-features
 
       - name: Test fixed-hash no_std
-        run: cargo test -p fixed-hash --no-default-features --features='byteorder,rustc-hex'
+        run: cargo test -p fixed-hash --no-default-features --features='array-bytes,byteorder'
 
       - name: Test fixed-hash all-features
         uses: actions-rs/cargo@v1
@@ -114,16 +114,16 @@ jobs:
           command: test
           args: -p parity-util-mem --target=aarch64-linux-android
 
-      - name: Test parity-util-mem estimate-heapsize 
+      - name: Test parity-util-mem estimate-heapsize
         run: cargo test -p parity-util-mem --features='estimate-heapsize'
 
-      - name: Test parity-util-mem jemalloc-global 
+      - name: Test parity-util-mem jemalloc-global
         run: cargo test -p parity-util-mem --features='jemalloc-global'
 
-      - name: Test parity-util-mem mimalloc-global 
+      - name: Test parity-util-mem mimalloc-global
         run: cargo test -p parity-util-mem --features='mimalloc-global'
 
-      - name: Test parity-util-mem dlmalloc-global 
+      - name: Test parity-util-mem dlmalloc-global
         run: cargo test -p parity-util-mem --no-default-features --features='dlmalloc-global'
 
   test_windows:
diff --git a/ethbloom/Cargo.toml b/ethbloom/Cargo.toml
index 0b9044b45..713fea931 100644
--- a/ethbloom/Cargo.toml
+++ b/ethbloom/Cargo.toml
@@ -20,18 +20,27 @@ impl-codec = { version = "0.6.0", path = "../primitive-types/impls/codec", defau
 scale-info = { version = ">=1.0, <3", features = ["derive"], default-features = false, optional = true }
 
 [dev-dependencies]
+array-bytes = "4.2"
 criterion = "0.4.0"
 rand = "0.8.0"
-hex-literal = "0.3.1"
 
 [features]
-default = ["std", "rlp", "serialize", "rustc-hex"]
-std = ["fixed-hash/std", "crunchy/std"]
-serialize = ["impl-serde"]
-rustc-hex = ["fixed-hash/rustc-hex"]
+default = [
+	"std",
+	"array-bytes",
+	"rlp",
+	"serialize",
+]
+std = [
+	"crunchy/std",
+	"fixed-hash/std",
+]
+
 arbitrary = ["fixed-hash/arbitrary"]
-rlp = ["impl-rlp"]
+array-bytes = ["fixed-hash/array-bytes"]
 codec = ["impl-codec", "scale-info"]
+rlp = ["impl-rlp"]
+serialize = ["impl-serde"]
 
 [[bench]]
 name = "bloom"
diff --git a/ethbloom/src/lib.rs b/ethbloom/src/lib.rs
index 4f22f3247..436411617 100644
--- a/ethbloom/src/lib.rs
+++ b/ethbloom/src/lib.rs
@@ -273,9 +273,11 @@ impl<'a> From<&'a Bloom> for BloomRef<'a> {
 
 #[cfg(test)]
 mod tests {
-	use super::{Bloom, Input};
 	use core::str::FromStr;
-	use hex_literal::hex;
+
+	use super::{Bloom, Input};
+
+	use array_bytes::hex2bytes_unchecked;
 
 	#[test]
 	#[rustfmt::skip]
@@ -298,8 +300,8 @@ mod tests {
 			 00000000000000000000000000000000\
 			 00000000000000000000000000000000",
 		).unwrap();
-		let address = hex!("ef2d6d194084c2de36e0dabfce45d046b37d1106");
-		let topic = hex!("02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc");
+		let address = hex2bytes_unchecked("ef2d6d194084c2de36e0dabfce45d046b37d1106");
+		let topic = hex2bytes_unchecked("02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc");
 
 		let mut my_bloom = Bloom::default();
 		assert!(!my_bloom.contains_input(Input::Raw(&address)));
diff --git a/ethereum-types/Cargo.toml b/ethereum-types/Cargo.toml
index 68c76036c..3a8404b43 100644
--- a/ethereum-types/Cargo.toml
+++ b/ethereum-types/Cargo.toml
@@ -10,9 +10,9 @@ rust-version = "1.60.0"
 
 [dependencies]
 ethbloom = { path = "../ethbloom", version = "0.13", optional = true, default-features = false }
-fixed-hash = { path = "../fixed-hash", version = "0.8", default-features = false, features = ["byteorder", "rustc-hex"] }
+fixed-hash = { path = "../fixed-hash", version = "0.8", default-features = false, features = ["array-bytes", "byteorder"] }
 uint-crate = { path = "../uint", package = "uint", version = "0.9", default-features = false }
-primitive-types = { path = "../primitive-types", version = "0.12", features = ["byteorder", "rustc-hex"], default-features = false }
+primitive-types = { path = "../primitive-types", version = "0.12", features = ["array-bytes", "byteorder"], default-features = false }
 impl-serde = { path = "../primitive-types/impls/serde", version = "0.4.0", default-features = false, optional = true }
 impl-rlp = { path = "../primitive-types/impls/rlp", version = "0.3", default-features = false, optional = true }
 impl-codec = { version = "0.6.0", path = "../primitive-types/impls/codec", default-features = false, optional = true }
diff --git a/fixed-hash/Cargo.toml b/fixed-hash/Cargo.toml
index f878d513a..7a29e12d1 100644
--- a/fixed-hash/Cargo.toml
+++ b/fixed-hash/Cargo.toml
@@ -15,21 +15,29 @@ rust-version = "1.56.1"
 features = ["quickcheck", "api-dummy"]
 
 [dependencies]
+arbitrary = { version = "1.0", optional = true }
+array-bytes = { version = "4.2", optional = true }
 byteorder = { version = "1.4.2", optional = true, default-features = false }
 quickcheck = { version = "1", optional = true }
 rand = { version = "0.8.0", optional = true, default-features = false }
-rustc-hex = { version = "2.0.1", optional = true, default-features = false }
 static_assertions = "1.0.0"
-arbitrary = { version = "1.0", optional = true }
 
 [dev-dependencies]
-rand_xorshift = "0.3.0"
 criterion = "0.4.0"
 rand = { version = "0.8.0", default-features = false, features = ["std_rng"] }
+rand_xorshift = "0.3.0"
 
 [features]
-default = ["std", "rand", "rustc-hex", "byteorder"]
-std = ["rustc-hex/std", "rand/std", "byteorder/std"]
+default = [
+	"std",
+	"array-bytes",
+	"byteorder",
+	"rand",
+]
+std = [
+	"byteorder/std",
+	"rand/std",
+]
 
 api-dummy = [] # Feature used by docs.rs to display documentation of hash types
 
diff --git a/fixed-hash/README.md b/fixed-hash/README.md
index 1974bea8f..6b5686885 100644
--- a/fixed-hash/README.md
+++ b/fixed-hash/README.md
@@ -39,7 +39,7 @@ construct_fixed_hash!{
 
 ## Features
 
-By default this is an standard library depending crate.  
+By default this is an standard library depending crate.
 For a `#[no_std]` environment use it as follows:
 
 ```
@@ -50,7 +50,6 @@ fixed-hash = { version = "0.3", default-features = false }
 
 - `std`: Use the standard library instead of the core library.
 	- Using this feature enables the following features
-		- `rustc-hex/std`
 		- `rand/std`
 		- `byteorder/std`
     - Enabled by default.
diff --git a/fixed-hash/src/hash.rs b/fixed-hash/src/hash.rs
index 9dc356cdc..7d6a880ed 100644
--- a/fixed-hash/src/hash.rs
+++ b/fixed-hash/src/hash.rs
@@ -547,34 +547,34 @@ macro_rules! impl_cmp_for_fixed_hash {
 	};
 }
 
-// Implementation for disabled rustc-hex crate support.
+// Implementation for disabled array-bytes crate support.
 //
 // # Note
 //
 // Feature guarded macro definitions instead of feature guarded impl blocks
-// to work around the problems of introducing `rustc-hex` crate feature in
+// to work around the problems of introducing `array-bytes` crate feature in
 // a user crate.
-#[cfg(not(feature = "rustc-hex"))]
+#[cfg(not(feature = "array-bytes"))]
 #[macro_export]
 #[doc(hidden)]
 macro_rules! impl_rustc_hex_for_fixed_hash {
 	( $name:ident ) => {};
 }
 
-// Implementation for enabled rustc-hex crate support.
+// Implementation for enabled array-bytes crate support.
 //
 // # Note
 //
 // Feature guarded macro definitions instead of feature guarded impl blocks
-// to work around the problems of introducing `rustc-hex` crate feature in
+// to work around the problems of introducing `array-bytes` crate feature in
 // a user crate.
-#[cfg(feature = "rustc-hex")]
+#[cfg(feature = "array-bytes")]
 #[macro_export]
 #[doc(hidden)]
 macro_rules! impl_rustc_hex_for_fixed_hash {
 	( $name:ident ) => {
 		impl $crate::core_::str::FromStr for $name {
-			type Err = $crate::rustc_hex::FromHexError;
+			type Err = $crate::array_bytes::Error;
 
 			/// Creates a hash type instance from the given string.
 			///
@@ -586,17 +586,8 @@ macro_rules! impl_rustc_hex_for_fixed_hash {
 			///
 			/// - When encountering invalid non hex-digits
 			/// - Upon empty string input or invalid input length in general
-			fn from_str(input: &str) -> $crate::core_::result::Result<$name, $crate::rustc_hex::FromHexError> {
-				let input = input.strip_prefix("0x").unwrap_or(input);
-				let mut iter = $crate::rustc_hex::FromHexIter::new(input);
-				let mut result = Self::zero();
-				for byte in result.as_mut() {
-					*byte = iter.next().ok_or(Self::Err::InvalidHexLength)??;
-				}
-				if iter.next().is_some() {
-					return Err(Self::Err::InvalidHexLength)
-				}
-				Ok(result)
+			fn from_str(input: &str) -> $crate::core_::result::Result<$name, $crate::array_bytes::Error> {
+				$crate::array_bytes::hex_n_into::<Self, { Self::len_bytes() }>(input)
 			}
 		}
 	};
diff --git a/fixed-hash/src/lib.rs b/fixed-hash/src/lib.rs
index 228f551e0..f835a814a 100644
--- a/fixed-hash/src/lib.rs
+++ b/fixed-hash/src/lib.rs
@@ -34,9 +34,9 @@ pub use static_assertions::const_assert;
 #[doc(hidden)]
 pub use byteorder;
 
-#[cfg(feature = "rustc-hex")]
+#[cfg(feature = "array-bytes")]
 #[doc(hidden)]
-pub use rustc_hex;
+pub use array_bytes;
 
 #[cfg(feature = "rand")]
 #[doc(hidden)]
diff --git a/fixed-hash/src/tests.rs b/fixed-hash/src/tests.rs
index 5a5f5d94d..3faa8952f 100644
--- a/fixed-hash/src/tests.rs
+++ b/fixed-hash/src/tests.rs
@@ -249,7 +249,7 @@ mod rand {
 	}
 }
 
-#[cfg(feature = "rustc-hex")]
+#[cfg(feature = "array-bytes")]
 mod from_str {
 	use super::*;
 
diff --git a/primitive-types/Cargo.toml b/primitive-types/Cargo.toml
index ea159ade9..7927904e0 100644
--- a/primitive-types/Cargo.toml
+++ b/primitive-types/Cargo.toml
@@ -20,16 +20,17 @@ scale-info-crate = { package = "scale-info", version = ">=0.9, <3", features = [
 [features]
 default = ["std"]
 std = ["uint/std", "fixed-hash/std", "impl-codec?/std"]
+
+arbitrary = ["fixed-hash/arbitrary", "uint/arbitrary"]
+array-bytes = ["fixed-hash/array-bytes"]
 byteorder = ["fixed-hash/byteorder"]
-rustc-hex = ["fixed-hash/rustc-hex"]
-serde = ["std", "impl-serde", "impl-serde/std"]
-serde_no_std = ["impl-serde"]
 codec = ["impl-codec"]
 scale-info = ["codec", "scale-info-crate"]
-rlp = ["impl-rlp"]
-arbitrary = ["fixed-hash/arbitrary", "uint/arbitrary"]
 fp-conversion = ["std"]
 num-traits = ["impl-num-traits"]
+rlp = ["impl-rlp"]
+serde = ["std", "impl-serde", "impl-serde/std"]
+serde_no_std = ["impl-serde"]
 
 [[test]]
 name = "scale_info"
diff --git a/rlp/Cargo.toml b/rlp/Cargo.toml
index c61433ecd..1ff97fd8d 100644
--- a/rlp/Cargo.toml
+++ b/rlp/Cargo.toml
@@ -9,18 +9,18 @@ edition = "2021"
 rust-version = "1.56.1"
 
 [dependencies]
+array-bytes = { version = "4.2" }
 bytes = { version = "1", default-features = false }
-rustc-hex = { version = "2.0.1", default-features = false }
 rlp-derive = { version = "0.1", path = "../rlp-derive", optional = true }
 
 [dev-dependencies]
 criterion = "0.4.0"
-hex-literal = "0.3.1"
 primitive-types = { path = "../primitive-types", version = "0.12", features = ["impl-rlp"] }
 
 [features]
 default = ["std"]
-std = ["bytes/std", "rustc-hex/std"]
+std = ["bytes/std"]
+
 derive = ["rlp-derive"]
 
 [[bench]]
diff --git a/rlp/src/rlpin.rs b/rlp/src/rlpin.rs
index 53b8731fc..17c2c1861 100644
--- a/rlp/src/rlpin.rs
+++ b/rlp/src/rlpin.rs
@@ -10,8 +10,6 @@
 use alloc::{string::String, vec::Vec};
 use core::{cell::Cell, fmt};
 
-use rustc_hex::ToHex;
-
 use crate::{error::DecoderError, impls::decode_usize, traits::Decodable};
 
 /// rlp offset
@@ -110,7 +108,7 @@ impl<'a> fmt::Display for Rlp<'a> {
 	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
 		match self.prototype() {
 			Ok(Prototype::Null) => write!(f, "null"),
-			Ok(Prototype::Data(_)) => write!(f, "\"0x{}\"", self.data().unwrap().to_hex::<String>()),
+			Ok(Prototype::Data(_)) => write!(f, "\"{}\"", array_bytes::bytes2hex("0x", self.data().unwrap())),
 			Ok(Prototype::List(len)) => {
 				write!(f, "[")?;
 				for i in 0..len - 1 {
diff --git a/rlp/tests/tests.rs b/rlp/tests/tests.rs
index a5eface28..bf44361da 100644
--- a/rlp/tests/tests.rs
+++ b/rlp/tests/tests.rs
@@ -8,21 +8,21 @@
 
 use core::{cmp, fmt};
 
+use array_bytes::{hex2bytes_unchecked, hex_n_into_unchecked};
 use bytes::{Bytes, BytesMut};
-use hex_literal::hex;
 use primitive_types::{H160, U256};
 use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};
 
 #[test]
 fn test_rlp_display() {
-	let data = hex!("f84d0589010efbef67941f79b2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
+	let data = hex2bytes_unchecked("f84d0589010efbef67941f79b2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
 	let rlp = Rlp::new(&data);
 	assert_eq!(format!("{}", rlp), "[\"0x05\", \"0x010efbef67941f79b2\", \"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\", \"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470\"]");
 }
 
 #[test]
 fn length_overflow() {
-	let bs = hex!("bfffffffffffffffffffffffe5");
+	let bs = hex2bytes_unchecked("bfffffffffffffffffffffffe5");
 	let rlp = Rlp::new(&bs);
 	let res: Result<u8, DecoderError> = rlp.as_val();
 	assert_eq!(Err(DecoderError::RlpInvalidLength), res);
@@ -173,9 +173,9 @@ where
 #[test]
 fn encode_u16() {
 	let tests = vec![
-		ETestPair::from((0_u16, hex!("80"))),
-		ETestPair::from((0x100_u16, hex!("820100"))),
-		ETestPair::from((0xffff_u16, hex!("82ffff"))),
+		ETestPair::from((0_u16, hex2bytes_unchecked("80"))),
+		ETestPair::from((0x100_u16, hex2bytes_unchecked("820100"))),
+		ETestPair::from((0xffff_u16, hex2bytes_unchecked("82ffff"))),
 	];
 	run_encode_tests(tests);
 }
@@ -183,9 +183,9 @@ fn encode_u16() {
 #[test]
 fn encode_u32() {
 	let tests = vec![
-		ETestPair::from((0_u32, hex!("80"))),
-		ETestPair::from((0x0001_0000_u32, hex!("83010000"))),
-		ETestPair::from((0x00ff_ffff_u32, hex!("83ffffff"))),
+		ETestPair::from((0_u32, hex2bytes_unchecked("80"))),
+		ETestPair::from((0x0001_0000_u32, hex2bytes_unchecked("83010000"))),
+		ETestPair::from((0x00ff_ffff_u32, hex2bytes_unchecked("83ffffff"))),
 	];
 	run_encode_tests(tests);
 }
@@ -193,9 +193,9 @@ fn encode_u32() {
 #[test]
 fn encode_u64() {
 	let tests = vec![
-		ETestPair::from((0_u64, hex!("80"))),
-		ETestPair::from((0x0100_0000_u64, hex!("8401000000"))),
-		ETestPair::from((0xFFFF_FFFF_u64, hex!("84ffffffff"))),
+		ETestPair::from((0_u64, hex2bytes_unchecked("80"))),
+		ETestPair::from((0x0100_0000_u64, hex2bytes_unchecked("8401000000"))),
+		ETestPair::from((0xFFFF_FFFF_u64, hex2bytes_unchecked("84ffffffff"))),
 	];
 	run_encode_tests(tests);
 }
@@ -203,9 +203,9 @@ fn encode_u64() {
 #[test]
 fn encode_u128() {
 	let tests = vec![
-		ETestPair::from((0_u128, hex!("80"))),
-		ETestPair::from((0x0100_0000_0000_0000_u128, hex!("880100000000000000"))),
-		ETestPair::from((0xFFFF_FFFF_FFFF_FFFF_u128, hex!("88ffffffffffffffff"))),
+		ETestPair::from((0_u128, hex2bytes_unchecked("80"))),
+		ETestPair::from((0x0100_0000_0000_0000_u128, hex2bytes_unchecked("880100000000000000"))),
+		ETestPair::from((0xFFFF_FFFF_FFFF_FFFF_u128, hex2bytes_unchecked("88ffffffffffffffff"))),
 	];
 	run_encode_tests(tests);
 }
@@ -213,12 +213,12 @@ fn encode_u128() {
 #[test]
 fn encode_u256() {
 	let tests = vec![
-		ETestPair::from((U256::from(0_u64), hex!("80"))),
-		ETestPair::from((U256::from(0x0100_0000_u64), hex!("8401000000"))),
-		ETestPair::from((U256::from(0xffff_ffff_u64), hex!("84ffffffff"))),
+		ETestPair::from((U256::from(0_u64), hex2bytes_unchecked("80"))),
+		ETestPair::from((U256::from(0x0100_0000_u64), hex2bytes_unchecked("8401000000"))),
+		ETestPair::from((U256::from(0xffff_ffff_u64), hex2bytes_unchecked("84ffffffff"))),
 		ETestPair::from((
-			hex!("  8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").into(),
-			hex!("a08090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"),
+			hex_n_into_unchecked::<_, 32>("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"),
+			hex2bytes_unchecked("a08090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"),
 		)),
 	];
 	run_encode_tests(tests);
@@ -230,7 +230,7 @@ fn encode_str() {
 		ETestPair::from(("cat", vec![0x83, b'c', b'a', b't'])),
 		ETestPair::from(("dog", vec![0x83, b'd', b'o', b'g'])),
 		ETestPair::from(("Marek", vec![0x85, b'M', b'a', b'r', b'e', b'k'])),
-		ETestPair::from(("", hex!("80"))),
+		ETestPair::from(("", hex2bytes_unchecked("80"))),
 		ETestPair::from((
 			"Lorem ipsum dolor sit amet, consectetur adipisicing elit",
 			vec![
@@ -271,8 +271,8 @@ fn encode_into_existing_buffer() {
 #[test]
 fn encode_address() {
 	let tests = vec![ETestPair::from((
-		H160::from(hex!("ef2d6d194084c2de36e0dabfce45d046b37d1106")),
-		hex!("94ef2d6d194084c2de36e0dabfce45d046b37d1106"),
+		H160::from(hex_n_into_unchecked::<H160, 20>("ef2d6d194084c2de36e0dabfce45d046b37d1106")),
+		hex2bytes_unchecked("94ef2d6d194084c2de36e0dabfce45d046b37d1106"),
 	))];
 	run_encode_tests(tests);
 }
@@ -281,10 +281,10 @@ fn encode_address() {
 #[test]
 fn encode_vector_u8() {
 	let tests = vec![
-		ETestPair::from((vec![], hex!("80"))),
-		ETestPair::from((vec![0u8], hex!("00"))),
-		ETestPair::from((vec![0x15], hex!("15"))),
-		ETestPair::from((vec![0x40, 0x00], hex!("824000"))),
+		ETestPair::from((vec![], hex2bytes_unchecked("80"))),
+		ETestPair::from((vec![0u8], hex2bytes_unchecked("00"))),
+		ETestPair::from((vec![0x15], hex2bytes_unchecked("15"))),
+		ETestPair::from((vec![0x40, 0x00], hex2bytes_unchecked("824000"))),
 	];
 	run_encode_tests(tests);
 }
@@ -292,10 +292,10 @@ fn encode_vector_u8() {
 #[test]
 fn encode_bytes() {
 	let tests = vec![
-		ETestPair::from((Bytes::from_static(&hex!("")), hex!("80"))),
-		ETestPair::from((Bytes::from_static(&hex!("00")), hex!("00"))),
-		ETestPair::from((Bytes::from_static(&hex!("15")), hex!("15"))),
-		ETestPair::from((Bytes::from_static(&hex!("4000")), hex!("824000"))),
+		ETestPair::from((Bytes::from_static([].as_slice()), hex2bytes_unchecked("80"))),
+		ETestPair::from((Bytes::from_static([0].as_slice()), hex2bytes_unchecked("00"))),
+		ETestPair::from((Bytes::from_static([21].as_slice()), hex2bytes_unchecked("15"))),
+		ETestPair::from((Bytes::from_static([64, 0].as_slice()), hex2bytes_unchecked("824000"))),
 	];
 	run_encode_tests(tests);
 }
@@ -303,10 +303,10 @@ fn encode_bytes() {
 #[test]
 fn encode_bytesmut() {
 	let tests = vec![
-		ETestPair::from((BytesMut::from(&[] as &[u8]), hex!("80"))),
-		ETestPair::from((BytesMut::from(&hex!("00") as &[u8]), hex!("00"))),
-		ETestPair::from((BytesMut::from(&hex!("15") as &[u8]), hex!("15"))),
-		ETestPair::from((BytesMut::from(&hex!("4000") as &[u8]), hex!("824000"))),
+		ETestPair::from((BytesMut::from([].as_slice()), hex2bytes_unchecked("80"))),
+		ETestPair::from((BytesMut::from([0].as_slice()), hex2bytes_unchecked("00"))),
+		ETestPair::from((BytesMut::from([21].as_slice()), hex2bytes_unchecked("15"))),
+		ETestPair::from((BytesMut::from([64, 0].as_slice()), hex2bytes_unchecked("824000"))),
 	];
 	run_encode_tests(tests);
 }
@@ -314,10 +314,10 @@ fn encode_bytesmut() {
 #[test]
 fn encode_vector_u64() {
 	let tests = vec![
-		VETestPair::from((vec![], hex!("c0"))),
-		VETestPair::from((vec![15_u64], hex!("c10f"))),
-		VETestPair::from((vec![1, 2, 3, 7, 0xff], hex!("c60102030781ff"))),
-		VETestPair::from((vec![0xffff_ffff, 1, 2, 3, 7, 0xff], hex!("cb84ffffffff0102030781ff"))),
+		VETestPair::from((vec![], hex2bytes_unchecked("c0"))),
+		VETestPair::from((vec![15_u64], hex2bytes_unchecked("c10f"))),
+		VETestPair::from((vec![1, 2, 3, 7, 0xff], hex2bytes_unchecked("c60102030781ff"))),
+		VETestPair::from((vec![0xffff_ffff, 1, 2, 3, 7, 0xff], hex2bytes_unchecked("cb84ffffffff0102030781ff"))),
 	];
 	run_encode_tests_list(tests);
 }
@@ -395,10 +395,10 @@ where
 #[test]
 fn decode_vector_u8() {
 	let tests = vec![
-		DTestPair::from((vec![], hex!("80"))),
-		DTestPair::from((vec![0_u8], hex!("00"))),
-		DTestPair::from((vec![0x15], hex!("15"))),
-		DTestPair::from((vec![0x40, 0x00], hex!("824000"))),
+		DTestPair::from((vec![], hex2bytes_unchecked("80"))),
+		DTestPair::from((vec![0_u8], hex2bytes_unchecked("00"))),
+		DTestPair::from((vec![0x15], hex2bytes_unchecked("15"))),
+		DTestPair::from((vec![0x40, 0x00], hex2bytes_unchecked("824000"))),
 	];
 	run_decode_tests(tests);
 }
@@ -406,10 +406,10 @@ fn decode_vector_u8() {
 #[test]
 fn decode_bytes() {
 	let tests = vec![
-		DTestPair::from((Bytes::from_static(&hex!("")), hex!("80"))),
-		DTestPair::from((Bytes::from_static(&hex!("00")), hex!("00"))),
-		DTestPair::from((Bytes::from_static(&hex!("15")), hex!("15"))),
-		DTestPair::from((Bytes::from_static(&hex!("4000")), hex!("824000"))),
+		DTestPair::from((Bytes::from_static([].as_slice()), hex2bytes_unchecked("80"))),
+		DTestPair::from((Bytes::from_static([0].as_slice()), hex2bytes_unchecked("00"))),
+		DTestPair::from((Bytes::from_static([21].as_slice()), hex2bytes_unchecked("15"))),
+		DTestPair::from((Bytes::from_static([64, 0].as_slice()), hex2bytes_unchecked("824000"))),
 	];
 	run_decode_tests(tests);
 }
@@ -417,10 +417,10 @@ fn decode_bytes() {
 #[test]
 fn decode_bytesmut() {
 	let tests = vec![
-		DTestPair::from((BytesMut::from(&hex!("") as &[u8]), hex!("80"))),
-		DTestPair::from((BytesMut::from(&hex!("00") as &[u8]), hex!("00"))),
-		DTestPair::from((BytesMut::from(&hex!("15") as &[u8]), hex!("15"))),
-		DTestPair::from((BytesMut::from(&hex!("4000") as &[u8]), hex!("824000"))),
+		DTestPair::from((BytesMut::from([].as_slice()), hex2bytes_unchecked("80"))),
+		DTestPair::from((BytesMut::from([0].as_slice()), hex2bytes_unchecked("00"))),
+		DTestPair::from((BytesMut::from([21].as_slice()), hex2bytes_unchecked("15"))),
+		DTestPair::from((BytesMut::from([64, 0].as_slice()), hex2bytes_unchecked("824000"))),
 	];
 	run_decode_tests(tests);
 }
@@ -428,31 +428,36 @@ fn decode_bytesmut() {
 #[test]
 fn decode_untrusted_u8() {
 	let tests = vec![
-		DTestPair::from((0x0_u8, hex!("80"))),
-		DTestPair::from((0x77_u8, hex!("77"))),
-		DTestPair::from((0xcc_u8, hex!("81cc"))),
+		DTestPair::from((0x0_u8, hex2bytes_unchecked("80"))),
+		DTestPair::from((0x77_u8, hex2bytes_unchecked("77"))),
+		DTestPair::from((0xcc_u8, hex2bytes_unchecked("81cc"))),
 	];
 	run_decode_tests(tests);
 }
 
 #[test]
 fn decode_untrusted_u16() {
-	let tests = vec![DTestPair::from((0x100u16, hex!("820100"))), DTestPair::from((0xffffu16, hex!("82ffff")))];
+	let tests = vec![
+		DTestPair::from((0x100u16, hex2bytes_unchecked("820100"))),
+		DTestPair::from((0xffffu16, hex2bytes_unchecked("82ffff"))),
+	];
 	run_decode_tests(tests);
 }
 
 #[test]
 fn decode_untrusted_u32() {
-	let tests =
-		vec![DTestPair::from((0x0001_0000u32, hex!("83010000"))), DTestPair::from((0x00ff_ffffu32, hex!("83ffffff")))];
+	let tests = vec![
+		DTestPair::from((0x0001_0000u32, hex2bytes_unchecked("83010000"))),
+		DTestPair::from((0x00ff_ffffu32, hex2bytes_unchecked("83ffffff"))),
+	];
 	run_decode_tests(tests);
 }
 
 #[test]
 fn decode_untrusted_u64() {
 	let tests = vec![
-		DTestPair::from((0x0100_0000_u64, hex!("8401000000"))),
-		DTestPair::from((0xFFFF_FFFF_u64, hex!("84ffffffff"))),
+		DTestPair::from((0x0100_0000_u64, hex2bytes_unchecked("8401000000"))),
+		DTestPair::from((0xFFFF_FFFF_u64, hex2bytes_unchecked("84ffffffff"))),
 	];
 	run_decode_tests(tests);
 }
@@ -460,8 +465,8 @@ fn decode_untrusted_u64() {
 #[test]
 fn decode_untrusted_u128() {
 	let tests = vec![
-		DTestPair::from((0x0100_0000_0000_0000_u128, hex!("880100000000000000"))),
-		DTestPair::from((0xFFFF_FFFF_FFFF_FFFF_u128, hex!("88ffffffffffffffff"))),
+		DTestPair::from((0x0100_0000_0000_0000_u128, hex2bytes_unchecked("880100000000000000"))),
+		DTestPair::from((0xFFFF_FFFF_FFFF_FFFF_u128, hex2bytes_unchecked("88ffffffffffffffff"))),
 	];
 	run_decode_tests(tests);
 }
@@ -469,12 +474,12 @@ fn decode_untrusted_u128() {
 #[test]
 fn decode_untrusted_u256() {
 	let tests = vec![
-		DTestPair::from((U256::from(0_u64), hex!("80"))),
-		DTestPair::from((U256::from(0x0100_0000_u64), hex!("8401000000"))),
-		DTestPair::from((U256::from(0xffff_ffff_u64), hex!("84ffffffff"))),
+		DTestPair::from((U256::from(0_u64), hex2bytes_unchecked("80"))),
+		DTestPair::from((U256::from(0x0100_0000_u64), hex2bytes_unchecked("8401000000"))),
+		DTestPair::from((U256::from(0xffff_ffff_u64), hex2bytes_unchecked("84ffffffff"))),
 		DTestPair::from((
-			hex!("  8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").into(),
-			hex!("a08090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"),
+			hex_n_into_unchecked::<_, 32>("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"),
+			hex2bytes_unchecked("a08090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"),
 		)),
 	];
 	run_decode_tests(tests);
@@ -486,7 +491,7 @@ fn decode_untrusted_str() {
 		DTestPair::from(("cat".to_owned(), vec![0x83, b'c', b'a', b't'])),
 		DTestPair::from(("dog".to_owned(), vec![0x83, b'd', b'o', b'g'])),
 		DTestPair::from(("Marek".to_owned(), vec![0x85, b'M', b'a', b'r', b'e', b'k'])),
-		DTestPair::from(("".to_owned(), hex!("80"))),
+		DTestPair::from(("".to_owned(), hex2bytes_unchecked("80"))),
 		DTestPair::from((
 			"Lorem ipsum dolor sit amet, consectetur adipisicing elit".to_owned(),
 			vec![
@@ -503,8 +508,8 @@ fn decode_untrusted_str() {
 #[test]
 fn decode_untrusted_address() {
 	let tests = vec![DTestPair::from((
-		H160::from(hex!("ef2d6d194084c2de36e0dabfce45d046b37d1106")),
-		hex!("94ef2d6d194084c2de36e0dabfce45d046b37d1106"),
+		hex_n_into_unchecked::<H160, 20>("ef2d6d194084c2de36e0dabfce45d046b37d1106"),
+		hex2bytes_unchecked("94ef2d6d194084c2de36e0dabfce45d046b37d1106"),
 	))];
 	run_decode_tests(tests);
 }
@@ -512,10 +517,10 @@ fn decode_untrusted_address() {
 #[test]
 fn decode_untrusted_vector_u64() {
 	let tests = vec![
-		VDTestPair::from((vec![], hex!("c0"))),
-		VDTestPair::from((vec![15_u64], hex!("c10f"))),
-		VDTestPair::from((vec![1, 2, 3, 7, 0xff], hex!("c60102030781ff"))),
-		VDTestPair::from((vec![0xffff_ffff, 1, 2, 3, 7, 0xff], hex!("cb84ffffffff0102030781ff"))),
+		VDTestPair::from((vec![], hex2bytes_unchecked("c0"))),
+		VDTestPair::from((vec![15_u64], hex2bytes_unchecked("c10f"))),
+		VDTestPair::from((vec![1, 2, 3, 7, 0xff], hex2bytes_unchecked("c60102030781ff"))),
+		VDTestPair::from((vec![0xffff_ffff, 1, 2, 3, 7, 0xff], hex2bytes_unchecked("cb84ffffffff0102030781ff"))),
 	];
 	run_decode_tests_list(tests);
 }
@@ -540,7 +545,7 @@ fn test_rlp_data_length_check() {
 
 #[test]
 fn test_rlp_long_data_length_check() {
-	let mut data = hex!("b8ff").to_vec();
+	let mut data = hex2bytes_unchecked("b8ff").to_vec();
 	for _ in 0..253 {
 		data.push(b'c');
 	}
@@ -553,7 +558,7 @@ fn test_rlp_long_data_length_check() {
 
 #[test]
 fn test_the_exact_long_string() {
-	let mut data = hex!("b8ff").to_vec();
+	let mut data = hex2bytes_unchecked("b8ff").to_vec();
 	for _ in 0..255 {
 		data.push(b'c');
 	}
@@ -566,7 +571,7 @@ fn test_the_exact_long_string() {
 
 #[test]
 fn test_rlp_2bytes_data_length_check() {
-	let mut data = hex!("b902ff").to_vec(); // 512+255
+	let mut data = hex2bytes_unchecked("b902ff").to_vec(); // 512+255
 	for _ in 0..700 {
 		data.push(b'c');
 	}
@@ -582,12 +587,12 @@ fn test_rlp_nested_empty_list_encode() {
 	let mut stream = RlpStream::new_list(2);
 	stream.append_list(&(Vec::new() as Vec<u32>));
 	stream.append(&0x28_u32);
-	assert_eq!(stream.out()[..], hex!("c2c028")[..]);
+	assert_eq!(stream.out()[..], hex2bytes_unchecked("c2c028")[..]);
 }
 
 #[test]
 fn test_rlp_list_length_overflow() {
-	let data = hex!("ffffffffffffffffff000000");
+	let data = hex2bytes_unchecked("ffffffffffffffffff000000");
 	let rlp = Rlp::new(&data);
 	let as_val: Result<String, DecoderError> = rlp.val_at(0);
 	assert_eq!(Err(DecoderError::RlpIsTooShort), as_val);
@@ -735,7 +740,7 @@ fn test_nested_list_roundtrip() {
 // https://github.com/paritytech/parity-ethereum/pull/9663
 #[test]
 fn test_list_at() {
-	let raw = hex!("f83e82022bd79020010db83c4d001500000000abcdef12820cfa8215a8d79020010db885a308d313198a2e037073488208ae82823a8443b9a355c5010203040531b9019afde696e582a78fa8d95ea13ce3297d4afb8ba6433e4154caa5ac6431af1b80ba76023fa4090c408f6b4bc3701562c031041d4702971d102c9ab7fa5eed4cd6bab8f7af956f7d565ee1917084a95398b6a21eac920fe3dd1345ec0a7ef39367ee69ddf092cbfe5b93e5e568ebc491983c09c76d922dc3");
+	let raw = hex2bytes_unchecked("f83e82022bd79020010db83c4d001500000000abcdef12820cfa8215a8d79020010db885a308d313198a2e037073488208ae82823a8443b9a355c5010203040531b9019afde696e582a78fa8d95ea13ce3297d4afb8ba6433e4154caa5ac6431af1b80ba76023fa4090c408f6b4bc3701562c031041d4702971d102c9ab7fa5eed4cd6bab8f7af956f7d565ee1917084a95398b6a21eac920fe3dd1345ec0a7ef39367ee69ddf092cbfe5b93e5e568ebc491983c09c76d922dc3");
 
 	let rlp = Rlp::new(&raw);
 	let _rlp1 = rlp.at(1).unwrap();
diff --git a/uint/README.md b/uint/README.md
index 34006f83d..8ac84bc20 100644
--- a/uint/README.md
+++ b/uint/README.md
@@ -65,7 +65,7 @@ see fuzz [README.md](fuzz/README.md)
 ## Crate Features
 
 - `std`: Use Rust's standard library.
-	- Enables `byteorder/std`, `rustc-hex/std`
+	- Enables `byteorder/std`
 	- Enabled by default.
 - `quickcheck`: Enable quickcheck-style property testing
 	- Use with `cargo test --release --features=quickcheck`.

From e503e0a0aefa1b0d20621450e05e7c9c51f0e99b Mon Sep 17 00:00:00 2001
From: Xavier Lau <xavier@inv.cafe>
Date: Thu, 24 Nov 2022 18:34:14 +0800
Subject: [PATCH 2/3] Fix compile

---
 ethbloom/benches/bloom.rs | 6 +++---
 ethbloom/src/lib.rs       | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/ethbloom/benches/bloom.rs b/ethbloom/benches/bloom.rs
index f3de3b7b0..1cd2da1b2 100644
--- a/ethbloom/benches/bloom.rs
+++ b/ethbloom/benches/bloom.rs
@@ -6,9 +6,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use array_bytes::hex2bytes_unchecked;
 use criterion::{criterion_group, criterion_main, Criterion};
 use ethbloom::{Bloom, Input};
-use hex_literal::hex;
 use tiny_keccak::{Hasher, Keccak};
 
 fn test_bloom() -> Bloom {
@@ -43,11 +43,11 @@ fn keccak256(input: &[u8]) -> [u8; 32] {
 }
 
 fn test_topic() -> Vec<u8> {
-	hex!("02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc").to_vec()
+	hex2bytes_unchecked("02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc")
 }
 
 fn test_address() -> Vec<u8> {
-	hex!("ef2d6d194084c2de36e0dabfce45d046b37d1106").to_vec()
+	hex2bytes_unchecked("ef2d6d194084c2de36e0dabfce45d046b37d1106")
 }
 
 fn test_dummy() -> Vec<u8> {
diff --git a/ethbloom/src/lib.rs b/ethbloom/src/lib.rs
index 436411617..1989c37d6 100644
--- a/ethbloom/src/lib.rs
+++ b/ethbloom/src/lib.rs
@@ -7,7 +7,7 @@
 // except according to those terms.
 
 //! ```
-//! use hex_literal::hex;
+//! use array_bytes::hex2bytes_unchecked;
 //! use ethbloom::{Bloom, Input};
 //!
 //! use std::str::FromStr;
@@ -29,8 +29,8 @@
 //! 	00000000000000000000000000000000\
 //! 	00000000000000000000000000000000"
 //! ).unwrap();
-//! let address = hex!("ef2d6d194084c2de36e0dabfce45d046b37d1106");
-//! let topic = hex!("02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc");
+//! let address = hex2bytes_unchecked("ef2d6d194084c2de36e0dabfce45d046b37d1106");
+//! let topic = hex2bytes_unchecked("02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc");
 //!
 //! let mut my_bloom = Bloom::default();
 //! assert!(!my_bloom.contains_input(Input::Raw(&address)));

From 2dd9650087186df38f07514ada54c2c993c450de Mon Sep 17 00:00:00 2001
From: Xavier Lau <xavier@inv.cafe>
Date: Sat, 26 Nov 2022 17:32:38 +0800
Subject: [PATCH 3/3] Optimize

---
 ethbloom/Cargo.toml    |  2 +-
 fixed-hash/Cargo.toml  |  2 +-
 fixed-hash/src/hash.rs |  8 ++++----
 rlp/Cargo.toml         |  2 +-
 rlp/tests/tests.rs     |  8 ++++----
 uint/Cargo.toml        |  9 ++++++---
 uint/src/lib.rs        |  2 +-
 uint/src/uint.rs       | 29 ++++++++++++++++-------------
 8 files changed, 34 insertions(+), 28 deletions(-)

diff --git a/ethbloom/Cargo.toml b/ethbloom/Cargo.toml
index 713fea931..832634774 100644
--- a/ethbloom/Cargo.toml
+++ b/ethbloom/Cargo.toml
@@ -20,7 +20,7 @@ impl-codec = { version = "0.6.0", path = "../primitive-types/impls/codec", defau
 scale-info = { version = ">=1.0, <3", features = ["derive"], default-features = false, optional = true }
 
 [dev-dependencies]
-array-bytes = "4.2"
+array-bytes = "6.0"
 criterion = "0.4.0"
 rand = "0.8.0"
 
diff --git a/fixed-hash/Cargo.toml b/fixed-hash/Cargo.toml
index 7a29e12d1..65ee01461 100644
--- a/fixed-hash/Cargo.toml
+++ b/fixed-hash/Cargo.toml
@@ -16,7 +16,7 @@ features = ["quickcheck", "api-dummy"]
 
 [dependencies]
 arbitrary = { version = "1.0", optional = true }
-array-bytes = { version = "4.2", optional = true }
+array-bytes = { version = "6.0", optional = true }
 byteorder = { version = "1.4.2", optional = true, default-features = false }
 quickcheck = { version = "1", optional = true }
 rand = { version = "0.8.0", optional = true, default-features = false }
diff --git a/fixed-hash/src/hash.rs b/fixed-hash/src/hash.rs
index 7d6a880ed..8fa987049 100644
--- a/fixed-hash/src/hash.rs
+++ b/fixed-hash/src/hash.rs
@@ -313,7 +313,7 @@ macro_rules! construct_fixed_hash {
 		impl_byteorder_for_fixed_hash!($name);
 		impl_rand_for_fixed_hash!($name);
 		impl_cmp_for_fixed_hash!($name);
-		impl_rustc_hex_for_fixed_hash!($name);
+		impl_array_bytes_for_fixed_hash!($name);
 		impl_quickcheck_for_fixed_hash!($name);
 		impl_arbitrary_for_fixed_hash!($name);
 	}
@@ -557,7 +557,7 @@ macro_rules! impl_cmp_for_fixed_hash {
 #[cfg(not(feature = "array-bytes"))]
 #[macro_export]
 #[doc(hidden)]
-macro_rules! impl_rustc_hex_for_fixed_hash {
+macro_rules! impl_array_bytes_for_fixed_hash {
 	( $name:ident ) => {};
 }
 
@@ -571,7 +571,7 @@ macro_rules! impl_rustc_hex_for_fixed_hash {
 #[cfg(feature = "array-bytes")]
 #[macro_export]
 #[doc(hidden)]
-macro_rules! impl_rustc_hex_for_fixed_hash {
+macro_rules! impl_array_bytes_for_fixed_hash {
 	( $name:ident ) => {
 		impl $crate::core_::str::FromStr for $name {
 			type Err = $crate::array_bytes::Error;
@@ -587,7 +587,7 @@ macro_rules! impl_rustc_hex_for_fixed_hash {
 			/// - When encountering invalid non hex-digits
 			/// - Upon empty string input or invalid input length in general
 			fn from_str(input: &str) -> $crate::core_::result::Result<$name, $crate::array_bytes::Error> {
-				$crate::array_bytes::hex_n_into::<Self, { Self::len_bytes() }>(input)
+				$crate::array_bytes::hex_n_into::<&str, Self, { Self::len_bytes() }>(input)
 			}
 		}
 	};
diff --git a/rlp/Cargo.toml b/rlp/Cargo.toml
index 1ff97fd8d..d9ce0f1d2 100644
--- a/rlp/Cargo.toml
+++ b/rlp/Cargo.toml
@@ -9,7 +9,7 @@ edition = "2021"
 rust-version = "1.56.1"
 
 [dependencies]
-array-bytes = { version = "4.2" }
+array-bytes = { version = "6.0" }
 bytes = { version = "1", default-features = false }
 rlp-derive = { version = "0.1", path = "../rlp-derive", optional = true }
 
diff --git a/rlp/tests/tests.rs b/rlp/tests/tests.rs
index bf44361da..5dddf346c 100644
--- a/rlp/tests/tests.rs
+++ b/rlp/tests/tests.rs
@@ -217,7 +217,7 @@ fn encode_u256() {
 		ETestPair::from((U256::from(0x0100_0000_u64), hex2bytes_unchecked("8401000000"))),
 		ETestPair::from((U256::from(0xffff_ffff_u64), hex2bytes_unchecked("84ffffffff"))),
 		ETestPair::from((
-			hex_n_into_unchecked::<_, 32>("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"),
+			hex_n_into_unchecked::<_, _, 32>("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"),
 			hex2bytes_unchecked("a08090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"),
 		)),
 	];
@@ -271,7 +271,7 @@ fn encode_into_existing_buffer() {
 #[test]
 fn encode_address() {
 	let tests = vec![ETestPair::from((
-		H160::from(hex_n_into_unchecked::<H160, 20>("ef2d6d194084c2de36e0dabfce45d046b37d1106")),
+		H160::from(hex_n_into_unchecked::<_, H160, 20>("ef2d6d194084c2de36e0dabfce45d046b37d1106")),
 		hex2bytes_unchecked("94ef2d6d194084c2de36e0dabfce45d046b37d1106"),
 	))];
 	run_encode_tests(tests);
@@ -478,7 +478,7 @@ fn decode_untrusted_u256() {
 		DTestPair::from((U256::from(0x0100_0000_u64), hex2bytes_unchecked("8401000000"))),
 		DTestPair::from((U256::from(0xffff_ffff_u64), hex2bytes_unchecked("84ffffffff"))),
 		DTestPair::from((
-			hex_n_into_unchecked::<_, 32>("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"),
+			hex_n_into_unchecked::<_, _, 32>("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"),
 			hex2bytes_unchecked("a08090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"),
 		)),
 	];
@@ -508,7 +508,7 @@ fn decode_untrusted_str() {
 #[test]
 fn decode_untrusted_address() {
 	let tests = vec![DTestPair::from((
-		hex_n_into_unchecked::<H160, 20>("ef2d6d194084c2de36e0dabfce45d046b37d1106"),
+		hex_n_into_unchecked::<_, H160, 20>("ef2d6d194084c2de36e0dabfce45d046b37d1106"),
 		hex2bytes_unchecked("94ef2d6d194084c2de36e0dabfce45d046b37d1106"),
 	))];
 	run_decode_tests(tests);
diff --git a/uint/Cargo.toml b/uint/Cargo.toml
index 0e4ed8aea..bb5758071 100644
--- a/uint/Cargo.toml
+++ b/uint/Cargo.toml
@@ -11,16 +11,19 @@ edition = "2021"
 rust-version = "1.56.1"
 
 [dependencies]
+arbitrary = { version = "1.0", optional = true }
+array-bytes = { version = "6.0" }
 byteorder = { version = "1.4.2", default-features = false }
 crunchy = { version = "0.2.2", default-features = false }
 quickcheck = { version = "1", optional = true }
-hex = { version = "0.4", default-features = false }
 static_assertions = "1.0.0"
-arbitrary = { version = "1.0", optional = true }
 
 [features]
 default = ["std"]
-std = ["byteorder/std", "crunchy/std", "hex/std"]
+std = [
+	"byteorder/std",
+	"crunchy/std"
+]
 
 [[example]]
 name = "modular"
diff --git a/uint/src/lib.rs b/uint/src/lib.rs
index e259c79d7..6c5dfda1b 100644
--- a/uint/src/lib.rs
+++ b/uint/src/lib.rs
@@ -19,7 +19,7 @@ pub use byteorder;
 pub use core as core_;
 
 #[doc(hidden)]
-pub use hex;
+pub use array_bytes;
 
 #[cfg(feature = "quickcheck")]
 #[doc(hidden)]
diff --git a/uint/src/uint.rs b/uint/src/uint.rs
index 2366543f4..58ed6f7fd 100644
--- a/uint/src/uint.rs
+++ b/uint/src/uint.rs
@@ -10,7 +10,7 @@
 
 // Rust Bitcoin Library
 // Written in 2014 by
-//	   Andrew Poelstra <apoelstra@wpsoftware.net>
+// 	   Andrew Poelstra <apoelstra@wpsoftware.net>
 //
 // To the extent possible under law, the author(s) have dedicated all
 // copyright and related and neighboring rights to this software to
@@ -82,7 +82,7 @@ impl FromStrRadixErr {
 impl fmt::Display for FromStrRadixErr {
 	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 		if let Some(ref src) = self.source {
-			return write!(f, "{}", src);
+			return write!(f, "{}", src)
 		}
 
 		match self.kind {
@@ -118,9 +118,10 @@ impl From<FromDecStrErr> for FromStrRadixErr {
 impl From<FromHexError> for FromStrRadixErr {
 	fn from(e: FromHexError) -> Self {
 		let kind = match e.inner {
-			hex::FromHexError::InvalidHexCharacter { .. } => FromStrRadixErrKind::InvalidCharacter,
-			hex::FromHexError::InvalidStringLength => FromStrRadixErrKind::InvalidLength,
-			hex::FromHexError::OddLength => FromStrRadixErrKind::InvalidLength,
+			array_bytes::Error::InvalidCharacter { .. } | array_bytes::Error::ParseIntError(_) =>
+				FromStrRadixErrKind::InvalidCharacter,
+			array_bytes::Error::InvalidLength | array_bytes::Error::MismatchedLength { .. } =>
+				FromStrRadixErrKind::InvalidLength,
 		};
 
 		Self { kind, source: Some(FromStrRadixErrSrc::Hex(e)) }
@@ -154,25 +155,27 @@ impl std::error::Error for FromDecStrErr {}
 
 #[derive(Debug)]
 pub struct FromHexError {
-	inner: hex::FromHexError,
+	inner: array_bytes::Error,
 }
 
 impl fmt::Display for FromHexError {
 	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-		write!(f, "{}", self.inner)
+		write!(f, "{:?}", self.inner)
 	}
 }
 
 #[cfg(feature = "std")]
 impl std::error::Error for FromHexError {
 	fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-		Some(&self.inner)
+		// Some(&self.inner)
+		// TODO: <https://github.com/rust-lang/project-error-handling/issues/3>
+		None
 	}
 }
 
 #[doc(hidden)]
-impl From<hex::FromHexError> for FromHexError {
-	fn from(inner: hex::FromHexError) -> Self {
+impl From<array_bytes::Error> for FromHexError {
+	fn from(inner: array_bytes::Error) -> Self {
 		Self { inner }
 	}
 }
@@ -1718,13 +1721,13 @@ macro_rules! construct_uint {
 				let encoded = value.as_bytes();
 
 				if encoded.len() > MAX_ENCODED_LEN {
-					return Err($crate::hex::FromHexError::InvalidStringLength.into());
+					return Err($crate::array_bytes::Error::InvalidLength.into());
 				}
 
 				if encoded.len() % 2 == 0 {
 					let out = &mut bytes[BYTES_LEN - encoded.len() / 2..];
 
-					$crate::hex::decode_to_slice(encoded, out).map_err(Self::Err::from)?;
+					$crate::array_bytes::hex2slice(encoded, out).map_err(Self::Err::from)?;
 				} else {
 					// Prepend '0' by overlaying our value on a scratch buffer filled with '0' characters.
 					let mut s = [b'0'; MAX_ENCODED_LEN];
@@ -1733,7 +1736,7 @@ macro_rules! construct_uint {
 
 					let out = &mut bytes[BYTES_LEN - encoded.len() / 2..];
 
-					$crate::hex::decode_to_slice(encoded, out).map_err(Self::Err::from)?;
+					$crate::array_bytes::hex2slice(encoded, out).map_err(Self::Err::from)?;
 				}
 
 				let bytes_ref: &[u8] = &bytes;