1use crate::{state::StateOverride, Block, BlockOverrides, Log, TransactionRequest};
4use alloc::{string::String, vec::Vec};
5use alloy_primitives::{Bytes, U256};
6
7pub const MAX_SIMULATE_BLOCKS: u64 = 256;
9
10#[derive(Clone, Debug)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15#[cfg_attr(
16 feature = "serde",
17 serde(
18 rename_all = "camelCase",
19 bound(
20 deserialize = "TxReq: serde::Deserialize<'de>",
21 serialize = "TxReq: serde::Serialize"
22 )
23 )
24)]
25pub struct SimBlock<TxReq = TransactionRequest> {
26 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))]
28 pub block_overrides: Option<BlockOverrides>,
29 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))]
31 pub state_overrides: Option<StateOverride>,
32 #[cfg_attr(feature = "serde", serde(default = "Vec::new"))]
34 pub calls: Vec<TxReq>,
35}
36
37impl<TxReq> Default for SimBlock<TxReq> {
38 fn default() -> Self {
39 Self { block_overrides: None, state_overrides: None, calls: Vec::new() }
40 }
41}
42
43impl<TxReq> SimBlock<TxReq> {
44 pub fn with_state_overrides(mut self, overrides: StateOverride) -> Self {
46 self.state_overrides = Some(overrides);
47 self
48 }
49
50 pub fn with_block_overrides(mut self, overrides: BlockOverrides) -> Self {
52 self.block_overrides = Some(overrides);
53 self
54 }
55
56 pub fn call(mut self, call: TxReq) -> Self {
58 self.calls.push(call);
59 self
60 }
61
62 pub fn extend_calls(mut self, calls: impl IntoIterator<Item = TxReq>) -> Self {
64 self.calls.extend(calls);
65 self
66 }
67
68 pub fn block_number_override(&self) -> Option<U256> {
70 self.block_overrides.as_ref().and_then(|overrides| overrides.number)
71 }
72}
73
74#[derive(Clone, Debug)]
76#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
77#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
78pub struct SimulatedBlock<B = Block> {
79 #[cfg_attr(feature = "serde", serde(flatten))]
81 pub inner: B,
82 pub calls: Vec<SimCallResult>,
84}
85
86#[derive(Clone, Debug)]
89#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
90#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
91pub struct SimCallResult {
92 pub return_data: Bytes,
94 #[cfg_attr(feature = "serde", serde(default))]
96 pub logs: Vec<Log>,
97 #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))]
99 pub gas_used: u64,
100 #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))]
102 pub status: bool,
103 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))]
105 pub error: Option<SimulateError>,
106}
107
108#[derive(Clone, Debug)]
113#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
114#[cfg_attr(
115 feature = "serde",
116 serde(
117 rename_all = "camelCase",
118 bound(
119 deserialize = "TxReq: serde::Deserialize<'de>",
120 serialize = "TxReq: serde::Serialize"
121 )
122 )
123)]
124pub struct SimulatePayload<TxReq = TransactionRequest> {
125 #[cfg_attr(feature = "serde", serde(default))]
127 pub block_state_calls: Vec<SimBlock<TxReq>>,
128 #[cfg_attr(feature = "serde", serde(default))]
130 pub trace_transfers: bool,
131 #[cfg_attr(feature = "serde", serde(default))]
133 pub validation: bool,
134 #[cfg_attr(feature = "serde", serde(default))]
136 pub return_full_transactions: bool,
137}
138
139impl<TxReq> Default for SimulatePayload<TxReq> {
140 fn default() -> Self {
141 Self {
142 block_state_calls: Vec::new(),
143 trace_transfers: false,
144 validation: false,
145 return_full_transactions: false,
146 }
147 }
148}
149
150impl<TxReq> SimulatePayload<TxReq> {
151 pub fn extend(mut self, block: SimBlock<TxReq>) -> Self {
153 self.block_state_calls.push(block);
154 self
155 }
156
157 pub fn extend_blocks(mut self, blocks: impl IntoIterator<Item = SimBlock<TxReq>>) -> Self {
159 self.block_state_calls.extend(blocks);
160 self
161 }
162
163 pub const fn with_trace_transfers(mut self) -> Self {
165 self.trace_transfers = true;
166 self
167 }
168
169 pub const fn with_validation(mut self) -> Self {
171 self.validation = true;
172 self
173 }
174
175 pub const fn with_full_transactions(mut self) -> Self {
177 self.return_full_transactions = true;
178 self
179 }
180}
181
182#[derive(Clone, Debug)]
184#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
185#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
186pub struct SimulateError {
187 pub code: i32,
191 pub message: String,
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198 use alloy_primitives::{Address, TxKind};
199 #[cfg(feature = "serde")]
200 use serde_json::json;
201 use similar_asserts::assert_eq;
202
203 #[test]
204 #[cfg(feature = "serde")]
205 fn test_eth_simulate_v1_account_not_precompile() {
206 let request_json = json!({
207 "jsonrpc": "2.0",
208 "id": 1,
209 "method": "eth_simulateV1",
210 "params": [{
211 "blockStateCalls": [
212 {
213 "blockOverrides": {},
214 "stateOverrides": {
215 "0xc000000000000000000000000000000000000000": {
216 "nonce": "0x5"
217 }
218 },
219 "calls": []
220 },
221 {
222 "blockOverrides": {},
223 "stateOverrides": {
224 "0xc000000000000000000000000000000000000000": {
225 "code": "0x600035600055"
226 }
227 },
228 "calls": [
229 {
230 "from": "0xc000000000000000000000000000000000000000",
231 "to": "0xc000000000000000000000000000000000000000",
232 "nonce": "0x0"
233 },
234 {
235 "from": "0xc100000000000000000000000000000000000000",
236 "to": "0xc100000000000000000000000000000000000000",
237 "nonce": "0x5"
238 }
239 ]
240 }
241 ],
242 "traceTransfers": false,
243 "validation": true,
244 "returnFullTransactions": false
245 }, "latest"]
246 });
247
248 let sim_opts: SimulatePayload =
249 serde_json::from_value(request_json["params"][0].clone()).unwrap();
250
251 let address_1: Address = "0xc000000000000000000000000000000000000000".parse().unwrap();
252 let address_2: Address = "0xc100000000000000000000000000000000000000".parse().unwrap();
253
254 assert!(sim_opts.validation);
255 assert_eq!(sim_opts.block_state_calls.len(), 2);
256
257 let block_state_call_1 = &sim_opts.block_state_calls[0];
258 assert!(block_state_call_1.state_overrides.as_ref().unwrap().contains_key(&address_1));
259 assert_eq!(
260 block_state_call_1
261 .state_overrides
262 .as_ref()
263 .unwrap()
264 .get(&address_1)
265 .unwrap()
266 .nonce
267 .unwrap(),
268 5
269 );
270
271 let block_state_call_2 = &sim_opts.block_state_calls[1];
272 assert!(block_state_call_2.state_overrides.as_ref().unwrap().contains_key(&address_1));
273
274 assert_eq!(block_state_call_2.calls.len(), 2);
275 assert_eq!(block_state_call_2.calls[0].from.unwrap(), address_1);
276 assert_eq!(block_state_call_2.calls[0].to.unwrap(), TxKind::Call(address_1));
277 assert_eq!(block_state_call_2.calls[0].nonce.unwrap(), 0);
278 assert_eq!(block_state_call_2.calls[1].from.unwrap(), address_2);
279 assert_eq!(block_state_call_2.calls[1].to.unwrap(), TxKind::Call(address_2));
280 assert_eq!(block_state_call_2.calls[1].nonce.unwrap(), 5);
281 }
282}