feat: Relax `Clone` requirements when `Arc<M>` is used (#1183)

`#[derive(Clone)]` was implementing `Clone` only if `M` was `Clone`,
however because of `Arc<M>` this can be relaxed.
This commit is contained in:
oblique 2022-04-27 15:33:22 +03:00 committed by GitHub
parent 86908bc533
commit 6faceb20d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 99 additions and 10 deletions

View File

@ -62,6 +62,8 @@
### Unreleased ### Unreleased
- Relax Clone requirements when Arc<Middleware> 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) - Generate a deploy function if bytecode is provided in the abigen! input (json artifact)
[#1030](https://github.com/gakonst/ethers-rs/pull/1030). [#1030](https://github.com/gakonst/ethers-rs/pull/1030).
- Generate correct bindings of struct's field names that are reserved words - Generate correct bindings of struct's field names that are reserved words
@ -192,6 +194,8 @@
### Unreleased ### Unreleased
- Relax Clone requirements when Arc<Middleware> is used
[#1183](https://github.com/gakonst/ethers-rs/pull/1183)
- Add `EventStream::select` to combine streams with different event types - Add `EventStream::select` to combine streams with different event types
[#725](https://github.com/gakonst/ethers-rs/pull/725) [#725](https://github.com/gakonst/ethers-rs/pull/725)
- Substitute output tuples with rust struct types for function calls - Substitute output tuples with rust struct types for function calls
@ -235,6 +239,8 @@
### Unreleased ### Unreleased
- Relax Clone requirements when Arc<Middleware> is used
[#1183](https://github.com/gakonst/ethers-rs/pull/1183)
- Ensure a consistent chain ID between a Signer and Provider in SignerMiddleware - Ensure a consistent chain ID between a Signer and Provider in SignerMiddleware
[#1095](https://gakonst/ethers-rs/pull/1095) [#1095](https://gakonst/ethers-rs/pull/1095)
- Add BlockNative gas oracle [#1175](https://github.com/gakonst/ethers-rs/pull/1175) - Add BlockNative gas oracle [#1175](https://github.com/gakonst/ethers-rs/pull/1175)

View File

@ -71,9 +71,13 @@ pub(crate) fn struct_declaration(cx: &Context) -> TokenStream {
#bytecode #bytecode
// Struct declaration // Struct declaration
#[derive(Clone)]
pub struct #name<M>(#ethers_contract::Contract<M>); pub struct #name<M>(#ethers_contract::Contract<M>);
impl<M> Clone for #name<M> {
fn clone(&self) -> Self {
#name(self.0.clone())
}
}
// Deref to the inner contract in order to access more specific functions functions // Deref to the inner contract in order to access more specific functions functions
impl<M> std::ops::Deref for #name<M> { impl<M> std::ops::Deref for #name<M> {

View File

@ -63,7 +63,7 @@ pub enum ContractError<M: Middleware> {
ContractNotDeployed, ContractNotDeployed,
} }
#[derive(Debug, Clone)] #[derive(Debug)]
#[must_use = "contract calls do nothing unless you `send` or `call` them"] #[must_use = "contract calls do nothing unless you `send` or `call` them"]
/// Helper for managing a transaction before submitting it to a node /// Helper for managing a transaction before submitting it to a node
pub struct ContractCall<M, D> { pub struct ContractCall<M, D> {
@ -77,6 +77,18 @@ pub struct ContractCall<M, D> {
pub(crate) datatype: PhantomData<D>, pub(crate) datatype: PhantomData<D>,
} }
impl<M, D> Clone for ContractCall<M, D> {
fn clone(&self) -> Self {
ContractCall {
tx: self.tx.clone(),
function: self.function.clone(),
block: self.block,
client: self.client.clone(),
datatype: self.datatype,
}
}
}
impl<M, D: Detokenize> ContractCall<M, D> { impl<M, D: Detokenize> ContractCall<M, D> {
/// Sets the `from` field in the transaction to the provided value /// Sets the `from` field in the transaction to the provided value
pub fn from<T: Into<Address>>(mut self, from: T) -> Self { pub fn from<T: Into<Address>>(mut self, from: T) -> Self {

View File

@ -150,13 +150,23 @@ use std::{fmt::Debug, marker::PhantomData, sync::Arc};
/// [`Abigen` builder]: crate::Abigen /// [`Abigen` builder]: crate::Abigen
/// [`event`]: method@crate::Contract::event /// [`event`]: method@crate::Contract::event
/// [`method`]: method@crate::Contract::method /// [`method`]: method@crate::Contract::method
#[derive(Debug, Clone)] #[derive(Debug)]
pub struct Contract<M> { pub struct Contract<M> {
base_contract: BaseContract, base_contract: BaseContract,
client: Arc<M>, client: Arc<M>,
address: Address, address: Address,
} }
impl<M> Clone for Contract<M> {
fn clone(&self) -> Self {
Contract {
base_contract: self.base_contract.clone(),
client: self.client.clone(),
address: self.address,
}
}
}
impl<M: Middleware> Contract<M> { impl<M: Middleware> Contract<M> {
/// Creates a new contract from the provided client, abi and address /// Creates a new contract from the provided client, abi and address
pub fn new(address: Address, abi: impl Into<BaseContract>, client: impl Into<Arc<M>>) -> Self { pub fn new(address: Address, abi: impl Into<BaseContract>, client: impl Into<Arc<M>>) -> Self {

View File

@ -19,7 +19,7 @@ use std::sync::Arc;
/// ///
/// This is just a wrapper type for [Deployer] with an additional type to convert the [Contract] /// This is just a wrapper type for [Deployer] with an additional type to convert the [Contract]
/// that the deployer returns when sending the transaction. /// that the deployer returns when sending the transaction.
#[derive(Debug, Clone)] #[derive(Debug)]
#[must_use = "Deployer does nothing unless you `send` it"] #[must_use = "Deployer does nothing unless you `send` it"]
pub struct ContractDeployer<M, C> { pub struct ContractDeployer<M, C> {
/// the actual deployer, exposed for overriding the defaults /// the actual deployer, exposed for overriding the defaults
@ -30,6 +30,12 @@ pub struct ContractDeployer<M, C> {
_contract: PhantomData<C>, _contract: PhantomData<C>,
} }
impl<M, C> Clone for ContractDeployer<M, C> {
fn clone(&self) -> Self {
ContractDeployer { deployer: self.deployer.clone(), _contract: self._contract }
}
}
impl<M: Middleware, C: From<Contract<M>>> ContractDeployer<M, C> { impl<M: Middleware, C: From<Contract<M>>> ContractDeployer<M, C> {
/// Create a new instance of this [ContractDeployer] /// Create a new instance of this [ContractDeployer]
pub fn new(deployer: Deployer<M>) -> Self { pub fn new(deployer: Deployer<M>) -> Self {
@ -89,7 +95,7 @@ impl<M: Middleware, C: From<Contract<M>>> ContractDeployer<M, C> {
} }
/// Helper which manages the deployment transaction of a smart contract /// Helper which manages the deployment transaction of a smart contract
#[derive(Debug, Clone)] #[derive(Debug)]
#[must_use = "Deployer does nothing unless you `send` it"] #[must_use = "Deployer does nothing unless you `send` it"]
pub struct Deployer<M> { pub struct Deployer<M> {
/// The deployer's transaction, exposed for overriding the defaults /// The deployer's transaction, exposed for overriding the defaults
@ -100,6 +106,18 @@ pub struct Deployer<M> {
block: BlockNumber, block: BlockNumber,
} }
impl<M> Clone for Deployer<M> {
fn clone(&self) -> Self {
Deployer {
tx: self.tx.clone(),
abi: self.abi.clone(),
client: self.client.clone(),
confs: self.confs,
block: self.block,
}
}
}
impl<M: Middleware> Deployer<M> { impl<M: Middleware> Deployer<M> {
/// Sets the number of confirmations to wait for the contract deployment transaction /// Sets the number of confirmations to wait for the contract deployment transaction
pub fn confirmations<T: Into<usize>>(mut self, confirmations: T) -> Self { pub fn confirmations<T: Into<usize>>(mut self, confirmations: T) -> Self {
@ -222,13 +240,23 @@ impl<M: Middleware> Deployer<M> {
/// println!("{}", contract.address()); /// println!("{}", contract.address());
/// # Ok(()) /// # Ok(())
/// # } /// # }
#[derive(Debug, Clone)] #[derive(Debug)]
pub struct ContractFactory<M> { pub struct ContractFactory<M> {
client: Arc<M>, client: Arc<M>,
abi: Abi, abi: Abi,
bytecode: Bytes, bytecode: Bytes,
} }
impl<M> Clone for ContractFactory<M> {
fn clone(&self) -> Self {
ContractFactory {
client: self.client.clone(),
abi: self.abi.clone(),
bytecode: self.bytecode.clone(),
}
}
}
impl<M: Middleware> ContractFactory<M> { impl<M: Middleware> ContractFactory<M> {
/// Creates a factory for deployment of the Contract with bytecode, and the /// 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 /// constructor defined in the abi. The client will be used to send any deployment

View File

@ -120,7 +120,6 @@ pub static ADDRESS_BOOK: Lazy<HashMap<U256, Address>> = Lazy::new(|| {
/// [`new`]: method@crate::Multicall::new /// [`new`]: method@crate::Multicall::new
/// [`block`]: method@crate::Multicall::block /// [`block`]: method@crate::Multicall::block
/// [`add_call`]: method@crate::Multicall::add_call /// [`add_call`]: method@crate::Multicall::add_call
#[derive(Clone)]
pub struct Multicall<M> { pub struct Multicall<M> {
calls: Vec<Call>, calls: Vec<Call>,
block: Option<BlockNumber>, block: Option<BlockNumber>,
@ -128,6 +127,17 @@ pub struct Multicall<M> {
legacy: bool, legacy: bool,
} }
impl<M> Clone for Multicall<M> {
fn clone(&self) -> Self {
Multicall {
calls: self.calls.clone(),
block: self.block,
contract: self.contract.clone(),
legacy: self.legacy,
}
}
}
#[derive(Clone)] #[derive(Clone)]
/// Helper struct for managing calls to be made to the `function` in smart contract `target` /// Helper struct for managing calls to be made to the `function` in smart contract `target`
/// with `data` /// with `data`

View File

@ -16,8 +16,12 @@ mod multicallcontract_mod {
pub static MULTICALLCONTRACT_ABI: Lazy<Abi> = Lazy::new(|| { pub static MULTICALLCONTRACT_ABI: Lazy<Abi> = 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" ) 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<M>(Contract<M>); pub struct MulticallContract<M>(Contract<M>);
impl<M> Clone for MulticallContract<M> {
fn clone(&self) -> Self {
MulticallContract(self.0.clone())
}
}
impl<M> std::ops::Deref for MulticallContract<M> { impl<M> std::ops::Deref for MulticallContract<M> {
type Target = Contract<M>; type Target = Contract<M>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {

View File

@ -38,7 +38,7 @@ pub enum Frequency {
Duration(u64), Duration(u64),
} }
#[derive(Debug, Clone)] #[derive(Debug)]
/// A Gas escalator allows bumping transactions' gas price to avoid getting them /// A Gas escalator allows bumping transactions' gas price to avoid getting them
/// stuck in the memory pool. /// stuck in the memory pool.
/// ///
@ -72,6 +72,17 @@ pub struct GasEscalatorMiddleware<M, E> {
frequency: Frequency, frequency: Frequency,
} }
impl<M, E: Clone> Clone for GasEscalatorMiddleware<M, E> {
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(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)] #[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<M, E> Middleware for GasEscalatorMiddleware<M, E> impl<M, E> Middleware for GasEscalatorMiddleware<M, E>

View File

@ -46,8 +46,12 @@ mod dsproxyfactory_mod {
pub static DSPROXYFACTORY_ABI: Lazy<Abi> = Lazy::new(|| { pub static DSPROXYFACTORY_ABI: Lazy<Abi> = 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") 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<M>(Contract<M>); pub struct DsProxyFactory<M>(Contract<M>);
impl<M> Clone for DsProxyFactory<M> {
fn clone(&self) -> Self {
DsProxyFactory(self.0.clone())
}
}
impl<M> std::ops::Deref for DsProxyFactory<M> { impl<M> std::ops::Deref for DsProxyFactory<M> {
type Target = Contract<M>; type Target = Contract<M>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {