Contracts¶
Smart contracts are programs deployed to the Ethereum network. See the ethereum.org docs for a proper introduction.
Contract Deployment Example¶
To run this example, you will need to install a few extra features:
- The sandbox node provided by eth-tester. You can install it with:
$ pip install -U "web3[tester]"
py-solc-x
. This is the supported route to installing the solidity compilersolc
. You can install it with:
$ pip install py-solc-x
After py-solc-x
is installed, you will need to install a version of solc
. You can install the latest version via a new REPL with:
>>> from solcx import install_solc
>>> install_solc(version='latest')
You should now be set up to run the contract deployment example below:
>>> from web3 import Web3
>>> from solcx import compile_source
# Solidity source code
>>> compiled_sol = compile_source(
... '''
... pragma solidity >0.5.0;
...
... contract Greeter {
... string public greeting;
...
... constructor() public {
... greeting = 'Hello';
... }
...
... function setGreeting(string memory _greeting) public {
... greeting = _greeting;
... }
...
... function greet() view public returns (string memory) {
... return greeting;
... }
... }
... ''',
... output_values=['abi', 'bin']
... )
# retrieve the contract interface
>>> contract_id, contract_interface = compiled_sol.popitem()
# get bytecode / bin
>>> bytecode = contract_interface['bin']
# get abi
>>> abi = contract_interface['abi']
# web3.py instance
>>> w3 = Web3(Web3.EthereumTesterProvider())
# set pre-funded account as sender
>>> w3.eth.default_account = w3.eth.accounts[0]
>>> Greeter = w3.eth.contract(abi=abi, bytecode=bytecode)
# Submit the transaction that deploys the contract
>>> tx_hash = Greeter.constructor().transact()
# Wait for the transaction to be mined, and get the transaction receipt
>>> tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
>>> greeter = w3.eth.contract(
... address=tx_receipt.contractAddress,
... abi=abi
... )
>>> greeter.functions.greet().call()
'Hello'
>>> tx_hash = greeter.functions.setGreeting('Nihao').transact()
>>> tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
>>> greeter.functions.greet().call()
'Nihao'
Contract Factories¶
These factories are not intended to be initialized directly.
Instead, create contract objects using the w3.eth.contract()
method. By default, the contract factory is Contract
. See the
example in ConciseContract
for specifying an alternate factory.
-
class
web3.contract.
Contract
(address)¶ Contract provides a default interface for deploying and interacting with Ethereum smart contracts.
The address parameter can be a hex address or an ENS name, like
mycontract.eth
.
-
class
web3.contract.
ConciseContract
(Contract())¶ Warning
Deprecated: This method is deprecated in favor of the
ContractCaller
API or the verbose syntaxThis variation of
Contract
is designed for more succinct read access, without making write access more wordy. This comes at a cost of losing access to features likedeploy()
and properties likeaddress
. It is recommended to use the classicContract
for those use cases. Just to be be clear, ConciseContract only exposes contract functions and all other Contract class methods and properties are not available with the ConciseContract API. This includes but is not limited tocontract.address
,contract.abi
, andcontract.deploy()
.Create this type of contract by passing a
Contract
instance toConciseContract
:>>> concise = ConciseContract(myContract)
This variation invokes all methods as a call, so if the classic contract had a method like
contract.functions.owner().call()
, you could call it withconcise.owner()
instead.For access to send a transaction or estimate gas, you can add a keyword argument like so:
>>> concise.withdraw(amount, transact={'from': eth.accounts[1], 'gas': 100000, ...}) >>> # which is equivalent to this transaction in the classic contract: >>> contract.functions.withdraw(amount).transact({'from': eth.accounts[1], 'gas': 100000, ...})
-
class
web3.contract.
ImplicitContract
(Contract())¶ Warning
Deprecated: This method is deprecated in favor of the verbose syntax
This variation mirrors
ConciseContract
, but it invokes all methods as a transaction rather than a call, so if the classic contract had a method likecontract.functions.owner.transact()
, you could call it withimplicit.owner()
instead.Create this type of contract by passing a
Contract
instance toImplicitContract
:>>> concise = ImplicitContract(myContract)
Properties¶
Each Contract Factory exposes the following properties.
-
Contract.
address
¶ The hexadecimal encoded 20-byte address of the contract, or an ENS name. May be
None
if not provided during factory creation.
-
Contract.
abi
¶ The contract ABI array.
-
Contract.
bytecode
¶ The contract bytecode string. May be
None
if not provided during factory creation.
-
Contract.
bytecode_runtime
¶ The runtime part of the contract bytecode string. May be
None
if not provided during factory creation.
-
Contract.
functions
¶ This provides access to contract functions as attributes. For example:
myContract.functions.MyMethod()
. The exposed contract functions are classes of the typeContractFunction
.
-
Contract.
events
¶ This provides access to contract events as attributes. For example:
myContract.events.MyEvent()
. The exposed contract events are classes of the typeContractEvent
.
Methods¶
Each Contract Factory exposes the following methods.
-
classmethod
Contract.
constructor
(*args, **kwargs).transact(transaction=None)¶ Construct and deploy a contract by sending a new public transaction.
If provided
transaction
should be a dictionary conforming to theweb3.eth.send_transaction(transaction)
method. This value may not contain the keysdata
orto
.If the contract takes constructor parameters they should be provided as positional arguments or keyword arguments.
If any of the arguments specified in the ABI are an
address
type, they will accept ENS names.If a
gas
value is not provided, then thegas
value for the deployment transaction will be created using theweb3.eth.estimate_gas()
method.Returns the transaction hash for the deploy transaction.
>>> deploy_txn = token_contract.constructor(web3.eth.coinbase, 12345).transact() >>> txn_receipt = web3.eth.get_transaction_receipt(deploy_txn) >>> txn_receipt['contractAddress'] '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318'
-
classmethod
Contract.
constructor
(*args, **kwargs).estimateGas(transaction=None, block_identifier=None) Warning
Deprecated: This method is deprecated in favor of
Contract.constructor(*args, **kwargs).estimate_gas()
-
classmethod
Contract.
constructor
(*args, **kwargs).estimate_gas(transaction=None, block_identifier=None) Estimate gas for constructing and deploying the contract.
This method behaves the same as the
Contract.constructor(*args, **kwargs).transact()
method, with transaction details being passed into the end portion of the function call, and function arguments being passed into the first portion.The
block_identifier
parameter is passed directly to the call at the end portion of the function call.Returns the amount of gas consumed which can be used as a gas estimate for executing this transaction publicly.
Returns the gas needed to deploy the contract.
>>> token_contract.constructor(web3.eth.coinbase, 12345).estimate_gas() 12563
-
classmethod
Contract.
constructor
(*args, **kwargs).buildTransaction(transaction=None) Warning
Deprecated: This method is deprecated in favor of
Contract.constructor(*args, **kwargs).build_transaction()
-
classmethod
Contract.
constructor
(*args, **kwargs).build_transaction(transaction=None) Construct the contract deploy transaction bytecode data.
If the contract takes constructor parameters they should be provided as positional arguments or keyword arguments.
If any of the
args
specified in the ABI are anaddress
type, they will accept ENS names.Returns the transaction dictionary that you can pass to send_transaction method.
>>> transaction = { 'gasPrice': w3.eth.gas_price, 'chainId': None } >>> contract_data = token_contract.constructor(web3.eth.coinbase, 12345).build_transaction(transaction) >>> web3.eth.send_transaction(contract_data)
-
classmethod
Contract.events.your_event_name.
create_filter
(fromBlock=block, toBlock=block, argument_filters={"arg1": "value"}, topics=[])¶ Creates a new event filter, an instance of
web3.utils.filters.LogFilter
.fromBlock
is a mandatory field. Defines the starting block (exclusive) filter block range. It can be either the starting block number, or ‘latest’ for the last mined block, or ‘pending’ for unmined transactions. In the case offromBlock
, ‘latest’ and ‘pending’ set the ‘latest’ or ‘pending’ block as a static value for the starting filter block.toBlock
optional. Defaults to ‘latest’. Defines the ending block (inclusive) in the filter block range. Special values ‘latest’ and ‘pending’ set a dynamic range that always includes the ‘latest’ or ‘pending’ blocks for the filter’s upper block range.address
optional. Defaults to the contract address. The filter matches the event logs emanating fromaddress
.argument_filters
, optional. Expects a dictionary of argument names and values. When provided event logs are filtered for the event argument values. Event arguments can be both indexed or unindexed. Indexed values with be translated to their corresponding topic arguments. Unindexed arguments will be filtered using a regular expression.topics
optional, accepts the standard JSON-RPC topics argument. See the JSON-RPC documentation for eth_newFilter more information on thetopics
parameters.
-
classmethod
Contract.events.your_event_name.
createFilter
(fromBlock=block, toBlock=block, argument_filters={"arg1": "value"}, topics=[])¶ Warning
Deprecated:
createFilter
has been deprecated in favor of Contract.events.your_event_name.create_filter
-
classmethod
Contract.events.your_event_name.
build_filter
()¶ Creates a EventFilterBuilder instance with the event abi, and the contract address if called from a deployed contract instance. The EventFilterBuilder provides a convenient way to construct the filter parameters with value checking against the event abi. It allows for defining multiple match values or of single values through the match_any and match_single methods.
filter_builder = myContract.events.myEvent.build_filter() filter_builder.fromBlock = "latest" filter_builder.args.clientID.match_any(1, 2, 3, 4) filter_builder.args.region.match_single("UK") filter_instance = filter_builder.deploy()
The
deploy
method returns aweb3.utils.filters.LogFilter
instance from the filter parameters generated by the filter builder. Defining multiple match values for array arguments can be accomplished easily with the filter builder:filter_builder = myContract.events.myEvent.build_filter() filter_builder.args.clientGroups.match_any((1, 3, 5,), (2, 3, 5), (1, 2, 3))
The filter builder blocks already defined filter parameters from being changed.
filter_builder = myContract.events.myEvent.build_filter() filter_builder.fromBlock = "latest" filter_builder.fromBlock = 0 # raises a ValueError
-
classmethod
Contract.
deploy
(transaction=None, args=None)¶ Warning
Deprecated: this method is deprecated in favor of
constructor()
, which provides more flexibility.Construct and send a transaction to deploy the contract.
If provided
transaction
should be a dictionary conforming to theweb3.eth.send_transaction(transaction)
method. This value may not contain the keysdata
orto
.If the contract takes constructor arguments they should be provided as a list via the
args
parameter.If any of the
args
specified in the ABI are anaddress
type, they will accept ENS names.If a
gas
value is not provided, then thegas
value for the deployment transaction will be created using theweb3.eth.estimate_gas()
method.Returns the transaction hash for the deploy transaction.
-
classmethod
Contract.
encodeABI
(fn_name, args=None, kwargs=None, data=None)¶ Encodes the arguments using the Ethereum ABI for the contract function that matches the given
fn_name
and argumentsargs
. Thedata
parameter defaults to the function selector.>>> contract.encodeABI(fn_name="register", args=["rainbows", 10]) "0xea87152b0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000087261696e626f7773000000000000000000000000000000000000000000000000"
-
classmethod
Contract.
all_functions
()¶ Returns a list of all the functions present in a Contract where every function is an instance of
ContractFunction
.>>> contract.all_functions() [<Function identity(uint256,bool)>, <Function identity(int256,bool)>]
-
classmethod
Contract.
get_function_by_signature
(signature)¶ Searches for a distinct function with matching signature. Returns an instance of
ContractFunction
upon finding a match. RaisesValueError
if no match is found.>>> contract.get_function_by_signature('identity(uint256,bool)') <Function identity(uint256,bool)>
-
classmethod
Contract.
find_functions_by_name
(name)¶ Searches for all function with matching name. Returns a list of matching functions where every function is an instance of
ContractFunction
. Returns an empty list when no match is found.>>> contract.find_functions_by_name('identity') [<Function identity(uint256,bool)>, <Function identity(int256,bool)>]
-
classmethod
Contract.
get_function_by_name
(name)¶ Searches for a distinct function with matching name. Returns an instance of
ContractFunction
upon finding a match. RaisesValueError
if no match is found or if multiple matches are found.>>> contract.get_function_by_name('unique_name') <Function unique_name(uint256)>
-
classmethod
Contract.
get_function_by_selector
(selector)¶ Searches for a distinct function with matching selector. The selector can be a hexadecimal string, bytes or int. Returns an instance of
ContractFunction
upon finding a match. RaisesValueError
if no match is found.>>> contract.get_function_by_selector('0xac37eebb') <Function identity(uint256)'> >>> contract.get_function_by_selector(b'\xac7\xee\xbb') <Function identity(uint256)'> >>> contract.get_function_by_selector(0xac37eebb) <Function identity(uint256)'>
-
classmethod
Contract.
find_functions_by_args
(*args)¶ Searches for all function with matching args. Returns a list of matching functions where every function is an instance of
ContractFunction
. Returns an empty list when no match is found.>>> contract.find_functions_by_args(1, True) [<Function identity(uint256,bool)>, <Function identity(int256,bool)>]
-
classmethod
Contract.
get_function_by_args
(*args)¶ Searches for a distinct function with matching args. Returns an instance of
ContractFunction
upon finding a match. RaisesValueError
if no match is found or if multiple matches are found.>>> contract.get_function_by_args(1) <Function unique_func_with_args(uint256)>
Note
Contract
methods all_functions
, get_function_by_signature
, find_functions_by_name
,
get_function_by_name
, get_function_by_selector
, find_functions_by_args
and
get_function_by_args
can only be used when abi is provided to the contract.
Note
Web3.py rejects the initialization of contracts that have more than one function
with the same selector or signature.
eg. blockHashAddendsInexpansible(uint256)
and blockHashAskewLimitary(uint256)
have the
same selector value equal to 0x00000000
. A contract containing both of these functions
will be rejected.
Invoke Ambiguous Contract Functions Example¶
Below is an example of a contract that has multiple functions of the same name, and the arguments are ambiguous.
>>> contract_source_code = """
pragma solidity ^0.4.21;
contract AmbiguousDuo {
function identity(uint256 input, bool uselessFlag) returns (uint256) {
return input;
}
function identity(int256 input, bool uselessFlag) returns (int256) {
return input;
}
}
"""
# fast forward all the steps of compiling and deploying the contract.
>>> ambiguous_contract.functions.identity(1, True) # raises ValidationError
>>> identity_func = ambiguous_contract.get_function_by_signature('identity(uint256,bool)')
>>> identity_func(1, True)
<Function identity(uint256,bool) bound to (1, True)>
>>> identity_func(1, True).call()
1
Enabling Strict Checks for Bytes Types¶
By default, web3 is not very strict when it comes to hex and bytes values.
A bytes type will take a hex string, a bytestring, or a regular python
string that can be decoded as a hex.
Additionally, if an abi specifies a byte size, but the value that gets
passed in is less than the specified size, web3 will automatically pad the value.
For example, if an abi specifies a type of bytes4
, web3 will handle all of the following values:
Input | Normalizes to |
---|---|
'' |
b'\x00\x00\x00\x00' |
'0x' |
b'\x00\x00\x00\x00' |
b'' |
b'\x00\x00\x00\x00' |
b'ab' |
b'ab\x00\x00' |
'0xab' |
b'\xab\x00\x00\x00' |
'1234' |
b'\x124\x00\x00' |
'0x61626364' |
b'abcd' |
'1234' |
b'1234' |
The following values will raise an error by default:
Input | Reason |
---|---|
b'abcde' |
Bytestring with more than 4 bytes |
'0x6162636423' |
Hex string with more than 4 bytes |
2 |
Wrong type |
'ah' |
String is not valid hex |
However, you may want to be stricter with acceptable values for bytes types.
For this you can use the w3.enable_strict_bytes_type_checking()
method,
which is available on the web3 instance. A web3 instance which has had this method
invoked will enforce a stricter set of rules on which values are accepted.
- A Python string that is not prefixed with
0x
will throw an error.- A bytestring whose length not exactly the specified byte size will raise an error.
Input | Normalizes to |
---|---|
'0x' |
b'\x00\x00\x00\x00' |
'0x61626364' |
b'abcd' |
'1234' |
b'1234' |
Input | Reason |
---|---|
'' |
Needs to be prefixed with a “0x” to be interpreted as an empty hex string |
'1234' |
Needs to either be a bytestring (b’1234’) or be a hex value of the right size, prefixed with 0x (in this case: ‘0x31323334’) |
b'' |
Needs to have exactly 4 bytes |
b'ab' |
Needs to have exactly 4 bytes |
'0xab' |
Needs to have exactly 4 bytes |
'0x6162636464' |
Needs to have exactly 4 bytes |
Taking the following contract code as an example:
>>> # pragma solidity >=0.4.22 <0.6.0;
...
... # contract ArraysContract {
... # bytes2[] public bytes2Value;
... # constructor(bytes2[] memory _bytes2Value) public {
... # bytes2Value = _bytes2Value;
... # }
... # function setBytes2Value(bytes2[] memory _bytes2Value) public {
... # bytes2Value = _bytes2Value;
... # }
... # function getBytes2Value() public view returns (bytes2[] memory) {
... # return bytes2Value;
... # }
... # }
>>> # abi = "..."
>>> # bytecode = "6080..."
>>> ArraysContract = w3.eth.contract(abi=abi, bytecode=bytecode)
>>> tx_hash = ArraysContract.constructor([b'b']).transact()
>>> tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
>>> array_contract = w3.eth.contract(
... address=tx_receipt.contractAddress,
... abi=abi
... )
>>> array_contract.functions.getBytes2Value().call()
[b'b\x00']
>>> array_contract.functions.setBytes2Value([b'a']).transact({'gas': 420000, 'gasPrice': Web3.to_wei(1, 'gwei')})
HexBytes('0xc5377ba25224bd763ceedc0ee455cc14fc57b23dbc6b6409f40a557a009ff5f4')
>>> array_contract.functions.getBytes2Value().call()
[b'a\x00']
>>> w3.enable_strict_bytes_type_checking()
>>> array_contract.functions.setBytes2Value([b'a']).transact()
Traceback (most recent call last):
...
ValidationError:
Could not identify the intended function with name `setBytes2Value`
Contract Functions¶
-
class
web3.contract.
ContractFunction
¶
The named functions exposed through the Contract.functions
property are
of the ContractFunction type. This class is not to be used directly,
but instead through Contract.functions
.
For example:
myContract = web3.eth.contract(address=contract_address, abi=contract_abi) twentyone = myContract.functions.multiply7(3).call()
If you have the function name in a variable, you might prefer this alternative:
func_to_call = 'multiply7' contract_func = myContract.functions[func_to_call] twentyone = contract_func(3).call()
ContractFunction
provides methods to interact with contract functions.
Positional and keyword arguments supplied to the contract function subclass
will be used to find the contract function by signature,
and forwarded to the contract function when applicable.
Methods¶
-
ContractFunction.
transact
(transaction)¶ Execute the specified function by sending a new public transaction.
Refer to the following invocation:
myContract.functions.myMethod(*args, **kwargs).transact(transaction)
The first portion of the function call
myMethod(*args, **kwargs)
selects the appropriate contract function based on the name and provided argument. Arguments can be provided as positional arguments, keyword arguments, or a mix of the two.The end portion of this function call
transact(transaction)
takes a single parameter which should be a python dictionary conforming to the same format as theweb3.eth.send_transaction(transaction)
method. This dictionary may not contain the keysdata
.If any of the
args
orkwargs
specified in the ABI are anaddress
type, they will accept ENS names.If a
gas
value is not provided, then thegas
value for the method transaction will be created using theweb3.eth.estimate_gas()
method.Returns the transaction hash.
>>> token_contract.functions.transfer(web3.eth.accounts[1], 12345).transact() "0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd"
-
ContractFunction.
call
(transaction, block_identifier='latest')¶ Call a contract function, executing the transaction locally using the
eth_call
API. This will not create a new public transaction.Refer to the following invocation:
myContract.functions.myMethod(*args, **kwargs).call(transaction)
This method behaves the same as the
ContractFunction.transact()
method, with transaction details being passed into the end portion of the function call, and function arguments being passed into the first portion.Returns the return value of the executed function.
>>> my_contract.functions.multiply7(3).call() 21 >>> token_contract.functions.myBalance().call({'from': web3.eth.coinbase}) 12345 # the token balance for `web3.eth.coinbase` >>> token_contract.functions.myBalance().call({'from': web3.eth.accounts[1]}) 54321 # the token balance for the account `web3.eth.accounts[1]`
You can call the method at a historical block using
block_identifier
. Some examples:# You can call your contract method at a block number: >>> token_contract.functions.myBalance().call(block_identifier=10) # or a number of blocks back from pending, # in this case, the block just before the latest block: >>> token_contract.functions.myBalance().call(block_identifier=-2) # or a block hash: >>> token_contract.functions.myBalance().call(block_identifier='0x4ff4a38b278ab49f7739d3a4ed4e12714386a9fdf72192f2e8f7da7822f10b4d') >>> token_contract.functions.myBalance().call(block_identifier=b'O\xf4\xa3\x8b\'\x8a\xb4\x9fw9\xd3\xa4\xedN\x12qC\x86\xa9\xfd\xf7!\x92\xf2\xe8\xf7\xdax"\xf1\x0bM') # Latest is the default, so this is redundant: >>> token_contract.functions.myBalance().call(block_identifier='latest') # You can check the state after your pending transactions (if supported by your node): >>> token_contract.functions.myBalance().call(block_identifier='pending')
Passing the
block_identifier
parameter for past block numbers requires that your Ethereum API node is running in the more expensive archive node mode. Normally synced Ethereum nodes will fail with a “missing trie node” error, because Ethereum node may have purged the past state from its database. More information about archival nodes here.
-
ContractFunction.
estimateGas
(transaction, block_identifier=None)¶ Warning
Deprecated: This method is deprecated in favor of
estimate_gas
-
ContractFunction.
estimate_gas
(transaction, block_identifier=None)¶ Call a contract function, executing the transaction locally using the
eth_call
API. This will not create a new public transaction.Refer to the following invocation:
myContract.functions.myMethod(*args, **kwargs).estimate_gas(transaction)
This method behaves the same as the
ContractFunction.transact()
method, with transaction details being passed into the end portion of the function call, and function arguments being passed into the first portion.Returns the amount of gas consumed which can be used as a gas estimate for executing this transaction publicly.
>>> my_contract.functions.multiply7(3).estimate_gas() 42650
Note
The parameter
block_identifier
is not enabled in geth nodes, hence passing a value ofblock_identifier
when connected to a geth nodes would result in an error like:ValueError: {'code': -32602, 'message': 'too many arguments, want at most 1'}
-
ContractFunction.
buildTransaction
(transaction)¶ Warning
Deprecated: This method is deprecated in favor of
build_transaction
-
ContractFunction.
build_transaction
(transaction)¶ Builds a transaction dictionary based on the contract function call specified.
Refer to the following invocation:
myContract.functions.myMethod(*args, **kwargs).build_transaction(transaction)
This method behaves the same as the
Contract.transact()
method, with transaction details being passed into the end portion of the function call, and function arguments being passed into the first portion.Note
nonce is not returned as part of the transaction dictionary unless it is specified in the first portion of the function call:
>>> math_contract.functions.increment(5).build_transaction({'nonce': 10})
You may use
getTransactionCount()
to get the current nonce for an account. Therefore a shortcut for producing a transaction dictionary with nonce included looks like:>>> math_contract.functions.increment(5).build_transaction({'nonce': web3.eth.get_transaction_count('0xF5...')})
Returns a transaction dictionary. This transaction dictionary can then be sent using
send_transaction()
.Additionally, the dictionary may be used for offline transaction signing using
sign_transaction()
.>>> math_contract.functions.increment(5).build_transaction({'maxFeePerGas': 2000000000, 'maxPriorityFeePerGas': 1000000000}) { 'to': '0x6Bc272FCFcf89C14cebFC57B8f1543F5137F97dE', 'data': '0x7cf5dab00000000000000000000000000000000000000000000000000000000000000005', 'value': 0, 'gas': 43242, 'maxFeePerGas': 2000000000, 'maxPriorityFeePerGas': 1000000000, 'chainId': 1 }
Fallback Function¶
The Contract Factory also offers an API to interact with the fallback function, which supports four methods like normal functions:
-
Contract.fallback.
call
(transaction)¶ Call fallback function, executing the transaction locally using the
eth_call
API. This will not create a new public transaction.
-
Contract.fallback.
estimateGas
(transaction)¶ Call fallback function and return the gas estimation.
-
Contract.fallback.
transact
(transaction)¶ Execute fallback function by sending a new public transaction.
-
Contract.fallback.
buildTransaction
(transaction)¶ Builds a transaction dictionary based on the contract fallback function call.
Events¶
-
class
web3.contract.
ContractEvents
¶
The named events exposed through the Contract.events
property are of the ContractEvents type. This class is not to be used directly, but instead through Contract.events
.
For example:
myContract = web3.eth.contract(address=contract_address, abi=contract_abi) tx_hash = myContract.functions.myFunction().transact() receipt = web3.eth.get_transaction_receipt(tx_hash) myContract.events.myEvent().process_receipt(receipt)
ContractEvent
provides methods to interact with contract events. Positional and keyword arguments supplied to the contract event subclass will be used to find the contract event by signature.
-
ContractEvents.
myEvent
(*args, **kwargs).process_receipt(transaction_receipt, errors=WARN) Extracts the pertinent logs from a transaction receipt.
If there are no errors,
process_receipt
returns a tuple of Event Log Objects, emitted from the event (e.g.myEvent
), with decoded ouput.>>> tx_hash = contract.functions.myFunction(12345).transact({'to':contract_address}) >>> tx_receipt = w3.eth.get_transaction_receipt(tx_hash) >>> rich_logs = contract.events.myEvent().process_receipt(tx_receipt) >>> rich_logs[0]['args'] {'myArg': 12345}
If there are errors, the logs will be handled differently depending on the flag that is passed in:
WARN
(default) - logs a warning to the console for the log that has an error, and discards the log. Returns any logs that are able to be processed.STRICT
- stops all processing and raises the error encountered.IGNORE
- returns any raw logs that raised an error with an added “errors” field, along with any other logs were able to be processed.DISCARD
- silently discards any logs that have errors, and returns processed logs that don’t have errors.
An event log error flag needs to be imported from
web3/logs.py
.>>> tx_hash = contract.functions.myFunction(12345).transact({'to':contract_address}) >>> tx_receipt = w3.eth.get_transaction_receipt(tx_hash) >>> processed_logs = contract.events.myEvent().process_receipt(tx_receipt) >>> processed_logs ( AttributeDict({ 'args': AttributeDict({}), 'event': 'myEvent', 'logIndex': 0, 'transactionIndex': 0, 'transactionHash': HexBytes('0xfb95ccb6ab39e19821fb339dee33e7afe2545527725b61c64490a5613f8d11fa'), 'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b', 'blockHash': HexBytes('0xd74c3e8bdb19337987b987aee0fa48ed43f8f2318edfc84e3a8643e009592a68'), 'blockNumber': 3 }) ) # Or, if there were errors encountered during processing: >>> from web3.logs import STRICT, IGNORE, DISCARD, WARN >>> processed_logs = contract.events.myEvent().process_receipt(tx_receipt, errors=IGNORE) >>> processed_logs ( AttributeDict({ 'type': 'mined', 'logIndex': 0, 'transactionIndex': 0, 'transactionHash': HexBytes('0x01682095d5abb0270d11a31139b9a1f410b363c84add467004e728ec831bd529'), 'blockHash': HexBytes('0x92abf9325a3959a911a2581e9ea36cba3060d8b293b50e5738ff959feb95258a'), 'blockNumber': 5, 'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b', 'data': '0x0000000000000000000000000000000000000000000000000000000000003039', 'topics': [ HexBytes('0xf70fe689e290d8ce2b2a388ac28db36fbb0e16a6d89c6804c461f65a1b40bb15') ], 'errors': LogTopicError('Expected 1 log topics. Got 0')}) }) ) >>> processed_logs = contract.events.myEvent().process_receipt(tx_receipt, errors=DISCARD) >>> assert processed_logs == () True
-
ContractEvents.
myEvent
(*args, **kwargs).processReceipt(transaction_receipt, errors=WARN) Warning
Deprecation: processReceipt is deprecated in favor of ContractEvents.myEvent.process_receipt
-
ContractEvents.
myEvent
(*args, **kwargs).process_log(log)¶ Similar to process_receipt, but only processes one log at a time, instead of a whole transaction receipt. Will return a single Event Log Object if there are no errors encountered during processing. If an error is encountered during processing, it will be raised.
>>> tx_hash = contract.functions.myFunction(12345).transact({'to':contract_address}) >>> tx_receipt = w3.eth.get_transaction_receipt(tx_hash) >>> log_to_process = tx_receipt['logs'][0] >>> processed_log = contract.events.myEvent().process_log(log_to_process) >>> processed_log AttributeDict({ 'args': AttributeDict({}), 'event': 'myEvent', 'logIndex': 0, 'transactionIndex': 0, 'transactionHash': HexBytes('0xfb95ccb6ab39e19821fb339dee33e7afe2545527725b61c64490a5613f8d11fa'), 'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b', 'blockHash': HexBytes('0xd74c3e8bdb19337987b987aee0fa48ed43f8f2318edfc84e3a8643e009592a68'), 'blockNumber': 3 })
-
ContractEvents.
myEvent
(*args, **kwargs).processLog(log) Warning
processLog has been deprecated in favor of ContractEvents.myEvent.process_log. It will be removed in v6.
Event Log Object¶
The Event Log Object is a python dictionary with the following keys:
args
: Dictionary - The arguments coming from the event.event
: String - The event name.logIndex
: Number - integer of the log index position in the block.transactionIndex
: Number - integer of the transactions index position log was created from.transactionHash
: String, 32 Bytes - hash of the transactions this log was created from.address
: String, 32 Bytes - address from which this log originated.blockHash
: String, 32 Bytes - hash of the block where this log was in. null when it’s pending.blockNumber
: Number - the block number where this log was in. null when it’s pending.
>>> transfer_filter = my_token_contract.events.Transfer.create_filter(fromBlock="0x0", argument_filters={'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf'})
>>> transfer_filter.get_new_entries()
[AttributeDict({'args': AttributeDict({'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'to': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'value': 10}),
'event': 'Transfer',
'logIndex': 0,
'transactionIndex': 0,
'transactionHash': HexBytes('0x9da859237e7259832b913d51cb128c8d73d1866056f7a41b52003c953e749678'),
'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b',
'blockHash': HexBytes('...'),
'blockNumber': 2})]
>>> transfer_filter.get_new_entries()
[]
>>> tx_hash = contract.functions.transfer(alice, 10).transact({'gas': 899000, 'gasPrice': 674302241})
>>> tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
>>> transfer_filter.get_new_entries()
[AttributeDict({'args': AttributeDict({'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'to': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'value': 10}),
'event': 'Transfer',
'logIndex': 0,
'transactionIndex': 0,
'transactionHash': HexBytes('0xa23e7ef4d2692c5cf34ee99123c9c73099e9c3b68c7850f91c1cbcb91ac327e0'),
'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b',
'blockHash': HexBytes('...'),
'blockNumber': 3})]
>>> transfer_filter.get_all_entries()
[AttributeDict({'args': AttributeDict({'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'to': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'value': 10}),
'event': 'Transfer',
'logIndex': 0,
'transactionIndex': 0,
'transactionHash': HexBytes('0x9da859237e7259832b913d51cb128c8d73d1866056f7a41b52003c953e749678'),
'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b',
'blockHash': HexBytes('...'),
'blockNumber': 2}),
AttributeDict({'args': AttributeDict({'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'to': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'value': 10}),
'event': 'Transfer',
'logIndex': 0,
'transactionIndex': 0,
'transactionHash': HexBytes('0xa23e7ef4d2692c5cf34ee99123c9c73099e9c3b68c7850f91c1cbcb91ac327e0'),
'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b',
'blockHash': HexBytes('...'),
'blockNumber': 3})]
Utils¶
-
classmethod
Contract.
decode_function_input
(data)¶ Decodes the transaction data used to invoke a smart contract function, and returns
ContractFunction
and decoded parameters asdict
.>>> transaction = w3.eth.get_transaction('0x5798fbc45e3b63832abc4984b0f3574a13545f415dd672cd8540cd71f735db56') >>> transaction.input '0x612e45a3000000000000000000000000b656b2a9c3b2416437a811e07466ca712f5a5b5a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000116c6f6e656c792c20736f206c6f6e656c7900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' >>> contract.decode_function_input(transaction.input) (<Function newProposal(address,uint256,string,bytes,uint256,bool)>, {'_recipient': '0xB656b2a9c3b2416437A811e07466cA712F5a5b5a', '_amount': 0, '_description': b'lonely, so lonely', '_transactionData': b'', '_debatingPeriod': 604800, '_newCurator': True})
ContractCaller¶
-
class
web3.contract.
ContractCaller
¶
The ContractCaller
class provides an API to call functions in a contract. This class
is not to be used directly, but instead through Contract.caller
.
There are a number of different ways to invoke the ContractCaller
.
For example:
>>> myContract = w3.eth.contract(address=address, abi=ABI)
>>> twentyone = myContract.caller.multiply7(3)
>>> twentyone
21
It can also be invoked using parentheses:
>>> twentyone = myContract.caller().multiply7(3)
>>> twentyone
21
And a transaction dictionary, with or without the transaction
keyword.
You can also optionally include a block identifier. For example:
>>> from_address = w3.eth.accounts[1]
>>> twentyone = myContract.caller({'from': from_address}).multiply7(3)
>>> twentyone
21
>>> twentyone = myContract.caller(transaction={'from': from_address}).multiply7(3)
>>> twentyone
21
>>> twentyone = myContract.caller(block_identifier='latest').multiply7(3)
>>> twentyone
21
Like ContractFunction
, ContractCaller
provides methods to interact with contract functions.
Positional and keyword arguments supplied to the contract caller subclass
will be used to find the contract function by signature,
and forwarded to the contract function when applicable.
Contract FAQs¶
How do I pass in a struct as a function argument?¶
Web3.py accepts struct arguments as dictionaries. This format also supports nested structs. Let’s take a look at a quick example. Given the following Solidity contract:
contract Example {
address addr;
struct S1 {
address a1;
address a2;
}
struct S2 {
bytes32 b1;
bytes32 b2;
}
struct X {
S1 s1;
S2 s2;
address[] users;
}
function update(X memory x) public {
addr = x.s1.a2;
}
function retrieve() public view returns (address) {
return addr;
}
}
You can interact with Web3.py contract API as follows:
# deploy or lookup the deployed contract, then:
>>> deployed_contract.functions.retrieve().call()
'0x0000000000000000000000000000000000000000'
>>> deployed_contract.functions.update({'s1': ['0x0000000000000000000000000000000000000001', '0x0000000000000000000000000000000000000002'], 's2': [b'0'*32, b'1'*32], 'users': []}).transact()
>>> deployed_contract.functions.retrieve().call()
'0x0000000000000000000000000000000000000002'