@@ -6,7 +6,7 @@ use alloy_primitives::{U256, bytes};
66use alloy_provider:: { PendingTransactionConfig , Provider } ;
77use alloy_rpc_types:: { Authorization , TransactionRequest } ;
88use alloy_serde:: WithOtherFields ;
9- use alloy_signer:: SignerSync ;
9+ use alloy_signer:: { Signature , SignerSync } ;
1010use anvil:: { NodeConfig , spawn} ;
1111
1212#[ tokio:: test( flavor = "multi_thread" ) ]
@@ -153,3 +153,73 @@ async fn can_send_eip7702_request() {
153153 assert_eq ! ( log. topics( ) . len( ) , 0 ) ;
154154 assert_eq ! ( log. data( ) . data, log_data) ;
155155}
156+
157+ #[ tokio:: test( flavor = "multi_thread" ) ]
158+ async fn eip7702_authorization_bypass ( ) {
159+ let node_config = NodeConfig :: test ( ) . with_hardfork ( Some ( EthereumHardfork :: Prague . into ( ) ) ) ;
160+ let ( api, handle) = spawn ( node_config) . await ;
161+ let provider = http_provider ( & handle. http_endpoint ( ) ) ;
162+
163+ let wallets = handle. dev_wallets ( ) . collect :: < Vec < _ > > ( ) ;
164+
165+ // deploy simple contract forwarding calldata to LOG0
166+ // PUSH7(CALLDATASIZE PUSH0 PUSH0 CALLDATACOPY CALLDATASIZE PUSH0 LOG0) PUSH0 MSTORE PUSH1(7)
167+ // PUSH1(25) RETURN
168+ let logger_bytecode = bytes ! ( "66365f5f37365fa05f5260076019f3" ) ;
169+
170+ let eip1559_est = provider. estimate_eip1559_fees ( ) . await . unwrap ( ) ;
171+
172+ let from = wallets[ 0 ] . address ( ) ;
173+ let tx = TransactionRequest :: default ( )
174+ . with_from ( from)
175+ . into_create ( )
176+ . with_nonce ( 0 )
177+ . with_max_fee_per_gas ( eip1559_est. max_fee_per_gas )
178+ . with_max_priority_fee_per_gas ( eip1559_est. max_priority_fee_per_gas )
179+ . with_input ( logger_bytecode) ;
180+
181+ let receipt = provider
182+ . send_transaction ( WithOtherFields :: new ( tx) )
183+ . await
184+ . unwrap ( )
185+ . get_receipt ( )
186+ . await
187+ . unwrap ( ) ;
188+
189+ assert ! ( receipt. status( ) ) ;
190+
191+ let contract = receipt. contract_address . unwrap ( ) ;
192+ let authorization = Authorization {
193+ chain_id : U256 :: from ( 31337u64 ) ,
194+ address : contract,
195+ nonce : provider. get_transaction_count ( from) . await . unwrap ( ) ,
196+ } ;
197+ let fake_auth_sig = Signature :: new ( U256 :: ZERO , U256 :: ZERO , true ) ;
198+ api. anvil_impersonate_signature ( fake_auth_sig. as_bytes ( ) . into ( ) , from) . await . unwrap ( ) ;
199+ let authorization = authorization. into_signed ( fake_auth_sig) ;
200+
201+ let log_data = bytes ! ( "11112222" ) ;
202+ let mut tx = TxEip7702 {
203+ max_fee_per_gas : eip1559_est. max_fee_per_gas ,
204+ max_priority_fee_per_gas : eip1559_est. max_priority_fee_per_gas ,
205+ gas_limit : 100000 ,
206+ chain_id : 31337 ,
207+ to : from,
208+ input : bytes ! ( "11112222" ) ,
209+ authorization_list : vec ! [ authorization] ,
210+ ..Default :: default ( )
211+ } ;
212+ let signature = wallets[ 1 ] . sign_transaction_sync ( & mut tx) . unwrap ( ) ;
213+
214+ let tx = tx. into_signed ( signature) ;
215+ let mut encoded = Vec :: new ( ) ;
216+ tx. eip2718_encode ( & mut encoded) ;
217+
218+ let receipt =
219+ provider. send_raw_transaction ( & encoded) . await . unwrap ( ) . get_receipt ( ) . await . unwrap ( ) ;
220+ let log = & receipt. inner . inner . logs ( ) [ 0 ] ;
221+ // assert that log was from EOA which signed authorization
222+ assert_eq ! ( log. address( ) , from) ;
223+ assert_eq ! ( log. topics( ) . len( ) , 0 ) ;
224+ assert_eq ! ( log. data( ) . data, log_data) ;
225+ }
0 commit comments