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