revm_statetest_types/
transaction.rs1use crate::{deserializer::deserialize_maybe_empty, TestAuthorization};
2use revm::{
3 context::TransactionType,
4 context_interface::transaction::AccessList,
5 primitives::{Address, Bytes, B256, U256},
6};
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub struct TransactionParts {
13 #[serde(rename = "type")]
14 pub tx_type: Option<u8>,
15 pub data: Vec<Bytes>,
16 pub gas_limit: Vec<U256>,
17 pub gas_price: Option<U256>,
18 pub nonce: U256,
19 pub secret_key: B256,
20 #[serde(default)]
22 pub sender: Option<Address>,
23 #[serde(default, deserialize_with = "deserialize_maybe_empty")]
24 pub to: Option<Address>,
25 pub value: Vec<U256>,
26 pub max_fee_per_gas: Option<U256>,
27 pub max_priority_fee_per_gas: Option<U256>,
28 pub initcodes: Option<Vec<Bytes>>,
29 #[serde(default)]
30 pub access_lists: Vec<Option<AccessList>>,
31 pub authorization_list: Option<Vec<TestAuthorization>>,
32 #[serde(default)]
33 pub blob_versioned_hashes: Vec<B256>,
34 pub max_fee_per_blob_gas: Option<U256>,
35}
36
37impl TransactionParts {
38 pub fn tx_type(&self, access_list_index: usize) -> Option<TransactionType> {
46 if let Some(tx_type) = self.tx_type {
47 return Some(TransactionType::from(tx_type));
48 }
49
50 let mut tx_type = TransactionType::Legacy;
51
52 if let Some(access_list) = self.access_lists.get(access_list_index) {
54 if access_list.is_some() {
55 tx_type = TransactionType::Eip2930;
56 }
57 }
58
59 if self.max_fee_per_gas.is_some() {
61 tx_type = TransactionType::Eip1559;
62 }
63
64 if self.max_fee_per_blob_gas.is_some() {
66 self.to?;
68 return Some(TransactionType::Eip4844);
69 }
70
71 if self.authorization_list.is_some() {
73 self.to?;
75 return Some(TransactionType::Eip7702);
76 }
77
78 if self.initcodes.is_some() {
80 self.to?;
82 return Some(TransactionType::Eip7873);
83 }
84
85 Some(tx_type)
86 }
87}
88
89#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
91#[serde(rename_all = "camelCase", deny_unknown_fields)]
92pub struct TxPartIndices {
93 pub data: usize,
94 pub gas: usize,
95 pub value: usize,
96}
97
98#[cfg(test)]
99mod test {
100
101 use super::*;
102
103 #[test]
104 fn decode_tx_parts() {
105 let tx = r#"{
106 "nonce": "0x00",
107 "maxPriorityFeePerGas": "0x00",
108 "maxFeePerGas": "0x07",
109 "gasLimit": [
110 "0x0423ff"
111 ],
112 "to": "0x0000000000000000000000000000000000001000",
113 "value": [
114 "0x00"
115 ],
116 "data": [
117 "0x"
118 ],
119 "accessLists": [
120 [
121 {
122 "address": "0x6389e7f33ce3b1e94e4325ef02829cd12297ef71",
123 "storageKeys": [
124 "0x0000000000000000000000000000000000000000000000000000000000000000"
125 ]
126 }
127 ]
128 ],
129 "authorizationList": [
130 {
131 "chainId": "0x00",
132 "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
133 "nonce": "0x00",
134 "v": "0x01",
135 "r": "0x5a8cac98fd240d8ef83c22db4a061ffa0facb1801245283cc05fc809d8b92837",
136 "s": "0x1c3162fe11d91bc24d4fa00fb19ca34531e0eacdf8142c804be44058d5b8244f",
137 "signer": "0x6389e7f33ce3b1e94e4325ef02829cd12297ef71"
138 }
139 ],
140 "sender": "0x8a0a19589531694250d570040a0c4b74576919b8",
141 "secretKey": "0x9e7645d0cfd9c3a04eb7a9db59a4eb7d359f2e75c9164a9d6b9a7d54e1b6a36f"
142 }"#;
143
144 let _: TransactionParts = serde_json::from_str(tx).unwrap();
145 }
146}