Skip to content

Commit 7f8e31a

Browse files
authored
fix(EOF): MIN_CALLEE_GAS light failure, static-mode check (#1599)
* fix(EOF): MIN_CALLEE_GAS light failure, static-mode check * clear buffer * readd min caller gas
1 parent 929d4b2 commit 7f8e31a

File tree

4 files changed

+25
-8
lines changed

4 files changed

+25
-8
lines changed

crates/interpreter/src/gas/constants.rs

+1
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,4 @@ pub const PER_CONTRACT_CODE_BASE_COST: u64 = 2400;
5454
pub const INITCODE_WORD_COST: u64 = 2;
5555

5656
pub const CALL_STIPEND: u64 = 2300;
57+
pub const MIN_CALLEE_GAS: u64 = CALL_STIPEND;

crates/interpreter/src/instruction_result.rs

+2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ pub enum InstructionResult {
3333
PrecompileOOG,
3434
InvalidOperandOOG,
3535
OpcodeNotFound,
36+
/// Transferring value with CALL/CALLCODE is not possible in static mode.
3637
CallNotAllowedInsideStatic,
38+
/// State change attempted in static mode.
3739
StateChangeDuringStaticCall,
3840
InvalidFEOpcode,
3941
InvalidJump,

crates/interpreter/src/instructions/contract.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mod call_helpers;
33
pub use call_helpers::{calc_call_gas, get_memory_input_and_out_ranges, resize_memory};
44

55
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},
77
interpreter::Interpreter,
88
primitives::{
99
eof::EofHeader, keccak256, Address, BerlinSpec, Bytes, Eof, Spec, SpecId::*, B256, U256,
@@ -170,7 +170,6 @@ pub fn extcall_gas_calc<H: Host + ?Sized>(
170170
return None;
171171
};
172172

173-
// TODO(EOF) is_empty should only be checked on delegatecall
174173
let call_cost = gas::call_cost(
175174
BerlinSpec::SPEC_ID,
176175
transfers_value,
@@ -184,10 +183,17 @@ pub fn extcall_gas_calc<H: Host + ?Sized>(
184183
let gas_reduce = max(interpreter.gas.remaining() / 64, 5000);
185184
let gas_limit = interpreter.gas().remaining().saturating_sub(gas_reduce);
186185

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.
191197
return None;
192198
}
193199

@@ -226,11 +232,14 @@ pub fn extcall<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host
226232

227233
pop!(interpreter, value);
228234
let has_transfer = value != U256::ZERO;
235+
if interpreter.is_static && has_transfer {
236+
interpreter.instruction_result = InstructionResult::CallNotAllowedInsideStatic;
237+
return;
238+
}
229239

230240
let Some(gas_limit) = extcall_gas_calc(interpreter, host, target_address, has_transfer) else {
231241
return;
232242
};
233-
// TODO Check if static and value 0
234243

235244
// Call host to interact with target contract
236245
interpreter.next_action = InterpreterAction::Call {
@@ -266,7 +275,6 @@ pub fn extdelegatecall<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpret
266275
let Some(gas_limit) = extcall_gas_calc(interpreter, host, target_address, false) else {
267276
return;
268277
};
269-
// TODO Check if static and value 0
270278

271279
// Call host to interact with target contract
272280
interpreter.next_action = InterpreterAction::Call {

crates/interpreter/src/interpreter.rs

+6
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,12 @@ impl Interpreter {
329329
&self.stack
330330
}
331331

332+
/// Returns a mutable reference to the interpreter's stack.
333+
#[inline]
334+
pub fn stack_mut(&mut self) -> &mut Stack {
335+
&mut self.stack
336+
}
337+
332338
/// Returns the current program counter.
333339
#[inline]
334340
pub fn program_counter(&self) -> usize {

0 commit comments

Comments
 (0)