diff --git a/.changeset/kind-foxes-sleep.md b/.changeset/kind-foxes-sleep.md new file mode 100644 index 000000000..29cbbb6e1 --- /dev/null +++ b/.changeset/kind-foxes-sleep.md @@ -0,0 +1,5 @@ +--- +"@nomicfoundation/edr": patch +--- + +Added support for EIP-712 payloads with signed integers diff --git a/Cargo.lock b/Cargo.lock index 080323942..ca2eecd18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,6 +44,34 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "alloy-dyn-abi" +version = "0.7.2" +source = "git+https://github.com/alloy-rs/core?rev=85aecdf#85aecdf54c56da20f274a21f372d3d37b8c118ca" +dependencies = [ + "alloy-json-abi", + "alloy-primitives 0.7.2 (git+https://github.com/alloy-rs/core?rev=85aecdf)", + "alloy-sol-type-parser", + "alloy-sol-types 0.7.2", + "const-hex", + "derive_more", + "itoa", + "serde", + "serde_json", + "winnow 0.6.8", +] + +[[package]] +name = "alloy-json-abi" +version = "0.7.2" +source = "git+https://github.com/alloy-rs/core?rev=85aecdf#85aecdf54c56da20f274a21f372d3d37b8c118ca" +dependencies = [ + "alloy-primitives 0.7.2 (git+https://github.com/alloy-rs/core?rev=85aecdf)", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + [[package]] name = "alloy-primitives" version = "0.5.4" @@ -67,9 +95,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99bbad0a6b588ef4aec1b5ddbbfdacd9ef04e00b979617765b03174318ee1f3a" +checksum = "525448f6afc1b70dd0f9d0a8145631bf2f5e434678ab23ab18409ca264cae6b3" dependencies = [ "alloy-rlp", "bytes", @@ -88,6 +116,27 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "alloy-primitives" +version = "0.7.2" +source = "git+https://github.com/alloy-rs/core?rev=85aecdf#85aecdf54c56da20f274a21f372d3d37b8c118ca" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal", + "itoa", + "k256", + "keccak-asm", + "proptest", + "rand", + "ruint", + "serde", + "tiny-keccak", +] + [[package]] name = "alloy-rlp" version = "0.3.4" @@ -118,16 +167,55 @@ checksum = "970e5cf1ca089e964d4f7f7afc7c9ad642bfb1bdc695a20b0cba3b3c28954774" dependencies = [ "const-hex", "dunce", - "heck", + "heck 0.4.1", "indexmap 2.2.6", "proc-macro-error", "proc-macro2", "quote", "syn 2.0.58", - "syn-solidity", + "syn-solidity 0.5.4", "tiny-keccak", ] +[[package]] +name = "alloy-sol-macro" +version = "0.7.2" +source = "git+https://github.com/alloy-rs/core?rev=85aecdf#85aecdf54c56da20f274a21f372d3d37b8c118ca" +dependencies = [ + "alloy-sol-macro-input", + "const-hex", + "heck 0.4.1", + "indexmap 2.2.6", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.58", + "syn-solidity 0.7.2", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "0.7.2" +source = "git+https://github.com/alloy-rs/core?rev=85aecdf#85aecdf54c56da20f274a21f372d3d37b8c118ca" +dependencies = [ + "const-hex", + "dunce", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.58", + "syn-solidity 0.7.2", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "0.7.2" +source = "git+https://github.com/alloy-rs/core?rev=85aecdf#85aecdf54c56da20f274a21f372d3d37b8c118ca" +dependencies = [ + "winnow 0.6.8", +] + [[package]] name = "alloy-sol-types" version = "0.5.4" @@ -135,7 +223,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a059d4d2c78f8f21e470772c75f9abd9ac6d48c2aaf6b278d1ead06ed9ac664" dependencies = [ "alloy-primitives 0.5.4", - "alloy-sol-macro", + "alloy-sol-macro 0.5.4", + "const-hex", + "serde", +] + +[[package]] +name = "alloy-sol-types" +version = "0.7.2" +source = "git+https://github.com/alloy-rs/core?rev=85aecdf#85aecdf54c56da20f274a21f372d3d37b8c118ca" +dependencies = [ + "alloy-primitives 0.7.2 (git+https://github.com/alloy-rs/core?rev=85aecdf)", + "alloy-sol-macro 0.7.2", "const-hex", "serde", ] @@ -633,7 +732,7 @@ version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro-error", "proc-macro2", "quote", @@ -1118,7 +1217,8 @@ dependencies = [ name = "edr_provider" version = "0.3.5" dependencies = [ - "alloy-sol-types", + "alloy-dyn-abi", + "alloy-sol-types 0.5.4", "anyhow", "auto_impl", "cargo_toml", @@ -1127,7 +1227,6 @@ dependencies = [ "edr_eth", "edr_evm", "edr_test_utils", - "ethers-core", "indexmap 2.2.6", "itertools 0.12.1", "k256", @@ -1242,81 +1341,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "ethabi" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" -dependencies = [ - "ethereum-types", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3", - "thiserror", - "uint", -] - -[[package]] -name = "ethbloom" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" -dependencies = [ - "crunchy", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "tiny-keccak", -] - -[[package]] -name = "ethereum-types" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" -dependencies = [ - "ethbloom", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "primitive-types", - "scale-info", - "uint", -] - -[[package]] -name = "ethers-core" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" -dependencies = [ - "arrayvec", - "bytes", - "chrono", - "const-hex", - "elliptic-curve", - "ethabi", - "generic-array", - "k256", - "num_enum", - "open-fastrlp", - "rand", - "rlp", - "serde", - "serde_json", - "strum", - "tempfile", - "thiserror", - "tiny-keccak", - "unicode-xid", -] - [[package]] name = "event-listener" version = "2.5.3" @@ -1620,6 +1644,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1778,24 +1808,6 @@ dependencies = [ "parity-scale-codec", ] -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - -[[package]] -name = "impl-serde" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" -dependencies = [ - "serde", -] - [[package]] name = "impl-trait-for-tuples" version = "0.2.2" @@ -2264,27 +2276,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_enum" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 2.0.58", -] - [[package]] name = "number_prefix" version = "0.4.0" @@ -2312,31 +2303,6 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" -[[package]] -name = "open-fastrlp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", - "ethereum-types", - "open-fastrlp-derive", -] - -[[package]] -name = "open-fastrlp-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" -dependencies = [ - "bytes", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "openssl" version = "0.10.64" @@ -2423,7 +2389,7 @@ version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" dependencies = [ - "proc-macro-crate 2.0.0", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -2585,22 +2551,9 @@ checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", "uint", ] -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - [[package]] name = "proc-macro-crate" version = "2.0.0" @@ -2610,15 +2563,6 @@ dependencies = [ "toml_edit 0.20.7", ] -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit 0.21.1", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2962,7 +2906,7 @@ name = "revm-primitives" version = "3.1.1" source = "git+https://github.com/NomicFoundation/revm?rev=aceb093#aceb0939b1712faa0e8f45c1f5621c11b81df94e" dependencies = [ - "alloy-primitives 0.7.0", + "alloy-primitives 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "auto_impl", "bitflags 2.5.0", "bitvec", @@ -3003,21 +2947,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ "bytes", - "rlp-derive", "rustc-hex", ] -[[package]] -name = "rlp-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "rpds" version = "1.1.0" @@ -3109,12 +3041,6 @@ dependencies = [ "base64", ] -[[package]] -name = "rustversion" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" - [[package]] name = "rusty-fork" version = "0.3.0" @@ -3142,30 +3068,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scale-info" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "788745a868b0e751750388f4e6546eb921ef714a4317fa6954f7cde114eb2eb7" -dependencies = [ - "cfg-if", - "derive_more", - "parity-scale-codec", - "scale-info-derive", -] - -[[package]] -name = "scale-info-derive" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dc2f4e8bc344b9fc3d5f74f72c2e55bfc38d28dc2ebc69c194a3df424e4d9ac" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "schannel" version = "0.1.23" @@ -3428,28 +3330,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "strum" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.58", -] - [[package]] name = "substrate-bn" version = "0.6.0" @@ -3503,6 +3383,17 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "syn-solidity" +version = "0.7.2" +source = "git+https://github.com/alloy-rs/core?rev=85aecdf#85aecdf54c56da20f274a21f372d3d37b8c118ca" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "sync_wrapper" version = "0.1.2" @@ -3738,7 +3629,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] @@ -3749,18 +3640,7 @@ checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ "indexmap 2.2.6", "toml_datetime", - "winnow", -] - -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] @@ -3950,12 +3830,6 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - [[package]] name = "url" version = "2.5.0" @@ -4300,6 +4174,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/crates/edr_provider/Cargo.toml b/crates/edr_provider/Cargo.toml index 7d0703aec..44f841c1d 100644 --- a/crates/edr_provider/Cargo.toml +++ b/crates/edr_provider/Cargo.toml @@ -4,6 +4,8 @@ version = "0.3.5" edition = "2021" [dependencies] +# TODO switch to Cargo version https://github.com/NomicFoundation/edr/issues/445 +alloy-dyn-abi = { git = "https://github.com/alloy-rs/core", rev = "85aecdf", features = ["eip712"] } alloy-sol-types = { version = "0.5.1", default-features = false, features = ["std"] } anyhow = { version = "1.0.75", optional = true } auto_impl = { version = "1.2", default-features = false } @@ -11,7 +13,6 @@ dyn-clone = { version = "1.0.13", default-features = false } edr_defaults = { version = "0.3.5", path = "../edr_defaults" } edr_eth = { version = "0.3.5", path = "../edr_eth", features = ["rand"] } edr_evm = { version = "0.3.5", path = "../edr_evm", features = ["tracing"] } -ethers-core = { version = "2.0.12" , features = ["eip712"] } indexmap = { version = "2.0.0", default-features = false, features = ["std"] } itertools = { version = "0.12.0", default-features = false, features = ["use_alloc"] } k256 = { version = "0.13.1", default-features = false, features = ["arithmetic", "ecdsa", "pem", "pkcs8", "precomputed-tables", "std"] } diff --git a/crates/edr_provider/src/data.rs b/crates/edr_provider/src/data.rs index bab1a2257..8f0096048 100644 --- a/crates/edr_provider/src/data.rs +++ b/crates/edr_provider/src/data.rs @@ -12,6 +12,7 @@ use std::{ time::{Duration, Instant, SystemTime, UNIX_EPOCH}, }; +use alloy_dyn_abi::eip712::TypedData; use edr_eth::{ block::{ calculate_next_base_fee_per_blob_gas, calculate_next_base_fee_per_gas, miner_reward, @@ -49,7 +50,6 @@ use edr_evm::{ OrderedTransaction, RandomHashGenerator, StorageSlot, SyncBlock, TracerEip3155, TxEnv, KECCAK_EMPTY, }; -use ethers_core::types::transaction::eip712::{Eip712, TypedData}; use gas::gas_used_ratio; use indexmap::IndexMap; use itertools::izip; @@ -1774,7 +1774,14 @@ impl ProviderData Result> { match self.local_accounts.get(address) { Some(secret_key) => { - let hash: B256 = message.encode_eip712()?.into(); + let hash: B256 = message + // TODO https://github.com/NomicFoundation/edr/issues/445 + // This returns B256, but we're currently using the EIP-712 types for Alloy from + // Git, so we need to convert it to a slice before converting to our B256. + .eip712_signing_hash()? + .as_slice() + .try_into() + .expect("Git and released version of B256 are compatible"); Ok(Signature::new(RecoveryMessage::Hash(hash), secret_key)?) } None => Err(ProviderError::UnknownAddress { address: *address }), diff --git a/crates/edr_provider/src/error.rs b/crates/edr_provider/src/error.rs index a8fb27c92..6457fd5f7 100644 --- a/crates/edr_provider/src/error.rs +++ b/crates/edr_provider/src/error.rs @@ -14,7 +14,6 @@ use edr_evm::{ DebugTraceError, ExecutionResult, HaltReason, MemPoolAddTransactionError, MineBlockError, MineTransactionError, OutOfGasError, TransactionCreationError, TransactionError, }; -use ethers_core::types::transaction::eip712::Eip712Error; use crate::{data::CreationError, IntervalConfigConversionError}; @@ -61,7 +60,7 @@ pub enum ProviderError { #[error("An EIP-4844 (shard blob) transaction is missing the to (receiver) parameter.")] Eip4844TransactionMissingReceiver, #[error(transparent)] - Eip712Error(#[from] Eip712Error), + Eip712Error(#[from] alloy_dyn_abi::Error), /// A transaction error occurred while estimating gas. #[error(transparent)] EstimateGasTransactionFailure(#[from] EstimateGasFailure), diff --git a/crates/edr_provider/src/requests/eth/sign.rs b/crates/edr_provider/src/requests/eth/sign.rs index 4aff0b285..0ef0fcce7 100644 --- a/crates/edr_provider/src/requests/eth/sign.rs +++ b/crates/edr_provider/src/requests/eth/sign.rs @@ -1,7 +1,7 @@ use core::fmt::Debug; +use alloy_dyn_abi::eip712::TypedData; use edr_eth::{Address, Bytes}; -use ethers_core::types::transaction::eip712::TypedData; use crate::{data::ProviderData, time::TimeSinceEpoch, ProviderError}; diff --git a/crates/edr_provider/src/requests/methods.rs b/crates/edr_provider/src/requests/methods.rs index 9314784ef..ff970845f 100644 --- a/crates/edr_provider/src/requests/methods.rs +++ b/crates/edr_provider/src/requests/methods.rs @@ -1,3 +1,4 @@ +use alloy_dyn_abi::eip712::TypedData; use edr_eth::{ remote::{ eth::CallRequest, @@ -8,7 +9,6 @@ use edr_eth::{ transaction::EthTransactionRequest, Address, Bytes, B256, U256, U64, }; -use ethers_core::types::transaction::eip712::TypedData; use super::serde::RpcAddress; use crate::requests::{ @@ -222,7 +222,7 @@ pub enum MethodInvocation { #[serde(rename = "eth_signTypedData_v4")] SignTypedDataV4( #[serde(deserialize_with = "crate::requests::serde::deserialize_address")] Address, - #[serde(deserialize_with = "crate::requests::serde::typed_data::deserialize")] TypedData, + #[serde(deserialize_with = "crate::requests::serde::deserialize_typed_data")] TypedData, ), /// `eth_subscribe` #[serde(rename = "eth_subscribe")] diff --git a/crates/edr_provider/src/requests/serde.rs b/crates/edr_provider/src/requests/serde.rs index 4bf0a5d36..0416bbed4 100644 --- a/crates/edr_provider/src/requests/serde.rs +++ b/crates/edr_provider/src/requests/serde.rs @@ -4,6 +4,7 @@ use std::{ str::FromStr, }; +use alloy_dyn_abi::TypedData; use edr_eth::{Address, Bytes, U256, U64}; use serde::{Deserialize, Deserializer, Serialize}; @@ -410,137 +411,17 @@ pub(crate) mod storage_value { } } -/// Helper module for deserializing the payload of an `eth_signTypedData_v4` -/// request. The types and the deserializer implementation are a patched version -/// of [`ethers_core`](https://github.com/gakonst/ethers-rs/blob/5394d899adca736a602e316e6f0c06fdb5aa64b9/ethers-core/src/types/transaction/eip712.rs) -/// in order to support hex strings for the salt parameter. -/// `ethers_core` is copyright (c) 2020 Georgios Konstantopoulos and is licensed -/// under the MIT License. -pub(crate) mod typed_data { - use std::collections::BTreeMap; - - use edr_eth::Bytes; - use ethers_core::types::transaction::eip712::{EIP712Domain, TypedData, Types}; - use serde::{Deserialize, Deserializer}; - - #[derive(Debug, Deserialize)] - #[serde(rename_all = "camelCase")] - struct PatchedEIP712Domain { - #[serde(default, skip_serializing_if = "Option::is_none")] - name: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - version: Option, - - #[serde( - default, - skip_serializing_if = "Option::is_none", - deserialize_with = "ethers_core::types::serde_helpers::deserialize_stringified_numeric_opt" - )] - chain_id: Option, - - #[serde(default, skip_serializing_if = "Option::is_none")] - verifying_contract: Option, - - // Changed salt from `[u8; 32]` to `Bytes` to support hex strings. - #[serde(default, skip_serializing_if = "Option::is_none")] - salt: Option, - } - - #[derive(Debug, thiserror::Error)] - #[error("The salt parameter must be exactly 32 bytes long.")] - struct InvalidSaltError; - - impl TryFrom for EIP712Domain { - type Error = InvalidSaltError; - - fn try_from(value: PatchedEIP712Domain) -> Result { - let PatchedEIP712Domain { - name, - version, - chain_id, - verifying_contract, - salt, - } = value; - - let salt: Option<[u8; 32]> = salt - .map(|bytes| { - let vec: Vec = bytes.into(); - vec.try_into().map_err(|_error| InvalidSaltError {}) - }) - .transpose()?; - - Ok(EIP712Domain { - name, - version, - chain_id, - verifying_contract, - salt, - }) - } - } - - #[derive(Deserialize)] - struct TypedDataHelper { - domain: PatchedEIP712Domain, - types: Types, - #[serde(rename = "primaryType")] - primary_type: String, - message: BTreeMap, - } - - #[derive(Deserialize)] - #[serde(untagged)] - enum Type { - Val(TypedDataHelper), - String(String), - } - - fn invalid_json_error<'de, DeserializerT: Deserializer<'de>>( - _error: impl std::error::Error, - ) -> DeserializerT::Error { +/// Helper function for deserializing the payload of an `eth_signTypedData_v4` +/// request. +pub(crate) fn deserialize_typed_data<'de, DeserializerT>( + deserializer: DeserializerT, +) -> Result +where + DeserializerT: Deserializer<'de>, +{ + TypedData::deserialize(deserializer).map_err(|_error| { serde::de::Error::custom("The message parameter is an invalid JSON.".to_string()) - } - - /// Helper function for deserializing the payload of an - /// `eth_signTypedData_v4` request. - pub(crate) fn deserialize<'de, DeserializerT>( - deserializer: DeserializerT, - ) -> Result - where - DeserializerT: Deserializer<'de>, - { - match Type::deserialize(deserializer).map_err(invalid_json_error::<'de, DeserializerT>)? { - Type::Val(v) => { - let TypedDataHelper { - domain, - types, - primary_type, - message, - } = v; - Ok(TypedData { - domain: domain.try_into().map_err(serde::de::Error::custom)?, - types, - primary_type, - message, - }) - } - Type::String(s) => { - let TypedDataHelper { - domain, - types, - primary_type, - message, - } = serde_json::from_str(&s).map_err(invalid_json_error::<'de, DeserializerT>)?; - Ok(TypedData { - domain: domain.try_into().map_err(serde::de::Error::custom)?, - types, - primary_type, - message, - }) - } - } - } + }) } fn invalid_hex<'de, D>(value: &str) -> D::Error diff --git a/crates/edr_provider/tests/issue_407.rs b/crates/edr_provider/tests/issue_407.rs new file mode 100644 index 000000000..dc58299b8 --- /dev/null +++ b/crates/edr_provider/tests/issue_407.rs @@ -0,0 +1,137 @@ +#![cfg(feature = "test-utils")] + +use edr_provider::{test_utils::create_test_config, time::CurrentTime, NoopLogger, Provider}; +use serde_json::json; +use tokio::runtime; + +// https://github.com/NomicFoundation/edr/issues/407 + +#[tokio::test(flavor = "multi_thread")] +async fn issue_407_uint() -> anyhow::Result<()> { + let config = create_test_config(); + let logger = Box::new(NoopLogger); + let subscriber = Box::new(|_event| {}); + let provider = Provider::new( + runtime::Handle::current(), + logger, + subscriber, + config, + CurrentTime, + )?; + + let request_with_uint = json!({ + "method": "eth_signTypedData_v4", + "params": [ + "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + { + "types": { + "Test": [ + { + "name": "amount", + "type": "uint256" + } + ], + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ] + }, + "domain": { + "name": "TestName", + "version": "1", + "chainId": "0x7a69", + "verifyingContract": "0x1111111111111111111111111111111111111111" + }, + "primaryType": "Test", + "message": { + "amount": "1234" + } + } + ] + }); + + let response = provider.handle_request(serde_json::from_value(request_with_uint)?)?; + + assert_eq!(response.result, "0x2d9b08a9086931cc3ebb9ae446d440e43f0e4ca0abedd2d973af8278c5471bb54181a8dae6018d14d29d62facc535fbba5b4010cdb3f06c0ddcf72e2663583361b"); + + Ok(()) +} + +#[tokio::test(flavor = "multi_thread")] +async fn issue_407_int() -> anyhow::Result<()> { + let config = create_test_config(); + let logger = Box::new(NoopLogger); + let subscriber = Box::new(|_event| {}); + let provider = Provider::new( + runtime::Handle::current(), + logger, + subscriber, + config, + CurrentTime, + )?; + + let request_with_uint = json!({ + "method": "eth_signTypedData_v4", + "params": [ + "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + { + "types": { + "Test": [ + { + "name": "amount", + "type": "int256" + } + ], + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ] + }, + "domain": { + "name": "TestName", + "version": "1", + "chainId": "0x7a69", + "verifyingContract": "0x1111111111111111111111111111111111111111" + }, + "primaryType": "Test", + "message": { + "amount": "1234" + } + } + ] + }); + + let response = provider.handle_request(serde_json::from_value(request_with_uint)?)?; + + assert_eq!(response.result, "0x30622c2e4318a3ffb2755ca111f42409bd5a4190b4b8a9b5f42227313708ecb54889d229dfb7dcfb246f15e7567ef7471fb26a7e99d83631d266a144502ee29f1c"); + + Ok(()) +}