stratus/eth/executor/
evm_input.rs

1use alloy_rpc_types_trace::geth::GethDebugTracingOptions;
2use display_json::DebugAsJson;
3
4use crate::eth::primitives::Address;
5use crate::eth::primitives::Block;
6use crate::eth::primitives::BlockNumber;
7use crate::eth::primitives::Bytes;
8use crate::eth::primitives::CallInput;
9use crate::eth::primitives::ChainId;
10use crate::eth::primitives::ExecutionInfo;
11use crate::eth::primitives::Gas;
12use crate::eth::primitives::Hash;
13use crate::eth::primitives::Nonce;
14use crate::eth::primitives::PendingBlockHeader;
15use crate::eth::primitives::PointInTime;
16use crate::eth::primitives::UnixTime;
17use crate::eth::primitives::Wei;
18use crate::eth::storage::ReadKind;
19use crate::eth::storage::TxCount;
20use crate::ext::OptionExt;
21use crate::ext::not;
22
23/// EVM input data. Usually derived from a transaction or call.
24#[derive(DebugAsJson, Clone, Default, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
25#[cfg_attr(test, derive(fake::Dummy))]
26pub struct EvmInput {
27    /// Operation party address.
28    ///
29    /// It can be:
30    /// * Transaction signer when executing an `eth_sendRawTransaction`.
31    /// * Placeholder when performing an `eth_call`
32    /// * Not specified when performing an `eth_call`
33    pub from: Address,
34
35    /// Operation counterparty address.
36    ///
37    /// It can be:
38    /// * Contract address when performing a function call.
39    /// * Destination account address when transfering funds.
40    /// * Not specified when deploying a contract.
41    pub to: Option<Address>,
42
43    /// Transfered amount from party to counterparty.
44    ///
45    /// Present only in native token transfers. When calling a contract function, the value is usually zero.
46    pub value: Wei,
47
48    /// Operation data.
49    ///
50    /// It can be:
51    /// * Function ID and parameters when performing a contract function call.
52    /// * Not specified when transfering funds.
53    /// * Contract bytecode when deploying a contract.
54    pub data: Bytes,
55
56    /// Operation party nonce.
57    ///
58    /// It can be:
59    /// * Required when executing an `eth_sendRawTransaction`.
60    /// * Not specified when performing an `eth_call`.
61    pub nonce: Option<Nonce>,
62
63    /// Max gas consumption allowed for the transaction.
64    pub gas_limit: Gas,
65
66    /// Gas price paid by each unit of gas consumed by the transaction.
67    pub gas_price: u128,
68
69    /// Number of the block where the transaction will be or was included.
70    pub block_number: BlockNumber,
71
72    /// Timestamp of the block where the transaction will be or was included.
73    pub block_timestamp: UnixTime,
74
75    /// Point-in-time from where accounts and slots will be read.
76    pub point_in_time: PointInTime,
77
78    /// ID of the blockchain where the transaction will be or was included.
79    ///
80    /// If not specified, it will not be validated.
81    pub chain_id: Option<ChainId>,
82
83    pub kind: ReadKind,
84}
85
86impl EvmInput {
87    /// Creates from a transaction that was sent to Stratus with `eth_sendRawTransaction` or during Importing.
88    pub fn from_eth_transaction(input: &ExecutionInfo, block_number: BlockNumber, block_timestamp: UnixTime) -> Self {
89        Self {
90            from: input.signer,
91            to: input.to,
92            value: input.value,
93            data: input.input.clone(),
94            gas_limit: input.gas_limit,
95            gas_price: input.gas_price,
96            nonce: Some(input.nonce),
97            block_number,
98            block_timestamp,
99            point_in_time: PointInTime::Pending,
100            chain_id: input.chain_id,
101            kind: ReadKind::Transaction,
102        }
103    }
104
105    /// Creates from a call that was sent directly to Stratus with `eth_call` or `eth_estimateGas` for a pending block.
106    pub fn from_pending_block(input: CallInput, pending_header: PendingBlockHeader, tx_count: TxCount) -> Self {
107        Self {
108            from: input.from.unwrap_or(Address::ZERO),
109            to: input.to.map_into(),
110            value: input.value,
111            data: input.data,
112            gas_limit: Gas::MAX,
113            gas_price: 0,
114            nonce: None,
115            block_number: pending_header.number,
116            block_timestamp: *pending_header.timestamp,
117            point_in_time: PointInTime::Pending,
118            chain_id: None,
119            kind: ReadKind::Call((pending_header.number, tx_count)),
120        }
121    }
122
123    /// Creates from a call that was sent directly to Stratus with `eth_call` or `eth_estimateGas` for a mined block.
124    pub fn from_mined_block(input: CallInput, block: Block, point_in_time: PointInTime) -> Self {
125        Self {
126            from: input.from.unwrap_or(Address::ZERO),
127            to: input.to.map_into(),
128            value: input.value,
129            data: input.data,
130            gas_limit: Gas::MAX,
131            gas_price: 0,
132            nonce: None,
133            block_number: block.number(),
134            block_timestamp: block.header.timestamp,
135            point_in_time,
136            chain_id: None,
137            kind: ReadKind::Call((block.number(), TxCount::Full)),
138        }
139    }
140
141    /// Checks if the input is a contract call.
142    ///
143    /// It is when there is a `to` address and the `data` field is also populated.
144    pub fn is_contract_call(&self) -> bool {
145        self.to.is_some() && not(self.data.is_empty())
146    }
147}
148
149impl PartialEq<&PendingBlockHeader> for EvmInput {
150    fn eq(&self, other: &&PendingBlockHeader) -> bool {
151        self.block_number == other.number && self.block_timestamp == *other.timestamp
152    }
153}
154
155pub struct InspectorInput {
156    pub tx_hash: Hash,
157    pub opts: GethDebugTracingOptions,
158    pub trace_unsuccessful_only: bool,
159}