Skip to main content

revm_interpreter/interpreter_action/
create_inputs.rs

1use context_interface::CreateScheme;
2use core::cell::OnceCell;
3use primitives::{Address, Bytes, U256};
4
5/// Inputs for a create call
6#[derive(Clone, Debug, Default, PartialEq, Eq)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct CreateInputs {
9    /// Caller address of the EVM
10    caller: Address,
11    /// The create scheme
12    scheme: CreateScheme,
13    /// The value to transfer
14    value: U256,
15    /// The init code of the contract
16    init_code: Bytes,
17    /// The gas limit of the call
18    gas_limit: u64,
19    /// State gas reservoir (EIP-8037). Passed from parent frame to child frame.
20    reservoir: u64,
21    /// Cached created address. This is computed lazily and cached to avoid
22    /// redundant keccak computations when inspectors call `created_address`.
23    #[cfg_attr(feature = "serde", serde(skip))]
24    cached_address: OnceCell<Address>,
25}
26
27impl CreateInputs {
28    /// Creates a new `CreateInputs` instance.
29    pub fn new(
30        caller: Address,
31        scheme: CreateScheme,
32        value: U256,
33        init_code: Bytes,
34        gas_limit: u64,
35        reservoir: u64,
36    ) -> Self {
37        Self {
38            caller,
39            scheme,
40            value,
41            init_code,
42            gas_limit,
43            reservoir,
44            cached_address: OnceCell::new(),
45        }
46    }
47
48    /// Returns the address that this create call will create.
49    ///
50    /// The result is cached to avoid redundant keccak computations.
51    pub fn created_address(&self, nonce: u64) -> Address {
52        *self.cached_address.get_or_init(|| match self.scheme {
53            CreateScheme::Create => self.caller.create(nonce),
54            CreateScheme::Create2 { salt } => self
55                .caller
56                .create2_from_code(salt.to_be_bytes(), &self.init_code),
57            CreateScheme::Custom { address } => address,
58        })
59    }
60
61    /// Returns the caller address of the EVM.
62    pub fn caller(&self) -> Address {
63        self.caller
64    }
65
66    /// Returns the create scheme of the EVM.
67    pub fn scheme(&self) -> CreateScheme {
68        self.scheme
69    }
70
71    /// Returns the value to transfer.
72    pub fn value(&self) -> U256 {
73        self.value
74    }
75
76    /// Returns the init code of the contract.
77    pub fn init_code(&self) -> &Bytes {
78        &self.init_code
79    }
80
81    /// Returns the gas limit of the call.
82    pub fn gas_limit(&self) -> u64 {
83        self.gas_limit
84    }
85
86    /// Set call
87    pub fn set_call(&mut self, caller: Address) {
88        self.caller = caller;
89        self.cached_address = OnceCell::new();
90    }
91
92    /// Set scheme
93    pub fn set_scheme(&mut self, scheme: CreateScheme) {
94        self.scheme = scheme;
95        self.cached_address = OnceCell::new();
96    }
97
98    /// Set value
99    pub fn set_value(&mut self, value: U256) {
100        self.value = value;
101    }
102
103    /// Set init code
104    pub fn set_init_code(&mut self, init_code: Bytes) {
105        self.init_code = init_code;
106        self.cached_address = OnceCell::new();
107    }
108
109    /// Set gas limit
110    pub fn set_gas_limit(&mut self, gas_limit: u64) {
111        self.gas_limit = gas_limit;
112    }
113
114    /// Returns the state gas reservoir (EIP-8037).
115    pub fn reservoir(&self) -> u64 {
116        self.reservoir
117    }
118
119    /// Set the state gas reservoir (EIP-8037).
120    pub fn set_reservoir(&mut self, reservoir: u64) {
121        self.reservoir = reservoir;
122    }
123}