revm_interpreter/instructions/contract/
call_helpers.rs1use crate::{
2 gas,
3 interpreter::Interpreter,
4 interpreter_types::{InterpreterTypes, LoopControl, MemoryTr, RuntimeFlag, StackTr},
5};
6use context_interface::{context::StateLoad, journaled_state::AccountLoad};
7use core::{cmp::min, ops::Range};
8use primitives::{hardfork::SpecId::*, Bytes, U256};
9
10#[inline]
11pub fn get_memory_input_and_out_ranges(
12 interpreter: &mut Interpreter<impl InterpreterTypes>,
13) -> Option<(Bytes, Range<usize>)> {
14 popn!([in_offset, in_len, out_offset, out_len], interpreter, None);
15
16 let in_range = resize_memory(interpreter, in_offset, in_len)?;
17
18 let mut input = Bytes::new();
19 if !in_range.is_empty() {
20 input = Bytes::copy_from_slice(interpreter.memory.slice(in_range).as_ref());
21 }
22
23 let ret_range = resize_memory(interpreter, out_offset, out_len)?;
24 Some((input, ret_range))
25}
26
27#[inline]
30pub fn resize_memory(
31 interpreter: &mut Interpreter<impl InterpreterTypes>,
32 offset: U256,
33 len: U256,
34) -> Option<Range<usize>> {
35 let len = as_usize_or_fail_ret!(interpreter, len, None);
36 let offset = if len != 0 {
37 let offset = as_usize_or_fail_ret!(interpreter, offset, None);
38 resize_memory!(interpreter, offset, len, None);
39 offset
40 } else {
41 usize::MAX };
43 Some(offset..offset + len)
44}
45
46#[inline]
47pub fn calc_call_gas(
48 interpreter: &mut Interpreter<impl InterpreterTypes>,
49 account_load: StateLoad<AccountLoad>,
50 has_transfer: bool,
51 local_gas_limit: u64,
52) -> Option<u64> {
53 let call_cost = gas::call_cost(
54 interpreter.runtime_flag.spec_id(),
55 has_transfer,
56 account_load,
57 );
58 gas!(interpreter, call_cost, None);
59
60 let gas_limit = if interpreter.runtime_flag.spec_id().is_enabled_in(TANGERINE) {
62 min(
64 interpreter.control.gas().remaining_63_of_64_parts(),
65 local_gas_limit,
66 )
67 } else {
68 local_gas_limit
69 };
70
71 Some(gas_limit)
72}