Repository: gakonst/ethers-rs
Pull request #865 (2022-02-05 00:50:11)

feat(ethers-contract): add `send_with_receipt` to `Deployer`


<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.

Bug fixes and new features should include tests.

Contributors guide: https://github.com/gakonst/ethers-rs/blob/master/CONTRIBUTING.md

The contributors guide includes instructions for running rustfmt and building the
documentation.
-->

## Motivation

I'd like to print the transaction hash when using `forge create` and its just generally
useful to have a reference to the receipt when deploying a contract. Currently
this is not possible due to the interface on the `Deployer`

<!--
Explain the context and why you're making that change. What is the problem
you're trying to solve? In some cases there is not a problem and this can be
thought of as being the motivation for your change.
-->

## Solution

The `Deployer` is used to deploy contracts and its `send`
function returns an attached instance of a `Contract`.
There is no way to know the transaction hash of the
deployment transaction, so this commit adds another
method `send_with_receipt` that returns an attached
`Contract` as well as a `TransactionReceipt`.

<!--
Summarize the solution and provide any necessary context needed to understand
the code change.
-->

## PR Checklist

- [x] Added Tests
- [x] Added Documentation
- [x] Updated the changelog



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e3327b8a..7379e9b2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,9 @@
   [#854](https://github.com/gakonst/ethers-rs/pull/852)
 - Refactor `ethers-contract-abigen` to use `eyre` instead of `anyhow` via
   [#858](https://github.com/gakonst/ethers-rs/pull/858)
+- Add `Deployer.send_with_receipt -> Result<(Contract, Receipt), Error>`
+  so that the receipt can be returned to the called when deploying
+  a contract [#865](https://github.com/gakonst/ethers-rs/pull/865)
 - Add Arbitrum mainnet and testnet to the list of known chains
 
 ## ethers-contract-abigen
diff --git a/ethers-contract/src/factory.rs b/ethers-contract/src/factory.rs
index eee777bc..9e7103ca 100644
--- a/ethers-contract/src/factory.rs
+++ b/ethers-contract/src/factory.rs
@@ -2,7 +2,10 @@ use crate::{Contract, ContractError};
 
 use ethers_core::{
     abi::{Abi, Token, Tokenize},
-    types::{transaction::eip2718::TypedTransaction, BlockNumber, Bytes, TransactionRequest},
+    types::{
+        transaction::eip2718::TypedTransaction, BlockNumber, Bytes, TransactionReceipt,
+        TransactionRequest,
+    },
 };
 use ethers_providers::Middleware;
 
@@ -66,6 +69,17 @@ impl<M: Middleware> Deployer<M> {
     /// be sufficiently confirmed (default: 1), it returns a [`Contract`](crate::Contract)
     /// struct at the deployed contract's address.
     pub async fn send(self) -> Result<Contract<M>, ContractError<M>> {
+        let (contract, _) = self.send_with_receipt().await?;
+        Ok(contract)
+    }
+
+    /// Broadcasts the contract deployment transaction and after waiting for it to
+    /// be sufficiently confirmed (default: 1), it returns a tuple with
+    /// the [`Contract`](crate::Contract) struct at the deployed contract's address
+    /// and the corresponding [`TransactionReceipt`](ethers_core::types::TransactionReceipt).
+    pub async fn send_with_receipt(
+        self,
+    ) -> Result<(Contract<M>, TransactionReceipt), ContractError<M>> {
         let pending_tx = self
             .client
             .send_transaction(self.tx, Some(self.block.into()))
@@ -81,7 +95,7 @@ impl<M: Middleware> Deployer<M> {
         let address = receipt.contract_address.ok_or(ContractError::ContractNotDeployed)?;
 
         let contract = Contract::new(address, self.abi.clone(), self.client);
-        Ok(contract)
+        Ok((contract, receipt))
     }
 
     /// Returns a reference to the deployer's ABI


Test patch:
diff --git a/ethers-contract/tests/contract.rs b/ethers-contract/tests/contract.rs
index 17bfe11e..09f82878 100644
--- a/ethers-contract/tests/contract.rs
+++ b/ethers-contract/tests/contract.rs
@@ -42,7 +42,8 @@ mod eth_tests {
         // 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 (contract, receipt) = deployer.clone().send_with_receipt().await.unwrap();
+        assert_eq!(receipt.contract_address.unwrap(), contract.address());
 
         let get_value = contract.method::<_, String>("getValue", ()).unwrap();
         let last_sender = contract.method::<_, Address>("lastSender", ()).unwrap();