diff --git a/crates/rpc/rpc-api/src/otterscan.rs b/crates/rpc/rpc-api/src/otterscan.rs index 110d922f318e..2593a114207f 100644 --- a/crates/rpc/rpc-api/src/otterscan.rs +++ b/crates/rpc/rpc-api/src/otterscan.rs @@ -1,5 +1,5 @@ use jsonrpsee::{core::RpcResult, proc_macros::rpc}; -use reth_primitives::{Address, BlockId, BlockNumberOrTag, TxHash, B256}; +use reth_primitives::{Address, BlockId, BlockNumberOrTag, Bytes, TxHash, B256}; use reth_rpc_types::{ BlockDetails, ContractCreator, InternalOperation, OtsBlockTransactions, TraceEntry, Transaction, TransactionsWithReceipts, @@ -25,7 +25,7 @@ pub trait Otterscan { /// Given a transaction hash, returns its raw revert reason. #[method(name = "getTransactionError")] - async fn get_transaction_error(&self, tx_hash: TxHash) -> RpcResult; + async fn get_transaction_error(&self, tx_hash: TxHash) -> RpcResult>; /// Extract all variations of calls, contract creation and self-destructs and returns a call /// tree. diff --git a/crates/rpc/rpc-builder/tests/it/http.rs b/crates/rpc/rpc-builder/tests/it/http.rs index 3429087191e5..fa1e48a380c2 100644 --- a/crates/rpc/rpc-builder/tests/it/http.rs +++ b/crates/rpc/rpc-builder/tests/it/http.rs @@ -300,9 +300,9 @@ where assert!(is_unimplemented( OtterscanClient::get_internal_operations(client, tx_hash).await.err().unwrap() )); - assert!(is_unimplemented( - OtterscanClient::get_transaction_error(client, tx_hash).await.err().unwrap() - )); + + OtterscanClient::get_transaction_error(client, tx_hash).await.unwrap(); + assert!(is_unimplemented( OtterscanClient::trace_transaction(client, tx_hash).await.err().unwrap() )); diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs index fa6f50bdafa4..550cee8cadaf 100644 --- a/crates/rpc/rpc/src/otterscan.rs +++ b/crates/rpc/rpc/src/otterscan.rs @@ -1,4 +1,5 @@ -use crate::result::internal_rpc_err; +use crate::{eth::EthTransactions, result::internal_rpc_err}; +use alloy_primitives::Bytes; use async_trait::async_trait; use jsonrpsee::core::RpcResult; use reth_primitives::{Address, BlockId, BlockNumberOrTag, TxHash, B256}; @@ -7,6 +8,8 @@ use reth_rpc_types::{ BlockDetails, ContractCreator, InternalOperation, OtsBlockTransactions, TraceEntry, Transaction, TransactionsWithReceipts, }; +use revm::inspectors::NoOpInspector; +use revm_primitives::ExecutionResult; const API_LEVEL: u64 = 8; @@ -26,7 +29,7 @@ impl OtterscanApi { #[async_trait] impl OtterscanServer for OtterscanApi where - Eth: EthApiServer, + Eth: EthApiServer + EthTransactions, { /// Handler for `ots_hasCode` async fn has_code(&self, address: Address, block_number: Option) -> RpcResult { @@ -44,8 +47,20 @@ where } /// Handler for `ots_getTransactionError` - async fn get_transaction_error(&self, _tx_hash: TxHash) -> RpcResult { - Err(internal_rpc_err("unimplemented")) + async fn get_transaction_error(&self, tx_hash: TxHash) -> RpcResult> { + let maybe_revert = self + .eth + .spawn_trace_transaction_in_block_with_inspector( + tx_hash, + NoOpInspector, + |_tx_info, _inspector, res, _| match res.result { + ExecutionResult::Revert { output, .. } => Ok(Some(output)), + _ => Ok(None), + }, + ) + .await + .map(Option::flatten)?; + Ok(maybe_revert) } /// Handler for `ots_traceTransaction`