Skip to content

State methods

Willow RPC serves account state on all seven chains. State is read from a provider’s EIP-1186 proof and verified against the state root of a block that Willow verified, before it is returned. On Ethereum, eth_call is executed by Willow over state verified in the same way. Methods whose results no block commits to, such as sending a transaction or estimating gas, are forwarded to a provider and returned as the provider answers them.

State methods are set per plan. Of the self-serve plans, Pay as you go, Builder, and Scale include them, and Free does not. A custom plan includes them only if its agreement does. A key on a plan that does not include state methods receives -32601 for every state method, including the forwarded methods, so a router sends the request to another provider. /v1/prices reports each plan’s state_methods. See Plans.

MethodChainsHow it is answeredUnits
eth_getBalance, eth_getTransactionCount, eth_getCode, eth_getStorageAt, eth_getProofAll sevenVerified against the block’s state root5
eth_callEthereumExecuted by Willow over verified state25
eth_sendRawTransaction, eth_estimateGas, eth_gasPrice, eth_maxPriorityFeePerGas, eth_feeHistory, eth_blobBaseFeeAll sevenForwarded to a provider, not verified3

A request that requires more than its listed units’ worth of provider requests costs 3 units per provider request instead. See Units.

eth_call on the other six chains returns -32601, as do state overrides on any chain. See eth_call.

On Robinhood Chain, reads are refused with -32000 while Willow does not receive the chain’s sequencer feed (see How Willow verifies data). The forwarded methods are served.

Willow requests the account, and any storage slots, as an eth_getProof response from a provider. It verifies the account proof and each storage proof against the state root in the header of the requested block, and verifies the returned code against the account’s code hash. A provider whose proof does not verify is not used, and the next provider is asked. If no provider returns a proof that verifies, the request is refused with -32000, so a router can send it to another provider.

The header is one Willow verified before serving it:

  • On Ethereum, state is read only at blocks the light client (Helios) has confirmed. See Blocks.
  • On the other six chains, state is read at blocks the sequencer signed, the same blocks Willow serves. See How Willow verifies data.

A value that does not exist is proven absent: the balance, nonce, and storage of an account with no entry in the state are returned as 0x0, and its code as 0x.

The block parameter accepts a hexadecimal number, a tag (latest, pending, earliest, finalized, or safe), a block hash, or an EIP-1898 object ({"blockHash": …} or {"blockNumber": …}). An omitted block parameter means latest. finalized and safe are served and refused as for the other methods (see finalized and safe), so safe is refused on Ethereum, Arbitrum One, and Robinhood Chain.

  • latest and pending on Ethereum refer to the newest block the light client has confirmed, which can be behind the newest block that eth_blockNumber returns. If that block is more than 180 seconds old, the request is refused with -32000 instead of being answered from an old block.
  • A block number on Ethereum later than the newest confirmed block is refused with -32000 (not yet confirmed by the light client).
  • On the other six chains, latest and pending refer to the newest block Willow holds, under the same freshness rule as the other methods.
  • Older blocks are answered when a provider holds their state. Willow asks archive providers for older blocks; a block whose state no provider returns is refused with -32000. On the six chains other than Ethereum, a block older than those Willow holds is refused as described in History.

eth_getTransactionCount with pending returns the provider’s pending nonce, which includes transactions in the provider’s mempool and therefore cannot be proven. Willow bounds it by the proven nonce at the newest confirmed block: the result is never below the proven nonce and never more than 64 above it.

eth_getBalance, eth_getTransactionCount, eth_getCode, and eth_getStorageAt return the same values as a node. eth_getProof returns the verified proof in the standard form (address, balance, codeHash, nonce, storageHash, accountProof, and storageProof), with at most 256 storage keys per request.

Request:

Terminal window
curl -s https://api.willow.tech/v1/rpc/1/{YOUR_KEY} \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getBalance","params":["0x00000000219ab540356cbb839cbe05303d7705fa","latest"]}'

Response:

{"id":1,"jsonrpc":"2.0","result":"0x…"}

eth_call is served on Ethereum. Willow executes the call in its own EVM at the requested block. Every account, storage slot, and contract code the call reads is proven against the block’s state root before the call returns. A provider’s access list is used only to request the likely state in advance; state it omits is requested when the execution reaches it, and is verified in the same way.

The call object accepts the standard fields: from, to, gas, gasPrice, maxFeePerGas, maxPriorityFeePerGas, value, data (or input), accessList, and chainId.

ResultCodeMessage
Returnedresult holds the return data.
Reverted3execution reverted, with the decoded reason when the data is an Error(string) or Panic(uint256). error.data holds the revert data.
Halted-32000out of gas, or VM execution error: followed by the reason.

These results are final: another provider executing the same call at the same block returns the same result, so a router should return them to the client rather than fall back.

  • State per call. A call may read at most 256 accounts and 8,192 storage slots. A call that reads more is refused with -32000 (the call reads more state than one call may).
  • Time. A request is answered within 20 seconds. A call whose state cannot be proven within that time is refused with -32000 (proving the state it reads took longer than this request may).
  • Overrides. State overrides and block overrides (the third and fourth parameters) are refused with -32601 (eth_call with state or block overrides is not available here), since the result would not describe the block’s state.
  • Blobs and authorizations. A call object with blobVersionedHashes or an authorizationList (EIP-7702) is refused with -32000.

eth_sendRawTransaction, eth_estimateGas, eth_gasPrice, eth_maxPriorityFeePerGas, eth_feeHistory, and eth_blobBaseFee are sent to a provider, and the provider’s answer is returned unchanged, including its errors. No block commits to these values, so they are not verified.

eth_sendRawTransaction returns the hash of the submitted transaction as computed from its bytes, not as reported by the provider. If a provider reports the transaction as already known, the transaction is treated as sent.

Each chain has separate capacity for reads, eth_call, sent transactions, and the other forwarded methods:

LaneAt once per chainAt once per key
Reads (eth_getBalance … eth_getProof)6416
eth_call84
eth_sendRawTransaction164
Other forwarded methods6416

A key’s requests beyond its share wait their turn. When the lane itself is full, a request waits up to 2 seconds and is then refused with -32000 (this server is busy, try again in a moment), so a router can send it to another provider.

Each kind of state method has a flat price in units, regardless of the size of the response. A request that required more provider requests than its price covers costs 3 units per provider request instead.

KindUnits
Forwarded method3
Read5
eth_call25
  • Billed: a result, a revert, a halted call, and an error returned by a provider for a forwarded method.
  • Billed per provider request (3 units each): a call refused because it reads too much state or ran out of time, since the provider requests were made.
  • Not billed: a refusal because the server is busy, because no provider returned a proof that verifies, or because the request was invalid.
CodeMeaningRemedy
3The call reverted. error.data holds the revert data.Return to the client. Do not fall back.
-32000, message without “not found”The call halted (out of gas, VM execution error: …).Return to the client. Do not fall back.
-32000, message with “not found”The block is not yet confirmed or is too old, no provider returned a proof that verifies, the call reads too much state or ran out of time, or the server is busy.Fall back to another provider.
-32601eth_call on a chain other than Ethereum, eth_call with overrides, or a key on a plan that does not include state methods.Send to another provider.
-32602A malformed address, slot, or call object, or more than 256 keys in eth_getProof.Correct the request.
Provider’s codeAn error returned by the provider for a forwarded method, such as a rejected transaction.Handle as the provider’s error.

Examples:

{"error":{"code":-32000,"message":"not found in this store: block 23650010 is not yet confirmed by the light client"},"id":1,"jsonrpc":"2.0"}
{"error":{"code":-32000,"message":"not found in this store: state reads: this server is busy, try again in a moment"},"id":2,"jsonrpc":"2.0"}
{"error":{"code":-32601,"message":"eth_call with state or block overrides is not available here"},"id":3,"jsonrpc":"2.0"}