@@ -16,8 +16,13 @@ fn create_authorization(
1616 delegation_address : H160 ,
1717 nonce : U256 ,
1818 authorizing_address : H160 ,
19- ) -> ( U256 , H160 , U256 , H160 ) {
20- ( chain_id, delegation_address, nonce, authorizing_address)
19+ ) -> ( U256 , H160 , U256 , Option < H160 > ) {
20+ (
21+ chain_id,
22+ delegation_address,
23+ nonce,
24+ Some ( authorizing_address) ,
25+ )
2126}
2227
2328/// Create a test vicinity for EIP-7702 tests
@@ -4075,3 +4080,116 @@ fn test_12_2_signature_replay_protection() {
40754080 // Nonce should still be 1 (no increment from failed authorization)
40764081 assert_eq ! ( executor. state( ) . basic( authorizing) . nonce, U256 :: from( 1 ) ) ;
40774082}
4083+
4084+ #[ test]
4085+ fn test_none_authorizing_address_rejection ( ) {
4086+ // Test: Authorization with None authorizing_address should be skipped
4087+ // We compare against a valid authorization to show the difference
4088+ let caller = H160 :: from_slice ( & [ 1u8 ; 20 ] ) ;
4089+ let implementation = H160 :: from_slice ( & [ 2u8 ; 20 ] ) ;
4090+ let authorizing = H160 :: from_slice ( & [ 3u8 ; 20 ] ) ;
4091+ let target = H160 :: from_slice ( & [ 4u8 ; 20 ] ) ;
4092+
4093+ let config = Config :: pectra ( ) ;
4094+
4095+ let mut state = BTreeMap :: new ( ) ;
4096+ state. insert (
4097+ caller,
4098+ evm:: backend:: MemoryAccount {
4099+ nonce : U256 :: zero ( ) ,
4100+ balance : U256 :: from ( 10_000_000 ) ,
4101+ storage : BTreeMap :: new ( ) ,
4102+ code : Vec :: new ( ) ,
4103+ } ,
4104+ ) ;
4105+
4106+ // Create implementation account with code
4107+ state. insert (
4108+ implementation,
4109+ evm:: backend:: MemoryAccount {
4110+ nonce : U256 :: zero ( ) ,
4111+ balance : U256 :: zero ( ) ,
4112+ storage : BTreeMap :: new ( ) ,
4113+ code : vec ! [ 0x60 , 0x42 , 0x60 , 0x00 , 0x52 , 0x60 , 0x20 , 0x60 , 0x00 , 0xf3 ] ,
4114+ } ,
4115+ ) ;
4116+
4117+ // Create empty authorizing account (suitable for delegation)
4118+ state. insert (
4119+ authorizing,
4120+ evm:: backend:: MemoryAccount {
4121+ nonce : U256 :: zero ( ) ,
4122+ balance : U256 :: zero ( ) ,
4123+ storage : BTreeMap :: new ( ) ,
4124+ code : Vec :: new ( ) ,
4125+ } ,
4126+ ) ;
4127+
4128+ let vicinity = create_test_vicinity ( ) ;
4129+ let mut backend = MemoryBackend :: new ( & vicinity, state) ;
4130+
4131+ // Test 1: Transaction with None authorizing_address
4132+ {
4133+ let metadata = evm:: executor:: stack:: StackSubstateMetadata :: new ( 1000000 , & config) ;
4134+ let state = evm:: executor:: stack:: MemoryStackState :: new ( metadata, & mut backend) ;
4135+ let precompiles = BTreeMap :: new ( ) ;
4136+ let mut executor = StackExecutor :: new_with_precompiles ( state, & config, & precompiles) ;
4137+
4138+ let authorization_with_none = (
4139+ U256 :: from ( 1 ) , // chain_id matches vicinity
4140+ implementation, // delegation_address
4141+ U256 :: zero ( ) , // nonce
4142+ None , // authorizing_address is None
4143+ ) ;
4144+
4145+ let ( exit_reason, _) = executor. transact_call (
4146+ caller,
4147+ target,
4148+ U256 :: zero ( ) ,
4149+ Vec :: new ( ) ,
4150+ 100_000 ,
4151+ Vec :: new ( ) ,
4152+ vec ! [ authorization_with_none] ,
4153+ ) ;
4154+
4155+ assert_eq ! ( exit_reason, ExitReason :: Succeed ( evm:: ExitSucceed :: Stopped ) ) ;
4156+
4157+ // Authorizing account should be unchanged (no delegation applied)
4158+ let authorizing_basic = executor. state ( ) . basic ( authorizing) ;
4159+ assert_eq ! ( authorizing_basic. nonce, U256 :: zero( ) ) ;
4160+ assert ! ( executor. code( authorizing) . is_empty( ) ) ;
4161+ }
4162+
4163+ // Test 2: Same transaction but with valid authorizing_address for comparison
4164+ {
4165+ let metadata = evm:: executor:: stack:: StackSubstateMetadata :: new ( 1000000 , & config) ;
4166+ let state = evm:: executor:: stack:: MemoryStackState :: new ( metadata, & mut backend) ;
4167+ let precompiles = BTreeMap :: new ( ) ;
4168+ let mut executor = StackExecutor :: new_with_precompiles ( state, & config, & precompiles) ;
4169+
4170+ let authorization_with_some = (
4171+ U256 :: from ( 1 ) , // chain_id matches vicinity
4172+ implementation, // delegation_address
4173+ U256 :: zero ( ) , // nonce
4174+ Some ( authorizing) , // authorizing_address is Some
4175+ ) ;
4176+
4177+ let ( exit_reason, _) = executor. transact_call (
4178+ caller,
4179+ target,
4180+ U256 :: zero ( ) ,
4181+ Vec :: new ( ) ,
4182+ 100_000 ,
4183+ Vec :: new ( ) ,
4184+ vec ! [ authorization_with_some] ,
4185+ ) ;
4186+
4187+ assert_eq ! ( exit_reason, ExitReason :: Succeed ( evm:: ExitSucceed :: Stopped ) ) ;
4188+
4189+ // Authorizing account should now have delegation designator
4190+ let authorizing_basic = executor. state ( ) . basic ( authorizing) ;
4191+ assert_eq ! ( authorizing_basic. nonce, U256 :: from( 1 ) ) ; // Nonce incremented
4192+ let expected_delegation = evm_core:: create_delegation_designator ( implementation) ;
4193+ assert_eq ! ( executor. code( authorizing) , expected_delegation) ;
4194+ }
4195+ }
0 commit comments