Foundry Anvil Guide: Complete Commands, Local Chains, and Advanced Solidity Workflows

Anvil is Foundry's local Ethereum JSON-RPC node. It starts quickly, provides prefunded development accounts and instant mining, and can fork any EVM-compatible network, control mining, manipulate time, impersonate accounts, edit balances and storage, persist chain state, and return execution traces.

Forge's test runner is ideal for Solidity tests inside one process. Anvil is better when an application needs a long-running node: frontend integration, multi-process end-to-end tests, deployment rehearsal, wallet connections, transaction-pool testing, and mainnet-state reproduction.

Anvil is a development node, not a production client. Its default accounts, mnemonic, and private keys are public and must only be used locally. Anvil flags and custom RPC methods evolve with Foundry; check anvil --help and the current official RPC reference for the installed version.


1. Start a local node

Confirm the installation:

anvil --version
anvil --help

Start Anvil:

anvil

By default, Anvil:

  • Listens on 127.0.0.1:8545
  • Generates 10 development accounts
  • Funds every account with 10,000 ETH
  • Uses chain ID 31337
  • Mines a block immediately for every valid submitted transaction
  • Prints accounts, private keys, mnemonic, and node information

Verify it from another terminal:

cast client --rpc-url http://127.0.0.1:8545
cast chain-id --rpc-url http://127.0.0.1:8545
cast block-number --rpc-url http://127.0.0.1:8545

Press Ctrl + C to stop it. Default state is in memory and disappears on exit; use --state or --dump-state when persistence is required.


2. Accounts, balances, and mnemonics

Generate 20 accounts with 1,000 ETH each:

anvil --accounts 20 --balance 1000

Use a mnemonic for deterministic addresses:

anvil --mnemonic "your twelve or twenty four word test mnemonic"

Generate a random mnemonic:

anvil --mnemonic-random

Common account flags include:

FlagPurpose
--accounts <NUM>Number of development accounts
--balance <NUM>Initial ETH balance of each account
--mnemonic <WORDS>Use a specific BIP-39 mnemonic
--mnemonic-random [WORDS]Generate a random mnemonic
--mnemonic-seed-unsafe <SEED>Deterministically derive a mnemonic from an unsafe test seed
--derivation-path <PATH>Set the HD wallet derivation path
--config-out <FILE>Write startup and account configuration as JSON

Generate machine-readable startup configuration:

anvil --silent --config-out ./tmp/anvil-config.json

The output can contain sensitive test-account material. Even for local development, do not commit it publicly or mix it with production configuration.

Anvil's default mnemonic is fixed and publicly known. Never send mainnet assets to these accounts or use them for airdrop eligibility, real signatures, or access control.


3. Host, port, and browser access

Change the port:

anvil --port 9545

Listening only on the local machine is the safer default:

anvil --host 127.0.0.1 --port 8545

Docker, WSL, or LAN integration may require all interfaces:

anvil --host 0.0.0.0 --port 8545

0.0.0.0 exposes the node to every device that can reach the port. Because Anvil offers state-editing and account-impersonation RPC methods, never expose it directly to the public internet. Restrict access with firewalls, container networks, or a secured reverse proxy.

Allow a browser frontend origin:

anvil --allow-origin http://localhost:3000

Related server flags are:

FlagPurpose
--host <IP>RPC listening address
--port <PORT>HTTP/WebSocket RPC port
--allow-origin <ORIGIN>Allowed CORS Origin
--no-corsDisable CORS
--no-request-size-limitRemove request-body size limits; consider memory risk
--ipc [PATH]Start IPC where the platform supports it
--silentSuppress startup and RPC logs

4. Chain ID, hardfork, and block environment

Customize chain and initial block values:

anvil \
  --chain-id 31338 \
  --timestamp 1758067200 \
  --gas-limit 30000000 \
  --gas-price 1000000000 \
  --block-base-fee-per-gas 1000000000

Select an EVM hardfork:

anvil --hardfork cancun

Important environment flags include:

FlagPurpose
--chain-id <ID>Set chain ID
--hardfork <NAME>Select London, Shanghai, Cancun, or another EVM ruleset
--timestamp <NUM>Set genesis timestamp
--number <NUM>Set initial block number where supported
--gas-limit <GAS>Set block gas limit
--disable-block-gas-limitDisable the call gas versus block gas constraint
--code-size-limit <BYTES>Change the EIP-170 runtime code-size limit
--disable-code-size-limitDisable the code-size limit for testing only
--gas-price <WEI>Set gas price
--block-base-fee-per-gas <WEI>Set block base fee
--disable-min-priority-feeDisable minimum priority-fee enforcement

The Solidity compiler's evm_version must be compatible with Anvil's hardfork. A contract compiled with a newer opcode can fail to deploy or execute on an older hardfork. Do not disable code-size limits by default merely to pass a test; the production chain still enforces its own rules.


5. Four mining modes

Instant mining

The default mines a block for each transaction:

anvil

This gives the fastest feedback for normal contract development, scripts, and frontend integration.

Interval mining

Mine every five seconds:

anvil --block-time 5

Several transactions can enter one block, which better models pending UI, confirmations, batches, and same-block ordering.

Manual mining

Disable automatic mining:

anvil --no-mining

Submitted transactions remain pending. Mine one block manually:

cast rpc evm_mine

Mine several blocks:

cast rpc anvil_mine 0x5

This mode provides exact ordering control and supports pending and replacement-transaction tests.

Mixed mining

anvil --block-time 10 --mixed-mining

Mixed mode combines interval mining with immediate behavior in selected cases. Its exact semantics can change, so check anvil --help for the installed version.

Control transaction ordering with --order:

anvil --no-mining --order fees
anvil --no-mining --order fifo

fees approximates fee priority; fifo creates deterministic arrival-order tests. Neither reproduces every builder, MEV, or private-order-flow policy on a live network.


6. Use Anvil with Forge, Cast, and a frontend

Set a shared RPC environment variable:

export ETH_RPC_URL=http://127.0.0.1:8545

Query with Cast:

cast chain-id
cast block-number
cast balance 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --ether

Deploy a Forge script:

forge script script/Deploy.s.sol:Deploy \
  --rpc-url "$ETH_RPC_URL" \
  --broadcast \
  --private-key "$ANVIL_TEST_PRIVATE_KEY"

The key must belong to a local Anvil test account. Use an encrypted keystore or hardware wallet on public networks.

A frontend wallet configuration normally uses:

Network name: Anvil Local
RPC URL: http://127.0.0.1:8545
Chain ID: 31337
Currency symbol: ETH

When browser, WSL, Docker, and host run in different network namespaces, 127.0.0.1 can refer to different machines. Configure port mappings and host addresses explicitly instead of disabling security controls blindly.


7. Fork mainnet or another EVM network

Fork the latest state:

anvil --fork-url "$MAINNET_RPC_URL"

Pin a block for reproducibility:

anvil \
  --fork-url "$MAINNET_RPC_URL" \
  --fork-block-number 19000000

The block can also follow the URL:

anvil --fork-url "$MAINNET_RPC_URL@19000000"

Common fork flags include:

FlagPurpose
--fork-url <URL>Upstream JSON-RPC endpoint
--fork-block-number <BLOCK>Pin the fork block
--fork-transaction-hash <HASH>Fork near a transaction for reproduction
--fork-chain-id <ID>Set upstream chain ID or support cached offline startup
--fork-header <HEADER>Add an upstream RPC header
--timeout <MS>Upstream request timeout
--retries <NUM>Retry transient network failures
--fork-retry-backoff <MS>Set retry backoff
--compute-units-per-second <NUM>Configure provider rate budget
--no-rate-limitDisable Anvil's upstream rate limiter
--no-storage-cachingAlways fetch storage from upstream
--cache-path <PATH>Select the RPC cache directory

Pinned forks are useful for:

  • Integration with real tokens, DEXes, oracles, and lending protocols
  • Historical failed-transaction or incident reproduction
  • Governance proposal, proxy upgrade, and permission-migration testing
  • Validation against real pool and oracle state

A fork is a local branch: writes do not change mainnet. Uncached reads still contact the upstream provider and remain subject to rate limits, archive availability, and method support.


8. Account impersonation

Allow automatic impersonation at startup:

anvil --fork-url "$MAINNET_RPC_URL" --auto-impersonate

Or impersonate one account:

cast rpc anvil_impersonateAccount "$WHALE"

Give it local ETH for gas:

BALANCE_HEX=$(cast to-hex 100000000000000000000)
cast rpc anvil_setBalance "$WHALE" "$BALANCE_HEX"

Send an unlocked transaction from the address:

cast send "$TOKEN" \
  "transfer(address,uint256)" "$RECIPIENT" 1000000 \
  --from "$WHALE" \
  --unlocked

Stop impersonation:

cast rpc anvil_stopImpersonatingAccount "$WHALE"

This supports whale-balance integration, admin permission, governance execution, and multisig-call tests. Impersonation proves only that the address could perform the operation in the local fork state; it does not provide its private key or work on a public network.


9. Time, blocks, and automining control

Disable and re-enable automining:

cast rpc evm_setAutomine false
cast rpc evm_setAutomine true

Advance node time and mine:

cast rpc evm_increaseTime 3600
cast rpc evm_mine

Set the next block timestamp:

cast rpc evm_setNextBlockTimestamp 1758067200
cast rpc evm_mine

Set a timestamp interval:

cast rpc anvil_setBlockTimestampInterval 12

Set the next block base fee:

cast rpc anvil_setNextBlockBaseFeePerGas 0x3b9aca00
cast rpc evm_mine

These methods support timelocks, auctions, TWAPs, governance delays, signature expiry, EIP-1559 fee handling, and confirmation tests. After changing time, mine a block so a contract can observe the new block.timestamp.


10. Snapshots, rollback, and persistence

Create an in-memory snapshot:

SNAPSHOT_ID=$(cast rpc evm_snapshot)

Run test transactions and revert:

cast rpc evm_revert "$SNAPSHOT_ID"

Snapshot IDs are normally single-use. Create a new snapshot after reverting when the baseline must be reused.

Load on startup and save on exit with one file:

anvil --state ./tmp/anvil-state.json

Control load and dump separately:

anvil --load-state ./fixtures/base-state.json
anvil --dump-state ./tmp/final-state.json

Save periodically:

anvil \
  --state ./tmp/anvil-state.json \
  --state-interval 30

Dump and load while running through RPC:

STATE=$(cast rpc anvil_dumpState)
cast rpc anvil_loadState "$STATE"

Persistence can reuse predeployed contracts in E2E tests, prepare repeatable demos, and preserve expensive protocol initialization. State files can be large and may contain test-account and application data; review them before committing.


11. Edit accounts, code, and storage directly

Set an ETH balance:

cast rpc anvil_setBalance "$USER" 0x56bc75e2d63100000

Set an account nonce:

cast rpc anvil_setNonce "$USER" 0x10

Write runtime bytecode to an address:

cast rpc anvil_setCode "$TARGET" "$RUNTIME_BYTECODE"

Modify a storage slot:

cast rpc anvil_setStorageAt "$CONTRACT" 0x0 "$VALUE_BYTES32"

Use Forge storage layout and compute mapping slots before editing:

forge inspect src/Token.sol:Token storage-layout
cast index address "$USER" 0

Direct state editing is useful for otherwise unreachable boundary conditions, upgrade migration tests, and incident reconstruction. It bypasses permissions, events, and invariants, so it is test setup—not proof that a real application flow is correct.


12. Transaction pool and replacement transactions

Run manual mining to inspect pending transactions:

anvil --no-mining --order fees

Inspect the pool:

cast tx-pool status
cast tx-pool inspect
cast tx-pool content
cast tx-pool content-from "$USER"

Remove a transaction from the pool:

cast rpc anvil_dropTransaction "$TX_HASH"

Applications include:

  • Same-nonce replacement with different gas prices
  • Wallet pending, cancel, and speed-up interfaces
  • Concurrent nonces from multiple accounts
  • Transaction selection under a block gas limit
  • Comparing fee-priority and FIFO execution

Anvil's pool is designed for deterministic development and cannot reproduce every private policy of a live client or block builder.


13. Tracing and debugging

Enable geth-style step tracing:

anvil --steps-tracing

Print more execution traces:

anvil --print-traces

Query a transaction trace:

cast rpc debug_traceTransaction "$TX_HASH" '{}'
cast run "$TX_HASH" --rpc-url http://127.0.0.1:8545

Related flags include:

FlagPurpose
--steps-tracingRecord opcode steps for geth-style debug calls
--print-tracesPrint transaction execution traces in the node terminal
--disable-console-logDisable special Solidity/Hardhat console handling
-v / -vv...Increase node log verbosity
--memory-limit <BYTES>Limit EVM execution memory against pathological requests

Tracing increases CPU, memory, and log volume. Keep the normal configuration light and enable detailed tracing only for revert, delegatecall, gas, or storage investigation.


14. Reset a fork and prepare a test baseline

Restore the current fork's initial state:

cast rpc anvil_reset

anvil_reset can also accept a new fork configuration at runtime. Because its JSON shape can change, consult the installed RPC reference and use cast rpc --raw with the exact parameter array.

A common E2E strategy is:

Start a pinned-block fork
  → deploy local implementations and fixtures
  → create evm_snapshot
  → execute one test case
  → evm_revert to baseline
  → create a fresh snapshot for the next case

This is faster than restarting the node per case and more reliable than accumulating shared state across cases. Parallel suites should use separate ports or separate Anvil processes.


15. Genesis, custom chains, and protocol modes

Start from a genesis file:

anvil --init ./genesis.json

This can configure preallocated accounts, initial code, balances, and chain environment. The genesis schema must match what the installed Anvil version supports.

Anvil also offers chain-specific semantic modes such as:

anvil --optimism

Some releases may expose Celo, Tempo, or other network options. These modes adjust relevant transaction and EVM semantics; they do not create a complete production network. Check version help and perform final acceptance on the target chain's real testnet.

Anvil's default deterministic CREATE2 deployer supports identical-address tests across environments. To model a chain without it, inspect and use --disable-default-create2-deployer.


16. Complete Anvil CLI flag map

Anvil is primarily controlled with startup flags and JSON-RPC methods instead of many CLI subcommands. Its top-level subcommands normally include completions, generate-fig-spec, and help.

General and account flags

FlagUse case
--accountsSet development account count
--balanceSet initial ETH per account
--mnemonicProduce stable repeatable addresses
--mnemonic-randomGenerate fresh test accounts
--mnemonic-seed-unsafeDerive deterministic accounts from a test seed
--derivation-pathMatch a specific HD wallet path
--config-outWrite account and node configuration as JSON
--silentReduce logs in automation
--prune-historyLimit historical state held in memory
--transaction-block-keeperControl retained blocks containing transactions
--max-persisted-statesLimit persisted states where supported

Mining and pool flags

FlagUse case
--block-timeMine on a fixed interval
--no-miningRequire manual mining
--mixed-miningCombine interval and instant mining
`--order feesfifo`
--slots-in-an-epochChange slots per epoch for specialized simulation
--disable-pool-balance-checksAdmit insufficient-balance transactions for edge tests

State and server flags

FlagUse case
--stateLoad at startup and save to the same file on exit
--load-stateInitialize from a state file
--dump-stateExport state on exit
--state-intervalSave state periodically
--preserve-historical-statesRetain additional historical states where supported
--initInitialize from genesis.json
--host / --portConfigure listening address and port
--allow-origin / --no-corsControl browser cross-origin access
--ipcEnable IPC transport

Fork and cache flags

FlagUse case
--fork-urlFork a remote EVM network
--fork-block-numberPin a reproducible block
--fork-transaction-hashTarget a transaction-reproduction point
--fork-chain-idExplicitly set fork chain ID
--fork-headerSend upstream RPC headers
--timeout / --retriesHandle unstable RPC endpoints
--fork-retry-backoffConfigure retry delay
--compute-units-per-secondMatch provider rate quota
--no-rate-limitDisable upstream request throttling
--no-storage-cachingAlways retrieve storage upstream
--cache-pathSelect fork cache location

EVM and safety-boundary flags

FlagUse case
--hardforkSelect an EVM ruleset
--chain-idSet a custom chain ID
--gas-limit / --gas-priceModel block gas and fees
--block-base-fee-per-gasSet EIP-1559 base fee
--code-size-limitTest another code-size limit
--disable-block-gas-limitDisable block gas constraints
--disable-code-size-limitDisable EIP-170
--auto-impersonateUnlock arbitrary addresses in a fork
--steps-tracing / --print-tracesCapture debugging traces
--disable-default-create2-deployerRemove the default CREATE2 deployer
--memory-limitLimit EVM execution memory
--optimismEnable OP-style chain semantics

17. Common Anvil custom RPC method map

Method names and parameters may change between releases. Check the official RPC reference before invoking them with cast rpc <METHOD> ....

Mining and time

RPC methodPurpose
evm_mine / anvil_mineMine one or several blocks
evm_setAutomineEnable or disable automatic mining
anvil_setIntervalMiningChange interval mining dynamically
evm_increaseTimeAdvance node time
evm_setNextBlockTimestampSet the next block timestamp
anvil_setBlockTimestampIntervalSet timestamp increments across blocks
anvil_removeBlockTimestampIntervalRemove timestamp interval behavior
anvil_setNextBlockBaseFeePerGasSet the next block's base fee

Snapshots, forks, and state

RPC methodPurpose
evm_snapshot / evm_revertCreate and restore an in-memory snapshot
anvil_resetReset or replace fork configuration
anvil_dumpState / anvil_loadStateExport or merge-load node state
anvil_nodeInfoQuery Anvil node and fork information

Accounts and EVM state

RPC methodPurpose
anvil_impersonateAccountImpersonate an address
anvil_stopImpersonatingAccountStop impersonating an address
anvil_autoImpersonateAccountToggle automatic impersonation dynamically
anvil_setBalanceSet an account's ETH balance
anvil_setNonceSet an account nonce
anvil_setCodeSet runtime bytecode at an address
anvil_setStorageAtEdit a contract storage slot
anvil_setChainIdChange chain ID where supported
anvil_setCoinbaseSet the coinbase address

Transaction pool and debugging

RPC methodPurpose
anvil_dropTransactionRemove a pending transaction
txpool_status / txpool_content / txpool_inspectInspect the pool
debug_traceTransactionReturn an opcode-level debug trace
trace_transactionReturn a call-level transaction trace

18. Common Solidity development recipes

Frontend and contract integration

anvil --chain-id 31337 --block-time 2

Point the frontend at http://127.0.0.1:8545 and use the same chain ID in deployment scripts. Pin a test mnemonic only when stable addresses are needed; never reuse a production mnemonic.

Reproduce historical protocol state

anvil \
  --fork-url "$MAINNET_RPC_URL" \
  --fork-block-number 19000000 \
  --auto-impersonate

Record the block, Foundry version, and RPC type so another developer can reproduce the result.

Test a timelock

cast send "$TIMELOCK" "schedule(bytes32)" "$OPERATION" \
  --private-key "$ANVIL_TEST_PRIVATE_KEY"
cast rpc evm_increaseTime 172800
cast rpc evm_mine
cast send "$TIMELOCK" "execute(bytes32)" "$OPERATION" \
  --private-key "$ANVIL_TEST_PRIVATE_KEY"

Test transaction replacement

anvil --no-mining --order fees

Send transactions with the same account and nonce but different fees, mine manually, and verify how wallet and backend code handle the replaced hash.

Reuse a complex E2E environment

anvil --state ./tmp/e2e-state.json --state-interval 30

Run deployment and seed scripts on first startup; restore the file later. Record the generation scripts and versions whenever a fixture changes so an opaque state blob is not the only source of truth.


19. Troubleshooting

SymptomLikely causeFix
Port 8545 is in useAnother Anvil or development node is runningStop it or use --port 9545
Contracts disappear after restartDefault state is memory-onlyUse --state or rerun deployment scripts
Historical fork query failsUpstream is not an archive RPCUse an RPC that retains the target block state
Fork is slow or returns 429Provider throttling or cold cachePin a block, retain cache, and tune rate/retry settings
Impersonated transaction lacks fundsThe address has no local gas balanceUse anvil_setBalance
Contract still sees old timeNo block was mined after time changeCall evm_mine
Transactions remain pending--no-mining is activeMine manually or re-enable automining
Browser cannot connectHost, port, CORS, or network namespace mismatchCheck binding, mapping, and Origin
Deployment hits invalid opcodeCompiler EVM target is newer than Anvil hardforkAlign evm_version and --hardfork
Custom RPC returns method not foundFoundry version or method name differsUpdate Foundry and inspect the current RPC reference

20. Security and reproducibility checklist

  1. Use default mnemonic and keys only locally
  2. Never bind Anvil directly to the public internet
  3. Keep API keys embedded in fork URLs out of logs and Git
  4. Pin blocks for important forks
  5. Align Solidity evm_version with the Anvil hardfork
  6. Record chain ID, Foundry version, startup flags, and seed scripts
  7. Before broadcasting, confirm the RPC is local Anvil rather than a public network
  8. Do not treat impersonation or direct state editing as a substitute for real authorization tests
  9. Give parallel jobs separate ports and state files
  10. Make state fixtures reproducible from scripts

A small but effective guard is:

cast chain-id --rpc-url "$ETH_RPC_URL"
cast client --rpc-url "$ETH_RPC_URL"

Before using a public Anvil test key, verify that these commands identify the intended local node and chain ID.


Summary

Anvil provides a programmable local EVM environment for Solidity development:

  1. Use default instant mining for fast development and deployment
  2. Use --block-time, --no-mining, and --order for realistic transaction lifecycles
  3. Use --fork-url with a pinned block to reproduce protocol state
  4. Use impersonation, time control, and state editing for complex boundaries
  5. Use snapshots and state dump/load for fast reproducible E2E baselines
  6. Use transaction-pool and tracing methods for nonce, ordering, and internal-call investigation
  7. Use hardfork, gas, and code-size flags to test different EVM environments

The critical boundary is that Anvil can bypass signatures, permissions, and organic state transitions. That makes it excellent for constructing test environments but insufficient by itself to prove production safety. Complete final acceptance on the target testnet with real network rules and secure signing.

References