revm_handler/
frame.rs

1use super::frame_data::*;
2use crate::{
3    instructions::InstructionProvider, precompile_provider::PrecompileProvider, EvmTr,
4    FrameInitOrResult, FrameOrResult, ItemOrResult,
5};
6use bytecode::{Eof, EOF_MAGIC_BYTES};
7use context::result::FromStringError;
8use context_interface::context::ContextError;
9use context_interface::ContextTr;
10use context_interface::{
11    journaled_state::{JournalCheckpoint, JournalTr},
12    Cfg, Database, Transaction,
13};
14use core::{cell::RefCell, cmp::min};
15use interpreter::{
16    gas,
17    interpreter::{EthInterpreter, ExtBytecode},
18    interpreter_types::{LoopControl, ReturnData, RuntimeFlag},
19    return_ok, return_revert, CallInputs, CallOutcome, CallValue, CreateInputs, CreateOutcome,
20    CreateScheme, EOFCreateInputs, EOFCreateKind, FrameInput, Gas, InputsImpl, InstructionResult,
21    Interpreter, InterpreterAction, InterpreterResult, InterpreterTypes, SharedMemory,
22};
23use primitives::{
24    constants::CALL_STACK_LIMIT,
25    hardfork::SpecId::{self, HOMESTEAD, LONDON, OSAKA, SPURIOUS_DRAGON},
26};
27use primitives::{keccak256, Address, Bytes, B256, U256};
28use state::Bytecode;
29use std::borrow::ToOwned;
30use std::{boxed::Box, rc::Rc, sync::Arc};
31
32/// Call frame trait
33pub trait Frame: Sized {
34    type Evm;
35    type FrameInit;
36    type FrameResult;
37    type Error;
38
39    fn init_first(
40        evm: &mut Self::Evm,
41        frame_input: Self::FrameInit,
42    ) -> Result<FrameOrResult<Self>, Self::Error>;
43
44    fn init(
45        &self,
46        evm: &mut Self::Evm,
47        frame_input: Self::FrameInit,
48    ) -> Result<FrameOrResult<Self>, Self::Error>;
49
50    fn run(&mut self, evm: &mut Self::Evm) -> Result<FrameInitOrResult<Self>, Self::Error>;
51
52    fn return_result(
53        &mut self,
54        evm: &mut Self::Evm,
55        result: Self::FrameResult,
56    ) -> Result<(), Self::Error>;
57}
58
59pub struct EthFrame<EVM, ERROR, IW: InterpreterTypes> {
60    phantom: core::marker::PhantomData<(EVM, ERROR)>,
61    /// Data of the frame.
62    data: FrameData,
63    /// Input data for the frame.
64    pub input: FrameInput,
65    /// Depth of the call frame.
66    depth: usize,
67    /// Journal checkpoint.
68    pub checkpoint: JournalCheckpoint,
69    /// Interpreter.
70    pub interpreter: Interpreter<IW>,
71    // This is worth making as a generic type FrameSharedContext.
72    pub memory: Rc<RefCell<SharedMemory>>,
73}
74
75impl<EVM, ERROR> Frame for EthFrame<EVM, ERROR, EthInterpreter>
76where
77    EVM: EvmTr<
78        Precompiles: PrecompileProvider<EVM::Context, Output = InterpreterResult>,
79        Instructions: InstructionProvider<
80            Context = EVM::Context,
81            InterpreterTypes = EthInterpreter,
82        >,
83    >,
84    ERROR: From<ContextTrDbError<EVM::Context>> + FromStringError,
85{
86    type Evm = EVM;
87    type FrameInit = FrameInput;
88    type FrameResult = FrameResult;
89    type Error = ERROR;
90
91    fn init_first(
92        evm: &mut Self::Evm,
93        frame_input: Self::FrameInit,
94    ) -> Result<FrameOrResult<Self>, Self::Error> {
95        EthFrame::init_first(evm, frame_input)
96    }
97
98    fn init(
99        &self,
100        evm: &mut Self::Evm,
101        frame_input: Self::FrameInit,
102    ) -> Result<FrameOrResult<Self>, Self::Error> {
103        self.init(evm, frame_input)
104    }
105
106    fn run(&mut self, context: &mut Self::Evm) -> Result<FrameInitOrResult<Self>, Self::Error> {
107        let next_action = context.run_interpreter(&mut self.interpreter);
108        self.process_next_action(context, next_action)
109    }
110
111    fn return_result(
112        &mut self,
113        context: &mut Self::Evm,
114        result: Self::FrameResult,
115    ) -> Result<(), Self::Error> {
116        self.return_result(context, result)
117    }
118}
119
120pub type ContextTrDbError<CTX> = <<CTX as ContextTr>::Db as Database>::Error;
121
122impl<CTX, ERROR, IW> EthFrame<CTX, ERROR, IW>
123where
124    IW: InterpreterTypes,
125{
126    pub fn new(
127        data: FrameData,
128        input: FrameInput,
129        depth: usize,
130        interpreter: Interpreter<IW>,
131        checkpoint: JournalCheckpoint,
132        memory: Rc<RefCell<SharedMemory>>,
133    ) -> Self {
134        Self {
135            phantom: Default::default(),
136            input,
137            data,
138            depth,
139            interpreter,
140            checkpoint,
141            memory,
142        }
143    }
144}
145
146impl<EVM, ERROR> EthFrame<EVM, ERROR, EthInterpreter>
147where
148    EVM: EvmTr<
149        Context: ContextTr,
150        Precompiles: PrecompileProvider<EVM::Context, Output = InterpreterResult>,
151        Instructions: InstructionProvider,
152    >,
153    ERROR: From<ContextTrDbError<EVM::Context>>,
154    ERROR: FromStringError,
155{
156    /// Make call frame
157    #[inline]
158    pub fn make_call_frame(
159        evm: &mut EVM,
160        depth: usize,
161        memory: Rc<RefCell<SharedMemory>>,
162        inputs: Box<CallInputs>,
163    ) -> Result<ItemOrResult<Self, FrameResult>, ERROR> {
164        let gas = Gas::new(inputs.gas_limit);
165
166        let (context, precompiles) = evm.ctx_precompiles();
167
168        let return_result = |instruction_result: InstructionResult| {
169            Ok(ItemOrResult::Result(FrameResult::Call(CallOutcome {
170                result: InterpreterResult {
171                    result: instruction_result,
172                    gas,
173                    output: Bytes::new(),
174                },
175                memory_offset: inputs.return_memory_offset.clone(),
176            })))
177        };
178
179        // Check depth
180        if depth > CALL_STACK_LIMIT as usize {
181            return return_result(InstructionResult::CallTooDeep);
182        }
183
184        // Make account warm and loaded
185        let _ = context
186            .journal()
187            .load_account_delegated(inputs.bytecode_address)?;
188
189        // Create subroutine checkpoint
190        let checkpoint = context.journal().checkpoint();
191
192        // Touch address. For "EIP-158 State Clear", this will erase empty accounts.
193        if let CallValue::Transfer(value) = inputs.value {
194            // Transfer value from caller to called account
195            // Target will get touched even if balance transferred is zero.
196            if let Some(i) =
197                context
198                    .journal()
199                    .transfer(inputs.caller, inputs.target_address, value)?
200            {
201                context.journal().checkpoint_revert(checkpoint);
202                return return_result(i.into());
203            }
204        }
205
206        let interpreter_input = InputsImpl {
207            target_address: inputs.target_address,
208            caller_address: inputs.caller,
209            input: inputs.input.clone(),
210            call_value: inputs.value.get(),
211        };
212        let is_static = inputs.is_static;
213        let gas_limit = inputs.gas_limit;
214
215        let is_ext_delegate_call = inputs.scheme.is_ext_delegate_call();
216        if !is_ext_delegate_call {
217            if let Some(result) = precompiles
218                .run(
219                    context,
220                    &inputs.bytecode_address,
221                    &interpreter_input,
222                    is_static,
223                    gas_limit,
224                )
225                .map_err(ERROR::from_string)?
226            {
227                if result.result.is_ok() {
228                    context.journal().checkpoint_commit();
229                } else {
230                    context.journal().checkpoint_revert(checkpoint);
231                }
232                return Ok(ItemOrResult::Result(FrameResult::Call(CallOutcome {
233                    result,
234                    memory_offset: inputs.return_memory_offset.clone(),
235                })));
236            }
237        }
238
239        let account = context
240            .journal()
241            .load_account_code(inputs.bytecode_address)?;
242
243        let mut code_hash = account.info.code_hash();
244        let mut bytecode = account.info.code.clone().unwrap_or_default();
245
246        // ExtDelegateCall is not allowed to call non-EOF contracts.
247        if is_ext_delegate_call && !bytecode.bytes_slice().starts_with(&EOF_MAGIC_BYTES) {
248            context.journal().checkpoint_revert(checkpoint);
249            return return_result(InstructionResult::InvalidExtDelegateCallTarget);
250        }
251
252        if bytecode.is_empty() {
253            context.journal().checkpoint_commit();
254            return return_result(InstructionResult::Stop);
255        }
256
257        if let Bytecode::Eip7702(eip7702_bytecode) = bytecode {
258            let account = &context
259                .journal()
260                .load_account_code(eip7702_bytecode.delegated_address)?
261                .info;
262            bytecode = account.code.clone().unwrap_or_default();
263            code_hash = account.code_hash();
264        }
265
266        // Create interpreter and executes call and push new CallStackFrame.
267        Ok(ItemOrResult::Item(Self::new(
268            FrameData::Call(CallFrame {
269                return_memory_range: inputs.return_memory_offset.clone(),
270            }),
271            FrameInput::Call(inputs),
272            depth,
273            Interpreter::new(
274                memory.clone(),
275                ExtBytecode::new_with_hash(bytecode, code_hash),
276                interpreter_input,
277                is_static,
278                false,
279                context.cfg().spec().into(),
280                gas_limit,
281            ),
282            checkpoint,
283            memory,
284        )))
285    }
286
287    /// Make create frame.
288    #[inline]
289    pub fn make_create_frame(
290        evm: &mut EVM,
291        depth: usize,
292        memory: Rc<RefCell<SharedMemory>>,
293        inputs: Box<CreateInputs>,
294    ) -> Result<ItemOrResult<Self, FrameResult>, ERROR> {
295        let context = evm.ctx();
296        let spec = context.cfg().spec().into();
297        let return_error = |e| {
298            Ok(ItemOrResult::Result(FrameResult::Create(CreateOutcome {
299                result: InterpreterResult {
300                    result: e,
301                    gas: Gas::new(inputs.gas_limit),
302                    output: Bytes::new(),
303                },
304                address: None,
305            })))
306        };
307
308        // Check depth
309        if depth > CALL_STACK_LIMIT as usize {
310            return return_error(InstructionResult::CallTooDeep);
311        }
312
313        // Prague EOF
314        if spec.is_enabled_in(OSAKA) && inputs.init_code.starts_with(&EOF_MAGIC_BYTES) {
315            return return_error(InstructionResult::CreateInitCodeStartingEF00);
316        }
317
318        // Fetch balance of caller.
319        let caller_balance = context
320            .journal()
321            .load_account(inputs.caller)?
322            .data
323            .info
324            .balance;
325
326        // Check if caller has enough balance to send to the created contract.
327        if caller_balance < inputs.value {
328            return return_error(InstructionResult::OutOfFunds);
329        }
330
331        // Increase nonce of caller and check if it overflows
332        let old_nonce;
333        if let Some(nonce) = context.journal().inc_account_nonce(inputs.caller)? {
334            old_nonce = nonce - 1;
335        } else {
336            return return_error(InstructionResult::Return);
337        }
338
339        // Create address
340        let mut init_code_hash = B256::ZERO;
341        let created_address = match inputs.scheme {
342            CreateScheme::Create => inputs.caller.create(old_nonce),
343            CreateScheme::Create2 { salt } => {
344                init_code_hash = keccak256(&inputs.init_code);
345                inputs.caller.create2(salt.to_be_bytes(), init_code_hash)
346            }
347        };
348
349        // warm load account.
350        context.journal().load_account(created_address)?;
351
352        // Create account, transfer funds and make the journal checkpoint.
353        let checkpoint = match context.journal().create_account_checkpoint(
354            inputs.caller,
355            created_address,
356            inputs.value,
357            spec,
358        ) {
359            Ok(checkpoint) => checkpoint,
360            Err(e) => return return_error(e.into()),
361        };
362
363        let bytecode = ExtBytecode::new_with_hash(
364            Bytecode::new_legacy(inputs.init_code.clone()),
365            init_code_hash,
366        );
367
368        let interpreter_input = InputsImpl {
369            target_address: created_address,
370            caller_address: inputs.caller,
371            input: Bytes::new(),
372            call_value: inputs.value,
373        };
374        let gas_limit = inputs.gas_limit;
375        Ok(ItemOrResult::Item(Self::new(
376            FrameData::Create(CreateFrame { created_address }),
377            FrameInput::Create(inputs),
378            depth,
379            Interpreter::new(
380                memory.clone(),
381                bytecode,
382                interpreter_input,
383                false,
384                false,
385                spec,
386                gas_limit,
387            ),
388            checkpoint,
389            memory,
390        )))
391    }
392
393    /// Make create frame.
394    #[inline]
395    pub fn make_eofcreate_frame(
396        evm: &mut EVM,
397        depth: usize,
398        memory: Rc<RefCell<SharedMemory>>,
399        inputs: Box<EOFCreateInputs>,
400    ) -> Result<ItemOrResult<Self, FrameResult>, ERROR> {
401        let context = evm.ctx();
402        let spec = context.cfg().spec().into();
403        let return_error = |e| {
404            Ok(ItemOrResult::Result(FrameResult::EOFCreate(
405                CreateOutcome {
406                    result: InterpreterResult {
407                        result: e,
408                        gas: Gas::new(inputs.gas_limit),
409                        output: Bytes::new(),
410                    },
411                    address: None,
412                },
413            )))
414        };
415
416        let (input, initcode, created_address) = match &inputs.kind {
417            EOFCreateKind::Opcode {
418                initcode,
419                input,
420                created_address,
421            } => (input.clone(), initcode.clone(), Some(*created_address)),
422            EOFCreateKind::Tx { initdata } => {
423                // Decode eof and init code.
424                // TODO : Handle inc_nonce handling more gracefully.
425                let Ok((eof, input)) = Eof::decode_dangling(initdata.clone()) else {
426                    context.journal().inc_account_nonce(inputs.caller)?;
427                    return return_error(InstructionResult::InvalidEOFInitCode);
428                };
429
430                if eof.validate().is_err() {
431                    // TODO : (EOF) New error type.
432                    context.journal().inc_account_nonce(inputs.caller)?;
433                    return return_error(InstructionResult::InvalidEOFInitCode);
434                }
435
436                // Use nonce from tx to calculate address.
437                let tx = context.tx();
438                let create_address = tx.caller().create(tx.nonce());
439
440                (input, eof, Some(create_address))
441            }
442        };
443
444        // Check depth
445        if depth > CALL_STACK_LIMIT as usize {
446            return return_error(InstructionResult::CallTooDeep);
447        }
448
449        // Fetch balance of caller.
450        let caller_balance = context
451            .journal()
452            .load_account(inputs.caller)?
453            .map(|a| a.info.balance);
454
455        // Check if caller has enough balance to send to the created contract.
456        if caller_balance.data < inputs.value {
457            return return_error(InstructionResult::OutOfFunds);
458        }
459
460        // Increase nonce of caller and check if it overflows
461        let Some(nonce) = context.journal().inc_account_nonce(inputs.caller)? else {
462            // Can't happen on mainnet.
463            return return_error(InstructionResult::Return);
464        };
465        let old_nonce = nonce - 1;
466
467        let created_address = created_address.unwrap_or_else(|| inputs.caller.create(old_nonce));
468
469        // Load account so it needs to be marked as warm for access list.
470        context.journal().load_account(created_address)?;
471
472        // Create account, transfer funds and make the journal checkpoint.
473        let checkpoint = match context.journal().create_account_checkpoint(
474            inputs.caller,
475            created_address,
476            inputs.value,
477            spec,
478        ) {
479            Ok(checkpoint) => checkpoint,
480            Err(e) => return return_error(e.into()),
481        };
482
483        let interpreter_input = InputsImpl {
484            target_address: created_address,
485            caller_address: inputs.caller,
486            input,
487            call_value: inputs.value,
488        };
489
490        let gas_limit = inputs.gas_limit;
491        Ok(ItemOrResult::Item(Self::new(
492            FrameData::EOFCreate(EOFCreateFrame { created_address }),
493            FrameInput::EOFCreate(inputs),
494            depth,
495            Interpreter::new(
496                memory.clone(),
497                ExtBytecode::new(Bytecode::Eof(Arc::new(initcode))),
498                interpreter_input,
499                false,
500                true,
501                spec,
502                gas_limit,
503            ),
504            checkpoint,
505            memory,
506        )))
507    }
508
509    pub fn init_with_context(
510        evm: &mut EVM,
511        depth: usize,
512        frame_init: FrameInput,
513        memory: Rc<RefCell<SharedMemory>>,
514    ) -> Result<ItemOrResult<Self, FrameResult>, ERROR> {
515        match frame_init {
516            FrameInput::Call(inputs) => Self::make_call_frame(evm, depth, memory, inputs),
517            FrameInput::Create(inputs) => Self::make_create_frame(evm, depth, memory, inputs),
518            FrameInput::EOFCreate(inputs) => Self::make_eofcreate_frame(evm, depth, memory, inputs),
519        }
520    }
521}
522
523impl<EVM, ERROR> EthFrame<EVM, ERROR, EthInterpreter>
524where
525    EVM: EvmTr<
526        Context: ContextTr,
527        Precompiles: PrecompileProvider<EVM::Context, Output = InterpreterResult>,
528        Instructions: InstructionProvider<
529            Context = EVM::Context,
530            InterpreterTypes = EthInterpreter,
531        >,
532    >,
533    ERROR: From<ContextTrDbError<EVM::Context>> + FromStringError,
534{
535    pub fn init_first(
536        evm: &mut EVM,
537        frame_input: FrameInput,
538    ) -> Result<ItemOrResult<Self, FrameResult>, ERROR> {
539        let memory = Rc::new(RefCell::new(SharedMemory::new()));
540        memory.borrow_mut().new_context();
541        Self::init_with_context(evm, 0, frame_input, memory)
542    }
543
544    fn init(
545        &self,
546        evm: &mut EVM,
547        frame_init: FrameInput,
548    ) -> Result<ItemOrResult<Self, FrameResult>, ERROR> {
549        self.memory.borrow_mut().new_context();
550        Self::init_with_context(evm, self.depth + 1, frame_init, self.memory.clone())
551    }
552
553    pub fn process_next_action(
554        &mut self,
555        evm: &mut EVM,
556        next_action: InterpreterAction,
557    ) -> Result<FrameInitOrResult<Self>, ERROR> {
558        let context = evm.ctx();
559        let spec = context.cfg().spec().into();
560
561        // Run interpreter
562
563        let mut interpreter_result = match next_action {
564            InterpreterAction::NewFrame(new_frame) => return Ok(ItemOrResult::Item(new_frame)),
565            InterpreterAction::Return { result } => result,
566            InterpreterAction::None => unreachable!("InterpreterAction::None is not expected"),
567        };
568
569        // Handle return from frame
570        let result = match &self.data {
571            FrameData::Call(frame) => {
572                // return_call
573                // Revert changes or not.
574                if interpreter_result.result.is_ok() {
575                    context.journal().checkpoint_commit();
576                } else {
577                    context.journal().checkpoint_revert(self.checkpoint);
578                }
579                ItemOrResult::Result(FrameResult::Call(CallOutcome::new(
580                    interpreter_result,
581                    frame.return_memory_range.clone(),
582                )))
583            }
584            FrameData::Create(frame) => {
585                let max_code_size = context.cfg().max_code_size();
586                return_create(
587                    context.journal(),
588                    self.checkpoint,
589                    &mut interpreter_result,
590                    frame.created_address,
591                    max_code_size,
592                    spec,
593                );
594
595                ItemOrResult::Result(FrameResult::Create(CreateOutcome::new(
596                    interpreter_result,
597                    Some(frame.created_address),
598                )))
599            }
600            FrameData::EOFCreate(frame) => {
601                let max_code_size = context.cfg().max_code_size();
602                return_eofcreate(
603                    context.journal(),
604                    self.checkpoint,
605                    &mut interpreter_result,
606                    frame.created_address,
607                    max_code_size,
608                );
609
610                ItemOrResult::Result(FrameResult::EOFCreate(CreateOutcome::new(
611                    interpreter_result,
612                    Some(frame.created_address),
613                )))
614            }
615        };
616
617        Ok(result)
618    }
619
620    fn return_result(&mut self, evm: &mut EVM, result: FrameResult) -> Result<(), ERROR> {
621        self.memory.borrow_mut().free_context();
622        match core::mem::replace(evm.ctx().error(), Ok(())) {
623            Err(ContextError::Db(e)) => return Err(e.into()),
624            Err(ContextError::Custom(e)) => return Err(ERROR::from_string(e)),
625            Ok(_) => (),
626        }
627
628        // Insert result to the top frame.
629        match result {
630            FrameResult::Call(outcome) => {
631                let out_gas = outcome.gas();
632                let ins_result = *outcome.instruction_result();
633                let returned_len = outcome.result.output.len();
634
635                let interpreter = &mut self.interpreter;
636                let mem_length = outcome.memory_length();
637                let mem_start = outcome.memory_start();
638                interpreter.return_data.set_buffer(outcome.result.output);
639
640                let target_len = min(mem_length, returned_len);
641
642                if ins_result == InstructionResult::FatalExternalError {
643                    panic!("Fatal external error in insert_call_outcome");
644                }
645
646                let item = {
647                    if interpreter.runtime_flag.is_eof() {
648                        match ins_result {
649                            return_ok!() => U256::ZERO,
650                            return_revert!() => U256::from(1),
651                            _ => U256::from(2),
652                        }
653                    } else if ins_result.is_ok() {
654                        U256::from(1)
655                    } else {
656                        U256::ZERO
657                    }
658                };
659                // Safe to push without stack limit check
660                let _ = interpreter.stack.push(item);
661
662                // Return unspend gas.
663                if ins_result.is_ok_or_revert() {
664                    interpreter
665                        .control
666                        .gas_mut()
667                        .erase_cost(out_gas.remaining());
668                    self.memory
669                        .borrow_mut()
670                        .set(mem_start, &interpreter.return_data.buffer()[..target_len]);
671                }
672
673                if ins_result.is_ok() {
674                    interpreter
675                        .control
676                        .gas_mut()
677                        .record_refund(out_gas.refunded());
678                }
679            }
680            FrameResult::Create(outcome) => {
681                let instruction_result = *outcome.instruction_result();
682                let interpreter = &mut self.interpreter;
683
684                if instruction_result == InstructionResult::Revert {
685                    // Save data to return data buffer if the create reverted
686                    interpreter
687                        .return_data
688                        .set_buffer(outcome.output().to_owned());
689                } else {
690                    // Otherwise clear it. Note that RETURN opcode should abort.
691                    interpreter.return_data.clear();
692                };
693
694                assert_ne!(
695                    instruction_result,
696                    InstructionResult::FatalExternalError,
697                    "Fatal external error in insert_eofcreate_outcome"
698                );
699
700                let this_gas = interpreter.control.gas_mut();
701                if instruction_result.is_ok_or_revert() {
702                    this_gas.erase_cost(outcome.gas().remaining());
703                }
704
705                let stack_item = if instruction_result.is_ok() {
706                    this_gas.record_refund(outcome.gas().refunded());
707                    outcome.address.unwrap_or_default().into_word().into()
708                } else {
709                    U256::ZERO
710                };
711
712                // Safe to push without stack limit check
713                let _ = interpreter.stack.push(stack_item);
714            }
715            FrameResult::EOFCreate(outcome) => {
716                let instruction_result = *outcome.instruction_result();
717                let interpreter = &mut self.interpreter;
718                if instruction_result == InstructionResult::Revert {
719                    // Save data to return data buffer if the create reverted
720                    interpreter
721                        .return_data
722                        .set_buffer(outcome.output().to_owned());
723                } else {
724                    // Otherwise clear it. Note that RETURN opcode should abort.
725                    interpreter.return_data.clear()
726                };
727
728                assert_ne!(
729                    instruction_result,
730                    InstructionResult::FatalExternalError,
731                    "Fatal external error in insert_eofcreate_outcome"
732                );
733
734                let this_gas = interpreter.control.gas_mut();
735                if instruction_result.is_ok_or_revert() {
736                    this_gas.erase_cost(outcome.gas().remaining());
737                }
738
739                let stack_item = if instruction_result.is_ok() {
740                    this_gas.record_refund(outcome.gas().refunded());
741                    outcome.address.expect("EOF Address").into_word().into()
742                } else {
743                    U256::ZERO
744                };
745
746                // Safe to push without stack limit check
747                let _ = interpreter.stack.push(stack_item);
748            }
749        }
750
751        Ok(())
752    }
753}
754
755pub fn return_create<JOURNAL: JournalTr>(
756    journal: &mut JOURNAL,
757    checkpoint: JournalCheckpoint,
758    interpreter_result: &mut InterpreterResult,
759    address: Address,
760    max_code_size: usize,
761    spec_id: SpecId,
762) {
763    // If return is not ok revert and return.
764    if !interpreter_result.result.is_ok() {
765        journal.checkpoint_revert(checkpoint);
766        return;
767    }
768    // Host error if present on execution
769    // If ok, check contract creation limit and calculate gas deduction on output len.
770    //
771    // EIP-3541: Reject new contract code starting with the 0xEF byte
772    if spec_id.is_enabled_in(LONDON) && interpreter_result.output.first() == Some(&0xEF) {
773        journal.checkpoint_revert(checkpoint);
774        interpreter_result.result = InstructionResult::CreateContractStartingWithEF;
775        return;
776    }
777
778    // EIP-170: Contract code size limit
779    // By default limit is 0x6000 (~25kb)
780    if spec_id.is_enabled_in(SPURIOUS_DRAGON) && interpreter_result.output.len() > max_code_size {
781        journal.checkpoint_revert(checkpoint);
782        interpreter_result.result = InstructionResult::CreateContractSizeLimit;
783        return;
784    }
785    let gas_for_code = interpreter_result.output.len() as u64 * gas::CODEDEPOSIT;
786    if !interpreter_result.gas.record_cost(gas_for_code) {
787        // Record code deposit gas cost and check if we are out of gas.
788        // EIP-2 point 3: If contract creation does not have enough gas to pay for the
789        // final gas fee for adding the contract code to the state, the contract
790        // creation fails (i.e. goes out-of-gas) rather than leaving an empty contract.
791        if spec_id.is_enabled_in(HOMESTEAD) {
792            journal.checkpoint_revert(checkpoint);
793            interpreter_result.result = InstructionResult::OutOfGas;
794            return;
795        } else {
796            interpreter_result.output = Bytes::new();
797        }
798    }
799    // If we have enough gas we can commit changes.
800    journal.checkpoint_commit();
801
802    // Do analysis of bytecode straight away.
803    let bytecode = Bytecode::new_legacy(interpreter_result.output.clone());
804
805    // Set code
806    journal.set_code(address, bytecode);
807
808    interpreter_result.result = InstructionResult::Return;
809}
810
811pub fn return_eofcreate<JOURNAL: JournalTr>(
812    journal: &mut JOURNAL,
813    checkpoint: JournalCheckpoint,
814    interpreter_result: &mut InterpreterResult,
815    address: Address,
816    max_code_size: usize,
817) {
818    // Note we still execute RETURN opcode and return the bytes.
819    // In EOF those opcodes should abort execution.
820    //
821    // In RETURN gas is still protecting us from ddos and in oog,
822    // behaviour will be same as if it failed on return.
823    //
824    // Bytes of RETURN will drained in `insert_eofcreate_outcome`.
825    if interpreter_result.result != InstructionResult::ReturnContract {
826        journal.checkpoint_revert(checkpoint);
827        return;
828    }
829
830    if interpreter_result.output.len() > max_code_size {
831        journal.checkpoint_revert(checkpoint);
832        interpreter_result.result = InstructionResult::CreateContractSizeLimit;
833        return;
834    }
835
836    // Deduct gas for code deployment.
837    let gas_for_code = interpreter_result.output.len() as u64 * gas::CODEDEPOSIT;
838    if !interpreter_result.gas.record_cost(gas_for_code) {
839        journal.checkpoint_revert(checkpoint);
840        interpreter_result.result = InstructionResult::OutOfGas;
841        return;
842    }
843
844    journal.checkpoint_commit();
845
846    // Decode bytecode has a performance hit, but it has reasonable restrains.
847    let bytecode = Eof::decode(interpreter_result.output.clone()).expect("Eof is already verified");
848
849    // Eof bytecode is going to be hashed.
850    journal.set_code(address, Bytecode::Eof(Arc::new(bytecode)));
851}