99//! unique Layer 2 features that cannot be expressed in standard
1010//! Ethereum transaction formats. This includes:
1111//!
12- //! - **`EIP_712_TX_TYPE` (0x71)**: User-submitted transactions with EIP-712 signing
1312//! - **`L1_L2_TX_TYPE` (0x7f)**: Transactions initiated from L1 (deposits, forced transactions)
1413//! - **`UPGRADE_TX_TYPE` (0x7e)**: System upgrade transactions (protocol changes)
1514
@@ -96,8 +95,6 @@ pub struct AbiEncodedTransaction<A: Allocator> {
9695
9796#[ allow( dead_code) ]
9897impl < A : Allocator > AbiEncodedTransaction < A > {
99- /// The type id of EIP712 transactions.
100- pub const EIP_712_TX_TYPE : u8 = 0x71 ;
10198 /// The type id of protocol upgrade transactions.
10299 pub const UPGRADE_TX_TYPE : u8 = 0x7e ;
103100 /// The type id of L1 -> L2 transactions.
@@ -218,7 +215,7 @@ impl<A: Allocator> AbiEncodedTransaction<A> {
218215 let tx_type = self . tx_type . read ( ) ;
219216
220217 match tx_type {
221- Self :: UPGRADE_TX_TYPE | Self :: L1_L2_TX_TYPE | Self :: EIP_712_TX_TYPE => { }
218+ Self :: UPGRADE_TX_TYPE | Self :: L1_L2_TX_TYPE => { }
222219 _ => return Err ( ( ) ) ,
223220 }
224221
@@ -232,7 +229,7 @@ impl<A: Allocator> AbiEncodedTransaction<A> {
232229 }
233230 }
234231
235- // paymasters are not supported, even for EIP712 txs
232+ // paymasters are not supported
236233 if self . paymaster . read ( ) != B160 :: ZERO {
237234 return Err ( ( ) ) ;
238235 }
@@ -248,17 +245,11 @@ impl<A: Allocator> AbiEncodedTransaction<A> {
248245 }
249246 }
250247 }
251- // reserved[1] = refund recipient for l1 to l2 and upgrade txs,
252- // for EIP712 txs should be zero
248+ // reserved[1] = refund recipient for l1 to l2 and upgrade txs
253249 match tx_type {
254250 Self :: L1_L2_TX_TYPE | Self :: UPGRADE_TX_TYPE => {
255251 // TODO: validate address?
256252 }
257- Self :: EIP_712_TX_TYPE => {
258- if !self . reserved [ 1 ] . read ( ) . is_zero ( ) {
259- return Err ( ( ) ) ;
260- }
261- }
262253 _ => unreachable ! ( ) ,
263254 }
264255
@@ -280,7 +271,7 @@ impl<A: Allocator> AbiEncodedTransaction<A> {
280271 }
281272 }
282273
283- // paymasters are not supported, even for EIP712 txs
274+ // paymasters are not supported
284275 if !self . paymaster_input . range . is_empty ( ) {
285276 return Err ( ( ) ) ;
286277 }
@@ -324,190 +315,19 @@ impl<A: Allocator> AbiEncodedTransaction<A> {
324315 ( parity, r, s)
325316 }
326317
327- ///
328- /// Calculate the signed transaction hash.
329- /// i.e. the one should be signed for the EOA accounts.
330- ///
331- pub fn calculate_signed_hash < R : Resources > (
332- & self ,
333- chain_id : u64 ,
334- resources : & mut R ,
335- ) -> Result < [ u8 ; 32 ] , TxError > {
336- let tx_type = self . tx_type . read ( ) ;
337- match tx_type {
338- Self :: EIP_712_TX_TYPE => self . eip712_tx_calculate_signed_hash ( chain_id, resources) ,
339- _ => Err (
340- internal_error ! ( "Invalid type for signed hash, most likely l1 or upgrade" ) . into ( ) ,
341- ) ,
342- }
343- }
344-
345318 ///
346319 /// Calculate the transaction hash.
347320 /// i.e. the transaction hash to be used in the explorer.
348321 ///
349- pub fn calculate_hash < R : Resources > (
350- & self ,
351- chain_id : u64 ,
352- resources : & mut R ,
353- ) -> Result < [ u8 ; 32 ] , TxError > {
322+ pub fn calculate_hash < R : Resources > ( & self , resources : & mut R ) -> Result < [ u8 ; 32 ] , TxError > {
354323 let tx_type = self . tx_type . read ( ) ;
355324 match tx_type {
356- Self :: EIP_712_TX_TYPE => self . eip712_tx_calculate_hash ( chain_id, resources) ,
357325 Self :: L1_L2_TX_TYPE => self . l1_tx_calculate_hash ( resources) ,
358326 Self :: UPGRADE_TX_TYPE => self . l1_tx_calculate_hash ( resources) ,
359327 _ => Err ( internal_error ! ( "Type should be validated" ) . into ( ) ) ,
360328 }
361329 }
362330
363- // Keccak256 of:
364- // EIP712Domain(string name,string version,uint256 chainId)
365- // = c2f8787176b8ac6bf7215b4adcc1e069bf4ab82d9ab1df05a57a91d425935b6e
366- const DOMAIN_TYPE_HASH : [ u8 ; 32 ] = [
367- 0xc2 , 0xf8 , 0x78 , 0x71 , 0x76 , 0xb8 , 0xac , 0x6b , 0xf7 , 0x21 , 0x5b , 0x4a , 0xdc , 0xc1 , 0xe0 ,
368- 0x69 , 0xbf , 0x4a , 0xb8 , 0x2d , 0x9a , 0xb1 , 0xdf , 0x05 , 0xa5 , 0x7a , 0x91 , 0xd4 , 0x25 , 0x93 ,
369- 0x5b , 0x6e ,
370- ] ;
371-
372- // Keccak256 of:
373- // zkSync
374- // = 19b453ce45aaaaf3a300f5a9ec95869b4f28ab10430b572ee218c3a6a5e07d6f
375- const DOMAIN_NAME_HASH : [ u8 ; 32 ] = [
376- 0x19 , 0xb4 , 0x53 , 0xce , 0x45 , 0xaa , 0xaa , 0xf3 , 0xa3 , 0x00 , 0xf5 , 0xa9 , 0xec , 0x95 , 0x86 ,
377- 0x9b , 0x4f , 0x28 , 0xab , 0x10 , 0x43 , 0x0b , 0x57 , 0x2e , 0xe2 , 0x18 , 0xc3 , 0xa6 , 0xa5 , 0xe0 ,
378- 0x7d , 0x6f ,
379- ] ;
380- // Keccak256 of:
381- // 2
382- // = ad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5
383- const DOMAIN_VERSION_HASH : [ u8 ; 32 ] = [
384- 0xad , 0x7c , 0x5b , 0xef , 0x02 , 0x78 , 0x16 , 0xa8 , 0x00 , 0xda , 0x17 , 0x36 , 0x44 , 0x4f , 0xb5 ,
385- 0x8a , 0x80 , 0x7e , 0xf4 , 0xc9 , 0x60 , 0x3b , 0x78 , 0x48 , 0x67 , 0x3f , 0x7e , 0x3a , 0x68 , 0xeb ,
386- 0x14 , 0xa5 ,
387- ] ;
388-
389- fn domain_hash_struct < R : Resources > (
390- chain_id : u64 ,
391- resources : & mut R ,
392- ) -> Result < [ u8 ; 32 ] , TxError > {
393- let len = Self :: DOMAIN_TYPE_HASH . len ( )
394- + Self :: DOMAIN_NAME_HASH . len ( )
395- + Self :: DOMAIN_VERSION_HASH . len ( )
396- + U256 :: BYTES ;
397- charge_keccak ( len, resources) ?;
398-
399- let mut hasher = Keccak256 :: new ( ) ;
400- hasher. update ( Self :: DOMAIN_TYPE_HASH ) ;
401- hasher. update ( Self :: DOMAIN_NAME_HASH ) ;
402- hasher. update ( Self :: DOMAIN_VERSION_HASH ) ;
403- hasher. update ( U256 :: from ( chain_id) . to_be_bytes :: < 32 > ( ) ) ;
404- Ok ( * hasher. finalize ( ) . split_first_chunk :: < 32 > ( ) . unwrap ( ) . 0 )
405- }
406-
407- // Keccak256 of:
408- // Transaction(uint256 txType,uint256 from,uint256 to,uint256 gasLimit,uint256 gasPerPubdataByteLimit,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,uint256 paymaster,uint256 nonce,uint256 value,bytes data,bytes32[] factoryDeps,bytes paymasterInput)
409- // = 848e1bfa1ac4e3576b728bda6721b215c70a7799a5b4866282a71bab954baac8
410- const TYPE_HASH : [ u8 ; 32 ] = [
411- 0x84 , 0x8e , 0x1b , 0xfa , 0x1a , 0xc4 , 0xe3 , 0x57 , 0x6b , 0x72 , 0x8b , 0xda , 0x67 , 0x21 , 0xb2 ,
412- 0x15 , 0xc7 , 0x0a , 0x77 , 0x99 , 0xa5 , 0xb4 , 0x86 , 0x62 , 0x82 , 0xa7 , 0x1b , 0xab , 0x95 , 0x4b ,
413- 0xaa , 0xc8 ,
414- ] ;
415-
416- fn hash_struct < R : Resources > ( & self , resources : & mut R ) -> Result < [ u8 ; 32 ] , TxError > {
417- let len = U256 :: BYTES * 14 ;
418- charge_keccak ( len, resources) ?;
419-
420- let mut hasher = Keccak256 :: new ( ) ;
421- hasher. update ( Self :: TYPE_HASH ) ;
422- hasher. update ( self . tx_type . encoding ( & self . underlying_buffer . as_slice ( ) ) ) ;
423- hasher. update ( self . from . encoding ( & self . underlying_buffer . as_slice ( ) ) ) ;
424- hasher. update ( self . to . encoding ( & self . underlying_buffer . as_slice ( ) ) ) ;
425- hasher. update ( self . gas_limit . encoding ( & self . underlying_buffer . as_slice ( ) ) ) ;
426- hasher. update (
427- self . gas_per_pubdata_limit
428- . encoding ( & self . underlying_buffer . as_slice ( ) ) ,
429- ) ;
430- hasher. update (
431- self . max_fee_per_gas
432- . encoding ( & self . underlying_buffer . as_slice ( ) ) ,
433- ) ;
434- hasher. update (
435- self . max_priority_fee_per_gas
436- . encoding ( & self . underlying_buffer . as_slice ( ) ) ,
437- ) ;
438- hasher. update ( self . paymaster . encoding ( & self . underlying_buffer . as_slice ( ) ) ) ;
439- hasher. update ( self . nonce . encoding ( & self . underlying_buffer . as_slice ( ) ) ) ;
440- hasher. update ( self . value . encoding ( & self . underlying_buffer . as_slice ( ) ) ) ;
441-
442- charge_keccak ( self . data . range . len ( ) , resources) ?;
443- let data_hash = <Keccak256 as MiniDigest >:: digest (
444- self . data . encoding ( & self . underlying_buffer . as_slice ( ) ) ,
445- ) ;
446- hasher. update ( & data_hash) ;
447-
448- charge_keccak ( self . factory_deps . range . len ( ) , resources) ?;
449- let factory_deps_hash = <Keccak256 as MiniDigest >:: digest (
450- self . factory_deps
451- . encoding ( & self . underlying_buffer . as_slice ( ) ) ,
452- ) ;
453- hasher. update ( & factory_deps_hash) ;
454-
455- charge_keccak ( self . paymaster_input . range . len ( ) , resources) ?;
456- let paymaster_input_hash = <Keccak256 as MiniDigest >:: digest (
457- self . paymaster_input
458- . encoding ( & self . underlying_buffer . as_slice ( ) ) ,
459- ) ;
460- hasher. update ( & paymaster_input_hash) ;
461-
462- Ok ( hasher. finalize ( ) )
463- }
464-
465- ///
466- /// Calculate signed tx hash(the one that should be signed by the sender):
467- /// Keccak256(0x19 0x01 ‖ domainSeparator ‖ hashStruct(tx))
468- ///
469- fn eip712_tx_calculate_signed_hash < R : Resources > (
470- & self ,
471- chain_id : u64 ,
472- resources : & mut R ,
473- ) -> Result < [ u8 ; 32 ] , TxError > {
474- let domain_separator = Self :: domain_hash_struct ( chain_id, resources) ?;
475- let hs = self . hash_struct ( resources) ?;
476- charge_keccak ( 2 + 2 * U256 :: BYTES , resources) ?;
477- let mut hasher = Keccak256 :: new ( ) ;
478- hasher. update ( [ 0x19 , 0x01 ] ) ;
479- hasher. update ( domain_separator) ;
480- hasher. update ( hs) ;
481-
482- Ok ( hasher. finalize ( ) )
483- }
484-
485- ///
486- /// Calculate tx hash with signature(to be used in the explorer):
487- /// Keccak256(signed_hash || Keccak256(signature))
488- ///
489- fn eip712_tx_calculate_hash < R : Resources > (
490- & self ,
491- chain_id : u64 ,
492- resources : & mut R ,
493- ) -> Result < [ u8 ; 32 ] , TxError > {
494- let signed_hash = self . eip712_tx_calculate_signed_hash ( chain_id, resources) ?;
495- // First charge for hashing the signature
496- charge_keccak ( self . signature . range . len ( ) , resources) ?;
497- // Next charge for combining the two hashes
498- charge_keccak ( U256 :: BYTES * 2 , resources) ?;
499-
500- let signature_hash = <Keccak256 as MiniDigest >:: digest (
501- self . signature . encoding ( & self . underlying_buffer . as_slice ( ) ) ,
502- ) ;
503-
504- let mut hasher = Keccak256 :: new ( ) ;
505- hasher. update ( signed_hash) ;
506- hasher. update ( signature_hash) ;
507-
508- Ok ( hasher. finalize ( ) )
509- }
510-
511331 ///
512332 /// Calculate l1 tx hash:
513333 /// Keccak256(abi.encode(transaction))
@@ -521,23 +341,14 @@ impl<A: Allocator> AbiEncodedTransaction<A> {
521341 Ok ( hasher. finalize ( ) )
522342 }
523343
524- /// Checks if the transaction is of type EIP-712
525- pub fn is_eip_712 ( & self ) -> bool {
526- self . tx_type . read ( ) == Self :: EIP_712_TX_TYPE
527- }
528-
529344 /// Returns the balance required to process the transaction.
530345 /// If the calculation overflows, returns `None`.
531346 pub fn required_balance ( & self ) -> Option < U256 > {
532- if self . is_eip_712 ( ) && self . paymaster . read ( ) != B160 :: ZERO {
533- Some ( self . value . read ( ) )
534- } else {
535- let fee_amount = self
536- . max_fee_per_gas
537- . read ( )
538- . checked_mul ( U256 :: from ( self . gas_limit . read ( ) ) ) ?;
539- self . value . read ( ) . checked_add ( U256 :: from ( fee_amount) )
540- }
347+ let fee_amount = self
348+ . max_fee_per_gas
349+ . read ( )
350+ . checked_mul ( U256 :: from ( self . gas_limit . read ( ) ) ) ?;
351+ self . value . read ( ) . checked_add ( U256 :: from ( fee_amount) )
541352 }
542353
543354 #[ allow( clippy:: len_without_is_empty) ]
@@ -560,10 +371,6 @@ impl<T: 'static + Clone + Copy + core::fmt::Debug> ParsedValue<T> {
560371 pub fn read_ref ( & self ) -> & T {
561372 & self . value
562373 }
563-
564- fn encoding < ' a > ( & self , source : & ' a [ u8 ] ) -> & ' a [ u8 ] {
565- unsafe { source. get_unchecked ( self . range . clone ( ) ) }
566- }
567374}
568375
569376struct Parser < ' a > {
0 commit comments