@@ -90,6 +90,74 @@ def test_authorization_state_gas_scaling(
9090 state_test (env = env , pre = pre , post = {}, tx = tx )
9191
9292
93+ @pytest .mark .exception_test
94+ @pytest .mark .parametrize (
95+ "num_auths" ,
96+ [
97+ pytest .param (1 , id = "single_auth" ),
98+ pytest .param (2 , id = "two_auths" ),
99+ pytest .param (3 , id = "three_auths" ),
100+ ],
101+ )
102+ @pytest .mark .parametrize (
103+ "extra_gas" ,
104+ [
105+ pytest .param (0 , id = "at_regular_intrinsic" ),
106+ pytest .param (1 , id = "one_above_regular_intrinsic" ),
107+ pytest .param (- 1 , id = "one_below_total_intrinsic" ),
108+ ],
109+ )
110+ @pytest .mark .valid_from ("EIP8037" )
111+ def test_set_code_tx_below_total_intrinsic (
112+ state_test : StateTestFiller ,
113+ pre : Alloc ,
114+ fork : Fork ,
115+ num_auths : int ,
116+ extra_gas : int ,
117+ ) -> None :
118+ """
119+ Reject set_code tx when gas_limit covers regular but not state intrinsic.
120+
121+ EIP-8037 charges each authorization a state component
122+ `(STATE_BYTES_PER_NEW_ACCOUNT + STATE_BYTES_PER_AUTH_BASE) *
123+ COST_PER_STATE_BYTE`; total intrinsic = `regular + N * state` for
124+ N authorizations. Sweep N = 1, 2, 3 and pin gas_limit at the
125+ lower end of the rejected interval to catch implementations that
126+ omit the state component from the pre-validate check.
127+ """
128+ intrinsic_state = fork .transaction_intrinsic_state_gas (
129+ authorization_count = num_auths ,
130+ )
131+ total_intrinsic = fork .transaction_intrinsic_cost_calculator ()(
132+ authorization_list_or_count = num_auths ,
133+ )
134+ intrinsic_regular = total_intrinsic - intrinsic_state
135+ gas_limit = (
136+ intrinsic_regular if extra_gas >= 0 else total_intrinsic
137+ ) + extra_gas
138+ assert gas_limit < total_intrinsic
139+
140+ contract = pre .deploy_contract (code = Op .STOP )
141+ authorization_list = [
142+ AuthorizationTuple (
143+ address = contract ,
144+ nonce = 1 ,
145+ signer = pre .fund_eoa (),
146+ )
147+ for _ in range (num_auths )
148+ ]
149+
150+ tx = Transaction (
151+ to = contract ,
152+ gas_limit = gas_limit ,
153+ authorization_list = authorization_list ,
154+ sender = pre .fund_eoa (),
155+ error = TransactionException .INTRINSIC_GAS_TOO_LOW ,
156+ )
157+
158+ state_test (pre = pre , post = {}, tx = tx )
159+
160+
93161@pytest .mark .valid_from ("EIP8037" )
94162def test_existing_account_refund (
95163 state_test : StateTestFiller ,
0 commit comments