fix(eip712): improve argument parsing (#1485)

* fix(eip712): improve argument parsing

* use reexported serde_json

* chore: rustfmt

* fix: add missing salt
This commit is contained in:
Matthias Seitz 2022-07-20 09:09:11 +02:00 committed by GitHub
parent 1d4f3efe8a
commit a958b4fd28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 35 deletions

View File

@ -42,7 +42,7 @@ pub(crate) fn struct_declaration(cx: &Context) -> TokenStream {
let abi_parse = if !cx.human_readable { let abi_parse = if !cx.human_readable {
quote! { quote! {
pub static #abi_name: #ethers_contract::Lazy<#ethers_core::abi::Abi> = #ethers_contract::Lazy::new(|| serde_json::from_str(#abi) pub static #abi_name: #ethers_contract::Lazy<#ethers_core::abi::Abi> = #ethers_contract::Lazy::new(|| #ethers_core::utils::__serde_json::from_str(#abi)
.expect("invalid abi")); .expect("invalid abi"));
} }
} else { } else {

View File

@ -61,7 +61,6 @@
//! determine if there is a nested eip712 struct. However, this work is not yet complete. //! determine if there is a nested eip712 struct. However, this work is not yet complete.
#![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::broken_intra_doc_links)]
#![deny(unused_crate_dependencies)]
use std::convert::TryFrom; use std::convert::TryFrom;
@ -121,7 +120,7 @@ fn impl_eip_712_macro(ast: &syn::DeriveInput) -> TokenStream {
fn type_hash() -> Result<[u8; 32], Self::Error> { fn type_hash() -> Result<[u8; 32], Self::Error> {
use std::convert::TryFrom; use std::convert::TryFrom;
let decoded = hex::decode(#type_hash)?; let decoded = #ethers_core::utils::hex::decode(#type_hash)?;
let byte_array: [u8; 32] = <[u8; 32]>::try_from(&decoded[..])?; let byte_array: [u8; 32] = <[u8; 32]>::try_from(&decoded[..])?;
Ok(byte_array) Ok(byte_array)
} }
@ -129,13 +128,13 @@ fn impl_eip_712_macro(ast: &syn::DeriveInput) -> TokenStream {
// Return the pre-computed domain separator from compile time; // Return the pre-computed domain separator from compile time;
fn domain_separator(&self) -> Result<[u8; 32], Self::Error> { fn domain_separator(&self) -> Result<[u8; 32], Self::Error> {
use std::convert::TryFrom; use std::convert::TryFrom;
let decoded = hex::decode(#domain_separator)?; let decoded = #ethers_core::utils::hex::decode(#domain_separator)?;
let byte_array: [u8; 32] = <[u8; 32]>::try_from(&decoded[..])?; let byte_array: [u8; 32] = <[u8; 32]>::try_from(&decoded[..])?;
Ok(byte_array) Ok(byte_array)
} }
fn domain(&self) -> Result<#ethers_core::types::transaction::eip712::EIP712Domain, Self::Error> { fn domain(&self) -> Result<#ethers_core::types::transaction::eip712::EIP712Domain, Self::Error> {
let domain: #ethers_core::types::transaction::eip712::EIP712Domain = serde_json::from_str(#domain_str)?; let domain: #ethers_core::types::transaction::eip712::EIP712Domain = # ethers_core::utils::__serde_json::from_str(#domain_str)?;
Ok(domain) Ok(domain)
} }

View File

@ -9,7 +9,7 @@ use syn::{
use crate::{ use crate::{
abi, abi,
abi::{ParamType, Token}, abi::{ParamType, Token},
types::{Address, H160, U256}, types::{Address, U256},
utils::keccak256, utils::keccak256,
}; };
@ -196,9 +196,14 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain {
type Error = TokenStream; type Error = TokenStream;
fn try_from(input: &syn::DeriveInput) -> Result<EIP712Domain, Self::Error> { fn try_from(input: &syn::DeriveInput) -> Result<EIP712Domain, Self::Error> {
let mut domain = EIP712Domain::default(); let mut domain = EIP712Domain::default();
let mut domain_name = None;
let mut domain_version = None;
let mut chain_id = None;
let mut verifying_contract = None;
let mut found_eip712_attribute = false; let mut found_eip712_attribute = false;
for attribute in input.attrs.iter() { 'attribute_search: for attribute in input.attrs.iter() {
if let AttrStyle::Outer = attribute.style { if let AttrStyle::Outer = attribute.style {
if let Ok(syn::Meta::List(meta)) = attribute.parse_meta() { if let Ok(syn::Meta::List(meta)) = attribute.parse_meta() {
if meta.path.is_ident("eip712") { if meta.path.is_ident("eip712") {
@ -219,7 +224,7 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain {
match ident.to_string().as_ref() { match ident.to_string().as_ref() {
"name" => match meta.lit { "name" => match meta.lit {
syn::Lit::Str(ref lit_str) => { syn::Lit::Str(ref lit_str) => {
if domain.name != String::default() { if domain_name.is_some() {
return Err(Error::new( return Err(Error::new(
meta.path.span(), meta.path.span(),
"domain name already specified", "domain name already specified",
@ -227,7 +232,7 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain {
.to_compile_error()) .to_compile_error())
} }
domain.name = lit_str.value(); domain_name = Some(lit_str.value());
} }
_ => { _ => {
return Err(Error::new( return Err(Error::new(
@ -239,7 +244,7 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain {
}, },
"version" => match meta.lit { "version" => match meta.lit {
syn::Lit::Str(ref lit_str) => { syn::Lit::Str(ref lit_str) => {
if domain.version != String::default() { if domain_version.is_some() {
return Err(Error::new( return Err(Error::new(
meta.path.span(), meta.path.span(),
"domain version already specified", "domain version already specified",
@ -247,7 +252,7 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain {
.to_compile_error()) .to_compile_error())
} }
domain.version = lit_str.value(); domain_version = Some(lit_str.value());
} }
_ => { _ => {
return Err(Error::new( return Err(Error::new(
@ -259,7 +264,7 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain {
}, },
"chain_id" => match meta.lit { "chain_id" => match meta.lit {
syn::Lit::Int(ref lit_int) => { syn::Lit::Int(ref lit_int) => {
if domain.chain_id != U256::default() { if chain_id.is_some() {
return Err(Error::new( return Err(Error::new(
meta.path.span(), meta.path.span(),
"domain chain_id already specified", "domain chain_id already specified",
@ -267,7 +272,7 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain {
.to_compile_error()) .to_compile_error())
} }
domain.chain_id = U256::from( chain_id = Some(U256::from(
lit_int.base10_parse::<u64>().map_err( lit_int.base10_parse::<u64>().map_err(
|_| { |_| {
Error::new( Error::new(
@ -277,7 +282,7 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain {
.to_compile_error() .to_compile_error()
}, },
)?, )?,
); ));
} }
_ => { _ => {
return Err(Error::new( return Err(Error::new(
@ -289,8 +294,7 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain {
}, },
"verifying_contract" => match meta.lit { "verifying_contract" => match meta.lit {
syn::Lit::Str(ref lit_str) => { syn::Lit::Str(ref lit_str) => {
if domain.verifying_contract != H160::default() if verifying_contract.is_some() {
{
return Err(Error::new( return Err(Error::new(
meta.path.span(), meta.path.span(),
"domain verifying_contract already specified", "domain verifying_contract already specified",
@ -298,13 +302,13 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain {
.to_compile_error()); .to_compile_error());
} }
domain.verifying_contract = lit_str.value().parse().map_err(|_| { verifying_contract = Some(lit_str.value().parse().map_err(|_| {
Error::new( Error::new(
meta.path.span(), meta.path.span(),
"failed to parse verifying contract into Address", "failed to parse verifying contract into Address",
) )
.to_compile_error() .to_compile_error()
})?; })?);
} }
_ => { _ => {
return Err(Error::new( return Err(Error::new(
@ -316,7 +320,7 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain {
}, },
"salt" => match meta.lit { "salt" => match meta.lit {
syn::Lit::Str(ref lit_str) => { syn::Lit::Str(ref lit_str) => {
if domain.salt != Option::None { if domain.salt.is_some() {
return Err(Error::new( return Err(Error::new(
meta.path.span(), meta.path.span(),
"domain salt already specified", "domain salt already specified",
@ -365,36 +369,41 @@ impl TryFrom<&syn::DeriveInput> for EIP712Domain {
} }
} }
if domain.name == String::default() { domain.name = domain_name.ok_or_else(|| {
return Err(Error::new( Error::new(
meta.path.span(), meta.path.span(),
"missing required domain attribute: 'name'".to_string(), "missing required domain attribute: 'name'".to_string(),
) )
.to_compile_error()) .to_compile_error()
} })?;
if domain.version == String::default() {
return Err(Error::new( domain.version = domain_version.ok_or_else(|| {
Error::new(
meta.path.span(), meta.path.span(),
"missing required domain attribute: 'version'".to_string(), "missing required domain attribute: 'version'".to_string(),
) )
.to_compile_error()) .to_compile_error()
} })?;
if domain.chain_id == U256::default() {
return Err(Error::new( domain.chain_id = chain_id.ok_or_else(|| {
Error::new(
meta.path.span(), meta.path.span(),
"missing required domain attribute: 'chain_id'".to_string(), "missing required domain attribute: 'chain_id'".to_string(),
) )
.to_compile_error()) .to_compile_error()
} })?;
if domain.verifying_contract == H160::default() {
return Err(Error::new( domain.verifying_contract = verifying_contract.ok_or_else(|| {
Error::new(
meta.path.span(), meta.path.span(),
"missing required domain attribute: 'verifying_contract'" "missing required domain attribute: 'verifying_contract'"
.to_string(), .to_string(),
) )
.to_compile_error()) .to_compile_error()
} })?;
} }
break 'attribute_search
} }
} }
} }

View File

@ -38,6 +38,12 @@ use k256::{ecdsa::SigningKey, PublicKey as K256PublicKey};
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use thiserror::Error; use thiserror::Error;
/// Re-export of serde-json
#[doc(hidden)]
pub mod __serde_json {
pub use serde_json::*;
}
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum ConversionError { pub enum ConversionError {
#[error("Unknown units: {0}")] #[error("Unknown units: {0}")]