Skip to content

Commit

Permalink
chore(dyn-abi): gate eip712 behind a feature
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed Jul 4, 2023
1 parent 674ed23 commit 1d886b3
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 155 deletions.
11 changes: 7 additions & 4 deletions crates/dyn-abi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
alloy-sol-types = { workspace = true, features = ["eip712-serde"] }
alloy-sol-types.workspace = true
alloy-primitives.workspace = true

hex.workspace = true
itoa.workspace = true
serde.workspace = true
serde_json.workspace = true

# eip712
serde = { workspace = true, optional = true }
serde_json = { workspace = true, optional = true }

# arbitrary
arbitrary = { workspace = true, optional = true }
Expand All @@ -38,7 +40,8 @@ ethabi = "18"

[features]
default = ["std"]
std = ["alloy-sol-types/std", "alloy-primitives/std", "hex/std", "serde/std", "serde_json/std"]
std = ["alloy-sol-types/std", "alloy-primitives/std", "hex/std", "serde?/std", "serde_json?/std"]
eip712 = ["alloy-sol-types/eip712-serde", "dep:serde", "dep:serde_json"]
arbitrary = [
"std",
"alloy-sol-types/arbitrary",
Expand Down
138 changes: 138 additions & 0 deletions crates/dyn-abi/src/eip712/coerce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,30 @@ use alloc::{
};
use alloy_primitives::{Address, I256, U256};

impl DynSolType {
/// Coerce a json value to a sol value via this type.
pub fn coerce(&self, value: &serde_json::Value) -> Result<DynSolValue, DynAbiError> {
match self {
DynSolType::Address => address(value),
DynSolType::Bytes => bytes(value),
DynSolType::Int(n) => int(*n, value),
DynSolType::Uint(n) => uint(*n, value),
DynSolType::Bool => bool(value),
DynSolType::Array(inner) => array(inner, value),
DynSolType::String => string(value),
DynSolType::FixedBytes(n) => fixed_bytes(*n, value),
DynSolType::FixedArray(inner, n) => fixed_array(inner, *n, value),
DynSolType::Tuple(inner) => tuple(inner, value),
DynSolType::CustomStruct {
name,
prop_names,
tuple,
} => coerce_custom_struct(name, prop_names, tuple, value),
DynSolType::CustomValue { name } => coerce_custom_value(name, value),
}
}
}

/// Coerce a `serde_json::Value` to a `DynSolValue::Address`
pub(crate) fn address(value: &serde_json::Value) -> Result<DynSolValue, DynAbiError> {
let address = value
Expand Down Expand Up @@ -226,3 +250,117 @@ pub(crate) fn coerce_custom_value(
value,
))
}

#[cfg(test)]
mod tests {
use super::*;
use alloc::{borrow::ToOwned, string::ToString};
use serde_json::json;

#[test]
fn it_coerces() {
let j = json!({
"message": {
"contents": "Hello, Bob!",
"attachedMoneyInEth": 4.2,
"from": {
"name": "Cow",
"wallets": [
"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
"0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF",
]
},
"to": [{
"name": "Bob",
"wallets": [
"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB",
"0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57",
"0xB0B0b0b0b0b0B000000000000000000000000000",
]
}]
}
});

let ty = DynSolType::CustomStruct {
name: "Message".to_owned(),
prop_names: vec!["contents".to_string(), "from".to_string(), "to".to_string()],
tuple: vec![
DynSolType::String,
DynSolType::CustomStruct {
name: "Person".to_owned(),
prop_names: vec!["name".to_string(), "wallets".to_string()],
tuple: vec![
DynSolType::String,
DynSolType::Array(Box::new(DynSolType::Address)),
],
},
DynSolType::Array(Box::new(DynSolType::CustomStruct {
name: "Person".to_owned(),
prop_names: vec!["name".to_string(), "wallets".to_string()],
tuple: vec![
DynSolType::String,
DynSolType::Array(Box::new(DynSolType::Address)),
],
})),
],
};
let top = j.as_object().unwrap().get("message").unwrap();

assert_eq!(
ty.coerce(top).unwrap(),
DynSolValue::CustomStruct {
name: "Message".to_owned(),
prop_names: vec!["contents".to_string(), "from".to_string(), "to".to_string()],
tuple: vec![
DynSolValue::String("Hello, Bob!".to_string()),
DynSolValue::CustomStruct {
name: "Person".to_owned(),
prop_names: vec!["name".to_string(), "wallets".to_string()],
tuple: vec![
DynSolValue::String("Cow".to_string()),
vec![
DynSolValue::Address(
"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"
.parse()
.unwrap()
),
DynSolValue::Address(
"0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF"
.parse()
.unwrap()
),
]
.into()
]
},
vec![DynSolValue::CustomStruct {
name: "Person".to_owned(),
prop_names: vec!["name".to_string(), "wallets".to_string()],
tuple: vec![
DynSolValue::String("Bob".to_string()),
vec![
DynSolValue::Address(
"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
.parse()
.unwrap()
),
DynSolValue::Address(
"0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57"
.parse()
.unwrap()
),
DynSolValue::Address(
"0xB0B0b0b0b0b0B000000000000000000000000000"
.parse()
.unwrap()
),
]
.into()
]
}]
.into()
]
}
)
}
}
43 changes: 26 additions & 17 deletions crates/dyn-abi/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::DynSolType;
use alloc::string::{String, ToString};
use core::fmt;

Expand All @@ -10,17 +9,19 @@ pub type DynAbiResult<T, E = DynAbiError> = core::result::Result<T, E>;
/// <https://eips.ethereum.org/EIPS/eip-712#definition-of-encodetype>
#[derive(Debug, Clone, PartialEq)]
pub enum DynAbiError {
/// Invalid size for a primitive type (intX, uintX, or bytesX).
InvalidSize(String),
/// Invalid type string, extra chars, or invalid structure.
InvalidTypeString(String),

/// Type mismatch during coercion.
#[cfg(feature = "eip712")]
TypeMismatch {
/// The expected type.
expected: DynSolType,
expected: crate::DynSolType,
/// The actual type.
actual: serde_json::Value,
},
/// Invalid size for a primitive type (intX, uintX, or bytesX).
InvalidSize(String),
/// Invalid type string, extra chars, or invalid structure.
InvalidTypeString(String),
/// Unknown type referenced from another type.
MissingType(String),
/// Detected circular dep during typegraph resolution.
Expand All @@ -45,16 +46,19 @@ impl std::error::Error for DynAbiError {
impl fmt::Display for DynAbiError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DynAbiError::InvalidSize(ty) => write!(f, "Invalid size for type: {ty}"),
DynAbiError::InvalidTypeString(ty) => write!(f, "Invalid type string: {ty}"),

#[cfg(feature = "eip712")]
DynAbiError::TypeMismatch { expected, actual } => {
write!(f, "Type mismatch, expected: {expected:?}, actual: {actual}")
}
DynAbiError::InvalidSize(ty) => write!(f, "Invalid size for type: {ty}"),
DynAbiError::InvalidTypeString(ty) => write!(f, "Invalid type string: {ty}"),
DynAbiError::MissingType(name) => write!(f, "Missing type in type resolution: {name}"),
DynAbiError::CircularDependency(dep) => write!(f, "Circular dependency: {dep}"),
DynAbiError::InvalidPropertyDefinition(def) => {
write!(f, "Invalid property definition: {def}")
}

DynAbiError::HexError(h) => h.fmt(f),
}
}
Expand All @@ -66,8 +70,21 @@ impl From<hex::FromHexError> for DynAbiError {
}
}

#[allow(dead_code)]
impl DynAbiError {
pub(crate) fn type_mismatch(expected: DynSolType, actual: &serde_json::Value) -> DynAbiError {
pub(crate) fn invalid_size(ty: impl ToString) -> DynAbiError {
DynAbiError::InvalidSize(ty.to_string())
}

pub(crate) fn invalid_type_string(ty: impl ToString) -> DynAbiError {
DynAbiError::InvalidTypeString(ty.to_string())
}

#[cfg(feature = "eip712")]
pub(crate) fn type_mismatch(
expected: crate::DynSolType,
actual: &serde_json::Value,
) -> DynAbiError {
DynAbiError::TypeMismatch {
expected,
actual: actual.clone(),
Expand All @@ -78,14 +95,6 @@ impl DynAbiError {
DynAbiError::InvalidPropertyDefinition(def.to_string())
}

pub(crate) fn invalid_size(ty: impl ToString) -> DynAbiError {
DynAbiError::InvalidSize(ty.to_string())
}

pub(crate) fn invalid_type_string(ty: impl ToString) -> DynAbiError {
DynAbiError::InvalidTypeString(ty.to_string())
}

pub(crate) fn missing_type(name: impl ToString) -> DynAbiError {
DynAbiError::MissingType(name.to_string())
}
Expand Down
2 changes: 2 additions & 0 deletions crates/dyn-abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ pub use token::DynToken;

pub mod parser;

#[cfg(feature = "eip712")]
pub mod eip712;
#[cfg(feature = "eip712")]
pub use eip712::{parser as eip712_parser, Resolver, TypedData};

#[cfg(test)]
Expand Down
Loading

0 comments on commit 1d886b3

Please sign in to comment.