diff --git a/Cargo.toml b/Cargo.toml index 553fca341fb..accf5b748d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ rustdoc-args = ["--cfg", "docsrs"] [workspace.dependencies] alloy-consensus = { version = "0.6", path = "crates/consensus", default-features = false } +alloy-consensus-any = { version = "0.6", path = "crates/consensus-any", default-features = false } alloy-contract = { version = "0.6", path = "crates/contract", default-features = false } alloy-eips = { version = "0.6", path = "crates/eips", default-features = false } alloy-eip7547 = { version = "0.6", path = "crates/eip7547", default-features = false } @@ -49,6 +50,7 @@ alloy-pubsub = { version = "0.6", path = "crates/pubsub", default-features = fal alloy-rpc-client = { version = "0.6", path = "crates/rpc-client", default-features = false } alloy-rpc-types-admin = { version = "0.6", path = "crates/rpc-types-admin", default-features = false } alloy-rpc-types-anvil = { version = "0.6", path = "crates/rpc-types-anvil", default-features = false } +alloy-rpc-types-any = { version = "0.6", path = "crates/rpc-types-any", default-features = false } alloy-rpc-types-beacon = { version = "0.6", path = "crates/rpc-types-beacon", default-features = false } alloy-rpc-types-debug = { version = "0.6", path = "crates/rpc-types-debug", default-features = false } alloy-rpc-types-engine = { version = "0.6", path = "crates/rpc-types-engine", default-features = false } diff --git a/crates/consensus-any/Cargo.toml b/crates/consensus-any/Cargo.toml new file mode 100644 index 00000000000..e288fab800d --- /dev/null +++ b/crates/consensus-any/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "alloy-consensus-any" +description = "Consensus interface for any network" + +version.workspace = true +edition.workspace = true +rust-version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +exclude.workspace = true + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints] +workspace = true + +[dependencies] +alloy-consensus = { workspace = true, features = ["serde"] } +alloy-eips.workspace = true +alloy-primitives.workspace = true +alloy-rlp.workspace = true +alloy-serde = { workspace = true, optional = true } + +# arbitrary +arbitrary = { workspace = true, features = ["derive"], optional = true } + +# serde +serde = { workspace = true, features = ["derive"], optional = true } + +[dev-dependencies] +arbitrary = { workspace = true, features = ["derive"] } + +[features] +default = ["std"] +std = ["alloy-eips/std"] +arbitrary = ["std", "dep:arbitrary", "alloy-eips/arbitrary"] +serde = [ + "dep:serde", + "alloy-primitives/serde", + "dep:alloy-serde", + "alloy-eips/serde", +] diff --git a/crates/consensus-any/README.md b/crates/consensus-any/README.md new file mode 100644 index 00000000000..1936fd4d080 --- /dev/null +++ b/crates/consensus-any/README.md @@ -0,0 +1,3 @@ +# alloy-consensus-any + +Consensus interface for any network. diff --git a/crates/consensus/src/block/any.rs b/crates/consensus-any/src/block/header.rs similarity index 98% rename from crates/consensus/src/block/any.rs rename to crates/consensus-any/src/block/header.rs index fee07672699..9a6676e4a2f 100644 --- a/crates/consensus/src/block/any.rs +++ b/crates/consensus-any/src/block/header.rs @@ -1,7 +1,6 @@ +use alloy_consensus::{BlockHeader, Header}; use alloy_primitives::{Address, BlockNumber, Bloom, Bytes, B256, B64, U256}; -use super::{BlockHeader, Header}; - /// Block header representation with certain fields made optional to account for possible /// differencies in network implementations. #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] @@ -184,8 +183,8 @@ impl BlockHeader for AnyHeader { } } -impl From for AnyHeader { - fn from(value: super::Header) -> Self { +impl From
for AnyHeader { + fn from(value: Header) -> Self { let Header { parent_hash, ommers_hash, diff --git a/crates/consensus-any/src/block/mod.rs b/crates/consensus-any/src/block/mod.rs new file mode 100644 index 00000000000..f55275f8ed8 --- /dev/null +++ b/crates/consensus-any/src/block/mod.rs @@ -0,0 +1,2 @@ +mod header; +pub use header::AnyHeader; diff --git a/crates/consensus-any/src/lib.rs b/crates/consensus-any/src/lib.rs new file mode 100644 index 00000000000..40278ef5148 --- /dev/null +++ b/crates/consensus-any/src/lib.rs @@ -0,0 +1,14 @@ +#![doc = include_str!("../README.md")] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/alloy.jpg", + html_favicon_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/favicon.ico" +)] +#![cfg_attr(not(test), warn(unused_crate_dependencies))] +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#![cfg_attr(not(feature = "std"), no_std)] + +mod block; +pub use block::AnyHeader; + +mod receipt; +pub use receipt::AnyReceiptEnvelope; diff --git a/crates/consensus/src/receipt/any.rs b/crates/consensus-any/src/receipt/envelope.rs similarity index 98% rename from crates/consensus/src/receipt/any.rs rename to crates/consensus-any/src/receipt/envelope.rs index fe98db7723b..e3a00b40ae0 100644 --- a/crates/consensus/src/receipt/any.rs +++ b/crates/consensus-any/src/receipt/envelope.rs @@ -1,4 +1,4 @@ -use crate::{Eip658Value, ReceiptWithBloom, TxReceipt}; +use alloy_consensus::{Eip658Value, ReceiptWithBloom, TxReceipt}; use alloy_eips::eip2718::{Decodable2718, Eip2718Result, Encodable2718}; use alloy_primitives::{bytes::BufMut, Bloom, Log}; use alloy_rlp::{Decodable, Encodable}; diff --git a/crates/consensus-any/src/receipt/mod.rs b/crates/consensus-any/src/receipt/mod.rs new file mode 100644 index 00000000000..1b786879ff9 --- /dev/null +++ b/crates/consensus-any/src/receipt/mod.rs @@ -0,0 +1,2 @@ +mod envelope; +pub use envelope::AnyReceiptEnvelope; diff --git a/crates/consensus/Cargo.toml b/crates/consensus/Cargo.toml index b62e8b0cf55..fe2e0f24815 100644 --- a/crates/consensus/Cargo.toml +++ b/crates/consensus/Cargo.toml @@ -44,7 +44,7 @@ derive_more = { workspace = true, features = [ "from", "deref", "deref_mut", - "into_iterator" + "into_iterator", ], default-features = false } auto_impl.workspace = true diff --git a/crates/consensus/src/block/mod.rs b/crates/consensus/src/block/mod.rs index aca61627609..177d24b8664 100644 --- a/crates/consensus/src/block/mod.rs +++ b/crates/consensus/src/block/mod.rs @@ -2,8 +2,6 @@ mod header; pub use header::{BlockHeader, Header}; -mod any; -pub use any::AnyHeader; #[cfg(all(feature = "serde", feature = "serde-bincode-compat"))] pub(crate) use header::serde_bincode_compat; diff --git a/crates/consensus/src/lib.rs b/crates/consensus/src/lib.rs index 5d4cb21f491..4abbb6bfe23 100644 --- a/crates/consensus/src/lib.rs +++ b/crates/consensus/src/lib.rs @@ -13,16 +13,13 @@ mod account; pub use account::Account; mod block; -pub use block::{AnyHeader, Block, BlockBody, BlockHeader, Header}; +pub use block::{Block, BlockBody, BlockHeader, Header}; pub mod constants; pub use constants::{EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH}; mod receipt; -pub use receipt::{ - AnyReceiptEnvelope, Eip658Value, Receipt, ReceiptEnvelope, ReceiptWithBloom, Receipts, - TxReceipt, -}; +pub use receipt::{Eip658Value, Receipt, ReceiptEnvelope, ReceiptWithBloom, Receipts, TxReceipt}; pub mod proofs; diff --git a/crates/consensus/src/receipt/mod.rs b/crates/consensus/src/receipt/mod.rs index 56766dca780..b27fba262c6 100644 --- a/crates/consensus/src/receipt/mod.rs +++ b/crates/consensus/src/receipt/mod.rs @@ -1,9 +1,6 @@ use alloy_primitives::{Bloom, Log}; use core::fmt; -mod any; -pub use any::AnyReceiptEnvelope; - mod envelope; pub use envelope::ReceiptEnvelope; diff --git a/crates/network/Cargo.toml b/crates/network/Cargo.toml index 386ad2e000c..fb9a1dd95ed 100644 --- a/crates/network/Cargo.toml +++ b/crates/network/Cargo.toml @@ -20,10 +20,12 @@ workspace = true [dependencies] alloy-consensus = { workspace = true, features = ["std"] } +alloy-consensus-any = { workspace = true, features = ["std", "serde"] } alloy-eips = { workspace = true, features = ["serde"] } alloy-json-rpc.workspace = true alloy-network-primitives.workspace = true alloy-primitives = { workspace = true, features = ["map"] } +alloy-rpc-types-any.workspace = true alloy-rpc-types-eth = { workspace = true, features = ["std", "serde"] } alloy-signer.workspace = true alloy-serde.workspace = true diff --git a/crates/network/src/any/mod.rs b/crates/network/src/any/mod.rs index 6dc5db6f645..8d0097d0f49 100644 --- a/crates/network/src/any/mod.rs +++ b/crates/network/src/any/mod.rs @@ -6,15 +6,13 @@ pub use either::{AnyTxEnvelope, AnyTypedTransaction}; mod unknowns; pub use unknowns::{AnyTxType, UnknownTxEnvelope, UnknownTypedTransaction}; -pub use alloy_consensus::{AnyHeader, AnyReceiptEnvelope}; +pub use alloy_consensus_any::{AnyHeader, AnyReceiptEnvelope}; use crate::Network; -use alloy_rpc_types_eth::{AnyTransactionReceipt, Block, Transaction, TransactionRequest}; +pub use alloy_rpc_types_any::{AnyRpcHeader, AnyTransactionReceipt}; +use alloy_rpc_types_eth::{Block, Transaction, TransactionRequest}; use alloy_serde::WithOtherFields; -/// A catch-all header type for handling headers on multiple networks. -pub type AnyRpcHeader = alloy_rpc_types_eth::Header; - /// A catch-all block type for handling blocks on multiple networks. pub type AnyRpcBlock = WithOtherFields>, AnyRpcHeader>>; @@ -62,9 +60,9 @@ impl Network for AnyNetwork { type UnsignedTx = AnyTypedTransaction; - type ReceiptEnvelope = alloy_consensus::AnyReceiptEnvelope; + type ReceiptEnvelope = AnyReceiptEnvelope; - type Header = alloy_consensus::AnyHeader; + type Header = AnyHeader; type TransactionRequest = WithOtherFields; diff --git a/crates/network/src/lib.rs b/crates/network/src/lib.rs index f034d950b81..8bf270be5e4 100644 --- a/crates/network/src/lib.rs +++ b/crates/network/src/lib.rs @@ -24,7 +24,8 @@ pub use ethereum::{Ethereum, EthereumWallet}; mod any; pub use any::{ AnyHeader, AnyNetwork, AnyReceiptEnvelope, AnyRpcBlock, AnyRpcHeader, AnyRpcTransaction, - AnyTxEnvelope, AnyTxType, AnyTypedTransaction, UnknownTxEnvelope, UnknownTypedTransaction, + AnyTransactionReceipt, AnyTxEnvelope, AnyTxType, AnyTypedTransaction, UnknownTxEnvelope, + UnknownTypedTransaction, }; pub use alloy_eips::eip2718; diff --git a/crates/rpc-types-any/Cargo.toml b/crates/rpc-types-any/Cargo.toml new file mode 100644 index 00000000000..560ef541358 --- /dev/null +++ b/crates/rpc-types-any/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "alloy-rpc-types-any" +description = "Types for any network" + +version.workspace = true +edition.workspace = true +rust-version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +exclude.workspace = true + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints] +workspace = true + +[dependencies] +alloy-consensus-any = { workspace = true, features = ["serde"] } +alloy-rpc-types-eth.workspace = true +alloy-serde.workspace = true + +[dev-dependencies] +alloy-primitives.workspace = true + +serde.workspace = true +serde_json.workspace = true diff --git a/crates/rpc-types-any/README.md b/crates/rpc-types-any/README.md new file mode 100644 index 00000000000..88ec9e0c219 --- /dev/null +++ b/crates/rpc-types-any/README.md @@ -0,0 +1,3 @@ +# alloy-rpc-types-any + +Types for any network. diff --git a/crates/rpc-types-any/src/block.rs b/crates/rpc-types-any/src/block.rs new file mode 100644 index 00000000000..3daac3be2e8 --- /dev/null +++ b/crates/rpc-types-any/src/block.rs @@ -0,0 +1,2 @@ +/// A catch-all header type for handling headers on multiple networks. +pub type AnyRpcHeader = alloy_rpc_types_eth::Header; diff --git a/crates/rpc-types-any/src/lib.rs b/crates/rpc-types-any/src/lib.rs new file mode 100644 index 00000000000..c61200edf22 --- /dev/null +++ b/crates/rpc-types-any/src/lib.rs @@ -0,0 +1,13 @@ +#![doc = include_str!("../README.md")] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/alloy.jpg", + html_favicon_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/favicon.ico" +)] +#![cfg_attr(not(test), warn(unused_crate_dependencies))] +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] + +mod transaction; +pub use transaction::AnyTransactionReceipt; + +mod block; +pub use block::AnyRpcHeader; diff --git a/crates/rpc-types-any/src/transaction/mod.rs b/crates/rpc-types-any/src/transaction/mod.rs new file mode 100644 index 00000000000..2e9f1f6fcdb --- /dev/null +++ b/crates/rpc-types-any/src/transaction/mod.rs @@ -0,0 +1,2 @@ +mod receipt; +pub use receipt::AnyTransactionReceipt; diff --git a/crates/rpc-types-any/src/transaction/receipt.rs b/crates/rpc-types-any/src/transaction/receipt.rs new file mode 100644 index 00000000000..aa81e91693e --- /dev/null +++ b/crates/rpc-types-any/src/transaction/receipt.rs @@ -0,0 +1,146 @@ +use alloy_rpc_types_eth::{Log, TransactionReceipt}; + +/// Alias for a catch-all receipt type. +#[doc(alias = "AnyTxReceipt")] +pub type AnyTransactionReceipt = + alloy_serde::WithOtherFields>>; + +#[cfg(test)] +mod test { + use super::*; + use alloy_primitives::b256; + + #[test] + fn deserialize_tx_receipt_op() { + // OtherFields for Optimism + #[derive(Debug, serde::Deserialize)] + struct OpOtherFields { + #[serde(rename = "l1BaseFeeScalar")] + l1_base_fee_scalar: String, + #[serde(rename = "l1BlobBaseFee")] + l1_blob_base_fee: String, + #[serde(rename = "l1BlobBaseFeeScalar")] + l1_blob_base_fee_scalar: String, + #[serde(rename = "l1Fee")] + l1_fee: String, + #[serde(rename = "l1GasPrice")] + l1_gas_price: String, + #[serde(rename = "l1GasUsed")] + l1_gas_used: String, + } + + let receipt_json = r#" + { + "status": "0x1", + "cumulativeGasUsed": "0xf1740", + "logs": [ + { + "address": "0x4200000000000000000000000000000000000006", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000005112996d3ae99f0b5360cea1a620ffcd78e8ff83", + "0x00000000000000000000000077e7c5cbeaad915cf5462064b02984e16a902e67" + ], + "data": "0x000000000000000000000000000000000000000000000000001c66f6e8b40c00", + "blockHash": "0x88e07a0d797b84bd122d6993a6faf5a59ada7f40c181c553c191dd400d3d1583", + "blockNumber": "0x73a43e1", + "transactionHash": "0x2bc7cb4648e847712e39abd42178e35214a70bb15c568d604687661b9539b4c2", + "transactionIndex": "0x9", + "logIndex": "0x16", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000040000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000008000000100000000000000000100000000000000000000010000020000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000002000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x0", + "transactionHash": "0x2bc7cb4648e847712e39abd42178e35214a70bb15c568d604687661b9539b4c2", + "transactionIndex": "0x9", + "blockHash": "0x88e07a0d797b84bd122d6993a6faf5a59ada7f40c181c553c191dd400d3d1583", + "blockNumber": "0x73a43e1", + "gasUsed": "0x85b9", + "effectiveGasPrice": "0x3ac9e84", + "from": "0x5112996d3ae99f0b5360cea1a620ffcd78e8ff83", + "to": "0x4200000000000000000000000000000000000006", + "contractAddress": null, + "l1BaseFeeScalar": "0x558", + "l1BlobBaseFee": "0x1", + "l1BlobBaseFeeScalar": "0xc5fc5", + "l1Fee": "0x105d4b2024", + "l1GasPrice": "0x5d749a07e", + "l1GasUsed": "0x800" + } + "#; + let receipt = serde_json::from_str::(receipt_json).unwrap(); + + assert_eq!( + receipt.transaction_hash, + b256!("2bc7cb4648e847712e39abd42178e35214a70bb15c568d604687661b9539b4c2") + ); + + let other: OpOtherFields = receipt.other.deserialize_into().unwrap(); + assert_eq!(other.l1_base_fee_scalar, "0x558"); + assert_eq!(other.l1_blob_base_fee, "0x1"); + assert_eq!(other.l1_blob_base_fee_scalar, "0xc5fc5"); + assert_eq!(other.l1_fee, "0x105d4b2024"); + assert_eq!(other.l1_gas_price, "0x5d749a07e"); + assert_eq!(other.l1_gas_used, "0x800"); + } + + #[test] + fn deserialize_tx_receipt_arb() { + // OtherFields for Arbitrum + #[derive(Debug, serde::Deserialize)] + struct ArbOtherFields { + #[serde(rename = "gasUsedForL1")] + gas_used_for_l1: String, + #[serde(rename = "l1BlockNumber")] + l1_block_number: String, + } + + let receipt_json = r#" + { + "status": "0x1", + "cumulativeGasUsed": "0x27ebb8", + "logs": [ + { + "address": "0x912ce59144191c1204e64559fe8253a0e49e6548", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000e487d95426e55a29f2266e6788ab55608ebb829b", + "0x0000000000000000000000009855134ed0c8b71266d9f3e15c0a518c07be5baf" + ], + "data": "0x00000000000000000000000000000000000000000000000009d40825d5ee8000", + "blockHash": "0x83ddb8850803238bd58615680bc3718686ec1e3deaea0bc5f67c07c8577547f5", + "blockNumber": "0xd288ac5", + "transactionHash": "0x5aeca744e0c1f6d7f68641aedd394ac4b6e18cbeac3f8b3c81056c0e51a61cf3", + "transactionIndex": "0x7", + "logIndex": "0x7", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000005000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000100000000000001000000000000000000000000000000000000000000020000000000000000000004400000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x0", + "transactionHash": "0x5aeca744e0c1f6d7f68641aedd394ac4b6e18cbeac3f8b3c81056c0e51a61cf3", + "transactionIndex": "0x7", + "blockHash": "0x83ddb8850803238bd58615680bc3718686ec1e3deaea0bc5f67c07c8577547f5", + "blockNumber": "0xd288ac5", + "gasUsed": "0x3ad89", + "effectiveGasPrice": "0x989680", + "from": "0xe487d95426e55a29f2266e6788ab55608ebb829b", + "to": "0x912ce59144191c1204e64559fe8253a0e49e6548", + "contractAddress": null, + "gasUsedForL1": "0x2c906", + "l1BlockNumber": "0x1323b96" + } + "#; + let receipt = serde_json::from_str::(receipt_json).unwrap(); + + assert_eq!( + receipt.transaction_hash, + b256!("5aeca744e0c1f6d7f68641aedd394ac4b6e18cbeac3f8b3c81056c0e51a61cf3") + ); + + let other: ArbOtherFields = receipt.other.deserialize_into().unwrap(); + assert_eq!(other.gas_used_for_l1, "0x2c906"); + assert_eq!(other.l1_block_number, "0x1323b96"); + } +} diff --git a/crates/rpc-types-eth/Cargo.toml b/crates/rpc-types-eth/Cargo.toml index ab2af043485..10fb6bb8943 100644 --- a/crates/rpc-types-eth/Cargo.toml +++ b/crates/rpc-types-eth/Cargo.toml @@ -21,6 +21,7 @@ workspace = true [dependencies] alloy-eips.workspace = true alloy-consensus.workspace = true +alloy-consensus-any.workspace = true alloy-network-primitives.workspace = true alloy-rlp = { workspace = true, features = ["arrayvec", "derive"] } alloy-primitives = { workspace = true, features = ["rlp", "map"] } diff --git a/crates/rpc-types-eth/src/transaction/mod.rs b/crates/rpc-types-eth/src/transaction/mod.rs index 3966aa57ed6..8559645cf0a 100644 --- a/crates/rpc-types-eth/src/transaction/mod.rs +++ b/crates/rpc-types-eth/src/transaction/mod.rs @@ -22,15 +22,13 @@ pub use error::ConversionError; mod receipt; pub use receipt::TransactionReceipt; -#[cfg(feature = "serde")] -pub use receipt::AnyTransactionReceipt; - pub mod request; pub use request::{TransactionInput, TransactionRequest}; pub use alloy_consensus::{ - AnyReceiptEnvelope, Receipt, ReceiptEnvelope, ReceiptWithBloom, Transaction as TransactionTrait, + Receipt, ReceiptEnvelope, ReceiptWithBloom, Transaction as TransactionTrait, }; +pub use alloy_consensus_any::AnyReceiptEnvelope; /// Transaction object used in RPC #[derive(Clone, Debug, Default, PartialEq, Eq)] diff --git a/crates/rpc-types-eth/src/transaction/receipt.rs b/crates/rpc-types-eth/src/transaction/receipt.rs index 5493929b3ec..6aab1a7d52e 100644 --- a/crates/rpc-types-eth/src/transaction/receipt.rs +++ b/crates/rpc-types-eth/src/transaction/receipt.rs @@ -134,12 +134,6 @@ impl TransactionReceipt { } } -/// Alias for a catch-all receipt type. -#[doc(alias = "AnyTxReceipt")] -#[cfg(feature = "serde")] -pub type AnyTransactionReceipt = - alloy_serde::WithOtherFields>>; - impl> ReceiptResponse for TransactionReceipt { fn contract_address(&self) -> Option
{ self.contract_address @@ -265,142 +259,6 @@ mod test { ); } - #[test] - #[cfg(feature = "serde")] - fn deserialize_tx_receipt_op() { - // OtherFields for Optimism - #[derive(Debug, serde::Deserialize)] - struct OpOtherFields { - #[serde(rename = "l1BaseFeeScalar")] - l1_base_fee_scalar: String, - #[serde(rename = "l1BlobBaseFee")] - l1_blob_base_fee: String, - #[serde(rename = "l1BlobBaseFeeScalar")] - l1_blob_base_fee_scalar: String, - #[serde(rename = "l1Fee")] - l1_fee: String, - #[serde(rename = "l1GasPrice")] - l1_gas_price: String, - #[serde(rename = "l1GasUsed")] - l1_gas_used: String, - } - - let receipt_json = r#" - { - "status": "0x1", - "cumulativeGasUsed": "0xf1740", - "logs": [ - { - "address": "0x4200000000000000000000000000000000000006", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000005112996d3ae99f0b5360cea1a620ffcd78e8ff83", - "0x00000000000000000000000077e7c5cbeaad915cf5462064b02984e16a902e67" - ], - "data": "0x000000000000000000000000000000000000000000000000001c66f6e8b40c00", - "blockHash": "0x88e07a0d797b84bd122d6993a6faf5a59ada7f40c181c553c191dd400d3d1583", - "blockNumber": "0x73a43e1", - "transactionHash": "0x2bc7cb4648e847712e39abd42178e35214a70bb15c568d604687661b9539b4c2", - "transactionIndex": "0x9", - "logIndex": "0x16", - "removed": false - } - ], - "logsBloom": "0x00000000000000000000000000000000000000000000000000040000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000008000000100000000000000000100000000000000000000010000020000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000002000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x0", - "transactionHash": "0x2bc7cb4648e847712e39abd42178e35214a70bb15c568d604687661b9539b4c2", - "transactionIndex": "0x9", - "blockHash": "0x88e07a0d797b84bd122d6993a6faf5a59ada7f40c181c553c191dd400d3d1583", - "blockNumber": "0x73a43e1", - "gasUsed": "0x85b9", - "effectiveGasPrice": "0x3ac9e84", - "from": "0x5112996d3ae99f0b5360cea1a620ffcd78e8ff83", - "to": "0x4200000000000000000000000000000000000006", - "contractAddress": null, - "l1BaseFeeScalar": "0x558", - "l1BlobBaseFee": "0x1", - "l1BlobBaseFeeScalar": "0xc5fc5", - "l1Fee": "0x105d4b2024", - "l1GasPrice": "0x5d749a07e", - "l1GasUsed": "0x800" - } - "#; - let receipt = serde_json::from_str::(receipt_json).unwrap(); - - assert_eq!( - receipt.transaction_hash, - b256!("2bc7cb4648e847712e39abd42178e35214a70bb15c568d604687661b9539b4c2") - ); - - let other: OpOtherFields = receipt.other.deserialize_into().unwrap(); - assert_eq!(other.l1_base_fee_scalar, "0x558"); - assert_eq!(other.l1_blob_base_fee, "0x1"); - assert_eq!(other.l1_blob_base_fee_scalar, "0xc5fc5"); - assert_eq!(other.l1_fee, "0x105d4b2024"); - assert_eq!(other.l1_gas_price, "0x5d749a07e"); - assert_eq!(other.l1_gas_used, "0x800"); - } - - #[test] - #[cfg(feature = "serde")] - fn deserialize_tx_receipt_arb() { - // OtherFields for Arbitrum - #[derive(Debug, serde::Deserialize)] - struct ArbOtherFields { - #[serde(rename = "gasUsedForL1")] - gas_used_for_l1: String, - #[serde(rename = "l1BlockNumber")] - l1_block_number: String, - } - - let receipt_json = r#" - { - "status": "0x1", - "cumulativeGasUsed": "0x27ebb8", - "logs": [ - { - "address": "0x912ce59144191c1204e64559fe8253a0e49e6548", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x000000000000000000000000e487d95426e55a29f2266e6788ab55608ebb829b", - "0x0000000000000000000000009855134ed0c8b71266d9f3e15c0a518c07be5baf" - ], - "data": "0x00000000000000000000000000000000000000000000000009d40825d5ee8000", - "blockHash": "0x83ddb8850803238bd58615680bc3718686ec1e3deaea0bc5f67c07c8577547f5", - "blockNumber": "0xd288ac5", - "transactionHash": "0x5aeca744e0c1f6d7f68641aedd394ac4b6e18cbeac3f8b3c81056c0e51a61cf3", - "transactionIndex": "0x7", - "logIndex": "0x7", - "removed": false - } - ], - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000005000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000100000000000001000000000000000000000000000000000000000000020000000000000000000004400000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x0", - "transactionHash": "0x5aeca744e0c1f6d7f68641aedd394ac4b6e18cbeac3f8b3c81056c0e51a61cf3", - "transactionIndex": "0x7", - "blockHash": "0x83ddb8850803238bd58615680bc3718686ec1e3deaea0bc5f67c07c8577547f5", - "blockNumber": "0xd288ac5", - "gasUsed": "0x3ad89", - "effectiveGasPrice": "0x989680", - "from": "0xe487d95426e55a29f2266e6788ab55608ebb829b", - "to": "0x912ce59144191c1204e64559fe8253a0e49e6548", - "contractAddress": null, - "gasUsedForL1": "0x2c906", - "l1BlockNumber": "0x1323b96" - } - "#; - let receipt = serde_json::from_str::(receipt_json).unwrap(); - - assert_eq!( - receipt.transaction_hash, - b256!("5aeca744e0c1f6d7f68641aedd394ac4b6e18cbeac3f8b3c81056c0e51a61cf3") - ); - - let other: ArbOtherFields = receipt.other.deserialize_into().unwrap(); - assert_eq!(other.gas_used_for_l1, "0x2c906"); - assert_eq!(other.l1_block_number, "0x1323b96"); - } - #[test] #[cfg(feature = "serde")] fn deserialize_pre_eip658_receipt() {