reth_rpc/eth/helpers/
types.rs

1//! L1 `eth` API types.
2
3use alloy_consensus::{Signed, Transaction as _, TxEip4844Variant, TxEnvelope};
4use alloy_network::{Ethereum, Network};
5use alloy_primitives::PrimitiveSignature as Signature;
6use alloy_rpc_types::TransactionRequest;
7use alloy_rpc_types_eth::{Transaction, TransactionInfo};
8use reth_primitives::{RecoveredTx, TransactionSigned};
9use reth_rpc_eth_api::EthApiTypes;
10use reth_rpc_eth_types::EthApiError;
11use reth_rpc_types_compat::TransactionCompat;
12
13/// A standalone [`EthApiTypes`] implementation for Ethereum.
14#[derive(Debug, Clone, Copy, Default)]
15pub struct EthereumEthApiTypes(EthTxBuilder);
16
17impl EthApiTypes for EthereumEthApiTypes {
18    type Error = EthApiError;
19    type NetworkTypes = Ethereum;
20    type TransactionCompat = EthTxBuilder;
21
22    fn tx_resp_builder(&self) -> &Self::TransactionCompat {
23        &self.0
24    }
25}
26
27/// Builds RPC transaction response for l1.
28#[derive(Debug, Clone, Copy, Default)]
29#[non_exhaustive]
30pub struct EthTxBuilder;
31
32impl TransactionCompat for EthTxBuilder
33where
34    Self: Send + Sync,
35{
36    type Transaction = <Ethereum as Network>::TransactionResponse;
37
38    type Error = EthApiError;
39
40    fn fill(
41        &self,
42        tx: RecoveredTx,
43        tx_info: TransactionInfo,
44    ) -> Result<Self::Transaction, Self::Error> {
45        let from = tx.signer();
46        let hash = tx.hash();
47        let TransactionSigned { transaction, signature, .. } = tx.into_signed();
48
49        let inner: TxEnvelope = match transaction {
50            reth_primitives::Transaction::Legacy(tx) => {
51                Signed::new_unchecked(tx, signature, hash).into()
52            }
53            reth_primitives::Transaction::Eip2930(tx) => {
54                Signed::new_unchecked(tx, signature, hash).into()
55            }
56            reth_primitives::Transaction::Eip1559(tx) => {
57                Signed::new_unchecked(tx, signature, hash).into()
58            }
59            reth_primitives::Transaction::Eip4844(tx) => {
60                Signed::new_unchecked(tx, signature, hash).into()
61            }
62            reth_primitives::Transaction::Eip7702(tx) => {
63                Signed::new_unchecked(tx, signature, hash).into()
64            }
65            reth_primitives::Transaction::Seismic(tx) => {
66                Signed::new_unchecked(tx, signature, hash).into()
67            }
68            #[allow(unreachable_patterns)]
69            _ => unreachable!(),
70        };
71
72        let TransactionInfo {
73            block_hash, block_number, index: transaction_index, base_fee, ..
74        } = tx_info;
75
76        let effective_gas_price = base_fee
77            .map(|base_fee| {
78                inner.effective_tip_per_gas(base_fee as u64).unwrap_or_default() + base_fee
79            })
80            .unwrap_or_else(|| inner.max_fee_per_gas());
81
82        Ok(Transaction {
83            inner,
84            block_hash,
85            block_number,
86            transaction_index,
87            from,
88            effective_gas_price: Some(effective_gas_price),
89        })
90    }
91
92    fn build_simulate_v1_transaction(
93        &self,
94        request: TransactionRequest,
95    ) -> Result<TransactionSigned, Self::Error> {
96        let Ok(tx) = request.build_typed_tx() else {
97            return Err(EthApiError::TransactionConversionError)
98        };
99
100        // Create an empty signature for the transaction.
101        let signature = Signature::new(Default::default(), Default::default(), false);
102        Ok(TransactionSigned::new_unhashed(tx.into(), signature))
103    }
104
105    fn otterscan_api_truncate_input(tx: &mut Self::Transaction) {
106        let input = match &mut tx.inner {
107            TxEnvelope::Eip1559(tx) => &mut tx.tx_mut().input,
108            TxEnvelope::Eip2930(tx) => &mut tx.tx_mut().input,
109            TxEnvelope::Legacy(tx) => &mut tx.tx_mut().input,
110            TxEnvelope::Eip4844(tx) => match tx.tx_mut() {
111                TxEip4844Variant::TxEip4844(tx) => &mut tx.input,
112                TxEip4844Variant::TxEip4844WithSidecar(tx) => &mut tx.tx.input,
113            },
114            TxEnvelope::Eip7702(tx) => &mut tx.tx_mut().input,
115            _ => return,
116        };
117        *input = input.slice(..4);
118    }
119}