Repository: gakonst/ethers-rs
Pull request #1148 (2022-04-15 19:56:07)

fix: support display for bytes
<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.

Bug fixes and new features should include tests.

Contributors guide: https://github.com/gakonst/ethers-rs/blob/master/CONTRIBUTING.md

The contributors guide includes instructions for running rustfmt and building the
documentation.
-->

## Motivation
support the `Bytes` type in `EthDisplay` and format using hex encode
<!--
Explain the context and why you're making that change. What is the problem
you're trying to solve? In some cases there is not a problem and this can be
thought of as being the motivation for your change.
-->

## Solution

<!--
Summarize the solution and provide any necessary context needed to understand
the code change.
-->

## PR Checklist

- [x] Added Tests
- [ ] Added Documentation
- [ ] Updated the changelog



Patch:
diff --git a/Cargo.lock b/Cargo.lock
index dac6a7a5..9347f3ae 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3585,7 +3585,7 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
 [[package]]
 name = "svm-rs"
 version = "0.2.9"
-source = "git+https://github.com/roynalnaruto/svm-rs#9c86111689147842dd76f5fe8db7cf472e729118"
+source = "git+https://github.com/roynalnaruto/svm-rs#1eb7f4e2ccb549096885ded598f6c05b2d96dccf"
 dependencies = [
  "anyhow",
  "cfg-if 1.0.0",
@@ -3614,7 +3614,7 @@ dependencies = [
 [[package]]
 name = "svm-rs-builds"
 version = "0.1.0"
-source = "git+https://github.com/roynalnaruto/svm-rs#9c86111689147842dd76f5fe8db7cf472e729118"
+source = "git+https://github.com/roynalnaruto/svm-rs#1eb7f4e2ccb549096885ded598f6c05b2d96dccf"
 dependencies = [
  "build_const",
  "hex",
diff --git a/ethers-contract/ethers-contract-derive/src/display.rs b/ethers-contract/ethers-contract-derive/src/display.rs
index 45918207..8fc613f1 100644
--- a/ethers-contract/ethers-contract-derive/src/display.rs
+++ b/ethers-contract/ethers-contract-derive/src/display.rs
@@ -42,7 +42,7 @@ pub(crate) fn derive_eth_display_impl(input: DeriveInput) -> Result<TokenStream,
                 }
                 ParamType::Bytes => {
                     quote! {
-                         write!(f, "0x{}", #hex_encode(self.#ident))?;
+                         write!(f, "0x{}", #hex_encode(&self.#ident))?;
                     }
                 }
                 ParamType::Bool | ParamType::String => {
diff --git a/ethers-contract/ethers-contract-derive/src/utils.rs b/ethers-contract/ethers-contract-derive/src/utils.rs
index 066cbbfa..abef0999 100644
--- a/ethers-contract/ethers-contract-derive/src/utils.rs
+++ b/ethers-contract/ethers-contract-derive/src/utils.rs
@@ -111,10 +111,26 @@ pub fn find_parameter_type(ty: &Type) -> Result<ParamType, Error> {
             Err(Error::new(ty.span(), "Failed to derive proper ABI from array field"))
         }
         Type::Path(ty) => {
-            if let Some(ident) = ty.path.get_ident() {
+            // check for `Vec`
+            if ty.path.segments.len() == 1 && ty.path.segments[0].ident == "Vec" {
+                if let PathArguments::AngleBracketed(ref args) = ty.path.segments[0].arguments {
+                    if args.args.len() == 1 {
+                        if let GenericArgument::Type(ref ty) = args.args.iter().next().unwrap() {
+                            let kind = find_parameter_type(ty)?;
+                            return Ok(ParamType::Array(Box::new(kind)))
+                        }
+                    }
+                }
+            }
+            let mut ident = ty.path.get_ident();
+            if ident.is_none() {
+                ident = ty.path.segments.last().map(|s| &s.ident);
+            }
+            if let Some(ident) = ident {
                 let ident = ident.to_string().to_lowercase();
                 return match ident.as_str() {
                     "address" => Ok(ParamType::Address),
+                    "bytes" => Ok(ParamType::Bytes),
                     "string" => Ok(ParamType::String),
                     "bool" => Ok(ParamType::Bool),
                     "int" | "uint" => Ok(ParamType::Uint(256)),
@@ -126,18 +142,6 @@ pub fn find_parameter_type(ty: &Type) -> Result<ParamType, Error> {
                     }),
                 }
             }
-            // check for `Vec`
-            if ty.path.segments.len() == 1 && ty.path.segments[0].ident == "Vec" {
-                if let PathArguments::AngleBracketed(ref args) = ty.path.segments[0].arguments {
-                    if args.args.len() == 1 {
-                        if let GenericArgument::Type(ref ty) = args.args.iter().next().unwrap() {
-                            let kind = find_parameter_type(ty)?;
-                            return Ok(ParamType::Array(Box::new(kind)))
-                        }
-                    }
-                }
-            }
-
             Err(Error::new(ty.span(), "Failed to derive proper ABI from fields"))
         }
         Type::Tuple(ty) => {


Test patch:
diff --git a/ethers-contract/tests/common/derive.rs b/ethers-contract/tests/common/derive.rs
index 65f07ca7..25dd7aaf 100644
--- a/ethers-contract/tests/common/derive.rs
+++ b/ethers-contract/tests/common/derive.rs
@@ -583,3 +583,16 @@ fn can_derive_array_tuples() {
         pub calldata: Bytes,
     }
 }
+
+#[test]
+fn eth_display_works_on_ethers_bytes() {
+    #[derive(Clone, Debug, Default, Eq, PartialEq, EthCall, EthDisplay)]
+    #[ethcall(name = "logBytes", abi = "logBytes(bytes)")]
+    pub struct LogBytesCall {
+        pub p_0: ethers_core::types::Bytes,
+    }
+    let call = LogBytesCall { p_0: hex::decode(b"aaaaaa").unwrap().into() };
+
+    let s = format!("{}", call);
+    assert_eq!(s, "0xaaaaaa");
+}