Web3.py Patterns: call state overrides

As of version 5.19.0, Web3.py includes one of Geth's lesser-known debugging features: the ability to override state when using the eth_call JSON-RPC method. What that means in practical terms is that you're able to alter the nonce or balance of the account sending the transaction, and the bytecode or state of the contract itself on the fly.

Note: eth_call executes all transactions locally, simulating their outcome on the network. No state is affected on the blockchain. Sadly, you cannot override your account balance to infinity ether on Mainnet.

This feature can save you the dev cycles of redeploying contracts or preparing accounts to have the intended state for any given test. Overridable fields include balance, nonce, code, state, and stateDiff, and can be overridden whether you own the accounts or not. See the Geth docs for the full specification.

A contrived example should give you the gist of it. In this example, we read from a Greeter contract, then override it's code to return an alternate phrase.

# 1) configure your Web3 instance:
from web3 import Web3, HTTPProvider
w3 = Web3(HTTPProvider(<your provider URL>))

# 2) build a transaction:
txn_params = {
    "from": "0xYourAddress",
    "to": "0xContractAddress",
    "data": "d67e4b84"  # Your function hash
}

# 3) sanity check - read from the contract: 
call_result = w3.eth.call(txn_params)
result = w3.codec.decode_single("string", call_result)
assert result == "Hello world!"

# 4) tweak the contract in Remix, for example,
#    then compile and grab the *runtime* bytecode
override_code = "0xOverrideRuntimeBytecode"

# 5) make the call again, but with overridden bytecode:
override_params = {"0xContractAddress": {"code": override_code}}
override_result = w3.eth.call(txn_params, "latest", override_params)
greeting = w3.codec.decode_single("string", override_result)
assert greeting == "Hola mundo!"

For one more command line example, see Geth's documentation. Happy debugging!