RPC reference
Standard eth_* methods behave as a node does. These are the additions, and the few places a fork has to answer differently.
Cheatcodes
The ones Foundry and Hardhat already know:
anvil_setBalance anvil_setNonce anvil_setCode anvil_setStorageAt anvil_impersonateAccount anvil_stopImpersonatingAccount anvil_autoImpersonateAccount anvil_mine evm_mine evm_increaseTime evm_snapshot evm_revert
forkstate_setTokenBalance(token, holder, amount)
Sets an ERC-20 balance. No token says where it keeps balances, so the storage slot is searched for; a failed search changes nothing.
forkstate_setPrice(feed, price) · forkstate_resetPrice(feed)
Makes a Chainlink price feed report any price — for liquidations, depegs and crashes. The price is in the feed's units ("1850.25"), or 0x hex for the raw answer. latestRoundData and friends answer with it; updatedAt is always the current block's time, so staleness checks pass. Every other call — decimals(), description() — runs the real feed. forkstate_resetPrice puts it back.
Smart accounts (ERC-4337)
Every testnet is also a bundler, running user operations through the real EntryPoint contracts — v0.6, v0.7 and v0.8 — so account-abstraction wallets and SDKs work unchanged. Point the SDK's bundler URL at the testnet's RPC URL.
| Method | Does |
|---|---|
eth_supportedEntryPoints | The EntryPoints deployed on the parent chain |
eth_sendUserOperation | Simulates, then runs it in its own block; answers the operation hash |
eth_estimateUserOperationGas | Limits that will be enough — generous, since gas on a testnet is free |
eth_getUserOperationReceipt | Success, gas paid, its logs and the transaction receipt |
eth_getUserOperationByHash | The operation, read back from the bundle that carried it |
An operation the EntryPoint would reject is refused before anything is mined, with its reason as the message (AA24 signature error) and ERC-7769's error codes.
eth_call with state overrides
Geth's third parameter: pretend some state is true for this one call.
[{ "to": "0x…", "data": "0x…" }, "latest", {
"0xToken": { "stateDiff": { "0x<slot>": "0x<32-byte value>" } },
"0xYou": { "balance": "0x56BC75E2D63100000" }
}]balance, nonce, code and stateDiff are honoured. state — “this storage and every other slot zero” — is refused, because a fork cannot list the slots it would have to blank.
Receipts say why a transaction failed
A failed receipt carries revertReason — the contract's message, or a Solidity panic by name — and revertData, the raw bytes for decoding a custom error with its ABI.
Past blocks
| Asked about | Answered by |
|---|---|
| latest, pending, or the newest block's number | the testnet |
| a block at or before the fork | the parent chain, exactly as it was then |
| a past block mined on the testnet | the testnet's state as it was when that block was mined — for the last 1,024 blocks |
eth_getLogs ranges that start before the fork include the parent's logs, and ablockHash filter returns only that block.
About a testnet
| Method | Answers |
|---|---|
forkstate_info | Chain id, fork block, size, whether it follows the parent's head |
forkstate_usage | Requests, cold reads and forwarded calls per day (takes a number of days) |
forkstate_contracts | Addresses this testnet has deployed code to |
forkstate_sync | Move a testnet that follows its parent to the parent's latest block |
forkstate_setChainId | Change the chain id; signatures must follow it |
Refused
eth_getProof— the parent's proof would claim your testnet's writes do not exist.eth_sign,eth_signTransaction— no key is ever held; sign in your wallet and send the raw transaction.