@@ -5,10 +5,13 @@ use crate::{
5
5
keccak256,
6
6
sign_types:: { biguint_to_32bytes_le, ct_option_ok_or, recover_pk, SignData , SECP256K1_Q } ,
7
7
AccessList , Address , Block , Bytecode , Bytes , Error , GethExecTrace , Hash , ToBigEndian ,
8
- ToLittleEndian , ToWord , Word , U64 ,
8
+ ToLittleEndian , ToWord , Word , H256 , U64 ,
9
9
} ;
10
10
use ethers_core:: {
11
- types:: { transaction:: response, NameOrAddress , TransactionRequest } ,
11
+ types:: {
12
+ transaction:: { eip2718:: TypedTransaction , response} ,
13
+ Eip1559TransactionRequest , Eip2930TransactionRequest , NameOrAddress , TransactionRequest ,
14
+ } ,
12
15
utils:: get_contract_address,
13
16
} ;
14
17
use ethers_signers:: { LocalWallet , Signer } ;
@@ -46,6 +49,90 @@ impl From<TxType> for u64 {
46
49
}
47
50
}
48
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
+ }
135
+
49
136
/// Definition of all of the data related to an account.
50
137
#[ serde_as]
51
138
#[ derive( PartialEq , Eq , Debug , Default , Clone , Serialize ) ]
@@ -183,6 +270,8 @@ pub struct Withdrawal {
183
270
/// Definition of all of the constants related to an Ethereum transaction.
184
271
#[ derive( Debug , Default , Clone , Serialize ) ]
185
272
pub struct Transaction {
273
+ /// Tx type
274
+ pub tx_type : TxType ,
186
275
/// Sender address
187
276
pub from : Address ,
188
277
/// Recipient address (None for contract creation)
@@ -199,9 +288,9 @@ pub struct Transaction {
199
288
/// Gas Price
200
289
pub gas_price : Word ,
201
290
/// Gas fee cap
202
- pub gas_fee_cap : Word ,
291
+ pub gas_fee_cap : Option < Word > ,
203
292
/// Gas tip cap
204
- pub gas_tip_cap : Word ,
293
+ pub gas_tip_cap : Option < Word > ,
205
294
/// The compiled code of a contract OR the first 4 bytes of the hash of the
206
295
/// invoked method signature and encoded parameters. For details see
207
296
/// Ethereum Contract ABI
@@ -215,6 +304,14 @@ pub struct Transaction {
215
304
pub r : Word ,
216
305
/// "s" value of the transaction signature
217
306
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 ,
218
315
}
219
316
220
317
impl From < & Transaction > for crate :: Transaction {
@@ -226,8 +323,8 @@ impl From<&Transaction> for crate::Transaction {
226
323
gas : tx. gas_limit . to_word ( ) ,
227
324
value : tx. value ,
228
325
gas_price : Some ( tx. gas_price ) ,
229
- max_priority_fee_per_gas : Some ( tx. gas_tip_cap ) ,
230
- 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 ,
231
328
input : tx. call_data . clone ( ) ,
232
329
access_list : tx. access_list . clone ( ) ,
233
330
v : tx. v . into ( ) ,
@@ -241,19 +338,23 @@ impl From<&Transaction> for crate::Transaction {
241
338
impl From < & crate :: Transaction > for Transaction {
242
339
fn from ( tx : & crate :: Transaction ) -> Transaction {
243
340
Transaction {
341
+ tx_type : TxType :: get_tx_type ( tx) ,
244
342
from : tx. from ,
245
343
to : tx. to ,
246
344
nonce : tx. nonce . as_u64 ( ) . into ( ) ,
247
345
gas_limit : tx. gas . as_u64 ( ) . into ( ) ,
248
346
value : tx. value ,
249
347
gas_price : tx. gas_price . unwrap_or_default ( ) ,
250
- gas_tip_cap : tx. max_priority_fee_per_gas . unwrap_or_default ( ) ,
251
- 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 ,
252
350
call_data : tx. input . clone ( ) ,
253
351
access_list : tx. access_list . clone ( ) ,
254
352
v : tx. v . as_u64 ( ) ,
255
353
r : tx. r ,
256
354
s : tx. s ,
355
+ rlp_bytes : tx. rlp ( ) . to_vec ( ) ,
356
+ rlp_unsigned_bytes : get_rlp_unsigned ( tx) ,
357
+ hash : tx. hash ,
257
358
}
258
359
}
259
360
}
@@ -283,13 +384,14 @@ impl Transaction {
283
384
gas_limit : U64 :: zero ( ) ,
284
385
value : Word :: zero ( ) ,
285
386
gas_price : Word :: zero ( ) ,
286
- gas_tip_cap : Word :: zero ( ) ,
287
- gas_fee_cap : Word :: zero ( ) ,
387
+ gas_tip_cap : Some ( Word :: zero ( ) ) ,
388
+ gas_fee_cap : Some ( Word :: zero ( ) ) ,
288
389
call_data : Bytes :: new ( ) ,
289
390
access_list : None ,
290
391
v : 0 ,
291
392
r : Word :: zero ( ) ,
292
393
s : Word :: zero ( ) ,
394
+ ..Default :: default ( )
293
395
}
294
396
}
295
397
/// Return the SignData associated with this Transaction.
@@ -382,6 +484,9 @@ impl Transaction {
382
484
s : self . s ,
383
485
v : U64 :: from ( self . v ) ,
384
486
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 ,
385
490
chain_id : Some ( chain_id) ,
386
491
..response:: Transaction :: default ( )
387
492
}
0 commit comments