Skip to content

Work around slow RPCs leading to crash #434

@linearray

Description

@linearray

probably related: #361

When deploying a contract boa will wait for the TX receipt, which states the block the TX is contained in. Afterwards it will reset the state to that block, this involves an eth_getBlockByNumber call: https://github.com/vyperlang/titanoboa/blob/master/boa/vm/fork.py#L194

Problem is, many RPCs don't have that block available on the API in time, boa gets a null result and crashes. A few seconds later the block is available and everything would have worked out. A good example for this behavior is https://sepolia.base.org/. I have seen this with at least two more RPCs in the past few days and, if needed, can find them again.

I worked around this for now by making my network interface artificially slow (introducing 2000ms delay between requests), but I think the fix would be retrying the request (when you know it should be there, like after deploying).

Traceback

  File "/Users/linearray/Documents/vypertest/bin/admin/deploy_erc20.py", line 13, in go
    token    = deployer.deploy(*args)
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/boa/contracts/vyper/vyper_contract.py", line 92, in deploy
    return VyperContract(
        self.compiler_data, *args, filename=self.filename, **kwargs
    )
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/boa/contracts/vyper/vyper_contract.py", line 558, in __init__
    addr = self._run_init(
        *args, value=value, override_address=override_address, gas=gas, sender=sender
    )
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/boa/contracts/vyper/vyper_contract.py", line 591, in _run_init
    address, computation = self.env.deploy(
                           ~~~~~~~~~~~~~~~^
        bytecode=initcode,
        ^^^^^^^^^^^^^^^^^^
    ...<4 lines>...
        sender=sender,
        ^^^^^^^^^^^^^^
    )
    ^
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/boa/network.py", line 413, in deploy
    txdata, receipt, trace = self._send_txn(
                             ~~~~~~~~~~~~~~^
        from_=sender, value=value, gas=gas, data=bytecode
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/boa/network.py", line 603, in _send_txn
    self._reset_fork(block_identifier=receipt["blockNumber"])
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/boa/network.py", line 536, in _reset_fork
    self.fork_rpc(self._rpc, reset_traces=False, block_identifier=block_identifier)
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/boa/environment.py", line 95, in fork_rpc
    self.evm.fork_rpc(rpc, block_identifier, debug=debug, **kwargs)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/boa/vm/py_evm.py", line 424, in fork_rpc
    self._init_vm(account_db_class)
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/boa/vm/py_evm.py", line 397, in _init_vm
    self.patch = VMPatcher(self.vm)
                 ~~~~~~~~~^^^^^^^^^
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/boa/vm/py_evm.py", line 63, in __init__
    (self._exc_patchables, vm.state.execution_context),
                           ^^^^^^^^
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/eth/vm/base.py", line 141, in state
    self._state = self.build_state(
                  ~~~~~~~~~~~~~~~~^
        self.chaindb.db,
        ^^^^^^^^^^^^^^^^
    ...<2 lines>...
        self.previous_hashes,
        ^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/eth/vm/base.py", line 160, in build_state
    return cls.get_state_class()(db, execution_context, header.state_root)
           ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/eth/vm/state.py", line 65, in __init__
    self._account_db = self.get_account_db_class()(db, state_root)
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/boa/vm/fork.py", line 174, in __init__
    super().__init__(
    ~~~~~~~~~~~~~~~~^
        caching_rpc, chain_id, block_identifier, *args, **kwargs2
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/Users/linearray/Documents/vypertest/.venv/lib/python3.14/site-packages/boa/vm/fork.py", line 197, in __init__
    self._block_number = to_int(self._block_info["number"])
                                ~~~~~~~~~~~~~~~~^^^^^^^^^^
TypeError: 'NoneType' object is not subscriptable

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions