ethers_providers/toolbox/
call_raw.rs1use crate::{utils::PinBoxFut, JsonRpcClient, Provider, ProviderError};
4use ethers_core::{
5 types::{transaction::eip2718::TypedTransaction, BlockId, BlockNumber, Bytes},
6 utils,
7};
8use pin_project::pin_project;
9use serde::{ser::SerializeTuple, Serialize};
10use std::{
11 fmt,
12 future::Future,
13 pin::Pin,
14 task::{Context, Poll},
15};
16
17pub use ethers_core::types::spoof;
18
19pub trait RawCall<'a> {
21 fn block(self, id: BlockId) -> Self;
23 fn state(self, state: &'a spoof::State) -> Self;
26
27 fn map<F>(self, f: F) -> Map<Self, F>
29 where
30 Self: Sized,
31 {
32 Map::new(self, f)
33 }
34}
35
36#[must_use = "call_raw::CallBuilder does nothing unless you `.await` or poll it"]
41pub enum CallBuilder<'a, P> {
42 Build(Caller<'a, P>),
44 Wait(PinBoxFut<'a, Bytes>),
47}
48
49impl<P: fmt::Debug> fmt::Debug for CallBuilder<'_, P> {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 match self {
52 Self::Build(call) => f.debug_tuple("Build").field(call).finish(),
53 Self::Wait(_) => f.debug_tuple("Wait").field(&"< Future >").finish(),
54 }
55 }
56}
57
58impl<'a, P> CallBuilder<'a, P> {
59 pub fn new(provider: &'a Provider<P>, tx: &'a TypedTransaction) -> Self {
61 Self::Build(Caller::new(provider, tx))
62 }
63
64 pub fn map_input<F>(self, f: F) -> Self
66 where
67 F: FnOnce(&mut Caller<'a, P>),
68 {
69 match self {
70 Self::Build(mut call) => {
71 f(&mut call);
72 Self::Build(call)
73 }
74 wait => wait,
75 }
76 }
77
78 pub fn unwrap(self) -> Caller<'a, P> {
81 match self {
82 Self::Build(b) => b,
83 _ => panic!("CallBuilder::unwrap on a Wait value"),
84 }
85 }
86}
87
88impl<'a, P> RawCall<'a> for CallBuilder<'a, P> {
89 fn block(self, id: BlockId) -> Self {
91 self.map_input(|call| call.input.block = Some(id))
92 }
93 fn state(self, state: &'a spoof::State) -> Self {
96 self.map_input(|call| call.input.state = Some(state))
97 }
98}
99
100impl<'a, P: JsonRpcClient> Future for CallBuilder<'a, P> {
101 type Output = Result<Bytes, ProviderError>;
102
103 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
104 let pin = self.get_mut();
105 loop {
106 match pin {
107 CallBuilder::Build(ref call) => {
108 let fut = Box::pin(call.execute());
109 *pin = CallBuilder::Wait(fut);
110 }
111 CallBuilder::Wait(ref mut fut) => return fut.as_mut().poll(cx),
112 }
113 }
114 }
115}
116
117#[derive(Clone, Debug)]
120pub struct Caller<'a, P> {
121 provider: &'a Provider<P>,
122 input: CallInput<'a>,
123}
124
125impl<'a, P> Caller<'a, P> {
126 pub fn new(provider: &'a Provider<P>, tx: &'a TypedTransaction) -> Self {
128 Self { provider, input: CallInput::new(tx) }
129 }
130}
131impl<'a, P: JsonRpcClient> Caller<'a, P> {
132 fn execute(&self) -> impl Future<Output = Result<Bytes, ProviderError>> + 'a {
135 self.provider.request("eth_call", utils::serialize(&self.input))
136 }
137}
138
139#[derive(Clone, Debug, PartialEq, Eq)]
141struct CallInput<'a> {
142 tx: &'a TypedTransaction,
143 block: Option<BlockId>,
144 state: Option<&'a spoof::State>,
145}
146
147impl<'a> CallInput<'a> {
148 fn new(tx: &'a TypedTransaction) -> Self {
149 Self { tx, block: None, state: None }
150 }
151}
152
153impl<'a> Serialize for CallInput<'a> {
154 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
155 where
156 S: serde::ser::Serializer,
157 {
158 let len = 2 + self.state.is_some() as usize;
159
160 let mut tup = serializer.serialize_tuple(len)?;
161 tup.serialize_element(self.tx)?;
162
163 let block = self.block.unwrap_or_else(|| BlockNumber::Latest.into());
164 tup.serialize_element(&block)?;
165
166 if let Some(state) = self.state {
167 tup.serialize_element(state)?;
168 }
169 tup.end()
170 }
171}
172
173#[must_use = "call_raw::Map does nothing unless you `.await` or poll it"]
179#[derive(Clone)]
180#[pin_project]
181pub struct Map<T, F> {
182 #[pin]
183 inner: T,
184 f: F,
185}
186
187impl<T: fmt::Debug, F> fmt::Debug for Map<T, F> {
188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189 f.debug_struct("Map").field("inner", &self.inner).finish()
190 }
191}
192
193impl<T, F> Map<T, F> {
194 pub fn new(inner: T, f: F) -> Self {
196 Self { inner, f }
197 }
198}
199
200impl<'a, T, F> RawCall<'a> for Map<T, F>
201where
202 T: RawCall<'a>,
203{
204 fn block(self, id: BlockId) -> Self {
206 Self { inner: self.inner.block(id), f: self.f }
207 }
208
209 fn state(self, state: &'a spoof::State) -> Self {
212 Self { inner: self.inner.state(state), f: self.f }
213 }
214}
215
216impl<T, F, Y> Future for Map<T, F>
217where
218 T: Future,
219 F: FnMut(T::Output) -> Y,
220{
221 type Output = Y;
222
223 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
224 let pin = self.project();
225 let x = futures_util::ready!(pin.inner.poll(cx));
226 Poll::Ready((pin.f)(x))
227 }
228}
229
230#[cfg(test)]
231mod tests {
232 use super::*;
233 use crate::Http;
234 use ethers_core::{
235 types::{Address, TransactionRequest, H256, U256},
236 utils::{get_contract_address, keccak256, parse_ether, Geth},
237 };
238 use serde::Deserialize;
239
240 #[derive(Debug, Deserialize)]
242 struct CallInputOwned(
243 TypedTransaction,
244 Option<BlockId>,
245 #[serde(default)] Option<spoof::State>,
246 );
247 impl<'a> From<&'a CallInputOwned> for CallInput<'a> {
248 fn from(src: &'a CallInputOwned) -> Self {
249 Self { tx: &src.0, block: src.1, state: src.2.as_ref() }
250 }
251 }
252
253 fn test_encode<P>(call: CallBuilder<P>) {
255 let input = call.unwrap().input;
256 let ser = utils::serialize(&input).to_string();
257 let de: CallInputOwned = serde_json::from_str(&ser).unwrap();
258 let de = CallInput::from(&de);
259
260 assert_eq!(input.tx, de.tx);
261 assert_eq!(input.state, de.state);
262
263 let block = input.block.or_else(|| Some(BlockNumber::Latest.into()));
264 assert_eq!(block, de.block);
265 }
266
267 #[test]
268 fn test_serialize() {
269 let adr1: Address = "0x6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap();
270 let adr2: Address = "0x295a70b2de5e3953354a6a8344e616ed314d7251".parse().unwrap();
271 let k1 = utils::keccak256("foo").into();
272 let v1 = H256::from_low_u64_be(534);
273 let k2 = utils::keccak256("bar").into();
274 let v2 = H256::from_low_u64_be(8675309);
275
276 let tx = TypedTransaction::default();
277 let (provider, _) = Provider::mocked();
278
279 let call = provider.call_raw(&tx);
280 test_encode(call);
281
282 let mut state = spoof::state();
283 state.account(adr1).nonce(1.into()).balance(2.into()).store(k1, v1).store(k2, v2);
284 let call = provider.call_raw(&tx).block(100.into()).state(&state);
285 test_encode(call);
286
287 let mut state = spoof::state();
288 state.account(adr1).nonce(1.into());
289 state.account(adr2).nonce(7.into());
290 let call = provider.call_raw(&tx).state(&state);
291 test_encode(call);
292
293 let mut state = spoof::state();
295 state.account(adr1);
296 let call = provider.call_raw(&tx).state(&state);
297 test_encode(call);
298 }
299
300 #[tokio::test]
301 async fn test_state_overrides() {
302 let geth = Geth::new().spawn();
303 let provider = Provider::<Http>::try_from(geth.endpoint()).unwrap();
304
305 let adr1: Address = "0x6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap();
306 let adr2: Address = "0x295a70b2de5e3953354a6a8344e616ed314d7251".parse().unwrap();
307 let pay_amt = parse_ether(1u64).unwrap();
308
309 let tx = TransactionRequest::pay(adr2, pay_amt).from(adr1).into();
311
312 let state = spoof::balance(adr1, pay_amt * 2);
314 provider.call_raw(&tx).state(&state).await.expect("eth_call success");
315
316 const RETURN_BALANCE: &str = "0x4760005260206000f3";
318 let bytecode = RETURN_BALANCE.parse().unwrap();
319 let balance = 100.into();
320
321 let tx = TransactionRequest::default().to(adr2).into();
322 let mut state = spoof::state();
323 state.account(adr2).code(bytecode).balance(balance);
324
325 let bytes = provider.call_raw(&tx).state(&state).await.unwrap();
327 assert_eq!(U256::from_big_endian(bytes.as_ref()), balance);
328
329 const DEPLOY_CONTRACT: &str = "0x6000600052602060006000f060005260206000f3";
331 let bytecode = DEPLOY_CONTRACT.parse().unwrap();
332 let nonce = 17.into();
333
334 let mut state = spoof::state();
335 state.account(adr2).code(bytecode).nonce(nonce);
336
337 let bytes = provider.call_raw(&tx).state(&state).await.unwrap();
339 let deployed = Address::from_slice(&bytes.as_ref()[12..]);
340 assert_eq!(deployed, get_contract_address(adr2, nonce.as_u64()));
341
342 const RETURN_STORAGE: &str = "0x60015460005260206000f3";
344 let bytecode = RETURN_STORAGE.parse().unwrap();
345 let slot = H256::from_low_u64_be(1);
346 let val = keccak256("foo").into();
347
348 let mut state = spoof::state();
349 state.account(adr2).code(bytecode).store(slot, val);
350
351 let bytes = provider.call_raw(&tx).state(&state).await.unwrap();
353 assert_eq!(H256::from_slice(bytes.as_ref()), val);
354 }
355}