revm_statetest_types/
transaction.rs1use crate::{deserializer::deserialize_maybe_empty, TestAuthorization};
2use context::TransactionType;
3use context_interface::transaction::AccessList;
4use primitives::{Address, Bytes, B256, U256};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct TransactionParts {
11 #[serde(rename = "type")]
13 pub tx_type: Option<u8>,
14 pub chain_id: Option<U256>,
17 pub data: Vec<Bytes>,
19 pub gas_limit: Vec<U256>,
21 pub gas_price: Option<U256>,
23 pub nonce: U256,
25 pub secret_key: Option<B256>,
31 #[serde(default)]
33 pub sender: Option<Address>,
34 #[serde(default, deserialize_with = "deserialize_maybe_empty")]
36 pub to: Option<Address>,
37 pub value: Vec<U256>,
39 pub max_fee_per_gas: Option<U256>,
41 pub max_priority_fee_per_gas: Option<U256>,
43 pub initcodes: Option<Vec<Bytes>>,
45 #[serde(default)]
47 pub access_lists: Vec<Option<AccessList>>,
48 pub authorization_list: Option<Vec<TestAuthorization>>,
50 #[serde(default)]
52 pub blob_versioned_hashes: Vec<B256>,
53 pub max_fee_per_blob_gas: Option<U256>,
55}
56
57impl TransactionParts {
58 pub fn tx_type(&self, access_list_index: usize) -> Option<TransactionType> {
66 if let Some(tx_type) = self.tx_type {
67 return Some(TransactionType::from(tx_type));
68 }
69
70 let mut tx_type = TransactionType::Legacy;
71
72 if let Some(access_list) = self.access_lists.get(access_list_index) {
74 if access_list.is_some() {
75 tx_type = TransactionType::Eip2930;
76 }
77 }
78
79 if self.max_fee_per_gas.is_some() {
81 tx_type = TransactionType::Eip1559;
82 }
83
84 if self.max_fee_per_blob_gas.is_some() {
86 self.to?;
88 return Some(TransactionType::Eip4844);
89 }
90
91 if self.authorization_list.is_some() {
93 self.to?;
95 return Some(TransactionType::Eip7702);
96 }
97
98 Some(tx_type)
99 }
100}
101
102#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
104#[serde(rename_all = "camelCase", deny_unknown_fields)]
105pub struct TxPartIndices {
106 pub data: usize,
108 pub gas: usize,
110 pub value: usize,
112}
113
114#[cfg(test)]
115mod test {
116
117 use super::*;
118
119 #[test]
120 fn decode_tx_parts() {
121 let tx = r#"{
122 "nonce": "0x00",
123 "maxPriorityFeePerGas": "0x00",
124 "maxFeePerGas": "0x07",
125 "gasLimit": [
126 "0x0423ff"
127 ],
128 "to": "0x0000000000000000000000000000000000001000",
129 "value": [
130 "0x00"
131 ],
132 "data": [
133 "0x"
134 ],
135 "accessLists": [
136 [
137 {
138 "address": "0x6389e7f33ce3b1e94e4325ef02829cd12297ef71",
139 "storageKeys": [
140 "0x0000000000000000000000000000000000000000000000000000000000000000"
141 ]
142 }
143 ]
144 ],
145 "authorizationList": [
146 {
147 "chainId": "0x00",
148 "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
149 "nonce": "0x00",
150 "v": "0x01",
151 "r": "0x5a8cac98fd240d8ef83c22db4a061ffa0facb1801245283cc05fc809d8b92837",
152 "s": "0x1c3162fe11d91bc24d4fa00fb19ca34531e0eacdf8142c804be44058d5b8244f",
153 "signer": "0x6389e7f33ce3b1e94e4325ef02829cd12297ef71"
154 }
155 ],
156 "sender": "0x8a0a19589531694250d570040a0c4b74576919b8",
157 "secretKey": "0x9e7645d0cfd9c3a04eb7a9db59a4eb7d359f2e75c9164a9d6b9a7d54e1b6a36f"
158 }"#;
159
160 let _: TransactionParts = serde_json::from_str(tx).unwrap();
161 }
162}