Skip to content

Latest commit

 

History

History
1293 lines (937 loc) · 60.9 KB

web3.contract.rst

File metadata and controls

1293 lines (937 loc) · 60.9 KB

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 compiler solc. 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() <web3.eth.Eth.contract> method. By default, the contract factory is Contract.

Properties

Each Contract Factory exposes the following properties.

Methods

Each Contract Factory exposes the following methods.

Creates a new event filter, an instance of :pyweb3.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 of fromBlock, '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 from address.
  • 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 the topics parameters.

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 Web3ValidationError

>>> 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

Disabling Strict Checks for Bytes Types

By default, web3 is strict when it comes to hex and bytes values, as of v6. If an abi specifies a byte size, but the value that gets passed in is not the specified size, web3 will invalidate the value. For example, if an abi specifies a type of bytes4, web3 will invalidate the following values:

Invalid byte and hex strings with strict (default) bytes4 type checking
Input Reason
'' Needs to be prefixed with a "0x" to be interpreted as an empty hex string
2 Wrong type
'ah' String is not valid hex
'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

However, you may want to be less strict with acceptable values for bytes types. This may prove useful if you trust that values coming through are what they are meant to be with respect to the ABI. In this case, the automatic padding might be convenient for inferred types. For this, you can set the w3.strict_bytes_type_checking flag to False, which is available on the Web3 instance. A Web3 instance which has this flag set to False will have a less strict set of rules on which values are accepted. A bytes type will allow values as a hex string, a bytestring, or a regular Python string that can be decoded as a hex. 0x-prefixed hex strings are also not required.

  • A Python string that is not prefixed with 0x is valid.
  • A bytestring whose length is less than the specified byte size is valid.
Valid byte and hex strings for a non-strict bytes4 type
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'

Taking the following contract code as an example:

arrayscontract

from web3 import Web3 w3 = Web3(Web3.EthereumTesterProvider()) bytecode = "608060405234801561001057600080fd5b506040516106103803806106108339810180604052602081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185602082028301116401000000008211171561007e57600080fd5b5050929190505050806000908051906020019061009c9291906100a3565b505061019c565b82805482825590600052602060002090600f0160109004810192821561015a5791602002820160005b8382111561012a57835183826101000a81548161ffff02191690837e010000000000000000000000000000000000000000000000000000000000009004021790555092602001926002016020816001010492830192600103026100cc565b80156101585782816101000a81549061ffff021916905560020160208160010104928301926001030261012a565b505b509050610167919061016b565b5090565b61019991905b8082111561019557600081816101000a81549061ffff021916905550600101610171565b5090565b90565b610465806101ab6000396000f3fe608060405260043610610051576000357c0100000000000000000000000000000000000000000000000000000000900480633b3230ee14610056578063d7c8a410146100e7578063dfe3136814610153575b600080fd5b34801561006257600080fd5b5061008f6004803603602081101561007957600080fd5b8101908080359060200190929190505050610218565b60405180827dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b3480156100f357600080fd5b506100fc61026c565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561013f578082015181840152602081019050610124565b505050509050019250505060405180910390f35b34801561015f57600080fd5b506102166004803603602081101561017657600080fd5b810190808035906020019064010000000081111561019357600080fd5b8201836020820111156101a557600080fd5b803590602001918460208302840111640100000000831117156101c757600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509192919290505050610326565b005b60008181548110151561022757fe5b9060005260206000209060109182820401919006600202915054906101000a90047e010000000000000000000000000000000000000000000000000000000000000281565b6060600080548060200260200160405190810160405280929190818152602001828054801561031c57602002820191906000526020600020906000905b82829054906101000a90047e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190600201906020826001010492830192600103820291508084116102a95790505b5050505050905090565b806000908051906020019061033c929190610340565b5050565b82805482825590600052602060002090600f016010900481019282156103f75791602002820160005b838211156103c757835183826101000a81548161ffff02191690837e01000000000000000000000000000000000000000000000000000000000000900402179055509260200192600201602081600101049283019260010302610369565b80156103f55782816101000a81549061ffff02191690556002016020816001010492830192600103026103c7565b505b5090506104049190610408565b5090565b61043691905b8082111561043257600081816101000a81549061ffff02191690555060010161040e565b5090565b9056fea165627a7a72305820a8f9f1f4815c1eedfb8df31298a5cd13b198895de878871328b5d96296b69b4e0029" abi = ''' [ { "constant": true, "inputs": [ { "name": "", "type": "uint256" } ], "name": "bytes2Value", "outputs": [ { "name": "", "type": "bytes2" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "getBytes2Value", "outputs": [ { "name": "", "type": "bytes2[]" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { "name": "_bytes2Value", "type": "bytes2[]" } ], "name": "setBytes2Value", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "name": "_bytes2Value", "type": "bytes2[]" } ], "payable": false, "stateMutability": "nonpayable", "type": "constructor" } ] '''.strip()

>>> #  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

>>> arrays_contract_instance = w3.eth.contract(abi=abi, bytecode=bytecode)

>>> tx_hash = arrays_contract_instance.constructor([b'bb']).transact() >>> tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) >>> arrays_contract = w3.eth.contract( ... address=tx_receipt.contractAddress, ... abi=abi ... ) >>> arrays_contract.functions.getBytes2Value().call() [b'bb']

>>> # set value with appropriate byte size >>> arrays_contract.functions.setBytes2Value([b'aa']).transact({'gas': 420000, "maxPriorityFeePerGas": 10 ** 9, "maxFeePerGas": 10 ** 9}) HexBytes('0xcb95151142ea56dbf2753d70388aef202a7bb5a1e323d448bc19f1d2e1fe3dc9') >>> # check value >>> arrays_contract.functions.getBytes2Value().call() [b'aa']

>>> # trying to set value without appropriate size (bytes2) is not valid >>> arrays_contract.functions.setBytes2Value([b'b']).transact() Traceback (most recent call last): ... web3.exceptions.Web3ValidationError: Could not identify the intended function with name >>> # check value is still b'aa' >>> arrays_contract.functions.getBytes2Value().call() [b'aa']

>>> # disabling strict byte checking... >>> w3.strict_bytes_type_checking = False

>>> tx_hash = arrays_contract_instance.constructor([b'b']).transact() >>> tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) >>> arrays_contract = w3.eth.contract( ... address=tx_receipt.contractAddress, ... abi=abi ... ) >>> # check value is zero-padded... i.e. b'bx00' >>> arrays_contract.functions.getBytes2Value().call() [b'bx00']

>>> # set the flag back to True >>> w3.strict_bytes_type_checking = True

>>> arrays_contract.functions.setBytes2Value([b'a']).transact() Traceback (most recent call last): ... web3.exceptions.Web3ValidationError: Could not identify the intended function with name

Contract Functions

The named functions exposed through the :pyContract.functions property are of the ContractFunction type. This class is not to be used directly, but instead through :pyContract.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()

:pyContractFunction 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.

EIP-3668 introduced support for the OffchainLookup revert / CCIP Read support. CCIP Read is set to True for calls by default, as recommended in EIP-3668. This is done via a global global_ccip_read_enabled flag on the provider. If raising the OffchainLookup revert is preferred for a specific call, the ccip_read_enabled flag on the call may be set to False.

>>> # raises the revert instead of handling the offchain lookup
>>> myContract.functions.revertsWithOffchainLookup(myData).call(ccip_read_enabled=False)
*** web3.exceptions.OffchainLookup

Disabling CCIP Read support can be useful if a transaction needs to be sent to the callback function. In such cases, "preflighting" with an eth_call, handling the OffchainLookup, and sending the data via a transaction may be necessary. See ccip-read-example in the examples section for how to preflight a transaction with a contract call.

Similarly, if CCIP Read is globally set to False via the global_ccip_read_enabled flag on the provider, it may be enabled on a per-call basis - overriding the global flag. This ensures only explicitly enabled calls will handle the OffchainLookup revert appropriately.

>>> # global flag set to `False`
>>> w3.provider.global_ccip_read_enabled = False

>>> # does not raise the revert since explicitly enabled on the call:
>>> response = myContract.functions.revertsWithOffchainLookup(myData).call(ccip_read_enabled=True)

If the function called results in a revert error, a ContractLogicError will be raised. If there is an error message with the error, web3.py attempts to parse the message that comes back and return it to the user as the error string. As of v6.3.0, the raw data is also returned and can be accessed via the data attribute on ContractLogicError.

Methods

Fallback Function

The Contract Factory also offers an API to interact with the fallback function, which supports four methods like normal functions:

Events

The named events exposed through the :pyContract.events property are of the ContractEvents type. This class is not to be used directly, but instead through :pyContract.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)

:pyContractEvent 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.

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.

create_filter

from web3 import Web3 from hexbytes import HexBytes w3 = Web3(Web3.EthereumTesterProvider()) bytecode = '6060604052341561000c57fe5b604051602080610acb833981016040528080519060200190919050505b620f42408114151561003b5760006000fd5b670de0b6b3a76400008102600281905550600254600060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b505b610a27806100a46000396000f30060606040523615610097576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde0314610099578063095ea7b31461013257806318160ddd1461018957806323b872dd146101af578063313ce5671461022557806370a082311461025157806395d89b411461029b578063a9059cbb14610334578063dd62ed3e1461038b575bfe5b34156100a157fe5b6100a96103f4565b60405180806020018281038252838181518152602001915080519060200190808383600083146100f8575b8051825260208311156100f8576020820191506020810190506020830392506100d4565b505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561013a57fe5b61016f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061042e565b604051808215151515815260200191505060405180910390f35b341561019157fe5b610199610521565b6040518082815260200191505060405180910390f35b34156101b757fe5b61020b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610527565b604051808215151515815260200191505060405180910390f35b341561022d57fe5b610235610791565b604051808260ff1660ff16815260200191505060405180910390f35b341561025957fe5b610285600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610796565b6040518082815260200191505060405180910390f35b34156102a357fe5b6102ab6107e0565b60405180806020018281038252838181518152602001915080519060200190808383600083146102fa575b8051825260208311156102fa576020820191506020810190506020830392506102d6565b505050905090810190601f1680156103265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561033c57fe5b610371600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061081a565b604051808215151515815260200191505060405180910390f35b341561039357fe5b6103de600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610973565b6040518082815260200191505060405180910390f35b604060405190810160405280600981526020017f54657374546f6b656e000000000000000000000000000000000000000000000081525081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a3600190505b92915050565b60025481565b600081600060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410806105f1575081600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b156105fc5760006000fd5b81600060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190505b9392505050565b601281565b6000600060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b604060405190810160405280600481526020017f544553540000000000000000000000000000000000000000000000000000000081525081565b600081600060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156108695760006000fd5b81600060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190505b92915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b929150505600a165627a7a723058205071371ee2a4a1be3c96e77d939cdc26161a256fdd638efc08bd33dfc65d3b850029' ABI = '[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function","stateMutability":"view"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function","stateMutability":"nonpayable"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function","stateMutability":"view"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function","stateMutability":"nonpayable"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function","stateMutability":"view"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function","stateMutability":"view"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function","stateMutability":"view"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function","stateMutability":"nonpayable"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function","stateMutability":"view"},{"inputs":[{"name":"_totalSupply","type":"uint256"}],"payable":false,"type":"constructor","stateMutability":"nonpayable"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}]' my_token_contract = w3.eth.contract(abi=ABI, bytecode=bytecode) alice, bob = w3.eth.accounts[0], w3.eth.accounts[1] assert alice == '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf', alice assert bob == '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF', bob tx_hash = my_token_contract.constructor(1000000).transact({'from': alice, 'gas': 899000, 'gasPrice': Web3.to_wei(1, 'gwei')}) assert tx_hash == HexBytes('0x49e3da72a95e4074a9eaea7b438c73ca154627d317e58abeae914e3769a15044'), tx_hash txn_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) assert txn_receipt['contractAddress'] == '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b', txn_receipt['contractAddress'] contract_address = txn_receipt['contractAddress'] contract = w3.eth.contract(contract_address, abi=ABI) total_supply = contract.functions.totalSupply().call() decimals = 10 ** 18 assert total_supply == 1000000 * decimals, total_supply tx_hash = contract.functions.transfer(alice, 10).transact({'gas': 899000, 'gasPrice': Web3.to_wei(1, 'gwei')}) tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)

create_filter

>>> 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': 1000000000}) >>> 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('...'), '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('...'), 'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b', 'blockHash': HexBytes('...'), 'blockNumber': 2}), AttributeDict({'args': AttributeDict({'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf', 'to': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf', 'value': 10}), 'event': 'Transfer', 'logIndex': 0, 'transactionIndex': 0, 'transactionHash': HexBytes('...'), 'address': '0xF2E246BB76DF876Cef8b38ae84130F4F55De395b', 'blockHash': HexBytes('...'), 'blockNumber': 3})]

Utils

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:

contractcaller

import json from web3 import Web3 w3 = Web3(Web3.EthereumTesterProvider()) bytecode = "0x606060405261022e806100126000396000f360606040523615610074576000357c01000000000000000000000000000000000000000000000000000000009004806316216f391461007657806361bc221a146100995780637cf5dab0146100bc578063a5f3c23b146100e8578063d09de08a1461011d578063dcf537b11461014057610074565b005b610083600480505061016c565b6040518082815260200191505060405180910390f35b6100a6600480505061017f565b6040518082815260200191505060405180910390f35b6100d26004808035906020019091905050610188565b6040518082815260200191505060405180910390f35b61010760048080359060200190919080359060200190919050506101ea565b6040518082815260200191505060405180910390f35b61012a6004805050610201565b6040518082815260200191505060405180910390f35b6101566004808035906020019091905050610217565b6040518082815260200191505060405180910390f35b6000600d9050805080905061017c565b90565b60006000505481565b6000816000600082828250540192505081905550600060005054905080507f3496c3ede4ec3ab3686712aa1c238593ea6a42df83f98a5ec7df9834cfa577c5816040518082815260200191505060405180910390a18090506101e5565b919050565b6000818301905080508090506101fb565b92915050565b600061020d6001610188565b9050610214565b90565b60006007820290508050809050610229565b91905056" ABI = json.loads('[{"constant":false,"inputs":[],"name":"return13","outputs":[{"name":"result","type":"int256"}],"type":"function"},{"constant":true,"inputs":[],"name":"counter","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"amt","type":"uint256"}],"name":"increment","outputs":[{"name":"result","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"a","type":"int256"},{"name":"b","type":"int256"}],"name":"add","outputs":[{"name":"result","type":"int256"}],"type":"function"},{"constant":false,"inputs":[],"name":"increment","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"a","type":"int256"}],"name":"multiply7","outputs":[{"name":"result","type":"int256"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"value","type":"uint256"}],"name":"increased","type":"event"}]') contract = w3.eth.contract(abi=ABI, bytecode=bytecode) deploy_txn = contract.constructor().transact() deploy_receipt = w3.eth.wait_for_transaction_receipt(deploy_txn) address = deploy_receipt.contractAddress

contractcaller

>>> myContract = w3.eth.contract(address=address, abi=ABI) >>> twentyone = myContract.caller.multiply7(3) >>> twentyone 21

It can also be invoked using parentheses:

contractcaller

>>> 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:

contractcaller

>>> 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 :pyContractFunction, :pyContractCaller 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'