1use crate::EthApi;
4use alloy_evm::block::BlockExecutorFactory;
5use alloy_primitives::{TxKind, U256};
6use alloy_rpc_types::TransactionRequest;
7use alloy_signer::Either;
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 = request.minimal_tx_type() as u8;
61
62 let TransactionRequest {
63 from,
64 to,
65 gas_price,
66 max_fee_per_gas,
67 max_priority_fee_per_gas,
68 gas,
69 value,
70 input,
71 nonce,
72 access_list,
73 chain_id,
74 blob_versioned_hashes,
75 max_fee_per_blob_gas,
76 authorization_list,
77 transaction_type: _,
78 sidecar: _,
79 } = request;
80
81 let CallFees { max_priority_fee_per_gas, gas_price, max_fee_per_blob_gas } =
82 CallFees::ensure_fees(
83 gas_price.map(U256::from),
84 max_fee_per_gas.map(U256::from),
85 max_priority_fee_per_gas.map(U256::from),
86 U256::from(evm_env.block_env.basefee),
87 blob_versioned_hashes.as_deref(),
88 max_fee_per_blob_gas.map(U256::from),
89 evm_env.block_env.blob_gasprice().map(U256::from),
90 )?;
91
92 let gas_limit = gas.unwrap_or(
93 evm_env.block_env.gas_limit,
99 );
100
101 let chain_id = chain_id.unwrap_or(evm_env.cfg_env.chain_id);
102
103 let caller = from.unwrap_or_default();
104
105 let nonce = if let Some(nonce) = nonce {
106 nonce
107 } else {
108 db.basic(caller).map_err(Into::into)?.map(|acc| acc.nonce).unwrap_or_default()
109 };
110
111 let env = TxEnv {
112 tx_type,
113 gas_limit,
114 nonce,
115 caller,
116 gas_price: gas_price.saturating_to(),
117 gas_priority_fee: max_priority_fee_per_gas.map(|v| v.saturating_to()),
118 kind: to.unwrap_or(TxKind::Create),
119 value: value.unwrap_or_default(),
120 data: input
121 .try_into_unique_input()
122 .map_err(Self::Error::from_eth_err)?
123 .unwrap_or_default(),
124 chain_id: Some(chain_id),
125 access_list: access_list.unwrap_or_default(),
126 blob_hashes: blob_versioned_hashes.unwrap_or_default(),
128 max_fee_per_blob_gas: max_fee_per_blob_gas
129 .map(|v| v.saturating_to())
130 .unwrap_or_default(),
131 authorization_list: authorization_list
133 .unwrap_or_default()
134 .into_iter()
135 .map(Either::Left)
136 .collect(),
137 };
138
139 Ok(env)
140 }
141}
142
143impl<Provider, Pool, Network, EvmConfig> EstimateCall for EthApi<Provider, Pool, Network, EvmConfig>
144where
145 Self: Call,
146 Provider: BlockReader,
147{
148}