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