Skip to main content

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