alloy_eips/
eip1898.rs

1//! [EIP-1898]: https://eips.ethereum.org/EIPS/eip-1898
2
3use alloy_primitives::{hex::FromHexError, ruint::ParseError, BlockHash, B256, U64};
4use alloy_rlp::{bytes, Decodable, Encodable, Error as RlpError};
5use core::{
6    fmt::{self, Formatter},
7    num::ParseIntError,
8    str::FromStr,
9};
10
11/// A helper struct to store the block number/hash and its parent hash.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
15#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
16pub struct BlockWithParent {
17    /// Parent hash.
18    pub parent: B256,
19    /// Block number/hash.
20    pub block: BlockNumHash,
21}
22
23impl BlockWithParent {
24    /// Creates a new [`BlockWithParent`] instance.
25    pub const fn new(parent: B256, block: BlockNumHash) -> Self {
26        Self { parent, block }
27    }
28}
29
30/// A block hash which may have a boolean `requireCanonical` field.
31///
32/// - If false, a RPC call should raise if a block matching the hash is not found.
33/// - If true, a RPC call should additionally raise if the block is not in the canonical chain.
34///
35/// <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1898.md#specification>
36#[derive(Clone, Copy, PartialEq, Eq)]
37#[cfg_attr(feature = "serde", derive(serde::Serialize))]
38#[cfg_attr(feature = "serde", serde(rename = "camelCase"))]
39pub struct RpcBlockHash {
40    /// A block hash
41    pub block_hash: BlockHash,
42    /// Whether the block must be a canonical block
43    pub require_canonical: Option<bool>,
44}
45
46impl RpcBlockHash {
47    /// Returns a [`RpcBlockHash`] from a [`B256`].
48    #[doc(alias = "from_block_hash")]
49    pub const fn from_hash(block_hash: B256, require_canonical: Option<bool>) -> Self {
50        Self { block_hash, require_canonical }
51    }
52}
53
54impl From<B256> for RpcBlockHash {
55    fn from(value: B256) -> Self {
56        Self::from_hash(value, None)
57    }
58}
59
60impl From<RpcBlockHash> for B256 {
61    fn from(value: RpcBlockHash) -> Self {
62        value.block_hash
63    }
64}
65
66impl AsRef<B256> for RpcBlockHash {
67    fn as_ref(&self) -> &B256 {
68        &self.block_hash
69    }
70}
71
72impl fmt::Display for RpcBlockHash {
73    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
74        let Self { block_hash, require_canonical } = self;
75        if *require_canonical == Some(true) {
76            f.write_str("canonical ")?;
77        }
78        write!(f, "hash {block_hash}")
79    }
80}
81
82impl fmt::Debug for RpcBlockHash {
83    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
84        match self.require_canonical {
85            Some(require_canonical) => f
86                .debug_struct("RpcBlockHash")
87                .field("block_hash", &self.block_hash)
88                .field("require_canonical", &require_canonical)
89                .finish(),
90            None => fmt::Debug::fmt(&self.block_hash, f),
91        }
92    }
93}
94
95/// A block Number (or tag - "latest", "earliest", "pending")
96///
97/// This enum allows users to specify a block in a flexible manner.
98#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
99pub enum BlockNumberOrTag {
100    /// Latest block
101    #[default]
102    Latest,
103    /// Finalized block accepted as canonical
104    Finalized,
105    /// Safe head block
106    Safe,
107    /// Earliest block (genesis)
108    Earliest,
109    /// Pending block (not yet part of the blockchain)
110    Pending,
111    /// Block by number from canonical chain
112    Number(u64),
113}
114
115impl BlockNumberOrTag {
116    /// Returns the numeric block number if explicitly set
117    pub const fn as_number(&self) -> Option<u64> {
118        match *self {
119            Self::Number(num) => Some(num),
120            _ => None,
121        }
122    }
123
124    /// Returns `true` if a numeric block number is set
125    pub const fn is_number(&self) -> bool {
126        matches!(self, Self::Number(_))
127    }
128
129    /// Returns `true` if it's "latest"
130    pub const fn is_latest(&self) -> bool {
131        matches!(self, Self::Latest)
132    }
133
134    /// Returns `true` if it's "finalized"
135    pub const fn is_finalized(&self) -> bool {
136        matches!(self, Self::Finalized)
137    }
138
139    /// Returns `true` if it's "safe"
140    pub const fn is_safe(&self) -> bool {
141        matches!(self, Self::Safe)
142    }
143
144    /// Returns `true` if it's "pending"
145    pub const fn is_pending(&self) -> bool {
146        matches!(self, Self::Pending)
147    }
148
149    /// Returns `true` if it's "earliest"
150    pub const fn is_earliest(&self) -> bool {
151        matches!(self, Self::Earliest)
152    }
153}
154
155impl From<u64> for BlockNumberOrTag {
156    fn from(num: u64) -> Self {
157        Self::Number(num)
158    }
159}
160
161impl From<U64> for BlockNumberOrTag {
162    fn from(num: U64) -> Self {
163        num.to::<u64>().into()
164    }
165}
166
167#[cfg(feature = "serde")]
168impl serde::Serialize for BlockNumberOrTag {
169    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
170    where
171        S: serde::Serializer,
172    {
173        match *self {
174            Self::Number(x) => serializer.serialize_str(&format!("0x{x:x}")),
175            Self::Latest => serializer.serialize_str("latest"),
176            Self::Finalized => serializer.serialize_str("finalized"),
177            Self::Safe => serializer.serialize_str("safe"),
178            Self::Earliest => serializer.serialize_str("earliest"),
179            Self::Pending => serializer.serialize_str("pending"),
180        }
181    }
182}
183
184#[cfg(feature = "serde")]
185impl<'de> serde::Deserialize<'de> for BlockNumberOrTag {
186    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
187    where
188        D: serde::Deserializer<'de>,
189    {
190        let s = alloc::string::String::deserialize(deserializer)?;
191        s.parse().map_err(serde::de::Error::custom)
192    }
193}
194
195impl FromStr for BlockNumberOrTag {
196    type Err = ParseBlockNumberError;
197
198    fn from_str(s: &str) -> Result<Self, Self::Err> {
199        Ok(match s.to_lowercase().as_str() {
200            "latest" => Self::Latest,
201            "finalized" => Self::Finalized,
202            "safe" => Self::Safe,
203            "earliest" => Self::Earliest,
204            "pending" => Self::Pending,
205            s => {
206                if let Some(hex_val) = s.strip_prefix("0x") {
207                    u64::from_str_radix(hex_val, 16)?.into()
208                } else {
209                    return Err(HexStringMissingPrefixError::default().into());
210                }
211            }
212        })
213    }
214}
215
216impl fmt::Display for BlockNumberOrTag {
217    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218        match *self {
219            Self::Number(x) => write!(f, "0x{x:x}"),
220            Self::Latest => f.pad("latest"),
221            Self::Finalized => f.pad("finalized"),
222            Self::Safe => f.pad("safe"),
223            Self::Earliest => f.pad("earliest"),
224            Self::Pending => f.pad("pending"),
225        }
226    }
227}
228
229impl fmt::Debug for BlockNumberOrTag {
230    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231        fmt::Display::fmt(self, f)
232    }
233}
234
235/// This is a helper type to allow for lenient parsing of block numbers.
236///
237/// The eth json-rpc spec requires quantities to be hex encoded, which [`BlockNumberOrTag`] strictly
238/// enforces.
239///
240/// This type can be used if you want to allow for lenient parsing of block numbers.
241#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
242#[cfg_attr(feature = "serde", derive(serde::Serialize))]
243#[cfg_attr(feature = "serde", serde(transparent))]
244pub struct LenientBlockNumberOrTag(BlockNumberOrTag);
245
246impl LenientBlockNumberOrTag {
247    /// Creates a new [`LenientBlockNumberOrTag`] from a [`BlockNumberOrTag`].
248    pub const fn new(block_number_or_tag: BlockNumberOrTag) -> Self {
249        Self(block_number_or_tag)
250    }
251
252    /// Returns the inner [`BlockNumberOrTag`].
253    pub const fn into_inner(self) -> BlockNumberOrTag {
254        self.0
255    }
256}
257
258impl From<LenientBlockNumberOrTag> for BlockNumberOrTag {
259    fn from(value: LenientBlockNumberOrTag) -> Self {
260        value.0
261    }
262}
263impl From<LenientBlockNumberOrTag> for BlockId {
264    fn from(value: LenientBlockNumberOrTag) -> Self {
265        value.into_inner().into()
266    }
267}
268
269/// A module that deserializes either a BlockNumberOrTag, or a simple number.
270#[cfg(feature = "serde")]
271pub mod lenient_block_number_or_tag {
272    use super::{BlockNumberOrTag, LenientBlockNumberOrTag};
273    use core::fmt;
274    use serde::{
275        de::{self, Visitor},
276        Deserialize, Deserializer,
277    };
278
279    /// Following the spec the block parameter is either:
280    ///
281    /// > HEX String - an integer block number
282    /// > Integer - a block number
283    /// > String "latest" - for the latest mined block
284    /// > String "finalized" - for the finalized block
285    /// > String "safe" - for the safe head block
286    /// > String "earliest" for the earliest/genesis block
287    /// > String "pending" - for the pending state/transactions
288    ///
289    /// and with EIP-1898:
290    /// > blockNumber: QUANTITY - a block number
291    /// > blockHash: DATA - a block hash
292    ///
293    /// <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1898.md>
294    ///
295    /// EIP-1898 does not all calls that use `BlockNumber` like `eth_getBlockByNumber` and doesn't
296    /// list raw integers as supported.
297    pub fn deserialize<'de, D>(deserializer: D) -> Result<BlockNumberOrTag, D::Error>
298    where
299        D: Deserializer<'de>,
300    {
301        LenientBlockNumberOrTag::deserialize(deserializer).map(Into::into)
302    }
303
304    impl<'de> Deserialize<'de> for LenientBlockNumberOrTag {
305        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
306        where
307            D: Deserializer<'de>,
308        {
309            struct LenientBlockNumberVisitor;
310
311            impl<'de> Visitor<'de> for LenientBlockNumberVisitor {
312                type Value = LenientBlockNumberOrTag;
313
314                fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
315                    formatter.write_str("a block number or tag, or a u64")
316                }
317
318                fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
319                where
320                    E: de::Error,
321                {
322                    Ok(LenientBlockNumberOrTag(v.into()))
323                }
324
325                fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
326                where
327                    E: de::Error,
328                {
329                    // Attempt to parse as a numeric string
330                    if let Ok(num) = v.parse::<u64>() {
331                        return Ok(LenientBlockNumberOrTag(BlockNumberOrTag::Number(num)));
332                    }
333
334                    BlockNumberOrTag::deserialize(de::value::StrDeserializer::<E>::new(v))
335                        .map(LenientBlockNumberOrTag)
336                        .map_err(de::Error::custom)
337                }
338            }
339
340            deserializer.deserialize_any(LenientBlockNumberVisitor)
341        }
342    }
343}
344
345/// Error thrown when parsing a [BlockNumberOrTag] from a string.
346#[derive(Debug)]
347pub enum ParseBlockNumberError {
348    /// Failed to parse hex value
349    ParseIntErr(ParseIntError),
350    /// Failed to parse hex value
351    ParseErr(ParseError),
352    /// Block numbers should be 0x-prefixed
353    MissingPrefix(HexStringMissingPrefixError),
354}
355
356/// Error variants when parsing a [BlockNumberOrTag]
357impl core::error::Error for ParseBlockNumberError {
358    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
359        match self {
360            Self::ParseIntErr(err) => Some(err),
361            Self::MissingPrefix(err) => Some(err),
362            Self::ParseErr(_) => None,
363        }
364    }
365}
366
367impl fmt::Display for ParseBlockNumberError {
368    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
369        match self {
370            Self::ParseIntErr(err) => write!(f, "{err}"),
371            Self::ParseErr(err) => write!(f, "{err}"),
372            Self::MissingPrefix(err) => write!(f, "{err}"),
373        }
374    }
375}
376
377impl From<ParseIntError> for ParseBlockNumberError {
378    fn from(err: ParseIntError) -> Self {
379        Self::ParseIntErr(err)
380    }
381}
382
383impl From<ParseError> for ParseBlockNumberError {
384    fn from(err: ParseError) -> Self {
385        Self::ParseErr(err)
386    }
387}
388
389impl From<HexStringMissingPrefixError> for ParseBlockNumberError {
390    fn from(err: HexStringMissingPrefixError) -> Self {
391        Self::MissingPrefix(err)
392    }
393}
394
395/// Thrown when a 0x-prefixed hex string was expected
396#[derive(Clone, Copy, Debug, Default)]
397#[non_exhaustive]
398pub struct HexStringMissingPrefixError;
399
400impl fmt::Display for HexStringMissingPrefixError {
401    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
402        f.write_str("hex string without 0x prefix")
403    }
404}
405
406impl core::error::Error for HexStringMissingPrefixError {}
407
408/// A Block Identifier.
409/// <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1898.md>
410#[derive(Clone, Copy, PartialEq, Eq)]
411pub enum BlockId {
412    /// A block hash and an optional bool that defines if it's canonical
413    Hash(RpcBlockHash),
414    /// A block number
415    Number(BlockNumberOrTag),
416}
417
418impl BlockId {
419    /// Returns the block hash if it is [BlockId::Hash]
420    pub const fn as_block_hash(&self) -> Option<BlockHash> {
421        match self {
422            Self::Hash(hash) => Some(hash.block_hash),
423            Self::Number(_) => None,
424        }
425    }
426
427    /// Returns the block number if it is [`BlockId::Number`] and not a tag
428    pub const fn as_u64(&self) -> Option<u64> {
429        match self {
430            Self::Number(x) => x.as_number(),
431            _ => None,
432        }
433    }
434
435    /// Returns true if this is [BlockNumberOrTag::Latest]
436    pub const fn is_latest(&self) -> bool {
437        matches!(self, Self::Number(BlockNumberOrTag::Latest))
438    }
439
440    /// Returns true if this is [BlockNumberOrTag::Pending]
441    pub const fn is_pending(&self) -> bool {
442        matches!(self, Self::Number(BlockNumberOrTag::Pending))
443    }
444
445    /// Returns true if this is [BlockNumberOrTag::Safe]
446    pub const fn is_safe(&self) -> bool {
447        matches!(self, Self::Number(BlockNumberOrTag::Safe))
448    }
449
450    /// Returns true if this is [BlockNumberOrTag::Finalized]
451    pub const fn is_finalized(&self) -> bool {
452        matches!(self, Self::Number(BlockNumberOrTag::Finalized))
453    }
454
455    /// Returns true if this is [BlockNumberOrTag::Earliest]
456    pub const fn is_earliest(&self) -> bool {
457        matches!(self, Self::Number(BlockNumberOrTag::Earliest))
458    }
459
460    /// Returns true if this is [BlockNumberOrTag::Number]
461    pub const fn is_number(&self) -> bool {
462        matches!(self, Self::Number(BlockNumberOrTag::Number(_)))
463    }
464    /// Returns true if this is [BlockId::Hash]
465    pub const fn is_hash(&self) -> bool {
466        matches!(self, Self::Hash(_))
467    }
468
469    /// Creates a new "pending" tag instance.
470    pub const fn pending() -> Self {
471        Self::Number(BlockNumberOrTag::Pending)
472    }
473
474    /// Creates a new "latest" tag instance.
475    pub const fn latest() -> Self {
476        Self::Number(BlockNumberOrTag::Latest)
477    }
478
479    /// Creates a new "earliest" tag instance.
480    pub const fn earliest() -> Self {
481        Self::Number(BlockNumberOrTag::Earliest)
482    }
483
484    /// Creates a new "finalized" tag instance.
485    pub const fn finalized() -> Self {
486        Self::Number(BlockNumberOrTag::Finalized)
487    }
488
489    /// Creates a new "safe" tag instance.
490    pub const fn safe() -> Self {
491        Self::Number(BlockNumberOrTag::Safe)
492    }
493
494    /// Creates a new block number instance.
495    pub const fn number(num: u64) -> Self {
496        Self::Number(BlockNumberOrTag::Number(num))
497    }
498
499    /// Create a new block hash instance.
500    pub const fn hash(block_hash: BlockHash) -> Self {
501        Self::Hash(RpcBlockHash { block_hash, require_canonical: None })
502    }
503
504    /// Create a new block hash instance that requires the block to be canonical.
505    pub const fn hash_canonical(block_hash: BlockHash) -> Self {
506        Self::Hash(RpcBlockHash { block_hash, require_canonical: Some(true) })
507    }
508}
509
510impl Default for BlockId {
511    fn default() -> Self {
512        BlockNumberOrTag::Latest.into()
513    }
514}
515
516impl From<u64> for BlockId {
517    fn from(num: u64) -> Self {
518        BlockNumberOrTag::Number(num).into()
519    }
520}
521
522impl From<U64> for BlockId {
523    fn from(value: U64) -> Self {
524        value.to::<u64>().into()
525    }
526}
527
528impl From<BlockNumberOrTag> for BlockId {
529    fn from(num: BlockNumberOrTag) -> Self {
530        Self::Number(num)
531    }
532}
533
534impl From<HashOrNumber> for BlockId {
535    fn from(block: HashOrNumber) -> Self {
536        match block {
537            HashOrNumber::Hash(hash) => hash.into(),
538            HashOrNumber::Number(num) => num.into(),
539        }
540    }
541}
542
543impl From<B256> for BlockId {
544    fn from(block_hash: B256) -> Self {
545        RpcBlockHash { block_hash, require_canonical: None }.into()
546    }
547}
548
549impl From<(B256, Option<bool>)> for BlockId {
550    fn from(hash_can: (B256, Option<bool>)) -> Self {
551        RpcBlockHash { block_hash: hash_can.0, require_canonical: hash_can.1 }.into()
552    }
553}
554
555impl From<RpcBlockHash> for BlockId {
556    fn from(value: RpcBlockHash) -> Self {
557        Self::Hash(value)
558    }
559}
560
561#[cfg(feature = "serde")]
562impl serde::Serialize for BlockId {
563    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
564    where
565        S: serde::Serializer,
566    {
567        use serde::ser::SerializeStruct;
568
569        match self {
570            Self::Hash(RpcBlockHash { block_hash, require_canonical }) => {
571                let mut s = serializer.serialize_struct("BlockIdEip1898", 1)?;
572                s.serialize_field("blockHash", block_hash)?;
573                if let Some(require_canonical) = require_canonical {
574                    s.serialize_field("requireCanonical", require_canonical)?;
575                }
576                s.end()
577            }
578            Self::Number(num) => num.serialize(serializer),
579        }
580    }
581}
582
583#[cfg(feature = "serde")]
584impl<'de> serde::Deserialize<'de> for BlockId {
585    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
586    where
587        D: serde::Deserializer<'de>,
588    {
589        struct BlockIdVisitor;
590
591        impl<'de> serde::de::Visitor<'de> for BlockIdVisitor {
592            type Value = BlockId;
593
594            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
595                formatter.write_str("Block identifier following EIP-1898")
596            }
597
598            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
599            where
600                E: serde::de::Error,
601            {
602                // Since there is no way to clearly distinguish between a DATA parameter and a QUANTITY parameter. A str is therefor deserialized into a Block Number: <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1898.md>
603                // However, since the hex string should be a QUANTITY, we can safely assume that if the len is 66 bytes, it is in fact a hash, ref <https://github.com/ethereum/go-ethereum/blob/ee530c0d5aa70d2c00ab5691a89ab431b73f8165/rpc/types.go#L184-L184>
604                if v.len() == 66 {
605                    Ok(v.parse::<B256>().map_err(serde::de::Error::custom)?.into())
606                } else {
607                    // quantity hex string or tag
608                    Ok(BlockId::Number(v.parse().map_err(serde::de::Error::custom)?))
609                }
610            }
611
612            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
613            where
614                A: serde::de::MapAccess<'de>,
615            {
616                let mut number = None;
617                let mut block_hash = None;
618                let mut require_canonical = None;
619                while let Some(key) = map.next_key::<alloc::string::String>()? {
620                    match key.as_str() {
621                        "blockNumber" => {
622                            if number.is_some() || block_hash.is_some() {
623                                return Err(serde::de::Error::duplicate_field("blockNumber"));
624                            }
625                            if require_canonical.is_some() {
626                                return Err(serde::de::Error::custom(
627                                    "Non-valid require_canonical field",
628                                ));
629                            }
630                            number = Some(map.next_value::<BlockNumberOrTag>()?)
631                        }
632                        "blockHash" => {
633                            if number.is_some() || block_hash.is_some() {
634                                return Err(serde::de::Error::duplicate_field("blockHash"));
635                            }
636
637                            block_hash = Some(map.next_value::<B256>()?);
638                        }
639                        "requireCanonical" => {
640                            if number.is_some() || require_canonical.is_some() {
641                                return Err(serde::de::Error::duplicate_field("requireCanonical"));
642                            }
643
644                            require_canonical = Some(map.next_value::<bool>()?)
645                        }
646                        key => {
647                            return Err(serde::de::Error::unknown_field(
648                                key,
649                                &["blockNumber", "blockHash", "requireCanonical"],
650                            ))
651                        }
652                    }
653                }
654
655                #[expect(clippy::option_if_let_else)]
656                if let Some(number) = number {
657                    Ok(number.into())
658                } else if let Some(block_hash) = block_hash {
659                    Ok((block_hash, require_canonical).into())
660                } else {
661                    Err(serde::de::Error::custom(
662                        "Expected `blockNumber` or `blockHash` with `requireCanonical` optionally",
663                    ))
664                }
665            }
666        }
667
668        deserializer.deserialize_any(BlockIdVisitor)
669    }
670}
671
672impl fmt::Display for BlockId {
673    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
674        match self {
675            Self::Hash(hash) => hash.fmt(f),
676            Self::Number(num) => num.fmt(f),
677        }
678    }
679}
680
681impl fmt::Debug for BlockId {
682    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
683        match self {
684            Self::Hash(hash) => hash.fmt(f),
685            Self::Number(num) => num.fmt(f),
686        }
687    }
688}
689
690/// Error thrown when parsing a [BlockId] from a string.
691#[derive(Debug)]
692pub enum ParseBlockIdError {
693    /// Failed to parse a block id from a number.
694    ParseIntError(ParseIntError),
695    /// Failed to parse hex number
696    ParseError(ParseError),
697    /// Failed to parse a block id as a hex string.
698    FromHexError(FromHexError),
699}
700
701impl fmt::Display for ParseBlockIdError {
702    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
703        match self {
704            Self::ParseIntError(err) => write!(f, "{err}"),
705            Self::ParseError(err) => write!(f, "{err}"),
706            Self::FromHexError(err) => write!(f, "{err}"),
707        }
708    }
709}
710
711impl core::error::Error for ParseBlockIdError {
712    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
713        match self {
714            Self::ParseIntError(err) => Some(err),
715            Self::FromHexError(err) => Some(err),
716            Self::ParseError(_) => None,
717        }
718    }
719}
720
721impl From<ParseIntError> for ParseBlockIdError {
722    fn from(err: ParseIntError) -> Self {
723        Self::ParseIntError(err)
724    }
725}
726
727impl From<FromHexError> for ParseBlockIdError {
728    fn from(err: FromHexError) -> Self {
729        Self::FromHexError(err)
730    }
731}
732
733impl FromStr for BlockId {
734    type Err = ParseBlockIdError;
735    fn from_str(s: &str) -> Result<Self, Self::Err> {
736        if s.starts_with("0x") {
737            return match s.len() {
738                66 => B256::from_str(s).map(Into::into).map_err(ParseBlockIdError::FromHexError),
739                _ => U64::from_str(s).map(Into::into).map_err(ParseBlockIdError::ParseError),
740            };
741        }
742
743        match s {
744            "latest" | "finalized" | "safe" | "earliest" | "pending" => {
745                Ok(BlockNumberOrTag::from_str(s).unwrap().into())
746            }
747            _ => s.parse::<u64>().map_err(ParseBlockIdError::ParseIntError).map(Into::into),
748        }
749    }
750}
751
752/// A number and a hash.
753#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
754#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
755#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
756pub struct NumHash {
757    /// The number
758    pub number: u64,
759    /// The hash.
760    pub hash: B256,
761}
762
763/// Block number and hash of the forked block.
764pub type ForkBlock = NumHash;
765
766/// A block number and a hash
767pub type BlockNumHash = NumHash;
768
769impl NumHash {
770    /// Creates a new `NumHash` from a number and hash.
771    pub const fn new(number: u64, hash: B256) -> Self {
772        Self { number, hash }
773    }
774
775    /// Consumes `Self` and returns the number and hash
776    pub const fn into_components(self) -> (u64, B256) {
777        (self.number, self.hash)
778    }
779
780    /// Returns whether or not the block matches the given [HashOrNumber].
781    pub fn matches_block_or_num(&self, block: &HashOrNumber) -> bool {
782        match block {
783            HashOrNumber::Hash(hash) => self.hash == *hash,
784            HashOrNumber::Number(number) => self.number == *number,
785        }
786    }
787}
788
789impl From<(u64, B256)> for NumHash {
790    fn from(val: (u64, B256)) -> Self {
791        Self { number: val.0, hash: val.1 }
792    }
793}
794
795impl From<(B256, u64)> for NumHash {
796    fn from(val: (B256, u64)) -> Self {
797        Self { hash: val.0, number: val.1 }
798    }
799}
800
801/// Either a hash _or_ a block number
802#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
803#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
804#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
805pub enum HashOrNumber {
806    /// The hash
807    Hash(B256),
808    /// The number
809    Number(u64),
810}
811
812/// A block hash _or_ a block number
813pub type BlockHashOrNumber = HashOrNumber;
814
815// === impl HashOrNumber ===
816
817impl HashOrNumber {
818    /// Returns the block number if it is a [`HashOrNumber::Number`].
819    #[inline]
820    pub const fn as_number(self) -> Option<u64> {
821        match self {
822            Self::Hash(_) => None,
823            Self::Number(num) => Some(num),
824        }
825    }
826
827    /// Returns the block hash if it is a [`HashOrNumber::Hash`].
828    #[inline]
829    pub const fn as_hash(self) -> Option<B256> {
830        match self {
831            Self::Hash(hash) => Some(hash),
832            Self::Number(_) => None,
833        }
834    }
835}
836
837impl From<B256> for HashOrNumber {
838    fn from(value: B256) -> Self {
839        Self::Hash(value)
840    }
841}
842
843impl From<&B256> for HashOrNumber {
844    fn from(value: &B256) -> Self {
845        (*value).into()
846    }
847}
848
849impl From<u64> for HashOrNumber {
850    fn from(value: u64) -> Self {
851        Self::Number(value)
852    }
853}
854
855impl From<U64> for HashOrNumber {
856    fn from(value: U64) -> Self {
857        value.to::<u64>().into()
858    }
859}
860
861impl From<RpcBlockHash> for HashOrNumber {
862    fn from(value: RpcBlockHash) -> Self {
863        Self::Hash(value.into())
864    }
865}
866
867/// Allows for RLP encoding of either a hash or a number
868impl Encodable for HashOrNumber {
869    fn encode(&self, out: &mut dyn bytes::BufMut) {
870        match self {
871            Self::Hash(block_hash) => block_hash.encode(out),
872            Self::Number(block_number) => block_number.encode(out),
873        }
874    }
875    fn length(&self) -> usize {
876        match self {
877            Self::Hash(block_hash) => block_hash.length(),
878            Self::Number(block_number) => block_number.length(),
879        }
880    }
881}
882
883/// Allows for RLP decoding of a hash or number
884impl Decodable for HashOrNumber {
885    fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
886        let header: u8 = *buf.first().ok_or(RlpError::InputTooShort)?;
887        // if the byte string is exactly 32 bytes, decode it into a Hash
888        // 0xa0 = 0x80 (start of string) + 0x20 (32, length of string)
889        if header == 0xa0 {
890            // strip the first byte, parsing the rest of the string.
891            // If the rest of the string fails to decode into 32 bytes, we'll bubble up the
892            // decoding error.
893            Ok(B256::decode(buf)?.into())
894        } else {
895            // a block number when encoded as bytes ranges from 0 to any number of bytes - we're
896            // going to accept numbers which fit in less than 64 bytes.
897            // Any data larger than this which is not caught by the Hash decoding should error and
898            // is considered an invalid block number.
899            Ok(u64::decode(buf)?.into())
900        }
901    }
902}
903
904impl fmt::Display for HashOrNumber {
905    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
906        match self {
907            Self::Hash(hash) => write!(f, "{hash}"),
908            Self::Number(num) => write!(f, "{num}"),
909        }
910    }
911}
912
913/// Error thrown when parsing a [HashOrNumber] from a string.
914#[derive(Debug)]
915pub struct ParseBlockHashOrNumberError {
916    input: alloc::string::String,
917    parse_int_error: ParseIntError,
918    hex_error: alloy_primitives::hex::FromHexError,
919}
920
921impl fmt::Display for ParseBlockHashOrNumberError {
922    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
923        write!(
924            f,
925            "failed to parse {:?} as a number: {} or hash: {}",
926            self.input, self.parse_int_error, self.hex_error
927        )
928    }
929}
930
931impl core::error::Error for ParseBlockHashOrNumberError {}
932
933impl FromStr for HashOrNumber {
934    type Err = ParseBlockHashOrNumberError;
935
936    fn from_str(s: &str) -> Result<Self, Self::Err> {
937        use alloc::string::ToString;
938
939        match u64::from_str(s) {
940            Ok(val) => Ok(val.into()),
941            Err(parse_int_error) => match B256::from_str(s) {
942                Ok(val) => Ok(val.into()),
943                Err(hex_error) => Err(ParseBlockHashOrNumberError {
944                    input: s.to_string(),
945                    parse_int_error,
946                    hex_error,
947                }),
948            },
949        }
950    }
951}
952
953#[cfg(test)]
954mod tests {
955    use super::*;
956    use alloc::{string::ToString, vec::Vec};
957    use alloy_primitives::b256;
958
959    const HASH: B256 = b256!("1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9");
960
961    #[test]
962    fn block_id_from_str() {
963        assert_eq!("0x0".parse::<BlockId>().unwrap(), BlockId::number(0));
964        assert_eq!("0x24A931".parse::<BlockId>().unwrap(), BlockId::number(2402609));
965        assert_eq!(
966            "0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
967                .parse::<BlockId>()
968                .unwrap(),
969            HASH.into()
970        );
971    }
972
973    #[test]
974    #[cfg(feature = "serde")]
975    fn compact_block_number_serde() {
976        let num: BlockNumberOrTag = 1u64.into();
977        let serialized = serde_json::to_string(&num).unwrap();
978        assert_eq!(serialized, "\"0x1\"");
979    }
980
981    #[test]
982    fn block_id_as_u64() {
983        assert_eq!(BlockId::number(123).as_u64(), Some(123));
984        assert_eq!(BlockId::number(0).as_u64(), Some(0));
985        assert_eq!(BlockId::earliest().as_u64(), None);
986        assert_eq!(BlockId::latest().as_u64(), None);
987        assert_eq!(BlockId::pending().as_u64(), None);
988        assert_eq!(BlockId::safe().as_u64(), None);
989        assert_eq!(BlockId::hash(BlockHash::ZERO).as_u64(), None);
990        assert_eq!(BlockId::hash_canonical(BlockHash::ZERO).as_u64(), None);
991    }
992
993    #[test]
994    #[cfg(feature = "serde")]
995    fn can_parse_eip1898_block_ids() {
996        let num = serde_json::json!(
997            { "blockNumber": "0x0" }
998        );
999        let id = serde_json::from_value::<BlockId>(num).unwrap();
1000        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Number(0u64)));
1001
1002        let num = serde_json::json!(
1003            { "blockNumber": "pending" }
1004        );
1005        let id = serde_json::from_value::<BlockId>(num).unwrap();
1006        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Pending));
1007
1008        let num = serde_json::json!(
1009            { "blockNumber": "latest" }
1010        );
1011        let id = serde_json::from_value::<BlockId>(num).unwrap();
1012        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Latest));
1013
1014        let num = serde_json::json!(
1015            { "blockNumber": "finalized" }
1016        );
1017        let id = serde_json::from_value::<BlockId>(num).unwrap();
1018        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Finalized));
1019
1020        let num = serde_json::json!(
1021            { "blockNumber": "safe" }
1022        );
1023        let id = serde_json::from_value::<BlockId>(num).unwrap();
1024        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Safe));
1025
1026        let num = serde_json::json!(
1027            { "blockNumber": "earliest" }
1028        );
1029        let id = serde_json::from_value::<BlockId>(num).unwrap();
1030        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Earliest));
1031
1032        let num = serde_json::json!("0x0");
1033        let id = serde_json::from_value::<BlockId>(num).unwrap();
1034        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Number(0u64)));
1035
1036        let num = serde_json::json!("pending");
1037        let id = serde_json::from_value::<BlockId>(num).unwrap();
1038        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Pending));
1039
1040        let num = serde_json::json!("latest");
1041        let id = serde_json::from_value::<BlockId>(num).unwrap();
1042        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Latest));
1043
1044        let num = serde_json::json!("finalized");
1045        let id = serde_json::from_value::<BlockId>(num).unwrap();
1046        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Finalized));
1047
1048        let num = serde_json::json!("safe");
1049        let id = serde_json::from_value::<BlockId>(num).unwrap();
1050        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Safe));
1051
1052        let num = serde_json::json!("earliest");
1053        let id = serde_json::from_value::<BlockId>(num).unwrap();
1054        assert_eq!(id, BlockId::Number(BlockNumberOrTag::Earliest));
1055
1056        let num = serde_json::json!(
1057            { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }
1058        );
1059        let id = serde_json::from_value::<BlockId>(num).unwrap();
1060        assert_eq!(
1061            id,
1062            BlockId::Hash(
1063                "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
1064                    .parse::<B256>()
1065                    .unwrap()
1066                    .into()
1067            )
1068        );
1069    }
1070
1071    #[test]
1072    fn display_rpc_block_hash() {
1073        let hash = RpcBlockHash::from_hash(HASH, Some(true));
1074
1075        assert_eq!(
1076            hash.to_string(),
1077            "canonical hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
1078        );
1079
1080        let hash = RpcBlockHash::from_hash(HASH, None);
1081
1082        assert_eq!(
1083            hash.to_string(),
1084            "hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
1085        );
1086    }
1087
1088    #[test]
1089    fn display_block_id() {
1090        let id = BlockId::hash(HASH);
1091
1092        assert_eq!(
1093            id.to_string(),
1094            "hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
1095        );
1096
1097        let id = BlockId::hash_canonical(HASH);
1098
1099        assert_eq!(
1100            id.to_string(),
1101            "canonical hash 0x1a15e3c30cf094a99826869517b16d185d45831d3a494f01030b0001a9d3ebb9"
1102        );
1103
1104        let id = BlockId::number(100000);
1105
1106        assert_eq!(id.to_string(), "0x186a0");
1107
1108        let id = BlockId::latest();
1109
1110        assert_eq!(id.to_string(), "latest");
1111
1112        let id = BlockId::safe();
1113
1114        assert_eq!(id.to_string(), "safe");
1115
1116        let id = BlockId::finalized();
1117
1118        assert_eq!(id.to_string(), "finalized");
1119
1120        let id = BlockId::earliest();
1121
1122        assert_eq!(id.to_string(), "earliest");
1123
1124        let id = BlockId::pending();
1125
1126        assert_eq!(id.to_string(), "pending");
1127    }
1128
1129    #[test]
1130    fn test_block_number_or_tag() {
1131        // Test Latest variant
1132        let latest = BlockNumberOrTag::Latest;
1133        assert_eq!(latest.as_number(), None);
1134        assert!(latest.is_latest());
1135        assert!(!latest.is_number());
1136        assert!(!latest.is_finalized());
1137        assert!(!latest.is_safe());
1138        assert!(!latest.is_pending());
1139        assert!(!latest.is_earliest());
1140
1141        // Test Finalized variant
1142        let finalized = BlockNumberOrTag::Finalized;
1143        assert_eq!(finalized.as_number(), None);
1144        assert!(finalized.is_finalized());
1145        assert!(!finalized.is_latest());
1146        assert!(!finalized.is_number());
1147        assert!(!finalized.is_safe());
1148        assert!(!finalized.is_pending());
1149        assert!(!finalized.is_earliest());
1150
1151        // Test Safe variant
1152        let safe = BlockNumberOrTag::Safe;
1153        assert_eq!(safe.as_number(), None);
1154        assert!(safe.is_safe());
1155        assert!(!safe.is_latest());
1156        assert!(!safe.is_number());
1157        assert!(!safe.is_finalized());
1158        assert!(!safe.is_pending());
1159        assert!(!safe.is_earliest());
1160
1161        // Test Earliest variant
1162        let earliest = BlockNumberOrTag::Earliest;
1163        assert_eq!(earliest.as_number(), None);
1164        assert!(earliest.is_earliest());
1165        assert!(!earliest.is_latest());
1166        assert!(!earliest.is_number());
1167        assert!(!earliest.is_finalized());
1168        assert!(!earliest.is_safe());
1169        assert!(!earliest.is_pending());
1170
1171        // Test Pending variant
1172        let pending = BlockNumberOrTag::Pending;
1173        assert_eq!(pending.as_number(), None);
1174        assert!(pending.is_pending());
1175        assert!(!pending.is_latest());
1176        assert!(!pending.is_number());
1177        assert!(!pending.is_finalized());
1178        assert!(!pending.is_safe());
1179        assert!(!pending.is_earliest());
1180
1181        // Test Number variant
1182        let number = BlockNumberOrTag::Number(42);
1183        assert_eq!(number.as_number(), Some(42));
1184        assert!(number.is_number());
1185        assert!(!number.is_latest());
1186        assert!(!number.is_finalized());
1187        assert!(!number.is_safe());
1188        assert!(!number.is_pending());
1189        assert!(!number.is_earliest());
1190    }
1191
1192    #[test]
1193    fn test_block_number_or_tag_from() {
1194        // Test conversion from u64
1195        let num = 100u64;
1196        let block: BlockNumberOrTag = num.into();
1197        assert_eq!(block, BlockNumberOrTag::Number(100));
1198
1199        // Test conversion from U64
1200        let num = U64::from(200);
1201        let block: BlockNumberOrTag = num.into();
1202        assert_eq!(block, BlockNumberOrTag::Number(200));
1203    }
1204
1205    #[test]
1206    fn test_block_id() {
1207        let hash = BlockHash::random();
1208
1209        // Block hash
1210        let block_id_hash = BlockId::hash(hash);
1211        assert_eq!(block_id_hash.as_block_hash(), Some(hash));
1212        assert!(block_id_hash.is_hash());
1213        assert!(!block_id_hash.is_number());
1214        assert!(!block_id_hash.is_latest());
1215        assert!(!block_id_hash.is_pending());
1216        assert!(!block_id_hash.is_safe());
1217        assert!(!block_id_hash.is_finalized());
1218        assert!(!block_id_hash.is_earliest());
1219
1220        // Block number
1221        let block_id_number = BlockId::number(123);
1222        assert_eq!(block_id_number.as_u64(), Some(123));
1223        assert!(block_id_number.is_number());
1224        assert!(!block_id_number.is_hash());
1225        assert!(!block_id_number.is_latest());
1226        assert!(!block_id_number.is_pending());
1227        assert!(!block_id_number.is_safe());
1228        assert!(!block_id_number.is_finalized());
1229        assert!(!block_id_number.is_earliest());
1230
1231        // Latest block
1232        let block_latest = BlockId::latest();
1233        assert!(block_latest.is_latest());
1234        assert!(!block_latest.is_number());
1235        assert!(!block_latest.is_hash());
1236        assert!(!block_latest.is_pending());
1237        assert!(!block_latest.is_safe());
1238        assert!(!block_latest.is_finalized());
1239        assert!(!block_latest.is_earliest());
1240
1241        // Pending block
1242        let block_pending = BlockId::pending();
1243        assert!(block_pending.is_pending());
1244        assert!(!block_pending.is_latest());
1245        assert!(!block_pending.is_number());
1246        assert!(!block_pending.is_hash());
1247        assert!(!block_pending.is_safe());
1248        assert!(!block_pending.is_finalized());
1249        assert!(!block_pending.is_earliest());
1250
1251        // Safe block
1252        let block_safe = BlockId::safe();
1253        assert!(block_safe.is_safe());
1254        assert!(!block_safe.is_latest());
1255        assert!(!block_safe.is_number());
1256        assert!(!block_safe.is_hash());
1257        assert!(!block_safe.is_pending());
1258        assert!(!block_safe.is_finalized());
1259        assert!(!block_safe.is_earliest());
1260
1261        // Finalized block
1262        let block_finalized = BlockId::finalized();
1263        assert!(block_finalized.is_finalized());
1264        assert!(!block_finalized.is_latest());
1265        assert!(!block_finalized.is_number());
1266        assert!(!block_finalized.is_hash());
1267        assert!(!block_finalized.is_pending());
1268        assert!(!block_finalized.is_safe());
1269        assert!(!block_finalized.is_earliest());
1270
1271        // Earliest block
1272        let block_earliest = BlockId::earliest();
1273        assert!(block_earliest.is_earliest());
1274        assert!(!block_earliest.is_latest());
1275        assert!(!block_earliest.is_number());
1276        assert!(!block_earliest.is_hash());
1277        assert!(!block_earliest.is_pending());
1278        assert!(!block_earliest.is_safe());
1279        assert!(!block_earliest.is_finalized());
1280
1281        // Default block
1282        assert!(BlockId::default().is_latest());
1283        assert!(!BlockId::default().is_number());
1284        assert!(!BlockId::default().is_hash());
1285        assert!(!BlockId::default().is_pending());
1286        assert!(!BlockId::default().is_safe());
1287        assert!(!BlockId::default().is_finalized());
1288        assert!(!BlockId::default().is_earliest());
1289    }
1290
1291    #[test]
1292    fn test_u64_to_block_id() {
1293        // Simple u64
1294        let num: u64 = 123;
1295        let block_id: BlockId = num.into();
1296
1297        match block_id {
1298            BlockId::Number(BlockNumberOrTag::Number(n)) => assert_eq!(n, 123),
1299            _ => panic!("Expected BlockId::Number with 123"),
1300        }
1301
1302        // Big integer U64
1303        let num: U64 = U64::from(456);
1304        let block_id: BlockId = num.into();
1305
1306        match block_id {
1307            BlockId::Number(BlockNumberOrTag::Number(n)) => assert_eq!(n, 456),
1308            _ => panic!("Expected BlockId::Number with 456"),
1309        }
1310
1311        // u64 as HashOrNumber
1312        let num: u64 = 789;
1313        let block_id: BlockId = HashOrNumber::Number(num).into();
1314
1315        match block_id {
1316            BlockId::Number(BlockNumberOrTag::Number(n)) => assert_eq!(n, 789),
1317            _ => panic!("Expected BlockId::Number with 789"),
1318        }
1319    }
1320
1321    #[test]
1322    fn test_block_number_or_tag_to_block_id() {
1323        let block_number_or_tag = BlockNumberOrTag::Pending;
1324        let block_id: BlockId = block_number_or_tag.into();
1325
1326        match block_id {
1327            BlockId::Number(BlockNumberOrTag::Pending) => {}
1328            _ => panic!("Expected BlockId::Number with Pending"),
1329        }
1330    }
1331
1332    #[test]
1333    fn test_hash_or_number_to_block_id_hash() {
1334        // B256 wrapped in HashOrNumber
1335        let hash: B256 = B256::random();
1336        let block_id: BlockId = HashOrNumber::Hash(hash).into();
1337
1338        match block_id {
1339            BlockId::Hash(rpc_block_hash) => assert_eq!(rpc_block_hash.block_hash, hash),
1340            _ => panic!("Expected BlockId::Hash"),
1341        }
1342
1343        // Simple B256
1344        let hash: B256 = B256::random();
1345        let block_id: BlockId = hash.into();
1346
1347        match block_id {
1348            BlockId::Hash(rpc_block_hash) => assert_eq!(rpc_block_hash.block_hash, hash),
1349            _ => panic!("Expected BlockId::Hash"),
1350        }
1351
1352        // Tuple with B256 and canonical flag
1353        let hash: B256 = B256::random();
1354        let block_id: BlockId = (hash, Some(true)).into();
1355
1356        match block_id {
1357            BlockId::Hash(rpc_block_hash) => {
1358                assert_eq!(rpc_block_hash.block_hash, hash);
1359                assert_eq!(rpc_block_hash.require_canonical, Some(true));
1360            }
1361            _ => panic!("Expected BlockId::Hash with canonical flag"),
1362        }
1363    }
1364
1365    #[test]
1366    fn test_hash_or_number_as_number() {
1367        // Test with a number
1368        let hash_or_number = HashOrNumber::Number(123);
1369        assert_eq!(hash_or_number.as_number(), Some(123));
1370
1371        // Test with a hash
1372        let hash = B256::random();
1373        let hash_or_number = HashOrNumber::Hash(hash);
1374        assert_eq!(hash_or_number.as_number(), None);
1375    }
1376
1377    #[test]
1378    fn test_hash_or_number_as_hash() {
1379        // Test with a hash
1380        let hash = B256::random();
1381        let hash_or_number = HashOrNumber::Hash(hash);
1382        assert_eq!(hash_or_number.as_hash(), Some(hash));
1383
1384        // Test with a number
1385        let hash_or_number = HashOrNumber::Number(456);
1386        assert_eq!(hash_or_number.as_hash(), None);
1387    }
1388
1389    #[test]
1390    fn test_hash_or_number_conversions() {
1391        // Test conversion from B256
1392        let hash = B256::random();
1393        let hash_or_number: HashOrNumber = hash.into();
1394        assert_eq!(hash_or_number, HashOrNumber::Hash(hash));
1395
1396        // Test conversion from &B256
1397        let hash_ref: HashOrNumber = (&hash).into();
1398        assert_eq!(hash_ref, HashOrNumber::Hash(hash));
1399
1400        // Test conversion from u64
1401        let number: u64 = 123;
1402        let hash_or_number: HashOrNumber = number.into();
1403        assert_eq!(hash_or_number, HashOrNumber::Number(number));
1404
1405        // Test conversion from U64
1406        let u64_value = U64::from(456);
1407        let hash_or_number: HashOrNumber = u64_value.into();
1408        assert_eq!(hash_or_number, HashOrNumber::Number(u64_value.to::<u64>()));
1409
1410        // Test conversion from RpcBlockHash (assuming RpcBlockHash is convertible to B256)
1411        let rpc_block_hash = RpcBlockHash { block_hash: hash, require_canonical: Some(true) };
1412        let hash_or_number: HashOrNumber = rpc_block_hash.into();
1413        assert_eq!(hash_or_number, HashOrNumber::Hash(hash));
1414    }
1415
1416    #[test]
1417    fn test_hash_or_number_rlp_roundtrip_hash() {
1418        // Test case: encoding and decoding a B256 hash
1419        let original_hash = B256::random();
1420        let hash_or_number: HashOrNumber = HashOrNumber::Hash(original_hash);
1421
1422        // Encode the HashOrNumber
1423        let mut buf = Vec::new();
1424        hash_or_number.encode(&mut buf);
1425
1426        // Decode the encoded bytes
1427        let decoded: HashOrNumber = HashOrNumber::decode(&mut &buf[..]).expect("Decoding failed");
1428
1429        // Assert that the decoded value matches the original
1430        assert_eq!(decoded, hash_or_number);
1431    }
1432
1433    #[test]
1434    fn test_hash_or_number_rlp_roundtrip_u64() {
1435        // Test case: encoding and decoding a u64 number
1436        let original_number: u64 = 12345;
1437        let hash_or_number: HashOrNumber = HashOrNumber::Number(original_number);
1438
1439        // Encode the HashOrNumber
1440        let mut buf = Vec::new();
1441        hash_or_number.encode(&mut buf);
1442
1443        // Decode the encoded bytes
1444        let decoded: HashOrNumber = HashOrNumber::decode(&mut &buf[..]).expect("Decoding failed");
1445
1446        // Assert that the decoded value matches the original
1447        assert_eq!(decoded, hash_or_number);
1448    }
1449
1450    #[test]
1451    fn test_numhash() {
1452        let number: u64 = 42;
1453        let hash = B256::random();
1454
1455        let num_hash = NumHash::new(number, hash);
1456
1457        // Validate the initial values
1458        assert_eq!(num_hash.number, number);
1459        assert_eq!(num_hash.hash, hash);
1460
1461        // Test into_components
1462        assert_eq!(num_hash.into_components(), (number, hash));
1463    }
1464
1465    #[test]
1466    fn test_numhash_matches_block_or_num() {
1467        let number: u64 = 42;
1468        let hash = B256::random();
1469
1470        let num_hash = NumHash::new(number, hash);
1471
1472        // Test matching by hash
1473        let block_hash = HashOrNumber::Hash(hash);
1474        assert!(num_hash.matches_block_or_num(&block_hash));
1475
1476        // Test matching by number
1477        let block_number = HashOrNumber::Number(number);
1478        assert!(num_hash.matches_block_or_num(&block_number));
1479
1480        // Test non-matching by different hash
1481        let different_hash = B256::random();
1482        let non_matching_hash = HashOrNumber::Hash(different_hash);
1483        assert!(!num_hash.matches_block_or_num(&non_matching_hash));
1484
1485        // Test non-matching by different number
1486        let different_number: u64 = 43;
1487        let non_matching_number = HashOrNumber::Number(different_number);
1488        assert!(!num_hash.matches_block_or_num(&non_matching_number));
1489    }
1490
1491    #[test]
1492    fn test_numhash_conversions() {
1493        // From a tuple (u64, B256)
1494        let number: u64 = 42;
1495        let hash = B256::random();
1496
1497        let num_hash_from_tuple: NumHash = (number, hash).into();
1498
1499        assert_eq!(num_hash_from_tuple.number, number);
1500        assert_eq!(num_hash_from_tuple.hash, hash);
1501
1502        // From a reversed tuple (B256, u64)
1503        let number: u64 = 42;
1504        let hash = B256::random();
1505
1506        let num_hash_from_reversed_tuple: NumHash = (hash, number).into();
1507
1508        assert_eq!(num_hash_from_reversed_tuple.number, number);
1509        assert_eq!(num_hash_from_reversed_tuple.hash, hash);
1510    }
1511
1512    #[test]
1513    #[cfg(feature = "serde")]
1514    fn test_block_id_from_str() {
1515        // Valid hexadecimal block ID (with 0x prefix)
1516        let hex_id = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
1517        assert_eq!(
1518            BlockId::from_str(hex_id).unwrap(),
1519            BlockId::Hash(RpcBlockHash::from_hash(B256::from_str(hex_id).unwrap(), None))
1520        );
1521
1522        // Valid tag strings
1523        assert_eq!(BlockId::from_str("latest").unwrap(), BlockNumberOrTag::Latest.into());
1524        assert_eq!(BlockId::from_str("finalized").unwrap(), BlockNumberOrTag::Finalized.into());
1525        assert_eq!(BlockId::from_str("safe").unwrap(), BlockNumberOrTag::Safe.into());
1526        assert_eq!(BlockId::from_str("earliest").unwrap(), BlockNumberOrTag::Earliest.into());
1527        assert_eq!(BlockId::from_str("pending").unwrap(), BlockNumberOrTag::Pending.into());
1528
1529        // Valid numeric string without prefix
1530        let numeric_string = "12345";
1531        let parsed_numeric_string = BlockId::from_str(numeric_string);
1532        assert!(parsed_numeric_string.is_ok());
1533
1534        // Hex interpretation of numeric string
1535        assert_eq!(
1536            BlockId::from_str("0x12345").unwrap(),
1537            BlockId::Number(BlockNumberOrTag::Number(74565))
1538        );
1539
1540        // Invalid non-numeric string
1541        let invalid_string = "invalid_block_id";
1542        let parsed_invalid_string = BlockId::from_str(invalid_string);
1543        assert!(parsed_invalid_string.is_err());
1544    }
1545
1546    /// Check parsing according to EIP-1898.
1547    #[test]
1548    #[cfg(feature = "serde")]
1549    fn can_parse_blockid_u64() {
1550        let num = serde_json::json!(
1551            {"blockNumber": "0xaf"}
1552        );
1553
1554        let id = serde_json::from_value::<BlockId>(num);
1555        assert_eq!(id.unwrap(), BlockId::from(175));
1556    }
1557
1558    #[test]
1559    #[cfg(feature = "serde")]
1560    fn can_parse_block_hash() {
1561        let block_hash =
1562            B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1563                .unwrap();
1564        let block_hash_json = serde_json::json!(
1565            { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}
1566        );
1567        let id = serde_json::from_value::<BlockId>(block_hash_json).unwrap();
1568        assert_eq!(id, BlockId::from(block_hash,));
1569    }
1570
1571    #[test]
1572    #[cfg(feature = "serde")]
1573    fn can_parse_block_hash_with_canonical() {
1574        let block_hash =
1575            B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1576                .unwrap();
1577        let block_id = BlockId::Hash(RpcBlockHash::from_hash(block_hash, Some(true)));
1578        let block_hash_json = serde_json::json!(
1579            { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true }
1580        );
1581        let id = serde_json::from_value::<BlockId>(block_hash_json).unwrap();
1582        assert_eq!(id, block_id)
1583    }
1584    #[test]
1585    #[cfg(feature = "serde")]
1586    fn can_parse_blockid_tags() {
1587        let tags = [
1588            ("latest", BlockNumberOrTag::Latest),
1589            ("finalized", BlockNumberOrTag::Finalized),
1590            ("safe", BlockNumberOrTag::Safe),
1591            ("pending", BlockNumberOrTag::Pending),
1592        ];
1593        for (value, tag) in tags {
1594            let num = serde_json::json!({ "blockNumber": value });
1595            let id = serde_json::from_value::<BlockId>(num);
1596            assert_eq!(id.unwrap(), BlockId::from(tag))
1597        }
1598    }
1599    #[test]
1600    #[cfg(feature = "serde")]
1601    fn repeated_keys_is_err() {
1602        let num = serde_json::json!({"blockNumber": 1, "requireCanonical": true, "requireCanonical": false});
1603        assert!(serde_json::from_value::<BlockId>(num).is_err());
1604        let num =
1605            serde_json::json!({"blockNumber": 1, "requireCanonical": true, "blockNumber": 23});
1606        assert!(serde_json::from_value::<BlockId>(num).is_err());
1607    }
1608
1609    /// Serde tests
1610    #[test]
1611    #[cfg(feature = "serde")]
1612    fn serde_blockid_tags() {
1613        let block_ids = [
1614            BlockNumberOrTag::Latest,
1615            BlockNumberOrTag::Finalized,
1616            BlockNumberOrTag::Safe,
1617            BlockNumberOrTag::Pending,
1618        ]
1619        .map(BlockId::from);
1620        for block_id in &block_ids {
1621            let serialized = serde_json::to_string(&block_id).unwrap();
1622            let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
1623            assert_eq!(deserialized, *block_id)
1624        }
1625    }
1626
1627    #[test]
1628    #[cfg(feature = "serde")]
1629    fn serde_blockid_number() {
1630        let block_id = BlockId::from(100u64);
1631        let serialized = serde_json::to_string(&block_id).unwrap();
1632        let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
1633        assert_eq!(deserialized, block_id)
1634    }
1635
1636    #[test]
1637    #[cfg(feature = "serde")]
1638    fn serde_blockid_hash() {
1639        let block_id = BlockId::from(B256::default());
1640        let serialized = serde_json::to_string(&block_id).unwrap();
1641        let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
1642        assert_eq!(deserialized, block_id)
1643    }
1644
1645    #[test]
1646    #[cfg(feature = "serde")]
1647    fn serde_blockid_hash_from_str() {
1648        let val = "\"0x898753d8fdd8d92c1907ca21e68c7970abd290c647a202091181deec3f30a0b2\"";
1649        let block_hash: B256 = serde_json::from_str(val).unwrap();
1650        let block_id: BlockId = serde_json::from_str(val).unwrap();
1651        assert_eq!(block_id, BlockId::Hash(block_hash.into()));
1652    }
1653
1654    #[test]
1655    #[cfg(feature = "serde")]
1656    fn serde_rpc_payload_block_tag() {
1657        let payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},"latest"],"id":1,"jsonrpc":"2.0"}"#;
1658        let value: serde_json::Value = serde_json::from_str(payload).unwrap();
1659        let block_id_param = value.pointer("/params/1").unwrap();
1660        let block_id: BlockId = serde_json::from_value::<BlockId>(block_id_param.clone()).unwrap();
1661        assert_eq!(BlockId::Number(BlockNumberOrTag::Latest), block_id);
1662    }
1663
1664    #[test]
1665    #[cfg(feature = "serde")]
1666    fn serde_rpc_payload_block_object() {
1667        let example_payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},{"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}],"id":1,"jsonrpc":"2.0"}"#;
1668        let value: serde_json::Value = serde_json::from_str(example_payload).unwrap();
1669        let block_id_param = value.pointer("/params/1").unwrap().to_string();
1670        let block_id: BlockId = serde_json::from_str::<BlockId>(&block_id_param).unwrap();
1671        let hash =
1672            B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1673                .unwrap();
1674        assert_eq!(BlockId::from(hash), block_id);
1675        let serialized = serde_json::to_string(&BlockId::from(hash)).unwrap();
1676        assert_eq!("{\"blockHash\":\"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3\"}", serialized)
1677    }
1678
1679    #[test]
1680    #[cfg(feature = "serde")]
1681    fn serde_rpc_payload_block_number() {
1682        let example_payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},{"blockNumber": "0x0"}],"id":1,"jsonrpc":"2.0"}"#;
1683        let value: serde_json::Value = serde_json::from_str(example_payload).unwrap();
1684        let block_id_param = value.pointer("/params/1").unwrap().to_string();
1685        let block_id: BlockId = serde_json::from_str::<BlockId>(&block_id_param).unwrap();
1686        assert_eq!(BlockId::from(0u64), block_id);
1687        let serialized = serde_json::to_string(&BlockId::from(0u64)).unwrap();
1688        assert_eq!("\"0x0\"", serialized)
1689    }
1690
1691    #[test]
1692    #[should_panic]
1693    #[cfg(feature = "serde")]
1694    fn serde_rpc_payload_block_number_duplicate_key() {
1695        let payload = r#"{"blockNumber": "0x132", "blockNumber": "0x133"}"#;
1696        let parsed_block_id = serde_json::from_str::<BlockId>(payload);
1697        parsed_block_id.unwrap();
1698    }
1699
1700    #[test]
1701    #[cfg(feature = "serde")]
1702    fn serde_rpc_payload_block_hash() {
1703        let payload = r#"{"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}"#;
1704        let parsed = serde_json::from_str::<BlockId>(payload).unwrap();
1705        let expected = BlockId::from(
1706            B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
1707                .unwrap(),
1708        );
1709        assert_eq!(parsed, expected);
1710    }
1711
1712    #[test]
1713    #[cfg(feature = "serde")]
1714    fn serde_blocknumber_non_0xprefix() {
1715        let s = "\"2\"";
1716        let err = serde_json::from_str::<BlockNumberOrTag>(s).unwrap_err();
1717        assert_eq!(err.to_string(), HexStringMissingPrefixError::default().to_string());
1718    }
1719
1720    #[cfg(feature = "serde")]
1721    #[derive(Debug, serde::Deserialize, PartialEq)]
1722    struct TestLenientStruct {
1723        #[serde(deserialize_with = "super::lenient_block_number_or_tag::deserialize")]
1724        block: BlockNumberOrTag,
1725    }
1726
1727    #[test]
1728    #[cfg(feature = "serde")]
1729    fn test_lenient_block_number_or_tag() {
1730        // Test parsing numeric strings
1731        let lenient_struct: TestLenientStruct =
1732            serde_json::from_str(r#"{"block": "0x1"}"#).unwrap();
1733        assert_eq!(lenient_struct.block, BlockNumberOrTag::Number(1));
1734
1735        let lenient_struct: TestLenientStruct =
1736            serde_json::from_str(r#"{"block": "123"}"#).unwrap();
1737        assert_eq!(lenient_struct.block, BlockNumberOrTag::Number(123));
1738
1739        // Test parsing tags
1740        let lenient_struct: TestLenientStruct =
1741            serde_json::from_str(r#"{"block": "latest"}"#).unwrap();
1742        assert_eq!(lenient_struct.block, BlockNumberOrTag::Latest);
1743
1744        let lenient_struct: TestLenientStruct =
1745            serde_json::from_str(r#"{"block": "finalized"}"#).unwrap();
1746        assert_eq!(lenient_struct.block, BlockNumberOrTag::Finalized);
1747
1748        let lenient_struct: TestLenientStruct =
1749            serde_json::from_str(r#"{"block": "safe"}"#).unwrap();
1750        assert_eq!(lenient_struct.block, BlockNumberOrTag::Safe);
1751
1752        let lenient_struct: TestLenientStruct =
1753            serde_json::from_str(r#"{"block": "earliest"}"#).unwrap();
1754        assert_eq!(lenient_struct.block, BlockNumberOrTag::Earliest);
1755
1756        let lenient_struct: TestLenientStruct =
1757            serde_json::from_str(r#"{"block": "pending"}"#).unwrap();
1758        assert_eq!(lenient_struct.block, BlockNumberOrTag::Pending);
1759
1760        // Test parsing raw numbers (not strings)
1761        let lenient_struct: TestLenientStruct = serde_json::from_str(r#"{"block": 123}"#).unwrap();
1762        assert_eq!(lenient_struct.block, BlockNumberOrTag::Number(123));
1763
1764        let lenient_struct: TestLenientStruct = serde_json::from_str(r#"{"block": 0}"#).unwrap();
1765        assert_eq!(lenient_struct.block, BlockNumberOrTag::Number(0));
1766
1767        // Test invalid inputs
1768        assert!(serde_json::from_str::<TestLenientStruct>(r#"{"block": "invalid"}"#).is_err());
1769        assert!(serde_json::from_str::<TestLenientStruct>(r#"{"block": null}"#).is_err());
1770        assert!(serde_json::from_str::<TestLenientStruct>(r#"{"block": {}}"#).is_err());
1771    }
1772
1773    #[test]
1774    fn test_lenient_block_number_or_tag_wrapper() {
1775        // Test the LenientBlockNumberOrTag wrapper directly
1776        let block_number: LenientBlockNumberOrTag = serde_json::from_str("\"latest\"").unwrap();
1777        assert_eq!(block_number.0, BlockNumberOrTag::Latest);
1778
1779        let block_number: LenientBlockNumberOrTag = serde_json::from_str("123").unwrap();
1780        assert_eq!(block_number.0, BlockNumberOrTag::Number(123));
1781
1782        let block_number: LenientBlockNumberOrTag = serde_json::from_str("\"0x1\"").unwrap();
1783        assert_eq!(block_number.0, BlockNumberOrTag::Number(1));
1784    }
1785}