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