I managed to successfully deploy a contract using Web3.py to the Ethereum Ropsten network using this bit of code

def deploy(self):
    instance = self.w3.eth.contract(abi=self.abi, bytecode=self.bin)

    construct_txn = instance.constructor().buildTransaction({
        'from': self.pub,
        'value': 10,
        'gas': 1000000,
        'gasPrice': w3.eth.gasPrice,
        'nonce': self.w3.eth.getTransactionCount(self.pub),

    signed = self.acct.signTransaction(construct_txn)
    tx_hash = self.w3.eth.sendRawTransaction(signed.rawTransaction)

I then take the transaction hash, and pass it to this function to create a contract instance I can play around with using Python

def contract_in_concise_mode(contract_address):
    # Contract instance in concise mode
    abi = contract_interface['abi']
    contract_instance = w3.eth.contract(address=contract_address, abi=abi, ContractFactoryClass=ConciseContract)
    return contract_instance

But I am getting this error

web3.exceptions.InvalidAddress: ('Address must be 20 bytes, as a hex string with a 0x prefix', '0xa ....... 49')

sendRawTransaction returns a transaction hash, and you need the contract address. Transaction hashes are 32 bytes and addresses are 20 bytes.

To get the address you have to examine the transaction receipt.

From web3.py documentation https://web3py.readthedocs.io/en/stable/contracts.html

# Wait for the transaction to be mined, and get the transaction receipt
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)

# Create the contract instance with the newly-deployed address
greeter = w3.eth.contract(

Function sendRawTransaction returns transaction hash rather than smart contract address. In order to get smart contract address, you have basically two options:

  1. Wait until transaction is mined, obtain its receipt, and extract contract address from it, as @Ismael suggested
  2. Derive smart contract address from from address and nonce value

For the first way do something like this:

contract_address = web3.eth.getTransactionReceipt(tx_hash)['contractAddress']

See details in Web3.py documentation

For the second way do something like this:

contract_address = sha3(rlp.encode([normalize_address(sender), nonce]))[12:]

For the seconds way you don't need to wait until your transaction is mined. See this answer for details how contract address is derived.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.