use context_interface::CreateScheme;
use core::cell::OnceCell;
use primitives::{keccak256, Address, Bytes, B256, U256};
#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CreateInputs {
caller: Address,
scheme: CreateScheme,
value: U256,
init_code: Bytes,
gas_limit: u64,
reservoir: u64,
#[cfg_attr(feature = "serde", serde(skip))]
cached_address: OnceCell<Address>,
#[cfg_attr(feature = "serde", serde(skip))]
cached_init_code_hash: OnceCell<B256>,
}
impl CreateInputs {
pub const fn new(
caller: Address,
scheme: CreateScheme,
value: U256,
init_code: Bytes,
gas_limit: u64,
reservoir: u64,
) -> Self {
Self {
caller,
scheme,
value,
init_code,
gas_limit,
reservoir,
cached_address: OnceCell::new(),
cached_init_code_hash: OnceCell::new(),
}
}
pub fn created_address(&self, nonce: u64) -> Address {
*self.cached_address.get_or_init(|| match self.scheme {
CreateScheme::Create => self.caller.create(nonce),
CreateScheme::Create2 { salt } => self
.caller
.create2(salt.to_be_bytes(), self.init_code_hash()),
CreateScheme::Custom { address } => address,
})
}
pub fn init_code_hash(&self) -> B256 {
*self
.cached_init_code_hash
.get_or_init(|| keccak256(self.init_code.as_ref()))
}
pub const fn caller(&self) -> Address {
self.caller
}
pub const fn scheme(&self) -> CreateScheme {
self.scheme
}
pub const fn value(&self) -> U256 {
self.value
}
pub const fn init_code(&self) -> &Bytes {
&self.init_code
}
pub const fn gas_limit(&self) -> u64 {
self.gas_limit
}
pub const fn set_call(&mut self, caller: Address) {
self.caller = caller;
self.cached_address = OnceCell::new();
}
pub const fn set_scheme(&mut self, scheme: CreateScheme) {
self.scheme = scheme;
self.cached_address = OnceCell::new();
}
pub const fn set_value(&mut self, value: U256) {
self.value = value;
}
pub fn set_init_code(&mut self, init_code: Bytes) {
self.init_code = init_code;
self.cached_address = OnceCell::new();
self.cached_init_code_hash = OnceCell::new();
}
pub const fn set_gas_limit(&mut self, gas_limit: u64) {
self.gas_limit = gas_limit;
}
pub const fn reservoir(&self) -> u64 {
self.reservoir
}
pub const fn set_reservoir(&mut self, reservoir: u64) {
self.reservoir = reservoir;
}
}