1#![allow(missing_docs)]
19
20use super::{byte::*, TypeEip1559, TypeEip2930, TypeEip4844, TypeEip7702, TypeLegacy};
21use alloc::vec::Vec;
22use codec::{Decode, Encode};
23use derive_more::{From, TryInto};
24pub use ethereum_types::*;
25use scale_info::TypeInfo;
26use serde::{de::Error, Deserialize, Deserializer, Serialize};
27
28#[derive(
30 Debug, Default, Clone, Encode, Decode, TypeInfo, Serialize, Deserialize, Eq, PartialEq,
31)]
32pub struct InputOrData {
33 #[serde(skip_serializing_if = "Option::is_none")]
34 input: Option<Bytes>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 data: Option<Bytes>,
37}
38
39impl From<Bytes> for InputOrData {
40 fn from(value: Bytes) -> Self {
41 InputOrData { input: Some(value), data: None }
42 }
43}
44
45impl From<Vec<u8>> for InputOrData {
46 fn from(value: Vec<u8>) -> Self {
47 InputOrData { input: Some(Bytes(value)), data: None }
48 }
49}
50
51impl InputOrData {
52 pub fn to_bytes(self) -> Bytes {
54 match self {
55 InputOrData { input: Some(input), data: _ } => input,
56 InputOrData { input: None, data: Some(data) } => data,
57 _ => Default::default(),
58 }
59 }
60
61 pub fn to_vec(self) -> Vec<u8> {
63 self.to_bytes().0
64 }
65}
66
67fn deserialize_input_or_data<'d, D: Deserializer<'d>>(d: D) -> Result<InputOrData, D::Error> {
68 let value = InputOrData::deserialize(d)?;
69 match &value {
70 InputOrData { input: Some(input), data: Some(data) } if input != data =>
71 Err(serde::de::Error::custom("Both \"data\" and \"input\" are set and not equal. Please use \"input\" to pass transaction call data")),
72 _ => Ok(value),
73 }
74}
75
76#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
78#[serde(rename_all = "camelCase")]
79pub struct Block {
80 pub base_fee_per_gas: U256,
82 pub blob_gas_used: U256,
84 pub difficulty: U256,
86 pub excess_blob_gas: U256,
88 pub extra_data: Bytes,
90 pub gas_limit: U256,
92 pub gas_used: U256,
94 pub hash: H256,
96 pub logs_bloom: Bytes256,
98 pub miner: Address,
100 pub mix_hash: H256,
102 pub nonce: Bytes8,
104 pub number: U256,
106 #[serde(skip_serializing_if = "Option::is_none")]
108 pub parent_beacon_block_root: Option<H256>,
109 pub parent_hash: H256,
111 pub receipts_root: H256,
113 #[serde(skip_serializing_if = "Option::is_none")]
115 pub requests_hash: Option<H256>,
116 pub sha_3_uncles: H256,
118 pub size: U256,
120 pub state_root: H256,
122 pub timestamp: U256,
124 #[serde(skip_serializing_if = "Option::is_none")]
126 pub total_difficulty: Option<U256>,
127 pub transactions: HashesOrTransactionInfos,
128 pub transactions_root: H256,
130 pub uncles: Vec<H256>,
132 pub withdrawals: Vec<Withdrawal>,
134 pub withdrawals_root: H256,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize, From, TryInto, Eq, PartialEq)]
140#[serde(untagged)]
141pub enum BlockNumberOrTag {
142 U256(U256),
144 BlockTag(BlockTag),
146}
147impl Default for BlockNumberOrTag {
148 fn default() -> Self {
149 BlockNumberOrTag::BlockTag(Default::default())
150 }
151}
152
153#[derive(Debug, Clone, Serialize, From, TryInto, Eq, PartialEq)]
155#[serde(untagged)]
156pub enum BlockNumberOrTagOrHash {
157 BlockNumber(U256),
159 BlockTag(BlockTag),
161 BlockHash(H256),
163}
164impl Default for BlockNumberOrTagOrHash {
165 fn default() -> Self {
166 BlockNumberOrTagOrHash::BlockTag(Default::default())
167 }
168}
169
170impl<'a> serde::Deserialize<'a> for BlockNumberOrTagOrHash {
172 fn deserialize<D>(de: D) -> Result<Self, D::Error>
173 where
174 D: serde::Deserializer<'a>,
175 {
176 #[derive(Deserialize)]
177 #[serde(untagged)]
178 pub enum BlockNumberOrTagOrHashWithAlias {
179 BlockTag(BlockTag),
180 BlockNumber(U64),
181 NestedBlockNumber {
182 #[serde(rename = "blockNumber")]
183 block_number: U256,
184 },
185 BlockHash(H256),
186 NestedBlockHash {
187 #[serde(rename = "blockHash")]
188 block_hash: H256,
189 },
190 }
191
192 let r = BlockNumberOrTagOrHashWithAlias::deserialize(de)?;
193 Ok(match r {
194 BlockNumberOrTagOrHashWithAlias::BlockTag(val) => BlockNumberOrTagOrHash::BlockTag(val),
195 BlockNumberOrTagOrHashWithAlias::BlockNumber(val) => {
196 let val: u64 =
197 val.try_into().map_err(|_| D::Error::custom("u64 conversion failed"))?;
198 BlockNumberOrTagOrHash::BlockNumber(val.into())
199 },
200
201 BlockNumberOrTagOrHashWithAlias::NestedBlockNumber { block_number: val } =>
202 BlockNumberOrTagOrHash::BlockNumber(val),
203 BlockNumberOrTagOrHashWithAlias::BlockHash(val) |
204 BlockNumberOrTagOrHashWithAlias::NestedBlockHash { block_hash: val } =>
205 BlockNumberOrTagOrHash::BlockHash(val),
206 })
207 }
208}
209
210#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
212#[serde(rename_all = "camelCase")]
213pub struct Filter {
214 pub address: Option<AddressOrAddresses>,
216 #[serde(skip_serializing_if = "Option::is_none")]
218 pub from_block: Option<BlockNumberOrTag>,
219 #[serde(skip_serializing_if = "Option::is_none")]
221 pub to_block: Option<BlockNumberOrTag>,
222 #[serde(skip_serializing_if = "Option::is_none")]
224 pub block_hash: Option<H256>,
225 #[serde(skip_serializing_if = "Option::is_none")]
227 pub topics: Option<FilterTopics>,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize, From, TryInto, Eq, PartialEq)]
232#[serde(untagged)]
233pub enum FilterResults {
234 Hashes(Vec<H256>),
236 Logs(Vec<Log>),
238}
239impl Default for FilterResults {
240 fn default() -> Self {
241 FilterResults::Hashes(Default::default())
242 }
243}
244
245#[derive(
247 Debug, Default, Clone, Encode, Decode, TypeInfo, Serialize, Deserialize, Eq, PartialEq,
248)]
249#[serde(rename_all = "camelCase")]
250pub struct GenericTransaction {
251 #[serde(skip_serializing_if = "Option::is_none")]
254 pub access_list: Option<AccessList>,
255 #[serde(default, skip_serializing_if = "Vec::is_empty")]
258 pub authorization_list: Vec<AuthorizationListEntry>,
259 #[serde(default)]
262 pub blob_versioned_hashes: Vec<H256>,
263 #[serde(default, skip_serializing_if = "Vec::is_empty")]
266 pub blobs: Vec<Bytes>,
267 #[serde(skip_serializing_if = "Option::is_none")]
270 pub chain_id: Option<U256>,
271 #[serde(skip_serializing_if = "Option::is_none")]
273 pub from: Option<Address>,
274 #[serde(skip_serializing_if = "Option::is_none")]
276 pub gas: Option<U256>,
277 #[serde(skip_serializing_if = "Option::is_none")]
280 pub gas_price: Option<U256>,
281 #[serde(flatten, deserialize_with = "deserialize_input_or_data")]
283 pub input: InputOrData,
284 #[serde(skip_serializing_if = "Option::is_none")]
287 pub max_fee_per_blob_gas: Option<U256>,
288 #[serde(skip_serializing_if = "Option::is_none")]
292 pub max_fee_per_gas: Option<U256>,
293 #[serde(skip_serializing_if = "Option::is_none")]
296 pub max_priority_fee_per_gas: Option<U256>,
297 #[serde(skip_serializing_if = "Option::is_none")]
299 pub nonce: Option<U256>,
300 pub to: Option<Address>,
302 #[serde(skip_serializing_if = "Option::is_none")]
304 pub r#type: Option<Byte>,
305 #[serde(skip_serializing_if = "Option::is_none")]
307 pub value: Option<U256>,
308}
309
310#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
312#[serde(rename_all = "camelCase")]
313pub struct ReceiptInfo {
314 #[serde(skip_serializing_if = "Option::is_none")]
318 pub blob_gas_price: Option<U256>,
319 #[serde(skip_serializing_if = "Option::is_none")]
323 pub blob_gas_used: Option<U256>,
324 pub block_hash: H256,
326 pub block_number: U256,
328 pub contract_address: Option<Address>,
331 pub cumulative_gas_used: U256,
334 pub effective_gas_price: U256,
339 pub from: Address,
341 pub gas_used: U256,
344 pub logs: Vec<Log>,
346 pub logs_bloom: Bytes256,
348 #[serde(skip_serializing_if = "Option::is_none")]
352 pub root: Option<H256>,
353 #[serde(skip_serializing_if = "Option::is_none")]
357 pub status: Option<U256>,
358 pub to: Option<Address>,
361 pub transaction_hash: H256,
363 pub transaction_index: U256,
365 #[serde(skip_serializing_if = "Option::is_none")]
367 pub r#type: Option<Byte>,
368}
369
370#[derive(Debug, Clone, Serialize, Deserialize, From, TryInto, Eq, PartialEq)]
372#[serde(untagged)]
373pub enum SyncingStatus {
374 SyncingProgress(SyncingProgress),
376 Bool(bool),
379}
380impl Default for SyncingStatus {
381 fn default() -> Self {
382 SyncingStatus::SyncingProgress(Default::default())
383 }
384}
385
386#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
388#[serde(rename_all = "camelCase")]
389pub struct TransactionInfo {
390 pub block_hash: H256,
392 pub block_number: U256,
394 pub from: Address,
396 pub hash: H256,
398 pub transaction_index: U256,
400 #[serde(flatten)]
401 pub transaction_signed: TransactionSigned,
402}
403
404#[derive(Debug, Clone, Serialize, Deserialize, From, TryInto, Eq, PartialEq)]
405#[serde(untagged)]
406pub enum TransactionUnsigned {
407 Transaction7702Unsigned(Transaction7702Unsigned),
408 Transaction4844Unsigned(Transaction4844Unsigned),
409 Transaction1559Unsigned(Transaction1559Unsigned),
410 Transaction2930Unsigned(Transaction2930Unsigned),
411 TransactionLegacyUnsigned(TransactionLegacyUnsigned),
412}
413impl Default for TransactionUnsigned {
414 fn default() -> Self {
415 TransactionUnsigned::TransactionLegacyUnsigned(Default::default())
416 }
417}
418
419pub type AccessList = Vec<AccessListEntry>;
421
422#[derive(Debug, Clone, Serialize, Deserialize, From, TryInto, Eq, PartialEq)]
424#[serde(untagged)]
425pub enum AddressOrAddresses {
426 Address(Address),
428 Addresses(Addresses),
430}
431impl Default for AddressOrAddresses {
432 fn default() -> Self {
433 AddressOrAddresses::Address(Default::default())
434 }
435}
436
437pub type Addresses = Vec<Address>;
439
440#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
451#[serde(rename_all = "lowercase")]
452pub enum BlockTag {
453 Earliest,
454 Finalized,
455 Safe,
456 #[default]
457 Latest,
458 Pending,
459}
460
461pub type FilterTopics = Vec<FilterTopic>;
463
464#[derive(Debug, Clone, Serialize, Deserialize, From, TryInto, Eq, PartialEq)]
465#[serde(untagged)]
466pub enum HashesOrTransactionInfos {
467 Hashes(Vec<H256>),
469 TransactionInfos(Vec<TransactionInfo>),
471}
472impl Default for HashesOrTransactionInfos {
473 fn default() -> Self {
474 HashesOrTransactionInfos::Hashes(Default::default())
475 }
476}
477
478#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
480#[serde(rename_all = "camelCase")]
481pub struct Log {
482 pub address: Address,
484 pub block_hash: H256,
486 pub block_number: U256,
488 #[serde(skip_serializing_if = "Option::is_none")]
490 pub data: Option<Bytes>,
491 pub log_index: U256,
493 #[serde(default)]
495 pub removed: bool,
496 #[serde(default)]
498 pub topics: Vec<H256>,
499 pub transaction_hash: H256,
501 pub transaction_index: U256,
503}
504
505#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
507#[serde(rename_all = "camelCase")]
508pub struct SyncingProgress {
509 #[serde(skip_serializing_if = "Option::is_none")]
511 pub current_block: Option<U256>,
512 #[serde(skip_serializing_if = "Option::is_none")]
514 pub highest_block: Option<U256>,
515 #[serde(skip_serializing_if = "Option::is_none")]
517 pub starting_block: Option<U256>,
518}
519
520#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
522#[serde(rename_all = "camelCase")]
523pub struct Transaction1559Unsigned {
524 pub access_list: AccessList,
527 pub chain_id: U256,
530 pub gas: U256,
532 pub gas_price: U256,
537 pub input: Bytes,
539 pub max_fee_per_gas: U256,
543 pub max_priority_fee_per_gas: U256,
546 pub nonce: U256,
548 pub to: Option<Address>,
550 pub r#type: TypeEip1559,
552 pub value: U256,
554}
555
556#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
558#[serde(rename_all = "camelCase")]
559pub struct Transaction2930Unsigned {
560 pub access_list: AccessList,
563 pub chain_id: U256,
566 pub gas: U256,
568 pub gas_price: U256,
571 pub input: Bytes,
573 pub nonce: U256,
575 pub to: Option<Address>,
577 pub r#type: TypeEip2930,
579 pub value: U256,
581}
582
583#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
585#[serde(rename_all = "camelCase")]
586pub struct Transaction4844Unsigned {
587 pub access_list: AccessList,
590 pub blob_versioned_hashes: Vec<H256>,
593 pub chain_id: U256,
596 pub gas: U256,
598 pub input: Bytes,
600 pub max_fee_per_blob_gas: U256,
603 pub max_fee_per_gas: U256,
607 pub max_priority_fee_per_gas: U256,
610 pub nonce: U256,
612 pub to: Address,
614 pub r#type: TypeEip4844,
616 pub value: U256,
618}
619
620#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
622#[serde(rename_all = "camelCase")]
623pub struct TransactionLegacyUnsigned {
624 #[serde(skip_serializing_if = "Option::is_none")]
627 pub chain_id: Option<U256>,
628 pub gas: U256,
630 pub gas_price: U256,
633 pub input: Bytes,
635 pub nonce: U256,
637 pub to: Option<Address>,
639 pub r#type: TypeLegacy,
641 pub value: U256,
643}
644
645#[derive(
647 Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq, TypeInfo, Encode, Decode,
648)]
649#[serde(rename_all = "camelCase")]
650pub struct Transaction7702Unsigned {
651 pub access_list: AccessList,
654 pub authorization_list: Vec<AuthorizationListEntry>,
657 pub chain_id: U256,
660 pub gas: U256,
662 pub gas_price: U256,
667 pub input: Bytes,
669 pub max_fee_per_gas: U256,
673 pub max_priority_fee_per_gas: U256,
676 pub nonce: U256,
678 pub to: Option<Address>,
680 pub r#type: TypeEip7702,
682 pub value: U256,
684}
685
686#[derive(
688 Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq, TypeInfo, Encode, Decode,
689)]
690#[serde(rename_all = "camelCase")]
691pub struct AuthorizationListEntry {
692 pub chain_id: U256,
694 pub address: Address,
696 pub nonce: U256,
698 pub y_parity: U256,
700 pub r: U256,
702 pub s: U256,
704}
705
706#[derive(Debug, Clone, Serialize, Deserialize, From, TryInto, Eq, PartialEq)]
707#[serde(untagged)]
708pub enum TransactionSigned {
709 Transaction7702Signed(Transaction7702Signed),
710 Transaction4844Signed(Transaction4844Signed),
711 Transaction1559Signed(Transaction1559Signed),
712 Transaction2930Signed(Transaction2930Signed),
713 TransactionLegacySigned(TransactionLegacySigned),
714}
715impl Default for TransactionSigned {
716 fn default() -> Self {
717 TransactionSigned::TransactionLegacySigned(Default::default())
718 }
719}
720
721impl TransactionSigned {
722 pub fn effective_gas_price(&self, base_gas_price: U256) -> U256 {
724 match &self {
725 TransactionSigned::TransactionLegacySigned(tx) =>
726 tx.transaction_legacy_unsigned.gas_price,
727 TransactionSigned::Transaction7702Signed(tx) => base_gas_price
728 .saturating_add(tx.transaction_7702_unsigned.max_priority_fee_per_gas)
729 .min(tx.transaction_7702_unsigned.max_fee_per_gas),
730 TransactionSigned::Transaction4844Signed(tx) => base_gas_price
731 .saturating_add(tx.transaction_4844_unsigned.max_priority_fee_per_gas)
732 .min(tx.transaction_4844_unsigned.max_fee_per_blob_gas),
733 TransactionSigned::Transaction1559Signed(tx) => base_gas_price
734 .saturating_add(tx.transaction_1559_unsigned.max_priority_fee_per_gas)
735 .min(tx.transaction_1559_unsigned.max_fee_per_gas),
736 TransactionSigned::Transaction2930Signed(tx) => tx.transaction_2930_unsigned.gas_price,
737 }
738 }
739}
740
741#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
743#[serde(rename_all = "camelCase")]
744pub struct Withdrawal {
745 pub address: Address,
747 pub amount: U256,
749 pub index: U256,
751 pub validator_index: U256,
753}
754
755#[derive(
757 Debug, Default, Clone, Encode, Decode, TypeInfo, Serialize, Deserialize, Eq, PartialEq,
758)]
759#[serde(rename_all = "camelCase")]
760pub struct AccessListEntry {
761 pub address: Address,
762 pub storage_keys: Vec<H256>,
763}
764
765#[derive(Debug, Clone, Serialize, Deserialize, From, TryInto, Eq, PartialEq)]
767#[serde(untagged)]
768pub enum FilterTopic {
769 Single(H256),
771 Multiple(Vec<H256>),
773}
774impl Default for FilterTopic {
775 fn default() -> Self {
776 FilterTopic::Single(Default::default())
777 }
778}
779
780#[derive(
782 Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq, TypeInfo, Encode, Decode,
783)]
784#[serde(rename_all = "camelCase")]
785pub struct Transaction7702Signed {
786 #[serde(flatten)]
787 pub transaction_7702_unsigned: Transaction7702Unsigned,
788 pub r: U256,
790 pub s: U256,
792 #[serde(skip_serializing_if = "Option::is_none")]
796 pub v: Option<U256>,
797 pub y_parity: U256,
800}
801
802#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
804#[serde(rename_all = "camelCase")]
805pub struct Transaction1559Signed {
806 #[serde(flatten)]
807 pub transaction_1559_unsigned: Transaction1559Unsigned,
808 pub r: U256,
810 pub s: U256,
812 #[serde(skip_serializing_if = "Option::is_none")]
816 pub v: Option<U256>,
817 pub y_parity: U256,
820}
821
822#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
824#[serde(rename_all = "camelCase")]
825pub struct Transaction2930Signed {
826 #[serde(flatten)]
827 pub transaction_2930_unsigned: Transaction2930Unsigned,
828 pub r: U256,
830 pub s: U256,
832 #[serde(skip_serializing_if = "Option::is_none")]
836 pub v: Option<U256>,
837 pub y_parity: U256,
840}
841
842#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
844#[serde(rename_all = "camelCase")]
845pub struct Transaction4844Signed {
846 #[serde(flatten)]
847 pub transaction_4844_unsigned: Transaction4844Unsigned,
848 pub r: U256,
850 pub s: U256,
852 pub y_parity: U256,
855}
856
857#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
859pub struct TransactionLegacySigned {
860 #[serde(flatten)]
861 pub transaction_legacy_unsigned: TransactionLegacyUnsigned,
862 pub r: U256,
864 pub s: U256,
866 pub v: U256,
868}
869
870#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
871#[serde(rename_all = "camelCase")]
872pub struct FeeHistoryResult {
873 pub oldest_block: U256,
875
876 #[serde(default, skip_serializing_if = "Vec::is_empty")]
881 pub base_fee_per_gas: Vec<U256>,
882
883 pub gas_used_ratio: Vec<f64>,
886
887 #[serde(default, skip_serializing_if = "Vec::is_empty")]
893 pub reward: Vec<Vec<U256>>,
894}
895
896#[cfg(test)]
897mod tests {
898 use super::*;
899
900 #[test]
901 fn test_block_serialization_roundtrip() {
902 let json_input = r#"{
903 "baseFeePerGas": "0x126f2347",
904 "blobGasUsed": "0x100000",
905 "difficulty": "0x0",
906 "excessBlobGas": "0x0",
907 "extraData": "0x546974616e2028746974616e6275696c6465722e78797a29",
908 "gasLimit": "0x2aca2c9",
909 "gasUsed": "0x1c06043",
910 "hash": "0xe6064637def8a5a9a90c8a666005975e4a6c46acf8af57e1f2adb20dfced133a",
911 "logsBloom": "0xbf7bf1afcf57ea95fbb5c6fd8db37db9dbffec27cfc6a39b3417e7786defd7e3d6fd577ecddd5676eee8bf79df8faddcefa7e169def77f7e7d6dbbfd1dfef9aebd9e707b4c4ed979fda2cdeeb96b3bfed5d5fabb68ff9e7f2dfb075eff643a93feebbc07877f0dff66fedf4ede0fbcfbf56f98a1626eaed77ed4e6be388f162f9b2deeff1eefa93bdacbf3fbbd7b6757cddb7ae5b3f9b7af9c3bbff7e7f6ddef9f2dff7f17997ea6867675c29fcbe6bf725efbffe1507589bfd47a3bf7b6f5dfde50776fd94fe772d2c7b6b58baf554de55c176f27efa6fdcff7f17689bafa7f7c7bf4fd5fb9b05c2f4ed785f17ac9779feeaf1f5bbdadfc42ebad367fdcf7ad",
912 "miner": "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97",
913 "mixHash": "0x7e53d2d6772895d024eb00da80213aec81fb4a15bec34a5a39403ad6162274af",
914 "nonce": "0x0000000000000000",
915 "number": "0x1606672",
916 "parentBeaconBlockRoot": "0xd9ef51c8f4155f238ba66df0d35a4d0a6bb043c0dacb5c5dbd5a231bbd4c8a01",
917 "parentHash": "0x37b527c98c86436f292d4e19fac3aba6d8c7768684ea972f50adc305fd9a1475",
918 "receiptsRoot": "0x2abab67c41b350435eb34f9dc0478dd7d262f35544cecf62a85af2da075bd38d",
919 "requestsHash": "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
920 "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
921 "size": "0x29e6c",
922 "stateRoot": "0x5159c56472adff9a760275ac63524a71f5645ede822a5547dd9ad333586d5157",
923 "timestamp": "0x6895a93f",
924 "transactions": [],
925 "transactionsRoot": "0xfb0b9f5b28bc927db98d82e18070d2b17434c31bd2773c5dd699e96fa76a34cd",
926 "uncles": [],
927 "withdrawals": [],
928 "withdrawalsRoot": "0x531480435633d56a52433b33f41ac9322f51a2df3364c4c112236fc6ac583118"
929 }"#;
930
931 let block: Block = serde_json::from_str(json_input).expect("Failed to deserialize block");
933
934 let serialized = serde_json::to_string(&block).expect("Failed to serialize block");
936
937 let block_roundtrip: Block =
939 serde_json::from_str(&serialized).expect("Failed to deserialize roundtrip block");
940
941 assert_eq!(block, block_roundtrip);
943 }
944}