pallet_revive/vm/evm/instructions/
contract.rs1mod call_helpers;
19
20use super::{utility::IntoAddress, Context};
21use crate::{
22 vm::{evm::U256Converter, Ext, RuntimeCosts},
23 Pallet,
24};
25use alloc::boxed::Box;
26pub use call_helpers::{calc_call_gas, get_memory_input_and_out_ranges};
27use revm::{
28 context_interface::CreateScheme,
29 interpreter::{
30 gas as revm_gas,
31 interpreter_action::{
32 CallInputs, CallScheme, CallValue, CreateInputs, FrameInput, InterpreterAction,
33 },
34 interpreter_types::{LoopControl, RuntimeFlag, StackTr},
35 CallInput, InstructionResult,
36 },
37 primitives::{Address, Bytes, B256, U256},
38};
39
40pub fn create<'ext, const IS_CREATE2: bool, E: Ext>(context: Context<'_, 'ext, E>) {
44 if context.interpreter.extend.is_read_only() {
45 context.interpreter.halt(InstructionResult::Revert);
46 return;
47 }
48
49 popn!([value, code_offset, len], context.interpreter);
50 let len = as_usize_or_fail!(context.interpreter, len);
51
52 let val = crate::U256::from_revm_u256(&value);
56 gas!(
57 context.interpreter,
58 RuntimeCosts::Instantiate {
59 input_data_len: len as u32, balance_transfer: Pallet::<E::T>::has_balance(val),
61 dust_transfer: Pallet::<E::T>::has_dust(val),
62 }
63 );
64
65 let mut code = Bytes::new();
66 if len != 0 {
67 if len > revm::primitives::eip3860::MAX_INITCODE_SIZE {
69 context.interpreter.halt(InstructionResult::CreateInitCodeSizeLimit);
70 return;
71 }
72
73 let code_offset = as_usize_or_fail!(context.interpreter, code_offset);
74 resize_memory!(context.interpreter, code_offset, len);
75 code =
76 Bytes::copy_from_slice(context.interpreter.memory.slice_len(code_offset, len).as_ref());
77 }
78
79 let scheme = if IS_CREATE2 {
81 popn!([salt], context.interpreter);
82 CreateScheme::Create2 { salt }
83 } else {
84 gas_legacy!(context.interpreter, revm_gas::CREATE);
85 CreateScheme::Create
86 };
87
88 context
90 .interpreter
91 .bytecode
92 .set_action(InterpreterAction::NewFrame(FrameInput::Create(Box::new(CreateInputs {
93 caller: context.interpreter.extend.address().0.into(),
94 scheme,
95 value,
96 init_code: code,
97 gas_limit: u64::MAX, }))));
99}
100
101pub fn call<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
105 popn!([local_gas_limit, to, value], context.interpreter);
106 let to = to.into_address();
107 let _local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX);
110
111 let has_transfer = !value.is_zero();
112 if context.interpreter.runtime_flag.is_static() && has_transfer {
113 context.interpreter.halt(InstructionResult::CallNotAllowedInsideStatic);
114 return;
115 }
116
117 let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(context.interpreter)
118 else {
119 return;
120 };
121
122 let scheme = CallScheme::Call;
123 let input = CallInput::SharedBuffer(input);
124
125 let Some(gas_limit) = calc_call_gas(context.interpreter, to, scheme, input.len(), value) else {
126 return;
127 };
128
129 context
131 .interpreter
132 .bytecode
133 .set_action(InterpreterAction::NewFrame(FrameInput::Call(Box::new(CallInputs {
134 input,
135 gas_limit,
136 target_address: to,
137 caller: Address::default(),
138 bytecode_address: to,
139 value: CallValue::Transfer(value),
140 scheme,
141 is_static: context.interpreter.runtime_flag.is_static(),
142 return_memory_offset,
143 }))));
144}
145
146pub fn call_code<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
153 context.interpreter.halt(revm::interpreter::InstructionResult::NotActivated);
154}
155
156pub fn delegate_call<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
160 popn!([local_gas_limit, to], context.interpreter);
161 let to = Address::from_word(B256::from(to));
162 let _local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX);
165
166 let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(context.interpreter)
167 else {
168 return;
169 };
170
171 let scheme = CallScheme::DelegateCall;
172 let input = CallInput::SharedBuffer(input);
173
174 let Some(gas_limit) = calc_call_gas(context.interpreter, to, scheme, input.len(), U256::ZERO)
175 else {
176 return;
177 };
178
179 context
181 .interpreter
182 .bytecode
183 .set_action(InterpreterAction::NewFrame(FrameInput::Call(Box::new(CallInputs {
184 input,
185 gas_limit,
186 target_address: Default::default(),
187 caller: Default::default(),
188 bytecode_address: to,
189 value: CallValue::Apparent(Default::default()),
190 scheme,
191 is_static: context.interpreter.runtime_flag.is_static(),
192 return_memory_offset,
193 }))));
194}
195
196pub fn static_call<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
200 popn!([local_gas_limit, to], context.interpreter);
201 let to = Address::from_word(B256::from(to));
202 let _local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX);
205
206 let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(context.interpreter)
207 else {
208 return;
209 };
210
211 let scheme = CallScheme::StaticCall;
212 let input = CallInput::SharedBuffer(input);
213
214 let Some(gas_limit) = calc_call_gas(context.interpreter, to, scheme, input.len(), U256::ZERO)
215 else {
216 return;
217 };
218
219 context
221 .interpreter
222 .bytecode
223 .set_action(InterpreterAction::NewFrame(FrameInput::Call(Box::new(CallInputs {
224 input,
225 gas_limit,
226 target_address: to,
227 caller: Default::default(),
228 bytecode_address: to,
229 value: CallValue::Transfer(U256::ZERO),
230 scheme,
231 is_static: true,
232 return_memory_offset,
233 }))));
234}