cfx_rpc_eth_types/
simulate.rs

1use crate::{
2    Block, BlockOverrides, Log, RpcAccountOverride as StateOverride,
3    TransactionRequest,
4};
5use cfx_bytes::Bytes;
6use cfx_types::U64;
7
8/// The maximum number of blocks that can be simulated in a single request,
9pub const MAX_SIMULATE_BLOCKS: u64 = 256;
10
11/// Represents a batch of calls to be simulated sequentially within a block.
12/// This struct includes block and state overrides as well as the transaction
13/// requests to be executed.
14#[derive(Clone, Debug, Default)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
17pub struct SimBlock {
18    /// Modifications to the default block characteristics.
19    #[cfg_attr(
20        feature = "serde",
21        serde(default, skip_serializing_if = "Option::is_none")
22    )]
23    pub block_overrides: Option<BlockOverrides>,
24    /// State modifications to apply before executing the transactions.
25    #[cfg_attr(
26        feature = "serde",
27        serde(default, skip_serializing_if = "Option::is_none")
28    )]
29    pub state_overrides: Option<StateOverride>,
30    /// A vector of transactions to be simulated.
31    #[cfg_attr(feature = "serde", serde(default))]
32    pub calls: Vec<TransactionRequest>,
33}
34
35impl SimBlock {
36    /// Enables state overrides
37    pub fn with_state_overrides(mut self, overrides: StateOverride) -> Self {
38        self.state_overrides = Some(overrides);
39        self
40    }
41
42    /// Enables block overrides
43    pub fn with_block_overrides(mut self, overrides: BlockOverrides) -> Self {
44        self.block_overrides = Some(overrides);
45        self
46    }
47
48    /// Adds a call to the block.
49    pub fn call(mut self, call: TransactionRequest) -> Self {
50        self.calls.push(call);
51        self
52    }
53
54    /// Adds multiple calls to the block.
55    pub fn extend_calls(
56        mut self, calls: impl IntoIterator<Item = TransactionRequest>,
57    ) -> Self {
58        self.calls.extend(calls);
59        self
60    }
61}
62
63/// Represents the result of simulating a block.
64#[derive(Clone, Debug)]
65#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
66#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
67pub struct SimulatedBlock<B = Block> {
68    /// The simulated block.
69    #[cfg_attr(feature = "serde", serde(flatten))]
70    pub inner: B,
71    /// A vector of results for each call in the block.
72    pub calls: Vec<SimCallResult>,
73}
74
75/// Captures the outcome of a transaction simulation.
76/// It includes the return value, logs produced, gas used, and the status of the
77/// transaction.
78#[derive(Clone, Debug)]
79#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
80#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
81pub struct SimCallResult {
82    /// The raw bytes returned by the transaction.
83    pub return_data: Bytes,
84    /// Logs generated during the execution of the transaction.
85    #[cfg_attr(feature = "serde", serde(default))]
86    pub logs: Vec<Log>,
87    /// The amount of gas used by the transaction.
88    pub gas_used: U64,
89    /// The final status of the transaction, typically indicating success or
90    /// failure. Should be 0 for failure and 1 for success.
91    pub status: U64,
92    /// Error in case the call failed
93    #[cfg_attr(
94        feature = "serde",
95        serde(default, skip_serializing_if = "Option::is_none")
96    )]
97    pub error: Option<SimulateError>,
98}
99
100/// Simulation options for executing multiple blocks and transactions.
101///
102/// This struct configures how simulations are executed, including whether to
103/// trace token transfers, validate transaction sequences, and whether to return
104/// full transaction objects.
105#[derive(Clone, Debug, Default)]
106#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
107#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
108pub struct SimulatePayload {
109    /// Array of block state calls to be executed at specific, optional
110    /// block/state.
111    #[cfg_attr(feature = "serde", serde(default))]
112    pub block_state_calls: Vec<SimBlock>,
113    /// Flag to determine whether to trace ERC20/ERC721 token transfers within
114    /// transactions.
115    #[cfg_attr(feature = "serde", serde(default))]
116    pub trace_transfers: bool,
117    /// Flag to enable or disable validation of the transaction sequence in the
118    /// blocks.
119    #[cfg_attr(feature = "serde", serde(default))]
120    pub validation: bool,
121    /// Flag to decide if full transactions should be returned instead of just
122    /// their hashes.
123    #[cfg_attr(feature = "serde", serde(default))]
124    pub return_full_transactions: bool,
125}
126
127impl SimulatePayload {
128    /// Adds a block to the simulation payload.
129    pub fn extend(mut self, block: SimBlock) -> Self {
130        self.block_state_calls.push(block);
131        self
132    }
133
134    /// Adds multiple blocks to the simulation payload.
135    pub fn extend_blocks(
136        mut self, blocks: impl IntoIterator<Item = SimBlock>,
137    ) -> Self {
138        self.block_state_calls.extend(blocks);
139        self
140    }
141
142    /// Enables tracing of token transfers.
143    pub const fn with_trace_transfers(mut self) -> Self {
144        self.trace_transfers = true;
145        self
146    }
147
148    /// Enables validation of the transaction sequence.
149    pub const fn with_validation(mut self) -> Self {
150        self.validation = true;
151        self
152    }
153
154    /// Enables returning full transactions.
155    pub const fn with_full_transactions(mut self) -> Self {
156        self.return_full_transactions = true;
157        self
158    }
159}
160
161/// The error response returned by the `eth_simulateV1` method.
162#[derive(Clone, Debug)]
163#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
164#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
165pub struct SimulateError {
166    /// Code error
167    /// -3200: Execution reverted
168    /// -32015: VM execution error
169    pub code: i32,
170    /// Message error
171    pub message: String,
172}