Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle rpc error response #7229

Merged
merged 1 commit into from
Feb 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"));
}
Loading