diff --git a/Cargo.lock b/Cargo.lock index 3dca59ba8..bc1db31c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2048,14 +2048,15 @@ version = "0.1.0" dependencies = [ "ethers-contract", "ethers-core", - "ethers-middleware", "ethers-providers", "ethers-signers", "eyre", "group", + "hex", "k256", "modular-frost", "rand_core", + "serde", "serde_json", "sha2", "sha3", @@ -2166,48 +2167,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "ethers-etherscan" -version = "2.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e53451ea4a8128fbce33966da71132cf9e1040dcfd2a2084fd7733ada7b2045" -dependencies = [ - "ethers-core", - "reqwest", - "semver 1.0.20", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "ethers-middleware" -version = "2.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473f1ccd0c793871bbc248729fa8df7e6d2981d6226e4343e3bbaa9281074d5d" -dependencies = [ - "async-trait", - "auto_impl", - "ethers-contract", - "ethers-core", - "ethers-etherscan", - "ethers-providers", - "ethers-signers", - "futures-channel", - "futures-locks", - "futures-util", - "instant", - "reqwest", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "tracing-futures", - "url", -] - [[package]] name = "ethers-providers" version = "2.0.10" @@ -2758,16 +2717,6 @@ dependencies = [ "waker-fn", ] -[[package]] -name = "futures-locks" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" -dependencies = [ - "futures-channel", - "futures-task", -] - [[package]] name = "futures-macro" version = "0.3.29" diff --git a/coins/ethereum/Cargo.toml b/coins/ethereum/Cargo.toml index 53b5342de..64755c80a 100644 --- a/coins/ethereum/Cargo.toml +++ b/coins/ethereum/Cargo.toml @@ -16,8 +16,6 @@ rustdoc-args = ["--cfg", "docsrs"] thiserror = { version = "1", default-features = false } eyre = { version = "0.6", default-features = false } -serde_json = { version = "1", default-features = false, features = ["std"] } - sha3 = { version = "0.10", default-features = false, features = ["std"] } group = { version = "0.13", default-features = false } @@ -26,11 +24,16 @@ frost = { package = "modular-frost", path = "../../crypto/frost", features = ["s ethers-core = { version = "2", default-features = false } ethers-signers = { version = "2", default-features = false } -ethers-middleware = { version = "2", default-features = false } ethers-providers = { version = "2", default-features = false } ethers-contract = { version = "2", default-features = false, features = ["abigen", "providers"] } [dev-dependencies] rand_core = { version = "0.6", default-features = false, features = ["std"] } + +hex = { version = "0.4", default-features = false, features = ["std"] } +serde = { version = "1", default-features = false, features = ["std"] } +serde_json = { version = "1", default-features = false, features = ["std"] } + sha2 = { version = "0.10", default-features = false, features = ["std"] } + tokio = { version = "1", features = ["macros"] } diff --git a/coins/ethereum/src/contract.rs b/coins/ethereum/src/contract.rs index f952d9d13..19104005d 100644 --- a/coins/ethereum/src/contract.rs +++ b/coins/ethereum/src/contract.rs @@ -1,13 +1,8 @@ -use std::{sync::Arc, fs::File}; - use thiserror::Error; use eyre::{eyre, Result}; -use ethers_signers::LocalWallet; -use ethers_middleware::SignerMiddleware; use ethers_providers::{Provider, Http}; -use ethers_contract::{abigen, ContractFactory}; -use ethers_solc::artifacts::contract::ContractBytecode; +use ethers_contract::abigen; use crate::crypto::ProcessedSignature; @@ -19,21 +14,8 @@ pub enum EthereumError { abigen!(Schnorr, "./artifacts/Schnorr.sol/Schnorr.json"); -pub async fn deploy_schnorr_verifier_contract( - client: Arc, LocalWallet>>, -) -> Result, LocalWallet>>> { - let path = "./artifacts/Schnorr.sol/Schnorr.json"; - let artifact: ContractBytecode = serde_json::from_reader(File::open(path).unwrap()).unwrap(); - let abi = artifact.abi.unwrap(); - let bin = artifact.bytecode.unwrap().object; - let factory = ContractFactory::new(abi, bin.into_bytes().unwrap(), client.clone()); - let contract = factory.deploy(())?.send().await?; - let contract = Schnorr::new(contract.address(), client); - Ok(contract) -} - pub async fn call_verify( - contract: &Schnorr, LocalWallet>>, + contract: &Schnorr>, params: &ProcessedSignature, ) -> Result<()> { if contract diff --git a/coins/ethereum/tests/contract.rs b/coins/ethereum/tests/contract.rs index fd99957ad..11b3583eb 100644 --- a/coins/ethereum/tests/contract.rs +++ b/coins/ethereum/tests/contract.rs @@ -1,13 +1,16 @@ -use std::{convert::TryFrom, sync::Arc, time::Duration}; +use std::{convert::TryFrom, sync::Arc, time::Duration, fs::File}; use rand_core::OsRng; use ::k256::{elliptic_curve::bigint::ArrayEncoding, U256}; -use ethers_core::utils::{keccak256, Anvil, AnvilInstance}; -use ethers_middleware::{Middleware, SignerMiddleware}; -use ethers_providers::{Provider, Http}; -use ethers_signers::LocalWallet; +use ethers_core::{ + abi::Abi, + utils::{keccak256, Anvil, AnvilInstance}, +}; +use ethers_contract::ContractFactory; +use ethers_providers::{Middleware, Provider, Http}; +use ethers_signers::{Signer, LocalWallet}; use frost::{ curve::Secp256k1, @@ -18,20 +21,71 @@ use frost::{ use ethereum_serai::{ crypto, - contract::{Schnorr, call_verify, deploy_schnorr_verifier_contract}, + contract::{Schnorr, call_verify}, }; -async fn deploy_test_contract( -) -> (u32, AnvilInstance, Schnorr, LocalWallet>>) { +#[derive(serde::Deserialize)] +struct Bytecode { + object: String, +} + +#[derive(serde::Deserialize)] +struct Artifact { + abi: Option, + bytecode: Bytecode, +} + +// TODO: Replace with a contract deployment from an unknown account, so the environment solely has +// to fund the deployer, not create/pass a wallet +pub async fn deploy_schnorr_verifier_contract( + chain_id: u32, + client: Arc>, + wallet: &LocalWallet, +) -> eyre::Result>> { + let path = "./artifacts/Schnorr.sol/Schnorr.json"; + let artifact: Artifact = serde_json::from_reader(File::open(path).unwrap()).unwrap(); + let abi = artifact.abi.unwrap(); + let hex_bin_buf = artifact.bytecode.object; + let hex_bin = + if let Some(stripped) = hex_bin_buf.strip_prefix("0x") { stripped } else { &hex_bin_buf }; + let bin = hex::decode(hex_bin).unwrap(); + let factory = ContractFactory::new(abi, bin.into(), client.clone()); + + let mut deployment_tx = factory.deploy(())?.tx; + deployment_tx.set_chain_id(chain_id); + deployment_tx.set_gas(500_000); + let (max_fee_per_gas, max_priority_fee_per_gas) = client.estimate_eip1559_fees(None).await?; + deployment_tx.as_eip1559_mut().unwrap().max_fee_per_gas = Some(max_fee_per_gas); + deployment_tx.as_eip1559_mut().unwrap().max_priority_fee_per_gas = Some(max_priority_fee_per_gas); + let signature = wallet.sign_transaction_sync(&deployment_tx)?; + let deployment_tx = deployment_tx.rlp_signed(&signature); + let pending_tx = client.send_raw_transaction(deployment_tx).await?; + + let mut receipt; + while { + receipt = client.get_transaction_receipt(pending_tx.tx_hash()).await?; + receipt.is_none() + } { + tokio::time::sleep(Duration::from_secs(6)).await; + } + let receipt = receipt.unwrap(); + assert!(receipt.status == Some(1.into())); + + let contract = Schnorr::new(receipt.contract_address.unwrap(), client.clone()); + Ok(contract) +} + +async fn deploy_test_contract() -> (u32, AnvilInstance, Schnorr>) { let anvil = Anvil::new().spawn(); - let wallet: LocalWallet = anvil.keys()[0].clone().into(); let provider = Provider::::try_from(anvil.endpoint()).unwrap().interval(Duration::from_millis(10u64)); let chain_id = provider.get_chainid().await.unwrap().as_u32(); - let client = Arc::new(SignerMiddleware::new_with_provider_chain(provider, wallet).await.unwrap()); + let wallet: LocalWallet = anvil.keys()[0].clone().into(); + let wallet = wallet.with_chain_id(chain_id); + let client = Arc::new(provider); - (chain_id, anvil, deploy_schnorr_verifier_contract(client).await.unwrap()) + (chain_id, anvil, deploy_schnorr_verifier_contract(chain_id, client, &wallet).await.unwrap()) } #[tokio::test]