From 792d41584557e292707afd64175f36b21871a731 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Tue, 30 Aug 2022 18:45:36 +0200 Subject: [PATCH] fix: set chain id explicitly (#1647) --- ethers-contract/tests/it/abigen.rs | 5 +-- ethers-core/src/utils/anvil.rs | 22 ++++++++++-- ethers-middleware/tests/signer.rs | 34 +++++++++++++++++++ examples/contract_human_readable.rs | 2 +- examples/contract_with_abi.rs | 2 +- examples/contract_with_abi_and_bytecode.rs | 2 +- .../ethers-wasm/tests/contract_with_abi.rs | 16 +++++---- examples/local_signer.rs | 2 +- 8 files changed, 70 insertions(+), 15 deletions(-) diff --git a/ethers-contract/tests/it/abigen.rs b/ethers-contract/tests/it/abigen.rs index 15658294..273498d0 100644 --- a/ethers-contract/tests/it/abigen.rs +++ b/ethers-contract/tests/it/abigen.rs @@ -4,7 +4,7 @@ use ethers_contract::{abigen, Abigen, EthCall, EthEvent}; use ethers_core::{ abi::{AbiDecode, AbiEncode, Address, Tokenizable}, - types::{transaction::eip2718::TypedTransaction, Eip1559TransactionRequest, U256}, + types::{transaction::eip2718::TypedTransaction, Chain, Eip1559TransactionRequest, U256}, utils::Anvil, }; use ethers_middleware::SignerMiddleware; @@ -608,7 +608,8 @@ async fn can_send_struct_param() { let server = Anvil::new().spawn(); let wallet: LocalWallet = server.keys()[0].clone().into(); let provider = Provider::try_from(server.endpoint()).unwrap(); - let client = Arc::new(SignerMiddleware::new(provider, wallet.with_chain_id(1337u64))); + let client = + Arc::new(SignerMiddleware::new(provider, wallet.with_chain_id(Chain::AnvilHardhat))); let contract = StructContract::deploy(client, ()).unwrap().legacy().send().await.unwrap(); diff --git a/ethers-core/src/utils/anvil.rs b/ethers-core/src/utils/anvil.rs index ac941b5b..05cfabed 100644 --- a/ethers-core/src/utils/anvil.rs +++ b/ethers-core/src/utils/anvil.rs @@ -1,5 +1,5 @@ use crate::{ - types::Address, + types::{Address, Chain}, utils::{secret_key_to_address, unused_port}, }; use k256::{ecdsa::SigningKey, SecretKey as K256SecretKey}; @@ -21,6 +21,7 @@ pub struct AnvilInstance { private_keys: Vec, addresses: Vec
, port: u16, + chain_id: Option, } impl AnvilInstance { @@ -39,6 +40,11 @@ impl AnvilInstance { self.port } + /// Returns the chain of the anvil instance + pub fn chain_id(&self) -> u64 { + self.chain_id.unwrap_or_else(|| Chain::AnvilHardhat.into()) + } + /// Returns the HTTP endpoint of this instance pub fn endpoint(&self) -> String { format!("http://localhost:{}", self.port) @@ -82,6 +88,7 @@ pub struct Anvil { program: Option, port: Option, block_time: Option, + chain_id: Option, mnemonic: Option, fork: Option, fork_block_number: Option, @@ -139,6 +146,13 @@ impl Anvil { self } + /// Sets the chain_id the `anvil` instance will use. + #[must_use] + pub fn chain_id>(mut self, chain_id: T) -> Self { + self.chain_id = Some(chain_id.into()); + self + } + /// Sets the mnemonic which will be used when the `anvil` instance is launched. #[must_use] pub fn mnemonic>(mut self, mnemonic: T) -> Self { @@ -208,6 +222,10 @@ impl Anvil { cmd.arg("-m").arg(mnemonic); } + if let Some(chain_id) = self.chain_id { + cmd.arg("--chain-id").arg(chain_id.to_string()); + } + if let Some(block_time) = self.block_time { cmd.arg("-b").arg(block_time.to_string()); } @@ -258,7 +276,7 @@ impl Anvil { child.stdout = Some(reader.into_inner()); - AnvilInstance { pid: child, private_keys, addresses, port } + AnvilInstance { pid: child, private_keys, addresses, port, chain_id: self.chain_id } } } diff --git a/ethers-middleware/tests/signer.rs b/ethers-middleware/tests/signer.rs index 0f1e94ff..3929e7c5 100644 --- a/ethers-middleware/tests/signer.rs +++ b/ethers-middleware/tests/signer.rs @@ -50,6 +50,40 @@ async fn send_eth() { assert!(balance_before > balance_after); } +// hardhat compatibility test, to show hardhat rejects tx signed for other chains +#[tokio::test] +#[cfg(not(feature = "celo"))] +#[ignore] +async fn send_with_chain_id_hardhat() { + let wallet: LocalWallet = + "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".parse().unwrap(); + let provider = Provider::try_from("http://localhost:8545").unwrap(); + let client = SignerMiddleware::new(provider, wallet); + + let tx = TransactionRequest::new().to(Address::random()).value(100u64); + let res = client.send_transaction(tx, None).await; + + let err = res.unwrap_err(); + assert!(err + .to_string() + .contains("Trying to send an incompatible EIP-155 transaction, signed for another chain.")); +} + +#[tokio::test] +#[cfg(not(feature = "celo"))] +#[ignore] +async fn send_with_chain_id_anvil() { + let wallet: LocalWallet = + "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".parse().unwrap(); + let provider = Provider::try_from("http://localhost:8545").unwrap(); + let client = SignerMiddleware::new(provider, wallet); + + let tx = TransactionRequest::new().to(Address::random()).value(100u64); + let res = client.send_transaction(tx, None).await; + + let _err = res.unwrap_err(); +} + #[tokio::test] #[cfg(not(feature = "celo"))] async fn pending_txs_with_confirmations_testnet() { diff --git a/examples/contract_human_readable.rs b/examples/contract_human_readable.rs index 33ddc2d2..3148dc58 100644 --- a/examples/contract_human_readable.rs +++ b/examples/contract_human_readable.rs @@ -42,7 +42,7 @@ async fn main() -> Result<()> { Provider::::try_from(anvil.endpoint())?.interval(Duration::from_millis(10u64)); // 4. instantiate the client with the wallet - let client = SignerMiddleware::new(provider, wallet); + let client = SignerMiddleware::new(provider, wallet.with_chain_id(anvil.chain_id())); let client = Arc::new(client); // 5. create a factory which will be used to deploy instances of the contract diff --git a/examples/contract_with_abi.rs b/examples/contract_with_abi.rs index 67219a78..35425777 100644 --- a/examples/contract_with_abi.rs +++ b/examples/contract_with_abi.rs @@ -31,7 +31,7 @@ async fn main() -> Result<()> { Provider::::try_from(anvil.endpoint())?.interval(Duration::from_millis(10u64)); // 4. instantiate the client with the wallet - let client = SignerMiddleware::new(provider, wallet); + let client = SignerMiddleware::new(provider, wallet.with_chain_id(anvil.chain_id())); let client = Arc::new(client); // 5. create a factory which will be used to deploy instances of the contract diff --git a/examples/contract_with_abi_and_bytecode.rs b/examples/contract_with_abi_and_bytecode.rs index c1920b12..2748e252 100644 --- a/examples/contract_with_abi_and_bytecode.rs +++ b/examples/contract_with_abi_and_bytecode.rs @@ -22,7 +22,7 @@ async fn main() -> Result<()> { Provider::::try_from(anvil.endpoint())?.interval(Duration::from_millis(10u64)); // 4. instantiate the client with the wallet - let client = Arc::new(SignerMiddleware::new(provider, wallet)); + let client = Arc::new(SignerMiddleware::new(provider, wallet.with_chain_id(anvil.chain_id()))); // 5. deploy contract let greeter_contract = diff --git a/examples/ethers-wasm/tests/contract_with_abi.rs b/examples/ethers-wasm/tests/contract_with_abi.rs index 678f54b2..5530df67 100644 --- a/examples/ethers-wasm/tests/contract_with_abi.rs +++ b/examples/ethers-wasm/tests/contract_with_abi.rs @@ -1,12 +1,14 @@ #![cfg(target_arch = "wasm32")] -use wasm_bindgen_test::*; - -use ethers::prelude::{ - abigen, ContractFactory, Http, JsonRpcClient, LocalWallet, Provider, SignerMiddleware, Ws, +use ethers::{ + prelude::{ + abigen, ContractFactory, Http, JsonRpcClient, LocalWallet, Provider, SignerMiddleware, Ws, + }, + signers::Signer, + types::Chain, }; - use std::{convert::TryFrom, sync::Arc}; +use wasm_bindgen_test::*; wasm_bindgen_test_configure!(run_in_browser); @@ -22,14 +24,14 @@ abigen!( async fn http_connect_and_deploy() { console_log!("connecting http..."); let provider = Provider::::try_from("http://localhost:8545").unwrap(); - deploy(provider, ethers_wasm::utils::key(0)).await; + deploy(provider, ethers_wasm::utils::key(0).with_chain_id(Chain::AnvilHardhat)).await; } #[wasm_bindgen_test] async fn ws_connect_and_deploy() { console_log!("connecting ws..."); let provider = Provider::new(Ws::connect("ws://localhost:8545").await.unwrap()); - deploy(provider, ethers_wasm::utils::key(1)).await; + deploy(provider, ethers_wasm::utils::key(1).with_chain_id(Chain::AnvilHardhat)).await; } async fn deploy(provider: Provider, wallet: LocalWallet) { diff --git a/examples/local_signer.rs b/examples/local_signer.rs index 64c570c3..764de4f5 100644 --- a/examples/local_signer.rs +++ b/examples/local_signer.rs @@ -13,7 +13,7 @@ async fn main() -> Result<()> { let provider = Provider::::try_from(anvil.endpoint())?; // connect the wallet to the provider - let client = SignerMiddleware::new(provider, wallet); + let client = SignerMiddleware::new(provider, wallet.with_chain_id(anvil.chain_id())); // craft the transaction let tx = TransactionRequest::new().to(wallet2.address()).value(10000);