revm_interpreter/instructions/contract/
call_helpers.rsuse crate::{
gas,
interpreter::Interpreter,
interpreter_types::{InterpreterTypes, LoopControl, MemoryTrait, RuntimeFlag, StackTrait},
};
use context_interface::journaled_state::AccountLoad;
use core::{cmp::min, ops::Range};
use primitives::{Bytes, U256};
use specification::hardfork::SpecId::*;
#[inline]
pub fn get_memory_input_and_out_ranges(
interpreter: &mut Interpreter<impl InterpreterTypes>,
) -> Option<(Bytes, Range<usize>)> {
popn!([in_offset, in_len, out_offset, out_len], interpreter, None);
let in_range = resize_memory(interpreter, in_offset, in_len)?;
let mut input = Bytes::new();
if !in_range.is_empty() {
input = Bytes::copy_from_slice(interpreter.memory.slice(in_range).as_ref());
}
let ret_range = resize_memory(interpreter, out_offset, out_len)?;
Some((input, ret_range))
}
#[inline]
pub fn resize_memory(
interpreter: &mut Interpreter<impl InterpreterTypes>,
offset: U256,
len: U256,
) -> Option<Range<usize>> {
let len = as_usize_or_fail_ret!(interpreter, len, None);
let offset = if len != 0 {
let offset = as_usize_or_fail_ret!(interpreter, offset, None);
resize_memory!(interpreter, offset, len, None);
offset
} else {
usize::MAX };
Some(offset..offset + len)
}
#[inline]
pub fn calc_call_gas(
interpreter: &mut Interpreter<impl InterpreterTypes>,
account_load: AccountLoad,
has_transfer: bool,
local_gas_limit: u64,
) -> Option<u64> {
let call_cost = gas::call_cost(
interpreter.runtime_flag.spec_id(),
has_transfer,
account_load,
);
gas!(interpreter, call_cost, None);
let gas_limit = if interpreter.runtime_flag.spec_id().is_enabled_in(TANGERINE) {
min(
interpreter.control.gas().remaining_63_of_64_parts(),
local_gas_limit,
)
} else {
local_gas_limit
};
Some(gas_limit)
}