[−][src]Struct ethers_contract::Contract
A Contract is an abstraction of an executable program on the Ethereum Blockchain. It has code (called byte code) as well as allocated long-term memory (called storage). Every deployed Contract has an address, which is used to connect to it so that it may be sent messages to call its methods.
A Contract can emit Events, which can be efficiently observed by applications to be notified when a contract has performed specific operation.
There are two types of methods that can be called on a Contract:
-
A Constant method may not add, remove or change any data in the storage, nor log any events, and may only call Constant methods on other contracts. These methods are free (no Ether is required) to call. The result from them may also be returned to the caller. Constant methods are marked as
pure
andview
in Solidity. -
A Non-Constant method requires a fee (in Ether) to be paid, but may perform any state-changing operation desired, log events, send ether and call Non-Constant methods on other Contracts. These methods cannot return their result to the caller. These methods must be triggered by a transaction, sent by an Externally Owned Account (EOA) either directly or indirectly (i.e. called from another contract), and are required to be mined before the effects are present. Therefore, the duration required for these operations can vary widely, and depend on the transaction gas price, network congestion and miner priority heuristics.
The Contract API provides simple way to connect to a Contract and call its methods, as functions on a Rust struct, handling all the binary protocol conversion, internal name mangling and topic construction. This allows a Contract object to be used like any standard Rust struct, without having to worry about the low-level details of the Ethereum Virtual Machine or Blockchain.
The Contract definition (called an Application Binary Interface, or ABI) must
be provided to instantiate a contract and the available methods and events will
be made available to call by providing their name as a str
via the method
and event
methods. If non-existing names are given, the function/event call
will fail.
Alternatively, you can and should use the abigen
macro, or the Abigen
builder
to generate type-safe bindings to your contracts.
Example
Assuming we already have our contract deployed at address
, we'll proceed to
interact with its methods and retrieve raw logs it has emitted.
use ethers::{ abi::Abi, utils::Solc, types::{Address, H256}, contract::Contract, providers::{Provider, Http}, signers::Wallet, }; use std::convert::TryFrom; // this is a fake address used just for this example let address = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee".parse::<Address>()?; // (ugly way to write the ABI inline, you can otherwise read it from a file) let abi: Abi = serde_json::from_str(r#"[{"inputs":[{"internalType":"string","name":"value","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"author","type":"address"},{"indexed":true,"internalType":"address","name":"oldAuthor","type":"address"},{"indexed":false,"internalType":"string","name":"oldValue","type":"string"},{"indexed":false,"internalType":"string","name":"newValue","type":"string"}],"name":"ValueChanged","type":"event"},{"inputs":[],"name":"getValue","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"value","type":"string"}],"name":"setValue","outputs":[],"stateMutability":"nonpayable","type":"function"}]"#)?; // connect to the network let client = Provider::<Http>::try_from("http://localhost:8545").unwrap(); // create the contract object at the address let contract = Contract::new(address, abi, client); // Calling constant methods is done by calling `call()` on the method builder. // (if the function takes no arguments, then you must use `()` as the argument) let init_value: String = contract .method::<_, String>("getValue", ())? .call() .await?; // Non-constant methods are executed via the `send()` call on the method builder. let call = contract .method::<_, H256>("setValue", "hi".to_owned())?; let pending_tx = call.send().await?; // `await`ing on the pending transaction resolves to a transaction receipt let receipt = pending_tx.confirmations(6).await?;
Event Logging
Querying structured logs requires you to have defined a struct with the expected
datatypes and to have implemented Detokenize
for it. This boilerplate code
is generated for you via the abigen
and Abigen
builder utilities.
use ethers_core::{abi::Abi, types::Address}; use ethers_contract::Contract; use ethers_providers::{Provider, Http, Middleware}; use ethers_signers::Wallet; use std::convert::TryFrom; use ethers_core::abi::{Detokenize, Token, InvalidOutputType}; #[derive(Clone, Debug)] struct ValueChanged { old_author: Address, new_author: Address, old_value: String, new_value: String, } impl Detokenize for ValueChanged { fn from_tokens(tokens: Vec<Token>) -> Result<ValueChanged, InvalidOutputType> { let old_author: Address = tokens[1].clone().into_address().unwrap(); let new_author: Address = tokens[1].clone().into_address().unwrap(); let old_value = tokens[2].clone().into_string().unwrap(); let new_value = tokens[3].clone().into_string().unwrap(); Ok(Self { old_author, new_author, old_value, new_value, }) } } let logs: Vec<ValueChanged> = contract .event("ValueChanged")? .from_block(0u64) .query() .await?; println!("{:?}", logs);
Disclaimer: these above docs have been adapted from the corresponding ethers.js page
Implementations
impl<M: Middleware> Contract<M>
[src]
pub fn new(
address: Address,
abi: impl Into<BaseContract>,
client: impl Into<Arc<M>>
) -> Self
[src]
address: Address,
abi: impl Into<BaseContract>,
client: impl Into<Arc<M>>
) -> Self
Creates a new contract from the provided client, abi and address
pub fn event<D: Detokenize>(
&self,
name: &str
) -> Result<Event<'_, '_, M, D>, Error>
[src]
&self,
name: &str
) -> Result<Event<'_, '_, M, D>, Error>
Returns an Event
builder for the provided event name.
pub fn method<T: Tokenize, D: Detokenize>(
&self,
name: &str,
args: T
) -> Result<ContractCall<M, D>, AbiError>
[src]
&self,
name: &str,
args: T
) -> Result<ContractCall<M, D>, AbiError>
Returns a transaction builder for the provided function name. If there are
multiple functions with the same name due to overloading, consider using
the method_hash
method instead, since this will use the first match.
pub fn method_hash<T: Tokenize, D: Detokenize>(
&self,
signature: Selector,
args: T
) -> Result<ContractCall<M, D>, AbiError>
[src]
&self,
signature: Selector,
args: T
) -> Result<ContractCall<M, D>, AbiError>
Returns a transaction builder for the selected function signature. This should be preferred if there are overloaded functions in your smart contract
pub fn at<T: Into<Address>>(&self, address: T) -> Self where
M: Clone,
[src]
M: Clone,
Returns a new contract instance at address
.
Clones self
internally
pub fn connect(&self, client: Arc<M>) -> Self where
M: Clone,
[src]
M: Clone,
Returns a new contract instance using the provided client
Clones self
internally
pub fn address(&self) -> Address
[src]
Returns the contract's address
pub fn abi(&self) -> &Abi
[src]
Returns a reference to the contract's ABI
pub fn client(&self) -> &M
[src]
Returns a reference to the contract's client
Trait Implementations
Auto Trait Implementations
impl<M> RefUnwindSafe for Contract<M> where
M: RefUnwindSafe,
[src]
M: RefUnwindSafe,
impl<M> Send for Contract<M> where
M: Send + Sync,
[src]
M: Send + Sync,
impl<M> Sync for Contract<M> where
M: Send + Sync,
[src]
M: Send + Sync,
impl<M> Unpin for Contract<M>
[src]
impl<M> UnwindSafe for Contract<M> where
M: RefUnwindSafe,
[src]
M: RefUnwindSafe,
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> Conv for T
impl<T> FmtForward for T
pub fn fmt_binary(self) -> FmtBinary<Self> where
Self: Binary,
Self: Binary,
pub fn fmt_display(self) -> FmtDisplay<Self> where
Self: Display,
Self: Display,
pub fn fmt_lower_exp(self) -> FmtLowerExp<Self> where
Self: LowerExp,
Self: LowerExp,
pub fn fmt_lower_hex(self) -> FmtLowerHex<Self> where
Self: LowerHex,
Self: LowerHex,
pub fn fmt_octal(self) -> FmtOctal<Self> where
Self: Octal,
Self: Octal,
pub fn fmt_pointer(self) -> FmtPointer<Self> where
Self: Pointer,
Self: Pointer,
pub fn fmt_upper_exp(self) -> FmtUpperExp<Self> where
Self: UpperExp,
Self: UpperExp,
pub fn fmt_upper_hex(self) -> FmtUpperHex<Self> where
Self: UpperHex,
Self: UpperHex,
impl<T> From<T> for T
[src]
impl<T> Instrument for T
[src]
pub fn instrument(self, span: Span) -> Instrumented<Self>
[src]
pub fn in_current_span(self) -> Instrumented<Self>
[src]
impl<T> Instrument for T
[src]
pub fn instrument(self, span: Span) -> Instrumented<Self>
[src]
pub fn in_current_span(self) -> Instrumented<Self>
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> Pipe for T
impl<T> PipeAsRef for T
pub fn pipe_as_ref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R where
Self: AsRef<T>,
T: 'a,
R: 'a,
Self: AsRef<T>,
T: 'a,
R: 'a,
pub fn pipe_as_mut<'a, T, R>(
&'a mut self,
func: impl FnOnce(&'a mut T) -> R
) -> R where
Self: AsMut<T>,
T: 'a,
R: 'a,
&'a mut self,
func: impl FnOnce(&'a mut T) -> R
) -> R where
Self: AsMut<T>,
T: 'a,
R: 'a,
impl<T> PipeBorrow for T
pub fn pipe_borrow<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R where
Self: Borrow<T>,
T: 'a,
R: 'a,
Self: Borrow<T>,
T: 'a,
R: 'a,
pub fn pipe_borrow_mut<'a, T, R>(
&'a mut self,
func: impl FnOnce(&'a mut T) -> R
) -> R where
Self: BorrowMut<T>,
T: 'a,
R: 'a,
&'a mut self,
func: impl FnOnce(&'a mut T) -> R
) -> R where
Self: BorrowMut<T>,
T: 'a,
R: 'a,
impl<T> PipeDeref for T
pub fn pipe_deref<'a, R>(
&'a self,
func: impl FnOnce(&'a Self::Target) -> R
) -> R where
Self: Deref,
R: 'a,
&'a self,
func: impl FnOnce(&'a Self::Target) -> R
) -> R where
Self: Deref,
R: 'a,
pub fn pipe_deref_mut<'a, R>(
&'a mut self,
func: impl FnOnce(&'a mut Self::Target) -> R
) -> R where
Self: DerefMut,
R: 'a,
&'a mut self,
func: impl FnOnce(&'a mut Self::Target) -> R
) -> R where
Self: DerefMut,
R: 'a,
impl<T> PipeRef for T
pub fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R where
R: 'a,
R: 'a,
pub fn pipe_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R where
R: 'a,
R: 'a,
impl<T> Same<T> for T
type Output = T
Should always be Self
impl<T> Tap for T
pub fn tap<F, R>(self, func: F) -> Self where
F: FnOnce(&Self) -> R,
F: FnOnce(&Self) -> R,
pub fn tap_dbg<F, R>(self, func: F) -> Self where
F: FnOnce(&Self) -> R,
F: FnOnce(&Self) -> R,
pub fn tap_mut<F, R>(self, func: F) -> Self where
F: FnOnce(&mut Self) -> R,
F: FnOnce(&mut Self) -> R,
pub fn tap_mut_dbg<F, R>(self, func: F) -> Self where
F: FnOnce(&mut Self) -> R,
F: FnOnce(&mut Self) -> R,
impl<T, U> TapAsRef<U> for T where
U: ?Sized,
U: ?Sized,
pub fn tap_ref<F, R>(self, func: F) -> Self where
Self: AsRef<T>,
F: FnOnce(&T) -> R,
Self: AsRef<T>,
F: FnOnce(&T) -> R,
pub fn tap_ref_dbg<F, R>(self, func: F) -> Self where
Self: AsRef<T>,
F: FnOnce(&T) -> R,
Self: AsRef<T>,
F: FnOnce(&T) -> R,
pub fn tap_ref_mut<F, R>(self, func: F) -> Self where
Self: AsMut<T>,
F: FnOnce(&mut T) -> R,
Self: AsMut<T>,
F: FnOnce(&mut T) -> R,
pub fn tap_ref_mut_dbg<F, R>(self, func: F) -> Self where
Self: AsMut<T>,
F: FnOnce(&mut T) -> R,
Self: AsMut<T>,
F: FnOnce(&mut T) -> R,
impl<T, U> TapBorrow<U> for T where
U: ?Sized,
U: ?Sized,
pub fn tap_borrow<F, R>(self, func: F) -> Self where
Self: Borrow<T>,
F: FnOnce(&T) -> R,
Self: Borrow<T>,
F: FnOnce(&T) -> R,
pub fn tap_borrow_dbg<F, R>(self, func: F) -> Self where
Self: Borrow<T>,
F: FnOnce(&T) -> R,
Self: Borrow<T>,
F: FnOnce(&T) -> R,
pub fn tap_borrow_mut<F, R>(self, func: F) -> Self where
Self: BorrowMut<T>,
F: FnOnce(&mut T) -> R,
Self: BorrowMut<T>,
F: FnOnce(&mut T) -> R,
pub fn tap_borrow_mut_dbg<F, R>(self, func: F) -> Self where
Self: BorrowMut<T>,
F: FnOnce(&mut T) -> R,
Self: BorrowMut<T>,
F: FnOnce(&mut T) -> R,
impl<T> TapDeref for T
pub fn tap_deref<F, R>(self, func: F) -> Self where
Self: Deref,
F: FnOnce(&Self::Target) -> R,
Self: Deref,
F: FnOnce(&Self::Target) -> R,
pub fn tap_deref_dbg<F, R>(self, func: F) -> Self where
Self: Deref,
F: FnOnce(&Self::Target) -> R,
Self: Deref,
F: FnOnce(&Self::Target) -> R,
pub fn tap_deref_mut<F, R>(self, func: F) -> Self where
Self: DerefMut,
F: FnOnce(&mut Self::Target) -> R,
Self: DerefMut,
F: FnOnce(&mut Self::Target) -> R,
pub fn tap_deref_mut_dbg<F, R>(self, func: F) -> Self where
Self: DerefMut,
F: FnOnce(&mut Self::Target) -> R,
Self: DerefMut,
F: FnOnce(&mut Self::Target) -> R,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
pub fn to_owned(&self) -> T
[src]
pub fn clone_into(&self, target: &mut T)
[src]
impl<T> TryConv for T
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
pub fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<V, T> VZip<V> for T where
V: MultiLane<T>,
V: MultiLane<T>,