Skip to main content

RPC methods

Although the majority of RPC methods follow the same behavior as in Ethereum, some methods might produce a different result, or add more information, when used on an Arbitrum chain. This page covers the differences in response body fields you'll find when calling RPC methods on an Arbitrum chain vs on Ethereum.

info

Comprehensive documentation on all generally available JSON-RPC methods for Ethereum can be found at ethereum.org. As Arbitrum has go-ethereum at its core, most of the documented methods there can be used with no modifications.

Transactions

When calling eth_getTransactionByHash and other methods that return a transaction, Arbitrum includes a few additional fields and leverages some existing fields in different ways than Ethereum.

Transaction types

In addition to the three transaction types currently supported on Ethereum, Arbitrum adds additional types listed below and documented in full detail here.

On RPC calls that return transactions, the type field will reflect the custom codes where applicable.

Transaction type codeTransaction type nameDescription
100ArbitrumDepositTxTypeUsed to deposit ETH from L1 to L2 via the Arbitrum bridge
101ArbitrumUnsignedTxTypeUsed to call an L2 contract from L1, originated by a user through the Arbitrum bridge
102ArbitrumContractTxTypeUsed to call an L2 contract from L1, originated by a contract through the Arbitrum bridge
104ArbitrumRetryTxTypeUsed to manually redeem a retryable ticket on L2 that failed to execute automatically (usually due to low gas)
105ArbitrumSubmitRetryableTxTypeUsed to submit a retryable ticket via the Arbitrum bridge on L1
106ArbitrumInternalTxTypeInternal transactions created by the ArbOS itself for certain state updates, like the L1 base fee and the block number

Additional fields

On RPC calls that return transactions, the following fields are added to the returned object.

Field nameDescription
requestIdOn L1 to L2 transactions, this field is added to indicate position in the Inbox queue

Existing fields with different behavior

On RPC calls that return transactions, the following fields will have a different content than what's received on Ethereum.

Field nameDescription
fromOn L1 to L2 transactions, this field will contain the aliased version of the L1's msg.sender

Transaction receipts

When calling eth_getTransactionReceipt, Arbitrum includes a few additional fields and leverages some existing fields in different ways than Ethereum.

Additional fields

On RPC calls that return transaction receipts, the following fields are added to the returned object.

Field nameDescription
l1BlockNumberThe L1 block number that would be used for block.number calls. More information in Block numbers and time
gasUsedForL1Amount of gas spent on L1 calldata in units of L2 gas. More information in Gas and fees

Blocks

When calling eth_getBlockByHash and other methods that return a block, Arbitrum includes a few additional fields and leverages some existing fields in different ways than Ethereum.

Additional fields

On RPC calls that return a block, the following fields are added to the returned object.

Field nameDescription
l1BlockNumberAn approximate L1 block number that occurred before this L2 block. More information in Block numbers and time
sendCountThe number of L2 to L1 messages since Nitro genesis
sendRootThe Merkle root of the outbox tree state

Existing fields with different behavior

On RPC calls that return a block, the following fields will have a different content than what's received on Ethereum.

Field nameDescription
extraDataThis field is equivalent to sendRoot
mixHashFirst 8 bytes is equivalent to sendCount, second 8 bytes is equivalent to l1BlockNumber
difficultyFixed at 0x1
gasLimitValue is fixed at 0x4000000000000, but it's important to note that Arbitrum One currently has a 32M gas limit per block. See Chain params for the gas limit of other chains

Other methods that are slightly different

eth_syncing

Calling eth_syncing returns false when the node is fully synced (just like on Ethereum). If the node is still syncing, eth_syncing returns an object with data about the synchronization status. Here, we provide more details.

Understanding messages, batches, and blocks

Nitro nodes receive transactions from their parent chain and the sequencer feed in the form of messages. These messages may contain multiple transactions that are executed by the node, which then produces blocks. Each message produces exactly one block. In most Nitro chains, the message number and the block number are the same. However, Arbitrum One has pre-Nitro (classic) blocks, so for that chain, message 0 produced block 22207818 (blocks prior to that one are 'classic' blocks). Keep in mind that the offset between message and block number is constant in the chain.

On the parent chain, messages appear in batches. The number of messages per batch changes between batches.

Custom eth_syncing fields

info

Note that the exact output for the eth_syncing RPC call of an out-of-sync Nitro node is not considered a stable API. It is still being actively developed and can be modified without notice between versions.

Field nameDescription
batchSeenLast batch number observed on the parent chain
batchProcessedLast batch that was processed on the parent chain. Processing means dividing the batch into messages
messageOfProcessedBatchLast message in the last processed batch
msgCountNumber of messages known/queued by the Nitro node
blockNumLast block created by the Nitro node (up-to-date L2 block the node is synced to)
messageOfLastBlockMessage that was used to produce the block above
broadcasterQueuedMessagesPosIf different than 0, this is expected to be greater than msgCount. This field notes a message that was read from the feed but not processed because earlier messages are still missing
lastL1BlockNumLast block number from the parent chain that Nitro sees. This is used to debug the connection with the parent chain
lastl1BlockHashLast block hash from the parent chain that Nitro sees. This is used to debug the connection with the parent chain
info

Note that if the sync process encounters an error while trying to collect the data above (not expected) this error will be added to the response.

Understanding common scenarios

  • If batchSeen > batchProcessed, some batches have still not been processed
  • If msgCount > messageOfLastBlock, some messages have been processed, but not all relevant blocks have been built (this is usually the longest stage while syncing a new node)
  • If broadcasterQueuedMessagesPos > msgCount, the feed is ahead of the last message known to the node

debug_traceTransaction

  • The Nitro node provides a native tracer for debugging Stylus contracts called stylusTracer, which returns a JSON array with objects containing the metadata for each executed HostIO. HostIOs are calls the WasmVM makes to read and write data in the EVM. With the result of this tracer and the code for the Stylus contract, you have all the data to understand what happened in a Stylus transaction.
info

The cargo-stylus command-line tool uses the stylusTracer to replay transactions locally inside a debugger. More information can be found on How to debug Stylus transactions using Cargo Stylus Replay.

The table below describes each field of the stylusTracer return value.

Field NameDescription
nameName of the execute HostIO.
argsArguments of the HostIO encoded as hex.
outsOutputs of the HostIO encoded as hex.
startInkAmount of Ink before executing the HostIO.
endInkAmount of Ink after executing the HostIO.
addressFor *call HostIOs, the address of the called contract.
stepsFor *call HostIOs, the steps performed by the called contract.

For example, the command below illustrates how to call this tracer for a transaction.

curl -s \
-X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"debug_traceTransaction","params":["<transaction-hash>", {"tracer": "stylusTracer"}],"id":1}' \
<nitro-node-rpc>

The result of this call will be something along the lines of.

{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"args": "0x00000024",
"endInk": 116090000,
"name": "user_entrypoint",
"outs": "0x",
"startInk": 116090000
},
{
"args": "0x",
"endInk": 116057558,
"name": "msg_reentrant",
"outs": "0x00000000",
"startInk": 116065958
},
{
"args": "0x",
"endInk": 115937952,
"name": "read_args",
"outs": "0x6c5283490000000000000000000000003bdff922e18bc03f1cf7b2a8b65a070cbec944f2",
"startInk": 115951512
},
...
]
}