web3.py: sending ether to a smart contract

Question:

I’m using web3.py to interact with a private Ethereum blockchain. I’d like to call the following function in a smart contract:

    uint256 public cookiePrice;

    function feed(string memory message) public payable {
        require(cookiePrice <= msg.value);
        applyFeeding(msg.sender, message);
    }

I am trying to call it like so:

    price = contract.functions.cookiePrice().call()
    txn = contract.functions.feed("my message").buildTransaction({
      'chainId': 13999911119,
      'gas': 70000,
      'value': price,
      'gasPrice': w3.toWei('8', 'gwei'),
      'nonce': int(time.time())
    })
    signed_txn = w3.eth.account.sign_transaction(txn, private_key=private_key)
    w3.eth.sendRawTransaction(signed_txn.rawTransaction)

This seems to succeed, in that sendRawTransaction returns the hash of the transaction (as described in the docs). But I can see on the chain that the call didn’t actually take effect.

Is there something obvious missing from the code above? Also, how can I get the return of sendRawTransaction to help me debug?

Asked By: tao_oat

||

Answers:

Your transaction was probably never mined because your nonce was way too high. The nonce for an account starts at 0 and increases by exactly 1 for each sent transaction.

You can use w3.eth.getTransactionCount to get the correct nonce for the account you’re using.

Answered By: user94559

Transactions are generated even though your code might fail. You have to pay the miner for executing code that potentially modifies the blockchain, and in case of failure during the execution the remaining gas might be returned to you, but the transaction is created anyway, and so its hash is returned to you.

So, it’s possible that the execution fails inside applyFeeding. I’d check a few things in that call, just in case:

  • What’s the type of price? If it’s int we’re fine.
  • You are not specifying the "from", so the default account is used. Make sure that’s what you want and that the account has enough funds and that its private key is the one you are using to sign.
  • Check for potential problems inside applyFeeding, specially related to who’s the sender, since it is a parameter of that function.
  • Check the amount of gas you are using is enough and you are not running out of gas.

FYI, if I recall correctly web3 has good defaults to several parameters like gas price, gas and nonce, which are dynamically calculated/estimated per call.

Answered By: Molina
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.