Repository: gakonst/ethers-rs
Pull request #428 (2021-09-02 16:15:57)

chore: add changelog for #427 changes
as title, forgot the changelog + add an extra example


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f74d5bf8..a537f377 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@
 
 ### Unreleased
 
+* Allow configuring the optimizer & passing arbitrary arguments to solc [#427](https://github.com/gakonst/ethers-rs/pull/427)
+
 ### 0.5.2
 * Correctly RLP Encode transactions as received from the mempool ([#415](https://github.com/gakonst/ethers-rs/pull/415))
 
@@ -21,6 +23,7 @@
 ## ethers-contract
 
 ### Unreleased
+* (De)Tokenize structs and events with only a single field as `Token:Tuple` ([#417](https://github.com/gakonst/ethers-rs/pull/417))
 
 ## ethers-middleware
 
diff --git a/ethers-contract/ethers-contract-derive/src/lib.rs b/ethers-contract/ethers-contract-derive/src/lib.rs
index ec112741..cf8f5646 100644
--- a/ethers-contract/ethers-contract-derive/src/lib.rs
+++ b/ethers-contract/ethers-contract-derive/src/lib.rs
@@ -414,7 +414,7 @@ fn derive_decode_from_log_impl(
         .filter(|f| !f.is_indexed())
         .map(|f| param_type_quote(&f.param.kind));
 
-    let data_types_init = quote! {let data_types = ::std::vec![#( #data_types ),*];};
+    let data_types_init = quote! {let data_types = [#( #data_types ),*];};
 
     // decode
     let (signature_check, flat_topics_init, topic_tokens_len_check) = if event.anonymous {
@@ -478,7 +478,6 @@ fn derive_decode_from_log_impl(
             #( tokens.push(#swap_tokens); )*
         }
     };
-
     Ok(quote! {
 
         let #core_crate::abi::RawLog {data, topics} = log;
@@ -492,7 +491,7 @@ fn derive_decode_from_log_impl(
 
         #tokens_init
 
-        #core_crate::abi::Detokenize::from_tokens(tokens).map_err(|_|#core_crate::abi::Error::InvalidData)
+        #core_crate::abi::Tokenizable::from_token(#core_crate::abi::Token::Tuple(tokens)).map_err(|_|#core_crate::abi::Error::InvalidData)
     })
 }
 
@@ -808,26 +807,6 @@ fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream {
                 #core_crate::abi::Token::Tuple(Vec::new())
             },
         ),
-        1 => {
-            // This is a hacky solution in order to keep the same tokenstream as for tuples
-            let from_token = quote! {
-                let mut iter = Some(token).into_iter();
-                Ok(#init_struct_impl)
-            };
-
-            // This is a hack to get rid of the trailing comma introduced in the macro that concatenates all the fields
-            if let Ok(into_token) = into_token_impl
-                .to_string()
-                .as_str()
-                .trim_end_matches(',')
-                .parse()
-            {
-                (from_token, into_token)
-            } else {
-                return Error::new(input.span(), "Failed to derive Tokenizeable implementation")
-                    .to_compile_error();
-            }
-        }
         _ => {
             let from_token = quote! {
                 if let #core_crate::abi::Token::Tuple(tokens) = token {
diff --git a/ethers-core/src/utils/solc.rs b/ethers-core/src/utils/solc.rs
index e3886169..da4692e7 100644
--- a/ethers-core/src/utils/solc.rs
+++ b/ethers-core/src/utils/solc.rs
@@ -210,6 +210,22 @@ impl Solc {
     }
 
     /// Sets the optimizer runs (default = 200). None indicates no optimization
+    ///
+    /// ```rust,no_run
+    /// use ethers_core::utils::Solc;
+    ///
+    /// // No optimization
+    /// let contracts = Solc::new("./contracts/*")
+    ///     .optimizer(None)
+    ///     .build().unwrap();
+    ///
+    /// // Some(200) is default, optimizer on with 200 runs
+    /// // .arg() allows passing arbitrary args to solc command
+    /// let optimized_contracts = Solc::new("./contracts/*")
+    ///     .optimizer(Some(200))
+    ///     .arg("--metadata-hash=none")
+    ///     .build().unwrap();
+    /// ```
     pub fn optimizer(mut self, runs: Option<usize>) -> Self {
         self.optimizer = runs;
         self


Test patch:
diff --git a/ethers-contract/tests/common/derive.rs b/ethers-contract/tests/common/derive.rs
index b9d04aa6..be1d87df 100644
--- a/ethers-contract/tests/common/derive.rs
+++ b/ethers-contract/tests/common/derive.rs
@@ -24,6 +24,11 @@ struct ValueChangedTuple(Address, Address, String, String);
 #[derive(Debug, Clone, PartialEq, EthAbiType)]
 struct ValueChangedTupleWrapper(ValueChangedTuple, String);
 
+#[derive(Debug, Clone, PartialEq, EthAbiType)]
+struct ValueChangedVecWrapper {
+    inner: Vec<ValueChanged>,
+}
+
 #[test]
 fn can_detokenize_struct() {
     let value = ValueChanged {
@@ -82,6 +87,26 @@ fn can_detokenize_nested_tuple_struct() {
     assert_eq!(value, ValueChangedTupleWrapper::from_token(token).unwrap());
 }
 
+#[test]
+fn can_detokenize_single_field() {
+    let value = ValueChangedVecWrapper { inner: vec![] };
+
+    let token = value.clone().into_token();
+    assert_eq!(value, ValueChangedVecWrapper::from_token(token).unwrap());
+
+    let value = ValueChangedVecWrapper {
+        inner: vec![ValueChanged {
+            old_author: "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee".parse().unwrap(),
+            new_author: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".parse().unwrap(),
+            old_value: "50".to_string(),
+            new_value: "100".to_string(),
+        }],
+    };
+
+    let token = value.clone().into_token();
+    assert_eq!(value, ValueChangedVecWrapper::from_token(token).unwrap());
+}
+
 #[test]
 fn can_derive_eth_event() {
     #[derive(Debug, Clone, PartialEq, EthEvent)]