I have my own private keys for an account and I'm using web3py to invoke a smart contract function. The way things are right now as per the docs, I first need to build the transaction, sign with my private keys and then send it as a raw transaction.
The problem is I can't build the transaction without it throwing a ContractLogicError
. The function will be valid a few blocks down the line so I want to send it as soon as possible but even though the docs claim that buildTransaction
doesn't actually send anything, it seems to validate the arguments with the current block for which it fails.
Is there a way for me to build the transaction without the smart contract validation, package it up and send it. This risks my contract failing on the chain and costing me gas fees, but it's a risk I'm willing to take.
Code looks something like this:
contract = [
{"name":"send","outputs":[],"stateMutability":"nonpayable","type":"function","inputs":[{"internalType":"uint256","name":"gameId","type":"uint256"},{"internalType":"uint256","name":"resourceId","type":"uint256"}]},
]
action = contract.functions.send(game_id, resource_id)
try:
txn = action.buildTransaction({
'chainId': CHAIN_ID,
'maxFeePerGas': w3.toWei(max_fee, 'gwei'),
'maxPriorityFeePerGas': w3.toWei(max_priority_fee, 'gwei'),
'from': from_address,
'nonce': nonce_manager[from_address],
})
signed = w3.eth.account.sign_transaction(txn, PRIVATE_KEY)
txhash = Web3.toHex(w3.eth.send_raw_transaction(signed.rawTransaction))
receipt = w3.eth.wait_for_transaction_receipt(txhash, timeout=60)
nonce_manager[from_address] += 1
return receipt, None
except Exception as e:
return None, e
I get a contract specific exception when I run this: INVALID RESOURCE_ID
and never even gets to send_raw_transaction
. Removing it makes no difference. However if I put this in a while loop it eventually works after a few blocks.
Tested on latest web3py
and Ubuntu 20.01 as well as Mac 12.1 both using Python 3.9.7
buildTransaction
method does not care about your node or the blockchain's current state, it cares about the ABI.ContractLogicError
is fired if the transaction is sent and the contract's execution reverts. The example in the doc works, so that "pretty much" is where the problem lies. Maybe we can help if you share exactly what you are trying to do, differently than the base example.send_raw_transaction
step and it throws the error. There is no point in be posting the source code because it will look identical to the example. The only way to replicate it is to run my entire program because it keeps monitoring the blockchain and quickly attempts to react to a transaction. Since I can working off of data from pending transactions I am able to see what's about to happen.