Skip to content

Commit

Permalink
fix: handle rpc error response (#7229)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse authored Feb 24, 2024
1 parent 05d89ca commit 43b4e23
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 82 deletions.
2 changes: 1 addition & 1 deletion crates/anvil/server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub trait RpcHandler: Clone + Send + Sync + 'static {
/// **Note**: override this function if the expected `Request` deviates from `{ "method" :
/// "<name>", "params": "<params>" }`
async fn on_call(&self, call: RpcMethodCall) -> RpcResponse {
trace!(target: "rpc", id = ?call.id , method = ?call.method, "received method call");
trace!(target: "rpc", id = ?call.id , method = ?call.method, params = ?call.params, "received method call");
let RpcMethodCall { method, params, id, .. } = call;

let params: serde_json::Value = params.into();
Expand Down
49 changes: 10 additions & 39 deletions crates/anvil/src/eth/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,10 +602,7 @@ impl EthApi {
if let BlockRequest::Number(number) = block_request {
if let Some(fork) = self.get_fork() {
if fork.predates_fork(number) {
return fork
.get_balance(address, number)
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.get_balance(address, number).await?)
}
}
}
Expand All @@ -630,9 +627,7 @@ impl EthApi {
if let Some(fork) = self.get_fork() {
if fork.predates_fork(number) {
return Ok(B256::from(
fork.storage_at(address, index, Some(BlockNumber::Number(number)))
.await
.map_err(|_| BlockchainError::DataUnavailable)?,
fork.storage_at(address, index, Some(BlockNumber::Number(number))).await?,
));
}
}
Expand Down Expand Up @@ -764,10 +759,7 @@ impl EthApi {
if let BlockRequest::Number(number) = block_request {
if let Some(fork) = self.get_fork() {
if fork.predates_fork(number) {
return fork
.get_code(address, number)
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.get_code(address, number).await?)
}
}
}
Expand All @@ -792,10 +784,7 @@ impl EthApi {
if let BlockRequest::Number(number) = block_request {
if let Some(fork) = self.get_fork() {
if fork.predates_fork_inclusive(number) {
return fork
.get_proof(address, keys, Some(number.into()))
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.get_proof(address, keys, Some(number.into())).await?)
}
}
}
Expand Down Expand Up @@ -990,10 +979,7 @@ impl EthApi {
"not available on past forked blocks".to_string(),
));
}
return fork
.call(&request, Some(number.into()))
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.call(&request, Some(number.into())).await?)
}
}
}
Expand Down Expand Up @@ -1040,10 +1026,7 @@ impl EthApi {
if let BlockRequest::Number(number) = block_request {
if let Some(fork) = self.get_fork() {
if fork.predates_fork(number) {
return fork
.create_access_list(&request, Some(number.into()))
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.create_access_list(&request, Some(number.into())).await?)
}
}
}
Expand Down Expand Up @@ -1185,10 +1168,7 @@ impl EthApi {
self.backend.ensure_block_number(Some(BlockId::Hash(block_hash.into()))).await?;
if let Some(fork) = self.get_fork() {
if fork.predates_fork_inclusive(number) {
return fork
.uncle_by_block_hash_and_index(block_hash, idx.into())
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.uncle_by_block_hash_and_index(block_hash, idx.into()).await?)
}
}
// It's impossible to have uncles outside of fork mode
Expand All @@ -1207,10 +1187,7 @@ impl EthApi {
let number = self.backend.ensure_block_number(Some(BlockId::Number(block_number))).await?;
if let Some(fork) = self.get_fork() {
if fork.predates_fork_inclusive(number) {
return fork
.uncle_by_block_number_and_index(number, idx.into())
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.uncle_by_block_number_and_index(number, idx.into()).await?);
}
}
// It's impossible to have uncles outside of fork mode
Expand Down Expand Up @@ -2174,10 +2151,7 @@ impl EthApi {
"not available on past forked blocks".to_string(),
));
}
return fork
.estimate_gas(&request, Some(number.into()))
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.estimate_gas(&request, Some(number.into())).await?)
}
}
}
Expand Down Expand Up @@ -2556,10 +2530,7 @@ impl EthApi {
if let BlockRequest::Number(number) = block_request {
if let Some(fork) = self.get_fork() {
if fork.predates_fork_inclusive(number) {
return fork
.get_nonce(address, number)
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.get_nonce(address, number).await?);
}
}
}
Expand Down
50 changes: 12 additions & 38 deletions crates/anvil/src/eth/backend/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,8 +393,7 @@ impl Backend {
let fork_block_number = fork.block_number();
let fork_block = fork
.block_by_number(fork_block_number)
.await
.map_err(|_| BlockchainError::DataUnavailable)?
.await?
.ok_or(BlockchainError::BlockNotFound)?;
// update all settings related to the forked block
{
Expand Down Expand Up @@ -1248,7 +1247,7 @@ impl Backend {
}

if let Some(fork) = self.get_fork() {
return fork.logs(&filter).await.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.logs(&filter).await?);
}

Ok(Vec::new())
Expand Down Expand Up @@ -1335,8 +1334,7 @@ impl Backend {
if fork.predates_fork(from) {
// this data is only available on the forked client
let filter = filter.clone().from_block(from).to_block(to_on_fork);
all_logs =
fork.logs(&filter).await.map_err(|_| BlockchainError::DataUnavailable)?;
all_logs = fork.logs(&filter).await?;

// update the range
from = fork.block_number() + 1;
Expand Down Expand Up @@ -1379,7 +1377,7 @@ impl Backend {
}

if let Some(fork) = self.get_fork() {
return fork.block_by_hash(hash).await.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.block_by_hash(hash).await?);
}

Ok(None)
Expand All @@ -1395,10 +1393,7 @@ impl Backend {
}

if let Some(fork) = self.get_fork() {
return fork
.block_by_hash_full(hash)
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.block_by_hash_full(hash).await?)
}

Ok(None)
Expand Down Expand Up @@ -1452,10 +1447,7 @@ impl Backend {
if let Some(fork) = self.get_fork() {
let number = self.convert_block_number(Some(number));
if fork.predates_fork_inclusive(number) {
return fork
.block_by_number(number)
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.block_by_number(number).await?)
}
}

Expand All @@ -1474,10 +1466,7 @@ impl Backend {
if let Some(fork) = self.get_fork() {
let number = self.convert_block_number(Some(number));
if fork.predates_fork_inclusive(number) {
return fork
.block_by_number_full(number)
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.block_by_number_full(number).await?)
}
}

Expand Down Expand Up @@ -1891,10 +1880,7 @@ impl Backend {
}

if let Some(fork) = self.get_fork() {
return fork.debug_trace_transaction(hash, opts).await.map_err(|err| {
warn!(target: "backend", "error delegating debug_traceTransaction: {:?}", err);
BlockchainError::DataUnavailable
})
return Ok(fork.debug_trace_transaction(hash, opts).await?)
}

Ok(GethTrace::Default(Default::default()))
Expand All @@ -1920,10 +1906,7 @@ impl Backend {

if let Some(fork) = self.get_fork() {
if fork.predates_fork(number) {
return fork.trace_block(number).await.map_err(|err| {
warn!(target: "backend", "error delegating trace_block: {:?}", err);
BlockchainError::DataUnavailable
})
return Ok(fork.trace_block(number).await?)
}
}

Expand All @@ -1939,10 +1922,7 @@ impl Backend {
}

if let Some(fork) = self.get_fork() {
let receipt = fork
.transaction_receipt(hash)
.await
.map_err(|_| BlockchainError::DataUnavailable)?;
let receipt = fork.transaction_receipt(hash).await?;
let number = self.convert_block_number(
receipt
.clone()
Expand Down Expand Up @@ -2116,10 +2096,7 @@ impl Backend {
if let Some(fork) = self.get_fork() {
let number = self.convert_block_number(Some(number));
if fork.predates_fork(number) {
return fork
.transaction_by_block_number_and_index(number, index.into())
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.transaction_by_block_number_and_index(number, index.into()).await?)
}
}

Expand All @@ -2136,10 +2113,7 @@ impl Backend {
}

if let Some(fork) = self.get_fork() {
return fork
.transaction_by_block_hash_and_index(hash, index.into())
.await
.map_err(|_| BlockchainError::DataUnavailable);
return Ok(fork.transaction_by_block_hash_and_index(hash, index.into()).await?)
}

Ok(None)
Expand Down
11 changes: 9 additions & 2 deletions crates/anvil/src/eth/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,15 @@ impl<T: Serialize> ToRpcResponseResult for Result<T> {
"Invalid input: `max_priority_fee_per_gas` greater than `max_fee_per_gas`",
),
BlockchainError::AlloyForkProvider(err) => {
error!(%err, "alloy fork provider error");
RpcError::internal_error_with(format!("Fork Error: {err:?}"))
error!(target: "backend", %err, "fork provider error");
match err {
TransportError::ErrorResp(err) => RpcError {
code: ErrorCode::from(err.code),
message: err.message.into(),
data: err.data.and_then(|data| serde_json::to_value(data).ok()),
},
err => RpcError::internal_error_with(format!("Fork Error: {err:?}")),
}
}
err @ BlockchainError::EvmError(_) => {
RpcError::internal_error_with(err.to_string())
Expand Down
30 changes: 28 additions & 2 deletions crates/anvil/tests/it/fork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ use crate::{
abi::*,
utils::{self, ethers_http_provider},
};
use alloy_primitives::U256 as rU256;
use alloy_primitives::{address, U256 as rU256};
use alloy_providers::provider::TempProvider;
use alloy_rpc_types::{request::TransactionRequest as CallRequest, BlockNumberOrTag};
use alloy_rpc_types::{
request::{TransactionInput, TransactionRequest as CallRequest},
BlockNumberOrTag,
};
use alloy_signer::Signer as AlloySigner;
use anvil::{eth::EthApi, spawn, NodeConfig, NodeHandle};
use anvil_core::types::Forking;
Expand Down Expand Up @@ -1119,3 +1122,26 @@ async fn test_arbitrum_fork_dev_balance() {
assert_eq!(balance, rU256::from(100000000000000000000u128));
}
}

// <https://github.com/foundry-rs/foundry/issues/7023>
#[tokio::test(flavor = "multi_thread")]
async fn test_fork_execution_reverted() {
let target = 16681681u64;
let (api, _handle) = spawn(fork_config().with_fork_block_number(Some(target + 1))).await;

let resp = api
.call(
CallRequest {
to: Some(address!("Fd6CC4F251eaE6d02f9F7B41D1e80464D3d2F377")),
input: TransactionInput::new("0x8f283b3c".as_bytes().into()),
..Default::default()
},
Some(target.into()),
None,
)
.await;

assert!(resp.is_err());
let err = resp.unwrap_err();
assert!(err.to_string().contains("execution reverted"));
}

0 comments on commit 43b4e23

Please sign in to comment.