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