@@ -3,7 +3,7 @@ mod call_helpers;
3
3
pub use call_helpers:: { calc_call_gas, get_memory_input_and_out_ranges, resize_memory} ;
4
4
5
5
use crate :: {
6
- gas:: { self , cost_per_word, EOF_CREATE_GAS , KECCAK256WORD } ,
6
+ gas:: { self , cost_per_word, EOF_CREATE_GAS , KECCAK256WORD , MIN_CALLEE_GAS } ,
7
7
interpreter:: Interpreter ,
8
8
primitives:: {
9
9
eof:: EofHeader , keccak256, Address , BerlinSpec , Bytes , Eof , Spec , SpecId :: * , B256 , U256 ,
@@ -170,7 +170,6 @@ pub fn extcall_gas_calc<H: Host + ?Sized>(
170
170
return None ;
171
171
} ;
172
172
173
- // TODO(EOF) is_empty should only be checked on delegatecall
174
173
let call_cost = gas:: call_cost (
175
174
BerlinSpec :: SPEC_ID ,
176
175
transfers_value,
@@ -184,10 +183,17 @@ pub fn extcall_gas_calc<H: Host + ?Sized>(
184
183
let gas_reduce = max ( interpreter. gas . remaining ( ) / 64 , 5000 ) ;
185
184
let gas_limit = interpreter. gas ( ) . remaining ( ) . saturating_sub ( gas_reduce) ;
186
185
187
- if gas_limit < 2300 {
188
- interpreter. instruction_result = InstructionResult :: CallNotAllowedInsideStatic ;
189
- // TODO(EOF) error;
190
- // interpreter.instruction_result = InstructionResult::CallGasTooLow;
186
+ // The MIN_CALLEE_GAS rule is a replacement for stipend:
187
+ // it simplifies the reasoning about the gas costs and is
188
+ // applied uniformly for all introduced EXT*CALL instructions.
189
+ //
190
+ // If Gas available to callee is less than MIN_CALLEE_GAS trigger light failure (Same as Revert).
191
+ if gas_limit < MIN_CALLEE_GAS {
192
+ // Push 1 to stack to indicate that call light failed.
193
+ // It is safe to ignore stack overflow error as we already popped multiple values from stack.
194
+ let _ = interpreter. stack_mut ( ) . push ( U256 :: from ( 1 ) ) ;
195
+ interpreter. return_data_buffer . clear ( ) ;
196
+ // Return none to continue execution.
191
197
return None ;
192
198
}
193
199
@@ -226,11 +232,14 @@ pub fn extcall<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host
226
232
227
233
pop ! ( interpreter, value) ;
228
234
let has_transfer = value != U256 :: ZERO ;
235
+ if interpreter. is_static && has_transfer {
236
+ interpreter. instruction_result = InstructionResult :: CallNotAllowedInsideStatic ;
237
+ return ;
238
+ }
229
239
230
240
let Some ( gas_limit) = extcall_gas_calc ( interpreter, host, target_address, has_transfer) else {
231
241
return ;
232
242
} ;
233
- // TODO Check if static and value 0
234
243
235
244
// Call host to interact with target contract
236
245
interpreter. next_action = InterpreterAction :: Call {
@@ -266,7 +275,6 @@ pub fn extdelegatecall<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpret
266
275
let Some ( gas_limit) = extcall_gas_calc ( interpreter, host, target_address, false ) else {
267
276
return ;
268
277
} ;
269
- // TODO Check if static and value 0
270
278
271
279
// Call host to interact with target contract
272
280
interpreter. next_action = InterpreterAction :: Call {
0 commit comments