diff --git a/Cargo.lock b/Cargo.lock index aa4eeafb..73deacce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,7 +104,7 @@ checksum = "b84f9ebcc6c1f5b8cb160f6990096a5c127f423fcb6e1ccc46c370cbdfb75dfc" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -138,7 +138,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -485,7 +485,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -821,7 +821,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -872,7 +872,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 1.0.109", ] [[package]] @@ -889,7 +889,7 @@ checksum = "0b75aed41bb2e6367cae39e6326ef817a851db13c13e4f3263714ca3cfb8de56" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -932,7 +932,7 @@ checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1272,7 +1272,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn", + "syn 2.0.0", "tempfile", "tokio", "toml", @@ -1289,7 +1289,7 @@ dependencies = [ "hex", "proc-macro2", "quote", - "syn", + "syn 2.0.0", ] [[package]] @@ -1312,13 +1312,12 @@ dependencies = [ "num_enum", "once_cell", "open-fastrlp", - "proc-macro2", "rand", "rlp", "serde", "serde_json", "strum", - "syn", + "syn 2.0.0", "tempfile", "thiserror", "tiny-keccak", @@ -1332,9 +1331,10 @@ dependencies = [ "ethers-contract-derive", "ethers-core", "hex", + "proc-macro2", "quote", "serde_json", - "syn", + "syn 2.0.0", ] [[package]] @@ -1816,7 +1816,7 @@ checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2204,7 +2204,7 @@ checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2615,7 +2615,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2664,7 +2664,7 @@ dependencies = [ "bytes", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2690,7 +2690,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2790,7 +2790,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2911,7 +2911,7 @@ dependencies = [ "phf_shared 0.11.1", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2955,7 +2955,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3051,7 +3051,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" dependencies = [ "proc-macro2", - "syn", + "syn 1.0.109", ] [[package]] @@ -3096,7 +3096,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "version_check", ] @@ -3340,7 +3340,7 @@ checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3549,7 +3549,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3687,7 +3687,7 @@ checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3753,7 +3753,7 @@ checksum = "079a83df15f85d89a68d64ae1238f142f172b1fa915d0d76b26a7cba1b659a69" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3844,7 +3844,7 @@ checksum = "ede930749cca4e3a3df7e37b5f0934a55693e01d028d7a4e506b44cbc059d95a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3951,7 +3951,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn", + "syn 1.0.109", ] [[package]] @@ -4015,6 +4015,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cff13bb1732bccfe3b246f3fdb09edfd51c01d6f5299b7ccd9457c2e4e37774" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "synstructure" version = "0.12.6" @@ -4023,7 +4034,7 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "unicode-xid", ] @@ -4099,7 +4110,7 @@ checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4200,7 +4211,7 @@ checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4316,7 +4327,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4388,7 +4399,7 @@ checksum = "258bc1c4f8e2e73a977812ab339d503e6feeb92700f6d07a6de4d321522d5c08" dependencies = [ "lazy_static", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4600,7 +4611,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-shared", ] @@ -4634,7 +4645,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4919,7 +4930,7 @@ checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "synstructure", ] diff --git a/Cargo.toml b/Cargo.toml index 3cd4a57e..91f3a247 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -107,7 +107,7 @@ serde_json = "1.0" # macros proc-macro2 = "1.0" quote = "1.0" -syn = { version = "1.0", features = ["extra-traits"] } +syn = { version = "2.0", features = ["extra-traits"] } async-trait = "0.1.66" auto_impl = "1.0" diff --git a/ethers-contract/ethers-contract-abigen/Cargo.toml b/ethers-contract/ethers-contract-abigen/Cargo.toml index fdbb5a47..3c15c8a0 100644 --- a/ethers-contract/ethers-contract-abigen/Cargo.toml +++ b/ethers-contract/ethers-contract-abigen/Cargo.toml @@ -30,7 +30,7 @@ ethers-core = { workspace = true, features = ["macros"] } proc-macro2.workspace = true quote.workspace = true -syn.workspace = true +syn = { workspace = true, features = ["full"] } prettyplease = "0.1.25" Inflector = "0.11" diff --git a/ethers-core/Cargo.toml b/ethers-core/Cargo.toml index fd5211ec..3966a99f 100644 --- a/ethers-core/Cargo.toml +++ b/ethers-core/Cargo.toml @@ -55,7 +55,6 @@ cargo_metadata = { version = "0.15.3", optional = true } # eip712 feature enabled dependencies convert_case = { version = "0.6.0", optional = true } syn = { workspace = true, optional = true } -proc-macro2 = { workspace = true, optional = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] tempfile.workspace = true @@ -73,5 +72,5 @@ rand.workspace = true [features] celo = ["legacy"] # celo support extends the transaction format with extra fields legacy = [] -eip712 = ["convert_case", "syn", "proc-macro2"] +eip712 = ["convert_case", "syn"] macros = ["syn", "cargo_metadata", "once_cell"] diff --git a/ethers-core/ethers-derive-eip712/Cargo.toml b/ethers-core/ethers-derive-eip712/Cargo.toml index 5f2e320a..3eea2719 100644 --- a/ethers-core/ethers-derive-eip712/Cargo.toml +++ b/ethers-core/ethers-derive-eip712/Cargo.toml @@ -19,6 +19,7 @@ proc-macro = true [dependencies] ethers-core = { workspace = true, features = ["eip712", "macros"] } +proc-macro2.workspace = true quote.workspace = true syn.workspace = true diff --git a/ethers-core/ethers-derive-eip712/src/lib.rs b/ethers-core/ethers-derive-eip712/src/lib.rs index e1c1272a..8b62e2d1 100644 --- a/ethers-core/ethers-derive-eip712/src/lib.rs +++ b/ethers-core/ethers-derive-eip712/src/lib.rs @@ -62,49 +62,40 @@ //! determine if there is a nested eip712 struct. However, this work is not yet complete. #![deny(missing_docs, unsafe_code, rustdoc::broken_intra_doc_links)] + use ethers_core::{macros::ethers_core_crate, types::transaction::eip712}; use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; use quote::quote; -use std::convert::TryFrom; -use syn::parse_macro_input; +use syn::{parse_macro_input, Result}; /// Derive macro for `Eip712` #[proc_macro_derive(Eip712, attributes(eip712))] pub fn eip_712_derive(input: TokenStream) -> TokenStream { - let ast = parse_macro_input!(input); - - impl_eip_712_macro(&ast) + let input = parse_macro_input!(input); + match impl_eip_712_macro(&input) { + Ok(tokens) => tokens, + Err(e) => e.to_compile_error(), + } + .into() } // Main implementation macro, used to compute static values and define // method for encoding the final eip712 payload; -fn impl_eip_712_macro(ast: &syn::DeriveInput) -> TokenStream { +fn impl_eip_712_macro(input: &syn::DeriveInput) -> Result { // Primary type should match the type in the ethereum verifying contract; - let primary_type = &ast.ident; + let primary_type = &input.ident; // Instantiate domain from parsed attributes - let domain = match eip712::EIP712Domain::try_from(ast) { - Ok(attributes) => attributes, - Err(e) => return TokenStream::from(e), - }; + let domain = eip712::EIP712Domain::try_from(input)?; let domain_separator = hex::encode(domain.separator()); // - let domain_str = match serde_json::to_string(&domain) { - Ok(s) => s, - Err(e) => { - return TokenStream::from( - syn::Error::new(ast.ident.span(), e.to_string()).to_compile_error(), - ) - } - }; + let domain_str = serde_json::to_string(&domain).unwrap(); // Must parse the AST at compile time. - let parsed_fields = match eip712::parse_fields(ast) { - Ok(fields) => fields, - Err(e) => return TokenStream::from(e), - }; + let parsed_fields = eip712::parse_fields(input)?; // Compute the type hash for the derived struct using the parsed fields from above. let type_hash = @@ -113,7 +104,7 @@ fn impl_eip_712_macro(ast: &syn::DeriveInput) -> TokenStream { // Use reference to ethers_core instead of directly using the crate itself. let ethers_core = ethers_core_crate(); - let implementation = quote! { + let tokens = quote! { impl Eip712 for #primary_type { type Error = #ethers_core::types::transaction::eip712::Eip712Error; @@ -168,5 +159,5 @@ fn impl_eip_712_macro(ast: &syn::DeriveInput) -> TokenStream { } }; - implementation.into() + Ok(tokens) } diff --git a/ethers-core/src/types/transaction/eip712.rs b/ethers-core/src/types/transaction/eip712.rs index b608652a..14891b69 100644 --- a/ethers-core/src/types/transaction/eip712.rs +++ b/ethers-core/src/types/transaction/eip712.rs @@ -7,7 +7,6 @@ use crate::{ use convert_case::{Case, Casing}; use core::convert::TryFrom; use ethabi::encode; -use proc_macro2::TokenStream; use serde::{Deserialize, Deserializer, Serialize}; use std::{ collections::{BTreeMap, HashSet}, @@ -15,25 +14,25 @@ use std::{ iter::FromIterator, }; use syn::{ - parse::Error, spanned::Spanned as _, AttrStyle, Data, DeriveInput, Expr, Fields, - GenericArgument, Lit, NestedMeta, PathArguments, Type, + parse::Error, spanned::Spanned, Data, DeriveInput, Expr, Fields, GenericArgument, Lit, LitInt, + LitStr, PathArguments, Type, }; /// Custom types for `TypedData` pub type Types = BTreeMap>; -/// Pre-computed value of the following statement: +/// Pre-computed value of the following expression: /// -/// `ethers_core::utils::keccak256("EIP712Domain(string name,string version,uint256 chainId,address +/// `keccak256("EIP712Domain(string name,string version,uint256 chainId,address /// verifyingContract)")` pub const EIP712_DOMAIN_TYPE_HASH: [u8; 32] = [ 139, 115, 195, 198, 155, 184, 254, 61, 81, 46, 204, 76, 247, 89, 204, 121, 35, 159, 123, 23, 155, 15, 250, 202, 169, 167, 93, 82, 43, 57, 64, 15, ]; -/// Pre-computed value of the following statement: +/// Pre-computed value of the following expression: /// -/// `ethers_core::utils::keccak256("EIP712Domain(string name,string version,uint256 chainId,address +/// `keccak256("EIP712Domain(string name,string version,uint256 chainId,address /// verifyingContract,bytes32 salt)")` pub const EIP712_DOMAIN_TYPE_HASH_WITH_SALT: [u8; 32] = [ 216, 124, 214, 239, 121, 212, 226, 185, 94, 21, 206, 138, 191, 115, 45, 181, 30, 199, 113, 241, @@ -247,190 +246,61 @@ impl Eip712 for EIP712WithDomain { // Parse the AST of the struct to determine the domain attributes impl TryFrom<&syn::DeriveInput> for EIP712Domain { - type Error = TokenStream; + type Error = Error; + fn try_from(input: &syn::DeriveInput) -> Result { + const ERROR: &str = "unrecognized eip712 attribute"; + const ALREADY_SPECIFIED: &str = "eip712 attribute already specified"; + let mut domain = EIP712Domain::default(); - let mut found_eip712_attribute = false; - - 'attribute_search: for attribute in input.attrs.iter() { - if let AttrStyle::Outer = attribute.style { - if let Ok(syn::Meta::List(meta)) = attribute.parse_meta() { - if meta.path.is_ident("eip712") { - found_eip712_attribute = true; - - for n in meta.nested.iter() { - if let NestedMeta::Meta(meta) = n { - match meta { - syn::Meta::NameValue(meta) => { - let ident = meta.path.get_ident().ok_or_else(|| { - Error::new( - meta.path.span(), - "unrecognized eip712 parameter", - ) - .to_compile_error() - })?; - - match ident.to_string().as_ref() { - "name" => match meta.lit { - syn::Lit::Str(ref lit_str) => { - if domain.name.is_some() { - return Err(Error::new( - meta.path.span(), - "domain name already specified", - ) - .to_compile_error()) - } - - domain.name = Some(lit_str.value()); - } - _ => { - return Err(Error::new( - meta.path.span(), - "domain name must be a string", - ) - .to_compile_error()) - } - }, - "version" => match meta.lit { - syn::Lit::Str(ref lit_str) => { - if domain.version.is_some() { - return Err(Error::new( - meta.path.span(), - "domain version already specified", - ) - .to_compile_error()) - } - - domain.version = Some(lit_str.value()); - } - _ => { - return Err(Error::new( - meta.path.span(), - "domain version must be a string", - ) - .to_compile_error()) - } - }, - "chain_id" => match meta.lit { - syn::Lit::Int(ref lit_int) => { - if domain.chain_id.is_some() { - return Err(Error::new( - meta.path.span(), - "domain chain_id already specified", - ) - .to_compile_error()) - } - - domain.chain_id = Some(U256::from( - lit_int.base10_parse::().map_err( - |_| { - Error::new( - meta.path.span(), - "failed to parse chain id", - ) - .to_compile_error() - }, - )?, - )); - } - _ => { - return Err(Error::new( - meta.path.span(), - "domain chain_id must be a positive integer", - ) - .to_compile_error()); - } - }, - "verifying_contract" => match meta.lit { - syn::Lit::Str(ref lit_str) => { - if domain.verifying_contract.is_some() { - return Err(Error::new( - meta.path.span(), - "domain verifying_contract already specified", - ) - .to_compile_error()); - } - - domain.verifying_contract = Some(lit_str.value().parse().map_err(|_| { - Error::new( - meta.path.span(), - "failed to parse verifying contract into Address", - ) - .to_compile_error() - })?); - } - _ => { - return Err(Error::new( - meta.path.span(), - "domain verifying_contract must be a string", - ) - .to_compile_error()); - } - }, - "salt" => match meta.lit { - syn::Lit::Str(ref lit_str) => { - if domain.salt.is_some() { - return Err(Error::new( - meta.path.span(), - "domain salt already specified", - ) - .to_compile_error()) - } - - // keccak256() to compute bytes32 - // encoded domain salt - let salt = keccak256(lit_str.value()); - - domain.salt = Some(salt); - } - _ => { - return Err(Error::new( - meta.path.span(), - "domain salt must be a string", - ) - .to_compile_error()) - } - }, - _ => { - return Err(Error::new( - meta.path.span(), - "unrecognized eip712 parameter; must be one of 'name', 'version', 'chain_id', or 'verifying_contract'", - ) - .to_compile_error()); - } - } - } - syn::Meta::Path(path) => { - return Err(Error::new( - path.span(), - "unrecognized eip712 parameter", - ) - .to_compile_error()) - } - syn::Meta::List(meta) => { - return Err(Error::new( - meta.path.span(), - "unrecognized eip712 parameter", - ) - .to_compile_error()) - } - } - } - } - } - - break 'attribute_search - } + for attr in input.attrs.iter() { + if !attr.path().is_ident("eip712") { + continue } - } - if !found_eip712_attribute { - return Err(Error::new_spanned( - input, - "missing required derive attribute: '#[eip712( ... )]'".to_string(), - ) - .to_compile_error()) + attr.parse_nested_meta(|meta| { + let ident = meta.path.get_ident().ok_or_else(|| meta.error(ERROR))?.to_string(); + match ident.as_str() { + "name" if domain.name.is_none() => { + let litstr: LitStr = meta.input.parse()?; + domain.name = Some(litstr.value()); + } + "name" => return Err(meta.error(ALREADY_SPECIFIED)), + + "version" if domain.version.is_none() => { + let litstr: LitStr = meta.input.parse()?; + domain.version = Some(litstr.value()); + } + "version" => return Err(meta.error(ALREADY_SPECIFIED)), + + "chain_id" if domain.chain_id.is_none() => { + let litint: LitInt = meta.input.parse()?; + let n: u64 = litint.base10_parse()?; + domain.chain_id = Some(n.into()); + } + "chain_id" => return Err(meta.error(ALREADY_SPECIFIED)), + + "verifying_contract" if domain.verifying_contract.is_none() => { + let litstr: LitStr = meta.input.parse()?; + let addr: Address = + litstr.value().parse().map_err(|e| Error::new(litstr.span(), e))?; + domain.verifying_contract = Some(addr); + } + "verifying_contract" => return Err(meta.error(ALREADY_SPECIFIED)), + + "salt" if domain.salt.is_none() => { + let litstr: LitStr = meta.input.parse()?; + let hash = keccak256(litstr.value()); + domain.salt = Some(hash); + } + "salt" => return Err(meta.error(ALREADY_SPECIFIED)), + + _ => return Err(meta.error(ERROR)), + } + + Ok(()) + })?; } Ok(domain) @@ -442,36 +312,35 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain { /// Typed data is a JSON object containing type information, domain separator parameters and the /// message object which has the following schema /// -/// ```js +/// ```json /// { -// type: 'object', -// properties: { -// types: { -// type: 'object', -// properties: { -// EIP712Domain: {type: 'array'}, -// }, -// additionalProperties: { -// type: 'array', -// items: { -// type: 'object', -// properties: { -// name: {type: 'string'}, -// type: {type: 'string'} -// }, -// required: ['name', 'type'] -// } -// }, -// required: ['EIP712Domain'] -// }, -// primaryType: {type: 'string'}, -// domain: {type: 'object'}, -// message: {type: 'object'} -// }, -// required: ['types', 'primaryType', 'domain', 'message'] -// } +/// "type": "object", +/// "properties": { +/// "types": { +/// "type": "object", +/// "properties": { +/// "EIP712Domain": { "type": "array" } +/// }, +/// "additionalProperties": { +/// "type": "array", +/// "items": { +/// "type": "object", +/// "properties": { +/// "name": { "type": "string" }, +/// "type": { "type": "string" } +/// }, +/// "required": ["name", "type"] +/// } +/// }, +/// "required": ["EIP712Domain"] +/// }, +/// "primaryType": { "type": "string" }, +/// "domain": { "type": "object" }, +/// "message": { "type": "object" } +/// }, +/// "required": ["types", "primaryType", "domain", "message"] +/// } /// ``` -/// #[derive(Debug, Clone, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] pub struct TypedData { @@ -775,7 +644,7 @@ pub fn encode_field( /// Parse the eth abi parameter type based on the syntax type; /// this method is copied from /// with additional modifications for finding byte arrays -pub fn find_parameter_type(ty: &Type) -> Result { +pub fn find_parameter_type(ty: &Type) -> Result { match ty { Type::Array(ty) => { let param = find_parameter_type(ty.elem.as_ref())?; @@ -790,8 +659,7 @@ pub fn find_parameter_type(ty: &Type) -> Result { } } } - Err(Error::new(ty.span(), "Failed to derive proper ABI from array field") - .to_compile_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() { @@ -810,7 +678,6 @@ pub fn find_parameter_type(ty: &Type) -> Result { ty.span(), format!("Failed to derive proper ABI from field: {s})"), ) - .to_compile_error() }), } } @@ -834,15 +701,13 @@ pub fn find_parameter_type(ty: &Type) -> Result { } } - Err(Error::new(ty.span(), "Failed to derive proper ABI from fields").to_compile_error()) + Err(Error::new(ty.span(), "Failed to derive proper ABI from fields")) } Type::Tuple(ty) => { let params = ty.elems.iter().map(find_parameter_type).collect::, _>>()?; Ok(ParamType::Tuple(params)) } - _ => { - Err(Error::new(ty.span(), "Failed to derive proper ABI from fields").to_compile_error()) - } + _ => Err(Error::new(ty.span(), "Failed to derive proper ABI from fields")), } } @@ -857,41 +722,33 @@ fn parse_int_param_type(s: &str) -> Option { } } -/// Return HashMap of the field name and the field type; -pub fn parse_fields(ast: &DeriveInput) -> Result, TokenStream> { +/// Return HashMap of the field name and the field type +pub fn parse_fields(input: &DeriveInput) -> Result, Error> { let mut fields = Vec::new(); - let data = match &ast.data { + let data = match &input.data { Data::Struct(s) => s, - _ => { - return Err(Error::new( - ast.span(), - "invalid data type. can only derive Eip712 for a struct", - ) - .to_compile_error()) + Data::Enum(e) => { + return Err(Error::new(e.enum_token.span, "Eip712 is not derivable for enums")) + } + Data::Union(u) => { + return Err(Error::new(u.union_token.span, "Eip712 is not derivable for unions")) } }; let named_fields = match &data.fields { Fields::Named(name) => name, - _ => { - return Err(Error::new(ast.span(), "unnamed fields are not supported").to_compile_error()) - } + _ => return Err(Error::new(input.span(), "unnamed fields are not supported")), }; for f in named_fields.named.iter() { - let field_name = - f.ident.clone().map(|i| i.to_string().to_case(Case::Camel)).ok_or_else(|| { - Error::new(named_fields.span(), "fields must be named").to_compile_error() - })?; - + let field_name = f.ident.as_ref().unwrap().to_string().to_case(Case::Camel); let field_type = - match f.attrs.iter().find(|a| a.path.segments.iter().any(|s| s.ident == "eip712")) { + match f.attrs.iter().find(|a| a.path().segments.iter().any(|s| s.ident == "eip712")) { // Found nested Eip712 Struct // TODO: Implement custom Some(a) => { - return Err(Error::new(a.span(), "nested Eip712 struct are not yet supported") - .to_compile_error()) + return Err(Error::new(a.span(), "nested Eip712 struct are not yet supported")) } // Not a nested eip712 struct, return the field param type; None => find_parameter_type(&f.ty)?,