From 2ca6c9bd3ef3e9212ce0244a8020f7e747f714bd Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Fri, 27 Oct 2023 17:16:32 +0900 Subject: [PATCH 1/5] fix: properly parse functions in their usual form --- crates/common/src/abi.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/common/src/abi.rs b/crates/common/src/abi.rs index abfee8d06c5c..80a0f7af004d 100644 --- a/crates/common/src/abi.rs +++ b/crates/common/src/abi.rs @@ -1,6 +1,6 @@ //! ABI related helper functions use alloy_dyn_abi::{DynSolType, DynSolValue, FunctionExt, JsonAbiExt}; -use alloy_json_abi::{Event, Function}; +use alloy_json_abi::{Event, Function, AbiItem}; use alloy_primitives::{hex, Address, Log, U256}; use ethers_core::types::Chain; use eyre::{ContextCompat, Result}; @@ -172,13 +172,14 @@ impl<'a> IntoFunction for &'a str { /// Given a function signature string, it tries to parse it as a `Function` pub fn get_func(sig: &str) -> Result { - Ok(match Function::parse(sig) { - Ok(func) => func, - Err(err) => { - // we return the `Function` parse error as this case is more likely - return Err(err.into()) + let item = match AbiItem::parse(sig) { + Ok(item) => match item { + AbiItem::Function(func) => func, + _ => return Err(eyre::eyre!("Expected function, got {:?}", item)), } - }) + Err(e) => return Err(e.into()) + }; + Ok(item.into_owned().to_owned()) } /// Given an event signature string, it tries to parse it as a `Event` From e95ba1ebd20b7a5539864632bdef2516cb7a8069 Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Fri, 27 Oct 2023 17:19:29 +0900 Subject: [PATCH 2/5] chore: fmt --- crates/common/src/abi.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/common/src/abi.rs b/crates/common/src/abi.rs index 80a0f7af004d..7ce0f6bf158a 100644 --- a/crates/common/src/abi.rs +++ b/crates/common/src/abi.rs @@ -1,6 +1,6 @@ //! ABI related helper functions use alloy_dyn_abi::{DynSolType, DynSolValue, FunctionExt, JsonAbiExt}; -use alloy_json_abi::{Event, Function, AbiItem}; +use alloy_json_abi::{AbiItem, Event, Function}; use alloy_primitives::{hex, Address, Log, U256}; use ethers_core::types::Chain; use eyre::{ContextCompat, Result}; @@ -176,8 +176,8 @@ pub fn get_func(sig: &str) -> Result { Ok(item) => match item { AbiItem::Function(func) => func, _ => return Err(eyre::eyre!("Expected function, got {:?}", item)), - } - Err(e) => return Err(e.into()) + }, + Err(e) => return Err(e.into()), }; Ok(item.into_owned().to_owned()) } From 24b2126e29f0a0989ecb500f1a13788b44522b62 Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Fri, 27 Oct 2023 17:39:12 +0900 Subject: [PATCH 3/5] chore: add test --- crates/common/src/abi.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/common/src/abi.rs b/crates/common/src/abi.rs index 7ce0f6bf158a..665fc269b47e 100644 --- a/crates/common/src/abi.rs +++ b/crates/common/src/abi.rs @@ -282,6 +282,17 @@ mod tests { use alloy_dyn_abi::EventExt; use alloy_primitives::B256; + #[test] + fn test_get_func() { + let func = get_func("function foo(uint256 a, uint256 b) returns (uint256)"); + assert!(func.is_ok()); + let func = func.unwrap(); + assert_eq!(func.name, "foo"); + assert_eq!(func.inputs.len(), 2); + assert_eq!(func.inputs[0].ty, "uint256"); + assert_eq!(func.inputs[1].ty, "uint256"); + } + #[test] fn parse_hex_uint_tokens() { let param = DynSolType::Uint(256); From d23e294aa76211b6e66298e59b7f0d8298a22733 Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Fri, 27 Oct 2023 17:44:02 +0900 Subject: [PATCH 4/5] chore: only fallback to human-readable abi if necessary --- crates/common/src/abi.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/crates/common/src/abi.rs b/crates/common/src/abi.rs index 665fc269b47e..c3d96962895b 100644 --- a/crates/common/src/abi.rs +++ b/crates/common/src/abi.rs @@ -172,14 +172,19 @@ impl<'a> IntoFunction for &'a str { /// Given a function signature string, it tries to parse it as a `Function` pub fn get_func(sig: &str) -> Result { - let item = match AbiItem::parse(sig) { - Ok(item) => match item { - AbiItem::Function(func) => func, - _ => return Err(eyre::eyre!("Expected function, got {:?}", item)), - }, - Err(e) => return Err(e.into()), - }; - Ok(item.into_owned().to_owned()) + if let Ok(func) = Function::parse(sig) { + Ok(func) + } else { + // Try to parse as human readable ABI. + let item = match AbiItem::parse(sig) { + Ok(item) => match item { + AbiItem::Function(func) => func, + _ => return Err(eyre::eyre!("Expected function, got {:?}", item)), + }, + Err(e) => return Err(e.into()), + }; + Ok(item.into_owned().to_owned()) + } } /// Given an event signature string, it tries to parse it as a `Event` From d0dfd9940c51c33e2c76d1ecf56d9ecf40342787 Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Fri, 27 Oct 2023 17:52:50 +0900 Subject: [PATCH 5/5] chore: add another function for test --- crates/common/src/abi.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/common/src/abi.rs b/crates/common/src/abi.rs index c3d96962895b..c7917f761bc3 100644 --- a/crates/common/src/abi.rs +++ b/crates/common/src/abi.rs @@ -296,6 +296,16 @@ mod tests { assert_eq!(func.inputs.len(), 2); assert_eq!(func.inputs[0].ty, "uint256"); assert_eq!(func.inputs[1].ty, "uint256"); + + // Stripped down function, which [Function] can parse. + let func = get_func("foo(bytes4 a, uint8 b)(bytes4)"); + assert!(func.is_ok()); + let func = func.unwrap(); + assert_eq!(func.name, "foo"); + assert_eq!(func.inputs.len(), 2); + assert_eq!(func.inputs[0].ty, "bytes4"); + assert_eq!(func.inputs[1].ty, "uint8"); + assert_eq!(func.outputs[0].ty, "bytes4"); } #[test]