use context_interface::{ContextTr, LocalContextTr};
use core::ops::Range;
use primitives::{Address, Bytes, B256, U256};
use state::Bytecode;
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum CallInput {
SharedBuffer(Range<usize>),
Bytes(Bytes),
}
impl CallInput {
pub fn len(&self) -> usize {
match self {
Self::Bytes(bytes) => bytes.len(),
Self::SharedBuffer(range) => range.len(),
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn bytes<CTX>(&self, ctx: &CTX) -> Bytes
where
CTX: ContextTr,
{
match self {
CallInput::Bytes(bytes) => bytes.clone(),
CallInput::SharedBuffer(range) => ctx
.local()
.shared_memory_buffer_slice(range.clone())
.map(|b| Bytes::from(b.to_vec()))
.unwrap_or_default(),
}
}
}
impl Default for CallInput {
#[inline]
fn default() -> Self {
CallInput::SharedBuffer(0..0)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CallInputs {
pub input: CallInput,
pub return_memory_offset: Range<usize>,
pub gas_limit: u64,
pub bytecode_address: Address,
pub known_bytecode: Option<(B256, Bytecode)>,
pub target_address: Address,
pub caller: Address,
pub value: CallValue,
pub scheme: CallScheme,
pub is_static: bool,
}
impl CallInputs {
#[inline]
pub fn transfers_value(&self) -> bool {
self.value.transfer().is_some_and(|x| x > U256::ZERO)
}
#[inline]
pub const fn transfer_value(&self) -> Option<U256> {
self.value.transfer()
}
#[inline]
pub const fn apparent_value(&self) -> Option<U256> {
self.value.apparent()
}
#[inline]
pub const fn transfer_from(&self) -> Address {
self.caller
}
#[inline]
pub const fn transfer_to(&self) -> Address {
self.target_address
}
#[inline]
pub const fn call_value(&self) -> U256 {
self.value.get()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum CallScheme {
Call,
CallCode,
DelegateCall,
StaticCall,
}
impl CallScheme {
pub fn is_call(&self) -> bool {
matches!(self, Self::Call)
}
pub fn is_call_code(&self) -> bool {
matches!(self, Self::CallCode)
}
pub fn is_delegate_call(&self) -> bool {
matches!(self, Self::DelegateCall)
}
pub fn is_static_call(&self) -> bool {
matches!(self, Self::StaticCall)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum CallValue {
Transfer(U256),
Apparent(U256),
}
impl Default for CallValue {
#[inline]
fn default() -> Self {
CallValue::Transfer(U256::ZERO)
}
}
impl CallValue {
#[inline]
pub const fn get(&self) -> U256 {
match *self {
Self::Transfer(value) | Self::Apparent(value) => value,
}
}
#[inline]
pub const fn transfer(&self) -> Option<U256> {
match *self {
Self::Transfer(transfer) => Some(transfer),
Self::Apparent(_) => None,
}
}
#[inline]
pub const fn is_transfer(&self) -> bool {
matches!(self, Self::Transfer(_))
}
#[inline]
pub const fn apparent(&self) -> Option<U256> {
match *self {
Self::Transfer(_) => None,
Self::Apparent(apparent) => Some(apparent),
}
}
#[inline]
pub const fn is_apparent(&self) -> bool {
matches!(self, Self::Apparent(_))
}
}