> For the complete documentation index, see [llms.txt](https://docs.rome.builders/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rome.builders/reference/json-rpc.md).

# JSON-RPC Support

Ethereum JSON-RPC methods supported by Rome EVM endpoints, plus Rome-specific behaviors — for Foundry, Hardhat, ethers, viem, and MetaMask.

Rome EVM endpoints speak standard Ethereum JSON-RPC. Foundry, Hardhat, ethers, viem, and MetaMask work against Rome the same way they do on any EVM chain. This page lists what's supported and the few Rome-specific behaviors worth knowing.

## Supported methods

**Core (state & execution):** `eth_chainId`, `eth_blockNumber`, `eth_getBalance`, `eth_getCode`, `eth_getStorageAt`, `eth_getTransactionCount`, `eth_call`, `eth_estimateGas`, `eth_gasPrice`, `eth_maxPriorityFeePerGas`, `eth_feeHistory`.

**Blocks & transactions:** `eth_getBlockByNumber`, `eth_getBlockByHash`, `eth_getBlockReceipts`, `eth_getTransactionByHash`, `eth_getTransactionReceipt`, `eth_sendRawTransaction`, block-by-index/count variants.

**Logs & filters:** `eth_getLogs`, `eth_newFilter`, `eth_newBlockFilter`, `eth_getFilterChanges`, `eth_getFilterLogs`, `eth_uninstallFilter`.

**WebSocket subscriptions:** `eth_subscribe` / `eth_unsubscribe` (`newHeads`, `logs`). See [WebSocket Subscriptions](/developer-guides/websocket-subscriptions.md).

**Net / web3:** `net_version`, `net_listening`, `net_peerCount`, `web3_clientVersion`.

**Small introspection methods:** `rpc_modules` (lists `debug`, `eth`, `net`, `rome`, `rpc`, `txpool`, `web3`), `eth_syncing` (always `false`), `eth_accounts` (always an empty list), `eth_getUncleCountByBlockNumber`, `eth_getUncleCountByBlockHash`, `eth_getUncleByBlockNumberAndIndex` and `eth_getUncleByBlockHashAndIndex` (no uncles, so counts are `0x0` and lookups return `null`), `eth_newPendingTransactionFilter` (accepted, but it never returns hashes because there is no public mempool), and `txpool_status`, which always returns `{"pending":"0x0","queued":"0x0"}` because there is no public mempool.

**Tracing:** `debug_traceRomeTransaction` takes a transaction hash and returns the per-sub-call and per-CPI breakdown for a transaction that bundles several calls into one batch. Ordinary transactions return `null`, as does a hash that is unknown or not indexed yet.

### Not supported

`debug_traceTransaction` / `trace_*` (Ethereum-style transaction tracing; they return `-32601`), `eth_getProof`, `eth_createAccessList`, `eth_blobBaseFee` (no blob transactions), and the `txpool_*` methods other than `txpool_status` (no public mempool). `newPendingTransactions` subscriptions are accepted but never emit.

## Rome extension methods

Beyond standard Ethereum RPC, the proxy exposes `rome_*` methods:

| Method                            | Purpose                                                                                                                                                                                                                     |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rome_emulateTx`                  | Emulate a transaction off-chain (returns the Solana execution result)                                                                                                                                                       |
| `rome_emulateTxWithPayer`         | Emulate against a specific payer                                                                                                                                                                                            |
| `rome_emulateCallAccounts`        | Emulate and return the Solana accounts a call touches                                                                                                                                                                       |
| `rome_emulateRegRollup`           | Emulate a rollup registration                                                                                                                                                                                               |
| `rome_getResources`               | Report proxy resource pool state (payers, holders)                                                                                                                                                                          |
| `rome_mintId`                     | Resolve the SPL mint behind an ERC-20 wrapper                                                                                                                                                                               |
| `rome_buildInfo`                  | Proxy build + on-chain program info                                                                                                                                                                                         |
| `rome_isCompatible`               | Check proxy/program compatibility                                                                                                                                                                                           |
| `rome_solanaTxForEvmTx`           | Get the Solana transaction(s) for an EVM tx hash                                                                                                                                                                            |
| `rome_sendUnsignedTransaction`    | Submit an unsigned transaction (synthetic-sender flows)                                                                                                                                                                     |
| `rome_composeUnsignedAtomicV1`    | Compose one Solana v1 transaction for an unsigned EIP-1559 body authorised by a Solana wallet's Ed25519 signature; the wallet signs it and the app broadcasts it. Refuses when the call does not fit one atomic transaction |
| `rome_composeUnsignedIterativeV1` | Same, but returns every leg (atomic if it fits, else the iterative legs); the wallet signs each and submits them with `rome_submitSignedV1Plan`                                                                             |
| `rome_submitSignedV1Plan`         | Broadcast a signed plan (up to 64 legs); the proxy is transport only, the wallet stays fee payer                                                                                                                            |
| `rome_relayUnsignedV1`            | One wallet signature, the proxy's payer drives the legs; the synthetic pays Rome gas (fund it first with `rome_composeExternalDepositV1`). Returns the EVM tx hash                                                          |
| `rome_composeExternalDepositV1`   | One wallet-signed transaction that credits the synthetic's native gas balance from the wallet's tokens                                                                                                                      |

## Rome-specific behaviors

### Gas is Solana-derived — estimate, don't hardcode

Rome meters execution in Solana compute units, surfaced as EVM gas. Most of what a write costs is creating Solana accounts: a recipient that has never been used, a new token account, a deployed contract. Those accounts are part of the estimate. Practical consequences:

* **Use `eth_estimateGas`, and never hardcode `21000`.** Standard tooling (`forge create`, `cast`, Hardhat, ethers, viem, MetaMask) already calls it and gets a usable value. For calls that touch Solana programs, add a margin (the SDK's `submitRomeTx` pads 1.3x) and set a gas ceiling if the estimate itself reverts. A hardcoded `21000` limit fails whenever the write creates accounts, for example a transfer to an address that has never been used.
* **Rome charges the gas actually used.** In the measurements below the gas used was never more than the estimate, so an estimate that is higher than the work done does not cost you the difference.
* **Leave the margin your tooling adds.** State can change between the estimate and the moment the transaction lands, and the estimate for a call that makes Solana CPIs can come out low. The SDK's `submitRomeTx` pads the estimate by 1.3x as a margin.

Measured on Hadrian, with the gas price at about 10.4 gwei at the time:

| Write                                                  | `eth_estimateGas` | Gas used  |
| ------------------------------------------------------ | ----------------- | --------- |
| Native transfer to a never-used address                | 1,086,961         | 1,086,961 |
| Native transfer to an existing address                 | 21,000            | 10,001    |
| wUSDC transfer to a never-used address                 | 2,544,921         | 2,544,921 |
| Wrap gas into wUSDC (`withdraw_to_ata`)                | 21,000            | 10,001    |
| Wrapper grant (`approve_spl` on the Helper precompile) | 21,000            | 10,001    |
| Deploy a 10-byte contract                              | 1,147,921         | 1,147,921 |

These are single measurements on one chain, not limits. The numbers depend on which accounts a call has to create, so estimate each write instead of copying them.

### `forge script --broadcast` needs `--skip-simulation`

`forge script` sets its broadcast gas limit from a **local** simulation, which under-provisions against Rome's gas model. Add `--skip-simulation` so Foundry uses the chain's `eth_estimateGas` instead:

```bash
forge script script/Deploy.s.sol:Deploy \
  --rpc-url <RPC> --private-key $PRIVATE_KEY --broadcast --skip-simulation
```

`forge create`, `cast send`, and Hardhat are unaffected — they already estimate on-chain.

### `eth_getLogs` is range-capped (\~12,000 blocks)

Like Infura, Alchemy, and other production RPCs, `eth_getLogs` rejects overly wide block ranges (error `-32005`). Bound your queries:

```javascript
const latest = await provider.getBlockNumber();
const logs = await contract.queryFilter(filter, latest - 5000, latest);
```

A `queryFilter` with no range scans all history and will exceed the cap — pass an explicit `fromBlock`/`toBlock`. Receipt-based event assertions (e.g. waiting on a tx and reading its logs) are unaffected.

### Fees

`eth_gasPrice` returns the real, oracle-derived price; wallets (including MetaMask) use it and display correct fees. Submitted fee fields are accepted permissively — both legacy and EIP-1559 transactions land with standard tooling defaults.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.rome.builders/reference/json-rpc.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
