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