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