@@ -5,10 +5,13 @@ use crate::{
55 keccak256,
66 sign_types:: { biguint_to_32bytes_le, ct_option_ok_or, recover_pk, SignData , SECP256K1_Q } ,
77 AccessList , Address , Block , Bytecode , Bytes , Error , GethExecTrace , Hash , ToBigEndian ,
8- ToLittleEndian , ToWord , Word , U64 ,
8+ ToLittleEndian , ToWord , Word , H256 , U64 ,
99} ;
1010use ethers_core:: {
11- types:: { transaction:: response, NameOrAddress , TransactionRequest } ,
11+ types:: {
12+ transaction:: { eip2718:: TypedTransaction , response} ,
13+ Eip1559TransactionRequest , Eip2930TransactionRequest , NameOrAddress , TransactionRequest ,
14+ } ,
1215 utils:: get_contract_address,
1316} ;
1417use ethers_signers:: { LocalWallet , Signer } ;
@@ -18,6 +21,117 @@ use num_bigint::BigUint;
1821use serde:: { Serialize , Serializer } ;
1922use serde_with:: serde_as;
2023use std:: collections:: HashMap ;
24+ use strum_macros:: EnumIter ;
25+
26+ /// Tx type
27+ #[ derive( Default , Debug , Copy , Clone , EnumIter , Serialize , PartialEq , Eq ) ]
28+ pub enum TxType {
29+ /// EIP 155 tx
30+ #[ default]
31+ Eip155 = 0 ,
32+ /// Pre EIP 155 tx
33+ PreEip155 ,
34+ /// EIP 1559 tx
35+ Eip1559 ,
36+ /// EIP 2930 tx
37+ Eip2930 ,
38+ }
39+
40+ impl From < TxType > for usize {
41+ fn from ( value : TxType ) -> Self {
42+ value as usize
43+ }
44+ }
45+
46+ impl From < TxType > for u64 {
47+ fn from ( value : TxType ) -> Self {
48+ value as u64
49+ }
50+ }
51+
52+ impl TxType {
53+ /// If this type is PreEip155
54+ pub fn is_pre_eip155 ( & self ) -> bool {
55+ matches ! ( * self , TxType :: PreEip155 )
56+ }
57+
58+ /// If this type is EIP155 or not
59+ pub fn is_eip155 ( & self ) -> bool {
60+ matches ! ( * self , TxType :: Eip155 )
61+ }
62+
63+ /// If this type is Eip1559 or not
64+ pub fn is_eip1559 ( & self ) -> bool {
65+ matches ! ( * self , TxType :: Eip1559 )
66+ }
67+
68+ /// If this type is Eip2930 or not
69+ pub fn is_eip2930 ( & self ) -> bool {
70+ matches ! ( * self , TxType :: Eip2930 )
71+ }
72+
73+ /// Get the type of transaction
74+ pub fn get_tx_type ( tx : & crate :: Transaction ) -> Self {
75+ match tx. transaction_type {
76+ Some ( x) if x == U64 :: from ( 1 ) => Self :: Eip2930 ,
77+ Some ( x) if x == U64 :: from ( 2 ) => Self :: Eip1559 ,
78+ _ => match tx. v . as_u64 ( ) {
79+ 0 | 1 | 27 | 28 => Self :: PreEip155 ,
80+ _ => Self :: Eip155 ,
81+ } ,
82+ }
83+ }
84+
85+ /// Return the recovery id of signature for recovering the signing pk
86+ pub fn get_recovery_id ( & self , v : u64 ) -> u8 {
87+ let recovery_id = match * self {
88+ TxType :: Eip155 => ( v + 1 ) % 2 ,
89+ TxType :: PreEip155 => {
90+ assert ! ( v == 0x1b || v == 0x1c , "v: {v}" ) ;
91+ v - 27
92+ }
93+ TxType :: Eip1559 => {
94+ assert ! ( v <= 1 ) ;
95+ v
96+ }
97+ TxType :: Eip2930 => {
98+ assert ! ( v <= 1 ) ;
99+ v
100+ }
101+ } ;
102+
103+ recovery_id as u8
104+ }
105+ }
106+
107+ /// Get the RLP bytes for signing
108+ pub fn get_rlp_unsigned ( tx : & crate :: Transaction ) -> Vec < u8 > {
109+ let sig_v = tx. v ;
110+ match TxType :: get_tx_type ( tx) {
111+ TxType :: Eip155 => {
112+ let mut tx: TransactionRequest = tx. into ( ) ;
113+ tx. chain_id = Some ( tx. chain_id . unwrap_or_else ( || {
114+ let recv_v = TxType :: Eip155 . get_recovery_id ( sig_v. as_u64 ( ) ) as u64 ;
115+ ( sig_v - recv_v - 35 ) / 2
116+ } ) ) ;
117+ tx. rlp ( ) . to_vec ( )
118+ }
119+ TxType :: PreEip155 => {
120+ let tx: TransactionRequest = tx. into ( ) ;
121+ tx. rlp_unsigned ( ) . to_vec ( )
122+ }
123+ TxType :: Eip1559 => {
124+ let tx: Eip1559TransactionRequest = tx. into ( ) ;
125+ let typed_tx: TypedTransaction = tx. into ( ) ;
126+ typed_tx. rlp ( ) . to_vec ( )
127+ }
128+ TxType :: Eip2930 => {
129+ let tx: Eip2930TransactionRequest = tx. into ( ) ;
130+ let typed_tx: TypedTransaction = tx. into ( ) ;
131+ typed_tx. rlp ( ) . to_vec ( )
132+ }
133+ }
134+ }
21135
22136/// Definition of all of the data related to an account.
23137#[ serde_as]
@@ -156,6 +270,8 @@ pub struct Withdrawal {
156270/// Definition of all of the constants related to an Ethereum transaction.
157271#[ derive( Debug , Default , Clone , Serialize ) ]
158272pub struct Transaction {
273+ /// Tx type
274+ pub tx_type : TxType ,
159275 /// Sender address
160276 pub from : Address ,
161277 /// Recipient address (None for contract creation)
@@ -172,9 +288,9 @@ pub struct Transaction {
172288 /// Gas Price
173289 pub gas_price : Word ,
174290 /// Gas fee cap
175- pub gas_fee_cap : Word ,
291+ pub gas_fee_cap : Option < Word > ,
176292 /// Gas tip cap
177- pub gas_tip_cap : Word ,
293+ pub gas_tip_cap : Option < Word > ,
178294 /// The compiled code of a contract OR the first 4 bytes of the hash of the
179295 /// invoked method signature and encoded parameters. For details see
180296 /// Ethereum Contract ABI
@@ -188,6 +304,14 @@ pub struct Transaction {
188304 pub r : Word ,
189305 /// "s" value of the transaction signature
190306 pub s : Word ,
307+
308+ /// RLP bytes
309+ pub rlp_bytes : Vec < u8 > ,
310+ /// RLP unsigned bytes
311+ pub rlp_unsigned_bytes : Vec < u8 > ,
312+
313+ /// Transaction hash
314+ pub hash : H256 ,
191315}
192316
193317impl From < & Transaction > for crate :: Transaction {
@@ -199,8 +323,8 @@ impl From<&Transaction> for crate::Transaction {
199323 gas : tx. gas_limit . to_word ( ) ,
200324 value : tx. value ,
201325 gas_price : Some ( tx. gas_price ) ,
202- max_priority_fee_per_gas : Some ( tx. gas_tip_cap ) ,
203- max_fee_per_gas : Some ( tx. gas_fee_cap ) ,
326+ max_priority_fee_per_gas : tx. gas_tip_cap ,
327+ max_fee_per_gas : tx. gas_fee_cap ,
204328 input : tx. call_data . clone ( ) ,
205329 access_list : tx. access_list . clone ( ) ,
206330 v : tx. v . into ( ) ,
@@ -214,19 +338,23 @@ impl From<&Transaction> for crate::Transaction {
214338impl From < & crate :: Transaction > for Transaction {
215339 fn from ( tx : & crate :: Transaction ) -> Transaction {
216340 Transaction {
341+ tx_type : TxType :: get_tx_type ( tx) ,
217342 from : tx. from ,
218343 to : tx. to ,
219344 nonce : tx. nonce . as_u64 ( ) . into ( ) ,
220345 gas_limit : tx. gas . as_u64 ( ) . into ( ) ,
221346 value : tx. value ,
222347 gas_price : tx. gas_price . unwrap_or_default ( ) ,
223- gas_tip_cap : tx. max_priority_fee_per_gas . unwrap_or_default ( ) ,
224- gas_fee_cap : tx. max_fee_per_gas . unwrap_or_default ( ) ,
348+ gas_tip_cap : tx. max_priority_fee_per_gas ,
349+ gas_fee_cap : tx. max_fee_per_gas ,
225350 call_data : tx. input . clone ( ) ,
226351 access_list : tx. access_list . clone ( ) ,
227352 v : tx. v . as_u64 ( ) ,
228353 r : tx. r ,
229354 s : tx. s ,
355+ rlp_bytes : tx. rlp ( ) . to_vec ( ) ,
356+ rlp_unsigned_bytes : get_rlp_unsigned ( tx) ,
357+ hash : tx. hash ,
230358 }
231359 }
232360}
@@ -256,13 +384,14 @@ impl Transaction {
256384 gas_limit : U64 :: zero ( ) ,
257385 value : Word :: zero ( ) ,
258386 gas_price : Word :: zero ( ) ,
259- gas_tip_cap : Word :: zero ( ) ,
260- gas_fee_cap : Word :: zero ( ) ,
387+ gas_tip_cap : Some ( Word :: zero ( ) ) ,
388+ gas_fee_cap : Some ( Word :: zero ( ) ) ,
261389 call_data : Bytes :: new ( ) ,
262390 access_list : None ,
263391 v : 0 ,
264392 r : Word :: zero ( ) ,
265393 s : Word :: zero ( ) ,
394+ ..Default :: default ( )
266395 }
267396 }
268397 /// Return the SignData associated with this Transaction.
@@ -355,6 +484,9 @@ impl Transaction {
355484 s : self . s ,
356485 v : U64 :: from ( self . v ) ,
357486 block_number : Some ( block_number) ,
487+ transaction_type : Some ( U64 :: from ( self . tx_type as u64 ) ) ,
488+ max_priority_fee_per_gas : self . gas_tip_cap ,
489+ max_fee_per_gas : self . gas_fee_cap ,
358490 chain_id : Some ( chain_id) ,
359491 ..response:: Transaction :: default ( )
360492 }
0 commit comments