From bd3a7042005c3b4aad92f500e983e26114382ba6 Mon Sep 17 00:00:00 2001 From: Francesco Iannelli <54247008+frjnn@users.noreply.github.com> Date: Thu, 4 Nov 2021 14:02:05 +0100 Subject: [PATCH] Feat/add call deployer (#554) * contract: add .call() method to Deployer It is now possible to dry run a contract deployment. * add .call() method of Deployer to unreleased * add PR to changelog --- CHANGELOG.md | 1 + ethers-contract/src/factory.rs | 13 +++++++++++++ ethers-contract/tests/common/mod.rs | 4 +++- ethers-contract/tests/contract.rs | 3 +++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 594bf543..34933a34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Unreleased +- Add `.call()` method to `Deployer` for performing dry runs of contract deployments. [#554](https://github.com/gakonst/ethers-rs/pull/554) - Improve error message from failure in `ethers_contract_abigen::Source::parse` [#552](https://github.com/gakonst/ethers-rs/pull/552) - use enumerated aliases for overloaded functions [#545](https://github.com/gakonst/ethers-rs/pull/545) - move `AbiEncode` `AbiDecode` trait to ethers-core and implement for core types [#531](https://github.com/gakonst/ethers-rs/pull/531) diff --git a/ethers-contract/src/factory.rs b/ethers-contract/src/factory.rs index 6be23ba8..5bc1a761 100644 --- a/ethers-contract/src/factory.rs +++ b/ethers-contract/src/factory.rs @@ -46,6 +46,19 @@ impl Deployer { self } + /// Dry runs the deployment of the contract + /// + /// Note: this function _does not_ send a transaction from your account + pub async fn call(&self) -> Result<(), ContractError> { + self.client + .call(&self.tx, Some(self.block.into())) + .await + .map_err(ContractError::MiddlewareError)?; + + // TODO: It would be nice to handle reverts in a structured way. + Ok(()) + } + /// Broadcasts the contract deployment transaction and after waiting for it to /// be sufficiently confirmed (default: 1), it returns a [`Contract`](crate::Contract) /// struct at the deployed contract's address. diff --git a/ethers-contract/tests/common/mod.rs b/ethers-contract/tests/common/mod.rs index 1ebf5002..5328b9eb 100644 --- a/ethers-contract/tests/common/mod.rs +++ b/ethers-contract/tests/common/mod.rs @@ -49,5 +49,7 @@ pub fn connect(ganache: &GanacheInstance, idx: usize) -> Arc> { /// Launches a ganache instance and deploys the SimpleStorage contract pub async fn deploy(client: Arc, abi: Abi, bytecode: Bytes) -> Contract { let factory = ContractFactory::new(abi, bytecode, client); - factory.deploy("initial value".to_string()).unwrap().legacy().send().await.unwrap() + let deployer = factory.deploy("initial value".to_string()).unwrap(); + assert!(deployer.call().await.is_ok()); + deployer.legacy().send().await.unwrap() } diff --git a/ethers-contract/tests/contract.rs b/ethers-contract/tests/contract.rs index 2aa0e75f..606a5f34 100644 --- a/ethers-contract/tests/contract.rs +++ b/ethers-contract/tests/contract.rs @@ -39,6 +39,9 @@ mod eth_tests { // (practically it's not expected that you'll need to deploy multiple instances of // the _same_ deployer, so it's fine to clone here from a dev UX vs perf tradeoff) let deployer = factory.deploy("initial value".to_string()).unwrap().legacy(); + // dry runs the deployment of the contract. takes the deployer by reference, no need to + // clone. + assert!(deployer.call().await.is_ok()); let contract = deployer.clone().send().await.unwrap(); let get_value = contract.method::<_, String>("getValue", ()).unwrap();