1use crate::EthApi;
4use alloy_consensus::TxType;
5use alloy_evm::block::BlockExecutorFactory;
6use alloy_primitives::{TxKind, U256};
7use alloy_rpc_types::TransactionRequest;
8use reth_evm::{ConfigureEvm, EvmEnv, EvmFactory, SpecFor};
9use reth_node_api::NodePrimitives;
10use reth_rpc_eth_api::{
11 helpers::{estimate::EstimateCall, Call, EthCall, LoadPendingBlock, LoadState, SpawnBlocking},
12 FromEthApiError, FromEvmError, FullEthApiTypes, IntoEthApiError,
13};
14use reth_rpc_eth_types::{revm_utils::CallFees, EthApiError, RpcInvalidTransactionError};
15use reth_storage_api::{BlockReader, ProviderHeader, ProviderTx};
16use revm::{context::TxEnv, context_interface::Block, Database};
17
18impl<Provider, Pool, Network, EvmConfig> EthCall for EthApi<Provider, Pool, Network, EvmConfig>
19where
20 Self: EstimateCall + LoadPendingBlock + FullEthApiTypes,
21 Provider: BlockReader,
22{
23}
24
25impl<Provider, Pool, Network, EvmConfig> Call for EthApi<Provider, Pool, Network, EvmConfig>
26where
27 Self: LoadState<
28 Evm: ConfigureEvm<
29 BlockExecutorFactory: BlockExecutorFactory<EvmFactory: EvmFactory<Tx = TxEnv>>,
30 Primitives: NodePrimitives<
31 BlockHeader = ProviderHeader<Self::Provider>,
32 SignedTx = ProviderTx<Self::Provider>,
33 >,
34 >,
35 Error: FromEvmError<Self::Evm>,
36 > + SpawnBlocking,
37 Provider: BlockReader,
38{
39 #[inline]
40 fn call_gas_limit(&self) -> u64 {
41 self.inner.gas_cap()
42 }
43
44 #[inline]
45 fn max_simulate_blocks(&self) -> u64 {
46 self.inner.max_simulate_blocks()
47 }
48
49 fn create_txn_env(
50 &self,
51 evm_env: &EvmEnv<SpecFor<Self::Evm>>,
52 request: TransactionRequest,
53 mut db: impl Database<Error: Into<EthApiError>>,
54 ) -> Result<TxEnv, Self::Error> {
55 if request.blob_versioned_hashes.as_ref().is_some_and(|hashes| hashes.is_empty()) {
57 return Err(RpcInvalidTransactionError::BlobTransactionMissingBlobHashes.into_eth_err())
58 }
59
60 let tx_type = if request.authorization_list.is_some() {
61 TxType::Eip7702
62 } else if request.sidecar.is_some() || request.max_fee_per_blob_gas.is_some() {
63 TxType::Eip4844
64 } else if request.max_fee_per_gas.is_some() || request.max_priority_fee_per_gas.is_some() {
65 TxType::Eip1559
66 } else if request.access_list.is_some() {
67 TxType::Eip2930
68 } else {
69 TxType::Legacy
70 } as u8;
71
72 let TransactionRequest {
73 from,
74 to,
75 gas_price,
76 max_fee_per_gas,
77 max_priority_fee_per_gas,
78 gas,
79 value,
80 input,
81 nonce,
82 access_list,
83 chain_id,
84 blob_versioned_hashes,
85 max_fee_per_blob_gas,
86 authorization_list,
87 transaction_type: _,
88 sidecar: _,
89 } = request;
90
91 let CallFees { max_priority_fee_per_gas, gas_price, max_fee_per_blob_gas } =
92 CallFees::ensure_fees(
93 gas_price.map(U256::from),
94 max_fee_per_gas.map(U256::from),
95 max_priority_fee_per_gas.map(U256::from),
96 U256::from(evm_env.block_env.basefee),
97 blob_versioned_hashes.as_deref(),
98 max_fee_per_blob_gas.map(U256::from),
99 evm_env.block_env.blob_gasprice().map(U256::from),
100 )?;
101
102 let gas_limit = gas.unwrap_or(
103 evm_env.block_env.gas_limit,
109 );
110
111 let chain_id = chain_id.unwrap_or(evm_env.cfg_env.chain_id);
112
113 let caller = from.unwrap_or_default();
114
115 let nonce = if let Some(nonce) = nonce {
116 nonce
117 } else {
118 db.basic(caller).map_err(Into::into)?.map(|acc| acc.nonce).unwrap_or_default()
119 };
120
121 let env = TxEnv {
122 tx_type,
123 gas_limit,
124 nonce,
125 caller,
126 gas_price: gas_price.saturating_to(),
127 gas_priority_fee: max_priority_fee_per_gas.map(|v| v.saturating_to()),
128 kind: to.unwrap_or(TxKind::Create),
129 value: value.unwrap_or_default(),
130 data: input
131 .try_into_unique_input()
132 .map_err(Self::Error::from_eth_err)?
133 .unwrap_or_default(),
134 chain_id: Some(chain_id),
135 access_list: access_list.unwrap_or_default(),
136 blob_hashes: blob_versioned_hashes.unwrap_or_default(),
138 max_fee_per_blob_gas: max_fee_per_blob_gas
139 .map(|v| v.saturating_to())
140 .unwrap_or_default(),
141 authorization_list: authorization_list.unwrap_or_default(),
143 };
144
145 Ok(env)
146 }
147}
148
149impl<Provider, Pool, Network, EvmConfig> EstimateCall for EthApi<Provider, Pool, Network, EvmConfig>
150where
151 Self: Call,
152 Provider: BlockReader,
153{
154}