1use alloc::vec::Vec;
2
3use alloy_primitives::Address;
4use alloy_rlp::{RlpDecodable, RlpEncodable};
5
6#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
8#[repr(u8)]
9#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
10#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))]
11#[cfg_attr(feature = "borsh", borsh(use_discriminant = true))]
12pub enum FrameStatus {
13 #[default]
15 Failure = 0x00,
16 Success = 0x01,
18 SkippedAtomicBatch = 0x02,
20}
21
22impl FrameStatus {
23 pub const fn is_failure(self) -> bool {
25 matches!(self, Self::Failure)
26 }
27
28 pub const fn is_success(self) -> bool {
30 matches!(self, Self::Success)
31 }
32
33 pub const fn is_skipped_atomic_batch(self) -> bool {
35 matches!(self, Self::SkippedAtomicBatch)
36 }
37
38 pub const fn try_from_u8(value: u8) -> Option<Self> {
40 match value {
41 0x00 => Some(Self::Failure),
42 0x01 => Some(Self::Success),
43 0x02 => Some(Self::SkippedAtomicBatch),
44 _ => None,
45 }
46 }
47}
48
49impl_u8_discriminant!(FrameStatus, InvalidStatus, "invalid EIP-8141 frame status");
50
51#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, RlpEncodable, RlpDecodable)]
53#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
54#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
55#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
56#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))]
57pub struct FrameGasUsed {
58 #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::quantity"))]
60 pub execution: u64,
61 #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::quantity"))]
63 pub state: u64,
64}
65
66#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, RlpEncodable, RlpDecodable)]
71#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
72#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
73#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
74#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))]
75pub struct FrameReceipt<Log = alloy_primitives::Log> {
76 pub status: FrameStatus,
78 pub gas_used: FrameGasUsed,
80 pub logs: Vec<Log>,
82}
83
84#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, RlpEncodable, RlpDecodable)]
86#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
87#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
88#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
89#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))]
90pub struct FrameReceiptPayload<Log = alloy_primitives::Log> {
91 #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::quantity"))]
93 pub cumulative_gas_used: u64,
94 pub payer: Address,
96 pub frame_receipts: Vec<FrameReceipt<Log>>,
98}
99
100impl<Log> FrameReceiptPayload<Log> {
101 pub fn map_logs<U>(self, mut f: impl FnMut(Log) -> U) -> FrameReceiptPayload<U> {
103 FrameReceiptPayload {
104 cumulative_gas_used: self.cumulative_gas_used,
105 payer: self.payer,
106 frame_receipts: self
107 .frame_receipts
108 .into_iter()
109 .map(|receipt| FrameReceipt {
110 status: receipt.status,
111 gas_used: receipt.gas_used,
112 logs: receipt.logs.into_iter().map(&mut f).collect(),
113 })
114 .collect(),
115 }
116 }
117}