From 6faceb20d707f294476f242bec9574e2f5bfa6f5 Mon Sep 17 00:00:00 2001 From: oblique Date: Wed, 27 Apr 2022 15:33:22 +0300 Subject: [PATCH] feat: Relax `Clone` requirements when `Arc` is used (#1183) `#[derive(Clone)]` was implementing `Clone` only if `M` was `Clone`, however because of `Arc` this can be relaxed. --- CHANGELOG.md | 6 ++++ .../src/contract/common.rs | 6 +++- ethers-contract/src/call.rs | 14 +++++++- ethers-contract/src/contract.rs | 12 ++++++- ethers-contract/src/factory.rs | 34 +++++++++++++++++-- ethers-contract/src/multicall/mod.rs | 12 ++++++- .../src/multicall/multicall_contract.rs | 6 +++- ethers-middleware/src/gas_escalator/mod.rs | 13 ++++++- .../src/transformer/ds_proxy/factory.rs | 6 +++- 9 files changed, 99 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 858ab45b..ebd46e94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,8 @@ ### Unreleased +- Relax Clone requirements when Arc is used + [#1183](https://github.com/gakonst/ethers-rs/pull/1183) - Generate a deploy function if bytecode is provided in the abigen! input (json artifact) [#1030](https://github.com/gakonst/ethers-rs/pull/1030). - Generate correct bindings of struct's field names that are reserved words @@ -192,6 +194,8 @@ ### Unreleased +- Relax Clone requirements when Arc is used + [#1183](https://github.com/gakonst/ethers-rs/pull/1183) - Add `EventStream::select` to combine streams with different event types [#725](https://github.com/gakonst/ethers-rs/pull/725) - Substitute output tuples with rust struct types for function calls @@ -235,6 +239,8 @@ ### Unreleased +- Relax Clone requirements when Arc is used + [#1183](https://github.com/gakonst/ethers-rs/pull/1183) - Ensure a consistent chain ID between a Signer and Provider in SignerMiddleware [#1095](https://gakonst/ethers-rs/pull/1095) - Add BlockNative gas oracle [#1175](https://github.com/gakonst/ethers-rs/pull/1175) diff --git a/ethers-contract/ethers-contract-abigen/src/contract/common.rs b/ethers-contract/ethers-contract-abigen/src/contract/common.rs index 818c4ab9..a4bfb4b7 100644 --- a/ethers-contract/ethers-contract-abigen/src/contract/common.rs +++ b/ethers-contract/ethers-contract-abigen/src/contract/common.rs @@ -71,9 +71,13 @@ pub(crate) fn struct_declaration(cx: &Context) -> TokenStream { #bytecode // Struct declaration - #[derive(Clone)] pub struct #name(#ethers_contract::Contract); + impl Clone for #name { + fn clone(&self) -> Self { + #name(self.0.clone()) + } + } // Deref to the inner contract in order to access more specific functions functions impl std::ops::Deref for #name { diff --git a/ethers-contract/src/call.rs b/ethers-contract/src/call.rs index 0abdc23e..c8eb7e1c 100644 --- a/ethers-contract/src/call.rs +++ b/ethers-contract/src/call.rs @@ -63,7 +63,7 @@ pub enum ContractError { ContractNotDeployed, } -#[derive(Debug, Clone)] +#[derive(Debug)] #[must_use = "contract calls do nothing unless you `send` or `call` them"] /// Helper for managing a transaction before submitting it to a node pub struct ContractCall { @@ -77,6 +77,18 @@ pub struct ContractCall { pub(crate) datatype: PhantomData, } +impl Clone for ContractCall { + fn clone(&self) -> Self { + ContractCall { + tx: self.tx.clone(), + function: self.function.clone(), + block: self.block, + client: self.client.clone(), + datatype: self.datatype, + } + } +} + impl ContractCall { /// Sets the `from` field in the transaction to the provided value pub fn from>(mut self, from: T) -> Self { diff --git a/ethers-contract/src/contract.rs b/ethers-contract/src/contract.rs index 1202c0e5..0769619a 100644 --- a/ethers-contract/src/contract.rs +++ b/ethers-contract/src/contract.rs @@ -150,13 +150,23 @@ use std::{fmt::Debug, marker::PhantomData, sync::Arc}; /// [`Abigen` builder]: crate::Abigen /// [`event`]: method@crate::Contract::event /// [`method`]: method@crate::Contract::method -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct Contract { base_contract: BaseContract, client: Arc, address: Address, } +impl Clone for Contract { + fn clone(&self) -> Self { + Contract { + base_contract: self.base_contract.clone(), + client: self.client.clone(), + address: self.address, + } + } +} + impl Contract { /// Creates a new contract from the provided client, abi and address pub fn new(address: Address, abi: impl Into, client: impl Into>) -> Self { diff --git a/ethers-contract/src/factory.rs b/ethers-contract/src/factory.rs index 3a16b48c..23ef6bb9 100644 --- a/ethers-contract/src/factory.rs +++ b/ethers-contract/src/factory.rs @@ -19,7 +19,7 @@ use std::sync::Arc; /// /// This is just a wrapper type for [Deployer] with an additional type to convert the [Contract] /// that the deployer returns when sending the transaction. -#[derive(Debug, Clone)] +#[derive(Debug)] #[must_use = "Deployer does nothing unless you `send` it"] pub struct ContractDeployer { /// the actual deployer, exposed for overriding the defaults @@ -30,6 +30,12 @@ pub struct ContractDeployer { _contract: PhantomData, } +impl Clone for ContractDeployer { + fn clone(&self) -> Self { + ContractDeployer { deployer: self.deployer.clone(), _contract: self._contract } + } +} + impl>> ContractDeployer { /// Create a new instance of this [ContractDeployer] pub fn new(deployer: Deployer) -> Self { @@ -89,7 +95,7 @@ impl>> ContractDeployer { } /// Helper which manages the deployment transaction of a smart contract -#[derive(Debug, Clone)] +#[derive(Debug)] #[must_use = "Deployer does nothing unless you `send` it"] pub struct Deployer { /// The deployer's transaction, exposed for overriding the defaults @@ -100,6 +106,18 @@ pub struct Deployer { block: BlockNumber, } +impl Clone for Deployer { + fn clone(&self) -> Self { + Deployer { + tx: self.tx.clone(), + abi: self.abi.clone(), + client: self.client.clone(), + confs: self.confs, + block: self.block, + } + } +} + impl Deployer { /// Sets the number of confirmations to wait for the contract deployment transaction pub fn confirmations>(mut self, confirmations: T) -> Self { @@ -222,13 +240,23 @@ impl Deployer { /// println!("{}", contract.address()); /// # Ok(()) /// # } -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct ContractFactory { client: Arc, abi: Abi, bytecode: Bytes, } +impl Clone for ContractFactory { + fn clone(&self) -> Self { + ContractFactory { + client: self.client.clone(), + abi: self.abi.clone(), + bytecode: self.bytecode.clone(), + } + } +} + impl ContractFactory { /// Creates a factory for deployment of the Contract with bytecode, and the /// constructor defined in the abi. The client will be used to send any deployment diff --git a/ethers-contract/src/multicall/mod.rs b/ethers-contract/src/multicall/mod.rs index 2055b133..275b4416 100644 --- a/ethers-contract/src/multicall/mod.rs +++ b/ethers-contract/src/multicall/mod.rs @@ -120,7 +120,6 @@ pub static ADDRESS_BOOK: Lazy> = Lazy::new(|| { /// [`new`]: method@crate::Multicall::new /// [`block`]: method@crate::Multicall::block /// [`add_call`]: method@crate::Multicall::add_call -#[derive(Clone)] pub struct Multicall { calls: Vec, block: Option, @@ -128,6 +127,17 @@ pub struct Multicall { legacy: bool, } +impl Clone for Multicall { + fn clone(&self) -> Self { + Multicall { + calls: self.calls.clone(), + block: self.block, + contract: self.contract.clone(), + legacy: self.legacy, + } + } +} + #[derive(Clone)] /// Helper struct for managing calls to be made to the `function` in smart contract `target` /// with `data` diff --git a/ethers-contract/src/multicall/multicall_contract.rs b/ethers-contract/src/multicall/multicall_contract.rs index 5706736f..c83753d0 100644 --- a/ethers-contract/src/multicall/multicall_contract.rs +++ b/ethers-contract/src/multicall/multicall_contract.rs @@ -16,8 +16,12 @@ mod multicallcontract_mod { pub static MULTICALLCONTRACT_ABI: Lazy = Lazy::new(|| { serde_json :: from_str ( "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct MulticallContract.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"returnData\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockCoinbase\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockDifficulty\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"difficulty\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockGasLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gaslimit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getEthBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]" ) . expect ( "invalid abi" ) }); - #[derive(Clone)] pub struct MulticallContract(Contract); + impl Clone for MulticallContract { + fn clone(&self) -> Self { + MulticallContract(self.0.clone()) + } + } impl std::ops::Deref for MulticallContract { type Target = Contract; fn deref(&self) -> &Self::Target { diff --git a/ethers-middleware/src/gas_escalator/mod.rs b/ethers-middleware/src/gas_escalator/mod.rs index 64919857..a71adbf3 100644 --- a/ethers-middleware/src/gas_escalator/mod.rs +++ b/ethers-middleware/src/gas_escalator/mod.rs @@ -38,7 +38,7 @@ pub enum Frequency { Duration(u64), } -#[derive(Debug, Clone)] +#[derive(Debug)] /// A Gas escalator allows bumping transactions' gas price to avoid getting them /// stuck in the memory pool. /// @@ -72,6 +72,17 @@ pub struct GasEscalatorMiddleware { frequency: Frequency, } +impl Clone for GasEscalatorMiddleware { + fn clone(&self) -> Self { + GasEscalatorMiddleware { + inner: self.inner.clone(), + escalator: self.escalator.clone(), + txs: self.txs.clone(), + frequency: self.frequency.clone(), + } + } +} + #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] #[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl Middleware for GasEscalatorMiddleware diff --git a/ethers-middleware/src/transformer/ds_proxy/factory.rs b/ethers-middleware/src/transformer/ds_proxy/factory.rs index c51225aa..4c5b05e2 100644 --- a/ethers-middleware/src/transformer/ds_proxy/factory.rs +++ b/ethers-middleware/src/transformer/ds_proxy/factory.rs @@ -46,8 +46,12 @@ mod dsproxyfactory_mod { pub static DSPROXYFACTORY_ABI: Lazy = Lazy::new(|| { serde_json :: from_str ("[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"isProxy\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"cache\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"build\",\"outputs\":[{\"name\":\"proxy\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"build\",\"outputs\":[{\"name\":\"proxy\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"proxy\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"cache\",\"type\":\"address\"}],\"name\":\"Created\",\"type\":\"event\"}]\n") . expect ("invalid abi") }); - #[derive(Clone)] pub struct DsProxyFactory(Contract); + impl Clone for DsProxyFactory { + fn clone(&self) -> Self { + DsProxyFactory(self.0.clone()) + } + } impl std::ops::Deref for DsProxyFactory { type Target = Contract; fn deref(&self) -> &Self::Target {