revm_handler/
execution.rs

1use super::frame_data::FrameResult;
2use bytecode::EOF_MAGIC_BYTES;
3use context_interface::ContextTr;
4use context_interface::Transaction;
5use interpreter::{
6    CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, EOFCreateInputs, EOFCreateKind,
7    FrameInput, Gas,
8};
9use primitives::TxKind;
10use specification::hardfork::SpecId;
11use std::boxed::Box;
12
13pub fn create_init_frame(tx: &impl Transaction, spec: SpecId, gas_limit: u64) -> FrameInput {
14    // Make new frame action.
15    let input = tx.input().clone();
16
17    match tx.kind() {
18        TxKind::Call(target_address) => FrameInput::Call(Box::new(CallInputs {
19            input,
20            gas_limit,
21            target_address,
22            bytecode_address: target_address,
23            caller: tx.caller(),
24            value: CallValue::Transfer(tx.value()),
25            scheme: CallScheme::Call,
26            is_static: false,
27            is_eof: false,
28            return_memory_offset: 0..0,
29        })),
30        TxKind::Create => {
31            // If first byte of data is magic 0xEF00, then it is EOFCreate.
32            if spec.is_enabled_in(SpecId::OSAKA) && input.starts_with(&EOF_MAGIC_BYTES) {
33                FrameInput::EOFCreate(Box::new(EOFCreateInputs::new(
34                    tx.caller(),
35                    tx.value(),
36                    gas_limit,
37                    EOFCreateKind::Tx { initdata: input },
38                )))
39            } else {
40                FrameInput::Create(Box::new(CreateInputs {
41                    caller: tx.caller(),
42                    scheme: CreateScheme::Create,
43                    value: tx.value(),
44                    init_code: input,
45                    gas_limit,
46                }))
47            }
48        }
49    }
50}
51
52/// TODO : Frame result should be a generic trait with needed functions.
53pub fn last_frame_result<CTX: ContextTr>(context: CTX, frame_result: &mut FrameResult) {
54    let instruction_result = frame_result.interpreter_result().result;
55    let gas = frame_result.gas_mut();
56    let remaining = gas.remaining();
57    let refunded = gas.refunded();
58
59    // Spend the gas limit. Gas is reimbursed when the tx returns successfully.
60    *gas = Gas::new_spent(context.tx().gas_limit());
61
62    if instruction_result.is_ok_or_revert() {
63        gas.erase_cost(remaining);
64    }
65
66    if instruction_result.is_ok() {
67        gas.record_refund(refunded);
68    }
69}