openzeppelin_monitor/models/blockchain/evm/
receipt.rs1use alloy::{
4 consensus::{Eip658Value, ReceiptEnvelope},
5 primitives::{aliases::B2048, Address, Bytes, Log as AlloyLog, B256, U256, U64},
6 rpc::types::{Index, TransactionReceipt as AlloyTransactionReceipt},
7};
8use serde::{Deserialize, Serialize};
9use std::ops::Deref;
10
11#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
14pub struct BaseReceipt {
15 #[serde(rename = "transactionHash")]
17 pub transaction_hash: B256,
18 #[serde(rename = "transactionIndex")]
20 pub transaction_index: Index,
21 #[serde(rename = "blockHash")]
23 pub block_hash: Option<B256>,
24 #[serde(rename = "blockNumber")]
26 pub block_number: Option<U64>,
27 #[serde(default)]
31 pub from: Address,
32 #[serde(default)]
36 pub to: Option<Address>,
37 #[serde(rename = "cumulativeGasUsed")]
39 pub cumulative_gas_used: U256,
40 #[serde(rename = "gasUsed")]
44 pub gas_used: Option<U256>,
45 #[serde(rename = "contractAddress")]
47 pub contract_address: Option<Address>,
48 pub logs: Vec<BaseLog>,
50 pub status: Option<U64>,
52 pub root: Option<B256>,
54 #[serde(rename = "logsBloom")]
56 pub logs_bloom: B2048,
57 #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
59 pub transaction_type: Option<U64>,
60 #[serde(rename = "effectiveGasPrice")]
62 pub effective_gas_price: Option<U256>,
63}
64
65#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
68pub struct BaseLog {
69 pub address: Address,
71 pub topics: Vec<B256>,
73 pub data: Bytes,
75 #[serde(rename = "blockHash")]
77 pub block_hash: Option<B256>,
78 #[serde(rename = "blockNumber")]
80 pub block_number: Option<U64>,
81 #[serde(rename = "transactionHash")]
83 pub transaction_hash: Option<B256>,
84 #[serde(rename = "transactionIndex")]
86 pub transaction_index: Option<Index>,
87 #[serde(rename = "logIndex")]
89 pub log_index: Option<U256>,
90 #[serde(rename = "transactionLogIndex")]
92 pub transaction_log_index: Option<U256>,
93 #[serde(rename = "logType")]
95 pub log_type: Option<String>,
96 pub removed: Option<bool>,
98}
99
100impl From<AlloyLog> for BaseLog {
101 fn from(log: AlloyLog) -> Self {
102 Self {
103 address: log.address,
104 topics: log.topics().to_vec(),
105 data: log.data.data,
106 block_hash: None,
107 block_number: None,
108 transaction_hash: None,
109 transaction_index: None,
110 log_index: None,
111 transaction_log_index: None,
112 log_type: None,
113 removed: None,
114 }
115 }
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize, Default)]
123pub struct TransactionReceipt(pub BaseReceipt);
124
125impl From<BaseReceipt> for TransactionReceipt {
126 fn from(tx: BaseReceipt) -> Self {
127 Self(tx)
128 }
129}
130
131impl From<AlloyTransactionReceipt> for TransactionReceipt {
132 fn from(receipt: AlloyTransactionReceipt) -> Self {
133 let inner_receipt = match &receipt.inner {
134 ReceiptEnvelope::Legacy(r) => &r.receipt,
135 ReceiptEnvelope::Eip2930(r) => &r.receipt,
136 ReceiptEnvelope::Eip1559(r) => &r.receipt,
137 ReceiptEnvelope::Eip4844(r) => &r.receipt,
138 ReceiptEnvelope::Eip7702(r) => &r.receipt,
139 };
140
141 let tx = BaseReceipt {
142 transaction_hash: receipt.transaction_hash,
143 transaction_index: Index::from(receipt.transaction_index.unwrap_or(0) as usize),
144 block_hash: receipt.block_hash,
145 block_number: receipt.block_number.map(U64::from),
146 from: receipt.from,
147 to: receipt.to,
148 cumulative_gas_used: U256::from(inner_receipt.cumulative_gas_used),
149 gas_used: Some(U256::from(receipt.gas_used)),
150 contract_address: receipt.contract_address,
151 logs: inner_receipt
152 .logs
153 .iter()
154 .cloned()
155 .map(|l| BaseLog::from(alloy::primitives::Log::from(l)))
156 .collect(),
157 status: match inner_receipt.status {
158 Eip658Value::Eip658(status) => Some(U64::from(if status { 1u64 } else { 0u64 })),
159 Eip658Value::PostState(_) => Some(U64::from(1u64)),
160 },
161 root: None,
162 logs_bloom: B2048::from_slice(match &receipt.inner {
163 ReceiptEnvelope::Legacy(r) => r.logs_bloom.as_slice(),
164 ReceiptEnvelope::Eip2930(r) => r.logs_bloom.as_slice(),
165 ReceiptEnvelope::Eip1559(r) => r.logs_bloom.as_slice(),
166 ReceiptEnvelope::Eip4844(r) => r.logs_bloom.as_slice(),
167 ReceiptEnvelope::Eip7702(r) => r.logs_bloom.as_slice(),
168 }),
169 transaction_type: Some(U64::from(match receipt.inner {
170 ReceiptEnvelope::Legacy(_) => 0,
171 ReceiptEnvelope::Eip2930(_) => 1,
172 ReceiptEnvelope::Eip1559(_) => 2,
173 ReceiptEnvelope::Eip4844(_) => 3,
174 ReceiptEnvelope::Eip7702(_) => 4,
175 })),
176 effective_gas_price: Some(U256::from(receipt.effective_gas_price)),
177 };
178 Self(tx)
179 }
180}
181
182impl Deref for TransactionReceipt {
183 type Target = BaseReceipt;
184
185 fn deref(&self) -> &Self::Target {
186 &self.0
187 }
188}