pallet_revive/vm/evm/instructions/contract/
call_helpers.rs1use crate::{
19 precompiles::{All as AllPrecompiles, Precompiles},
20 vm::{evm::U256Converter, Ext},
21 Pallet, RuntimeCosts,
22};
23use core::ops::Range;
24use revm::{
25 interpreter::{
26 interpreter_action::CallScheme,
27 interpreter_types::{MemoryTr, StackTr},
28 Interpreter,
29 },
30 primitives::{Address, U256},
31};
32use sp_core::H160;
33
34#[inline]
36pub fn get_memory_input_and_out_ranges<'a, E: Ext>(
37 interpreter: &mut Interpreter<crate::vm::evm::EVMInterpreter<'a, E>>,
38) -> Option<(Range<usize>, Range<usize>)> {
39 popn!([in_offset, in_len, out_offset, out_len], interpreter, None);
40
41 let mut in_range = resize_memory(interpreter, in_offset, in_len)?;
42
43 if !in_range.is_empty() {
44 let offset = <_ as MemoryTr>::local_memory_offset(&interpreter.memory);
45 in_range = in_range.start.saturating_add(offset)..in_range.end.saturating_add(offset);
46 }
47
48 let ret_range = resize_memory(interpreter, out_offset, out_len)?;
49 Some((in_range, ret_range))
50}
51
52#[inline]
55pub fn resize_memory<'a, E: Ext>(
56 interpreter: &mut Interpreter<crate::vm::evm::EVMInterpreter<'a, E>>,
57 offset: U256,
58 len: U256,
59) -> Option<Range<usize>> {
60 let len = as_usize_or_fail_ret!(interpreter, len, None);
61 let offset = if len != 0 {
62 let offset = as_usize_or_fail_ret!(interpreter, offset, None);
63 resize_memory!(interpreter, offset, len, None);
64 offset
65 } else {
66 usize::MAX };
68 Some(offset..offset + len)
69}
70
71#[inline]
73pub fn calc_call_gas<'a, E: Ext>(
74 interpreter: &mut Interpreter<crate::vm::evm::EVMInterpreter<'a, E>>,
75 callee: Address,
76 scheme: CallScheme,
77 input_len: usize,
78 value: U256,
79) -> Option<u64> {
80 let callee: H160 = callee.0 .0.into();
81 let precompile = <AllPrecompiles<E::T>>::get::<E>(&callee.as_fixed_bytes());
82
83 match precompile {
84 Some(precompile) => {
85 let base_cost = if precompile.has_contract_info() {
87 RuntimeCosts::PrecompileWithInfoBase
88 } else {
89 RuntimeCosts::PrecompileBase
90 };
91 gas!(interpreter, base_cost, None);
92
93 gas!(interpreter, RuntimeCosts::PrecompileDecode(input_len as u32), None);
95 },
96 None => {
97 let base_cost = if scheme.is_delegate_call() {
99 RuntimeCosts::DelegateCallBase
100 } else {
101 RuntimeCosts::CallBase
102 };
103 gas!(interpreter, base_cost, None);
104
105 gas!(interpreter, RuntimeCosts::CopyFromContract(input_len as u32), None);
106 },
107 };
108 if !value.is_zero() {
109 gas!(
110 interpreter,
111 RuntimeCosts::CallTransferSurcharge {
112 dust_transfer: Pallet::<E::T>::has_dust(crate::U256::from_revm_u256(&value)),
113 },
114 None
115 );
116 }
117 Some(u64::MAX) }