Skip to main content

reth_rpc/eth/helpers/
types.rs

1//! L1 `eth` API types.
2
3use alloy_network::Ethereum;
4use reth_evm_ethereum::EthEvmConfig;
5use reth_rpc_convert::RpcConverter;
6use reth_rpc_eth_types::receipt::EthReceiptConverter;
7
8/// An [`RpcConverter`] with its generics set to Ethereum specific.
9pub type EthRpcConverter<ChainSpec> =
10    RpcConverter<Ethereum, EthEvmConfig, EthReceiptConverter<ChainSpec>>;
11
12//tests for simulate
13#[cfg(test)]
14mod tests {
15    use super::*;
16    use alloy_consensus::{Transaction, TxType};
17    use alloy_primitives::{Address, B256, U256};
18    use alloy_rpc_types_eth::TransactionRequest;
19    use evm2::evm::EmptyDB;
20    use reth_chainspec::MAINNET;
21    use reth_evm_ethereum::EthEvmEnv;
22    use reth_rpc_convert::RpcConvert;
23    use reth_rpc_eth_types::simulate::resolve_transaction;
24
25    #[test]
26    fn test_resolve_transaction_empty_request() {
27        let builder = EthRpcConverter::new(EthReceiptConverter::new(MAINNET.clone()));
28        let mut db = EmptyDB::default();
29        let tx = TransactionRequest::default();
30        let result = resolve_transaction(tx, 21000, 0, 1, false, &mut db, &builder).unwrap();
31
32        // For an empty request, we should get a valid transaction with defaults
33        let tx = result.into_inner();
34        assert_eq!(tx.max_fee_per_gas(), 0);
35        assert_eq!(tx.max_priority_fee_per_gas(), Some(0));
36        assert_eq!(tx.gas_price(), None);
37    }
38
39    #[test]
40    fn test_resolve_transaction_legacy() {
41        let mut db = EmptyDB::default();
42        let builder = EthRpcConverter::new(EthReceiptConverter::new(MAINNET.clone()));
43
44        let tx = TransactionRequest { gas_price: Some(100), ..Default::default() };
45
46        let tx = resolve_transaction(tx, 21000, 0, 1, false, &mut db, &builder).unwrap();
47
48        assert_eq!(tx.tx_type(), TxType::Legacy);
49
50        let tx = tx.into_inner();
51        assert_eq!(tx.gas_price(), Some(100));
52        assert_eq!(tx.max_priority_fee_per_gas(), None);
53    }
54
55    #[test]
56    fn test_resolve_transaction_partial_eip1559() {
57        let mut db = EmptyDB::default();
58        let rpc_converter = EthRpcConverter::new(EthReceiptConverter::new(MAINNET.clone()));
59
60        let tx = TransactionRequest {
61            max_fee_per_gas: Some(200),
62            max_priority_fee_per_gas: Some(10),
63            ..Default::default()
64        };
65
66        let result = resolve_transaction(tx, 21000, 0, 1, false, &mut db, &rpc_converter).unwrap();
67
68        assert_eq!(result.tx_type(), TxType::Eip1559);
69        let tx = result.into_inner();
70        assert_eq!(tx.max_fee_per_gas(), 200);
71        assert_eq!(tx.max_priority_fee_per_gas(), Some(10));
72        assert_eq!(tx.gas_price(), None);
73    }
74
75    #[test]
76    fn test_resolve_transaction_wraps_max_nonce_when_nonce_check_disabled() {
77        let mut db = EmptyDB::default();
78        let rpc_converter = EthRpcConverter::new(EthReceiptConverter::new(MAINNET.clone()));
79
80        let tx = TransactionRequest { nonce: Some(u64::MAX), ..Default::default() };
81
82        let result = resolve_transaction(tx, 21000, 0, 1, true, &mut db, &rpc_converter).unwrap();
83
84        assert_eq!(result.nonce(), 0);
85    }
86
87    #[test]
88    fn test_typed_request_fee_defaults() {
89        let converter = EthRpcConverter::new(EthReceiptConverter::new(MAINNET.clone()));
90        // Default blob fee caps must retain values beyond u64 without truncation.
91        for blob_fee in [u128::from(u64::MAX), u128::from(u64::MAX) + 1, u128::MAX] {
92            let mut env = EthEvmEnv::default();
93            env.block.blob_basefee = U256::from(blob_fee);
94            env.block.basefee = U256::from(30);
95            let request = TransactionRequest {
96                to: Some(Address::repeat_byte(0xaa).into()),
97                blob_versioned_hashes: Some(vec![B256::repeat_byte(1)]),
98                gas_price: Some(100),
99                ..Default::default()
100            };
101
102            let tx = converter.tx_env(request.clone(), &env).unwrap();
103
104            assert_eq!(tx.max_fee_per_blob_gas(), Some(blob_fee));
105            // Flat gasPrice must not be reduced to the base fee for a blob request.
106            assert_eq!(tx.effective_gas_price(Some(30)), 100);
107
108            // An authorization list selects EIP-7702, which must preserve the same flat price.
109            let request = TransactionRequest {
110                authorization_list: Some(vec![]),
111                blob_versioned_hashes: None,
112                ..request
113            };
114            let tx = converter.tx_env(request.clone(), &env).unwrap();
115            assert_eq!(tx.effective_gas_price(Some(30)), 100);
116
117            // An explicit zero priority fee still opts into base-fee pricing.
118            let request = TransactionRequest {
119                gas_price: None,
120                max_fee_per_gas: Some(100),
121                max_priority_fee_per_gas: Some(0),
122                ..request
123            };
124            let tx = converter.tx_env(request, &env).unwrap();
125            assert_eq!(tx.effective_gas_price(Some(30)), 30);
126        }
127    }
128}