Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
feat: Relax Clone requirements when Arc<M> is used (#1183)
Browse files Browse the repository at this point in the history
`#[derive(Clone)]` was implementing `Clone` only if `M` was `Clone`,
however because of `Arc<M>` this can be relaxed.
  • Loading branch information
oblique authored Apr 27, 2022
1 parent 86908bc commit 6faceb2
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 10 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@

### 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)
[#1030](https://github.com/gakonst/ethers-rs/pull/1030).
- Generate correct bindings of struct's field names that are reserved words
Expand Down Expand Up @@ -192,6 +194,8 @@

### 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
[#725](https://github.com/gakonst/ethers-rs/pull/725)
- Substitute output tuples with rust struct types for function calls
Expand Down Expand Up @@ -235,6 +239,8 @@

### 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
[#1095](https://gakonst/ethers-rs/pull/1095)
- Add BlockNative gas oracle [#1175](https://github.com/gakonst/ethers-rs/pull/1175)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,13 @@ pub(crate) fn struct_declaration(cx: &Context) -> TokenStream {
#bytecode

// Struct declaration
#[derive(Clone)]
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
impl<M> std::ops::Deref for #name<M> {
Expand Down
14 changes: 13 additions & 1 deletion ethers-contract/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub enum ContractError<M: Middleware> {
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<M, D> {
Expand All @@ -77,6 +77,18 @@ pub struct ContractCall<M, 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> {
/// Sets the `from` field in the transaction to the provided value
pub fn from<T: Into<Address>>(mut self, from: T) -> Self {
Expand Down
12 changes: 11 additions & 1 deletion ethers-contract/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<M> {
base_contract: BaseContract,
client: Arc<M>,
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> {
/// 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 {
Expand Down
34 changes: 31 additions & 3 deletions ethers-contract/src/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<M, C> {
/// the actual deployer, exposed for overriding the defaults
Expand All @@ -30,6 +30,12 @@ pub struct ContractDeployer<M, 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> {
/// Create a new instance of this [ContractDeployer]
pub fn new(deployer: Deployer<M>) -> Self {
Expand Down Expand Up @@ -89,7 +95,7 @@ impl<M: Middleware, C: From<Contract<M>>> ContractDeployer<M, C> {
}

/// 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<M> {
/// The deployer's transaction, exposed for overriding the defaults
Expand All @@ -100,6 +106,18 @@ pub struct Deployer<M> {
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> {
/// Sets the number of confirmations to wait for the contract deployment transaction
pub fn confirmations<T: Into<usize>>(mut self, confirmations: T) -> Self {
Expand Down Expand Up @@ -222,13 +240,23 @@ impl<M: Middleware> Deployer<M> {
/// println!("{}", contract.address());
/// # Ok(())
/// # }
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct ContractFactory<M> {
client: Arc<M>,
abi: Abi,
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> {
/// 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
Expand Down
12 changes: 11 additions & 1 deletion ethers-contract/src/multicall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,24 @@ pub static ADDRESS_BOOK: Lazy<HashMap<U256, Address>> = Lazy::new(|| {
/// [`new`]: method@crate::Multicall::new
/// [`block`]: method@crate::Multicall::block
/// [`add_call`]: method@crate::Multicall::add_call
#[derive(Clone)]
pub struct Multicall<M> {
calls: Vec<Call>,
block: Option<BlockNumber>,
contract: MulticallContract<M>,
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)]
/// Helper struct for managing calls to be made to the `function` in smart contract `target`
/// with `data`
Expand Down
6 changes: 5 additions & 1 deletion ethers-contract/src/multicall/multicall_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ mod multicallcontract_mod {
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" )
});
#[derive(Clone)]
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> {
type Target = Contract<M>;
fn deref(&self) -> &Self::Target {
Expand Down
13 changes: 12 additions & 1 deletion ethers-middleware/src/gas_escalator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -72,6 +72,17 @@ pub struct GasEscalatorMiddleware<M, E> {
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(not(target_arch = "wasm32"), async_trait)]
impl<M, E> Middleware for GasEscalatorMiddleware<M, E>
Expand Down
6 changes: 5 additions & 1 deletion ethers-middleware/src/transformer/ds_proxy/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,12 @@ mod dsproxyfactory_mod {
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")
});
#[derive(Clone)]
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> {
type Target = Contract<M>;
fn deref(&self) -> &Self::Target {
Expand Down

0 comments on commit 6faceb2

Please sign in to comment.