provider.anvil

Documentation for eth_defi.provider.anvil Python module.

Anvil integration.

_ ..anvil:

This module provides Python integration for Anvil.

  • Anvil is a blazing-fast local testnet node implementation in Rust from Foundry project

  • Anvil can replace eth_tester.main.EthereumTester as the unit/integration test backend.

  • Anvil is mostly used in mainnet fork test cases.

  • Anvil is a more stable an alternative to Ganache (eth_defi.ganache)

  • Anvil is part of Foundry, a toolkit for Ethereum application development.

To install Anvil on:

curl -L https://foundry.paradigm.xyz | bash
PATH=~/.foundry/bin:$PATH
foundryup  # Needs to be in path, or installation fails

This will install foundryup, anvil at ~/.foundry/bin and adds the folder to your shell rc file PATH.

For more information see Anvil reference.

See also eth_defi.trace for Solidity tracebacks using Anvil.

The code was originally lifted from Brownie project.

Functions

create_anvil_snapshot_state(web3)

Capture the current Anvil state for later reuse.

create_fork_funded_wallet(web3, ...[, ...])

On Anvil forked mainnet, create a wallet with some USDC funds.

dump_state(web3)

Call evm_snapshot on Anvil

find_erc20_balance_slot(web3, token_address, ...)

Find the ERC-20 balanceOf mapping storage slot by brute force.

fork_network_anvil([fork_url, ...])

Creates Anvil unit test backend or mainnet fork.

fund_erc20_on_anvil(web3, token_address, ...)

Fund an address with ERC-20 tokens by directly setting Anvil storage.

is_anvil(web3)

Are we connected to Anvil node.

is_mainnet_fork(web3)

Have we forked mainnet for this test.

launch_anvil([fork_url, unlocked_addresses, ...])

Creates Anvil unit test backend or mainnet fork.

load_state(web3, state)

Call evm_snapshot on Anvil

make_anvil_custom_rpc_request(web3, method)

Make a request to special named EVM JSON-RPC endpoint.

mine(web3[, timestamp, increase_timestamp])

Call evm_setNextBlockTimestamp on Anvil.

reset_anvil_snapshot(web3, state)

Revert a shared Anvil backend to a stored snapshot and resave it.

revert(web3, snapshot_id)

Call evm_revert on Anvil

set_balance(web3, address, raw_amount)

Call anvil_setBalance on Anvil

sleep(web3, seconds)

Call emv_increaseTime on Anvil

snapshot(web3)

Call evm_snapshot on Anvil

unlock_account(web3, address)

Make Anvil mainnet fork to accept transactions to any Ethereum account.

Classes

AnvilForkMetadata

Metadata for a locally running Anvil JSON-RPC endpoint.

AnvilLaunch

Control Anvil processes launched on background.

AnvilSnapshotState

Mutable reset point for a shared Anvil backend.

Exceptions

ArchiveNodeRequired

RPC endpoint does not provide archive node access.

InvalidArgumentWarning

Lifted from Brownie.

RPCRequestError

Lifted from Brownie.

class AnvilForkMetadata

Bases: object

Metadata for a locally running Anvil JSON-RPC endpoint.

This metadata lets later Web3 objects created from only the local Anvil URL still report which upstream fork RPC providers Anvil was configured to use.

Variables
  • chain_id – Chain id reported by the local Anvil instance after startup.

  • upstream_rpc_urls – Original upstream RPC URLs passed to Anvil fork mode. If Anvil was started as a standalone local backend, this is empty.

  • fork_block_number – Explicit fork block used for Anvil, if any.

  • effective_fork_url – URL passed to Anvil as --fork-url. With multiple upstreams this can be a local failover proxy URL instead of one of the upstream RPC URLs.

__init__(chain_id, upstream_rpc_urls, fork_block_number, effective_fork_url)
Parameters
Return type

None

class AnvilLaunch

Bases: object

Control Anvil processes launched on background.

Comes with a helpful close() method when it is time to put Anvil rest.

The chain_id, upstream_rpc_urls, fork_block_number and effective_fork_url fields are the canonical launch metadata exposed to callers. The module-level metadata registry mirrors these values only so that later create_multi_provider_web3(launch.json_rpc_url) calls can attach the same context to retry diagnostics.

__init__(port, cmd, json_rpc_url, process, chain_id=None, upstream_rpc_urls=(), fork_block_number=None, effective_fork_url=None, proxy=None, _proxy_managed=True)
Parameters
Return type

None

close(log_level=None, block=True, block_timeout=30)

Close the background Anvil process.

If this instance owns the RPCProxy (i.e. it was auto-created, not passed in by the caller), the proxy is shut down after Anvil exits and its per-provider statistics are logged.

Parameters
  • log_level (Optional[int]) – Dump Anvil messages to logging

  • block – Block the execution until anvil is gone

  • block_timeout – How long time we try to kill Anvil until giving up.

Returns

Anvil stdout, stderr as string

Return type

tuple[bytes, bytes]

class AnvilSnapshotState

Bases: object

Mutable reset point for a shared Anvil backend.

This helper is designed for pytest suites that keep one Anvil process alive across multiple tests and reset it cheaply using evm_snapshot / evm_revert instead of relaunching the fork each time.

Use create_anvil_snapshot_state() to take the initial snapshot and reset_anvil_snapshot() to restore it between tests.

Note

Only use this pattern in self-contained test modules or conftest files where the web3 fixture is not overridden by sibling modules. Placing an autouse=True restore fixture in a shared conftest.py causes ScopeMismatch errors when other test modules in the same directory override web3 with function scope (e.g. for a different chain). Additionally, module-scoped Anvil forks combined with repeated snapshot/revert cycles can hang on CI runners under pytest-xdist parallel execution, likely due to Anvil process responsiveness degradation after many revert cycles.

Example:

import pytest

from eth_defi.provider.anvil import AnvilSnapshotState, create_anvil_snapshot_state, reset_anvil_snapshot


@pytest.fixture(scope="module")
def deployed_state(web3, deploy_info) -> AnvilSnapshotState:
    # deploy_info is resolved first so the snapshot captures the
    # expensive post-deployment baseline
    return create_anvil_snapshot_state(web3)


@pytest.fixture(autouse=True)
def restore_deployed_state(web3, deployed_state) -> None:
    reset_anvil_snapshot(web3, deployed_state)
__init__(snapshot_id)
Parameters

snapshot_id (int) –

Return type

None

exception ArchiveNodeRequired

Bases: Exception

RPC endpoint does not provide archive node access.

This is raised when a fork test requires historical block access but the RPC endpoint only provides recent blocks.

__init__(message, rpc_url=None, requested_block=None, available_block=None, response_headers=None)
Parameters
__new__(**kwargs)
add_note(note, /)

Add a note to the exception

with_traceback(tb, /)

Set self.__traceback__ to tb and return self.

exception InvalidArgumentWarning

Bases: Warning

Lifted from Brownie.

__init__(*args, **kwargs)
__new__(**kwargs)
add_note(note, /)

Add a note to the exception

with_traceback(tb, /)

Set self.__traceback__ to tb and return self.

exception RPCRequestError

Bases: Exception

Lifted from Brownie.

__init__(*args, **kwargs)
__new__(**kwargs)
add_note(note, /)

Add a note to the exception

with_traceback(tb, /)

Set self.__traceback__ to tb and return self.

create_anvil_snapshot_state(web3)

Capture the current Anvil state for later reuse.

This is the manual building block for snapshot-based fixtures. Call this once after the expensive setup you want to reuse, such as a mainnet fork or a full protocol deployment.

See AnvilSnapshotState for a pytest usage example.

Parameters

web3 (web3.main.Web3) –

Return type

eth_defi.provider.anvil.AnvilSnapshotState

create_fork_funded_wallet(web3, usdc_address, large_usdc_holder, usdc_amount=Decimal('10000'), eth_amount=Decimal('10'))

On Anvil forked mainnet, create a wallet with some USDC funds.

  • Make a new private key account on a forked mainnet

  • Top this up with ETH and USDC from a large USDC holder

Parameters
Return type

eth_defi.hot_wallet.HotWallet

dump_state(web3)

Call evm_snapshot on Anvil

Parameters

web3 (web3.main.Web3) –

Return type

int

find_erc20_balance_slot(web3, token_address, holder_address)

Find the ERC-20 balanceOf mapping storage slot by brute force.

Tries slots 0-19 using Anvil snapshots, which covers all common ERC-20 implementations (OpenZeppelin, Solmate, USDC proxy, etc.).

Note

Only works on Anvil forks, as it uses evm_snapshot, evm_revert, and anvil_setStorageAt RPC methods.

Parameters
Returns

Storage slot number (0-19).

Raises

RuntimeError – If no matching slot is found in the first 20 slots.

Return type

int

fork_network_anvil(fork_url=None, unlocked_addresses=None, cmd='anvil', port=(19999, 29999, 25), block_time=0, launch_wait_seconds=20.0, attempts=3, hardfork='cancun', gas_limit=None, steps_tracing=False, test_request_timeout=3.0, fork_block_number=None, log_wait=False, code_size_limit=None, rpc_smoke_test=True, verbose=False, inherit_stdio=False, warm_up_block=False, archive=True, proxy_multiple_upstream=True)

Creates Anvil unit test backend or mainnet fork.

  • Anvil can be used as web3.py test backend instead of EthereumTester. Anvil offers faster execution and tracing - see eth_defi.trace.

  • Forking a mainnet is a common way to test against live deployments. This function invokes anvil command and tells it to fork a given JSON-RPC endpoint.

When called, a subprocess is started on the background. To stop this process, call eth_defi.anvil.AnvilLaunch.close().

This function waits launch_wait_seconds in order to anvil process to start and complete the chain fork.

Unit test backend:

Mainnet fork: Here is an example that forks BNB chain mainnet and transfer 500 BUSD stablecoin to a test account we control:

from eth_defi.anvil import fork_network_anvil
from eth_defi.chain import install_chain_middleware
from eth_defi.gas import node_default_gas_price_strategy


@pytest.fixture()
def large_busd_holder() -> HexAddress:
    # An onchain address with BUSD balance
    # Binance Hot Wallet 6
    return HexAddress(HexStr("0x8894E0a0c962CB723c1976a4421c95949bE2D4E3"))


@pytest.fixture()
def user_1() -> LocalAccount:
    # Create a test account
    return Account.create()


@pytest.fixture()
def anvil_bnb_chain_fork(request, large_busd_holder, user_1, user_2) -> str:
    # Create a testable fork of live BNB chain.
    mainnet_rpc = os.environ["BNB_CHAIN_JSON_RPC"]
    launch = fork_network_anvil(mainnet_rpc, unlocked_addresses=[large_busd_holder])
    try:
        yield launch.json_rpc_url
    finally:
        # Wind down Anvil process after the test is complete
        launch.close(log_level=logging.ERROR)


@pytest.fixture()
def web3(anvil_bnb_chain_fork: str):
    # Set up a local unit testing blockchain
    # https://web3py.readthedocs.io/en/stable/examples.html#contract-unit-tests-in-python
    web3 = Web3(HTTPProvider(anvil_bnb_chain_fork))
    # Anvil needs POA middlware if parent chain needs POA middleware
    install_chain_middleware(web3)
    web3.eth.set_gas_price_strategy(node_default_gas_price_strategy)
    return web3


def test_anvil_fork_transfer_busd(web3: Web3, large_busd_holder: HexAddress, user_1: LocalAccount):
    # Forks the BNB chain mainnet and transfers from USDC to the user.

    # BUSD deployment on BNB chain
    # https://bscscan.com/token/0xe9e7cea3dedca5984780bafc599bd69add087d56
    busd_details = fetch_erc20_details(web3, "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56")
    busd = busd_details.contract

    # Transfer 500 BUSD to the user 1
    tx_hash = busd.functions.transfer(user_1.address, 500 * 10**18).transact({"from": large_busd_holder})

    # Because Ganache has instamine turned on by default, we do not need to wait for the transaction
    receipt = web3.eth.get_transaction_receipt(tx_hash)
    assert receipt.status == 1, "BUSD transfer reverted"

    assert busd.functions.balanceOf(user_1.address).call() == 500 * 10**18

See the full example in tests source code.

If anvil refuses to terminate properly, you can kill a process by a port in your terminal:

# Kill any process listening to localhost:19999
kill -SIGKILL $(lsof -ti:19999)

See also

Note

Looks like we have some issues Anvil instance lingering around even after AnvilLaunch.close() if scoped pytest fixtures are used.

If you intentionally keep a fork alive across multiple tests, pair a module-scoped launch_anvil() / fork_network_anvil() fixture with create_anvil_snapshot_state() and reset_anvil_snapshot() so you can reset state cheaply between tests.

Parameters
  • cmd – Override anvil command. If not given we look up from PATH.

  • fork_url (Optional[str]) –

    HTTP JSON-RPC URL of the network we want to fork.

    If not given launch an empty test backend.

  • unlocked_addresses (list[eth_typing.evm.HexAddress | str]) – List of addresses of which ownership we take to allow test code to transact as them

  • port (Union[int, tuple]) –

    Localhost port we bind for Anvil JSON-RPC.

    The tuple format is (min port, max port, opening attempts).

    By default, takes a tuple range and tries to open a a random port in the range, until empty found. This allows to run multiple parallel Anvil’s during unit testing with pytest -n auto.

    You can also specify an individual port.

  • launch_wait_seconds – How long we wait anvil to start until giving up

  • block_time

    How long Anvil takes to mine a block. Default is zero: Anvil is in automining mode and creates a new block for each new transaction.

    Set to 1 or higher so that you can poll the transaction as you would do with a live JSON-RPC node.

  • attempts

    How many attempts we do to start anvil.

    Anvil launch may fail without any output. This could be because the given JSON-RPC node is throttling your API requests. In this case we just try few more times again by killing the Anvil process and starting it again.

  • gas_limit (Optional[int]) – Set the block gas limit.

  • hardfork (Optional[str]) – EVM version to use

  • step_tracing

    Enable Anvil step tracing.

    Needed to get structured logs.

    Only needed on GoEthereum style tracing, not needed for Parity style tracing.

    See https://book.getfoundry.sh/reference/anvil/

  • test_request_timeout – Set the timeout fro the JSON-RPC requests that attempt to determine if Anvil was successfully launched.

  • fork_block_number (Optional[int]) –

    For at a specific block height of the parent chain.

    If not given, fork at the latest block. Needs an archive node to work.

    HyperEVM is a special case: if the caller does not supply an explicit fork block, launch_anvil() automatically pins the fork a few blocks behind the tip. This avoids the recurring HyperEVM failure where Anvil aborts with Error: failed to create genesis because the upstream RPC responds with {"message":"Unknown block","code":26} while resolving latest during genesis creation.

  • rpc_smoke_test – Check that the RPC is working before attempting to start Anvil

  • verbose

    Make Anvil the proces to dump a lot of stuff to stdout/stderr.

    See -vvvv https://getfoundry.sh/anvil/reference/anvil

  • inherit_stdio (bool) –

    If True, let the Anvil subprocess inherit the parent process stdout/stderr instead of capturing them in pipes.

    This is useful in Docker and other supervised environments where you want Anvil logs to appear live in the container logs.

    Warning

    When False (default), stdout/stderr are captured and only read when the process is shut down. If Anvil is very chatty, those pipe buffers can fill up and stall the subprocess.

  • warm_up_block (bool) –

    If True and running in fork mode, eagerly call eth_getBlockByNumber(fork_block, true) against the freshly started local Anvil instance.

    This can move an expensive first fork hydration from an arbitrary later request to startup. It does not remove the cost, but it makes it happen once, predictably, before the caller starts using the node.

  • archive (bool) –

    Check that the RPC endpoint provides archive node access.

    When True (default) and fork_block_number is specified, performs a smoke test to verify the RPC can access historical blocks. If the RPC cannot access the requested block, raises ArchiveNodeRequired with HTTP response headers to help identify the problematic RPC provider.

  • proxy_multiple_upstream (RPCProxy | RPCProxyConfig | bool) –

    Controls how multiple upstream RPC providers in fork_url are handled.

    Background: Anvil accepts only a single --fork-url and has no internal retry or failover logic. When the upstream is slow or rate-limited, Anvil hangs indefinitely. This parameter enables a transparent JSON-RPC proxy (RPCProxy) that sits between Anvil and multiple upstreams, providing automatic failover, per-request timeouts, and diagnostics.

    The proxy is only relevant when fork_url contains multiple space-separated RPC URLs. With a single URL this parameter is ignored.

    Accepted values:

    • ``True`` (default) — automatically start a proxy with default settings when multiple RPCs are detected. The proxy lifecycle is tied to AnvilLaunch.close(): it starts before Anvil and shuts down (logging per-provider statistics) after Anvil exits.

    • ``False`` — disable the proxy entirely. Falls back to the legacy behaviour of picking one RPC in round-robin order per launch_anvil() call, with no intra-session failover.

    • An :py:class:`~eth_defi.provider.rpc_proxy.RPCProxyConfig` instance — automatically start a proxy with custom settings. Any fields not set explicitly use their dataclass defaults. Example:

      from eth_defi.provider.rpc_proxy import RPCProxyConfig
      
      launch_anvil(
          fork_url="https://rpc-a.example.com https://rpc-b.example.com",
          proxy_multiple_upstream=RPCProxyConfig(
              timeout=15.0,
              retries=5,
              auto_switch_request_count=50,
          ),
      )
      
    • An :py:class:`~eth_defi.provider.rpc_proxy.RPCProxy` instance — use a proxy that you created yourself via start_rpc_proxy(). Useful when you need full control over the proxy lifecycle or want to share a single proxy across multiple Anvil instances. In this case launch_anvil does not manage the proxy lifecycle — you must call close() yourself.

    See eth_defi.provider.rpc_proxy for the full proxy API.

  • code_size_limit (int) –

Parma code_size_limit

Max smart contract size

Parma log_wait

Display info level logging while waiting for Anvil to start.

Raises

ArchiveNodeRequired – When archive=True and the RPC endpoint cannot access the requested historical block.

Return type

eth_defi.provider.anvil.AnvilLaunch

fund_erc20_on_anvil(web3, token_address, recipient, amount)

Fund an address with ERC-20 tokens by directly setting Anvil storage.

Auto-detects the balanceOf mapping slot using find_erc20_balance_slot(), then writes the amount directly to the token’s storage.

Example — mint 1000 USDC on an Arbitrum Anvil fork:

from eth_defi.provider.anvil import launch_anvil, fund_erc20_on_anvil
from eth_defi.provider.multi_provider import create_multi_provider_web3
from eth_defi.token import USDC_NATIVE_TOKEN, fetch_erc20_details

anvil = launch_anvil(fork_url="https://arb1.arbitrum.io/rpc")
web3 = create_multi_provider_web3(anvil.json_rpc_url)

chain_id = web3.eth.chain_id  # 42161
usdc_address = USDC_NATIVE_TOKEN[chain_id]
usdc = fetch_erc20_details(web3, usdc_address)

recipient = "0xYourAddress..."
fund_erc20_on_anvil(
    web3,
    usdc_address,
    recipient,
    usdc.convert_to_raw(1000),  # 1000 USDC
)

balance = usdc.fetch_balance_of(recipient)
assert balance == 1000
Parameters
Returns

The storage slot that was written to.

Return type

int

is_anvil(web3)

Are we connected to Anvil node.

You need to change some behavior depending if you are connected to a real node or Anvil simulation.

This can be either

  • Mainnet work (chain id copied from the forked blockchain)

  • Anvil test backend

See also launch_anvil()

Warning

This method will crash with Base mainnet sequencer:

requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://mainnet-sequencer.base.org/.

Parameters

web3 (web3.main.Web3) – Web3 connection instance to check

Returns

True if we think we are connected to Anvil

Return type

bool

is_mainnet_fork(web3)

Have we forked mainnet for this test.

Returns

True if we think we are connected to a forked mainnet, False if we think we are a standalone local dev chain.

Parameters

web3 (web3.main.Web3) –

Return type

bool

launch_anvil(fork_url=None, unlocked_addresses=None, cmd='anvil', port=(19999, 29999, 25), block_time=0, launch_wait_seconds=20.0, attempts=3, hardfork='cancun', gas_limit=None, steps_tracing=False, test_request_timeout=3.0, fork_block_number=None, log_wait=False, code_size_limit=None, rpc_smoke_test=True, verbose=False, inherit_stdio=False, warm_up_block=False, archive=True, proxy_multiple_upstream=True)

Creates Anvil unit test backend or mainnet fork.

  • Anvil can be used as web3.py test backend instead of EthereumTester. Anvil offers faster execution and tracing - see eth_defi.trace.

  • Forking a mainnet is a common way to test against live deployments. This function invokes anvil command and tells it to fork a given JSON-RPC endpoint.

When called, a subprocess is started on the background. To stop this process, call eth_defi.anvil.AnvilLaunch.close().

This function waits launch_wait_seconds in order to anvil process to start and complete the chain fork.

Unit test backend:

Mainnet fork: Here is an example that forks BNB chain mainnet and transfer 500 BUSD stablecoin to a test account we control:

from eth_defi.anvil import fork_network_anvil
from eth_defi.chain import install_chain_middleware
from eth_defi.gas import node_default_gas_price_strategy


@pytest.fixture()
def large_busd_holder() -> HexAddress:
    # An onchain address with BUSD balance
    # Binance Hot Wallet 6
    return HexAddress(HexStr("0x8894E0a0c962CB723c1976a4421c95949bE2D4E3"))


@pytest.fixture()
def user_1() -> LocalAccount:
    # Create a test account
    return Account.create()


@pytest.fixture()
def anvil_bnb_chain_fork(request, large_busd_holder, user_1, user_2) -> str:
    # Create a testable fork of live BNB chain.
    mainnet_rpc = os.environ["BNB_CHAIN_JSON_RPC"]
    launch = fork_network_anvil(mainnet_rpc, unlocked_addresses=[large_busd_holder])
    try:
        yield launch.json_rpc_url
    finally:
        # Wind down Anvil process after the test is complete
        launch.close(log_level=logging.ERROR)


@pytest.fixture()
def web3(anvil_bnb_chain_fork: str):
    # Set up a local unit testing blockchain
    # https://web3py.readthedocs.io/en/stable/examples.html#contract-unit-tests-in-python
    web3 = Web3(HTTPProvider(anvil_bnb_chain_fork))
    # Anvil needs POA middlware if parent chain needs POA middleware
    install_chain_middleware(web3)
    web3.eth.set_gas_price_strategy(node_default_gas_price_strategy)
    return web3


def test_anvil_fork_transfer_busd(web3: Web3, large_busd_holder: HexAddress, user_1: LocalAccount):
    # Forks the BNB chain mainnet and transfers from USDC to the user.

    # BUSD deployment on BNB chain
    # https://bscscan.com/token/0xe9e7cea3dedca5984780bafc599bd69add087d56
    busd_details = fetch_erc20_details(web3, "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56")
    busd = busd_details.contract

    # Transfer 500 BUSD to the user 1
    tx_hash = busd.functions.transfer(user_1.address, 500 * 10**18).transact({"from": large_busd_holder})

    # Because Ganache has instamine turned on by default, we do not need to wait for the transaction
    receipt = web3.eth.get_transaction_receipt(tx_hash)
    assert receipt.status == 1, "BUSD transfer reverted"

    assert busd.functions.balanceOf(user_1.address).call() == 500 * 10**18

See the full example in tests source code.

If anvil refuses to terminate properly, you can kill a process by a port in your terminal:

# Kill any process listening to localhost:19999
kill -SIGKILL $(lsof -ti:19999)

See also

Note

Looks like we have some issues Anvil instance lingering around even after AnvilLaunch.close() if scoped pytest fixtures are used.

If you intentionally keep a fork alive across multiple tests, pair a module-scoped launch_anvil() / fork_network_anvil() fixture with create_anvil_snapshot_state() and reset_anvil_snapshot() so you can reset state cheaply between tests.

Parameters
  • cmd – Override anvil command. If not given we look up from PATH.

  • fork_url (Optional[str]) –

    HTTP JSON-RPC URL of the network we want to fork.

    If not given launch an empty test backend.

  • unlocked_addresses (list[eth_typing.evm.HexAddress | str]) – List of addresses of which ownership we take to allow test code to transact as them

  • port (Union[int, tuple]) –

    Localhost port we bind for Anvil JSON-RPC.

    The tuple format is (min port, max port, opening attempts).

    By default, takes a tuple range and tries to open a a random port in the range, until empty found. This allows to run multiple parallel Anvil’s during unit testing with pytest -n auto.

    You can also specify an individual port.

  • launch_wait_seconds – How long we wait anvil to start until giving up

  • block_time

    How long Anvil takes to mine a block. Default is zero: Anvil is in automining mode and creates a new block for each new transaction.

    Set to 1 or higher so that you can poll the transaction as you would do with a live JSON-RPC node.

  • attempts

    How many attempts we do to start anvil.

    Anvil launch may fail without any output. This could be because the given JSON-RPC node is throttling your API requests. In this case we just try few more times again by killing the Anvil process and starting it again.

  • gas_limit (Optional[int]) – Set the block gas limit.

  • hardfork (Optional[str]) – EVM version to use

  • step_tracing

    Enable Anvil step tracing.

    Needed to get structured logs.

    Only needed on GoEthereum style tracing, not needed for Parity style tracing.

    See https://book.getfoundry.sh/reference/anvil/

  • test_request_timeout – Set the timeout fro the JSON-RPC requests that attempt to determine if Anvil was successfully launched.

  • fork_block_number (Optional[int]) –

    For at a specific block height of the parent chain.

    If not given, fork at the latest block. Needs an archive node to work.

    HyperEVM is a special case: if the caller does not supply an explicit fork block, launch_anvil() automatically pins the fork a few blocks behind the tip. This avoids the recurring HyperEVM failure where Anvil aborts with Error: failed to create genesis because the upstream RPC responds with {"message":"Unknown block","code":26} while resolving latest during genesis creation.

  • rpc_smoke_test – Check that the RPC is working before attempting to start Anvil

  • verbose

    Make Anvil the proces to dump a lot of stuff to stdout/stderr.

    See -vvvv https://getfoundry.sh/anvil/reference/anvil

  • inherit_stdio (bool) –

    If True, let the Anvil subprocess inherit the parent process stdout/stderr instead of capturing them in pipes.

    This is useful in Docker and other supervised environments where you want Anvil logs to appear live in the container logs.

    Warning

    When False (default), stdout/stderr are captured and only read when the process is shut down. If Anvil is very chatty, those pipe buffers can fill up and stall the subprocess.

  • warm_up_block (bool) –

    If True and running in fork mode, eagerly call eth_getBlockByNumber(fork_block, true) against the freshly started local Anvil instance.

    This can move an expensive first fork hydration from an arbitrary later request to startup. It does not remove the cost, but it makes it happen once, predictably, before the caller starts using the node.

  • archive (bool) –

    Check that the RPC endpoint provides archive node access.

    When True (default) and fork_block_number is specified, performs a smoke test to verify the RPC can access historical blocks. If the RPC cannot access the requested block, raises ArchiveNodeRequired with HTTP response headers to help identify the problematic RPC provider.

  • proxy_multiple_upstream (RPCProxy | RPCProxyConfig | bool) –

    Controls how multiple upstream RPC providers in fork_url are handled.

    Background: Anvil accepts only a single --fork-url and has no internal retry or failover logic. When the upstream is slow or rate-limited, Anvil hangs indefinitely. This parameter enables a transparent JSON-RPC proxy (RPCProxy) that sits between Anvil and multiple upstreams, providing automatic failover, per-request timeouts, and diagnostics.

    The proxy is only relevant when fork_url contains multiple space-separated RPC URLs. With a single URL this parameter is ignored.

    Accepted values:

    • ``True`` (default) — automatically start a proxy with default settings when multiple RPCs are detected. The proxy lifecycle is tied to AnvilLaunch.close(): it starts before Anvil and shuts down (logging per-provider statistics) after Anvil exits.

    • ``False`` — disable the proxy entirely. Falls back to the legacy behaviour of picking one RPC in round-robin order per launch_anvil() call, with no intra-session failover.

    • An :py:class:`~eth_defi.provider.rpc_proxy.RPCProxyConfig` instance — automatically start a proxy with custom settings. Any fields not set explicitly use their dataclass defaults. Example:

      from eth_defi.provider.rpc_proxy import RPCProxyConfig
      
      launch_anvil(
          fork_url="https://rpc-a.example.com https://rpc-b.example.com",
          proxy_multiple_upstream=RPCProxyConfig(
              timeout=15.0,
              retries=5,
              auto_switch_request_count=50,
          ),
      )
      
    • An :py:class:`~eth_defi.provider.rpc_proxy.RPCProxy` instance — use a proxy that you created yourself via start_rpc_proxy(). Useful when you need full control over the proxy lifecycle or want to share a single proxy across multiple Anvil instances. In this case launch_anvil does not manage the proxy lifecycle — you must call close() yourself.

    See eth_defi.provider.rpc_proxy for the full proxy API.

  • code_size_limit (int) –

Parma code_size_limit

Max smart contract size

Parma log_wait

Display info level logging while waiting for Anvil to start.

Raises

ArchiveNodeRequired – When archive=True and the RPC endpoint cannot access the requested historical block.

Return type

eth_defi.provider.anvil.AnvilLaunch

load_state(web3, state)

Call evm_snapshot on Anvil

Parameters
  • web3 (web3.main.Web3) –

  • state (str) –

Return type

int

make_anvil_custom_rpc_request(web3, method, args=None)

Make a request to special named EVM JSON-RPC endpoint.

Parameters
  • method (str) – RPC endpoint name

  • args (Optional[list]) – JSON-RPC call arguments

  • web3 (web3.main.Web3) –

Returns

RPC result

Raises

RPCRequestError – In the case RPC method errors

Return type

Any

mine(web3, timestamp=None, increase_timestamp=0)

Call evm_setNextBlockTimestamp on Anvil.

Mine blocks, optionally set the time of the new block.

Parameters
  • web3 (web3.main.Web3) – Web3 connection connected to Anvil JSON-RPC.

  • timestamp (Optional[int]) – Jump to absolute future timestamp.

  • increase_timestamp (float) – How many seconds we leap to the future.

Return type

None

reset_anvil_snapshot(web3, state)

Revert a shared Anvil backend to a stored snapshot and resave it.

evm_revert consumes the snapshot it restores. Because of this, the helper immediately creates a new snapshot after each reset so the same AnvilSnapshotState instance can be reused by the next test.

See AnvilSnapshotState for a pytest usage example.

Parameters
Return type

None

revert(web3, snapshot_id)

Call evm_revert on Anvil

https://book.getfoundry.sh/reference/anvil/

Returns

True if a snapshot was reverted

Parameters
  • web3 (web3.main.Web3) –

  • snapshot_id (int) –

Return type

bool

set_balance(web3, address, raw_amount)

Call anvil_setBalance on Anvil

Parameters
  • web3 (web3.main.Web3) –

  • address (str) –

  • raw_amount (int) –

Return type

int

sleep(web3, seconds)

Call emv_increaseTime on Anvil

Parameters
  • web3 (web3.main.Web3) –

  • seconds (int) –

Return type

int

snapshot(web3)

Call evm_snapshot on Anvil

Parameters

web3 (web3.main.Web3) –

Return type

int

unlock_account(web3, address)

Make Anvil mainnet fork to accept transactions to any Ethereum account.

This is even when we do not have a private key for the account.

Parameters
  • web3 (web3.main.Web3) – Web3 instance

  • address (str) – Account to unlock