From e147eb38ae1ada122639da453ecedd412126d463 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Wed, 16 Oct 2024 14:35:45 -0400 Subject: [PATCH] feat: verify message hash --- Cargo.lock | 41 +++++- Cargo.toml | 5 +- README.md | 9 +- src/lib.rs | 335 +++++++++++++++++++++++++++----------------- src/test_helpers.rs | 27 ++-- 5 files changed, 256 insertions(+), 161 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c905a7..9258ec2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,8 @@ dependencies = [ "alloy-rpc-client", "alloy-rpc-types", "alloy-serde 0.3.1", + "alloy-signer", + "alloy-signer-local", "alloy-transport", "alloy-transport-http", ] @@ -457,6 +459,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-signer-local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fabe917ab1778e760b4701628d1cae8e028ee9d52ac6307de4e1e9286ab6b5f" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives 0.8.0", + "alloy-signer", + "async-trait", + "k256", + "rand", + "thiserror", +] + [[package]] name = "alloy-sol-macro" version = "0.8.0" @@ -1121,8 +1139,6 @@ dependencies = [ "alloy", "alloy-node-bindings", "alloy-primitives 0.8.0", - "k256", - "rand", "regex", "serde_json", "tokio", @@ -1584,7 +1600,6 @@ dependencies = [ "elliptic-curve", "once_cell", "sha2", - "signature", ] [[package]] @@ -1841,6 +1856,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + [[package]] name = "parking_lot_core" version = "0.9.10" @@ -2076,9 +2101,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -2088,9 +2113,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -2624,6 +2649,8 @@ dependencies = [ "bytes", "libc", "mio", + "num_cpus", + "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", diff --git a/Cargo.toml b/Cargo.toml index 6333249..ade7b5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,11 +8,10 @@ license = "MIT OR Apache-2.0" alloy = { version = "0.3", features = ["contract", "rpc-types"] } [dev-dependencies] +alloy = { version = "0.3", features = ["signer-local"] } alloy-node-bindings = { git = "https://github.com/alloy-rs/alloy.git", rev = "d68a6b7" } -k256 = "0.13" -rand = "0.8" regex = "1" -tokio = { version = "1", features = ["test-util", "macros", "process"] } +tokio = { version = "1", features = ["full"] } [build-dependencies] alloy-primitives = { version = "0.8.0" } diff --git a/README.md b/README.md index 1f54711..a06f11f 100644 --- a/README.md +++ b/README.md @@ -23,13 +23,10 @@ erc6492 = { git = "https://github.com/reown-com/erc6492.git", version = "0.1.0" This crate uses [Alloy](https://github.com/alloy-rs) and requires an RPC provider in order to verify all signature types. ```rust -use alloy_primitives::{address, bytes, eip191_hash_message}; -use alloy_provider::{network::Ethereum, ReqwestProvider}; - let address = address!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); -let message = "xxx"; +let message = eip191_hash_message("Hello, world!"); let signature = bytes!("aaaa"); -let provider = ReqwestProvider::::new_http("https://rpc.example.com"); +let provider = ReqwestProvider::::new_http("https://rpc.example.com".parse().unwrap()); let verification = verify_signature(signature, address, message, provider).await.unwrap(); if verification.is_valid() { @@ -37,4 +34,4 @@ if verification.is_valid() { } ``` -See test cases in `src/lib.rs` for more examples. +See doctest on `verify_signature()` and test cases in `src/lib.rs` for more examples. diff --git a/src/lib.rs b/src/lib.rs index d1fcc63..4e02107 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ use alloy::{ - primitives::{eip191_hash_message, Address, Bytes}, + primitives::{Address, Bytes, B256}, providers::Provider, rpc::types::{TransactionInput, TransactionRequest}, sol, @@ -39,22 +39,39 @@ pub type RpcError = alloy::transports::RpcError; /// If the signature is invalid, it will return `Ok(Verification::Invalid)`. /// /// If an error occurs while making the RPC call, it will return `Err(RpcError)`. -pub async fn verify_signature( - signature: S, +/// ```rust +/// # use alloy::primitives::eip191_hash_message; +/// # use alloy::providers::{network::Ethereum, ReqwestProvider}; +/// # use alloy::signers::{local::LocalSigner, SignerSync}; +/// # use erc6492::verify_signature; +/// # +/// # #[tokio::main] +/// # async fn main() { +/// # let account = LocalSigner::random(); +/// # let message = "Hello, world!"; +/// # let message_hash = eip191_hash_message(message); +/// # let signature = account.sign_message_sync(message.as_bytes()).unwrap().as_bytes().into(); +/// # let address = account.address(); +/// # +/// # let provider = ReqwestProvider::::new_http("https://rpc.sepolia.org".parse().unwrap()); +/// let verification = verify_signature(signature, address, message_hash, &provider).await.unwrap(); +/// assert!(verification.is_valid()); +/// # } +/// ``` +pub async fn verify_signature( + signature: Bytes, address: Address, - message: M, + message_hash: B256, provider: &P, ) -> Result where - S: Into, - M: AsRef<[u8]>, P: Provider, T: Transport + Clone, { let call = ValidateSigOffchain::constructorCall { _signer: address, - _hash: eip191_hash_message(message), - _signature: signature.into(), + _hash: message_hash, + _signature: signature, }; let bytes = VALIDATE_SIG_OFFCHAIN_BYTECODE .iter() @@ -101,14 +118,12 @@ mod test { super::*, alloy::{ network::Ethereum, - primitives::{address, b256, bytes, Uint}, + primitives::{address, b256, bytes, eip191_hash_message, Uint}, providers::ReqwestProvider, + signers::{k256::ecdsa::SigningKey, local::LocalSigner, SignerSync}, sol_types::{SolCall, SolValue}, }, - k256::ecdsa::SigningKey, - test_helpers::{ - deploy_contract, sign_message, spawn_anvil, CREATE2_CONTRACT, ERC1271_MOCK_CONTRACT, - }, + test_helpers::{deploy_contract, spawn_anvil, CREATE2_CONTRACT, ERC1271_MOCK_CONTRACT}, }; // Manual test. Paste address, signature, message, and project ID to verify @@ -118,6 +133,7 @@ mod test { async fn manual() { let address = address!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); let message = "xxx"; + let message_hash = eip191_hash_message(message); let signature = bytes!("aaaa"); let provider = ReqwestProvider::::new_http( @@ -125,87 +141,119 @@ mod test { .parse() .unwrap(), ); - assert!(verify_signature(signature, address, message, &provider) - .await - .unwrap() - .is_valid()); + assert!( + verify_signature(signature, address, message_hash, &provider) + .await + .unwrap() + .is_valid() + ); } #[tokio::test] async fn eoa_pass() { - let (_anvil, _rpc_url, provider, _private_key) = spawn_anvil(); + let (_anvil, _rpc_url, provider, _signer) = spawn_anvil(); - let private_key = SigningKey::random(&mut rand::thread_rng()); + let signer = LocalSigner::random(); let message = "xxx"; - let signature = sign_message(message, &private_key); - let address = Address::from_private_key(&private_key); - assert!(verify_signature(signature, address, message, &provider) - .await + let message_hash = eip191_hash_message(message); + let signature = signer + .sign_message_sync(message.as_bytes()) .unwrap() - .is_valid()); + .as_bytes(); + let address = signer.address(); + assert!( + verify_signature(signature.into(), address, message_hash, &provider) + .await + .unwrap() + .is_valid() + ); } #[tokio::test] async fn eoa_wrong_signature() { - let (_anvil, _rpc_url, provider, _private_key) = spawn_anvil(); + let (_anvil, _rpc_url, provider, _signer) = spawn_anvil(); - let private_key = SigningKey::random(&mut rand::thread_rng()); + let signer = LocalSigner::random(); let message = "xxx"; - let mut signature = sign_message(message, &private_key); - *signature.first_mut().unwrap() = signature.first().unwrap().wrapping_add(1); - let address = Address::from_private_key(&private_key); - assert!(!verify_signature(signature, address, message, &provider) - .await + let message_hash = eip191_hash_message(message); + let mut signature = signer + .sign_message_sync(message.as_bytes()) .unwrap() - .is_valid()); + .as_bytes(); + *signature.first_mut().unwrap() = signature.first().unwrap().wrapping_add(1); + let address = signer.address(); + assert!( + !verify_signature(signature.into(), address, message_hash, &provider) + .await + .unwrap() + .is_valid() + ); } #[tokio::test] async fn eoa_wrong_address() { - let (_anvil, _rpc_url, provider, _private_key) = spawn_anvil(); + let (_anvil, _rpc_url, provider, _signer) = spawn_anvil(); - let private_key = SigningKey::random(&mut rand::thread_rng()); + let signer = LocalSigner::random(); let message = "xxx"; - let signature = sign_message(message, &private_key); - let mut address = Address::from_private_key(&private_key); - *address.0.first_mut().unwrap() = address.0.first().unwrap().wrapping_add(1); - assert!(!verify_signature(signature, address, message, &provider) - .await + let message_hash = eip191_hash_message(message); + let signature = signer + .sign_message_sync(message.as_bytes()) .unwrap() - .is_valid()); + .as_bytes(); + let mut address = signer.address(); + *address.0.first_mut().unwrap() = address.0.first().unwrap().wrapping_add(1); + assert!( + !verify_signature(signature.into(), address, message_hash, &provider) + .await + .unwrap() + .is_valid() + ); } #[tokio::test] async fn eoa_wrong_message() { - let (_anvil, _rpc_url, provider, _private_key) = spawn_anvil(); + let (_anvil, _rpc_url, provider, _signer) = spawn_anvil(); - let private_key = SigningKey::random(&mut rand::thread_rng()); + let signer = LocalSigner::random(); let message = "xxx"; - let signature = sign_message(message, &private_key); - let address = Address::from_private_key(&private_key); - let message2 = "yyy"; - assert!(!verify_signature(signature, address, message2, &provider) - .await + let signature = signer + .sign_message_sync(message.as_bytes()) .unwrap() - .is_valid()); + .as_bytes() + .into(); + let address = signer.address(); + let message2 = "yyy"; + let message2_hash = eip191_hash_message(message2); + assert!( + !verify_signature(signature, address, message2_hash, &provider) + .await + .unwrap() + .is_valid() + ); } #[tokio::test] async fn erc1271_pass() { - let (_anvil, rpc_url, provider, private_key) = spawn_anvil(); + let (_anvil, rpc_url, provider, signer) = spawn_anvil(); let contract_address = deploy_contract( &rpc_url, - &private_key, + &signer, ERC1271_MOCK_CONTRACT, - Some(&Address::from_private_key(&private_key).to_string()), + Some(&signer.address().to_string()), ) .await; let message = "xxx"; - let signature = sign_message(message, &private_key); + let message_hash = eip191_hash_message(message); + let signature = signer + .sign_message_sync(message.as_bytes()) + .unwrap() + .as_bytes() + .into(); assert!( - verify_signature(signature, contract_address, message, &provider) + verify_signature(signature, contract_address, message_hash, &provider) .await .unwrap() .is_valid() @@ -214,21 +262,25 @@ mod test { #[tokio::test] async fn erc1271_wrong_signature() { - let (_anvil, rpc_url, provider, private_key) = spawn_anvil(); + let (_anvil, rpc_url, provider, signer) = spawn_anvil(); let contract_address = deploy_contract( &rpc_url, - &private_key, + &signer, ERC1271_MOCK_CONTRACT, - Some(&Address::from_private_key(&private_key).to_string()), + Some(&signer.address().to_string()), ) .await; let message = "xxx"; - let mut signature = sign_message(message, &private_key); + let message_hash = eip191_hash_message(message); + let mut signature = signer + .sign_message_sync(message.as_bytes()) + .unwrap() + .as_bytes(); *signature.first_mut().unwrap() = signature.first().unwrap().wrapping_add(1); assert!( - !verify_signature(signature, contract_address, message, &provider) + !verify_signature(signature.into(), contract_address, message_hash, &provider) .await .unwrap() .is_valid(), @@ -237,23 +289,27 @@ mod test { #[tokio::test] async fn erc1271_wrong_signer() { - let (anvil, rpc_url, provider, private_key) = spawn_anvil(); + let (anvil, rpc_url, provider, signer) = spawn_anvil(); let contract_address = deploy_contract( &rpc_url, - &private_key, + &signer, ERC1271_MOCK_CONTRACT, - Some(&Address::from_private_key(&private_key).to_string()), + Some(&signer.address().to_string()), ) .await; let message = "xxx"; - let signature = sign_message( - message, - &SigningKey::from_bytes(&anvil.keys().get(1).unwrap().to_bytes()).unwrap(), - ); + let message_hash = eip191_hash_message(message); + let signature = LocalSigner::from_signing_key( + SigningKey::from_bytes(&anvil.keys().get(1).unwrap().to_bytes()).unwrap(), + ) + .sign_message_sync(message.as_bytes()) + .unwrap() + .as_bytes() + .into(); assert!( - !verify_signature(signature, contract_address, message, &provider) + !verify_signature(signature, contract_address, message_hash, &provider) .await .unwrap() .is_valid() @@ -262,12 +318,12 @@ mod test { #[tokio::test] async fn erc1271_wrong_contract_address() { - let (_anvil, rpc_url, provider, private_key) = spawn_anvil(); + let (_anvil, rpc_url, provider, signer) = spawn_anvil(); let mut contract_address = deploy_contract( &rpc_url, - &private_key, + &signer, ERC1271_MOCK_CONTRACT, - Some(&Address::from_private_key(&private_key).to_string()), + Some(&signer.address().to_string()), ) .await; @@ -275,10 +331,15 @@ mod test { contract_address.0.first().unwrap().wrapping_add(1); let message = "xxx"; - let signature = sign_message(message, &private_key); + let message_hash = eip191_hash_message(message); + let signature = signer + .sign_message_sync(message.as_bytes()) + .unwrap() + .as_bytes() + .into(); assert!( - !verify_signature(signature, contract_address, message, &provider) + !verify_signature(signature, contract_address, message_hash, &provider) .await .unwrap() .is_valid() @@ -287,21 +348,26 @@ mod test { #[tokio::test] async fn erc1271_wrong_message() { - let (_anvil, rpc_url, provider, private_key) = spawn_anvil(); + let (_anvil, rpc_url, provider, signer) = spawn_anvil(); let contract_address = deploy_contract( &rpc_url, - &private_key, + &signer, ERC1271_MOCK_CONTRACT, - Some(&Address::from_private_key(&private_key).to_string()), + Some(&signer.address().to_string()), ) .await; let message = "xxx"; - let signature = sign_message(message, &private_key); + let signature = signer + .sign_message_sync(message.as_bytes()) + .unwrap() + .as_bytes() + .into(); let message2 = "yyy"; + let message2_hash = eip191_hash_message(message2); assert!( - !verify_signature(signature, contract_address, message2, &provider) + !verify_signature(signature, contract_address, message2_hash, &provider) .await .unwrap() .is_valid(), @@ -370,20 +436,22 @@ mod test { #[tokio::test] async fn erc6492_pass() { - let (_anvil, rpc_url, provider, private_key) = spawn_anvil(); + let (_anvil, rpc_url, provider, signer) = spawn_anvil(); let create2_factory_address = - deploy_contract(&rpc_url, &private_key, CREATE2_CONTRACT, None).await; + deploy_contract(&rpc_url, &signer, CREATE2_CONTRACT, None).await; let message = "xxx"; - let signature = sign_message(message, &private_key); - let (predeploy_address, signature) = predeploy_signature( - Address::from_private_key(&private_key), - create2_factory_address, - signature, - ); + let message_hash = eip191_hash_message(message); + let signature = signer + .sign_message_sync(message.as_bytes()) + .unwrap() + .as_bytes() + .into(); + let (predeploy_address, signature) = + predeploy_signature(signer.address(), create2_factory_address, signature); assert!( - verify_signature(signature, predeploy_address, message, &provider) + verify_signature(signature.into(), predeploy_address, message_hash, &provider) .await .unwrap() .is_valid() @@ -392,21 +460,22 @@ mod test { #[tokio::test] async fn erc6492_wrong_signature() { - let (_anvil, rpc_url, provider, private_key) = spawn_anvil(); + let (_anvil, rpc_url, provider, signer) = spawn_anvil(); let create2_factory_address = - deploy_contract(&rpc_url, &private_key, CREATE2_CONTRACT, None).await; + deploy_contract(&rpc_url, &signer, CREATE2_CONTRACT, None).await; let message = "xxx"; - let mut signature = sign_message(message, &private_key); + let message_hash = eip191_hash_message(message); + let mut signature = signer + .sign_message_sync(message.as_bytes()) + .unwrap() + .as_bytes(); *signature.first_mut().unwrap() = signature.first().unwrap().wrapping_add(1); - let (predeploy_address, signature) = predeploy_signature( - Address::from_private_key(&private_key), - create2_factory_address, - signature, - ); + let (predeploy_address, signature) = + predeploy_signature(signer.address(), create2_factory_address, signature.into()); assert!( - !verify_signature(signature, predeploy_address, message, &provider) + !verify_signature(signature.into(), predeploy_address, message_hash, &provider) .await .unwrap() .is_valid(), @@ -415,23 +484,24 @@ mod test { #[tokio::test] async fn erc6492_wrong_signer() { - let (anvil, rpc_url, provider, private_key) = spawn_anvil(); + let (anvil, rpc_url, provider, signer) = spawn_anvil(); let create2_factory_address = - deploy_contract(&rpc_url, &private_key, CREATE2_CONTRACT, None).await; + deploy_contract(&rpc_url, &signer, CREATE2_CONTRACT, None).await; let message = "xxx"; - let signature = sign_message( - message, - &SigningKey::from_bytes(&anvil.keys().get(1).unwrap().to_bytes()).unwrap(), - ); - let (predeploy_address, signature) = predeploy_signature( - Address::from_private_key(&private_key), - create2_factory_address, - signature, - ); + let message_hash = eip191_hash_message(message); + let signature = LocalSigner::from_signing_key( + SigningKey::from_bytes(&anvil.keys().get(1).unwrap().to_bytes()).unwrap(), + ) + .sign_message_sync(message.as_bytes()) + .unwrap() + .as_bytes() + .into(); + let (predeploy_address, signature) = + predeploy_signature(signer.address(), create2_factory_address, signature); assert!( - !verify_signature(signature, predeploy_address, message, &provider) + !verify_signature(signature.into(), predeploy_address, message_hash, &provider) .await .unwrap() .is_valid(), @@ -440,23 +510,25 @@ mod test { #[tokio::test] async fn erc6492_wrong_contract_address() { - let (_anvil, rpc_url, provider, private_key) = spawn_anvil(); + let (_anvil, rpc_url, provider, signer) = spawn_anvil(); let create2_factory_address = - deploy_contract(&rpc_url, &private_key, CREATE2_CONTRACT, None).await; + deploy_contract(&rpc_url, &signer, CREATE2_CONTRACT, None).await; let message = "xxx"; - let signature = sign_message(message, &private_key); - let (mut predeploy_address, signature) = predeploy_signature( - Address::from_private_key(&private_key), - create2_factory_address, - signature, - ); + let message_hash = eip191_hash_message(message); + let signature = signer + .sign_message_sync(message.as_bytes()) + .unwrap() + .as_bytes() + .into(); + let (mut predeploy_address, signature) = + predeploy_signature(signer.address(), create2_factory_address, signature); *predeploy_address.0.first_mut().unwrap() = predeploy_address.0.first().unwrap().wrapping_add(1); assert!( - !verify_signature(signature, predeploy_address, message, &provider) + !verify_signature(signature.into(), predeploy_address, message_hash, &provider) .await .unwrap() .is_valid(), @@ -465,24 +537,29 @@ mod test { #[tokio::test] async fn erc6492_wrong_message() { - let (_anvil, rpc_url, provider, private_key) = spawn_anvil(); + let (_anvil, rpc_url, provider, signer) = spawn_anvil(); let create2_factory_address = - deploy_contract(&rpc_url, &private_key, CREATE2_CONTRACT, None).await; + deploy_contract(&rpc_url, &signer, CREATE2_CONTRACT, None).await; let message = "xxx"; - let signature = sign_message(message, &private_key); - let (predeploy_address, signature) = predeploy_signature( - Address::from_private_key(&private_key), - create2_factory_address, - signature, - ); + let signature = signer + .sign_message_sync(message.as_bytes()) + .unwrap() + .as_bytes() + .into(); + let (predeploy_address, signature) = + predeploy_signature(signer.address(), create2_factory_address, signature); let message2 = "yyy"; - assert!( - !verify_signature(signature, predeploy_address, message2, &provider) - .await - .unwrap() - .is_valid(), - ); + let message2_hash = eip191_hash_message(message2); + assert!(!verify_signature( + signature.into(), + predeploy_address, + message2_hash, + &provider + ) + .await + .unwrap() + .is_valid()); } } diff --git a/src/test_helpers.rs b/src/test_helpers.rs index 098b991..26e0b4c 100644 --- a/src/test_helpers.rs +++ b/src/test_helpers.rs @@ -2,11 +2,11 @@ use { alloy::{ hex, network::Ethereum, - primitives::{eip191_hash_message, Address}, + primitives::Address, providers::ReqwestProvider, + signers::{k256::ecdsa::SigningKey, local::LocalSigner}, }, alloy_node_bindings::{Anvil, AnvilInstance}, - k256::ecdsa::SigningKey, regex::Regex, std::process::Stdio, tokio::process::Command, @@ -20,7 +20,12 @@ fn format_foundry_dir(path: &str) -> String { ) } -pub fn spawn_anvil() -> (AnvilInstance, String, ReqwestProvider, SigningKey) { +pub fn spawn_anvil() -> ( + AnvilInstance, + String, + ReqwestProvider, + LocalSigner, +) { let anvil = Anvil::at(format_foundry_dir("bin/anvil")).spawn(); let rpc_url = anvil.endpoint(); let provider = ReqwestProvider::::new_http(anvil.endpoint_url()); @@ -29,7 +34,7 @@ pub fn spawn_anvil() -> (AnvilInstance, String, ReqwestProvider, SigningKey) { anvil, rpc_url, provider, - SigningKey::from_bytes(&private_key.to_bytes()).unwrap(), + LocalSigner::from_signing_key(private_key.into()), ) } @@ -38,11 +43,11 @@ pub const CREATE2_CONTRACT: &str = "Create2"; pub async fn deploy_contract( rpc_url: &str, - private_key: &SigningKey, + signer: &LocalSigner, contract_name: &str, constructor_arg: Option<&str>, ) -> Address { - let key_encoded = hex::encode(private_key.to_bytes()); + let key_encoded = hex::encode(signer.to_bytes()); let cache_folder = format_foundry_dir("forge/cache"); let out_folder = format_foundry_dir("forge/out"); let mut args = vec![ @@ -84,13 +89,3 @@ pub async fn deploy_contract( .extract(); contract_address.parse().unwrap() } - -pub fn sign_message(message: &str, private_key: &SigningKey) -> Vec { - let hash = eip191_hash_message(message.as_bytes()); - let (signature, recovery): (k256::ecdsa::Signature, _) = private_key - .sign_prehash_recoverable(hash.as_slice()) - .unwrap(); - let signature = signature.to_bytes(); - // need for +27 is mentioned in ERC-1271 reference implementation - [&signature[..], &[recovery.to_byte() + 27]].concat() -}