feat(revm): use GenericRevertReason type (#5854)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
PA
2023-12-27 13:40:37 +01:00
committed by GitHub
parent fa2fd0d50b
commit fba9a59802
2 changed files with 46 additions and 16 deletions

View File

@ -1,9 +1,9 @@
//! Types for representing call trace items.
use crate::tracing::{config::TraceStyle, utils::convert_memory};
use crate::tracing::{config::TraceStyle, utils, utils::convert_memory};
pub use alloy_primitives::Log;
use alloy_primitives::{Address, Bytes, U256, U64};
use alloy_sol_types::decode_revert_reason;
use reth_rpc_types::trace::{
geth::{CallFrame, CallLogFrame, GethDefaultTracingOptions, StructLog},
parity::{
@ -347,9 +347,7 @@ impl CallTraceNode {
// we need to populate error and revert reason
if !self.trace.success {
// decode the revert reason, but don't include it if it's empty
call_frame.revert_reason = decode_revert_reason(self.trace.output.as_ref())
.filter(|reason| !reason.is_empty());
call_frame.revert_reason = utils::maybe_revert_reason(self.trace.output.as_ref());
// Note: the call tracer mimics parity's trace transaction and geth maps errors to parity style error messages, <https://github.com/ethereum/go-ethereum/blob/34d507215951fb3f4a5983b65e127577989a6db8/eth/tracers/native/call_flat.go#L39-L55>
call_frame.error = self.trace.as_error_msg(TraceStyle::Parity);
@ -679,14 +677,3 @@ impl AsRef<[u8]> for RecordedMemory {
self.as_bytes()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn decode_empty_revert() {
let reason = decode_revert_reason("".as_bytes());
assert_eq!(reason, Some("".to_string()));
}
}

View File

@ -1,6 +1,7 @@
//! Util functions for revm related ops
use alloy_primitives::{hex, Address, Bytes, B256};
use alloy_sol_types::{ContractError, GenericRevertReason};
use revm::{
interpreter::CreateInputs,
primitives::{CreateScheme, SpecId, KECCAK_EMPTY},
@ -58,3 +59,45 @@ pub(crate) fn load_account_code<DB: DatabaseRef>(
})
.map(Into::into)
}
/// Returns a non empty revert reason if the output is a revert/error.
#[inline]
pub(crate) fn maybe_revert_reason(output: &[u8]) -> Option<String> {
let reason = match GenericRevertReason::decode(output)? {
GenericRevertReason::ContractError(err) => {
match err {
ContractError::Revert(revert) => {
// return the raw revert reason and don't use the revert's display message
revert.reason
}
err => err.to_string(),
}
}
GenericRevertReason::RawString(err) => err,
};
if reason.is_empty() {
None
} else {
Some(reason)
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloy_sol_types::{GenericContractError, SolInterface};
#[test]
fn decode_empty_revert() {
let reason = GenericRevertReason::decode("".as_bytes()).map(|x| x.to_string());
assert_eq!(reason, Some("".to_string()));
}
#[test]
fn decode_revert_reason() {
let err = GenericContractError::Revert("my revert".into());
let encoded = err.abi_encode();
let reason = maybe_revert_reason(&encoded).unwrap();
assert_eq!(reason, "my revert");
}
}