# Home

The official documentation for MegaETH — the first real-time blockchain.

Welcome to the MegaETH documentation. MegaETH is a high-performance Ethereum L2 with \~10ms block times and real-time transaction processing.

## Get Started

<table data-view="cards"><thead><tr><th></th><th></th><th data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>User Guide</strong></td><td>Connect your wallet, get testnet tokens, and start using MegaETH.</td><td><a href="/pages/dt6H9BO2KFE8gOJFKG7I">/pages/dt6H9BO2KFE8gOJFKG7I</a></td></tr><tr><td><strong>Developer Docs</strong></td><td>Build dApps on MegaETH — EVM differences, gas model, RPC reference.</td><td><a href="/pages/1B4XsWbSpJqPqBEwjoV8">/pages/1B4XsWbSpJqPqBEwjoV8</a></td></tr><tr><td><strong>Specification</strong></td><td>Formal protocol spec — EVM behavior, gas model, system contracts, and upgrade history.</td><td><a href="https://docs.megaeth.com/spec/">https://docs.megaeth.com/spec/</a></td></tr></tbody></table>

## Learn How MegaETH Works

* [Architecture](/architecture) — how transactions flow from submission through execution, streaming, and L1 settlement.
* [Mini-Blocks](/mini-block) — the two block types and why MegaETH redesigned the block format for real-time performance.


# Architecture

MegaETH network architecture — how transactions flow from submission through execution, streaming, and L1 settlement.

MegaETH is an Ethereum L2 built on the [OP Stack](https://docs.optimism.io/stack/getting-started), optimized for real-time execution. The sequencer produces [mini-blocks](/mini-block) every \~10 milliseconds and [EVM blocks](/mini-block) every \~1 second, streaming state to globally distributed RPC nodes so that users and applications see transaction results within milliseconds.

## How a Transaction Moves Through MegaETH

Like all blockchains, MegaETH processes transactions and maintains a shared ledger. What makes it different is *speed*: a transaction is confirmed in roughly 10 milliseconds — not seconds or minutes. The rest of this page walks through exactly how that happens, from submission to final settlement on Ethereum L1.

```mermaid
sequenceDiagram
    participant User
    participant RPC as RPC Endpoint
    participant Seq as Sequencer
    participant Nodes as RPC Nodes
    participant L1 as Ethereum L1

    User->>RPC: Submit transaction
    RPC->>Seq: Forward to sequencer
    Seq->>Seq: Execute (~10ms)
    Seq-->>Nodes: Stream mini-block (receipts, logs, state)
    Nodes-->>User: Transaction confirmed
    Note over Seq,L1: Periodically
    Seq->>L1: Batch and submit block data (via EigenDA)
    L1->>L1: Finalize via dispute resolution
```

### 1. Submission

A user's transaction — a swap, a transfer, a contract call — arrives at an RPC endpoint. The endpoint validates it (correct format, valid signature, sufficient balance) and forwards it to the [sequencer](https://docs.optimism.io/connect/resources/glossary#sequencer), the single node responsible for ordering and executing transactions.

### 2. Execution

The sequencer executes the transaction against the current chain state. Every \~10 milliseconds, it seals the recently executed transactions into a [mini-block](/mini-block) — a lightweight block containing the transactions, their execution results (receipts), and the resulting state changes.

### 3. Streaming

The sequencer streams each mini-block to RPC nodes distributed across multiple regions. As soon as an RPC node receives a mini-block, its contents — transaction receipts, event logs, and state updates — become immediately queryable. This is how a wallet can show a confirmed transaction within milliseconds: the RPC node it connects to has already received the mini-block containing the result.

Applications that need the lowest possible latency can subscribe to mini-blocks directly via the [Realtime API](/developer-docs/overview-2/realtime-api).

### 4. L1 Settlement

Periodically, the sequencer seals an [EVM block](/mini-block#relationship-to-evm-blocks) — a standard Ethereum-format block that bundles all the mini-blocks produced during that interval. The block data is posted to [EigenDA](https://docs.eigenlayer.xyz/eigenda/overview/) for [data availability](https://docs.optimism.io/connect/resources/glossary#data-availability). EigenDA returns a certificate proving the data is available, and the OP Stack [batcher](https://docs.optimism.io/builders/chain-operators/architecture#batcher) submits that certificate to Ethereum L1. Block proposals can then be challenged through [dispute resolution](https://specs.optimism.io/fault-proof/index.html).

This is what gives MegaETH its security: even though the sequencer processes transactions at sub-second speed, all results are ultimately anchored to Ethereum and can be independently verified.

## Components

### Sequencer

The [sequencer](https://docs.optimism.io/connect/resources/glossary#sequencer) is the block producer — the single node that decides transaction ordering. It executes transactions, assembles them into mini-blocks and EVM blocks, and broadcasts execution results to the rest of the network.

The sequencer is operated with high availability. If the active node goes down, a standby takes over within tens of milliseconds, and software upgrades happen without pausing the chain.

### RPC Nodes

RPC nodes are the network's public interface. They serve read requests (account balances, contract calls, event logs), accept transaction submissions, and maintain a replica of the chain state synced from the sequencer. Depending on how a node maintains state, there are two types:

* **Replica nodes** receive blocks and execution results from the sequencer and apply them to a local replica of the chain's state and history without re-execution. This is the default mode — it is lightweight and optimized for serving read requests at scale.
* **Full nodes** receive blocks and locally re-execute them, independently validating every state transition. Full nodes do not need to trust the sequencer's execution results.

MegaETH operates RPC nodes across multiple geographic regions so that users worldwide connect to a nearby node with low latency. There are two ways to access them (see [Connect to MegaETH](/user-guide/connect) for endpoints):

* **Public RPC endpoint** — available to everyone, rate-limited.
* **Managed RPC providers** — [Alchemy](https://www.alchemy.com/) and others offer higher throughput and debug methods (`debug_*`, `trace_*`).

### Data Availability

When the sequencer produces a block, it must make the block data publicly available so that anyone can verify the chain — this is the [data availability](https://docs.optimism.io/connect/resources/glossary#data-availability) requirement. MegaETH uses [EigenDA](https://www.eigenlayer.xyz/) as the primary data availability layer. Without a DA certificate, the sequencer cannot submit the block to L1. This ensures that even if the sequencer behaves maliciously, replica nodes and provers can always access the data they need.

### Fault Proof

MegaETH settles on Ethereum L1 using the OP Stack's [dispute resolution](https://specs.optimism.io/fault-proof/index.html) framework. Block proposals are submitted to L1 and can be challenged within a dispute window.

For dispute resolution, MegaETH uses **Kailua** — a ZK fraud proof system built on RISC-Zero. Instead of the multi-round interactive bisection used by standard OP Stack, Kailua generates a single zero-knowledge proof to resolve disputes, making challenges faster and cheaper.

### Provers

Provers re-execute blocks and generate cryptographic proofs that attest to the correctness of the sequencer's execution results. These proofs are used in the [fault proof](#fault-proof) process: if a block proposal on L1 is challenged, a prover can produce a proof to resolve the dispute.

## Related Pages

* [Get Started](/user-guide/get-started) — connect your wallet, bridge ETH, and explore the network
* [Connect to MegaETH](/user-guide/connect) — chain IDs, RPC endpoints, and network parameters
* [Mini-Blocks](/mini-block) — the two block types and how they enable sub-second latency
* [Overview](/developer-docs/overview) — developer quickstart with RPC endpoints and chain configuration
* [Realtime API](/developer-docs/overview-2/realtime-api) — subscribe to mini-blocks and get results in real time


# Mini-Blocks

MegaETH mini-blocks — what they are, how they differ from EVM blocks, and what they mean for your application.

MegaETH produces two types of blocks: **Mini-blocks** and **EVM blocks**.

* **Mini-blocks** are produced every \~10 milliseconds. They are MegaETH-specific and designed for sub-second transaction confirmations.
* **EVM blocks** are produced every \~1 second. They are identical to standard Ethereum blocks and compatible with all existing tools, wallets, and indexers.

Every transaction appears in exactly one mini-block and exactly one EVM block. Mini-blocks give you the result faster; EVM blocks give you the standard Ethereum data format.

## Why Mini-Blocks Exist

Handling blocks at 10 millisecond intervals requires significant resources. Software optimizations and powerful hardware give the sequencer ample headroom to produce 100 blocks per second, but pushing the data to other nodes — especially ones with limited connectivity — quickly becomes a bottleneck.

The key issue is that standard EVM block headers take up quite some space — more than 500 bytes per block. At 100 blocks per second, this translates to 1.57 TB of data per year just for the headers, a significant burden for lightweight setups.

Beyond the resource overhead, the standard EVM block header is designed for chains whose block times are seconds or higher, as well as light clients who use block headers as the sole root of trust. Timestamps have one-second resolution, and the multiple Merkle roots optimize for succinctness of Merkle proofs rather than compactness of the headers.

Interacting with a chain in realtime — at tens of milliseconds of latency — calls for a different paradigm. Mini-blocks redesign the block format for compactness and low latency: compact headers, microsecond-resolution timestamps, and only the data needed for real-time streaming.

## What This Means in Practice

For most users and developers, mini-blocks are invisible — your wallet, your toolchain, and your contracts all work with standard EVM blocks as they would on any other chain. No code changes are needed.

Where mini-blocks matter is latency. A transaction is confirmed in \~10 milliseconds, not 1 second. Wallets and applications that subscribe to mini-blocks via the [Realtime API](/developer-docs/overview-2/realtime-api) can show results almost instantly — useful for trading, gaming, real-time feeds, and anything where milliseconds count.

## How Mini-Blocks Work

The sequencer executes transactions continuously. Every \~10ms, it seals the executed transactions into a mini-block and streams the results — receipts, state changes, event logs — to RPC nodes across the network. RPC nodes make these results available to applications immediately, before the EVM block is sealed.

Every \~1 second, the sequencer seals an EVM block containing all the mini-blocks produced during that interval. The EVM block includes a standard Ethereum block header with Merkle roots, bloom filters, and all the fields that Ethereum tooling expects.

```
Time ──────────────────────────────────────────────────────────►
│ mini-block 0 │ mini-block 1 │ ... │ mini-block ~99 │
└──────────────────────── EVM block N ──────────────────────────┘
```

## Properties of Mini-Blocks

Mini-blocks share the core properties you would expect from any block:

* **Ordered.** Mini-blocks are totally ordered by height, starting from 0 at genesis.
* **Complete.** Every transaction processed by the sequencer appears in exactly one mini-block.
* **Preconfirmed.** A transaction included in a mini-block carries the same preconfirmation guarantee as one included in an EVM block — the sequencer has committed to its ordering and result, and [signs every mini-block header](#sequencer-signatures) to make that commitment verifiable.

Where they differ from EVM blocks:

| Property                       | EVM Block    | Mini-Block                                                                                                         |
| ------------------------------ | ------------ | ------------------------------------------------------------------------------------------------------------------ |
| Production interval            | \~1 second   | \~10 milliseconds                                                                                                  |
| Header size                    | \~500+ bytes | Compact (no state root, no bloom filter)                                                                           |
| Timestamp resolution           | 1 second     | Microsecond (via [High-Precision Timestamp](/developer-docs/overview-3/system-contracts#high-precision-timestamp)) |
| Compatible with standard tools | Yes          | Requires [Realtime API](/developer-docs/overview-2/realtime-api)                                                   |
| Contains state root            | Yes          | No                                                                                                                 |

## Sequencer signatures

The preconfirmation guarantee is not just a promise — it is cryptographically enforced. The sequencer signs every mini-block header with its sequencer key, and the signature is delivered alongside the mini-block in the [Realtime API](/developer-docs/overview-2/realtime-api) stream. A signed mini-block is a binding commitment: if the sequencer ever sealed an EVM block that contradicts a mini-block it signed, anyone holding the signed header could prove the misbehavior.

The signing key is registered onchain in the [SequencerRegistry](https://docs.megaeth.com/spec/system-contracts/sequencer-registry) system contract at `0x6342000000000000000000000000000000000006`, introduced in Rex5. The key can be rotated by scheduling a change in the registry; rotations take effect at an EVM block boundary, and the full change history remains queryable onchain.

The signature is a standard secp256k1 ECDSA signature over `keccak256(rlp(header))`, where the header is the following eight fields of the [`miniBlocks` subscription payload](/developer-docs/rpc/reference/eth_subscribe#miniblocks), RLP-encoded in this order:

| # | Payload field          | Type         |
| - | ---------------------- | ------------ |
| 1 | `block_number`         | integer      |
| 2 | `block_timestamp`      | integer      |
| 3 | `index`                | integer      |
| 4 | `mini_block_number`    | integer      |
| 5 | `mini_block_timestamp` | integer      |
| 6 | `gas_used`             | integer      |
| 7 | `transaction_root`     | 32-byte hash |
| 8 | `receipt_root`         | 32-byte hash |

Integers are RLP-encoded in their minimal big-endian form. The signature is verifiable onchain with `ecrecover`. The `signature` field of the payload carries the components as an object: `r`, `s`, and `yParity`.

{% hint style="info" %}
Mini-blocks produced before Rex5 are unsigned — the `signature` field is absent from their payloads.
{% endhint %}

### Verifying a mini-block signature

To verify a mini-block, rebuild the header hash, recover the signer from the signature, and compare it against the sequencer key registered onchain.

The example below uses [viem](https://viem.sh) and takes a notification payload `mb` exactly as delivered by the [`miniBlocks` subscription](/developer-docs/rpc/reference/eth_subscribe#miniblocks).

```typescript
import {
  createPublicClient,
  http,
  keccak256,
  toRlp,
  recoverAddress,
  parseAbi,
} from "viem";

const client = createPublicClient({
  transport: http("https://mainnet.megaeth.com/rpc"),
});

// RLP integer form: minimal big-endian bytes; zero is the empty byte string
const int = (hex: `0x${string}`): `0x${string}` => {
  let h = BigInt(hex).toString(16);
  if (h === "0") return "0x";
  return `0x${h.length % 2 ? "0" + h : h}`;
};

// `mb` is a notification payload from the `miniBlocks` subscription
async function isSignedBySequencer(mb: any): Promise<boolean> {
  // 1. Rebuild the signed digest: keccak256(rlp(header))
  const hash = keccak256(
    toRlp([
      int(mb.block_number),
      int(mb.block_timestamp),
      int(mb.index),
      int(mb.mini_block_number),
      int(mb.mini_block_timestamp),
      int(mb.gas_used),
      mb.transaction_root,
      mb.receipt_root,
    ]),
  );
  // 2. Recover the signer from the raw digest (no EIP-191 prefix)
  const signer = await recoverAddress({ hash, signature: mb.signature });
  // 3. Look up the sequencer key that was active for this block
  const sequencer = await client.readContract({
    address: "0x6342000000000000000000000000000000000006",
    abi: parseAbi(["function sequencerAt(uint256) view returns (address)"]),
    functionName: "sequencerAt",
    args: [BigInt(mb.block_number)],
  });
  return signer.toLowerCase() === sequencer.toLowerCase();
}
```

When verifying historical mini-blocks, use `sequencerAt(blockNumber)` rather than `currentSequencer()` — the sequencer key can rotate, and the registry resolves which key was active at any block. `currentSequencer()` is sufficient when verifying live mini-blocks as they stream in.

{% hint style="warning" %}
A valid signature proves the sequencer committed to the mini-block's contents — it does not by itself prove finality. Full finality still depends on the containing EVM block being posted to and finalized on the L1.
{% endhint %}

## Relationship to EVM Blocks

Every mini-block belongs to exactly one EVM block — its transactions never span multiple EVM blocks. The ratio is roughly 1 EVM block to \~100 mini-blocks, but the exact count varies. To get the precise number, use the `miniBlockCount` field in the `newHeads` subscription response:

```json
{
  "number": "0x57f898",
  "miniBlockCount": "0x57"
}
```

## Subscribing to Mini-Blocks

To take advantage of mini-block latency, subscribe over WebSocket using the [Realtime API](/developer-docs/overview-2/realtime-api):

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_subscribe",
  "params": ["miniBlocks"]
}
```

Each notification delivers the mini-block's transactions, receipts, and state changes — everything your application needs to react immediately, without waiting for the next EVM block.

## Related Pages

* [Architecture](/architecture) — how transactions flow through the MegaETH network
* [Realtime API](/developer-docs/overview-2/realtime-api) — subscribe to mini-blocks and get execution results with minimum latency
* [eth\_subscribe](/developer-docs/rpc/reference/eth_subscribe) — full reference of the `miniBlocks` subscription payload
* [High-Precision Timestamp](/developer-docs/overview-3/system-contracts#high-precision-timestamp) — microsecond timestamps available within mini-blocks
* [SequencerRegistry (spec)](https://docs.megaeth.com/spec/system-contracts/sequencer-registry) — onchain registry of the sequencer signing key


# Get Started

Get started with MegaETH — connect your wallet, bridge ETH, and explore the network.

MegaETH is a high-performance Ethereum L2 with real-time transaction processing. Whether you are here to try the testnet or use mainnet, this guide will help you get up and running.

{% stepper %}
{% step %}

### Connect your wallet

In MetaMask, Rabby, or any Ethereum-compatible wallet, go to **Settings → Networks → Add Network** and enter these details:

{% tabs %}
{% tab title="Mainnet" %}

| Field               | Value                                                         |
| ------------------- | ------------------------------------------------------------- |
| **Network Name**    | MegaETH                                                       |
| **RPC URL**         | <code class="expression">space.vars.mainnet\_rpc</code>       |
| **Chain ID**        | <code class="expression">space.vars.mainnet\_chain\_id</code> |
| **Currency Symbol** | ETH                                                           |
| **Block Explorer**  | <code class="expression">space.vars.mainnet\_etherscan</code> |
| {% endtab %}        |                                                               |

{% tab title="Testnet" %}

| Field               | Value                                                         |
| ------------------- | ------------------------------------------------------------- |
| **Network Name**    | MegaETH Testnet                                               |
| **RPC URL**         | <code class="expression">space.vars.testnet\_rpc</code>       |
| **Chain ID**        | <code class="expression">space.vars.testnet\_chain\_id</code> |
| **Currency Symbol** | ETH                                                           |
| **Block Explorer**  | <code class="expression">space.vars.testnet\_etherscan</code> |
| {% endtab %}        |                                                               |
| {% endtabs %}       |                                                               |

Save the network and switch to it. For more details, see [Connect to MegaETH](/user-guide/connect).
{% endstep %}

{% step %}

### Get tokens

{% tabs %}
{% tab title="Mainnet" %}
Bridge ETH or other tokens from Ethereum using the official bridge at [**rabbithole.megaeth.com/bridge**](https://rabbithole.megaeth.com/bridge). Connect your wallet, choose a token and amount, and confirm the transaction. See [Get Funds on Mainnet](/user-guide/bridge) for more options including third-party bridges and fiat onramps.
{% endtab %}

{% tab title="Testnet" %}
Visit the faucet at [testnet.megaeth.com](https://testnet.megaeth.com), enter your wallet address, and complete the verification step. The faucet provides 1 testnet ETH, 100 testnet USDM, and 1,000 testnet MEGA per user every 24 hours. See the [Faucet](/user-guide/faucet) page for details.
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Start using MegaETH

You are ready to interact with dApps, send transactions, and explore the network. Browse live apps in [Rabbithole Featured Apps](https://rabbithole.megaeth.com/featured-apps). Explore more projects through [Rabbithole Discover](https://rabbithole.megaeth.com/discover) and the community-run [Fluffle Tools ecosystem directory](https://www.fluffle.tools/). Track real-time network performance at [uptime.megaeth.com](https://uptime.megaeth.com).
{% endstep %}
{% endstepper %}

## Learn More

* [Connect to MegaETH](/user-guide/connect) — full chain parameters, block explorers
* [Bridge](/user-guide/bridge) — bridging ETH from Ethereum
* [Key Contracts & Tokens](/developer-docs/overview-1/contracts) — important contract addresses
* [Faucet](/user-guide/faucet) — free testnet tokens
* [User FAQ](/user-guide/faq) — common questions


# Connect to MegaETH

Connect your wallet to MegaETH — chain parameters, RPC endpoints, and block explorers for Mainnet and Testnet.

## Chain Parameters

{% tabs %}
{% tab title="Mainnet" %}

| Parameter              | Value                                                                                                                                             |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Network Name**       | MegaETH                                                                                                                                           |
| **Chain ID**           | <code class="expression">space.vars.mainnet\_chain\_id</code> (<code class="expression">space.vars.mainnet\_chain\_id\_hex</code>)                |
| **Native & Gas Token** | Ether (ETH), 18 decimals                                                                                                                          |
| **RPC URL**            | <code class="expression">space.vars.mainnet\_rpc</code>                                                                                           |
| **Block Time**         | Mini-blocks: <code class="expression">space.vars.miniblock\_time</code> / EVM blocks: <code class="expression">space.vars.evm\_block\_time</code> |
| **Block Gas Limit**    | <code class="expression">space.vars.block\_gas\_limit</code> gas per EVM block                                                                    |
| **Base Fee Per Gas**   | <code class="expression">space.vars.base\_fee\_per\_gas</code>                                                                                    |
| **EIP-1559**           | Base fee adjustment is effectively disabled                                                                                                       |
| {% endtab %}           |                                                                                                                                                   |

{% tab title="Testnet" %}

| Parameter              | Value                                                                                                                                             |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Network Name**       | MegaETH Testnet                                                                                                                                   |
| **Chain ID**           | <code class="expression">space.vars.testnet\_chain\_id</code> (<code class="expression">space.vars.testnet\_chain\_id\_hex</code>)                |
| **Native & Gas Token** | Ether (ETH), 18 decimals                                                                                                                          |
| **RPC URL**            | <code class="expression">space.vars.testnet\_rpc</code>                                                                                           |
| **Managed RPC**        | [Alchemy](https://www.alchemy.com/) sells managed endpoints for higher rate limits                                                                |
| **Block Time**         | Mini-blocks: <code class="expression">space.vars.miniblock\_time</code> / EVM blocks: <code class="expression">space.vars.evm\_block\_time</code> |
| **Block Gas Limit**    | <code class="expression">space.vars.block\_gas\_limit</code> gas per EVM block                                                                    |
| **Base Fee Per Gas**   | <code class="expression">space.vars.base\_fee\_per\_gas</code>                                                                                    |
| **EIP-1559**           | Base fee adjustment is effectively disabled                                                                                                       |

{% hint style="warning" %}
**RPC endpoints are rate limited and may change.** Always check this page for the latest URLs and status.
{% endhint %}

{% hint style="warning" %}
**Network maintenance may occur.** RPCs may go offline during upgrades. Contracts and state may be rolled back in rare cases.
{% endhint %}

{% hint style="info" %}
**Testnet is not incentivized.** Testnet tokens and transactions have no real monetary value. Everything on the chain is solely for experimental purposes.
{% endhint %}
{% endtab %}
{% endtabs %}

## Connect Your Wallet

{% stepper %}
{% step %}

### Open your wallet settings

In MetaMask, Rabby, or any Ethereum-compatible wallet, go to **Settings → Networks → Add Network**.
{% endstep %}

{% step %}

### Enter MegaETH network details

{% tabs %}
{% tab title="Mainnet" %}

| Field           | Value                                                         |
| --------------- | ------------------------------------------------------------- |
| Network Name    | MegaETH                                                       |
| RPC URL         | <code class="expression">space.vars.mainnet\_rpc</code>       |
| Chain ID        | <code class="expression">space.vars.mainnet\_chain\_id</code> |
| Currency Symbol | ETH                                                           |
| Block Explorer  | <code class="expression">space.vars.mainnet\_etherscan</code> |
| {% endtab %}    |                                                               |

{% tab title="Testnet" %}

| Field           | Value                                                         |
| --------------- | ------------------------------------------------------------- |
| Network Name    | MegaETH Testnet                                               |
| RPC URL         | <code class="expression">space.vars.testnet\_rpc</code>       |
| Chain ID        | <code class="expression">space.vars.testnet\_chain\_id</code> |
| Currency Symbol | ETH                                                           |
| Block Explorer  | <code class="expression">space.vars.testnet\_etherscan</code> |
| {% endtab %}    |                                                               |
| {% endtabs %}   |                                                               |
| {% endstep %}   |                                                               |

{% step %}

### Save and switch

Save the network and switch to MegaETH. Your wallet is now connected.
{% endstep %}
{% endstepper %}

## Block Explorers

{% tabs %}
{% tab title="Mainnet" %}

* [Blockscout](https://megaeth.blockscout.com/)
* [Etherscan](https://mega.etherscan.io)
  {% endtab %}

{% tab title="Testnet" %}

* [Etherscan](https://testnet-mega.etherscan.io/)
  {% endtab %}
  {% endtabs %}

## Network Status

Check real-time network performance — block height, block time, and transactions per second — at [uptime.megaeth.com](https://uptime.megaeth.com).

## Getting Testnet ETH

Use the [faucet](/user-guide/faucet) to request free testnet tokens.


# Get Funds on Mainnet

Bridge assets to MegaETH — supported bridges, cross-chain swaps, and fiat on-ramps.

There are several ways to get tokens on MegaETH Mainnet — bridge from Ethereum or other chains, swap cross-chain, or buy directly with a card.

{% hint style="info" %}
This page is for **mainnet only**. For testnet tokens, use the [faucet](/user-guide/faucet) instead.
{% endhint %}

## Bridge via Rabbithole

The easiest way to move assets to MegaETH is through **Rabbithole**, the official MegaETH portal.

{% stepper %}
{% step %}

#### Go to the bridge

Visit [**rabbithole.megaeth.com/bridge**](https://rabbithole.megaeth.com/bridge).
{% endstep %}

{% step %}

#### Connect your wallet

Click **Connect Wallet** and approve the connection in your wallet (MetaMask, Rabby, etc.).
{% endstep %}

{% step %}

#### Choose a bridge and token

Rabbithole offers two built-in options:

* **USDm Bridge** — convert USDC to USDm at a 1:1 rate.
* **LI.FI** — swap and bridge tokens from Ethereum and other chains to MegaETH.

Select the token and amount you want to bridge, then confirm the transaction in your wallet.
{% endstep %}

{% step %}

#### Wait for confirmation

Your tokens will appear on MegaETH once the transaction is processed. The estimated time is shown before you confirm.
{% endstep %}
{% endstepper %}

## Other Bridges

Several third-party bridges also support MegaETH. You can find them listed at the bottom of the [Rabbithole bridge page](https://rabbithole.megaeth.com/bridge), including:

* [**Bungee**](https://www.bungee.exchange/) — crosschain swap aggregator
* [**Stargate**](https://stargate.finance/) — bridge USDT0 and USDm to MegaETH, powered by LayerZero
* [**deBridge**](https://debridge.com/) — instant bridging from Solana and 25+ chains
* [**Across**](https://across.to/) — fast and cheap cross-chain transfers
* [**Portal (Wormhole)**](https://portalbridge.com/) — bridge USDC, ETH, SOL, and 100+ tokens across 30+ chains
* [**Jumper**](https://jumper.xyz/) — multi-asset bridge and swap aggregator, powered by LI.FI
* [**Relay**](https://relay.link/) — pay for any onchain action with any asset, across any chain

{% hint style="info" %}
For a full list of supported bridges, see [**fluffle.tools/bridge**](https://www.fluffle.tools/bridge).
{% endhint %}

## Buy with a Card

If you do not already hold crypto, you can buy ETH or stablecoins directly on MegaETH using a debit card, credit card, or bank transfer.

Go to the **Fund** tab at [**rabbithole.megaeth.com/fund**](https://rabbithole.megaeth.com/fund), connect your wallet, and follow the prompts from the fiat onramp provider.

## Advanced: Direct Contract Bridge

{% hint style="warning" %}
This method is for advanced users only. Most users should use the [Rabbithole bridge](https://rabbithole.megaeth.com/bridge) above.
{% endhint %}

MegaETH uses an OP Stack [Standard Bridge](https://docs.optimism.io/app-developers/guides/bridging/standard-bridge). You can send ETH directly to the bridge contract on Ethereum Mainnet:

`0x0CA3A2FBC3D770b578223FBB6b062fa875a2eE75`

The same amount of ETH (minus Ethereum gas fees) will appear at your address on MegaETH after the Ethereum transaction is finalized. For developer details on the bridge contract, see the [Developer Docs](/developer-docs/overview).


# Force-include a transaction

How to force-include a transaction on MegaETH by submitting it directly to Ethereum via Etherscan, bypassing the sequencer.

Force inclusion submits a transaction directly to the L1 OptimismPortal, bypassing the sequencer. Once submitted on Ethereum, MegaETH is required to include it on L2 within 12 hours. Under normal conditions it lands in about 5–20 minutes.

{% hint style="warning" %}
This is an advanced operation. For routine transactions, submit normally through your wallet or RPC.
{% endhint %}

## When to use

* The sequencer is offline and your transaction cannot get through.
* A transaction is being consistently ignored despite sufficient gas.
* You need a censorship-resistance guarantee for a high-stakes action.

## Contract addresses

{% tabs %}
{% tab title="Mainnet" %}

| Contract       | Chain              | Address                                      |
| -------------- | ------------------ | -------------------------------------------- |
| OptimismPortal | Ethereum (chain 1) | `0x7f82f57F0Dd546519324392e408b01fcC7D709e8` |
| {% endtab %}   |                    |                                              |

{% tab title="Testnet (Sepolia)" %}

| Contract       | Chain                             | Address                                      |
| -------------- | --------------------------------- | -------------------------------------------- |
| OptimismPortal | Ethereum Sepolia (chain 11155111) | `0xF68D900e1Cdec64a8f5Dc0Ee873A9E2879256b10` |
| {% endtab %}   |                                   |                                              |
| {% endtabs %}  |                                   |                                              |

## Steps

You need a browser wallet (MetaMask, Rabby, etc.) funded with ETH on Ethereum Mainnet or Sepolia.

{% stepper %}
{% step %}

### Open OptimismPortal on Etherscan

Go to the OptimismPortal contract for your network and open the **Write as Proxy** tab:

* **Mainnet:** [OptimismPortal on Etherscan](https://etherscan.io/address/0x7f82f57F0Dd546519324392e408b01fcC7D709e8#writeProxyContract) (`0x7f82f57F0Dd546519324392e408b01fcC7D709e8`)
* **Testnet (Sepolia):** [OptimismPortal on Sepolia Etherscan](https://sepolia.etherscan.io/address/0xF68D900e1Cdec64a8f5Dc0Ee873A9E2879256b10#writeProxyContract) (`0xF68D900e1Cdec64a8f5Dc0Ee873A9E2879256b10`)
  {% endstep %}

{% step %}

### Connect your wallet

Click **Connect to Web3** and approve the connection. Make sure your wallet is set to the correct network — Ethereum Mainnet for production, Sepolia for testnet.
{% endstep %}

{% step %}

### Fill in the depositTransaction fields

Scroll to **depositTransaction** in the list and expand it. Fill in the six fields:

| Field                 | What to enter                                                                                                                                                                |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `payableAmount (ETH)` | ETH to send to MegaETH (e.g. `0.001`). Enter `0` for contract calls with no ETH attached.                                                                                    |
| `_to (address)`       | The destination address on MegaETH — your wallet address for a plain ETH transfer, or a contract address for a call.                                                         |
| `_value (uint256)`    | Same as `payableAmount` in wei. For 0.001 ETH enter `1000000000000000`. Enter `0` if sending no ETH.                                                                         |
| `_gasLimit (uint64)`  | Gas budget for L2 execution. Use `100000` for a plain ETH transfer; for contract call estimates see [Force Inclusion — Foundry](/developer-docs/overview-1/force-inclusion). |
| `_isCreation (bool)`  | `false` unless you are deploying a new contract on MegaETH.                                                                                                                  |
| `_data (bytes)`       | `0x` for a plain ETH transfer. For a contract call, paste the encoded function call data here.                                                                               |

{% hint style="info" %}
If `_gasLimit` is too low, the L2 transaction will revert on MegaETH — but your ETH is still delivered to `_to` even on failure. The L1 gas fee for submitting the deposit is non-refundable regardless.
{% endhint %}
{% endstep %}

{% step %}

### Submit and save the transaction hash

Click **Write** and confirm in your wallet. Save the Ethereum transaction hash to track the deposit.
{% endstep %}

{% step %}

### Verify on MegaETH

After 5–20 minutes, check your balance or transaction on the block explorer:

* **Mainnet:** [megaeth.blockscout.com](https://megaeth.blockscout.com)
* **Testnet:** [testnet-mega.etherscan.io](https://testnet-mega.etherscan.io)
  {% endstep %}
  {% endstepper %}

For scripted or automated force inclusion using Foundry, see [Force Inclusion — Foundry](/developer-docs/overview-1/force-inclusion).


# Get ETH on Testnet

MegaETH testnet faucet — request limits, eligibility, and how to get testnet ETH.

The MegaETH faucet gives you free testnet ETH so you can try out the network without spending real money. Testnet ETH has no monetary value — it is only for testing.

{% hint style="warning" %}
The faucet is for **testnet only**. If you need ETH on MegaETH Mainnet, see [Get Funds on Mainnet](/user-guide/bridge) for bridging and other options.
{% endhint %}

## How to Get Testnet ETH

Visit the faucet at [**testnet.megaeth.com**](https://testnet.megaeth.com).

Enter your wallet address and complete the verification step. The faucet will send testnet ETH directly to your wallet.

{% hint style="info" %}
If you are on the Fluffle whitelist, registered via Discord, active in Telegram, or have interacted with MegaETH on Twitter, you may already be prefunded and can start using the chain right away.
{% endhint %}

## Limits

* The faucet provides **1 testnet ETH**, **100 testnet USDM**, and **1,000 testnet MEGA** per user every 24 hours.
* Requests are tracked by IP address. Switching wallets will not bypass the limit.
* If you need more testnet ETH to deploy and test a protocol, reach out to the team directly.

## Rules

* Do not set up your own faucet in your dApp. Direct users to the official MegaETH faucet instead.
* The limits exist to prevent abuse and maintain network stability — not to create artificial scarcity.

## After Mainnet

The faucet will remain open after mainnet launch, but will continue to distribute tokens only for the testnet. It will not be possible to bridge testnet ETH onto mainnet.


# User FAQ

Frequently asked questions for MegaETH users — wallet issues, testnet ETH, and faucet.

## Wallet & Transactions

### My wallet transfers keep getting stuck and don't go through. What should I do?

This is usually caused by a pending transaction with a nonce conflict or underpriced gas. Try replacing the stuck transaction with a higher gas price.

### Why am I getting a 405 error when I click on the RPC endpoint link?

RPC endpoints are not meant to be opened directly in a browser. They only accept POST requests with properly formatted data, and will return a "405 Method Not Allowed" error if you try to open them in a browser (which sends a GET request instead). To use the RPC, connect through a wallet, dApp, or developer tool.

## Testnet ETH

### How can I get testnet ETH to interact with the chain?

Use the [official faucet](https://testnet.megaeth.com) to request testnet ETH.

If you are on the Fluffle whitelist, registered via Discord, active in Telegram, or have interacted with MegaETH on Twitter, you may already be prefunded and can start using the chain right away.

### Is the faucet capped?

Yes. The faucet provides 1 testnet ETH, 100 testnet USDM, and 1,000 testnet MEGA per user every 24 hours.

### Can I use different wallets to get more ETH from the faucet?

No. Requests are tracked by IP address, so switching wallets will not bypass the request limit.

### The testnet ETH from the faucet is not enough for me to deploy and test my protocol. How can I get more?

Please reach out to the team directly.

### Can I set up my own faucet in my dApp?

No. Please direct users to the official MegaETH faucet instead.

### Why is testnet ETH distribution controlled?

The limits exist purely as a last line of defense against abuse and to maintain network stability. They are not there to create artificial scarcity or out of concern about inflation.

### Will the faucet stay open after mainnet?

Yes, it will remain operational after mainnet launch but will continue to distribute tokens only for the testnet. It will not be possible to bridge testnet ETH onto mainnet.


# Overview

Overview of developing on MegaETH — EVM compatibility, gas estimation, debugging, and bridging.

MegaETH is fully compatible with Ethereum smart contracts. Standard Solidity toolchains (Foundry, Hardhat, Remix) work out of the box.

For network parameters (chain ID, RPC URLs, block explorers), see [Connect to MegaETH](/user-guide/connect).

## EVM Compatibility

MegaETH's execution environment is called **MegaEVM**. It is fully compatible with Ethereum smart contracts but introduces a few differences compared to Ethereum's EVM, especially around the [dual gas model](https://docs.megaeth.com/spec/megaevm/dual-gas-model). See [EVM Differences](/developer-docs/overview-3) for a complete list.

The MegaEVM implementation is open source and can be found on [GitHub](https://github.com/megaeth-labs/mega-evm).

## Gas Estimation

MegaETH's dual gas model means standard Ethereum toolchains may underestimate gas. Always use a MegaETH RPC endpoint for gas estimation, or bypass local simulation entirely. See [Gas Estimation](/developer-docs/overview-1/gas-estimation) for code examples, toolchain configuration, and common pitfalls.

## Debugging Transactions

MegaETH supports `debug_traceTransaction` and other debug RPC methods (via managed RPC providers), and provides [`mega-evme`](https://docs.megaeth.com/mega-evme) for local transaction replay and simulation. See [Debugging Transactions](/developer-docs/overview-1/debugging) for usage examples and common debugging scenarios.

## Onchain Payments

To charge for access to an API, content, or a metered service, MegaETH dapps can use the HTTP 402 "pay then retry" pattern with the x402 and MPP protocol families. See [Onchain Payments](/developer-docs/payments) for the five concrete payment flows — one-time and pay-as-you-go, user-paid and gas-sponsored — with diagrams and a runnable reference implementation.

## Using the Canonical Bridge

MegaETH's canonical bridge is the preferred method to bridge Ether (ETH) from Ethereum to MegaETH. The Ethereum side of the bridge is at `0x0CA3A2FBC3D770b578223FBB6b062fa875a2eE75` on Ethereum Mainnet. Currently, it runs OP Stack's [Standard Bridge](https://docs.optimism.io/app-developers/guides/bridging/standard-bridge) in its [op-contracts/v3.0.0 release](https://github.com/ethereum-optimism/optimism/blob/backports/op-contracts/v3.0.0/packages/contracts-bedrock/src/universal/StandardBridge.sol) with a small patch adjusting a few parameters.

### Simple bridge (native transfer)

The easiest way to bridge Ether to MegaETH is sending Ether to the bridge address on Ethereum Mainnet in a plain native transfer. The same amount of Ether sans gas fees will appear in sender's address on MegaETH after the transfer is finalized on Ethereum Mainnet.

### Advanced bridge (depositETH)

For more control, use the `depositETH` method of the bridge contract. It allows for specifying the (approximate) amount of gas that should be charged by and forwarded from Ethereum Mainnet to MegaETH for the deposit transaction to use, as well as adding extra data to the transaction.

As an example, the following `cast send` command calls `depositETH` to bridge 0.001 Ether with 61000 gas and extra data `bunny`:

```bash
cast send 0x0CA3A2FBC3D770b578223FBB6b062fa875a2eE75 \
  'depositETH(uint32, bytes)' 61000 "0x62756e6e79" \
  --value 0.001ether
```

To bridge ERC-20 tokens using the canonical bridge, see [Bridge ERC-20 Tokens](/developer-docs/bridge-erc20).

## L1 Contracts (Ethereum Mainnet)

See [Contracts & Tokens](/developer-docs/overview-1/contracts#l1-contracts-ethereum) for all L1 contract addresses (bridge, DisputeGameFactory, OptimismPortal, SystemConfig, etc.).

## Next Steps

* [EVM Differences](/developer-docs/overview-3) — what's different from Ethereum
* [Gas Model](/developer-docs/overview-3/gas-model) — how MegaETH's dual gas model works
* [System Contracts](/developer-docs/overview-3/system-contracts) — oracle, timestamp, and other system contracts
* [JSON-RPC](/developer-docs/rpc) — protocol guidance, limits, errors, and RPC methods
* [Realtime API](/developer-docs/overview-2/realtime-api) — WebSocket and real-time RPC extensions
* [Onchain Payments](/developer-docs/payments) — charge for APIs, content, or metered services onchain


# Bridge ERC-20 Tokens

How to deploy and bridge an ERC-20 token from Ethereum to MegaETH using the OP Stack Standard Bridge.

MegaETH's canonical bridge supports ERC-20 token bridging via the OP Stack [Standard Bridge](https://docs.optimism.io/app-developers/guides/bridging/standard-bridge). Bridging locks tokens in the `L1StandardBridge` on Ethereum and mints a paired `OptimismMintableERC20` on MegaETH.

## Prerequisites

* [Foundry](https://getfoundry.sh/) installed (`forge` and `cast`)
* A wallet funded with ETH on both L1 (for deployment and bridging gas) and L2 (for registration gas)
* An ERC-20 contract ready to deploy, or an existing L1 token address

## Contract Addresses

{% tabs %}
{% tab title="Mainnet" %}

| Contract                     | Chain                        | Address                                      |
| ---------------------------- | ---------------------------- | -------------------------------------------- |
| L1StandardBridge             | Ethereum (chain 1)           | `0x0CA3A2FBC3D770b578223FBB6b062fa875a2eE75` |
| OptimismMintableERC20Factory | Ethereum (chain 1)           | `0xF875030B9464001fC0f964E47546b0AFEEbD7C61` |
| L2StandardBridge             | MegaETH Mainnet (chain 4326) | `0x4200000000000000000000000000000000000010` |
| OptimismMintableERC20Factory | MegaETH Mainnet (chain 4326) | `0x4200000000000000000000000000000000000012` |
| {% endtab %}                 |                              |                                              |

{% tab title="Testnet (Sepolia)" %}

| Contract                     | Chain                             | Address                                      |
| ---------------------------- | --------------------------------- | -------------------------------------------- |
| L1StandardBridge             | Ethereum Sepolia (chain 11155111) | `0x8033d50c753b3f19748f239ac8cf915b2888cd32` |
| OptimismMintableERC20Factory | Ethereum Sepolia (chain 11155111) | `0x11f008caa3083aa8a3b6f9f06f923e98a28fa286` |
| L2StandardBridge             | MegaETH Testnet (chain 6343)      | `0x4200000000000000000000000000000000000010` |
| OptimismMintableERC20Factory | MegaETH Testnet (chain 6343)      | `0x4200000000000000000000000000000000000012` |
| {% endtab %}                 |                                   |                                              |
| {% endtabs %}                |                                   |                                              |

## Steps

{% stepper %}
{% step %}

### Deploy your ERC-20 on L1

Deploy your token contract on Ethereum (or Sepolia for testing). The example below uses a Foundry script; adapt it for your own token.

```bash
forge script script/Deploy.s.sol \
  --rpc-url $L1_RPC \
  --broadcast \
  --private-key $PRIVATE_KEY
```

Save the deployed token address — you will need it in the next step.
{% endstep %}

{% step %}

### Register the L2 counterpart

Call `createOptimismMintableERC20` on the `OptimismMintableERC20Factory` **on MegaETH**. This deploys a bridgeable ERC-20 on L2 that is linked to your L1 token. Replace `"MyToken"` and `"MTK"` with your token's name and symbol.

```bash
cast send $L2_MINTABLE_FACTORY \
  "createOptimismMintableERC20(address,string,string)" \
  $L1_TOKEN "MyToken" "MTK" \
  --rpc-url $L2_RPC \
  --private-key $PRIVATE_KEY
```

The factory emits an `OptimismMintableERC20Created(address indexed localToken, address indexed remoteToken, address deployer)` event. Parse the `localToken` field from the receipt to get your L2 token address.

```bash
# Extract the L2 token address from the event logs
# topics[0] is keccak256("OptimismMintableERC20Created(address,address,address)")
# topics[1] is the L2 token address ABI-encoded as a 32-byte padded value; [26:] strips the leading zeros
cast receipt $TX_HASH --rpc-url $L2_RPC --json \
  | jq -r '.logs[] | select(.topics[0] == "0x52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb") | "0x" + .topics[1][26:]'
```

{% endstep %}

{% step %}

### Approve the L1 bridge

Approve `L1StandardBridge` to spend the tokens you want to bridge. Set `$AMOUNT` in wei (e.g. `100000000000000000000` for 100 tokens with 18 decimals).

```bash
cast send $L1_TOKEN \
  "approve(address,uint256)" \
  $L1_BRIDGE $AMOUNT \
  --rpc-url $L1_RPC \
  --private-key $PRIVATE_KEY
```

{% endstep %}

{% step %}

### Bridge tokens to MegaETH

Call `bridgeERC20` on `L1StandardBridge`. Pass both the L1 and L2 token addresses, the amount in wei, a minimum gas limit for L2 execution, and empty extra data.

```bash
cast send $L1_BRIDGE \
  "bridgeERC20(address,address,uint256,uint32,bytes)" \
  $L1_TOKEN \
  $L2_TOKEN \
  $AMOUNT \
  200000 \
  0x \
  --rpc-url $L1_RPC \
  --private-key $PRIVATE_KEY
```

`200000` is sufficient for most standard ERC-20 tokens. The bridge transaction locks tokens on L1 and relays a message to MegaETH to mint the equivalent amount on L2.
{% endstep %}

{% step %}

### Verify the L2 balance

After the L1 transaction is finalized and relayed (\~1–2 minutes), check the balance on MegaETH.

```bash
cast call $L2_TOKEN \
  "balanceOf(address)(uint256)" \
  $(cast wallet address --private-key $PRIVATE_KEY) \
  --rpc-url $L2_RPC
```

{% hint style="info" %}
The deposit takes approximately 1–2 minutes to appear on MegaETH — one L1 block for finality, plus sequencer relay time. You can track the L1 transaction on [Etherscan](https://etherscan.io) (mainnet) or [Sepolia Etherscan](https://sepolia.etherscan.io) (testnet), and the L2 deposit on [MegaETH Blockscout](https://megaeth.blockscout.com) (mainnet) or the [testnet explorer](https://testnet-mega.etherscan.io).
{% endhint %}
{% endstep %}
{% endstepper %}

## Withdrawals (L2 → L1)

Withdrawing tokens back to Ethereum requires initiating a withdrawal on L2 and then proving and finalizing it on L1 after the challenge period. This follows the standard OP Stack withdrawal flow — see the [OP Stack withdrawal guide](https://docs.optimism.io/app-developers/guides/bridging/standard-bridge#withdrawing-erc-20-tokens) for details.


# Send Transaction

How to submit transactions on MegaETH — deploy contracts, estimate gas, and debug failures.

MegaETH is fully EVM-compatible. Point your toolchain at a MegaETH RPC endpoint and everything works — Foundry, Hardhat, Remix, ethers.js, viem, web3.py. For network parameters (chain ID, RPC URLs), see [Connect to MegaETH](/user-guide/connect). To bridge ETH or tokens from Ethereum, see [Bridge](/user-guide/bridge).

## Estimate gas correctly

MegaETH's [dual gas model](/developer-docs/overview-3/gas-model) charges both compute gas and storage gas. Local EVM simulations (Foundry, Hardhat) only know about compute gas and will underestimate — sometimes by a large margin.

A simple ETH transfer costs 21,000 gas on Ethereum but **60,000 gas** on MegaETH (21,000 compute + 39,000 storage). A toolchain that estimates 21,000 will produce a transaction that reverts with "intrinsic gas too low."

**The fix:** always estimate gas against a MegaETH RPC endpoint or use [`mega-evme`](/developer-docs/overview-1/debugging#simulating-a-new-transaction) tool to simulate, instead of a local standard EVM.

{% tabs %}
{% tab title="Foundry" %}

```bash
# Estimate with MegaETH RPC (correct)
cast estimate 0xContract 'myFunction(uint256)' 42 \
  --rpc-url https://mainnet.megaeth.com/rpc
```

{% endtab %}

{% tab title="curl" %}

```bash
curl -s https://mainnet.megaeth.com/rpc \
  -X POST -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "eth_estimateGas",
    "params": [{"from":"0xYou","to":"0xContract","data":"0xCalldata"}],
    "id": 1
  }'
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
The public RPC runs `eth_estimateGas` through a CPU-limited estimator whose source-default budget is **0.5 seconds**. Long-running estimates can fail even when the transaction's protocol gas limit would be valid. If this affects a large deployment, either set a manual gas limit or use a [managed RPC provider](/developer-docs/tooling#rpc-providers) with a different estimation policy. You can determine the exact gas needed by simulating locally with [`mega-evme`](/developer-docs/overview-1/debugging#simulating-a-new-transaction).
{% endhint %}

For the full list of pitfalls (volatile data caps, resource limits, receipt interpretation), see [Gas Estimation](/developer-docs/overview-1/gas-estimation).

## Submit transaction

{% tabs %}
{% tab title="Foundry (forge create)" %}

```bash
# forge create calls eth_estimateGas on the RPC — no local simulation
forge create src/MyContract.sol:MyContract \
  --rpc-url https://mainnet.megaeth.com/rpc \
  --private-key $PRIVATE_KEY
```

{% endtab %}

{% tab title="Foundry (forge script)" %}

```bash
# forge script runs local EVM simulation by default, which underestimates gas.
# Use --skip-simulation to bypass local estimation and let the RPC handle it.
forge script script/Deploy.s.sol \
  --rpc-url https://mainnet.megaeth.com/rpc \
  --private-key $PRIVATE_KEY \
  --skip-simulation \
  --broadcast
```

{% endtab %}

{% tab title="cast" %}

```bash
# Send a simple ETH transfer
cast send 0xRecipient --value 0.1ether \
  --rpc-url https://mainnet.megaeth.com/rpc \
  --private-key $PRIVATE_KEY
```

{% endtab %}

{% tab title="eth\_sendRawTransaction" %}

```bash
# 1. Sign the transaction offline (e.g., with cast)
SIGNED_TX=$(cast mktx 0xRecipient --value 0.1ether \
  --rpc-url https://mainnet.megaeth.com/rpc \
  --private-key $PRIVATE_KEY)

# 2. Submit via eth_sendRawTransaction
curl -s https://mainnet.megaeth.com/rpc \
  -X POST -H "Content-Type: application/json" \
  -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_sendRawTransaction\",\"params\":[\"$SIGNED_TX\"]}"
```

{% endtab %}

{% tab title="realtime\_sendRawTransaction" %}

```bash
# Sign the transaction offline
SIGNED_TX=$(cast mktx 0xRecipient --value 0.1ether \
  --rpc-url https://mainnet.megaeth.com/rpc \
  --private-key $PRIVATE_KEY)

# Submit and get the receipt back in one call — no polling needed
curl -s https://mainnet.megaeth.com/rpc \
  -X POST -H "Content-Type: application/json" \
  -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"realtime_sendRawTransaction\",\"params\":[\"$SIGNED_TX\"]}"
```

Returns the full transaction receipt directly. The node waits up to 5 seconds by default; the public gateway caps an explicit timeout at 3,000 milliseconds and returns `-32000 realtime transaction expired` if the deadline elapses first. See [`realtime_sendRawTransaction`](/developer-docs/rpc/reference/realtime_sendrawtransaction) for the full reference.
{% endtab %}
{% endtabs %}

For key contract addresses (bridge, CREATE2 factory), token lists (stablecoins, LSTs, BTC), and how to bridge tokens onto MegaETH, see [Contracts & Tokens](/developer-docs/overview-1/contracts). To bridge assets from Ethereum, see [Bridge](/user-guide/bridge).

## Debug a failed transaction

When a transaction reverts, MegaETH provides two debugging tools:

1. **`debug_traceTransaction`** — standard Ethereum debug RPC, available through [managed providers](/developer-docs/tooling#rpc-providers) like Alchemy.
2. [**`mega-evme`**](/developer-docs/overview-1/debugging#simulating-a-new-transaction) — MegaETH's local transaction simulation tool. No RPC provider needed.

{% tabs %}
{% tab title="mega-evme (replay)" %}

```bash
# Replay a failed transaction with call-level tracing
mega-evme replay 0xYourTxHash \
  --rpc https://mainnet.megaeth.com/rpc \
  --trace --tracer call
```

{% endtab %}

{% tab title="mega-evme (what-if)" %}

```bash
# Would the transaction succeed with more gas?
mega-evme replay 0xYourTxHash \
  --rpc https://mainnet.megaeth.com/rpc \
  --override.gas-limit 30000000
```

{% endtab %}

{% tab title="cast (debug RPC)" %}

```bash
# Requires a provider that supports debug_traceTransaction
cast rpc debug_traceTransaction 0xYourTxHash \
  --rpc-url https://your-alchemy-endpoint.com
```

{% endtab %}
{% endtabs %}

Common failure causes:

| Symptom                                      | Likely cause                                    | Fix                                       |
| -------------------------------------------- | ----------------------------------------------- | ----------------------------------------- |
| `intrinsic gas too low`                      | Gas estimated by local EVM, missing storage gas | Estimate against MegaETH RPC              |
| `out of gas` with low compute usage          | Storage gas exceeded the limit                  | Increase gas limit or reduce state writes |
| `out of gas` after reading `block.timestamp` | Volatile data access caps compute gas to 20M    | Split work across multiple transactions   |
| `resource limit exceeded`                    | Hit data size, KV updates, or state growth cap  | Reduce state operations per transaction   |

For the full debugging guide, see [Debugging Transactions](/developer-docs/overview-1/debugging).

## Understand execution semantics

MegaETH is EVM-compatible, but the execution model has differences that affect gas costs and transaction behavior. The key concepts:

* **Dual gas model** — every transaction pays compute gas + storage gas. See [Gas Model](/developer-docs/overview-3/gas-model).
* **Resource limits** — per-transaction caps on data size, KV updates, and state growth beyond gas. See [Resource Limits](/developer-docs/overview-3/resource-limits).
* **Volatile data access** — reading `block.timestamp`, `block.number`, or oracle data caps compute gas to 20M. See [Volatile Data Access](/developer-docs/overview-3/volatile-data).
* **System contracts** — oracle, high-precision timestamp, and keyless deployment at fixed addresses. See [System Contracts](/developer-docs/overview-3/system-contracts).

For the complete list of behavioral differences, see [EVM Differences](/developer-docs/overview-3).


# Contracts & Tokens

Key contract addresses and tokens on MegaETH and Ethereum Mainnet.

## Core

{% tabs %}
{% tab title="Mainnet" %}

| Token                                | Address                                                                                                                           | Description                                                        |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| [MEGA](https://megaeth.com)          | [`0x28B7E77f82B25B95953825F1E3eA0E36c1c29861`](https://megaeth.blockscout.com/address/0x28B7E77f82B25B95953825F1E3eA0E36c1c29861) | MegaETH's native protocol token.                                   |
| WETH                                 | [`0x4200000000000000000000000000000000000006`](https://megaeth.blockscout.com/address/0x4200000000000000000000000000000000000006) | Wrapped Ether — an ERC-20 version of ETH for use in dApps.         |
| [Multicall3](https://multicall3.com) | [`0xcA11bde05977b3631167028862bE2a173976CA11`](https://megaeth.blockscout.com/address/0xcA11bde05977b3631167028862bE2a173976CA11) | Utility contract that batches multiple calls into one transaction. |
| {% endtab %}                         |                                                                                                                                   |                                                                    |

{% tab title="Testnet" %}

| Token                                | Address                                                                                                                              | Description                                                        |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------ |
| [MEGA](https://megaeth.com)          | [`0xc903c68C1d389CEd76fEe0349067a4295828e6c2`](https://testnet-mega.etherscan.io/address/0xc903c68C1d389CEd76fEe0349067a4295828e6c2) | MegaETH's native protocol token (testnet deployment).              |
| WETH                                 | [`0x4200000000000000000000000000000000000006`](https://testnet-mega.etherscan.io/address/0x4200000000000000000000000000000000000006) | Wrapped Ether — an ERC-20 version of ETH for use in dApps.         |
| [Multicall3](https://multicall3.com) | [`0xcA11bde05977b3631167028862bE2a173976CA11`](https://testnet-mega.etherscan.io/address/0xcA11bde05977b3631167028862bE2a173976CA11) | Utility contract that batches multiple calls into one transaction. |
| {% endtab %}                         |                                                                                                                                      |                                                                    |
| {% endtabs %}                        |                                                                                                                                      |                                                                    |

## Stablecoins

{% tabs %}
{% tab title="Mainnet" %}

| Token                         | Address                                                                                                                           | Description                                                                                                                |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| [CUSD](https://www.cap.app)   | [`0xcCcc62962d17b8914c62D74FfB843d73B2a3cccC`](https://megaeth.blockscout.com/address/0xcCcc62962d17b8914c62D74FfB843d73B2a3cccC) | Dollar-pegged stablecoin by Cap Finance.                                                                                   |
| [STCUSD](https://www.cap.app) | [`0x88887bE419578051FF9F4eb6C858A951921D8888`](https://megaeth.blockscout.com/address/0x88887bE419578051FF9F4eb6C858A951921D8888) | Yield-bearing version of CUSD — grows in value as Cap's protocol earns returns.                                            |
| [USDM](https://megaeth.com)   | [`0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7`](https://megaeth.blockscout.com/address/0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7) | MegaETH's native stablecoin, backed by U.S. Treasury-based reserves.                                                       |
| [USDmY](https://megaeth.com)  | [`0x2eA493384F42d7Ea78564F3EF4C86986eAB4a890`](https://megaeth.blockscout.com/address/0x2eA493384F42d7Ea78564F3EF4C86986eAB4a890) | Yield-bearing version of USDM — holders earn returns from the underlying reserves.                                         |
| [USDe](https://ethena.fi)     | [`0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34`](https://megaeth.blockscout.com/address/0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34) | Synthetic dollar by Ethena Labs, backed by crypto assets and hedged with futures.                                          |
| [sUSDe](https://ethena.fi)    | [`0x211Cc4DD073734dA055fbF44a2b4667d5E5fE5d2`](https://megaeth.blockscout.com/address/0x211Cc4DD073734dA055fbF44a2b4667d5E5fE5d2) | Staked USDe — grows in value over time as it earns Ethena protocol revenue.                                                |
| [USDT0](https://usdt0.to)     | [`0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb`](https://megaeth.blockscout.com/address/0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb) | Cross-chain USDT by Tether and LayerZero, usable across 15+ blockchains. 6 decimals.                                       |
| [iTRY](https://try.finance)   | [`0x996ce957408804fEC19237D866799d9C7076E48c`](https://megaeth.blockscout.com/address/0x996ce957408804fEC19237D866799d9C7076E48c) | Interest-bearing Turkish Lira stablecoin — LayerZero OFT from Ethereum that earns yield from Turkish Lira reserves.        |
| [wiTRY](https://try.finance)  | [`0x15B271D9012b5820FC42b1c495B4C1e206547De5`](https://megaeth.blockscout.com/address/0x15B271D9012b5820FC42b1c495B4C1e206547De5) | Wrapped iTRY — non-rebasing version of iTRY for DeFi compatibility, available on MegaETH as a LayerZero OFT from Ethereum. |
| {% endtab %}                  |                                                                                                                                   |                                                                                                                            |
| {% endtabs %}                 |                                                                                                                                   |                                                                                                                            |

## ETH Liquid Staking & Restaking

{% tabs %}
{% tab title="Mainnet" %}

| Token                                  | Address                                                                                                                           | Description                                                                       |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| [ezETH](https://www.renzoprotocol.com) | [`0x09601A65e7de7BC8A19813D263dD9E98bFdC3c57`](https://megaeth.blockscout.com/address/0x09601A65e7de7BC8A19813D263dD9E98bFdC3c57) | Renzo restaked ETH — earns staking and restaking rewards simultaneously.          |
| [pufETH](https://www.puffer.fi)        | [`0x37D6382B6889cCeF8d6871A8b60E667115eDDBcF`](https://megaeth.blockscout.com/address/0x37D6382B6889cCeF8d6871A8b60E667115eDDBcF) | Puffer Finance liquid restaking token — earns staking and restaking rewards.      |
| [rsETH](https://kelpdao.xyz)           | [`0xc3eACf0612346366Db554C991D7858716db09f58`](https://megaeth.blockscout.com/address/0xc3eACf0612346366Db554C991D7858716db09f58) | Kelp DAO restaked ETH — earns restaking rewards on top of regular staking yields. |
| [wrsETH](https://kelpdao.xyz)          | [`0x4Fc44BE15e9B6E30C1E774E2C87A21D3E8b5403F`](https://megaeth.blockscout.com/address/0x4Fc44BE15e9B6E30C1E774E2C87A21D3E8b5403F) | Wrapped rsETH — cross-chain version of rsETH by Kelp DAO.                         |
| [wstETH](https://lido.fi)              | [`0x601aC63637933D88285A025C685AC4e9a92a98dA`](https://megaeth.blockscout.com/address/0x601aC63637933D88285A025C685AC4e9a92a98dA) | Lido wrapped staked ETH — staking rewards accrue in the token's value.            |
| {% endtab %}                           |                                                                                                                                   |                                                                                   |
| {% endtabs %}                          |                                                                                                                                   |                                                                                   |

## BTC

{% tabs %}
{% tab title="Mainnet" %}

| Token                               | Address                                                                                                                           | Description                                                                       |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| BTC.b                               | [`0xB0F70C0bD6FD87dbEb7C10dC692a2a6106817072`](https://megaeth.blockscout.com/address/0xB0F70C0bD6FD87dbEb7C10dC692a2a6106817072) | Bridged Bitcoin — real BTC bridged onto EVM chains. 8 decimals.                   |
| [LBTC](https://www.lombard.finance) | [`0xecAc9C5F704e954931349Da37F60E39f515c11c1`](https://megaeth.blockscout.com/address/0xecAc9C5F704e954931349Da37F60E39f515c11c1) | Lombard staked BTC — earns native Bitcoin yield while usable in DeFi. 8 decimals. |
| [WBTC](https://wbtc.network)        | [`0x32090fB1399a31cC095e6341a6353b7c09ba84FB`](https://megaeth.blockscout.com/address/0x32090fB1399a31cC095e6341a6353b7c09ba84FB) | Wrapped Bitcoin by BitGo — backed 1:1 by BTC held in custody. 8 decimals.         |
| {% endtab %}                        |                                                                                                                                   |                                                                                   |
| {% endtabs %}                       |                                                                                                                                   |                                                                                   |

## Other Tokens

{% tabs %}
{% tab title="Mainnet" %}

| Token                                     | Address                                                                                                                           | Description                                                                                |
| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| CROWN                                     | [`0xf7d2F0d0b0517CBDbf87C86910ce10FaAab3589D`](https://megaeth.blockscout.com/address/0xf7d2F0d0b0517CBDbf87C86910ce10FaAab3589D) | Crown Credits — a token native to MegaETH.                                                 |
| [DCASH](https://app.offshoreprotocol.fun) | [`0x6691D67Ece85Ed950244c2CB5848d6498134321f`](https://megaeth.blockscout.com/address/0x6691D67Ece85Ed950244c2CB5848d6498134321f) | Dirty Cash — game token of Offshore Protocol, an on-chain idle RPG.                        |
| [DIRTY](https://offshoreprotocol.xyz)     | [`0xC2f34f8849a8607FD73E06D6849bDA07C2b7DE38`](https://megaeth.blockscout.com/address/0xC2f34f8849a8607FD73E06D6849bDA07C2b7DE38) | Dirty Money — game token of Offshore Protocol, an on-chain idle RPG.                       |
| [MegaSIR](https://www.sir.trading)        | [`0x9367A0c482703d8d9bda995B03f8E71056a72500`](https://megaeth.blockscout.com/address/0x9367A0c482703d8d9bda995B03f8E71056a72500) | SIR Trading token — a leverage protocol with no liquidations or funding fees. 12 decimals. |
| [NXT](https://nxterminal.xyz)             | [`0x2F55e14F0b2B2118d2026d20Ad2C39EAcBdCAc47`](https://megaeth.blockscout.com/address/0x2F55e14F0b2B2118d2026d20Ad2C39EAcBdCAc47) | NX Terminal Token — native utility token of NX Terminal: Protocol Wars.                    |
| [WSOL](https://wormhole.com)              | [`0x9a96E366F6b2ED5850A38B58D355a80aFD998411`](https://megaeth.blockscout.com/address/0x9a96E366F6b2ED5850A38B58D355a80aFD998411) | Solana's native SOL token bridged via Wormhole. 9 decimals.                                |

{% hint style="info" %}
This list is sourced from the [mega-tokenlist](https://github.com/megaeth-labs/mega-tokenlist) registry. If a token you are looking for is not listed, check the registry for the latest additions.
{% endhint %}
{% endtab %}
{% endtabs %}

## OP Stack Predeploys

These contracts are predeployed at fixed addresses on all OP Stack chains. The addresses are the same on both MegaETH Mainnet and Testnet.

| Contract                                                                                                                  | Address                                      | Description                                        |
| ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | -------------------------------------------------- |
| [L2CrossDomainMessenger](https://docs.optimism.io/op-stack/protocol/smart-contracts#l2crossdomainmessenger)               | `0x4200000000000000000000000000000000000007` | Send and receive messages between L1 and L2.       |
| [L2StandardBridge](https://docs.optimism.io/op-stack/protocol/smart-contracts#l2standardbridge)                           | `0x4200000000000000000000000000000000000010` | Bridge ETH and ERC-20 tokens between L1 and L2.    |
| [GasPriceOracle](https://docs.optimism.io/op-stack/protocol/smart-contracts#gaspriceoracle)                               | `0x420000000000000000000000000000000000000F` | L1 fee estimation for transactions.                |
| [SequencerFeeVault](https://docs.optimism.io/op-stack/protocol/smart-contracts#sequencerfeevault)                         | `0x4200000000000000000000000000000000000011` | Holds fees collected by the sequencer.             |
| [OptimismMintableERC20Factory](https://docs.optimism.io/op-stack/protocol/smart-contracts#optimismmintableerc20factory)   | `0x4200000000000000000000000000000000000012` | Create bridgeable ERC-20 tokens on L2.             |
| [L2ERC721Bridge](https://docs.optimism.io/op-stack/protocol/smart-contracts#l2erc721bridge)                               | `0x4200000000000000000000000000000000000014` | Bridge ERC-721 (NFT) tokens between L1 and L2.     |
| [L1Block](https://docs.optimism.io/op-stack/protocol/smart-contracts#l1block)                                             | `0x4200000000000000000000000000000000000015` | Access the latest known L1 block info from L2.     |
| [L2ToL1MessagePasser](https://docs.optimism.io/op-stack/protocol/smart-contracts#l2tol1messagepasser)                     | `0x4200000000000000000000000000000000000016` | Send messages from L2 to L1 (used by withdrawals). |
| [OptimismMintableERC721Factory](https://docs.optimism.io/op-stack/protocol/smart-contracts#optimismmintableerc721factory) | `0x4200000000000000000000000000000000000017` | Create bridgeable ERC-721 tokens on L2.            |
| [GovernanceToken](https://docs.optimism.io/op-stack/protocol/smart-contracts#governancetoken)                             | `0x4200000000000000000000000000000000000042` | OP governance token (EIP-2612 support).            |

{% hint style="info" %}
WETH and Multicall3 are also OP Stack predeploys/preinstalls — they are listed under [Core](#core) above. For full details, see the OP Stack [predeploys](https://docs.optimism.io/op-stack/protocol/smart-contracts#layer-2-contracts-predeploys) documentation.
{% endhint %}

## OP Stack Preinstalls

These contracts come preinstalled on OP Stack chains at their standard addresses. The addresses are the same on both MegaETH Mainnet and Testnet.

| Contract                                                                                         | Address                                      | Description                                  |
| ------------------------------------------------------------------------------------------------ | -------------------------------------------- | -------------------------------------------- |
| [Safe](https://github.com/safe-global/safe-smart-account)                                        | `0x69f4D1788e39c87893C980c06EdF4b7f686e2938` | Gnosis Safe multisig wallet.                 |
| [SafeL2](https://github.com/safe-global/safe-smart-account)                                      | `0xfb1bffC9d739B8D520DaF37dF666da4C687191EA` | Gnosis Safe optimized for L2.                |
| [MultiSend](https://github.com/safe-global/safe-smart-account)                                   | `0x998739BFdAAdde7C933B942a68053933098f9EDa` | Batch multiple Safe transactions.            |
| [MultiSendCallOnly](https://github.com/safe-global/safe-smart-account)                           | `0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B` | Batch multiple read-only calls via Safe.     |
| [Safe Singleton Factory](https://github.com/safe-global/safe-singleton-factory)                  | `0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7` | Deterministic deployment for Safe contracts. |
| [create2Deployer](https://github.com/pcaversaccio/create2deployer)                               | `0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2` | Deploy contracts to deterministic addresses. |
| [CreateX](https://github.com/pcaversaccio/createx)                                               | `0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed` | Advanced deterministic contract deployment.  |
| [Deterministic Deployment Proxy](https://github.com/Arachnid/deterministic-deployment-proxy)     | `0x4e59b44847b379578588920cA78FbF26c0B4956C` | Arachnid's CREATE2 factory.                  |
| [Permit2](https://github.com/Uniswap/permit2)                                                    | `0x000000000022D473030F116dDEE9F6B43aC78BA3` | Uniswap's universal token approval contract. |
| [ERC-4337 EntryPoint v0.6](https://github.com/eth-infinitism/account-abstraction/tree/v0.6.0)    | `0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789` | Account abstraction entry point (v0.6).      |
| [ERC-4337 SenderCreator v0.6](https://github.com/eth-infinitism/account-abstraction/tree/v0.6.0) | `0x7fc98430eAEdbb6070B35B39D798725049088348` | Creates sender contracts for ERC-4337 v0.6.  |
| [ERC-4337 EntryPoint v0.7](https://github.com/eth-infinitism/account-abstraction/tree/v0.7.0)    | `0x0000000071727De22E5E9d8BAf0edAc6f37da032` | Account abstraction entry point (v0.7).      |
| [ERC-4337 SenderCreator v0.7](https://github.com/eth-infinitism/account-abstraction/tree/v0.7.0) | `0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C` | Creates sender contracts for ERC-4337 v0.7.  |

{% hint style="info" %}
For full details, see the OP Stack [preinstalls](https://docs.optimism.io/op-stack/features/preinstalls#contracts-and-deployed-addresses) documentation.
{% endhint %}

## L1 Contracts (Ethereum)

{% tabs %}
{% tab title="Mainnet" %}

| Name                                     | Address                                                                                                                 | Notes                                                                  |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| L1StandardBridgeProxy (Canonical Bridge) | [`0x0CA3A2FBC3D770b578223FBB6b062fa875a2eE75`](https://etherscan.io/address/0x0CA3A2FBC3D770b578223FBB6b062fa875a2eE75) | Send ETH here to [bridge](/user-guide/bridge) from Ethereum to MegaETH |
| OptimismPortalProxy                      | [`0x7f82f57F0Dd546519324392e408b01fcC7D709e8`](https://etherscan.io/address/0x7f82f57F0Dd546519324392e408b01fcC7D709e8) | Entry point for deposits and withdrawals                               |
| DisputeGameFactoryProxy                  | [`0x8546840adf796875cd9aacc5b3b048f6b2c9d563`](https://etherscan.io/address/0x8546840adf796875cd9aacc5b3b048f6b2c9d563) | Creates dispute games for fault proofs                                 |
| SystemConfigProxy                        | [`0x1ED92E1bc9A2735216540EDdD0191144681cb77E`](https://etherscan.io/address/0x1ED92E1bc9A2735216540EDdD0191144681cb77E) | On-chain system configuration                                          |
| L1CrossDomainMessengerProxy              | [`0x6C7198250087B29A8040eC63903Bc130f4831Cc9`](https://etherscan.io/address/0x6C7198250087B29A8040eC63903Bc130f4831Cc9) | Cross-domain message passing                                           |
| L1ERC721BridgeProxy                      | [`0x3D8ee269F87A7f3F0590c5C0d825FFF06212A242`](https://etherscan.io/address/0x3D8ee269F87A7f3F0590c5C0d825FFF06212A242) | Bridge ERC-721 tokens between L1 and L2                                |
| OptimismMintableERC20FactoryProxy        | [`0xF875030B9464001fC0f964E47546b0AFEEbD7C61`](https://etherscan.io/address/0xF875030B9464001fC0f964E47546b0AFEEbD7C61) | Create bridgeable ERC-20 tokens on L1                                  |
| SuperchainConfigProxy                    | [`0x5d0ff601bc8580d8682c0462df55343cb0b99285`](https://etherscan.io/address/0x5d0ff601bc8580d8682c0462df55343cb0b99285) | Superchain-wide configuration                                          |
| ProtocolVersionsProxy                    | [`0x150355311f965af4937fcca526f9df0573fd5b85`](https://etherscan.io/address/0x150355311f965af4937fcca526f9df0573fd5b85) | Protocol version tracking                                              |
| USDM                                     | [`0xEc2AF1C8B110a61fD9C3Fa6a554a031Ca9943926`](https://etherscan.io/address/0xEc2AF1C8B110a61fD9C3Fa6a554a031Ca9943926) |                                                                        |

MegaETH's L1 contracts are from OP Stack's [op-contracts/v3.0.0 release](https://github.com/ethereum-optimism/optimism/tree/backports/op-contracts/v3.0.0/packages/contracts-bedrock). See OP Stack docs for [descriptions of these contracts](https://docs.optimism.io/op-stack/protocol/smart-contracts#l1-contract-details).
{% endtab %}
{% endtabs %}

## Adding a Token to the Registry

To get your token listed, submit a pull request to the [mega-tokenlist](https://github.com/megaeth-labs/mega-tokenlist) repository.

{% stepper %}
{% step %}

### Create a token folder

Create `data/YOUR_TOKEN/` in the repository.
{% endstep %}

{% step %}

### Add token metadata

Create a `data.json` file with your token's name, symbol, decimals, and per-chain addresses.

```json
{
  "name": "My Token",
  "symbol": "MTK",
  "decimals": 18,
  "tokens": {
    "megaeth": {
      "address": "0xYourTokenAddress",
      "isOrigin": true,
      "mechanism": "native"
    }
  }
}
```

If the token is bridged from Ethereum, include both chains:

```json
{
  "name": "My Token",
  "symbol": "MTK",
  "decimals": 18,
  "tokens": {
    "ethereum": {
      "address": "0xEthereumAddress",
      "isOrigin": true,
      "mechanism": "lock",
      "bridge": "0xBridgeOrLockboxAddress"
    },
    "megaeth": {
      "address": "0xMegaETHAddress",
      "isOrigin": false,
      "mechanism": "mint",
      "bridge": "0xMintEndpointAddress"
    }
  }
}
```

{% endstep %}

{% step %}

### Add a logo

Add a `logo.svg` or `logo.png` (256×256 recommended) to the same folder.
{% endstep %}

{% step %}

### Submit a PR

Open a pull request. Once merged, the token will appear in the generated tokenlist.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
EVM addresses must be checksummed ([EIP-55](https://eips.ethereum.org/EIPS/eip-55)). For the full data schema and bridge mechanism types (`native`, `lock`, `mint`, `burn`), see the [mega-tokenlist README](https://github.com/megaeth-labs/mega-tokenlist#token-data-schema).
{% endhint %}


# Gas Estimation

How to estimate gas on MegaETH — code examples, toolchain configuration, and common pitfalls.

MegaETH's [dual gas model](/developer-docs/overview-3/gas-model) charges both compute gas and storage gas. Standard Ethereum toolchains are unaware of storage gas and will underestimate the gas a transaction needs. This page explains how to estimate gas correctly and avoid common errors.

## Why Standard Tooling Underestimates Gas

Ethereum toolchains like Foundry and Hardhat often run a local EVM to simulate transactions and estimate gas. These local EVMs do not implement MegaETH's storage gas, so they only account for compute gas. The result is an estimate that is too low — sometimes by a large margin.

For example, a simple Ether transfer costs 21,000 gas on Ethereum but **60,000 gas** on MegaETH (21,000 compute + 39,000 storage). A toolchain that estimates 21,000 will produce a transaction that fails with "intrinsic gas too low."

The fix is straightforward: **always use a MegaETH RPC endpoint for gas estimation** instead of relying on local simulation.

## Using `eth_estimateGas`

Calling `eth_estimateGas` on a MegaETH RPC endpoint is the recommended approach. The endpoint runs the transaction through MegaEVM and returns an accurate estimate that accounts for compute gas, storage gas, the bucket multiplier, and all resource dimensions.

{% tabs %}
{% tab title="curl" %}

```bash
curl -s https://mainnet.megaeth.com/rpc \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "eth_estimateGas",
    "params": [{
      "from": "0xYourAddress",
      "to": "0xContractAddress",
      "data": "0xCalldata"
    }],
    "id": 1
  }'
```

{% endtab %}

{% tab title="cast" %}

```bash
cast estimate 0xContractAddress \
  'myFunction(uint256)' 42 \
  --rpc-url https://mainnet.megaeth.com/rpc \
  --from 0xYourAddress
```

{% endtab %}
{% endtabs %}

Any Ethereum SDK (ethers.js, viem, alloy, web3.py, etc.) works the same way — just point it at a MegaETH RPC endpoint and call `estimateGas` as usual.

### Public RPC Simulation Limits

The public gateway adds a **60,000,000 compute-gas limit** to `eth_call` while preserving the caller's total `gas` field. `eth_estimateGas` uses a different protection: the gateway calls the node's CPU-limited estimator with a source-default budget of **500,000,000 nanoseconds (0.5 seconds)**. It does not add the same 60M compute-gas override to gas estimation.

An `eth_call` that exceeds its compute limit or an estimation that exceeds its CPU-time budget can fail even when the transaction's protocol gas limit would be valid. There are two workarounds:

1. **Set a manual gas limit.** Use the `--gas-limit` flag (see [Toolchain Configuration](#toolchain-configuration) below) to skip estimation entirely and submit the transaction with a known gas value. You can determine the right value by simulating the transaction locally with [`mega-evme`](/developer-docs/overview-1/debugging#using-mega-evme), which has no gas cap and fully implements MegaETH's gas model.
2. **Use a managed RPC provider with a higher cap.** Managed RPC providers may use different compute and CPU-time policies for `eth_call` and `eth_estimateGas`. See the [RPC Providers](/developer-docs/tooling#rpc-providers) table for providers that support MegaETH.

### Request Body Size for Large Deployments

Estimating gas for a large contract deployment sends the full initcode in the request body. To accommodate this, the public RPC endpoint allows `eth_call`, `eth_callMany`, `eth_createAccessList`, and `eth_estimateGas` bodies up to **1.5 MiB** — well above the 128 KiB limit applied to ordinary read methods. A request that exceeds this limit is rejected with HTTP `413` / `-32099` (`payload too large`). See [HTTP request and response limits](/developer-docs/rpc/operations-and-limits#http-request-and-response-limits) for the full breakdown.

## Toolchain Configuration

### Foundry

Foundry's `forge script` uses its own built-in EVM for local simulation, which does not account for MegaETH's storage gas. Pass `--skip-simulation` to bypass the local EVM — `forge script` will then call `eth_estimateGas` on the remote RPC before broadcasting each transaction:

```bash
forge script MyScript \
  --skip-simulation \
  --rpc-url https://mainnet.megaeth.com/rpc
```

For `cast send`, gas estimation goes through the remote RPC by default, so no special flags are needed. If you want to set a manual gas limit instead, pass `--gas-limit` to skip estimation entirely:

```bash
cast send 0xContractAddress \
  'myFunction(uint256)' 42 \
  --gas-limit 30000000 \
  --rpc-url https://mainnet.megaeth.com/rpc \
  --private-key $PRIVATE_KEY
```

## Common Errors

### "intrinsic gas too low"

The transaction's `gasLimit` is below the minimum intrinsic gas cost. On MegaETH, the minimum is **60,000** (21,000 compute + 39,000 storage), not 21,000 as on Ethereum.

**Fix:** Use `eth_estimateGas` on a MegaETH endpoint, or set `gasLimit` to at least 60,000.

### Out of gas from storage gas

The transaction ran out of gas because storage-heavy operations (contract creation, `SSTORE`, `LOG`) consumed more gas than expected. This typically happens when gas was estimated by a non-MegaETH-aware tool.

**Fix:** Use `eth_estimateGas` on a MegaETH endpoint. For contract deployments, note that code deposit costs **10,000 storage gas per byte** — a 24 KB contract costs roughly 240,000,000 storage gas alone.

### Out of gas from volatile data access

Accessing volatile data — `block.timestamp`, `block.number`, oracle storage — caps the transaction's compute gas to **20,000,000**. If the transaction performs heavy computation after reading volatile data, it may hit this cap and revert.

**Fix:** Split the work across multiple transactions so that only lightweight transactions (under 20M compute gas) access volatile data. See [Volatile Data Access](/developer-docs/overview-3/volatile-data) for the full list of triggers and best practices.

### Resource limit exceeded

MegaETH enforces per-transaction limits beyond gas: Data Size (12.5 MB), KV Updates (500,000), and State Growth (1,000). A transaction that stays within its gas budget can still fail if it exceeds one of these limits.

**Fix:** Reduce the number of state operations per transaction. See [Resource Limits](/developer-docs/overview-3/resource-limits) for the full table.

## Interpreting Gas in Receipts

The `gasUsed` field in a transaction receipt reports the **total gas consumed** — compute gas plus storage gas combined. MegaETH does not expose a per-dimension breakdown in the receipt.

This means `gasUsed` will be higher than what a standard Ethereum tool would predict for the same operations. If you need to debug which dimension caused a failure, see [Debugging Transactions](/developer-docs/overview-1/debugging) for how to replay a transaction with full tracing.

## Related Pages

* [Gas Model](/developer-docs/overview-3/gas-model) — how compute gas, storage gas, and the bucket multiplier work
* [EVM Differences](/developer-docs/overview-3) — volatile data caps, SSTORE refund changes, 98/100 forwarding
* [RPC Reference](/developer-docs/rpc/reference) — method availability and restrictions
* [Developer FAQ](/developer-docs/faq) — `eth_estimateGas` gas cap, block gas limit
* [Dual Gas Model (spec)](https://docs.megaeth.com/spec/megaevm/dual-gas-model) — formal specification of compute gas and storage gas
* [Resource Limits (spec)](https://docs.megaeth.com/spec/megaevm/resource-limits) — per-transaction and per-block limit enforcement


# Debugging Transactions

Debug failing transactions on MegaETH — trace with debug\_traceTransaction, replay with mega-evme, and diagnose gas errors.

MegaETH provides two ways to debug transactions:

1. **`debug_*` RPC methods** — trace transactions via JSON-RPC
2. **`mega-evme`** — replay or simulate transactions locally with full tracing

## Debug RPC Methods

The public MegaETH RPC endpoint supports tracing mined transactions and blocks. It does not support `debug_traceCall`; use [`mega-evme`](#simulating-a-new-transaction) for local call simulation or check whether a managed RPC provider exposes that method.

The following methods are supported:

* [**`debug_traceTransaction`**](/developer-docs/rpc/reference/debug_tracetransaction) — trace an already-mined transaction by hash
* [**`debug_traceBlockByNumber`**](/developer-docs/rpc/reference/debug_traceblockbynumber) / [**`debug_traceBlockByHash`**](/developer-docs/rpc/reference/debug_traceblockbyhash) — trace all transactions in a block

### Supported Tracers

| Tracer                  | `tracer` value          | Description                                                                  |
| ----------------------- | ----------------------- | ---------------------------------------------------------------------------- |
| Default (struct logger) | *(omit `tracer` field)* | Opcode-level trace with gas, stack, memory, and storage at each step         |
| callTracer              | `"callTracer"`          | Nested call tree with inputs, outputs, and gas usage per call                |
| prestateTracer          | `"prestateTracer"`      | Account state before execution; set `"diffMode": true` for before/after diff |
| flatCallTracer          | `"flatCallTracer"`      | Parity-style flat list of all calls                                          |

{% hint style="info" %}
JavaScript tracers are not supported.
{% endhint %}

For method parameters, tracer configuration options, and response formats, see the [geth debug namespace documentation](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug) and [built-in tracers reference](https://geth.ethereum.org/docs/developers/evm-tracing/built-in-tracers).

## Using mega-evme

[`mega-evme`](https://docs.megaeth.com/mega-evme) is a local CLI tool that uses the open-source [MegaEVM](https://github.com/megaeth-labs/mega-evm) implementation. It can perfectly simulate any transaction's behavior on MegaETH, including storage gas, compute gas caps, and resource limits.

Use `mega-evme` when you want full local control over tracing, deterministic replay, or what-if analysis with transaction overrides.

### Installation

```bash
git clone https://github.com/megaeth-labs/mega-evm.git
cd mega-evm
cargo build --release -p mega-evme
# Binary: target/release/mega-evme
```

### Replaying an On-Chain Transaction

Replay a transaction by its hash to see exactly what happened during execution:

```bash
mega-evme replay 0xYourTxHash \
  --rpc https://mainnet.megaeth.com/rpc \
  --trace \
  --tracer opcode
```

Use the **call tracer** for a higher-level view of the call tree:

```bash
mega-evme replay 0xYourTxHash \
  --rpc https://mainnet.megaeth.com/rpc \
  --trace \
  --tracer call \
  --trace.call.with-log
```

Use the **pre-state diff** to see exactly which storage slots and balances changed:

```bash
mega-evme replay 0xYourTxHash \
  --rpc https://mainnet.megaeth.com/rpc \
  --trace \
  --tracer pre-state \
  --trace.prestate.diff-mode
```

Save the trace to a file for later analysis:

```bash
mega-evme replay 0xYourTxHash \
  --rpc https://mainnet.megaeth.com/rpc \
  --trace \
  --tracer opcode \
  --trace.output trace.json
```

#### "What-if" Replay

Override transaction fields to test alternative scenarios without rebroadcasting:

```bash
# Replay with a higher gas limit
mega-evme replay 0xYourTxHash \
  --rpc https://mainnet.megaeth.com/rpc \
  --override.gas-limit 50000000 \
  --trace

# Replay with different calldata
mega-evme replay 0xYourTxHash \
  --rpc https://mainnet.megaeth.com/rpc \
  --override.input 0xNewCalldata \
  --trace
```

### Simulating a New Transaction

Simulate a transaction against live chain state by forking from an RPC endpoint:

```bash
mega-evme tx \
  --fork \
  --rpc https://mainnet.megaeth.com/rpc \
  --receiver 0xContractAddress \
  --input 0xCalldata \
  --sender 0xYourAddress \
  --trace \
  --tracer call
```

Fork from a specific block:

```bash
mega-evme tx \
  --fork \
  --rpc https://mainnet.megaeth.com/rpc \
  --fork.block 12345678 \
  --receiver 0xContractAddress \
  --input 0xCalldata \
  --trace
```

### Tracers

`mega-evme` supports three tracers, each giving a different level of detail. Pass `--tracer <type>` along with `--trace` to select one.

#### Opcode Tracer (`--tracer opcode`)

The default tracer. Produces a step-by-step log of every EVM opcode executed, including the program counter, opcode name, gas remaining, stack contents, memory, and storage changes at each step.

Use this when you need to pinpoint the exact instruction where a transaction fails — for example, identifying which `SSTORE` consumed unexpected storage gas, or confirming that a specific opcode triggered the volatile data compute gas cap. The output is verbose; use the flags below to reduce noise:

| Flag                                | Effect                                                    |
| ----------------------------------- | --------------------------------------------------------- |
| `--trace.opcode.disable-memory`     | Omit memory snapshots (significantly reduces output size) |
| `--trace.opcode.disable-stack`      | Omit stack contents                                       |
| `--trace.opcode.disable-storage`    | Omit storage changes                                      |
| `--trace.opcode.enable-return-data` | Include return data from calls                            |

#### Call Tracer (`--tracer call`)

Produces a nested call tree showing every `CALL`, `DELEGATECALL`, `STATICCALL`, and `CREATE` during execution, with gas usage, input/output data, and error messages for each frame.

Use this when you need to understand the high-level flow of a transaction — which contracts were called, in what order, and where a revert originated. Add `--trace.call.with-log` to include emitted event logs in the output, or `--trace.call.only-top-call` to show only the top-level call.

#### Pre-state Tracer (`--tracer pre-state`)

Captures a snapshot of all account state (balances, nonces, code, storage slots) that the transaction touched before execution began.

Use this when you need to understand the initial conditions that led to a specific outcome — for example, verifying what a storage slot contained before an `SSTORE` overwrote it. Add `--trace.prestate.diff-mode` to get a before/after diff showing exactly which balances, nonces, and storage slots changed.

## Common Debugging Scenarios

### Transaction Reverts with No Reason

Use the **callTracer** to find which internal call reverted and inspect its return data:

```bash
mega-evme replay 0xYourTxHash \
  --rpc https://mainnet.megaeth.com/rpc \
  --trace \
  --tracer call
```

Look for the deepest call with `"error": "Reverted"` in the output — its `output` field contains the ABI-encoded revert reason.

### Out of Gas from Storage Gas

If a transaction runs out of gas but the compute gas usage seems low, storage gas is likely the cause. Use the **opcode tracer** and look for `SSTORE`, `CREATE`, `LOG`, or calldata-heavy operations consuming unexpectedly large amounts of gas.

See [Gas Estimation](/developer-docs/overview-1/gas-estimation) for how to avoid this with proper estimation.

### Out of Gas from Volatile Data Access

Accessing `block.timestamp`, `block.number`, or oracle storage caps the transaction's compute gas to 20,000,000. If the trace shows execution halting after one of these reads, the transaction exceeded the 20M total compute gas cap imposed by volatile data access. Split the work across multiple transactions so that only lightweight transactions access volatile data.

See [Volatile Data Access](/developer-docs/overview-3/volatile-data) for the full list of triggers and best practices.

## Related Pages

* [Gas Estimation](/developer-docs/overview-1/gas-estimation) — estimate gas correctly and avoid common errors
* [EVM Differences](/developer-docs/overview-3) — volatile data caps, SSTORE refund changes, 98/100 forwarding
* [Gas Model](/developer-docs/overview-3/gas-model) — how compute gas and storage gas work
* [RPC Reference](/developer-docs/rpc/reference) — method availability and restrictions
* [Dual Gas Model (spec)](https://docs.megaeth.com/spec/megaevm/dual-gas-model) — formal specification of compute gas and storage gas
* [Gas Detention (spec)](https://docs.megaeth.com/spec/megaevm/gas-detention) — compute gas cap triggered by volatile data access
* [mega-evme](https://docs.megaeth.com/mega-evme) — full command reference, configuration, and cookbook


# Force Inclusion — Foundry

Force-include a transaction on MegaETH using Foundry (cast or forge) — step-by-step guide for scripted and automated submissions.

Force inclusion submits a transaction directly to the L1 OptimismPortal, bypassing the sequencer. This page covers the scripted path using [Foundry](https://getfoundry.sh/). For the Etherscan UI path, see [Force-include a transaction](/user-guide/force-inclusion).

## Contract addresses

{% tabs %}
{% tab title="Mainnet" %}

| Contract       | Chain              | Address                                      |
| -------------- | ------------------ | -------------------------------------------- |
| OptimismPortal | Ethereum (chain 1) | `0x7f82f57F0Dd546519324392e408b01fcC7D709e8` |
| {% endtab %}   |                    |                                              |

{% tab title="Testnet (Sepolia)" %}

| Contract       | Chain                             | Address                                      |
| -------------- | --------------------------------- | -------------------------------------------- |
| OptimismPortal | Ethereum Sepolia (chain 11155111) | `0xF68D900e1Cdec64a8f5Dc0Ee873A9E2879256b10` |
| {% endtab %}   |                                   |                                              |
| {% endtabs %}  |                                   |                                              |

## Step-by-step

Your L1 wallet address is preserved as the sender on MegaETH — so the same private key that holds tokens on MegaETH signs the L1 transaction.

{% stepper %}
{% step %}

#### Set environment variables

```bash
export PRIVATE_KEY=0x...
export TOKEN=...        # ERC-20 contract address on MegaETH
export RECIPIENT=...    # address to receive the tokens
export AMOUNT=...       # amount in wei

# Testnet
export PORTAL=0xF68D900e1Cdec64a8f5Dc0Ee873A9E2879256b10
export L1_RPC=https://ethereum-sepolia-rpc.publicnode.com
export L2_RPC=https://carrot.megaeth.com/rpc  # see Connect page for all RPC options

# Mainnet
# export PORTAL=0x7f82f57F0Dd546519324392e408b01fcC7D709e8
# export L1_RPC=<your Ethereum mainnet RPC>
# export L2_RPC=https://mainnet.megaeth.com/rpc
```

{% endstep %}

{% step %}

#### Check your L2 token balance

```bash
SENDER=$(cast wallet address --private-key $PRIVATE_KEY)
cast call $TOKEN "balanceOf(address)(uint256)" $SENDER --rpc-url $L2_RPC
```

{% endstep %}

{% step %}

#### Estimate L2 gas

Always query the MegaETH L2 RPC — MegaETH's dual gas model (compute + storage) means standard Ethereum tooling underestimates. Add 20% headroom to account for storage gas variance.

```bash
SENDER=$(cast wallet address --private-key $PRIVATE_KEY)

GAS_EST=$(cast estimate $TOKEN \
  "transfer(address,uint256)" $RECIPIENT $AMOUNT \
  --from $SENDER \
  --rpc-url $L2_RPC)

export GAS_LIMIT=$(( GAS_EST * 120 / 100 ))
echo "estimate: $GAS_EST   limit: $GAS_LIMIT"
```

For a standard ERC-20 `transfer()` on MegaETH the estimate is approximately 54,000 gas; a limit of 65,000 is sufficient.

{% hint style="warning" %}
The portal enforces a minimum `_gasLimit` based on calldata length (\~26,500 for a `transfer()` call). Values below the minimum revert with `SmallGasLimit`.
{% endhint %}
{% endstep %}

{% step %}

#### Encode the calldata

The `_data` field passed to `depositTransaction` is the function call you want to execute on L2, serialized into bytes (ABI-encoded). Use `cast calldata` to produce it:

```bash
CALLDATA=$(cast calldata "transfer(address,uint256)" $RECIPIENT $AMOUNT)
echo $CALLDATA
```

Example output:

```
0xa9059cbb000000000000000000000000<recipient>0000000000000000000000000000000000000000000000000de0b6b3a7640000
```

The first 4 bytes (`0xa9059cbb`) are the `transfer` function selector. The remaining 64 bytes are the ABI-encoded `recipient` address and `amount`.

For a plain ETH transfer with no contract call, set `_data` to `0x` and skip this step.
{% endstep %}

{% step %}

#### Submit depositTransaction on L1

{% tabs %}
{% tab title="cast" %}

```bash
cast send $PORTAL \
  "depositTransaction(address,uint256,uint64,bool,bytes)" \
  $TOKEN \
  0 \
  $GAS_LIMIT \
  false \
  $CALLDATA \
  --value 0 \
  --rpc-url $L1_RPC \
  --private-key $PRIVATE_KEY
```

{% endtab %}

{% tab title="forge script" %}
Create `script/ForceInclude.s.sol`:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import {Script} from "forge-std/Script.sol";

interface IOptimismPortal {
    function depositTransaction(
        address _to, uint256 _value, uint64 _gasLimit,
        bool _isCreation, bytes calldata _data
    ) external payable;
}

contract ForceInclude is Script {
    function run() external {
        address portal    = vm.envAddress("PORTAL");
        address token     = vm.envAddress("TOKEN");
        address recipient = vm.envAddress("RECIPIENT");
        uint256 amount    = vm.envUint("AMOUNT");
        uint64  gasLimit  = uint64(vm.envUint("GAS_LIMIT"));

        bytes memory data = abi.encodeWithSignature(
            "transfer(address,uint256)", recipient, amount
        );

        vm.startBroadcast();
        IOptimismPortal(portal).depositTransaction(
            token, 0, gasLimit, false, data
        );
        vm.stopBroadcast();
    }
}
```

```bash
forge script script/ForceInclude.s.sol \
  --rpc-url $L1_RPC \
  --broadcast \
  --private-key $PRIVATE_KEY
```

{% endtab %}
{% endtabs %}

The call emits a `TransactionDeposited` event on L1. Save the transaction hash to track the deposit.
{% endstep %}

{% step %}

#### Verify on L2

After 5–20 minutes, confirm the recipient's balance increased.

```bash
cast call $TOKEN "balanceOf(address)(uint256)" $RECIPIENT --rpc-url $L2_RPC
```

{% endstep %}
{% endstepper %}

## How it works

1. `depositTransaction` emits `TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData)` on L1.
2. MegaETH watches for these events and converts each one into a deposited transaction (type `0x7E`) to execute on L2.
3. The deposited transaction runs on L2 with your L1 wallet address as the sender (no address transformation is applied for regular wallets).
4. `_gasLimit` caps L2 execution gas. If unused, it is not refunded, but no ETH is charged on L1 for it — only the standard Ethereum gas fee for calling `depositTransaction` applies.
5. Setting `_value` forwards ETH to `_to`; it must equal `msg.value`.

For the formal deposit specification, see [Deposits](https://specs.optimism.io/protocol/deposits.html) in the OP Stack spec.


# Read from MegaETH

How to read current state, historical data, transactions, logs, and real-time updates from MegaETH.

MegaETH supports standard Ethereum JSON-RPC reads for accounts, contracts, blocks, transactions, receipts, and logs. Existing Ethereum libraries work without a MegaETH-specific read API.

The main difference is freshness. Requests using `latest` or `pending` read from MegaETH's streaming state, which advances as mini-blocks are produced. You can therefore read state updated within milliseconds without waiting for the next EVM block.

## Choose a read pattern

| Pattern                  | Use it for                                                                           | Starting point                                              |
| ------------------------ | ------------------------------------------------------------------------------------ | ----------------------------------------------------------- |
| HTTP JSON-RPC            | One-time reads, contract calls, simulations, and historical queries                  | [JSON-RPC](/developer-docs/rpc)                             |
| WebSocket subscriptions  | Push-based logs, pending transactions, block headers, mini-blocks, and state changes | [Realtime API](/developer-docs/overview-2/realtime-api)     |
| Concrete block selectors | Reproducible reads against a specific EVM block                                      | [Type reference](/developer-docs/rpc/types#block-selectors) |

Use HTTP for request-and-response workflows. Use WebSocket subscriptions when your application needs updates as they happen or wants to avoid polling.

## State freshness and block tags

| Selector                 | Data source                | Behavior                                                             |
| ------------------------ | -------------------------- | -------------------------------------------------------------------- |
| `latest`                 | Streaming state            | Includes state committed by the latest mini-block.                   |
| `pending`                | Streaming state            | Uses the same real-time state view as `latest`.                      |
| `safe`                   | EVM block state            | Reads the latest block considered safe.                              |
| `finalized`              | EVM block state            | Reads the latest finalized block.                                    |
| Hexadecimal block number | Historical EVM block state | Repeats the state view for that block when retained by the endpoint. |

No additional flag or header is required for real-time reads. Pass `latest` or `pending` to methods that accept a block selector.

Historical availability depends on the serving endpoint's retention. If an old state query returns code `4444`, see the [Error reference](/developer-docs/rpc/error-codes#historical-state-unavailable).

## Public gateway behavior

The public MegaETH endpoint applies operational policies in addition to each method's JSON-RPC contract. Account for these policies when choosing query size, concurrency, and retry behavior.

| Behavior                    | What to expect                                                                                                                                                                  | Details                                                                                                        |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| Rate limiting               | Read methods use per-IP tiers with fixed 10-second windows. A limited request returns HTTP `429` with JSON-RPC code `-32005`.                                                   | [Read rate limits](/developer-docs/rpc/operations-and-limits#read-rate-limits)                                 |
| Request and response limits | The default request-body limit is 128 KiB, large reads and simulations allow up to 1.5 MiB, batches contain at most 100 requests, and responses are limited to 50 MiB.          | [HTTP request and response limits](/developer-docs/rpc/operations-and-limits#http-request-and-response-limits) |
| Method-specific limits      | Expensive methods such as `eth_call`, `eth_callMany`, `eth_feeHistory`, and `eth_getLogs` have additional execution or result constraints.                                      | [Method-specific limits](/developer-docs/rpc/operations-and-limits#method-specific-limits)                     |
| Gateway caching             | Eligible reads may be served from the gateway's internal cache. Cache policy depends on the method and selector, and `Cache-Control: no-store` only controls downstream caches. | [Gateway caching](/developer-docs/rpc/operations-and-limits#gateway-caching)                                   |

Use bounded ranges and pagination for large log or historical queries. Retry `-32005` failures with exponential backoff and jitter instead of immediate repetition. Inspect `X-Workers-Cache-Status` when you need to determine whether an eligible response came from the gateway cache.

## Common tasks

* Read an account balance with [`eth_getBalance`](/developer-docs/rpc/reference/eth_getbalance).
* Read contract storage with [`eth_getStorageAt`](/developer-docs/rpc/reference/eth_getstorageat).
* Execute a read-only contract call with [`eth_call`](/developer-docs/rpc/reference/eth_call).
* Look up a transaction or receipt with [`eth_getTransactionByHash`](/developer-docs/rpc/reference/eth_gettransactionbyhash) and [`eth_getTransactionReceipt`](/developer-docs/rpc/reference/eth_gettransactionreceipt).
* Query emitted events with [`eth_getLogs`](/developer-docs/rpc/reference/eth_getlogs).
* Stream real-time updates with [`eth_subscribe`](/developer-docs/rpc/reference/eth_subscribe).

## Next steps

* [JSON-RPC](/developer-docs/rpc) explains request framing, shared types, errors, and public gateway limits.
* [RPC Reference](/developer-docs/rpc/reference) lists method availability and the complete method documentation.
* [Realtime API](/developer-docs/overview-2/realtime-api) explains mini-block-level reads and WebSocket subscriptions.
* [Operations and limits](/developer-docs/rpc/operations-and-limits) documents rate limits, request limits, caching, and WebSocket limits.


# Realtime API

MegaETH Realtime API — how to use MegaETH's low-latency extensions to Ethereum JSON-RPC for real-time data access.

MegaETH executes transactions as soon as they arrive at the sequencer and emits execution results within \~10 milliseconds. The Realtime API exposes these results through extensions to Ethereum JSON-RPC, so your application can react to on-chain events with minimal latency.

On a standard EVM chain, query methods like `eth_getBalance` or `eth_getTransactionReceipt` reflect state as of the most recent block — produced every few seconds. On MegaETH, these same methods reflect state as of the most recent [mini-block](/mini-block) — produced every \~10ms. No special parameters are needed; using `latest` or `pending` as the block tag automatically queries against the most recent mini-block.

{% hint style="info" %}
The Realtime API is an evolving standard. Additional functionality will be added based on feedback.
{% endhint %}

## Available Methods

| Method                                                                                     | What it does                                                                                           | Reference                                                                   |
| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- |
| [`eth_subscribe`](/developer-docs/rpc/reference/eth_subscribe)                             | Stream headers, logs, pending transactions, sync status, mini-blocks, and state changes over WebSocket | [Full reference](/developer-docs/rpc/reference/eth_subscribe)               |
| [`realtime_sendRawTransaction`](/developer-docs/rpc/reference/realtime_sendrawtransaction) | Submit a transaction and get the receipt back in one call — no polling                                 | [Full reference](/developer-docs/rpc/reference/realtime_sendrawtransaction) |

The following standard Ethereum methods also return real-time results on MegaETH — they query against the latest mini-block automatically when called with `latest` or `pending`:

| Method                      | What it does            |
| --------------------------- | ----------------------- |
| `eth_getBalance`            | Account balance         |
| `eth_getStorageAt`          | Contract storage slot   |
| `eth_getTransactionCount`   | Account nonce           |
| `eth_getCode`               | Contract bytecode       |
| `eth_call`                  | Simulate a call         |
| `eth_callMany`              | Simulate multiple calls |
| `eth_createAccessList`      | Generate an access list |
| `eth_estimateGas`           | Estimate gas            |
| `eth_getTransactionByHash`  | Transaction by hash     |
| `eth_getTransactionReceipt` | Transaction receipt     |

## Use Cases

### Instant transaction confirmation

**Problem:** Your dapp submits a transaction and needs the receipt immediately — polling `eth_getTransactionReceipt` adds latency and complexity.

**Solution:** Use [`realtime_sendRawTransaction`](/developer-docs/rpc/reference/realtime_sendrawtransaction). It submits the transaction and waits for the receipt in a single round-trip. The node's default wait is 5 seconds; an explicit timeout is capped at 3 seconds by the public gateway. Drop-in replacement for `eth_sendRawTransaction`.

### Streaming events for a live UI

**Problem:** Your frontend needs to update in real time as swaps, transfers, or game actions happen on-chain.

**Solution:** Subscribe to [`logs`](/developer-docs/rpc/reference/eth_subscribe#logs) over WebSocket with `fromBlock` and `toBlock` set to `"pending"`. Logs arrive within \~10ms of execution — fast enough for live trading dashboards, game UIs, and notification systems. Filter by contract address and topics to receive only the events you care about.

### Monitoring account state changes

**Problem:** You need to track balance or storage changes for specific accounts in real time (e.g., a liquidation bot watching collateral ratios).

**Solution:** Subscribe to [`stateChanges`](/developer-docs/rpc/reference/eth_subscribe#statechanges) with the account addresses you want to monitor. Each notification includes the updated balance, nonce, and any storage slots that changed.

### Building a block explorer or indexer

**Problem:** You need every transaction and receipt as soon as it's executed, not when the next EVM block is sealed.

**Solution:** Subscribe to [`miniBlocks`](/developer-docs/rpc/reference/eth_subscribe#miniblocks). Each notification contains the full set of transactions and receipts for that mini-block.

## How It Works

On standard EVM chains, query methods reflect state as of the most recent EVM block (produced every \~1 second on MegaETH, longer on other chains). On MegaETH, the Realtime API queries against the most recent mini-block instead — produced every \~10ms.

This means `eth_getBalance`, `eth_getTransactionReceipt`, `eth_call`, and other read methods return up-to-date results without any special parameters. Use `latest` or `pending` as the block tag and you get mini-block-level freshness automatically.

Mini-blocks carry the same preconfirmation guarantee as EVM blocks. The sequencer treats them identically — results returned by the Realtime API are not "tentative" or "unconfirmed." Each mini-block header is signed by the sequencer, making the commitment independently verifiable — see [Sequencer signatures](/mini-block#sequencer-signatures).

### Example: real-time balance query

At time T, Alice has 10 ETH. At T+100ms, she sends 1 ETH to Bob — the transaction is packaged into a mini-block at T+110ms.

* Bob calls `eth_getBalance(alice, "latest")` at T+110ms → **9 ETH** (reflects the mini-block).
* Charlie calls `eth_getBalance(alice, "0x64")` (a specific EVM block number) → **10 ETH** (the EVM block hasn't been sealed yet).

## Related Pages

* [Mini-Blocks](/mini-block) — understanding the two block types
* [RPC Reference](/developer-docs/rpc/reference) — full method availability and method documentation
* [Operations and limits](/developer-docs/rpc/operations-and-limits) — public gateway limits and caching behavior


# Transaction Execution

How MegaEVM differs from standard Ethereum — contract size limits, gas forwarding, and precompile overrides.

*MegaEVM* is MegaETH's execution environment. It is fully compatible with Ethereum smart contracts while introducing optimizations for MegaETH's unique architecture.

## Overview

MegaEVM builds on established standards. Its latest hardfork, *Rex5*, is based on [Optimism Isthmus](https://specs.optimism.io/protocol/isthmus/overview.html), which in turn is adapted from [Ethereum Prague](https://ethereum.org/roadmap/pectra/). This means:

* All standard Solidity contracts work on MegaETH.
* Standard development tools (Hardhat, Foundry, Remix, etc.) are compatible.
* Existing Ethereum libraries and patterns apply.

MegaEVM introduces a few changes to accommodate MegaETH's low fees and high capacity. The most important change is the *multidimensional gas model and resource limits*. In MegaEVM, transactions consume two types of gas: *compute gas*, which models computation at large and is identically defined as Ethereum's gas; and *storage gas*, a new concept that models the storage subsystem in particular. Similarly, MegaEVM caps resource usage of transactions and blocks using rules that each target an individual type of resource. Developers should consider these changes in contrast to Ethereum's EVM, where gas is the singular metric for metering and limiting resource consumption.

## Key Differences at a Glance

| Feature             | Ethereum       | MegaETH              | Remarks                                                                  |
| ------------------- | -------------- | -------------------- | ------------------------------------------------------------------------ |
| Max contract size   | 24 KB          | **512 KB**           |                                                                          |
| Max initcode size   | 48 KB          | **536 KB**           |                                                                          |
| Gas forwarding rule | 63/64          | **98/100**           | As defined in [EIP-150](https://eips.ethereum.org/EIPS/eip-150).         |
| Gas model           | Unidimensional | **Multidimensional** | Compute gas and storage gas. Compute gas is identical to Ethereum's gas. |
| Resource limits     | Unidimensional | **Multidimensional** | 4 limits in addition to total gas limit specified by sender.             |
| Base intrinsic gas  | 21,000         | **60,000**           | 21,000 compute gas plus 39,000 storage gas.                              |

For the full gas model details, see [Gas Model](/developer-docs/overview-3/gas-model).

## Access to Volatile Data

Reading volatile data — `block.timestamp`, `block.number`, oracle storage, or the beneficiary account — triggers a detention cap of additional **20,000,000 compute gas** from the point of access. This ensures transactions with external dependencies yield quickly and don't block parallel execution.

For the full list of triggers, best practices for structuring contracts around this cap, and Solidity examples, see [Volatile Data Access](/developer-docs/overview-3/volatile-data). For the formal specification, see [Gas Detention](https://docs.megaeth.com/spec/megaevm/gas-detention).

## Increased Contract Size Limit

MegaETH supports contracts up to **512 KB** in size, increased from 24 KB in Ethereum. For the formal specification, see [Contract Limits](https://docs.megaeth.com/spec/megaevm/contract-limits).

## `SELFDESTRUCT` with EIP-6780 Semantics

The `SELFDESTRUCT` opcode follows [EIP-6780](https://eips.ethereum.org/EIPS/eip-6780) semantics. It only destroys a contract when called within the same transaction that created the contract. In all other cases, `SELFDESTRUCT` behaves as a simple Ether transfer without destroying the contract or clearing its storage. For the formal specification, see [SELFDESTRUCT](https://docs.megaeth.com/spec/megaevm/selfdestruct).

## No Storage Gas Refund for SSTORE Resets

On Ethereum, resetting a storage slot to its original value within the same transaction refunds part of the gas. On MegaETH, storage gas is **not refunded** when a slot is set back to its original value — the full storage gas cost is still charged.

{% hint style="success" %}
Use transient storage ([EIP-1153](https://eips.ethereum.org/EIPS/eip-1153) `TSTORE`/`TLOAD`) for scratch data that only needs to persist within a transaction. This avoids storage gas costs entirely.
{% endhint %}

## "98/100" Rule for Gas Forwarding

MegaETH allows a caller to forward at most **98/100** of remaining gas to a callee. The parameter is 63/64 in Ethereum.

{% hint style="danger" %}
**Migration note:** Contracts that compute gas forwarding amounts assuming the standard 63/64 rule ([EIP-150](https://eips.ethereum.org/EIPS/eip-150)) will see different behavior. The parent call frame retains 2% instead of \~1.6%, so subcalls receive slightly less gas. Review any patterns that rely on precise gas forwarding calculations.
{% endhint %}

For the formal specification, see [Gas Forwarding](https://docs.megaeth.com/spec/megaevm/gas-forwarding).

## Precompile Gas Overrides

MegaETH inherits all precompiles from Optimism Isthmus, which includes Ethereum Prague precompiles, EIP-2537 BLS12-381 precompiles, and RIP-7212 P256VERIFY. Two precompiles have adjusted gas costs:

| Precompile           | Address | Cost Override                                                                                                     |
| -------------------- | ------- | ----------------------------------------------------------------------------------------------------------------- |
| KZG Point Evaluation | `0x0A`  | 100,000 gas (2× the standard Prague cost of 50,000)                                                               |
| ModExp               | `0x05`  | [EIP-7883](https://eips.ethereum.org/EIPS/eip-7883) gas schedule (raises the cost floor for large-exponent calls) |

For the formal specification, see [Precompiles](https://docs.megaeth.com/spec/megaevm/precompiles).

## Related Pages

* [Gas Model](/developer-docs/overview-3/gas-model) — full dual gas model and resource limits
* [System Contracts](/developer-docs/overview-3/system-contracts) — native oracle interface and high-precision timestamp
* [Volatile Data Access](/developer-docs/overview-3/volatile-data) — compute gas cap on volatile data reads
* [EVM Specification](https://docs.megaeth.com/spec/megaevm/overview) — formal normative specification


# Gas Model

MegaETH dual gas model — compute gas, storage gas, bucket multiplier, resource limits, and developer tips.

MegaETH uses a *multidimensional gas model* that separates gas costs into two categories:

* **Compute Gas**: Standard execution costs as defined in Ethereum's EVM
* **Storage Gas**: Additional costs for operations that create persistent data

The total gas of a transaction is the sum of its compute gas and storage gas.

## How Gas Limit, Compute Gas, and Storage Gas Relate

The `gas_limit` field in a transaction works the same as on Ethereum — it sets the maximum total gas the transaction may consume. Both compute gas and storage gas are deducted from this single budget. In addition, MegaEVM enforces a separate compute gas ceiling of 200,000,000 that caps only the compute portion. A transaction can be halted by either ceiling: the total `gas_limit` or the compute gas cap.

{% hint style="info" %}
**In practice:**

* **`gas_limit`:** Set this to cover your expected total gas (compute + storage). `eth_estimateGas` on a MegaETH endpoint accounts for both.
* **`gas_used` in receipts:** Reports total gas consumed (compute + storage combined).
* **Compute gas limit:** An invisible additional ceiling of 200,000,000. Most transactions stay well under it.
  {% endhint %}

### Transaction Intrinsic Costs

Every transaction pays a base cost before any execution begins:

| Component   | Cost       |
| ----------- | ---------- |
| Compute gas | 21,000     |
| Storage gas | 39,000     |
| **Total**   | **60,000** |

The RPC returns "intrinsic gas too low" when the transaction gas limit is below 60,000.

## Compute Gas Costs

For any operation, its compute gas cost in MegaEVM equals its gas cost in standard EVM. For example, updating a cold storage slot from zero to nonzero costs 22,100 gas in standard EVM, so the compute gas cost of that operation in MegaEVM is also 22,100. Every transaction incurs an intrinsic compute gas cost of 21,000, just as in Ethereum.

As a rule of thumb, the amount of compute gas a transaction burns equals the amount of gas it would burn in Ethereum's EVM.

## Storage Gas Costs

The storage gas cost of most operations is zero. The following table lists all operations where storage gas applies. Some storage gas calculations involve a parameter called *bucket multiplier* (denoted as m). The next section explains this concept.

| Operation                | Storage Gas Cost | Remarks                                                                                                                                         |
| ------------------------ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| Intrinsic                | 39,000           | Incurred by every transaction. Combined with the intrinsic compute gas cost of 21,000, the total intrinsic gas cost of a transaction is 60,000. |
| Zero-to-nonzero `SSTORE` | 20,000 × (m−1)   | Only applies to zero-to-nonzero writes.                                                                                                         |
| Account creation         | 25,000 × (m−1)   | Value transfer to empty account.                                                                                                                |
| Contract creation        | 32,000 × (m−1)   | `CREATE`/`CREATE2` operations.                                                                                                                  |
| Code deposit             | 10,000/byte      | Per byte of deployed bytecode.                                                                                                                  |
| `LOG` topic              | 3,750/topic      | Per topic in event.                                                                                                                             |
| `LOG` data               | 80/byte          | Per byte of event data.                                                                                                                         |
| Calldata (zero)          | 40/byte          | Per zero byte in transaction input.                                                                                                             |
| Calldata (nonzero)       | 160/byte         | Per nonzero byte in transaction input.                                                                                                          |
| EIP-7623 floor (zero)    | 100/byte         | [EIP-7623](https://eips.ethereum.org/EIPS/eip-7623) floor cost per zero byte in transaction input.                                              |
| EIP-7623 floor (nonzero) | 400/byte         | [EIP-7623](https://eips.ethereum.org/EIPS/eip-7623) floor cost per nonzero byte in transaction input.                                           |

All other operations not mentioned in the table incur no storage gas cost.

**Calldata floor cost:** [EIP-7623](https://eips.ethereum.org/EIPS/eip-7623) introduced a minimum ("floor") charge for calldata. After execution, if total gas consumed is less than the calldata floor cost, the transaction is charged the floor cost instead. MegaETH applies the same 10× storage gas multiplier to the floor cost (hence the 100/byte and 400/byte entries in the table above).

**Revert behavior for `LOG`:** `LOG` storage gas follows standard EVM gas semantics — gas spent in a reverted call frame is consumed and not refunded. However, the data size tracked for the `LOG` is rolled back on revert, since the log itself is discarded.

**Prefer transient storage or memory over persistent storage.** Allocating new storage slots costs storage gas and counts towards [resource limits](/developer-docs/overview-3/resource-limits). Use transient storage ([EIP-1153](https://eips.ethereum.org/EIPS/eip-1153) `TSTORE`/`TLOAD`) for data that only needs to persist within a transaction, or memory for data within a single call.

**Reuse storage slots.** Storage gas applies when changing a slot from zero to nonzero but not when overwriting a nonzero slot. If a slot will be freed and reallocated soon, consider keeping it nonzero to avoid the storage gas charge on the next write.

## Bucket Multiplier

Accounts and their storage slots are stored in segments of MegaETH's SALT state trie called "buckets." Buckets grow in size and capacity as they hold more data. The cost of writing new data to a bucket (creating new accounts or changing storage slots from zero to nonzero) varies based on its capacity, and such variation is reflected in storage gas costs in the form of the *bucket multiplier* (denoted as m).

The bucket multiplier of a bucket is defined as the ratio of its capacity to the minimum capacity of buckets:

```
Bucket Multiplier = Bucket Capacity / MIN_BUCKET_CAP
```

SALT's design ensures that the bucket multiplier is always an integer.

A few rules of thumb for developers:

* Unless a bucket has expanded to handle heavy storage needs, the bucket multiplier is typically 1.
* When the bucket multiplier is 1, `SSTORE`, account creation, and contract creation incur zero storage gas cost.
* Buckets expand as they fill up; the multiplier increases and storage gas costs rise.
* Developers typically do not need to consider the bucket multiplier when designing contracts.

Below are examples of storage gas costs at different bucket multiplier values.

| Operation                | m=1 | m=2    | m=4    |
| ------------------------ | --- | ------ | ------ |
| Zero-to-nonzero `SSTORE` | 0   | 20,000 | 60,000 |
| Account creation         | 0   | 25,000 | 75,000 |
| Contract creation        | 0   | 32,000 | 96,000 |

{% hint style="success" %}
**Gas estimation:** Use `eth_estimateGas` on a MegaETH RPC endpoint for accurate gas estimates. The endpoint accounts for SALT multipliers, storage gas, and all resource dimensions. Do not attempt to compute gas costs manually — the dynamic multiplier depends on on-chain SALT bucket state. See [Gas Estimation](/developer-docs/overview-1/gas-estimation) for code examples, toolchain configuration, and common pitfalls.
{% endhint %}

## Multidimensional Resource Limits

In addition to the gas limit, MegaEVM enforces four per-transaction and per-block resource limits: compute gas, data size, KV updates, and state growth. A transaction that stays within its gas budget can still fail if it exceeds one of these limits. See [Resource Limits](/developer-docs/overview-3/resource-limits) for the full limits table, enforcement behavior, and resource type definitions.

## Related Pages

* [Resource Limits](/developer-docs/overview-3/resource-limits) — per-transaction and per-block resource ceilings
* [EVM Differences](/developer-docs/overview-3) — full list of behavioral differences from Ethereum
* [Dual Gas Model (spec)](https://docs.megaeth.com/spec/megaevm/dual-gas-model) — formal specification of compute gas and storage gas
* [Resource Accounting (spec)](https://docs.megaeth.com/spec/megaevm/resource-accounting) — how counters are tracked per opcode


# Resource Limits

MegaETH resource limits — 7 per-transaction and per-block ceilings on gas, compute, data, KV updates, state growth, transaction size, and DA size.

MegaETH enforces seven resource limits on transactions and blocks.

| Resource                     | Per-Transaction | Per-Block      | How it changes       |
| ---------------------------- | --------------- | -------------- | -------------------- |
| **Gas**                      | 10,000,000,000  | 10,000,000,000 | Sequencer-configured |
| **Compute Gas**              | 200,000,000     | Unlimited      | Protocol constant    |
| **Data Size**                | 12.5 MB         | 12.5 MB        | Protocol constant    |
| **KV Updates**               | 500,000         | 500,000        | Protocol constant    |
| **State Growth**             | 1,000           | 1,000          | Protocol constant    |
| **Transaction Encoded Size** | 1 MB            | Unlimited      | Sequencer-configured |
| **DA Size**                  | Adaptive        | Adaptive       | Adaptive             |

Note: "Unlimited" means no dedicated per-block limit exists for that resource, but it is still implicitly bounded by other per-block limits such as block gas limit and DA size.

* **Protocol constants** can only change through a hardfork.
* **Sequencer-configured** values reflect the current mainnet configuration and may change without a hardfork.
* **Adaptive** values are adjusted by the sequencer at runtime, following the same mechanism as OP Stack's [DA Footprint Block Limit](https://specs.optimism.io/protocol/jovian/exec-engine.html#da-footprint-block-limit).

## Resource Definitions

* **Gas** — the total gas (compute + storage) a transaction may consume. Uses the same semantics as the block gas limit and transaction gas limit of standard Ethereum. See [Gas Model](/developer-docs/overview-3/gas-model).
* [**Compute Gas**](/developer-docs/overview-3/gas-model#compute-gas-costs) — the computational component of gas, identical to Ethereum's gas definition.
* **Data Size** — the total bytes that need to be transmitted and stored for a transaction, including calldata, event logs (topics and data), storage writes (40 bytes per write), account updates (40 bytes each), and deployed contract code.
* **KV Updates** — the number of distinct state entries (accounts and storage slots) modified by a transaction. Repeated updates to the same entry count as one.
* **State Growth** — the number of new state entries (accounts, storage slots, contracts) created by a transaction. Entries cleared before the transaction ends do not count.
* **Transaction Encoded Size** — the byte size of the RLP-encoded transaction.
* **DA Size** — the compressed size of the transaction's data for L1 data availability submission.

For Data Size, KV Updates, and State Growth, block-level usage is the sum of usage across all transactions in the block.

For formal definitions of resource limits and accounting, see [Resource Limits (spec)](https://docs.megaeth.com/spec/megaevm/resource-limits) and [Resource Accounting (spec)](https://docs.megaeth.com/spec/megaevm/resource-accounting).

## Enforcement

The seven limits are enforced at two different stages, which determines what happens when a transaction exceeds one.

### Before execution

**Gas**, **Transaction Encoded Size**, and **DA Size** are checked before a transaction enters a block. A transaction that exceeds any of these per-transaction limits is **rejected by the transaction pool** and never included in a block.

**Gas** and **DA Size** also have per-block limits. The block builder stops adding transactions once the block's cumulative gas or DA size reaches the limit.

### During execution

**Compute Gas**, **Data Size**, **KV Updates**, and **State Growth** are enforced while the transaction runs (see [formal spec](https://docs.megaeth.com/spec/megaevm/resource-limits)).

**Per-transaction**: when a transaction exceeds any of these four limits:

1. Execution halts immediately.
2. Any remaining gas is preserved and refunded to the sender.
3. The transaction is included in the block with status set to failed (status=0).
4. No state changes from the transaction are applied.

**Data Size**, **KV Updates**, and **State Growth** also have per-block limits, enforced during block building:

1. Before executing a transaction, the block builder checks whether any previous transaction has already caused the block to exceed a per-block limit. If so, the block is sealed and no more transactions are added.
2. Otherwise, the transaction is executed. If its execution causes the block to exceed a per-block limit, the transaction is still included — it is not reverted or discarded. Per-transaction limits still apply.
3. No further transactions will be added to the block after it exceeds any per-block limit.

The last transaction in a block is allowed to push the block's resource usage beyond the per-block limit. This maximizes block utilization by avoiding the waste of a valid transaction whose resource consumption can only be known after execution.

**Compute Gas** has no separate per-block limit. Since Compute Gas is a component of total gas, and each transaction's total gas counts towards the block gas limit, the cumulative Compute Gas in a block is implicitly bounded by the block gas limit.

## Related Pages

* [Gas Model](/developer-docs/overview-3/gas-model) — compute gas, storage gas, and the bucket multiplier
* [Gas Estimation](/developer-docs/overview-1/gas-estimation) — estimate gas correctly and avoid common errors
* [EVM Differences](/developer-docs/overview-3) — full list of behavioral differences from Ethereum
* [Resource Limits (spec)](https://docs.megaeth.com/spec/megaevm/resource-limits) — formal specification of limit enforcement
* [Resource Accounting (spec)](https://docs.megaeth.com/spec/megaevm/resource-accounting) — how counters are tracked per opcode


# Volatile Data Access

Volatile data access on MegaETH — what triggers the 20M compute gas cap, best practices for reading block data and oracle state, and common pitfalls.

MegaETH provides APIs for transactions to access *volatile data* — data that changes frequently and expires quickly after being accessed. This includes the current block metadata (block number, timestamp, coinbase), the beneficiary account state, and data from the [native oracle interface](/developer-docs/overview-3/system-contracts).

When a transaction reads volatile data, a dependency forms between it and other transactions that modify the same data. This harms parallel execution performance — for example, reading `block.number` prevents the sequencer from producing the next block until the reading transaction finishes.

To mitigate this, MegaEVM imposes a **detention cap of 20,000,000 compute gas** on the transaction once it accesses any volatile data source. The cap is relative: accessing volatile data allows **20M more** compute gas from the point of access, regardless of how much was consumed before. For example, a transaction that uses 15M compute gas before reading `block.timestamp` still has 20M of compute gas remaining (effective limit = 15M + 20M = 35M).

## What Triggers the Cap

### Block Environment Opcodes

Accessing any of these opcodes triggers a **20,000,000 compute gas** detention cap from the point of access.

| Opcode        | Description               |
| ------------- | ------------------------- |
| `NUMBER`      | Current block number      |
| `TIMESTAMP`   | Current block timestamp   |
| `COINBASE`    | Block beneficiary address |
| `PREVRANDAO`  | Previous block randomness |
| `GASLIMIT`    | Block gas limit           |
| `BASEFEE`     | Base fee per gas          |
| `BLOCKHASH`   | Historical block hash     |
| `BLOBBASEFEE` | Blob base fee             |
| `BLOBHASH`    | Blob hash lookup          |

### Beneficiary Account Access

Accessing the block beneficiary (coinbase) account in any way also triggers the cap:

| Trigger                                     | Description                             |
| ------------------------------------------- | --------------------------------------- |
| `BALANCE`, `SELFBALANCE`                    | Reading beneficiary's balance           |
| `EXTCODECOPY`, `EXTCODESIZE`, `EXTCODEHASH` | Accessing beneficiary's code            |
| Transaction sender is beneficiary           | When `msg.sender == block.coinbase`     |
| Transaction recipient is beneficiary        | When call target is `block.coinbase`    |
| `DELEGATECALL` to beneficiary               | Delegated context accessing beneficiary |

### Native Oracle Service

Reading oracle data via `SLOAD` from the oracle contract storage triggers the cap.

* Oracle contract address: `0x6342000000000000000000000000000000000001`
* Triggered by: `SLOAD` from oracle contract storage
* `DELEGATECALL` to the oracle contract does **not** trigger this limit

### Shared Cap

All volatile data sources share the same 20,000,000 compute gas detention cap. The first volatile read triggers the cap; subsequent reads of other volatile sources do not extend it.

## Best Practices

### Read volatile data as late as possible

Because the detention cap is measured from the point of access, deferring the volatile data read to the end of the transaction maximizes the computation you can perform.

```solidity
// Good: heavy computation first, volatile read last
function processAndCheckTime(uint256[] calldata items) external {
    for (uint i = 0; i < items.length; i++) {
        processItem(items[i]);
    }
    // Cap starts here — but the heavy work is already done
    require(block.timestamp <= deadline, "Expired");
}
```

```solidity
// Bad: reading volatile data first wastes the budget
function processWithTimestamp(uint256[] calldata items) external {
    uint256 currentTime = block.timestamp; // Cap starts immediately
    for (uint i = 0; i < items.length; i++) {
        processItem(items[i]);  // Competing with the 20M budget
    }
}
```

For the formal definition, see [Gas Detention](https://docs.megaeth.com/spec/megaevm/gas-detention).

### Split volatile reads and heavy computation into separate transactions

If your contract needs both volatile data and more than 20M compute gas of heavy computation after the volatile read, split the work across two transactions:

1. A lightweight transaction that reads volatile data and stores the result on-chain.
2. A separate transaction that reads the stored result and performs heavy computation — no cap applies because it never accesses volatile data.

## Related Pages

* [EVM Differences](/developer-docs/overview-3) — full list of MegaEVM behavioral differences
* [Gas Estimation](/developer-docs/overview-1/gas-estimation) — estimate gas correctly on MegaETH
* [Debugging Transactions](/developer-docs/overview-1/debugging) — trace gas consumption with mega-evme
* [Gas Detention (spec)](https://docs.megaeth.com/spec/megaevm/gas-detention) — formal specification of the gas detention mechanism


# System Contracts

MegaETH system contracts — addresses, interfaces, preconditions, and usage examples.

MegaETH provides system contracts that give transactions access to functionality beyond the standard EVM.

| Contract                                              | Address                                                                                                                           | Purpose                                              |
| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| [High-Precision Timestamp](#high-precision-timestamp) | [`0x6342000000000000000000000000000000000002`](https://megaeth.blockscout.com/address/0x6342000000000000000000000000000000000002) | Microsecond-resolution timestamps                    |
| [KeylessDeploy](#keyless-deployment)                  | [`0x6342000000000000000000000000000000000003`](https://megaeth.blockscout.com/address/0x6342000000000000000000000000000000000003) | Deterministic cross-chain deployment (Nick's Method) |
| [MegaAccessControl](#mega-access-control)             | [`0x6342000000000000000000000000000000000004`](https://megaeth.blockscout.com/address/0x6342000000000000000000000000000000000004) | Opt out of volatile data access detection            |
| [MegaLimitControl](#mega-limit-control)               | [`0x6342000000000000000000000000000000000005`](https://megaeth.blockscout.com/address/0x6342000000000000000000000000000000000005) | Query remaining compute gas budget                   |
| [SequencerRegistry](#sequencer-registry)              | [`0x6342000000000000000000000000000000000006`](https://megaeth.blockscout.com/address/0x6342000000000000000000000000000000000006) | System address and sequencer role registry           |

## Sequencer Registry

Tracks the current system address (Oracle and system-transaction authority) and the current sequencer (mini-block signing key). Rex5 introduces this contract. Most dapp code does not call it directly, but contracts and tools can read it when they need the canonical onchain source for either role.

**Address:** `0x6342000000000000000000000000000000000006`

For the formal specification, see [SequencerRegistry (spec)](https://docs.megaeth.com/spec/system-contracts/sequencer-registry).

## High-Precision Timestamp

Provides timestamps at microsecond resolution. The timestamp is the moment when the transaction *started* execution on the sequencer. Useful when `block.timestamp` (one-second resolution) is not granular enough.

{% hint style="info" %}
This timestamp is published by the sequencer based on its local clock. Using it requires trusting the sequencer to provide accurate time data.
{% endhint %}

**Address:** `0x6342000000000000000000000000000000000002`

**Interface:**

```solidity
interface IHighPrecisionTimestamp {
    /// @notice Returns the current timestamp in microseconds since Unix epoch.
    /// @return Microsecond-precision timestamp, non-decreasing within a block,
    ///         capped at block.timestamp × 1,000,000.
    function timestamp() external view returns (uint256);
}

IHighPrecisionTimestamp hpt = IHighPrecisionTimestamp(
    0x6342000000000000000000000000000000000002
);
uint256 timestampUs = hpt.timestamp(); // microsecond timestamp
uint256 timestampSec = timestampUs / 1_000_000; // convert to second timestamp
```

**Outcome:**

* Returns the current timestamp in microseconds since Unix epoch.
* Reading the timestamp accesses [volatile data](/developer-docs/overview-3/volatile-data) and **triggers the 20M compute gas detention cap**. Avoid reading it in transactions that perform heavy computation.

**Properties:**

| Property     | Value                                                                     |
| ------------ | ------------------------------------------------------------------------- |
| Precision    | 1 μs (1/1,000,000 second)                                                 |
| Range        | `(previous_block.timestamp × 1,000,000, block.timestamp × 1,000,000]`     |
| Monotonicity | Non-decreasing within a block                                             |
| Snapshot     | Stable within a single transaction — repeated reads return the same value |

**Common use cases:** HFT strategies, rate limiting, latency measurements, sub-second auctions, TWAP calculations.

## Keyless Deployment

Deploys a contract to a deterministic address using Nick's Method — a technique for deploying to the same address on every EVM chain without holding the deployer's private key.

On MegaETH, the original keyless deployment transaction would run out of gas because code deposit storage gas (10,000 gas/byte) makes deploying even a small contract far more expensive than on Ethereum. This system contract re-executes the original transaction with a caller-supplied gas limit override.

**Address:** `0x6342000000000000000000000000000000000003`

**Interface:**

```solidity
interface IKeylessDeploy {
    /// @notice Re-executes a pre-signed keyless deployment transaction with a custom gas limit,
    ///         deploying the contract to the same deterministic address as on any other EVM chain.
    /// @param keylessDeploymentTransaction RLP-encoded signed deployment transaction by Nick's Method.
    /// @param gasLimitOverride Gas limit to use instead of the original transaction's gas limit.
    /// @return gasUsed Actual gas consumed by the deployment.
    /// @return deployedAddress Address where the contract was deployed.
    /// @return errorData Empty on success; revert data on failure.
    function keylessDeploy(
        bytes calldata keylessDeploymentTransaction,
        uint256 gasLimitOverride
    ) external returns (uint64 gasUsed, address deployedAddress, bytes memory errorData);
}

IKeylessDeploy deployer = IKeylessDeploy(0x6342000000000000000000000000000000000003);
bytes memory originalTx = hex"f8a58085174876e800830186a08080b853604580600e...";
(uint64 gasUsed, address deployed,) = deployer.keylessDeploy(originalTx, 500_000);
```

**Preconditions:**

* `keylessDeploymentTransaction` must be a valid RLP-encoded Nick's Method deployment transaction: pre-EIP-155, contract creation (`to` = null), nonce = 0, with no trailing bytes after the signed payload.
* `gasLimitOverride` must be ≥ the original transaction's gas limit.
* The deployment address must not already contain code.
* The call must carry zero ETH value.
* The signer's balance must cover the inner transaction's `value` (zero for typical deployments) — the sandbox runs fee-free, so the signer needs no balance for gas.

**Outcome:**

* On success: returns `gasUsed`, `deployedAddress` (the deterministic address), and empty `errorData`.
* On deployment failure (e.g., out of gas): the call **does not revert**. It returns `gasUsed`, `deployedAddress = 0x0`, and `errorData` describing the failure. State changes from the attempted deployment are still applied, and the gas it consumed is charged to the outer call.

### Gas billing

The outer transaction pays for everything the sandboxed deployment does:

| Charge                 | Amount                                       | When                                                                        |
| ---------------------- | -------------------------------------------- | --------------------------------------------------------------------------- |
| Dispatch overhead      | 100,000 compute gas                          | Always — retained even if the deployment is rejected                        |
| Sandbox gas            | Exact gas used by the re-executed deployment | On every completed deployment attempt, success or failure                   |
| Signer materialization | New-account storage gas for the inner signer | Only if the signer account does not exist yet (one-time per signer address) |

Size the outer transaction's gas limit for `100,000 + sandbox gas used + signer materialization`, not just the inner deployment's own cost. `gasLimitOverride` is capped to the outer call's remaining gas, so the sandbox can never spend more than the outer transaction provides. The sandbox's resource usage (compute gas, data size, KV updates, and state growth) also counts toward the outer transaction's [resource limits](/developer-docs/overview-3/resource-limits).

The inner signer pays no gas: the sandbox runs fee-free, so the signer address needs no ETH beyond the inner transaction's `value` (zero for typical Nick's Method deployments). A consequence is that the `GASPRICE` opcode reads `0` inside the deployed contract's constructor.

{% hint style="danger" %}
**Migration note (Rex5):** before Rex5, the outer call was charged only the 100,000 gas dispatch overhead. Rex5 charges the full sandbox gas to the outer transaction — for storage-heavy deployments this raises the relayer-side gas budget by 10–100×.
{% endhint %}

{% hint style="warning" %}
Code deposit costs 10,000 storage gas per byte on MegaETH. A 24 KB contract costs roughly 240M storage gas. If `gasLimitOverride` is too low for this cost, the inner deployment will fail (out of gas) but the outer call still succeeds — check `errorData` and `deployedAddress`, and note the outer call is still charged the gas the failed attempt consumed. Simulate the transaction with [`mega-evme`](/developer-docs/overview-1/debugging#simulating-a-new-transaction) to find the required gas — it has no gas cap and fully implements MegaETH's gas model. Alternatively, use `eth_estimateGas` on a MegaETH endpoint (subject to the [public RPC simulation limits](/developer-docs/overview-1/gas-estimation#public-rpc-simulation-limits)).
{% endhint %}

{% hint style="info" %}
Deploying common keyless contracts (e.g., CREATE2 Factory, EIP-1820 Registry) can be expensive due to storage gas. If you need a widely-used contract deployed, reach out to the MegaETH team — it may already be deployed or the team can assist.
{% endhint %}

**Already-deployed contracts** (available on MegaETH via KeylessDeploy):

| Contract                                                                      | Deployed Address                                                                                                                  |
| ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| [CREATE2 Factory](https://github.com/Arachnid/deterministic-deployment-proxy) | [`0x4e59b44847b379578588920ca78fbf26c0b4956c`](https://megaeth.blockscout.com/address/0x4e59b44847b379578588920ca78fbf26c0b4956c) |
| [EIP-1820 Registry](https://eips.ethereum.org/EIPS/eip-1820)                  | [`0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24`](https://megaeth.blockscout.com/address/0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24) |

## Mega Access Control

Provides a proactive mechanism to prevent untrusted subcalls from accessing [volatile data](/developer-docs/overview-3/volatile-data). A contract can disable volatile data access for its entire call subtree before any untrusted code runs. Attempts to access volatile data while disabled revert immediately, preventing both the access and the [detention](/developer-docs/overview-3/volatile-data) side effect.

**Address:** `0x6342000000000000000000000000000000000004`

**Interface:**

Functions are declared `view` so they can be called from `view` contexts. The node intercepts these calls and tracks the restriction outside EVM storage, so no state modification occurs.

```solidity
interface IMegaAccessControl {
    function disableVolatileDataAccess() external view;
    function enableVolatileDataAccess() external view;
    function isVolatileDataAccessDisabled() external view returns (bool disabled);
}

IMegaAccessControl accessControl = IMegaAccessControl(
    0x6342000000000000000000000000000000000004
);
accessControl.disableVolatileDataAccess();
// All subcalls from this point cannot access volatile data.
// Attempts to read block.timestamp, oracle storage, etc. revert immediately.
```

**Outcome:**

* `disableVolatileDataAccess()` — disables volatile data access for the caller's call frame and all descendant call frames.
* `enableVolatileDataAccess()` — re-enables access, but only if the restriction was set at the caller's own depth. If a parent frame disabled access, the call reverts with `DisabledByParent()`.
* `isVolatileDataAccessDisabled()` — returns `true` if volatile data access is currently disabled.

The restriction automatically ends when the call frame that called `disableVolatileDataAccess` returns. No explicit cleanup is needed.

{% hint style="success" %}
Use MegaAccessControl when calling untrusted contracts to prevent them from silently triggering gas detention and tightening your gas budget.
{% endhint %}

**Common use cases:** DeFi protocols calling untrusted hooks, proxy contracts with user-supplied logic, batch execution of arbitrary calls.

## Mega Limit Control

Provides a runtime query for the effective remaining compute gas, accounting for both [gas detention](/developer-docs/overview-3/volatile-data) and per-call-frame resource budgets. The standard `GAS` opcode does not reflect these MegaETH-specific constraints.

**Address:** `0x6342000000000000000000000000000000000005`

**Interface:**

```solidity
interface IMegaLimitControl {
    function remainingComputeGas() external view returns (uint64 remaining);
}

IMegaLimitControl limitControl = IMegaLimitControl(
    0x6342000000000000000000000000000000000005
);
uint64 remaining = limitControl.remainingComputeGas();
// Use 'remaining' to decide whether to attempt a costly sub-call
```

**Outcome:**

* Returns the effective remaining compute gas for the caller's call frame at the time of the call.
* The returned value accounts for both the detention cap (if triggered) and the per-call-frame compute gas budget — it is the minimum of the two.
* The value is a point-in-time snapshot that decreases as execution proceeds.

**Common use cases:** Gas-aware batching (loop until budget exhausted), deciding whether to attempt expensive sub-calls, on-chain gas budgeting.

## Related Pages

* [Volatile Data Access](/developer-docs/overview-3/volatile-data) — compute gas cap, best practices for reading volatile data
* [System Contracts (spec)](https://docs.megaeth.com/spec/system-contracts/overview) — formal specification of the system contract registry
* [Oracle (spec)](https://docs.megaeth.com/spec/system-contracts/oracle) — underlying oracle contract that powers the High-Precision Timestamp and other services
* [KeylessDeploy (spec)](https://docs.megaeth.com/spec/system-contracts/keyless-deploy) — keyless deployment sandbox and validation rules
* [MegaAccessControl (spec)](https://docs.megaeth.com/spec/system-contracts/mega-access-control) — volatile data access restriction mechanism
* [MegaLimitControl (spec)](https://docs.megaeth.com/spec/system-contracts/mega-limit-control) — remaining compute gas query
* [SequencerRegistry (spec)](https://docs.megaeth.com/spec/system-contracts/sequencer-registry) — system address and sequencer role registry
* [Rex5 Upgrade (spec)](https://docs.megaeth.com/spec/upgrades/rex5) — full list of Rex5 behavior changes


# Build with AI

AI coding skills and tools for building on MegaETH with Claude Code, Cursor, Windsurf, and other AI assistants.

AI coding assistants can help you build on MegaETH faster — deploying contracts, integrating payments, interacting with DeFi protocols, and more. The community maintains a curated list of **AI coding skills** that teach your assistant MegaETH-specific patterns: the dual gas model, instant receipts via `realtime_sendRawTransaction`, mini-block subscriptions, and system contract usage.

Skills follow the [SKILL.md](https://docs.anthropic.com/en/docs/claude-code/skills) and [AGENTS.md](https://docs.agentsmd.dev) conventions and work with tools like Claude Code, Cursor, Windsurf, and OpenClaw.

## Available Skills

| Category               | Skills                                                                                        |
| ---------------------- | --------------------------------------------------------------------------------------------- |
| **General**            | End-to-end MegaETH development — Foundry setup, gas model, WebSocket subscriptions, debugging |
| **Payments**           | x402 HTTP payments, USDm stablecoin integration, Permit2 flows                                |
| **DeFi**               | Kumbaya DEX (Uniswap V3 fork) — swaps, quoting, liquidity, multi-hop routing                  |
| **Identity & Content** | .Mega Domains (naming service), WARREN (on-chain permanent web CMS)                           |
| **Agents**             | ERC-8004 Trustless Agents — on-chain identity, reputation, and validation                     |

For the full list with installation links and detailed descriptions, see the [**awesome-megaeth-ai**](https://github.com/megaeth-labs/awesome-megaeth-ai) repository.

## Getting Started

Most skills are single files you drop into your project. For example, with Claude Code:

```bash
# Add a MegaETH dev skill to your project
curl -o .claude/skills/megaeth-dev.md \
  https://raw.githubusercontent.com/0xBreadguy/megaeth-ai-developer-skills/main/SKILL.md
```

Your AI assistant will automatically pick up the skill and use it when relevant.

{% hint style="info" %}
These skills are community-contributed and are not endorsed by MegaETH Labs. Always review skill content before adding it to your project.
{% endhint %}


# Tooling & Infrastructure

Developer tooling and infrastructure partners on MegaETH — RPC providers, block explorers, oracles, indexers, bridges, wallets, account abstraction, developer tooling, and more.

## RPC Providers

| Provider       | Protocol           | Get Started                                                       | Public Endpoint                                           | Mainnet   |
| -------------- | ------------------ | ----------------------------------------------------------------- | --------------------------------------------------------- | --------- |
| MegaETH        | HTTP               | [Docs](https://docs.megaeth.com/developer-docs/overview-2)        | `https://mainnet.megaeth.com/rpc`                         | Supported |
| MegaETH        | WebSocket          | [Docs](https://docs.megaeth.com/developer-docs/overview-2)        | `wss://mainnet.megaeth.com/ws`                            | Supported |
| Alchemy        | HTTP               | [Docs](https://www.alchemy.com/docs/megaeth/megaeth-api-overview) | No public endpoint (API key required)                     | Supported |
| Alchemy        | WebSocket          | [Docs](https://www.alchemy.com/docs/megaeth/megaeth-api-overview) | No public endpoint (API key required)                     | Supported |
| QuickNode      | HTTP               | [Docs](https://www.quicknode.com/chains/megaeth)                  | No public endpoint (API key required)                     | Supported |
| QuickNode      | WebSocket          | [Docs](https://www.quicknode.com/chains/megaeth)                  | No public endpoint (API key required)                     | Supported |
| Nirvana Labs   | HTTP               | [Docs](https://docs.nirvanalabs.io)                               | No public endpoint (API key required)                     | Supported |
| Nirvana Labs   | WebSocket          | [Docs](https://docs.nirvanalabs.io)                               | No public endpoint (API key required)                     | Supported |
| dRPC           | HTTP               | [Docs](https://drpc.org/chainlist/megaeth-mainnet-rpc)            | `https://megaeth.drpc.org`                                | Supported |
| dRPC           | WebSocket          | [Docs](https://drpc.org/chainlist/megaeth-mainnet-rpc)            | `wss://megaeth.drpc.org`                                  | Supported |
| GlobalStake    | HTTP               | [Docs](https://globalstake.io)                                    | `https://rpc-megaeth-mainnet.globalstake.io`              | Supported |
| Liquify        | HTTP               | [Docs](https://portal.liquify.com/)                               | `https://gateway.liquify.com/api=MEGAETHM2ONGJ26QTI0N1N6` | Supported |
| Dwellir        | HTTP               | [Docs](https://www.dwellir.com/networks/megaeth)                  | No public endpoint (API key required)                     | Supported |
| Dwellir        | WebSocket          | [Docs](https://www.dwellir.com/networks/megaeth)                  | No public endpoint (API key required)                     | Supported |
| Envio HyperRPC | HTTP *(read-only)* | [Docs](https://docs.envio.dev/docs/HyperRPC/overview-hyperrpc)    | `https://megaeth.rpc.hypersync.xyz`                       | Supported |
| Chainstack     | HTTP               | [Docs](https://chainstack.com/build-better-with-megaeth/)         | No public endpoint (API key required)                     | Supported |

***

## Explorers

| Explorer                                     | Mainnet   |
| -------------------------------------------- | --------- |
| [Etherscan](https://mega.etherscan.io)       | Supported |
| [Blockscout](https://megaeth.blockscout.com) | Supported |
| [Explore Mega](https://exploremega.xyz)      | Supported |

***

## Oracles

| Provider                                  | Get Started                                             | Mainnet Contract                                                                                                                                                                    | Feeds                                                                                                                                                                                               | Mainnet   |
| ----------------------------------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| [Chainlink](https://chain.link)           | [Docs](https://docs.chain.link/)                        | [Data Streams](https://docs.chain.link/data-streams/supported-networks?streamsNetwork=mega), [Data Feeds](https://docs.chain.link/data-feeds/price-feeds/addresses?network=MegaETH) | [Data Streams](https://docs.chain.link/data-streams), [Data Feeds](https://docs.chain.link/data-feeds)                                                                                              | Supported |
| [Redstone](https://www.redstone.finance/) | [Docs](https://docs.redstone.finance/docs/introduction) | [Contract Addresses](https://app.redstone.finance/app/feeds/?networks=4326)                                                                                                         | [Push Model feeds](https://app.redstone.finance/app/feeds/?page=1\&sortBy=popularity\&sortDesc=false\&perPage=32), [Pull Model](https://app.redstone.finance/app/pull-model/redstone-primary-prod/) | Supported |
| [Pyth](https://www.pyth.network/)         | [Docs](https://docs.pyth.network/price-feeds)           | `0x2880aB155794e7179c9eE2e38200202908C17B43`                                                                                                                                        | [Price Feeds](https://docs.pyth.network/price-feeds/contract-addresses/evm)                                                                                                                         | Supported |
| [Stork](https://www.stork.network/)       | [Docs](https://docs.stork.network)                      | `0xacC0a0cF13571d30B4b8637996F5D6D774d4fd62`                                                                                                                                        | Real-time price feeds                                                                                                                                                                               | Supported |

***

## Indexers

| Indexer                           | Get Started                                                                      | Supported Services                                                                                                                                                                                                           | Mainnet   |
| --------------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| [Goldsky](https://goldsky.com)    | [Docs](https://docs.goldsky.com/chains/megaeth)                                  | [Subgraphs](https://docs.goldsky.com/chains/megaeth#subgraphs), [Mirror (Data Pipelines)](https://docs.goldsky.com/chains/megaeth#mirror)                                                                                    | Supported |
| [Envio](https://envio.dev/)       | [Docs](https://docs.envio.dev/docs/HyperIndex/contract-import)                   | [HyperIndex (Subgraphs)](https://docs.envio.dev/blog/how-to-index-megaeth-data-using-envio#hyperindex), [HyperSync (Data Access)](https://docs.envio.dev/blog/how-to-index-megaeth-data-using-envio#hypersync)               | Supported |
| [Mobula](https://mobula.io)       | [Docs](https://mobula.io/chain-mega)                                             | [Real-time Market & Wallet Data API](https://mobula.io/chain-mega), [Streams (WebSockets)](https://docs.mobula.io/indexing-stream/introduction)                                                                              | Supported |
| [The Graph](https://thegraph.com) | [Docs](https://thegraph.com/docs/en/supported-networks/megaeth/)                 | [Subgraphs](https://thegraph.com/docs/en/subgraphs/quick-start/)                                                                                                                                                             | Supported |
| [SQD](https://www.sqd.ai)         | [Docs](https://beta.docs.sqd.dev/en/data/evm/megaeth-mainnet/overview)           | [Subsquid data lake / Portal API](https://beta.docs.sqd.dev/en/data/evm/megaeth-mainnet/overview), [Squid SDK](https://github.com/subsquid-labs/squid-megaeth-example)                                                       | Supported |
| [GoldRush](https://goldrush.dev)  | [Docs](https://goldrush.dev/docs/chains/megaeth)                                 | [Foundational API](https://goldrush.dev/docs/goldrush-foundational-api), [Streaming API](https://goldrush.dev/docs/goldrush-streaming-api)                                                                                   | Supported |
| [Allium](https://allium.so)       | [Docs](https://docs.allium.so/historical-data/supported-blockchains/evm/megaeth) | [Historical Data](https://docs.allium.so/historical-data/supported-blockchains/evm/megaeth), [Realtime API](https://docs.allium.so/api/developer/overview), [Kafka Streams](https://docs.allium.so/api/datastreams/overview) | Supported |

***

## Data & Analytics

| Tool                                                                   | Mainnet   |
| ---------------------------------------------------------------------- | --------- |
| [Uptime Dashboard](https://uptime.megaeth.com)                         | Supported |
| [Dune Analytics](https://dune.com/blockchains/megaeth)                 | Supported |
| [Birdeye](https://birdeye.so/megaeth/find-gems)                        | Supported |
| [DexScreener](https://dexscreener.com/megaeth)                         | Supported |
| [Defined.fi](https://www.defined.fi/tokens/discover?network=mega)      | Supported |
| [Miniblocks](https://miniblocks.io)                                    | Supported |
| [DefiLlama](https://defillama.com/chain/megaeth)                       | Supported |
| [CoinGecko](https://www.coingecko.com/en/categories/megaeth-ecosystem) | Supported |
| [Grow The Pie](https://www.growthepie.com/chains/megaeth)              | Supported |

***

## Bridges & Interoperability

| Provider                                  | Get Started                                                                  | Mainnet   |
| ----------------------------------------- | ---------------------------------------------------------------------------- | --------- |
| [LayerZero](https://layerzero.network)    | [Docs](https://docs.layerzero.network)                                       | Supported |
| [Chainlink CCIP](https://chain.link/ccip) | [Docs](https://docs.chain.link/ccip/directory/mainnet/chain/megaeth-mainnet) | Supported |
| [Wormhole](https://wormhole.com)          | [Docs](https://docs.wormhole.com)                                            | Supported |
| [Hyperlane](https://hyperlane.xyz)        | [Docs](https://docs.hyperlane.xyz)                                           | Supported |
| [Across](https://across.to)               | [Docs](https://docs.across.to)                                               | Supported |
| [deBridge](https://debridge.finance)      | [Docs](https://docs.debridge.finance)                                        | Supported |
| [LiFi](https://li.fi)                     | [Docs](https://docs.li.fi)                                                   | Supported |
| [Socket](https://socket.tech)             | [Docs](https://docs.socket.tech)                                             | Supported |
| [Relay](https://relay.link)               | [Docs](https://docs.relay.link)                                              | Supported |
| [GasZip](https://www.gas.zip)             | [Docs](https://www.gas.zip)                                                  | Supported |

***

## Account Abstraction & Smart Accounts

| Provider                                       | Type                                | Get Started                                         | Mainnet   |
| ---------------------------------------------- | ----------------------------------- | --------------------------------------------------- | --------- |
| [ZeroDev](https://zerodev.app)                 | Kernel smart accounts (ERC-4337)    | [Docs](https://docs.zerodev.app)                    | Supported |
| [Privy](https://privy.io)                      | Embedded wallets / headless signing | [Docs](https://docs.privy.io)                       | Supported |
| [Safe](https://safe.global)                    | Multisig / smart account            | [Docs](https://docs.safe.global)                    | Supported |
| [MetaMask Smart Accounts](https://metamask.io) | Smart Accounts                      | [Docs](https://docs.metamask.io/smart-accounts-kit) | Supported |

***

## Wallets

| Wallet                                   | Type                          | Mainnet   |
| ---------------------------------------- | ----------------------------- | --------- |
| [MetaMask](https://metamask.io)          | Browser / mobile              | Supported |
| [Zerion](https://zerion.io)              | Mobile / web portfolio wallet | Supported |
| [Rainbow](https://rainbow.me)            | Mobile wallet                 | Supported |
| [Bitget Wallet](https://web3.bitget.com) | Mobile / web wallet           | Supported |
| [imToken](https://token.im)              | Mobile wallet                 | Supported |

***

## Developer Tooling

| Tool                                                 | Type                               | Get Started                                                                        | Mainnet   |
| ---------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------- | --------- |
| [Tenderly](https://tenderly.co)                      | Debugging, simulation, alerts      | [Docs](https://docs.tenderly.co)                                                   | Planned   |
| [mega-evm](https://github.com/megaeth-labs/mega-evm) | EVM debugger / tx replay           | [Docs](https://github.com/megaeth-labs/mega-evm/blob/main/bin/mega-evme/README.md) | Supported |
| [Blocksec Phalcon](https://blocksec.com/phalcon)     | Transaction debugging & simulation | [App](https://blocksec.com/phalcon/explorer)                                       | Supported |

***

## Security & Compliance

| Provider                                              | Type                                   | Mainnet   |
| ----------------------------------------------------- | -------------------------------------- | --------- |
| [Chainalysis / Hexagate](https://www.chainalysis.com) | Blockchain analytics, threat detection | Supported |
| [TRM Labs](https://www.trmlabs.com)                   | Transaction risk & compliance          | Supported |
| [Cipherowl](https://cipherowl.ai)                     | On-chain security analytics            | Supported |

***

## On-Ramps & Payments

| Provider                             | Type                               | Get Started                       | Mainnet   |
| ------------------------------------ | ---------------------------------- | --------------------------------- | --------- |
| [Transak](https://transak.com)       | Fiat on-ramp                       | [Docs](https://docs.transak.com)  | Supported |
| [Ramp Network](https://ramp.network) | Fiat on-ramp                       | [Docs](https://docs.ramp.network) | Supported |
| [Meridian](https://mrdn.finance/)    | x402 micropayments (agent economy) | —                                 | Supported |
| [Halliday](https://halliday.xyz)     | Crypto payments, onramps & swaps   | [Docs](https://docs.halliday.xyz) | Supported |

***

## Custody

| Provider                                   | Mainnet   |
| ------------------------------------------ | --------- |
| [Fireblocks](https://www.fireblocks.com)   | Supported |
| [Anchorage Digital](https://anchorage.com) | Supported |
| [BitGo](https://bitgo.com)                 | Supported |

***


# Verifiable Randomness (VRF)

Verifiable onchain randomness on MegaETH via DrandOracleQuicknet — a preinstalled, stateless BLS12-381 verifier for the public drand quicknet beacon.

MegaETH ships with a preinstalled verifiable random function (VRF) service: [DrandOracleQuicknet](https://github.com/Zodomo/DrandVerifier), a stateless BLS12-381 signature verifier deployed at a fixed address on each MegaETH network. Any contract can consume it. The randomness itself comes from [drand](https://drand.love), a public randomness beacon independently produced by a global network of participants and freely downloadable over HTTP.

At the highest level:

1. Your app commits to a specific future drand round.
2. Anyone — user, relayer, keeper, bot — fetches that round's signature from the public `api.drand.sh` once it's published.
3. They submit it in a transaction; `DrandOracleQuicknet.verifyNormalized(round, sig)` checks the BLS pairing onchain and returns a canonical 32-byte random value.

{% hint style="info" %}
For a complete worked example — contract, tests, and an end-to-end shell demo — see the [Drand VRF Lottery](https://github.com/megaeth-labs/documentation/blob/main/docs/dev/examples/vrf-drand-quicknet-lottery/README.md).
{% endhint %}

## What is VRF?

A verifiable random function produces a random value together with a **proof** of its validity. Given the proof and a public verification key, anyone can independently check three properties:

* **Correctness.** The value was produced according to the VRF's public rules — no one can forge it.
* **Uniqueness.** For any given input, there is exactly one valid output. The producer cannot choose among alternatives to bias the result.
* **Unpredictability.** Before the proof is published, the value is indistinguishable from random.

For onchain use, the property that matters most is *public verifiability*: the proof is small enough that a smart contract can check it directly, without trusting the producer.

## The VRF service on MegaETH

`DrandOracleQuicknet` is pre-deployed at a known address on each MegaETH network. Treat it the way you'd treat `ecrecover` — a stateless verification function your contract can call without owning or operating anything.

Source and full ABI: [Zodomo/DrandVerifier](https://github.com/Zodomo/DrandVerifier).

### Addresses

| Network         | Chain ID | `DrandOracleQuicknet`                        |
| --------------- | -------- | -------------------------------------------- |
| MegaETH Mainnet | 4326     | `0x7a53a6eFA81c426838fcf4824E6e207923969b36` |
| MegaETH Testnet | 6343     | `0x4e1673dcAA38136b5032F27ef93423162aF977Cc` |

### What it is (and isn't)

* A regular Solidity contract at the address above — not an EVM precompile. You interact with it like any other contract via normal `CALL` / `STATICCALL`.
* Completely stateless. Every call is a pure verification against hardcoded drand parameters (group public key, period, genesis, scheme). It has no owner, no upgrade path, no pause, and no storage that tracks anything per-caller.
* Identical on every MegaETH network. Same source, same configuration (drand quicknet: 3-second period, G1 signatures). Only the deployed address changes per network.

### Underlying protocol

The verifier speaks drand quicknet (`bls-unchained-g1-rfc9380`), a drand subnet that signs a new round every **three seconds**. Each beacon is a 48-byte compressed G1 BLS12-381 signature over `sha256(uint64 round, big-endian)` under a fixed threshold-BLS group public key. The verifier checks each signature with a pairing check through EIP-2537 BLS12-381 precompiles — which MegaETH supports natively.

For the protocol spec and security model, see the [drand developer docs](https://docs.drand.love/developer/).

## What is drand?

**drand** is a public randomness beacon produced by the "League of Entropy" — a coalition of independent organizations (Cloudflare, Protocol Labs, EPFL, universities, and more).

Every few seconds, drand participants each sign a predetermined message (derived from the round number) with their BLS key share. Once enough shares arrive, anyone can combine them into a single valid BLS signature under the group public key. That signature **is** the beacon. Hashing it yields a 32-byte random value.

This gives three properties that matter for onchain randomness:

* **Publicly verifiable.** Anyone with the group public key can check any beacon.
* **Unpredictable.** The output is unknown until enough honest participants sign — no single party can predict it.
* **Unbiasable.** BLS signatures are deterministic; even a threshold majority cannot cherry-pick among outputs, only decide whether to produce one.

drand has multiple networks. MegaETH's `DrandOracleQuicknet` targets the **quicknet** scheme specifically — the 3-second unchained subnet with G1 signatures. Details on protocol variants are in the [drand protocol specification](https://docs.drand.love/docs/specification/).

## How to use `DrandOracleQuicknet`

Source, full ABI, and test vectors live at [Zodomo/DrandVerifier](https://github.com/Zodomo/DrandVerifier) — start there if you need anything beyond the summary below.

### API surface

| Function                                                               | Purpose                                                                                                                                                                |
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PERIOD_SECONDS() → uint64`                                            | Returns `3` — the drand quicknet period.                                                                                                                               |
| `GENESIS_TIMESTAMP() → uint64`                                         | Returns `1692803367` — the Unix timestamp of round 1.                                                                                                                  |
| `roundMessageHash(uint64 round) → bytes32`                             | The 32-byte digest drand signs for a given round. Useful for offchain proof construction.                                                                              |
| `verify(uint64 round, bytes sig) → bool`                               | Runs the pairing check. Reverts on malformed signature bytes.                                                                                                          |
| `safeVerify(uint64 round, bytes sig) → bool`                           | Same, but returns `false` instead of reverting on malformed input.                                                                                                     |
| `verifyAPI(string json) → bool`                                        | Accepts a raw `api.drand.sh` JSON payload and verifies it. Convenient, costs extra gas for JSON parsing.                                                               |
| `verifyNormalized(uint64 round, bytes sig) → (bool, bytes32, bytes32)` | Verifies and, if valid, returns `(true, normalizedRoundHash, chainScopedHash)`. Encoding-invariant — the correct choice when you derive randomness from the signature. |

{% hint style="success" %}
For randomness consumption, use `verifyNormalized`. It returns a canonical random value independent of whether the submitter handed you compressed or uncompressed signature bytes.
{% endhint %}

### Minimal pattern

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.34;

interface IDrandOracleQuicknet {
    function PERIOD_SECONDS() external pure returns (uint64);
    function GENESIS_TIMESTAMP() external pure returns (uint64);
    function verifyNormalized(uint64 round, bytes calldata sig)
        external view returns (bool, bytes32, bytes32);
}

contract RandomizedApp {
    IDrandOracleQuicknet constant VRF =
        IDrandOracleQuicknet(0x4e1673dcAA38136b5032F27ef93423162aF977Cc); // MegaETH Testnet

    uint64 public revealRound; // 0 = open / not yet committed
    bool public settled;
    bytes32 public randomness;

    uint64 constant MIN_FUTURE_ROUNDS = 2; // on MegaETH; larger on slower chains

    /// Step 1: commit to a drand round that has NOT YET been signed.
    function commit() external {
        require(revealRound == 0 || settled, "in flight");
        uint64 period = VRF.PERIOD_SECONDS();
        uint64 genesis = VRF.GENESIS_TIMESTAMP();
        uint64 currentRound = uint64((block.timestamp - genesis) / period) + 1;
        revealRound = currentRound + MIN_FUTURE_ROUNDS;

        // Defensive tripwire: always holds while MIN_FUTURE_ROUNDS >= 1, but
        // reverts visibly if the constant is ever lowered to 0 or if someone
        // refactors the offset formula into a buggy state. See Security
        // caveats §1.
        uint256 publishTime = genesis + uint256(revealRound - 1) * period;
        require(publishTime > block.timestamp, "round already producible");

        settled = false;

        // Any app input that influences the outcome MUST be locked here too.
    }

    /// Step 2: after publishTime, anyone submits the beacon signature.
    function reveal(bytes calldata sig) external {
        require(revealRound != 0 && !settled, "not settlable");
        uint64 period = VRF.PERIOD_SECONDS();
        uint64 genesis = VRF.GENESIS_TIMESTAMP();
        uint256 publishTime = genesis + uint256(revealRound - 1) * period;
        require(block.timestamp >= publishTime, "round not published yet");

        settled = true; // checks-effects-interactions: flip before external call.

        // We take the 3rd return (chainScopedHash): chain- and contract-bound,
        // so the same beacon can't be replayed across chains or contracts.
        (bool ok,, bytes32 r) = VRF.verifyNormalized(revealRound, sig);
        require(ok, "bad signature");

        randomness = r;
        // ... consume r (e.g. choose a winner, derive a secret, mint an NFT trait, ...)
    }
}
```

Under 50 lines, and the only external dependency is the address constant.

### Fetching the beacon offchain

The drand API is public, unauthenticated, and served by multiple independent relays. Any of the paths below work — the JSON shape is identical.

{% tabs %}
{% tab title="curl" %}

```bash
# Get the round you committed to (replace 27985651 with yours).
curl -fsSL "https://api.drand.sh/v2/chains/52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971/rounds/27985651"

# {"round":27985651,"signature":"b3548e49211c5285c23420d01f4be07ef60d55680f1d609191524aa3e4089360ad869393f6a7b28451617e3acbf0c58f"}
```

{% endtab %}

{% tab title="cast" %}

```bash
# Call reveal on your contract with the fetched signature.
SIG=$(curl -fsSL "https://api.drand.sh/v2/chains/52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971/rounds/$ROUND" \
  | jq -r '.signature')

cast send $MY_CONTRACT "reveal(bytes)" "0x$SIG" \
  --rpc-url $MEGAETH_RPC --private-key $PRIVATE_KEY
```

{% endtab %}

{% tab title="viem" %}

```typescript
import { createWalletClient, http } from "viem";

const response = await fetch(
  `https://api.drand.sh/v2/chains/52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971/rounds/${round}`,
);
const { signature } = await response.json();

await walletClient.writeContract({
  address: MY_CONTRACT,
  abi: MY_ABI,
  functionName: "reveal",
  args: [`0x${signature}` as `0x${string}`],
});
```

{% endtab %}
{% endtabs %}

The drand quicknet chain hash `52db9ba7…0c84e971` is fixed — don't change it.

### Timing

drand quicknet publishes a **new beacon every 3 seconds**, deterministically. Round `N` becomes signable at `GENESIS_TIMESTAMP + (N - 1) * 3` seconds (Unix), where `GENESIS_TIMESTAMP = 1692803367`. This cadence is fixed — there is no faster round under quicknet, so 3 s is the irreducible unit of VRF latency.

A single VRF cycle walks through four stages:

| Stage              | Happens at                             | Typical wait                      |
| ------------------ | -------------------------------------- | --------------------------------- |
| Commit tx included | `t₀` — your dapp picks `revealRound`   | one MegaETH mini-block (\~10 ms)  |
| Round produced     | `t₁ = GENESIS + (revealRound − 1)·3 s` | 1–2 drand periods (3–6 s from t₀) |
| Beacon live on API | `t₂ ≈ t₁ + <1 s`                       | threshold BLS aggregation latency |
| Reveal tx included | `t₃` — submitter sends `reveal(sig)`   | one MegaETH mini-block (\~10 ms)  |

#### Minimum realistic VRF time

With `revealRound = currentRound + 2` (the default in the [Drand VRF Lottery](https://github.com/megaeth-labs/documentation/blob/main/docs/dev/examples/vrf-drand-quicknet-lottery/README.md)), end-to-end is **\~4–7 s** from commit to settled randomness. The wide range comes from where in a 3-second round your commit tx lands: commit just before a round boundary and you wait nearly 3 s (one period); commit just after and you wait nearly 6 s (two periods).

{% hint style="warning" %}
Don't set `revealRound = currentRound + 1`. If your commit tx lands in the tail of the current round, drand may have already signed the next one by the time it's confirmed on MegaETH — defeating the "future round" property. `revealRound ≥ currentRound + 2` gives you a full round of slack against timestamp races and mini-block reordering.
{% endhint %}

For apps that don't need low latency (weekly draws, cross-epoch reveals, cooldown periods) set `revealRound` further out to buy larger safety margins, at a direct 3-seconds-per-round cost.

### Worked example

The [Drand VRF Lottery](https://github.com/megaeth-labs/documentation/blob/main/docs/dev/examples/vrf-drand-quicknet-lottery/README.md) is a complete Foundry project — `src/DrandLottery.sol`, test suite, deploy scripts, and an `./script/demo.sh` that drives the full lifecycle end-to-end against a real MegaETH network. Clone it if you want something you can run immediately.

## Security caveats

`DrandOracleQuicknet` answers exactly one question: "is this a valid drand beacon for this round?". Everything else — when to consume it, which round to use, how to lock application inputs — is your contract's responsibility. Get these three things right and you're safe; get any one wrong and the cryptography cannot save you.

The caveats below cover **integration-level** concerns — what your consuming contract must do to make drand randomness safe to use. For **protocol-level** concerns that sit below our layer — drand's threshold-honesty assumption, front-running by malicious drand nodes, DoS and liveness bounds, DKG assumptions — see drand's own [Security Model](https://docs.drand.love/docs/security-model/). Your contract inherits those assumptions by consuming drand; they are not things `DrandOracleQuicknet` can enforce.

### 1. Commit to a future round and lock every outcome-relevant input at commit time

{% hint style="danger" %}
The round you consume must be one drand has **not yet signed** at commit time, and the entrant set, stakes, tier choices, or anything else that affects the outcome must all be pinned in the same transaction.
{% endhint %}

drand beacons are public. If you pick the current round, or leave any outcome-relevant input mutable after commit, the submitter can read the beacon offchain and only proceed when the result favors them. Three concrete rules your commit logic must enforce:

* **Derive `revealRound` from `block.timestamp + safety margin`.** Use `currentRound + MIN_FUTURE_ROUNDS` with `MIN_FUTURE_ROUNDS ≥ 2` on MegaETH (larger on slower chains — see [Timing](#timing)).
* **Make failure loud with an explicit require.** Inside `commit`, after computing `revealRound`, assert:

  ```solidity
  uint64 genesis = VRF.GENESIS_TIMESTAMP();
  uint64 period = VRF.PERIOD_SECONDS();
  uint256 publishTime = genesis + uint256(revealRound - 1) * period;
  require(publishTime > block.timestamp, "round already producible");
  ```

  Without this check, a stale or adversarial `block.timestamp` (miner drift, reorg, arithmetic edge case) can silently produce a `revealRound` that drand has already signed — the tx succeeds, no revert, but an attacker watching `api.drand.sh` has already seen the outcome. The `require` turns a silent security break into a visible revert.
* **Pin an exact round, not "≥ committedRound".** Reject any reveal whose round argument doesn't match the stored `revealRound` exactly; otherwise the submitter gets to pick among several already-produced rounds.

And **freeze application state** — entrant set, stakes, tier choices, any outcome-relevant input — in the same commit transaction. An input that can still move after commit gives the submitter adaptivity even if the round itself is properly pinned.

### 2. Own the state the verifier doesn't

{% hint style="danger" %}
`DrandOracleQuicknet` is stateless by design. Replay prevention, freshness checks, and encoding canonicalization are all on your consuming contract.
{% endhint %}

Three things your contract must do that the verifier will not:

* **Freshness:** require `block.timestamp >= publish_time(revealRound)` in `reveal` so a premature submission cannot succeed by accident.
* **Replay:** flip a `settled` / `consumed` storage flag before the external verify call (checks-effects-interactions), so the same beacon cannot be consumed twice.
* **Encoding:** use `verifyNormalized`. The same valid G1 point can be encoded as 48 bytes (compressed) or 96 bytes (uncompressed); if you hash raw signature bytes yourself, the submitter gets to choose between two different random values. `verifyNormalized` hashes the canonical uncompressed point so both encodings produce the same output.

### 3. Handle drand stalls explicitly

{% hint style="warning" %}
drand can miss a round — network outages and DKG incidents happen. A contract that waits forever for a stalled round is a bricked contract.
{% endhint %}

Add an expiry or fallback path so the game can resolve if the beacon never arrives. For example, a cancel-and-refund function gated by `block.timestamp >= publishTime + STALL_WINDOW`, or retry against a later round. See the [DoS scenarios](https://docs.drand.love/docs/security-model/#dos-the-drand-network) in drand's security model for how long such stalls can plausibly last.

## References

* [Drand VRF Lottery example](https://github.com/megaeth-labs/documentation/blob/main/docs/dev/examples/vrf-drand-quicknet-lottery/README.md) — runnable consumer contract with deploy scripts and an end-to-end shell demo
* [Zodomo/DrandVerifier](https://github.com/Zodomo/DrandVerifier) — source of `DrandOracleQuicknet`, full test suite, gas snapshot
* [drand developer docs](https://docs.drand.love/developer/)
* [drand protocol specification](https://docs.drand.love/docs/specification/) — including beacon timing
* [drand security model](https://docs.drand.love/docs/security-model/)
* [EIP-2537 — BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)


# Onchain Payments

How to accept onchain payments in a MegaETH dapp — the HTTP 402 "pay then retry" pattern, the x402 and MPP protocol families, and five concrete payment flows (one-time and pay-as-you-go, user-paid and

This guide shows how to charge for access to an API, a piece of content, or a metered service in a MegaETH dapp. It explains the one pattern every approach shares, the two protocol families built on it, and five concrete flows you can pick from.

{% hint style="info" %}
All five flows run against the same MegaETH Testnet token and are implemented end-to-end in the [MegaETH Payment Demo](https://github.com/megaeth-labs/payment-demo). This guide explains the mechanisms; the demo is the code.
{% endhint %}

{% hint style="warning" %}
**Onchain payments can be reorged.** A payment transaction that looks confirmed — a `transfer`, a `permit` settlement, or a channel `close` — can still be rolled back if the chain reorgs, so its receipt is not final the instant you see it. Before releasing the paid resource, wait for the level of confirmation your risk tolerance requires rather than trusting a single freshly-seen receipt, and make payment verification **idempotent** so a replayed or re-mined transaction is never double-credited.
{% endhint %}

## HTTP 402

Every flow in this guide is a variation on the same handshake, built on the long-reserved `402 Payment Required` HTTP status code:

1. The client requests a protected resource with no payment.
2. The server replies `402 Payment Required` with a machine-readable **challenge** describing the price, the token, and the recipient.
3. The client satisfies the challenge — by paying, or by signing an authorization.
4. The client retries the same request, carrying **proof of payment**.
5. The server verifies the proof, serves the resource, and returns a **receipt**.

What changes between flows is only two things: **what counts as proof**, and **who pays the gas** for the onchain payment transaction. Everything else is the same request/response shape.

```mermaid
sequenceDiagram
    participant C as Client
    participant S as Resource server
    C->>S: GET /resource (no payment)
    S-->>C: 402 Payment Required (price, token, recipient)
    C->>C: pay or sign authorization
    C->>S: retry GET + proof of payment
    S->>S: verify proof
    S-->>C: 200 + resource + receipt
```

## Two protocol families

For dapps, there are two interoperable-by-pattern (but independent) protocol stacks to choose from, each with a Node.js SDK. They both ride on HTTP 402; they are not extensions of each other.

| Family                                                              | NPM Package | Model it covers                         |
| ------------------------------------------------------------------- | ----------- | --------------------------------------- |
| [**x402**](https://github.com/x402-foundation/x402/tree/main/specs) | `@x402/*`   | One-time payments via a *facilitator*   |
| [**MPP**](https://mpp.dev/overview)                                 | `mppx`      | One-time *and* pay-as-you-go (channels) |

Think of them like two payment processors that speak the same wire protocol. x402 is a standards-style one-shot paywall; MPP ([Machine Payments Protocol](https://mpp.dev/overview)) adds streaming/metered billing on top of the same idea.

## The two axes that organize everything

Before the five flows, hold two questions in your head:

* **One-time or streaming?** Charge once per request, or open a channel and bill many requests cheaply?
* **Who pays gas onchain?** The end user, or you (the server) sponsoring it so the user only signs?

The five flows are just the useful points in that 2×2, plus x402 as the standards-based one-time reference.

| # | Flow                                                                 | Model         | User only signs? (gasless)  |
| - | -------------------------------------------------------------------- | ------------- | --------------------------- |
| 1 | [x402 exact](#flow-1--x402-exact-payment)                            | one-time      | yes — facilitator sponsors  |
| 2 | [MPP charge (push)](#flow-2--mpp-charge-push-mode)                   | one-time      | no — user sends the payment |
| 3 | [MPP charge (gasless / pull)](#flow-3--mpp-charge-gasless-pull-mode) | one-time      | yes — server pulls funds    |
| 4 | [MPP session (official)](#flow-4--mpp-session-pay-as-you-go)         | pay-as-you-go | no — user funds the channel |
| 5 | [MPP session (gasless)](#flow-5--mpp-session-gasless)                | pay-as-you-go | yes — server relays funding |

## Flow 1 — x402 exact payment

**Use it for:** a standards-based one-time paywall, with gasless onboarding for first-time users. **Official spec:** [x402 `exact` scheme for EVM](https://github.com/x402-foundation/x402/blob/main/specs/schemes/exact/scheme_exact_evm.md).

The server declares a price in a structured challenge. The client signs a typed-data payment authorization, and a separate component called a **facilitator** verifies it and settles it onchain. The facilitator holds a funded key, so it can submit the settlement transaction and **sponsor the gas** — the user never needs the native gas token for their first payment.

1. The client requests the resource and gets a `402` challenge (price, token, `payTo`).
2. The client signs a typed-data payment authorization (Permit2 / EIP-2612) — **no gas**.
3. The client retries the request carrying the payment header.
4. The resource server hands the payload to the **facilitator**, which verifies and settles it onchain — **the facilitator pays gas**.
5. The server returns the content plus a settlement header.

```mermaid
sequenceDiagram
    participant C as Client
    participant S as Resource server
    participant F as Facilitator
    C->>S: GET /resource
    S-->>C: 402 (price, token, payTo)
    C->>C: sign Permit2 / EIP-2612 authorization
    C->>S: retry GET + payment header
    S->>F: verify(payload)
    S->>F: settle(payload)
    F->>F: submit onchain tx (sponsors gas)
    F-->>S: settlement result
    S-->>C: 200 + content + settlement header
```

The defining trait is the **facilitator**: the resource server stays thin (it only declares a price and gates content) and delegates all key-holding and onchain work. The demo runs the facilitator in-process by default, but it can also be a remote service.

{% hint style="success" %}
x402's gas sponsoring pairs **Permit2** (the transfer rail) with an **EIP-2612 signature** (to set up the Permit2 allowance without a separate gas-paid `approve`). That combination is what makes a brand-new user's first payment fully gasless.
{% endhint %}

## Flow 2 — MPP charge, push mode

**Use it for:** the simplest possible one-time payment, with no server key and no sponsorship. **Official spec:** [MPP `charge` intent](https://mpp.dev/intents/charge).

The client just makes the payment itself and shows the receipt. This is MPP's official `tempo.charge` intent.

1. The client requests the resource and gets a `tempo.charge` challenge (amount, token, recipient).
2. The client's wallet sends a normal ERC-20 `transfer(recipient, amount)` — **the user pays gas**.
3. The client retries with proof: `{ type: "hash", hash }`.
4. The server verifies that transaction onchain (right token, recipient, amount; one-time-use) and serves the content.

```mermaid
sequenceDiagram
    participant C as Client
    participant S as Resource server
    participant T as Token (ERC-20)
    C->>S: GET /resource
    S-->>C: 402 tempo.charge (amount, token, recipient)
    C->>T: transfer(recipient, amount) — client pays gas
    T-->>C: tx hash
    C->>S: retry GET + proof { type: "hash", hash }
    S->>T: read receipt (token, recipient, amount, one-time-use)
    S-->>C: 200 + content + receipt
```

The only onchain interaction is the user's own transfer. The server never sends a transaction — it just reads the receipt — so this flow needs no server private key.

{% hint style="warning" %}
Push proof is a transaction hash, validated by amount + recipient + one-time-use. It is not cryptographically bound to a specific request, so use the optional `memo`/`expires` fields (or per-request recipients) if you need tight request-to-payment binding.
{% endhint %}

## Flow 3 — MPP charge, gasless (pull) mode

**Use it for:** a one-time charge where the user has no native gas token and should only sign. **Official spec:** [MPP `charge` intent](https://mpp.dev/intents/charge) (this gasless pull is a Permit-based variant of it).

Same one-time charge, but the **server pays gas and pulls the funds**. The user signs an [EIP-2612](#building-blocks) `permit`; the server submits it and then pulls the payment.

1. The challenge tells the client the spender, token name, and version.
2. The client reads the token nonce and signs `Permit(owner, spender, value, nonce, deadline)`.
3. The client sends the signed permit as proof.
4. The server verifies the signature, nonce, deadline, amount, and balance.
5. The server submits `permit(...)` and then `transferFrom(owner, recipient, amount)` — **the server pays gas for both**.

```mermaid
sequenceDiagram
    participant C as Client
    participant S as Resource server
    participant T as Token (ERC-20)
    C->>S: GET /resource
    S-->>C: 402 (spender, token name, version)
    C->>C: sign Permit(owner, spender, value, nonce, deadline)
    C->>S: retry GET + signed permit
    S->>S: verify signature, nonce, deadline, amount, balance
    S->>T: permit(...) — server pays gas
    S->>T: transferFrom(owner, recipient, amount) — server pays gas
    S-->>C: 200 + content + receipt
```

This is the same user-facing shape as push mode, but the proof is a signature instead of a finished transaction, and settlement moves to the server. It requires a funded server key.

{% hint style="info" %}
The official MPP `charge` intent only standardizes **push mode** (Flow 2), where the user sends and pays for the transfer. This gasless pull variant is a **demo extension**: it adds an [EIP-2612](#building-blocks) `permit` + `transferFrom` settlement path so the server can pull the funds and pay the gas. It is not part of the official spec.
{% endhint %}

## Flow 4 — MPP session (pay-as-you-go)

**Use it for:** high-frequency or metered billing — pay per API call, per inference, per request — where one transaction per payment would be too slow and too expensive. **Official spec:** [MPP `session` intent](https://mpp.dev/intents/session).

This is a **unidirectional payment channel**. The client deposits once into an onchain escrow contract, then pays for each request with a cheap **offchain signed voucher** that carries a running total (i.e., accumulated costs). Only three moments ever touch the chain — opening the channel, topping it up, and closing it to settle — while paying for each individual request is a pure offchain signature. The steps below name the concrete operations: `open`, `topUp`, and `close` are functions on the escrow contract, while the per-request `voucher` is an offchain signature.

1. The client `open`s the channel, depositing `N` into the escrow — **client pays gas**.
2. For each request, the client signs an offchain `voucher` carrying the new **cumulative** total — **no gas**.
3. The server serves each request, remembering only the single highest voucher per channel.
4. When the deposit runs low, the client `topUp`s more — **client pays gas**.
5. To settle, the server `close`s with the highest voucher; the escrow pays the payee that amount and refunds the rest — **server pays gas**.

```mermaid
sequenceDiagram
    participant P as Payer (client)
    participant E as Escrow
    participant S as Payee (server)
    P->>E: open — deposit N (onchain)
    P-->>S: voucher: cumulative = 1 (offchain, no gas)
    P-->>S: voucher: cumulative = 2 (offchain, no gas)
    P-->>S: voucher: cumulative = 3 (offchain, no gas)
    S->>E: close with cumulative = 3 (onchain)
    E->>S: pay 3
    E->>P: refund N − 3
```

The four actions:

| Action    | Initiated by (pays gas) | Tx recipient                | Fund flow                                                          | Onchain?          | Purpose                                   |
| --------- | ----------------------- | --------------------------- | ------------------------------------------------------------------ | ----------------- | ----------------------------------------- |
| `open`    | client                  | escrow contract             | client → escrow (deposit `N`)                                      | yes (client gas)  | deposit, create channel, sign 1st voucher |
| `voucher` | client (signs only)     | — (sent to server offchain) | none — promises a cumulative amount                                | **no** — gas-free | pay for one request                       |
| `topUp`   | client                  | escrow contract             | client → escrow (add deposit)                                      | yes (client gas)  | add deposit when it runs low              |
| `close`   | server (payee)          | escrow contract             | escrow → payee (highest voucher); escrow → payer (refund the rest) | yes (server gas)  | settle highest voucher, refund the rest   |

The key invariant: vouchers carry a **cumulative** total, so the server only ever needs to remember the single highest voucher per channel. On `close`, the escrow pays the payee that highest amount and refunds the unused deposit to the payer.

{% hint style="danger" %}
The server settles on the highest voucher it has accepted, so that per-channel state must be **durable and concurrency-safe** in production. Use a shared store (not in-process memory) across serverless instances, and guard the voucher update with an atomic compare-and-swap so concurrent requests on one channel cannot be double-served.
{% endhint %}

## Flow 5 — MPP session, gasless

**Use it for:** the same metered billing as Flow 4, but with a zero-gas experience — the user only ever signs. **Official spec:** [MPP `session` intent](https://mpp.dev/intents/session) (this gasless variant relays funding via Permit2).

The channel model, vouchers, and `close` are identical to Flow 4. The only difference is **who funds the channel onchain**: instead of the client sending `open`/`topUp` transactions, the client signs a **Permit2** authorization and the **server relays** the funding.

1. The client signs a **Permit2** authorization to fund the channel instead of sending `open` — **no gas**.
2. The server relays it via `openWithPermit2`, opening the channel onchain — **server pays gas**.
3. For each request, the client signs an offchain cumulative `voucher` — **no gas** (identical to Flow 4).
4. To add funds, the client signs another Permit2 and the server relays `topUpWithPermit2` — **server pays gas**.
5. The server `close`s with the highest voucher; the escrow pays the payee and refunds the rest — **server pays gas**.

```mermaid
sequenceDiagram
    participant P as Payer (client)
    participant S as Server (relayer + payee)
    participant E as Escrow
    P->>P: sign Permit2 authorization (deposit N)
    P->>S: send signed Permit2
    S->>E: openWithPermit2(...) — server pays gas
    P-->>S: voucher: cumulative = 1 (offchain, no gas)
    P-->>S: voucher: cumulative = 2 (offchain, no gas)
    S->>E: close with highest voucher — server pays gas
    E->>S: pay accepted amount
    E->>P: refund the rest
```

The four actions:

| Action             | Initiated by (pays gas)              | Tx recipient                | Fund flow                                                          | Onchain?          | Purpose                                         |
| ------------------ | ------------------------------------ | --------------------------- | ------------------------------------------------------------------ | ----------------- | ----------------------------------------------- |
| `openWithPermit2`  | server relays (client signs Permit2) | escrow contract             | client → escrow (deposit `N`, pulled via Permit2)                  | yes (server gas)  | fund + create channel, client signs 1st voucher |
| `voucher`          | client (signs only)                  | — (sent to server offchain) | none — promises a cumulative amount                                | **no** — gas-free | pay for one request                             |
| `topUpWithPermit2` | server relays (client signs Permit2) | escrow contract             | client → escrow (add deposit)                                      | yes (server gas)  | add deposit when it runs low                    |
| `close`            | server (payee)                       | escrow contract             | escrow → payee (highest voucher); escrow → payer (refund the rest) | yes (server gas)  | settle highest voucher, refund the rest         |

The contrast with Flow 4 is only **who sends the funding transaction** — the client signs instead of sending, and the server relays:

| Phase     | Flow 4 (official)           | Flow 5 (gasless)                |
| --------- | --------------------------- | ------------------------------- |
| `open`    | client calls escrow `open`  | server calls `openWithPermit2`  |
| `topUp`   | client calls escrow `topUp` | server calls `topUpWithPermit2` |
| `voucher` | offchain signature          | offchain signature (identical)  |
| `close`   | server settles              | server settles (identical)      |

Because a relayer (the server), not the payer, sends the funding transaction, the escrow needs entry points where the payer is authorized by **signature** rather than by being `msg.sender`. That is exactly what **Permit2** and **EIP-3009** provide, and why the gasless flow uses an escrow variant with signature-authorized funding methods (`*WithPermit2` and `receiveWithAuthorization`).

{% hint style="info" %}
The official MPP `session` spec defines only the **base escrow**, funded by the client's own `open`/`topUp` transactions — it has **no gasless funding path**. This gasless flow is a **demo extension**: the escrow variant adds signature-authorized funding entry points — `*WithPermit2` ([Permit2](#building-blocks)) and `receiveWithAuthorization` ([EIP-3009](#building-blocks)) — so a relayer can fund on the payer's behalf. It is not part of the official spec.
{% endhint %}

## Choosing a flow

Start from the two axes:

| If you need…                                     | Use           |
| ------------------------------------------------ | ------------- |
| A standards-based one-time paywall               | Flow 1 (x402) |
| The simplest one-time charge, no server key      | Flow 2        |
| A one-time charge with zero gas for the user     | Flow 3        |
| Metered/streaming billing, user pays gas         | Flow 4        |
| Metered/streaming billing, zero gas for the user | Flow 5        |

{% hint style="success" %}
Gasless flows (1, 3, 5) trade a little server cost and a funded relayer key for a much smoother user experience: the user never needs the native gas token and only signs. Non-gasless flows (2, 4) are simpler to operate because the user pays their own gas.
{% endhint %}

## Building blocks

These primitives recur across the flows. Each lets someone authorize a token movement with a **signature** instead of a pre-sent `approve` transaction — the foundation of every gasless flow.

* **EIP-2612 `permit`** — a token-native signed approval (`Permit(owner, spender, value, nonce, deadline)`). Works only if the token implements it. Used in Flows 1 and 3.
* **Permit2** — a single canonical contract (deployed at the same address on every chain) that adds signature-based transfers to *any* ERC-20 after a one-time `approve(Permit2)`. Its **witness** data binds an authorization to specific terms, preventing reuse on a different channel. Used in Flows 1 and 5.
* **EIP-3009 `receiveWithAuthorization`** — a token-native signed transfer with arbitrary (non-sequential) nonces, enabling concurrent authorizations. Supported by the escrow as an alternative funding path.
* **Payment channel + voucher** — an onchain escrow settled by cumulative offchain signatures. The core of Flows 4 and 5.

## MegaETH-specific payment demo

The [MegaETH Payment Demo](https://github.com/megaeth-labs/payment-demo) implements all five flows against MegaETH Testnet, with a connected wallet on the client and a relayer/facilitator on the server.

| Flow | Protected route                 | Demo UI component        |
| ---- | ------------------------------- | ------------------------ |
| 1    | `GET /api/x402/exact`           | `X402Demo`               |
| 2    | `GET /api/mpp/charge`           | `MppDemo`                |
| 3    | `GET /api/mpp/gasless-charge`   | `MppGaslessDemo`         |
| 4    | `POST /api/mpp/session`         | `MppOfficialSessionDemo` |
| 5    | `POST /api/mpp/session-gasless` | `MppSessionGaslessDemo`  |

The repository also includes the escrow contract (`contract/`) and protocol scheme notes (`docs/`) explaining each flow in more detail.

**Notes:**

* **Token.** The demo uses a testnet USD-style ERC-20 (USDm) as the payment asset across all five flows.
* **Escrow.** The session flows use a `TempoStreamChannel`-style escrow deployed on MegaETH; the gasless variant adds Permit2 / EIP-3009 funding entry points so a relayer can fund on the payer's behalf.
* **Fast settlement.** Server-side settlement (gasless charge, channel `close`, relayed funding) is submitted via MegaETH's realtime transaction RPC, which returns a receipt synchronously instead of requiring a separate poll. See [`realtime_sendRawTransaction`](/developer-docs/rpc/reference/realtime_sendrawtransaction) and the [Realtime API](/developer-docs/overview-2/realtime-api).
* **Gas.** Sponsored flows require a funded server key to pay gas. Estimate gas with `eth_estimateGas` against a MegaETH endpoint rather than computing it manually — see [Gas Estimation](/developer-docs/overview-1/gas-estimation).

## Further reading

* [MegaETH Payment Demo](https://github.com/megaeth-labs/payment-demo) — runnable Next.js app implementing all five flows
* [x402 specification](https://github.com/x402-foundation/x402/tree/main/specs) — the official x402 protocol spec ([repo and packages](https://github.com/x402-foundation/x402))
* [MPP specification](https://mpp.dev/overview) — the official Machine Payments Protocol spec, built on the [Payment HTTP authentication scheme](https://paymentauth.org) ([`mppx` SDK](https://github.com/wevm/mppx))
* [Realtime API](/developer-docs/overview-2/realtime-api) — synchronous transaction submission on MegaETH
* [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612) · [EIP-3009](https://eips.ethereum.org/EIPS/eip-3009) · [Permit2](https://github.com/Uniswap/permit2)


# JSON-RPC

MegaETH JSON-RPC endpoints, shared protocol conventions, operational limits, and method reference.

MegaETH exposes Ethereum-compatible JSON-RPC over HTTP and WebSocket, with additional methods and real-time behavior. Start with the shared guides below, then use the RPC Reference for individual method contracts.

## Get started

* [Quickstart](/developer-docs/rpc/quickstart) — make a read-only request and verify the connected network.
* [JSON-RPC basics](/developer-docs/rpc/json-rpc-basics) — request envelopes, notifications, batches, and response handling.
* [Type reference](/developer-docs/rpc/types) — hexadecimal quantities, byte strings, addresses, hashes, and selectors.
* [Error reference](/developer-docs/rpc/error-codes) — standard, Ethereum, MegaETH, and public-gateway errors.
* [Operations and limits](/developer-docs/rpc/operations-and-limits) — rate limits, payload caps, caching, and WebSocket limits.

## RPC Reference

Use the [RPC Reference](/developer-docs/rpc/reference) for method availability and individual request, response, error, and example documentation.


# Quickstart

Make your first read-only MegaETH JSON-RPC requests and verify the connected network.

Use these read-only requests to confirm connectivity and learn the basic response shape. The public HTTP endpoint accepts JSON-RPC `POST` requests without an API key.

## Endpoints

| Network | HTTP                              | WebSocket                      |
| ------- | --------------------------------- | ------------------------------ |
| Mainnet | `https://mainnet.megaeth.com/rpc` | `wss://mainnet.megaeth.com/ws` |
| Testnet | `https://carrot.megaeth.com/rpc`  | `wss://carrot.megaeth.com/ws`  |

Use HTTP for standard requests and WebSocket for [`eth_subscribe`](/developer-docs/rpc/reference/eth_subscribe) and [`eth_unsubscribe`](/developer-docs/rpc/reference/eth_unsubscribe).

## Check the latest block

```bash
curl -sS https://mainnet.megaeth.com/rpc \
  -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
```

A successful response contains a hexadecimal block number:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x..."
}
```

## Verify the network

```bash
curl -sS https://mainnet.megaeth.com/rpc \
  -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":2,"method":"eth_chainId","params":[]}'
```

MegaETH Mainnet returns `0x10e6` (4326), and MegaETH Testnet returns `0x18c7` (6343).

## Read account state

Replace the zero address with the account you want to query.

```bash
curl -sS https://mainnet.megaeth.com/rpc \
  -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":3,"method":"eth_getBalance","params":["0x0000000000000000000000000000000000000000","latest"]}'
```

The result is a hexadecimal [`Quantity`](/developer-docs/rpc/types#quantity) denominated in wei.

## Next steps

* Use [JSON-RPC basics](/developer-docs/rpc/json-rpc-basics) for envelopes, notifications, and batches.
* Use [Operations and limits](/developer-docs/rpc/operations-and-limits) before sending large batches or historical queries.
* Use [Error reference](/developer-docs/rpc/error-codes) to distinguish transport failures from JSON-RPC errors.
* Browse the [RPC Reference](/developer-docs/rpc/reference) for request and response schemas.


# JSON-RPC basics

Shared JSON-RPC 2.0 request, notification, batch, success, and error conventions used by MegaETH.

MegaETH uses JSON-RPC 2.0 for HTTP requests and WebSocket messages. Method pages define the parameter order, result shape, and method-specific behavior.

## Request envelope

| Field     | JSON type        | Required                      | Rule                                                  |
| --------- | ---------------- | ----------------------------- | ----------------------------------------------------- |
| `jsonrpc` | string           | Yes                           | Must be `"2.0"`.                                      |
| `id`      | string or number | Unless sending a notification | Correlates the response with the request.             |
| `method`  | string           | Yes                           | Names the RPC method.                                 |
| `params`  | array or object  | Method-defined                | Method pages in this reference use positional arrays. |

Use a unique string or number for `id` when you expect a response. JSON-RPC permits a `null` request ID, but clients should avoid it because a response may also use `null` when the request ID cannot be determined.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_chainId",
  "params": []
}
```

## Notifications

A notification omits `id`. The server does not return a response, including when the notification is invalid.

```json
{
  "jsonrpc": "2.0",
  "method": "eth_blockNumber",
  "params": []
}
```

Use notifications only when your application intentionally does not need a result or error.

## Batch requests

A batch is a JSON array containing request or notification objects. The public gateway accepts at most 100 items in one batch.

```json
[
  {
    "jsonrpc": "2.0",
    "id": "block",
    "method": "eth_blockNumber",
    "params": []
  },
  {
    "jsonrpc": "2.0",
    "id": "chain",
    "method": "eth_chainId",
    "params": []
  }
]
```

Batch responses may arrive in a different order from their requests. Match each response by `id`, and remember that notification items do not produce response items. See [Operations and limits](/developer-docs/rpc/operations-and-limits#http-request-and-response-limits) for batch accounting and body-size limits.

## Success response

A successful response contains `result` and does not contain `error`. The result type is defined by the method.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x10e6"
}
```

Values such as `null`, `"0x0"`, and `[]` can be successful results when documented by the method.

## Error response

A failed call contains `error` and does not contain `result`.

| Field           | JSON type                 | Required | Description                     |
| --------------- | ------------------------- | -------- | ------------------------------- |
| `jsonrpc`       | string                    | Yes      | Always `"2.0"`.                 |
| `id`            | string, number, or `null` | Yes      | Usually matches the request ID. |
| `error.code`    | number                    | Yes      | Machine-readable error code.    |
| `error.message` | string                    | Yes      | Human-readable summary.         |
| `error.data`    | any                       | No       | Additional structured details.  |

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32602,
    "message": "Invalid params"
  }
}
```

HTTP `200` only means the HTTP exchange completed. Always inspect the JSON-RPC body for `result` or `error`. See [Error reference](/developer-docs/rpc/error-codes) for standard, Ethereum, gateway, and MegaETH-specific codes.

## Sources

* [JSON-RPC 2.0 Specification](https://www.jsonrpc.org/specification)
* [EIP-1474: Remote procedure call specification](https://eips.ethereum.org/EIPS/eip-1474)


# Type reference

Hexadecimal quantities, byte strings, addresses, hashes, block selectors, and transaction call objects used by MegaETH JSON-RPC.

This page defines wire types shared by MegaETH JSON-RPC methods. Method pages remain self-contained and specify the types accepted in each position.

## Core wire types

### `Quantity`

A `Quantity` is a non-negative integer encoded as a `0x`-prefixed hexadecimal string. It uses the shortest representation, so leading zeroes are not allowed except in `0x0`.

| Valid    | Invalid |
| -------- | ------- |
| `0x0`    | `0`     |
| `0x1`    | `0x01`  |
| `0x5208` | `21000` |

### `Data`

`Data` is an arbitrary byte sequence encoded as a `0x`-prefixed hexadecimal string. It contains exactly two hexadecimal digits per byte and may be empty.

| Valid        | Invalid    |
| ------------ | ---------- |
| `0x`         | `0`        |
| `0x12`       | `0x1`      |
| `0xdeadbeef` | `deadbeef` |

### `Address`

An `Address` is a 20-byte value encoded as `0x` followed by 40 hexadecimal digits. The wire format accepts upper- or lowercase hexadecimal digits.

Example: `0x0000000000000000000000000000000000000000`.

### `Hash32`

A `Hash32` is a 32-byte hash encoded as `0x` followed by 64 hexadecimal digits. Block hashes, transaction hashes, and trie roots use this representation.

### `Bytes32`

`Bytes32` has the same wire width as `Hash32` but represents a fixed-width value rather than necessarily a hash. Storage keys and proof values commonly use this representation.

## Block selectors

Methods that read block or state data may accept a block number encoded as `Quantity` or one of these tags:

| Tag         | Meaning on MegaETH                                           |
| ----------- | ------------------------------------------------------------ |
| `earliest`  | The genesis block.                                           |
| `latest`    | The latest streaming state, including committed mini-blocks. |
| `pending`   | The latest streaming state.                                  |
| `safe`      | The latest safe EVM block known to the node.                 |
| `finalized` | The latest finalized EVM block known to the node.            |

Some methods also accept an EIP-1898 block selector object containing `blockHash` or `blockNumber`. Check the method page before using the object form because support is method-specific.

## Transaction call object

Simulation methods such as [`eth_call`](/developer-docs/rpc/reference/eth_call), [`eth_estimateGas`](/developer-docs/rpc/reference/eth_estimategas), and [`eth_createAccessList`](/developer-docs/rpc/reference/eth_createaccesslist) accept a transaction call object. Common fields include:

| Field                  | Type                | Description                                 |
| ---------------------- | ------------------- | ------------------------------------------- |
| `from`                 | `Address`           | Simulated sender.                           |
| `to`                   | `Address` or `null` | Recipient, or `null` for contract creation. |
| `gas`                  | `Quantity`          | Gas limit supplied to the simulation.       |
| `gasPrice`             | `Quantity`          | Legacy gas price.                           |
| `maxFeePerGas`         | `Quantity`          | EIP-1559 maximum fee.                       |
| `maxPriorityFeePerGas` | `Quantity`          | EIP-1559 priority fee.                      |
| `value`                | `Quantity`          | Value transferred in wei.                   |
| `input` or `data`      | `Data`              | Calldata or contract creation bytecode.     |
| `nonce`                | `Quantity`          | Sender nonce when the method supports it.   |
| `accessList`           | array               | EIP-2930 access list.                       |

Do not combine `gasPrice` with EIP-1559 fee fields. Use the relevant method page for accepted fields and defaults.

## Common validation mistakes

| Mistake                  | Wrong                          | Correct                |
| ------------------------ | ------------------------------ | ---------------------- |
| Decimal quantity         | `21000`                        | `"0x5208"`             |
| Leading zeroes           | `"0x0001"`                     | `"0x1"`                |
| Odd-length data          | `"0x123"`                      | `"0x0123"`             |
| Short address            | `"0x1234"`                     | A full 20-byte address |
| Mixed log selector modes | `blockHash` with `fromBlock`   | Use one selector mode  |
| Mixed fee models         | `gasPrice` with `maxFeePerGas` | Use one fee model      |

## Source

* [EIP-1474: Value encoding](https://eips.ethereum.org/EIPS/eip-1474#value-encoding)


# Error reference

Standard JSON-RPC, Ethereum, MegaETH, and public-gateway errors with retry guidance.

HTTP status and JSON-RPC status describe different layers. An HTTP `200` response can contain either a JSON-RPC `result` or a JSON-RPC `error`.

## Error surfaces

| Surface              | Shape                                         | Meaning                                                                                     |
| -------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------- |
| Transport failure    | No valid JSON-RPC body                        | The HTTP, routing, connectivity, or gateway layer failed.                                   |
| JSON-RPC error       | Top-level `error` object                      | The request envelope, method, parameters, or server execution failed.                       |
| Method-defined error | A successful `result` contains an error field | The JSON-RPC call succeeded, but the method reports an execution outcome inside its result. |
| Empty success        | `result` is `null`, `"0x0"`, or `[]`          | The method succeeded and returned its documented empty value.                               |

Check the method page before treating an empty success as a failure. See [JSON-RPC basics](/developer-docs/rpc/json-rpc-basics#error-response) for the complete error envelope.

## Standard JSON-RPC errors

| Code     | Name             | Meaning                                                                        | Retry |
| -------- | ---------------- | ------------------------------------------------------------------------------ | ----- |
| `-32700` | Parse error      | The request body is not valid JSON.                                            | No    |
| `-32600` | Invalid Request  | The JSON-RPC envelope is invalid.                                              | No    |
| `-32601` | Method not found | The method is unknown, disabled, or unavailable on this endpoint or transport. | No    |
| `-32602` | Invalid params   | The parameters do not satisfy the method contract.                             | No    |
| `-32603` | Internal error   | The server failed while processing a valid request.                            | Maybe |

Malformed JSON and unknown methods on the public HTTP endpoint return a JSON-RPC error body with HTTP `200`. Client logic should therefore inspect `error.code` instead of inferring success from the HTTP status.

## Ethereum server errors

EIP-1474 assigns the following server-error codes:

| Code     | Meaning                                        | Typical action                                                 |
| -------- | ---------------------------------------------- | -------------------------------------------------------------- |
| `-32000` | Invalid input or a general server-side failure | Inspect the message and method context before retrying.        |
| `-32001` | Resource not found                             | Verify the block, transaction, or other selector.              |
| `-32002` | Resource unavailable                           | Retry later if the requested resource should become available. |
| `-32003` | Transaction rejected                           | Correct the transaction or its fees before retrying.           |
| `-32004` | Method not supported                           | Use a supported method or endpoint.                            |
| `-32005` | Limit exceeded                                 | Reduce load or request scope, then retry with backoff.         |
| `-32006` | JSON-RPC version not supported                 | Send JSON-RPC `"2.0"`.                                         |

Providers can reuse `-32000` for several failures. Use both the numeric code and message for diagnostics, but avoid matching only on message text.

## MegaETH and gateway errors

| Code     | Meaning                    | Typical cause                                                                          | Action                                                                         |
| -------- | -------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `3`      | Execution reverted         | `eth_call` or `eth_estimateGas` reached an EVM revert.                                 | Inspect and decode `error.data`, then change the call inputs or state context. |
| `4444`   | Pruned history unavailable | The serving node does not retain the requested historical state.                       | Use a newer block or an endpoint with the required history.                    |
| `-32005` | Limit exceeded             | A public rate limit, WebSocket subscription cap, or server-capacity limit was reached. | Reduce concurrency or scope and retry with exponential backoff and jitter.     |
| `-32099` | Payload too large          | The HTTP request body exceeds the applicable gateway limit.                            | Reduce the body or batch size.                                                 |

See [Operations and limits](/developer-docs/rpc/operations-and-limits) for the public gateway thresholds.

### Execution revert example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": 3,
    "message": "execution reverted",
    "data": "0x08c379a0..."
  }
}
```

The first four bytes of `error.data` identify the revert payload format. Decode the payload when possible before retrying.

### Historical state unavailable

Code `4444` applies to historical state that the node has pruned or never retained. It commonly affects state reads such as `eth_getBalance`, `eth_getCode`, `eth_getStorageAt`, and `eth_getTransactionCount` at an old block.

Keep the request and selector unchanged while testing another endpoint. Do not retry the same endpoint repeatedly because retention is not a transient condition.

## HTTP status handling

| HTTP status    | Meaning at the transport layer        | Client action                                                    |
| -------------- | ------------------------------------- | ---------------------------------------------------------------- |
| `200`          | The HTTP exchange completed.          | Inspect the JSON-RPC body for `result` or `error`.               |
| `413`          | The request body is too large.        | Handle JSON-RPC `-32099` when present and reduce the payload.    |
| `429`          | The gateway rate-limited the request. | Handle JSON-RPC `-32005` when present and retry with backoff.    |
| `500` or `503` | The gateway or upstream failed.       | Retry sparingly after checking request size and endpoint health. |

Do not hardcode a one-to-one mapping between every JSON-RPC code and an HTTP status.

## What to record

Capture these fields before retrying or escalating a failure:

* endpoint and transport
* method name
* block or resource selector
* HTTP status
* JSON-RPC code, message, and data
* request ID
* retry count and delay

Never log private keys or unsigned transaction secrets. Redact raw signed transactions unless the transaction is already public and your logging policy allows them.

## Sources

* [JSON-RPC 2.0 Specification](https://www.jsonrpc.org/specification)
* [EIP-1474: Remote procedure call specification](https://eips.ethereum.org/EIPS/eip-1474)
* `mega-reth`: `crates/rpc/rpc-eth-types/src/error/mod.rs`


# Operations and limits

Public MegaETH JSON-RPC rate limits, payload limits, method caps, caching behavior, and WebSocket limits.

This page describes limits applied by the public MegaETH gateway. Method pages define the underlying request and response contracts.

## HTTP request and response limits

| Limit                                  | Value        |
| -------------------------------------- | ------------ |
| Default request body                   | 128 KiB      |
| Transaction-submission request body    | 2.5 MiB      |
| Simulation and large-read request body | 1.5 MiB      |
| Batch size                             | 100 requests |
| Batch subrequest budget                | 950          |
| Response size                          | 50 MiB       |

The 2.5 MiB body limit applies to `eth_sendRawTransaction`, `eth_sendRawTransactionSync`, and `realtime_sendRawTransaction`. The 1.5 MiB body limit applies to `eth_call`, `eth_callMany`, `eth_createAccessList`, and `eth_estimateGas`. A body that exceeds its limit is rejected with HTTP `413` and JSON-RPC code `-32099`.

The batch subrequest budget counts expanded work rather than only top-level batch items. For example, the calls inside `eth_callMany` contribute to that budget.

## Method-specific limits

| Method            | Public gateway behavior                                                                                                                           |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `eth_call`        | Compute gas is capped at 60,000,000.                                                                                                              |
| `eth_callMany`    | At most 100 bundles and 100 total calls, 60,000,000 compute gas per call, and a 25-second timeout.                                                |
| `eth_estimateGas` | The node applies a CPU-time limit whose current default is 0.5 seconds.                                                                           |
| `eth_feeHistory`  | `blockCount` is capped at 256.                                                                                                                    |
| `eth_getLogs`     | The public indexed path does not impose a gateway block-range cap, but backend row, execution-time, memory, and response-size limits still apply. |

Use bounded ranges and pagination for log scans and historical backfills. Do not assume that removing a block-range cap makes an unbounded query safe.

## Read rate limits

Read requests are limited per client IP in fixed 10-second windows.

| Category | Requests per 10 seconds | Typical methods                                                                                                             |
| -------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| Instant  | 2,000                   | `eth_chainId`, `eth_blockNumber`, `net_version`, `eth_accounts`, `web3_clientVersion`, `eth_getBalance`, `eth_getStorageAt` |
| Simple   | 500                     | Basic block and transaction reads not assigned to another category                                                          |
| Compute  | 200                     | `eth_call`, `eth_callMany`, `eth_estimateGas`, `eth_createAccessList`, and debug trace methods                              |
| IO-heavy | 200                     | `eth_getLogs` and `eth_getBlockReceipts`                                                                                    |

Transaction-submission methods are exempt from these read limits. `eth_callMany` is charged by its inner calls rather than as one unit. A rate-limited request returns HTTP `429` with JSON-RPC code `-32005`.

Use exponential backoff with jitter for retryable throttling. Reduce concurrency and query size before increasing retry frequency.

## Gateway caching

The public gateway has several internal caches. Their eligibility and lifetime depend on the method and selector: immutable block numbers and hashes can use longer-lived entries, while head-following reads use shorter policies or bypass a cache layer. See each method's reference page for its method-specific behavior.

The gateway's Workers read-cache layer is limited to:

* `eth_getBlockByNumber`
* `eth_getBlockReceipts`
* `eth_getHeaderByNumber`
* `web3_clientVersion`

For the block-selecting methods in this layer, only an explicit historical block number, a block hash, or `earliest` is eligible. The `latest`, `pending`, `safe`, and `finalized` tags bypass this layer. Other gateway cache layers can still apply method-specific short-lived policies to head-following reads.

Rate-limit accounting differs by request shape:

* A single read is rate-limited before cache lookup, so a cache hit consumes its category budget.
* A read batch checks the cache first and charges only cache misses against the read-rate budget.

Every public response includes `Cache-Control: no-store` for downstream caches. This header does not disable the gateway's internal cache. For methods eligible for the Workers read-cache layer, `X-Workers-Cache-Status` indicates whether that layer returned the response.

The gateway does not expose a request header or parameter that bypasses its internal cache.

## WebSocket limits

| Limit                              | Value                                |
| ---------------------------------- | ------------------------------------ |
| Connections per IP                 | 5                                    |
| Subscriptions per connection       | 5                                    |
| Client message rate                | 5 messages per second per connection |
| Idle timeout                       | 60 seconds                           |
| Maximum message size               | 64 KiB                               |
| Addresses in a `logs` filter       | 20                                   |
| Topic positions in a `logs` filter | 4                                    |

Use `wss://mainnet.megaeth.com/ws` for Mainnet and `wss://carrot.megaeth.com/ws` for Testnet. Send a lightweight request such as `eth_chainId` at least every 30 seconds to prevent idle disconnection. Reconnect, recreate subscriptions, and reconcile any missed data after a disconnect because notifications are not replayed automatically.

The public WebSocket endpoint accepts:

* `eth_subscribe`
* `eth_unsubscribe`
* `eth_sendRawTransaction`
* `eth_sendRawTransactionSync`
* `realtime_sendRawTransaction`
* `eth_chainId`

## Related pages

* [Error reference](/developer-docs/rpc/error-codes)
* [`eth_subscribe`](/developer-docs/rpc/reference/eth_subscribe)
* [`eth_getLogs`](/developer-docs/rpc/reference/eth_getlogs)


# RPC Reference

Complete reference for the 51 JSON-RPC methods available through MegaETH's public HTTP and WebSocket endpoints.

This reference documents the JSON-RPC methods available through the public MegaETH HTTP and WebSocket endpoints. Use [JSON-RPC](/developer-docs/rpc) for request framing, shared wire types, errors, and gateway limits.

## Available Methods

{% hint style="info" %}
The table below reflects the public MegaETH Mainnet endpoint. "Unavailable" includes methods recognized by the gateway but disabled or unimplemented upstream. Managed providers may expose additional methods.
{% endhint %}

| Method                                    | Availability   | Additional restrictions or behavior                                                             |
| ----------------------------------------- | -------------- | ----------------------------------------------------------------------------------------------- |
| `debug_getHistoryTransactionCount`        | Available      | MegaETH-specific.                                                                               |
| `debug_getRawHeader`                      | Available      |                                                                                                 |
| `debug_traceBlockByHash`                  | Available      | Large responses are streamed.                                                                   |
| `debug_traceBlockByNumber`                | Available      | Large responses are streamed.                                                                   |
| `debug_traceCall`                         | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `debug_traceTransaction`                  | Available      | Large responses are streamed.                                                                   |
| `eth_accounts`                            | Available      | Returns an empty array because the gateway does not manage user keys.                           |
| `eth_blockNumber`                         | Available      |                                                                                                 |
| `eth_call`                                | Available      | Compute gas limited to 60,000,000.                                                              |
| `eth_callAfter`                           | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `eth_callMany`                            | Available      | 100 bundles and 100 total calls; 60,000,000 compute gas per call; timeout capped at 25 seconds. |
| `eth_chainId`                             | Available      |                                                                                                 |
| `eth_createAccessList`                    | Available      | Routed to the compute pool; no separate 60M compute override is added.                          |
| `eth_estimateGas`                         | Available      | Uses an internal CPU-time limit; the source default is 0.5 seconds.                             |
| `eth_feeHistory`                          | Available      | Block range limited to 256.                                                                     |
| `eth_gasPrice`                            | Available      |                                                                                                 |
| `eth_getBalance`                          | Available      |                                                                                                 |
| `eth_getBlockByHash`                      | Available      |                                                                                                 |
| `eth_getBlockByNumber`                    | Available      |                                                                                                 |
| `eth_getBlockReceipts`                    | Available      |                                                                                                 |
| `eth_getBlockTransactionCountByHash`      | Available      |                                                                                                 |
| `eth_getBlockTransactionCountByNumber`    | Available      |                                                                                                 |
| `eth_getCode`                             | Available      |                                                                                                 |
| `eth_getCodeByHash`                       | Available      | MegaETH-specific.                                                                               |
| `eth_getFilterChanges`                    | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `eth_getFilterLogs`                       | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `eth_getHeaderByHash`                     | Available      | MegaETH-specific.                                                                               |
| `eth_getHeaderByNumber`                   | Available      | MegaETH-specific.                                                                               |
| `eth_getLogs`                             | Available      |                                                                                                 |
| `eth_getLogsWithCursor`                   | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `eth_getStorageAt`                        | Available      |                                                                                                 |
| `eth_getTransactionByBlockHashAndIndex`   | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `eth_getTransactionByBlockNumberAndIndex` | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `eth_getTransactionByHash`                | Available      |                                                                                                 |
| `eth_getTransactionCount`                 | Available      |                                                                                                 |
| `eth_getTransactionReceipt`               | Available      |                                                                                                 |
| `eth_getUncleByBlockHashAndIndex`         | Available      | Returns `null` for valid MegaETH blocks.                                                        |
| `eth_getUncleByBlockNumberAndIndex`       | Available      | Returns `null` for valid MegaETH blocks.                                                        |
| `eth_getUncleCountByBlockHash`            | Available      | Returns `0x0` for valid MegaETH blocks.                                                         |
| `eth_getUncleCountByBlockNumber`          | Available      | Returns `0x0` for valid MegaETH blocks.                                                         |
| `eth_getWithdrawalProof`                  | Available      | OP Stack withdrawal proof method.                                                               |
| `eth_maxPriorityFeePerGas`                | Available      |                                                                                                 |
| `eth_mining`                              | Unavailable    | The node reports the method as unimplemented.                                                   |
| `eth_newBlockFilter`                      | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `eth_newFilter`                           | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `eth_newPendingTransactionFilter`         | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `eth_protocolVersion`                     | Available      | Legacy compatibility method.                                                                    |
| `eth_sendRawTransaction`                  | Available      |                                                                                                 |
| `eth_sendRawTransactionSync`              | Available      | MegaETH-specific synchronous receipt method.                                                    |
| `eth_subscribe`                           | WebSocket only | Supports six subscription types; see the method page.                                           |
| `eth_syncing`                             | Available      |                                                                                                 |
| `eth_uninstallFilter`                     | Available      | Returns `false` when the filter ID does not exist.                                              |
| `eth_unsubscribe`                         | WebSocket only |                                                                                                 |
| `mega_getBlockWitness`                    | Available      | MegaETH-specific.                                                                               |
| `mega_getWithdrawalProof`                 | Available      | Alias routed to `eth_getWithdrawalProof`.                                                       |
| `mega_outputAtBlock`                      | Available      | OP Stack output-root method.                                                                    |
| `net_listening`                           | Available      |                                                                                                 |
| `net_peerCount`                           | Available      |                                                                                                 |
| `net_version`                             | Available      |                                                                                                 |
| `optimism_outputAtBlock`                  | Available      | Alias of `mega_outputAtBlock`.                                                                  |
| `realtime_sendRawTransaction`             | Available      | MegaETH-specific synchronous receipt method.                                                    |
| `trace_block`                             | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `trace_call`                              | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `trace_transaction`                       | Unavailable    | The public endpoint returns `-32601`.                                                           |
| `web3_clientVersion`                      | Available      |                                                                                                 |

## State and simulation

* [`eth_accounts`](/developer-docs/rpc/reference/eth_accounts)
* [`eth_call`](/developer-docs/rpc/reference/eth_call)
* [`eth_callMany`](/developer-docs/rpc/reference/eth_callmany)
* [`eth_createAccessList`](/developer-docs/rpc/reference/eth_createaccesslist)
* [`eth_estimateGas`](/developer-docs/rpc/reference/eth_estimategas)
* [`eth_getBalance`](/developer-docs/rpc/reference/eth_getbalance)
* [`eth_getCode`](/developer-docs/rpc/reference/eth_getcode)
* [`eth_getCodeByHash`](/developer-docs/rpc/reference/eth_getcodebyhash)
* [`eth_getStorageAt`](/developer-docs/rpc/reference/eth_getstorageat)
* [`eth_getTransactionCount`](/developer-docs/rpc/reference/eth_gettransactioncount)

## Blocks, transactions, and receipts

* [`eth_blockNumber`](/developer-docs/rpc/reference/eth_blocknumber)
* [`eth_getBlockByHash`](/developer-docs/rpc/reference/eth_getblockbyhash)
* [`eth_getBlockByNumber`](/developer-docs/rpc/reference/eth_getblockbynumber)
* [`eth_getBlockReceipts`](/developer-docs/rpc/reference/eth_getblockreceipts)
* [`eth_getBlockTransactionCountByHash`](/developer-docs/rpc/reference/eth_getblocktransactioncountbyhash)
* [`eth_getBlockTransactionCountByNumber`](/developer-docs/rpc/reference/eth_getblocktransactioncountbynumber)
* [`eth_getHeaderByHash`](/developer-docs/rpc/reference/eth_getheaderbyhash)
* [`eth_getHeaderByNumber`](/developer-docs/rpc/reference/eth_getheaderbynumber)
* [`eth_getTransactionByHash`](/developer-docs/rpc/reference/eth_gettransactionbyhash)
* [`eth_getTransactionReceipt`](/developer-docs/rpc/reference/eth_gettransactionreceipt)
* [`eth_getUncleByBlockHashAndIndex`](/developer-docs/rpc/reference/eth_getunclebyblockhashandindex)
* [`eth_getUncleByBlockNumberAndIndex`](/developer-docs/rpc/reference/eth_getunclebyblocknumberandindex)
* [`eth_getUncleCountByBlockHash`](/developer-docs/rpc/reference/eth_getunclecountbyblockhash)
* [`eth_getUncleCountByBlockNumber`](/developer-docs/rpc/reference/eth_getunclecountbyblocknumber)
* [`eth_syncing`](/developer-docs/rpc/reference/eth_syncing)

## Logs and subscriptions

* [`eth_getLogs`](/developer-docs/rpc/reference/eth_getlogs)
* [`eth_subscribe`](/developer-docs/rpc/reference/eth_subscribe) — WebSocket only
* [`eth_uninstallFilter`](/developer-docs/rpc/reference/eth_uninstallfilter)
* [`eth_unsubscribe`](/developer-docs/rpc/reference/eth_unsubscribe) — WebSocket only

## Fees and transaction submission

* [`eth_feeHistory`](/developer-docs/rpc/reference/eth_feehistory)
* [`eth_gasPrice`](/developer-docs/rpc/reference/eth_gasprice)
* [`eth_maxPriorityFeePerGas`](/developer-docs/rpc/reference/eth_maxpriorityfeepergas)
* [`eth_sendRawTransaction`](/developer-docs/rpc/reference/eth_sendrawtransaction)
* [`eth_sendRawTransactionSync`](/developer-docs/rpc/reference/eth_sendrawtransactionsync)
* [`realtime_sendRawTransaction`](/developer-docs/rpc/reference/realtime_sendrawtransaction)

## Debug methods

* [`debug_getHistoryTransactionCount`](/developer-docs/rpc/reference/debug_gethistorytransactioncount)
* [`debug_getRawHeader`](/developer-docs/rpc/reference/debug_getrawheader)
* [`debug_traceBlockByHash`](/developer-docs/rpc/reference/debug_traceblockbyhash)
* [`debug_traceBlockByNumber`](/developer-docs/rpc/reference/debug_traceblockbynumber)
* [`debug_traceTransaction`](/developer-docs/rpc/reference/debug_tracetransaction)

## MegaETH and OP Stack methods

* [`eth_getWithdrawalProof`](/developer-docs/rpc/reference/eth_getwithdrawalproof)
* [`mega_getBlockWitness`](/developer-docs/rpc/reference/mega_getblockwitness)
* [`mega_getWithdrawalProof`](/developer-docs/rpc/reference/mega_getwithdrawalproof)
* [`mega_outputAtBlock`](/developer-docs/rpc/reference/mega_outputatblock)
* [`optimism_outputAtBlock`](/developer-docs/rpc/reference/optimism_outputatblock)

## Network and client information

* [`eth_chainId`](/developer-docs/rpc/reference/eth_chainid)
* [`eth_protocolVersion`](/developer-docs/rpc/reference/eth_protocolversion)
* [`net_listening`](/developer-docs/rpc/reference/net_listening)
* [`net_peerCount`](/developer-docs/rpc/reference/net_peercount)
* [`net_version`](/developer-docs/rpc/reference/net_version)
* [`web3_clientVersion`](/developer-docs/rpc/reference/web3_clientversion)


# debug\_getHistoryTransactionCount

debug\_getHistoryTransactionCount JSON-RPC reference for MegaETH.

## Summary

Returns the chain-wide cumulative transaction count up to and including a given block.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`block`** string **REQUIRED**

Hex block number or tag (`earliest`, `latest`, `safe`, `finalized`). `pending` is not supported.

## Result

**`result`** Quantity

Cumulative transaction count across all blocks up to the selected block. Consecutive blocks with no transactions return the same value.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`debug_getHistoryTransactionCount` is not part of the core Ethereum execution JSON-RPC API. It is a MegaETH debug extension.

### MegaETH Node Behavior

MegaETH adds this diagnostic method. It resolves the selected block and returns the cumulative transaction count through that block; `pending` is not a supported selector.

### MegaETH Public Gateway

The public gateway exposes the method in the simple read tier and caches resolved results as immutable data for 30 minutes.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                                                 |
| -------- | ---------------- | ------------------- | ------------------------------------------------------------------------------- |
| `-32001` | Method           | Resource not found  | Block selector cannot be resolved or unsupported tag such as `pending` was used |
| `-32602` | Request          | Invalid params      | Invalid parameter shape                                                         |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget.                     |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit.                     |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "debug_getHistoryTransactionCount",
  "params": ["0x12a05f"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x12cbab"
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/debug.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# debug\_getRawHeader

Returns the RLP-encoded header for a MegaETH block.

## Summary

Returns a block header encoded with Recursive Length Prefix (RLP). The public MegaETH endpoint supports this standard debug method.

## Parameters

| Position | Name    | Type                    | Required | Description                                                              |
| -------- | ------- | ----------------------- | -------- | ------------------------------------------------------------------------ |
| `0`      | `block` | `QUANTITY` or block tag | Yes      | Block number or `latest`, `safe`, `finalized`, `earliest`, or `pending`. |

## Result

The result is a `DATA` value containing the RLP-encoded header. Decode the bytes as an Ethereum block header rather than treating them as a JSON block object.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The method returns the canonical RLP representation of the selected block header.

### MegaETH Node Behavior

MegaETH exposes the method through its debug namespace and accepts a block number or tag. The encoded header includes the fields used by the selected MegaETH hardfork.

### MegaETH Public Gateway

The public gateway forwards this method through its compute pool and may cache immutable block selections.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                     |
| -------- | ---------------- | ----------------- | --------------------------------------------------- |
| `-32602` | Method           | Invalid params    | The block selector is missing or malformed.         |
| `-32000` | Method           | Server error      | The block is unavailable or cannot be encoded.      |
| `-32099` | Transport/policy | Payload too large | The request exceeds the public endpoint body limit. |

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "debug_getRawHeader",
  "params": ["0x1"]
}
```

The RLP value is abbreviated below.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0xf9026ba09425ed45fa0843e257166258f69bced9ef9eb2d0bb23c6b5a901fba3…"
}
```

## Sources

* Spec: [Ethereum Execution APIs, `src/debug/getters.yaml`](https://github.com/ethereum/execution-apis/blob/50d1e5e0b6f5a5046e45421e5c84497ab6e55e6c/src/debug/getters.yaml)
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# debug\_traceBlockByHash

Replays every transaction in a MegaETH block selected by hash and returns execution traces.

## Summary

Replays a block selected by hash and returns one execution trace per transaction. The public MegaETH endpoint supports this standard debug method.

## Parameters

| Position | Name          | Type             | Required                  | Description                                                                   |
| -------- | ------------- | ---------------- | ------------------------- | ----------------------------------------------------------------------------- |
| `0`      | `blockHash`   | `DATA`, 32 bytes | Yes                       | Hash of the block to replay.                                                  |
| `1`      | `traceConfig` | object           | Yes on the public gateway | Tracer selection and tracer-specific options. Use `{}` for the opcode tracer. |

Common `traceConfig` fields include `tracer`, `tracerConfig`, and `timeout`. For example, set `tracer` to `"callTracer"` for a nested call frame instead of opcode-level `structLogs`.

## Result

The result is an array ordered by transaction index. Each entry contains `txHash` and either `result` or `error`; the shape of `result` depends on the selected tracer.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The method replays all transactions in the selected block against its parent state. The genesis block cannot be replayed because it has no parent state.

### MegaETH Node Behavior

MegaETH uses the standard geth-compatible tracer options and returns a trace paired with each transaction hash. System transactions may therefore appear in block traces.

### MegaETH Public Gateway

The public gateway streams trace responses because they can be large. It requires two positional parameters and supports `callTracer`.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                                          |
| -------- | ---------------- | ----------------- | ------------------------------------------------------------------------ |
| `-32602` | Method           | Invalid params    | Either positional parameter is missing or malformed.                     |
| `-32000` | Method           | Server error      | The block is unknown, its parent state is unavailable, or tracing fails. |
| `-32099` | Transport/policy | Payload too large | The request exceeds the public endpoint body limit.                      |

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "debug_traceBlockByHash",
  "params": [
    "0x57804c21b747137075b29ce153b4f559345a3624273660c87e81bd57e7cbbc3d",
    { "tracer": "callTracer" }
  ]
}
```

The nested call frame is abbreviated below.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "txHash": "0xecc262f36652019b75f4cb7315ff19f430fc92efd5a8048948400407d55fd904",
      "result": {
        "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001",
        "to": "0x4200000000000000000000000000000000000015",
        "gasUsed": "0xb9d56c",
        "type": "CALL"
      }
    }
  ]
}
```

## Sources

* Spec: [Ethereum Execution APIs, `src/debug/trace.yaml`](https://github.com/ethereum/execution-apis/blob/50d1e5e0b6f5a5046e45421e5c84497ab6e55e6c/src/debug/trace.yaml)
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# debug\_traceBlockByNumber

Replays every transaction in a MegaETH block selected by number and returns execution traces.

## Summary

Replays a block selected by number or tag and returns one execution trace per transaction. The public MegaETH endpoint supports this standard debug method.

## Parameters

| Position | Name          | Type                    | Required                  | Description                                                                   |
| -------- | ------------- | ----------------------- | ------------------------- | ----------------------------------------------------------------------------- |
| `0`      | `block`       | `QUANTITY` or block tag | Yes                       | Block number or `latest`, `safe`, `finalized`, `earliest`, or `pending`.      |
| `1`      | `traceConfig` | object                  | Yes on the public gateway | Tracer selection and tracer-specific options. Use `{}` for the opcode tracer. |

Common `traceConfig` fields include `tracer`, `tracerConfig`, and `timeout`.

## Result

The result is an array ordered by transaction index. Each entry contains `txHash` and either `result` or `error`; the shape of `result` depends on the selected tracer.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The method replays all transactions in the selected block against its parent state. The genesis block cannot be replayed because it has no parent state.

### MegaETH Node Behavior

MegaETH uses geth-compatible tracer options and includes system transactions in the block trace when present.

### MegaETH Public Gateway

The public gateway streams trace responses and requires two positional parameters.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                                               |
| -------- | ---------------- | ----------------- | ----------------------------------------------------------------------------- |
| `-32602` | Method           | Invalid params    | Either positional parameter is missing or malformed.                          |
| `-32000` | Method           | Server error      | The block or parent state is unavailable, a timeout occurs, or tracing fails. |
| `-32099` | Transport/policy | Payload too large | The request exceeds the public endpoint body limit.                           |

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "debug_traceBlockByNumber",
  "params": ["0x1", { "tracer": "callTracer" }]
}
```

The nested call frame is abbreviated below.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "txHash": "0xecc262f36652019b75f4cb7315ff19f430fc92efd5a8048948400407d55fd904",
      "result": {
        "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001",
        "to": "0x4200000000000000000000000000000000000015",
        "gasUsed": "0xb9d56c",
        "type": "CALL"
      }
    }
  ]
}
```

## Sources

* Spec: [Ethereum Execution APIs, `src/debug/trace.yaml`](https://github.com/ethereum/execution-apis/blob/50d1e5e0b6f5a5046e45421e5c84497ab6e55e6c/src/debug/trace.yaml)
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# debug\_traceTransaction

Replays a MegaETH transaction and returns its execution trace.

## Summary

Replays a transaction in its original block context and returns an execution trace. The public MegaETH endpoint supports this standard debug method.

## Parameters

| Position | Name              | Type             | Required                  | Description                                                                   |
| -------- | ----------------- | ---------------- | ------------------------- | ----------------------------------------------------------------------------- |
| `0`      | `transactionHash` | `DATA`, 32 bytes | Yes                       | Hash of a mined transaction.                                                  |
| `1`      | `traceConfig`     | object           | Yes on the public gateway | Tracer selection and tracer-specific options. Use `{}` for the opcode tracer. |

## Result

The result shape depends on the tracer. With no named tracer, the result contains opcode-level `structLogs`; with `callTracer`, it is a nested call frame.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The method reconstructs the transaction's pre-execution state, replays the transaction, and returns the selected trace format.

### MegaETH Node Behavior

MegaETH provides geth-compatible opcode and named tracers. Tracing a system transaction may expose MegaETH system-contract calls.

### MegaETH Public Gateway

The public gateway streams this method's response and requires both positional parameters.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                                                         |
| -------- | ---------------- | ----------------- | --------------------------------------------------------------------------------------- |
| `-32602` | Method           | Invalid params    | The hash or trace configuration is missing or malformed.                                |
| `-32000` | Method           | Server error      | The transaction or required history is unavailable, a timeout occurs, or tracing fails. |
| `-32099` | Transport/policy | Payload too large | The request exceeds the public endpoint body limit.                                     |

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "debug_traceTransaction",
  "params": [
    "0xecc262f36652019b75f4cb7315ff19f430fc92efd5a8048948400407d55fd904",
    { "tracer": "callTracer" }
  ]
}
```

The nested call frame is abbreviated below.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001",
    "to": "0x4200000000000000000000000000000000000015",
    "gas": "0x5f5e100",
    "gasUsed": "0xb9d56c",
    "type": "CALL"
  }
}
```

## Sources

* Spec: [Ethereum Execution APIs, `src/debug/trace.yaml`](https://github.com/ethereum/execution-apis/blob/50d1e5e0b6f5a5046e45421e5c84497ab6e55e6c/src/debug/trace.yaml)
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_accounts

eth\_accounts JSON-RPC reference for MegaETH.

## Summary

Returns a list of addresses controlled by the RPC node.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

None.

## Result

**`result`** Address\[]

Accounts controlled by the RPC node; always empty on public endpoints.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

A self-hosted node can report accounts only when its RPC environment manages keys. The execution client itself does not imply that the public service controls user accounts.

### MegaETH Public Gateway

The gateway does not query a signer or node. It synthesizes an empty array, so an empty result means only that the public endpoint does not manage user keys.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                              |
| -------- | ---------------- | ------------------- | ------------------------------------------------------------ |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's instant read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit.  |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 27, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 41,
  "method": "eth_accounts",
  "params": []
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 41,
  "result": []
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/client.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/hardcoded-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 27, 2026


# eth\_blockNumber

eth\_blockNumber JSON-RPC reference for MegaETH.

## Summary

Returns the latest block number.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

None.

## Result

**`result`** Quantity

Current head block number; advances with each new block.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node returns the current canonical EVM block height. Mini-blocks produced within the current EVM block do not each increment this number.

### MegaETH Public Gateway

The gateway uses the instant read tier and may cache the head number for 1 second. Applications that need mini-block cadence should use WebSocket subscriptions instead.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                              |
| -------- | ---------------- | ------------------- | ------------------------------------------------------------ |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's instant read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit.  |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 21,
  "method": "eth_blockNumber",
  "params": []
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 21,
  "result": "0xaeb3d6"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/client.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_call

eth\_call JSON-RPC reference for MegaETH.

## Summary

Simulates a transaction against a given block's state and returns the result without creating an on-chain transaction.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`transaction`** object **REQUIRED**

Transaction to simulate.

* **`from`** Address

  Caller; set explicitly when `msg.sender` matters.
* **`to`** Address

  Target; `null` for contract-creation simulation.
* **`value`** Quantity

  Wei value sent.
* **`input`** Data

  Calldata; `data` is also accepted but `input` is preferred. If both are present they must be identical.
* **`gas`** Quantity

  Gas cap.
* **`gasPrice`** Quantity

  Legacy gas price; do not combine with EIP-1559 fields.
* **`maxFeePerGas`** Quantity

  EIP-1559 max fee.
* **`maxPriorityFeePerGas`** Quantity

  EIP-1559 priority fee.
* **`nonce`** Quantity

  Caller nonce override.
* **`accessList`** array

  EIP-2930 access list; each entry: `{ "address": Address, "storageKeys": [Bytes32] }`.

***

**`block`** string

Hex block number or tag (`latest`, `safe`, `finalized`, `earliest`, `pending`). The default is `"latest"`.

***

**`stateOverride`** object

Per-address state overrides for this simulation.

Object keyed by address. Each value:

* **`balance`** Quantity

  Override the account balance.
* **`nonce`** Quantity

  Override the account nonce.
* **`code`** Data

  Override the account bytecode.
* **`state`** object

  Replace full storage (slot → value); mutually exclusive with `stateDiff`.
* **`stateDiff`** object

  Patch individual storage slots; mutually exclusive with `state`.
* **`movePrecompileToAddress`** Address

  Move a precompile to the specified address before `code` is applied.

***

**`blockOverrides`** object

Block environment overrides for this simulation.

* **`number`** Quantity

  Override `block.number`.
* **`time`** Quantity

  Override `block.timestamp`.
* **`gasLimit`** Quantity

  Override `block.gasLimit`.
* **`feeRecipient`** Address

  Override `block.coinbase`.
* **`prevRandao`** Quantity

  Override randomness.
* **`baseFeePerGas`** Quantity

  Override `block.baseFee`.
* **`blobBaseFee`** Quantity

  Override blob base fee.

## Result

**`result`** Data

Raw return bytes. Calls to non-contract addresses return `0x`. Reverts surface as JSON-RPC errors, not as a normal result.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node simulates the call against the selected state without persisting changes. MegaETH's execution model applies its multidimensional execution limits in addition to the gas field.

### MegaETH Public Gateway

The gateway routes the request to the compute pool, rewrites it to `mega_callWithBlock`, buffers the rewritten response, and does not cache it. It preserves the caller's `gas` field and separately supplies an internal compute-gas limit of 60,000,000; the internal limit caps compute gas without replacing the total gas budget. The public endpoint permits a 1.5 MiB single-request body.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                              |
| -------- | ---------------- | ------------------- | ------------------------------------------------------------ |
| `-32602` | Request          | Invalid params      | Malformed call object, block selector, or override object    |
| `3`      | Method           | Execution reverted  | Simulated execution reverted                                 |
| `-32000` | Method           | Server error        | Simulation failed or hit an execution limit                  |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's compute read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 1.5 MiB public endpoint limit.  |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 46,
  "method": "eth_call",
  "params": [
    {
      "to": "0x0000000000000000000000000000000000000004",
      "input": "0x11223344"
    },
    "latest"
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 46,
  "result": "0x11223344"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/execute.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/eth/api.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/mega-call-with-block-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_callMany

Executes ordered bundles of read-only calls against a selected MegaETH state.

## Summary

Executes one or more ordered bundles of read-only calls and returns a result for every call. The public MegaETH gateway adds validation, compute limits, and an optional timeout to the node method.

## Parameters

| Position | Name             | Type             | Required | Description                                                        |
| -------- | ---------------- | ---------------- | -------- | ------------------------------------------------------------------ |
| `0`      | `bundles`        | array            | Yes      | One to 100 bundle objects, with at most 100 transactions in total. |
| `1`      | `stateContext`   | object           | Yes      | State against which the bundles execute.                           |
| `2`      | `stateOverrides` | object or `null` | No       | Temporary account-state overrides.                                 |
| `3`      | `timeoutMs`      | integer          | No       | Gateway timeout from 1 to 25,000 milliseconds; defaults to 5,000.  |

Each bundle requires a non-empty `transactions` array and may include a `blockOverride` object. Each transaction uses the standard `eth_call` transaction-call fields. `stateContext.blockNumber` is required and accepts a block number, block tag, or EIP-1898-style block reference. `stateContext.transactionIndex` may be `-1` or a non-negative integer.

## Result

The result is an array of bundle results. Each bundle result is an array containing one object per transaction; a successful call object contains a `value` field with the returned `DATA`.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`eth_callMany` is not part of the core Ethereum JSON-RPC API, although compatible implementations use it for ordered multi-call simulation.

### MegaETH Node Behavior

The MegaETH node executes bundles in order against a shared evolving simulation state and returns a nested result array.

### MegaETH Public Gateway

The gateway accepts two to four positional parameters, limits requests to 100 bundles and 100 total transactions, and limits each call to 60,000,000 compute gas. It applies a 5-second default timeout and accepts an explicit timeout up to 25 seconds.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                                                                             |
| -------- | ---------------- | ----------------- | ----------------------------------------------------------------------------------------------------------- |
| `-32602` | Method           | Invalid params    | Required objects are missing, fields are malformed, or bundle, transaction, or timeout limits are exceeded. |
| `-32000` | Method           | Server error      | A simulation cannot execute or its timeout expires.                                                         |
| `-32099` | Transport/policy | Payload too large | The request exceeds the 1.5 MiB public endpoint body limit.                                                 |

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_callMany",
  "params": [
    [
      {
        "transactions": [
          {
            "to": "0x0000000000000000000000000000000000000000",
            "data": "0x"
          }
        ]
      }
    ],
    { "blockNumber": "latest" }
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [[{ "value": "0x" }]]
}
```

## Sources

* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_chainId

eth\_chainId JSON-RPC reference for MegaETH.

## Summary

Returns the chain ID of the connected network.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

None.

## Result

**`result`** Quantity

The chain ID for the connected network.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node derives this value from its chain specification. MegaETH Mainnet uses chain ID 4326; callers should read the value rather than hardcode it across environments.

### MegaETH Public Gateway

The gateway uses the instant read tier and caches the immutable result for 30 minutes. MegaETH Mainnet returned chain ID 4326 in the captured example.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                              |
| -------- | ---------------- | ------------------- | ------------------------------------------------------------ |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's instant read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit.  |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 31,
  "method": "eth_chainId",
  "params": []
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 31,
  "result": "0x10e6"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/client.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_createAccessList

eth\_createAccessList JSON-RPC reference for MegaETH.

## Summary

Generates an access list for a transaction.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`transaction`** object **REQUIRED**

Transaction to simulate.

* **`from`** Address

  Caller.
* **`to`** Address

  Target; `null` for contract-creation simulation.
* **`value`** Quantity

  Wei value sent.
* **`input`** Data

  Calldata; prefer over `data`.
* **`gas`** Quantity

  Gas cap.
* **`gasPrice`** Quantity

  Legacy gas price; do not combine with EIP-1559 fields.
* **`maxFeePerGas`** Quantity

  EIP-1559 max fee.
* **`maxPriorityFeePerGas`** Quantity

  EIP-1559 priority fee.
* **`nonce`** Quantity

  Caller nonce override.
* **`accessList`** array

  EIP-2930 access list; each entry: `{ "address": Address, "storageKeys": [Bytes32] }`.

***

**`block`** string

Hex block number or tag (`latest`, `safe`, `finalized`, `earliest`, `pending`). The default is `"latest"`.

***

**`stateOverride`** object

Per-address state overrides for this simulation.

Object keyed by address. Each value:

* **`balance`** Quantity

  Override the account balance.
* **`nonce`** Quantity

  Override the account nonce.
* **`code`** Data

  Override the account bytecode.
* **`state`** object

  Replace full storage (slot → value); mutually exclusive with `stateDiff`.
* **`stateDiff`** object

  Patch individual storage slots; mutually exclusive with `state`.
* **`movePrecompileToAddress`** Address

  Move a precompile to the specified address before `code` is applied.

## Result

* **`accessList`** array

  Generated EIP-2930 access list; each entry: `{ "address": Address, "storageKeys": [Bytes32] }`.
* **`gasUsed`** Quantity

  Gas with the generated access list applied.
* **`error`** string

  Execution error when the call reverts; may coexist with `accessList` and `gasUsed`.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node executes the call in access-list collection mode and returns both the accessed addresses and storage keys and the resulting gas usage.

### MegaETH Public Gateway

The gateway routes the method to the compute pool without response caching and permits a 1.5 MiB single-request body. Unlike `eth_call`, gateway source does not add the separate 60,000,000 compute-gas override to this method.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message              | When it happens                                              |
| -------- | ---------------- | -------------------- | ------------------------------------------------------------ |
| `-32602` | Request          | Invalid params       | Malformed transaction object or block selector               |
| `-32000` | Method           | Server error         | Pre-execution check failed (e.g. intrinsic gas too low)      |
| `-32003` | Method           | Transaction rejected | Sender cannot cover gas and value in the selected state      |
| `-32005` | Transport/policy | Rate limit exceeded  | The caller exceeds the public gateway's compute read budget. |
| `-32099` | Transport/policy | Payload too large    | The request body exceeds the 1.5 MiB public endpoint limit.  |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "eth_createAccessList",
  "params": [
    {
      "to": "0x1111111111111111111111111111111111111111",
      "input": "0x"
    },
    "latest"
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "accessList": [],
    "gasUsed": "0xea60"
  }
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/execute.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/eth/api.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_estimateGas

eth\_estimateGas JSON-RPC reference for MegaETH.

## Summary

Estimates the gas required to execute a transaction.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`transaction`** object **REQUIRED**

Transaction to simulate.

* **`from`** Address

  Caller.
* **`to`** Address

  Target; `null` for contract-creation simulation.
* **`value`** Quantity

  Wei value sent.
* **`input`** Data

  Calldata; prefer over `data`.
* **`gas`** Quantity

  Gas cap.
* **`gasPrice`** Quantity

  Legacy gas price; do not combine with EIP-1559 fields.
* **`maxFeePerGas`** Quantity

  EIP-1559 max fee.
* **`maxPriorityFeePerGas`** Quantity

  EIP-1559 priority fee.
* **`nonce`** Quantity

  Caller nonce override.
* **`accessList`** array

  EIP-2930 access list; each entry: `{ "address": Address, "storageKeys": [Bytes32] }`.

***

**`block`** string

Hex block number or tag (`latest`, `safe`, `finalized`, `earliest`, `pending`). The default is `"latest"`.

***

**`stateOverride`** object

Per-address state overrides for this simulation.

Object keyed by address. Each value:

* **`balance`** Quantity

  Override the account balance.
* **`nonce`** Quantity

  Override the account nonce.
* **`code`** Data

  Override the account bytecode.
* **`state`** object

  Replace full storage (slot → value); mutually exclusive with `stateDiff`.
* **`stateDiff`** object

  Patch individual storage slots; mutually exclusive with `state`.
* **`movePrecompileToAddress`** Address

  Move a precompile to the specified address before `code` is applied.

## Result

**`result`** Quantity

Estimated execution gas.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

MegaETH's estimator uses a 60,000-gas intrinsic floor for a basic transfer and supports state overrides. The node also exposes a CPU-limited variant used by the public gateway.

### MegaETH Public Gateway

The gateway routes the request to the compute pool and rewrites it to the node's `eth_estimateGasWithCpuLimit` method. It does not cache the result and supplies an internal CPU-time limit whose source default is 500,000,000 nanoseconds (0.5 seconds). This is distinct from `eth_call`'s 60,000,000 compute-gas limit. The public endpoint permits a 1.5 MiB single-request body.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                                                             |
| -------- | ---------------- | ------------------- | ------------------------------------------------------------------------------------------- |
| `-32602` | Request          | Invalid params      | Malformed transaction fields, fee model, or block selector                                  |
| `-32000` | Method           | Server error        | Estimation failed, hit a provider-side execution limit, or used a rejected explicit gas cap |
| `3`      | Method           | Execution reverted  | Simulated execution reverted                                                                |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's compute read budget.                                |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 1.5 MiB public endpoint limit.                                 |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 57,
  "method": "eth_estimateGas",
  "params": [
    {
      "to": "0x0000000000000000000000000000000000000000",
      "value": "0x0"
    },
    "latest"
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 57,
  "result": "0xea60"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/execute.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/eth/replace.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_feeHistory

eth\_feeHistory JSON-RPC reference for MegaETH.

## Summary

Returns historical gas fee data for a range of blocks.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`blockCount`** Quantity **REQUIRED**

Number of blocks (`1`–`256`).

***

**`newestBlock`** string **REQUIRED**

Hex block number or tag: `latest`, `safe`, `finalized`, `earliest`, `pending`.

***

**`rewardPercentiles`** number\[]

Monotonically increasing values from `0` to `100`; omit to exclude `reward` from the result.

## Result

* **`oldestBlock`** Quantity

  First block in the returned range.
* **`baseFeePerGas`** Quantity\[]

  Base fee per block; length is `blockCount + 1`.
* **`gasUsedRatio`** number\[]

  Gas utilization ratio per block.
* **`reward`** Quantity\[]\[]

  Percentile reward values; present only when `rewardPercentiles` was provided.
* **`baseFeePerBlobGas`** Quantity\[]

  Blob base fee per block when available.
* **`blobGasUsedRatio`** number\[]

  Blob gas utilization ratio per block when available.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node implements the standard fee-history shape. The public gateway does not forward this method to the node, so node-derived fee history must not be inferred from public results.

### MegaETH Public Gateway

The gateway synthesizes this response locally instead of querying a node. It accepts 1 to 256 blocks and currently fills the response with a 1,000,000-wei base fee, 0.1 gas-used ratio, 1-wei blob base fee, zero blob utilization, and zero rewards. Treat these as gateway policy values, not measured historical blocks.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                                 |
| -------- | ---------------- | ------------------- | --------------------------------------------------------------- |
| `-32602` | Request          | Invalid params      | Invalid request shape or `blockCount` outside the allowed range |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget.     |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit.     |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 27, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 66,
  "method": "eth_feeHistory",
  "params": ["0x2", "latest", [25, 75]]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 66,
  "result": {
    "oldestBlock": "0xfffff",
    "baseFeePerGas": ["0xf4240", "0xf4240", "0xf4240"],
    "gasUsedRatio": [0.1, 0.1],
    "reward": [
      ["0x0", "0x0"],
      ["0x0", "0x0"]
    ],
    "baseFeePerBlobGas": ["0x1", "0x1", "0x1"],
    "blobGasUsedRatio": [0, 0]
  }
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/fee_market.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/fee-history-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 27, 2026


# eth\_gasPrice

eth\_gasPrice JSON-RPC reference for MegaETH.

## Summary

Returns the current gas price in wei. Under MegaETH's current fee policy, this method returns `0xf4240` (1,000,000 wei = 0.001 gwei).

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

None.

## Result

**`result`** Quantity

Gas price in wei.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node's gas oracle reflects the active MegaETH fee policy. On Mainnet the observed value was 1,000,000 wei, or 0.001 gwei.

### MegaETH Public Gateway

The gateway uses the simple read path and may cache the head-dependent result for 1 second. The captured Mainnet value was 1,000,000 wei, or 0.001 gwei.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_gasPrice",
  "params": []
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0xf4240"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/fee_market.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getBalance

eth\_getBalance JSON-RPC reference for MegaETH.

## Summary

Returns the ETH balance of an account in wei at a given block.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`address`** Address **REQUIRED**

Target account or contract address.

***

**`block`** string

Hex block number or tag (`latest`, `safe`, `finalized`, `earliest`, `pending`). The default is `"latest"`.

## Result

**`result`** Quantity

Balance in wei. The method returns a zero quantity for unknown accounts and zero-balance accounts alike.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node reads the account balance from the selected state. `latest` and `pending` can include state already visible through MegaETH's real-time mini-block pipeline.

### MegaETH Public Gateway

For `latest` or `pending`, the gateway rewrites the request to `mega_getAccountInfo`, treats `pending` as `latest`, and compares rollback-aware cached metadata with the upstream result. It can return cached data when the upstream fails; historical selectors bypass this account cache.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message                    | When it happens                                              |
| -------- | ---------------- | -------------------------- | ------------------------------------------------------------ |
| `-32602` | Request          | Invalid params             | Malformed address or block selector                          |
| `-32001` | Method           | Resource not found         | Block selector cannot be resolved                            |
| `4444`   | Method           | Pruned history unavailable | Requested historical state is not available                  |
| `-32005` | Transport/policy | Rate limit exceeded        | The caller exceeds the public gateway's instant read budget. |
| `-32099` | Transport/policy | Payload too large          | The request body exceeds the 128 KiB public endpoint limit.  |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 27, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_getBalance",
  "params": ["0x0000000000000000000000000000000000000000", "pending"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x7b0ecf3e28d5"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/state.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/account-query-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 27, 2026


# eth\_getBlockByHash

eth\_getBlockByHash JSON-RPC reference for MegaETH.

## Summary

Returns a block by its hash.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`blockHash`** Hash32 **REQUIRED**

Target block hash.

***

**`fullTransactions`** boolean **REQUIRED**

`false` returns transaction hashes; `true` returns full transaction objects.

## Result

`Block | null` — `null` when the hash is well-formed but does not match any block.

* **`number`** Quantity

  Block number.
* **`hash`** Hash32

  Block hash.
* **`parentHash`** Hash32

  Parent block hash.
* **`timestamp`** Quantity

  Block timestamp.
* **`miner`** Address

  Fee recipient / coinbase.
* **`gasLimit`** Quantity

  Block gas limit.
* **`gasUsed`** Quantity

  Gas consumed by the block.
* **`transactions`** Hash32\[] | Transaction\[]

  Hashes when `fullTransactions = false`; full objects when `true`.

Additional standard fields (`stateRoot`, `logsBloom`, `transactionsRoot`, `receiptsRoot`, `baseFeePerGas`, …) are also included.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node returns the canonical block matching the hash, or `null` if the hash is unknown. It honors the `fullTransactions` response-shape flag.

### MegaETH Public Gateway

The gateway streams and caches successful block responses for 30 minutes, using a hash-to-number mapping to deduplicate entries. A `null` lookup is not cached.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message                    | When it happens                                                |
| -------- | ---------------- | -------------------------- | -------------------------------------------------------------- |
| `-32602` | Request          | Invalid params             | Block hash is malformed or `fullTransactions` is not a boolean |
| `4444`   | Method           | Pruned history unavailable | Requested historical block is not available on this endpoint   |
| `-32005` | Transport/policy | Rate limit exceeded        | The caller exceeds the public gateway's simple read budget.    |
| `-32099` | Transport/policy | Payload too large          | The request body exceeds the 128 KiB public endpoint limit.    |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 74,
  "method": "eth_getBlockByHash",
  "params": [
    "0xe0b5b2b8222c00dcbe9f359fc917a9190127bd1b958e11b6caa2035dd03952f1",
    false
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 74,
  "result": {
    "hash": "0xe0b5b2b8222c00dcbe9f359fc917a9190127bd1b958e11b6caa2035dd03952f1",
    "number": "0x100000",
    "timestamp": "0x692225d3",
    "transactions": [
      "0x243d39c7f6cd74a9a081a6fe4bdfce37ac6136b9454691aeeb9ed77998450cbc"
    ]
  }
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/block.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/get-block-by-hash-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getBlockByNumber

eth\_getBlockByNumber JSON-RPC reference for MegaETH.

## Summary

Returns a block by number or tag.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`block`** string **REQUIRED**

Hex block number or tag: `latest`, `safe`, `finalized`, `earliest`, `pending`.

***

**`fullTransactions`** boolean **REQUIRED**

`false` returns transaction hashes; `true` returns full transaction objects.

## Result

`Block | null` — `null` when the requested block does not exist or is not yet available.

* **`number`** Quantity

  Block number.
* **`hash`** Hash32

  Block hash.
* **`parentHash`** Hash32

  Parent block hash.
* **`timestamp`** Quantity

  Block timestamp.
* **`miner`** Address

  Fee recipient / coinbase.
* **`gasLimit`** Quantity

  Block gas limit.
* **`gasUsed`** Quantity

  Gas consumed by the block.
* **`transactions`** Hash32\[] | Transaction\[]

  Hashes when `fullTransactions = false`; full objects when `true`.

Additional standard fields (`stateRoot`, `logsBloom`, `transactionsRoot`, `receiptsRoot`, `baseFeePerGas`, …) are also included.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node resolves a block number or tag and honors the `fullTransactions` response-shape flag. A missing block is represented by `null`.

### MegaETH Public Gateway

The gateway returns `null` immediately for `pending`. Other responses are streamed and cached; head-following tags use short-lived entries while fixed blocks are treated as immutable.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message                    | When it happens                                                 |
| -------- | ---------------- | -------------------------- | --------------------------------------------------------------- |
| `-32602` | Request          | Invalid params             | Malformed block selector or `fullTransactions` is not a boolean |
| `4444`   | Method           | Pruned history unavailable | Requested historical block is not available on this endpoint    |
| `-32005` | Transport/policy | Rate limit exceeded        | The caller exceeds the public gateway's simple read budget.     |
| `-32099` | Transport/policy | Payload too large          | The request body exceeds the 128 KiB public endpoint limit.     |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 81,
  "method": "eth_getBlockByNumber",
  "params": ["0x100000", false]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 81,
  "result": {
    "hash": "0xe0b5b2b8222c00dcbe9f359fc917a9190127bd1b958e11b6caa2035dd03952f1",
    "number": "0x100000",
    "timestamp": "0x692225d3",
    "transactions": [
      "0x243d39c7f6cd74a9a081a6fe4bdfce37ac6136b9454691aeeb9ed77998450cbc"
    ]
  }
}
```

Pending-block edge case:

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 27, 2026

Outcome: null

```json
{
  "jsonrpc": "2.0",
  "id": 82,
  "method": "eth_getBlockByNumber",
  "params": ["pending", false]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 82,
  "result": null
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/block.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/simple-cache-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 24 and July 27, 2026


# eth\_getBlockReceipts

eth\_getBlockReceipts JSON-RPC reference for MegaETH.

## Summary

Returns all transaction receipts for a block.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`block`** string | object **REQUIRED**

Block number, tag (`earliest`, `latest`, `safe`, `finalized`, `pending`), block hash, or `{"blockHash":"0x…"}` selector object.

## Result

`Receipt[] | null` — receipts for every transaction in the block. The method returns `null` when the block is not found. It returns `[]` when the block exists but contains no transactions.

Each array element contains:

* **`transactionHash`** Hash32

  Transaction hash.
* **`status`** Quantity

  A nonzero status indicates success; zero indicates that execution reverted.
* **`blockHash`** Hash32

  Containing block hash.
* **`blockNumber`** Quantity

  Containing block number.
* **`from`** Address

  Sender.
* **`to`** Address | null

  Recipient; `null` for contract creation.
* **`gasUsed`** Quantity

  Gas consumed by this transaction.
* **`effectiveGasPrice`** Quantity

  Effective gas price.
* **`contractAddress`** Address | null

  Created contract address when applicable.
* **`logs`** Log\[]

  Emitted log entries.

Additional fields include `cumulativeGasUsed`, `logsBloom`, `type`, and L1 fee fields (`l1Fee`, `l1GasPrice`, `l1GasUsed`, etc.).

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node returns all receipts for the selected block. The response can be large because MegaETH blocks can contain many transactions.

### MegaETH Public Gateway

The gateway returns `null` immediately for `pending`, streams large responses, and caches successful results for up to 30 minutes. The method is in the IO-heavy read tier.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message                    | When it happens                                               |
| -------- | ---------------- | -------------------------- | ------------------------------------------------------------- |
| `-32602` | Request          | Invalid params             | Malformed or unsupported block selector                       |
| `4444`   | Method           | Pruned history unavailable | Historical block data unavailable on this endpoint            |
| `-32005` | Transport/policy | Rate limit exceeded        | The caller exceeds the public gateway's IO-heavy read budget. |
| `-32099` | Transport/policy | Payload too large          | The request body exceeds the 128 KiB public endpoint limit.   |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 16,
  "method": "eth_getBlockReceipts",
  "params": [
    {
      "blockHash": "0x57804c21b747137075b29ce153b4f559345a3624273660c87e81bd57e7cbbc3d"
    }
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 16,
  "result": [
    {
      "type": "0x7e",
      "status": "0x1",
      "cumulativeGasUsed": "0xb9d56c",
      "logs": [],
      "depositNonce": "0x0",
      "depositReceiptVersion": "0x1",
      "transactionHash": "0xecc262f36652019b75f4cb7315ff19f430fc92efd5a8048948400407d55fd904",
      "transactionIndex": "0x0",
      "blockHash": "0x57804c21b747137075b29ce153b4f559345a3624273660c87e81bd57e7cbbc3d",
      "blockNumber": "0x1",
      "gasUsed": "0xb9d56c",
      "effectiveGasPrice": "0x0",
      "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001",
      "to": "0x4200000000000000000000000000000000000015",
      "contractAddress": null,
      "l1GasPrice": "0x22ba611d",
      "l1GasUsed": "0x6e7",
      "l1Fee": "0x0",
      "l1BaseFeeScalar": "0x558",
      "l1BlobBaseFee": "0x7",
      "l1BlobBaseFeeScalar": "0xc5fc5"
    }
  ]
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/block.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/simple-cache-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getBlockTransactionCountByHash

eth\_getBlockTransactionCountByHash JSON-RPC reference for MegaETH.

## Summary

Returns the number of transactions in the block matching the given hash.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`blockHash`** Hash32 **REQUIRED**

Target block hash.

## Result

**`result`** Quantity | null

Transaction count; `null` when the block is not found.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node looks up the block and returns its transaction count. An unknown block produces `null`.

### MegaETH Public Gateway

The gateway caches successful hash-based lookups for 30 minutes in the simple read tier.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32602` | Request          | Invalid params      | Block hash missing or malformed                             |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "eth_getBlockTransactionCountByHash",
  "params": [
    "0xa97b8563203de36f0c8430709734438fbf7f2444b6de9f307853fc46b230de3e"
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": "0x18"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/block.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getBlockTransactionCountByNumber

eth\_getBlockTransactionCountByNumber JSON-RPC reference for MegaETH.

## Summary

Returns the number of transactions in a block identified by block number or tag.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`block`** string **REQUIRED**

Hex block number or tag: `latest`, `safe`, `finalized`, `earliest`, `pending`.

## Result

**`result`** Quantity | null

Transaction count; `null` when the block is not found.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node resolves the number or tag and returns the block's transaction count. An unknown block produces `null`.

### MegaETH Public Gateway

The gateway caches successful fixed-block lookups for 30 minutes in the simple read tier.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32602` | Request          | Invalid params      | Block selector is malformed                                 |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "eth_getBlockTransactionCountByNumber",
  "params": ["0xb11362"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 4,
  "result": "0x17"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/block.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getCode

eth\_getCode JSON-RPC reference for MegaETH.

## Summary

Returns the runtime bytecode stored at an address at a given block.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`address`** Address **REQUIRED**

Target account or contract address.

***

**`block`** string

Hex block number, block hash, or tag (`latest`, `safe`, `finalized`, …). The default is `"latest"`.

## Result

**`result`** Data

Runtime bytecode (not creation bytecode) at the address; `0x` when no code is deployed.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node returns runtime bytecode from the selected state. A missing account and an account with no code are both represented by empty bytecode.

### MegaETH Public Gateway

The gateway streams bytecode responses and caches successful fixed-state lookups for up to 30 minutes. The exact cache key follows the address and block selector.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message                    | When it happens                                             |
| -------- | ---------------- | -------------------------- | ----------------------------------------------------------- |
| `-32602` | Request          | Invalid params             | Malformed address or block selector                         |
| `-32001` | Method           | Resource not found         | Block selector cannot be resolved                           |
| `4444`   | Method           | Pruned history unavailable | Requested historical state is unavailable                   |
| `-32005` | Transport/policy | Rate limit exceeded        | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large          | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "eth_getCode",
  "params": ["0x4200000000000000000000000000000000000011", "latest"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": "0x6080604052\u2026"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/state.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getCodeByHash

eth\_getCodeByHash JSON-RPC reference for MegaETH.

## Summary

Returns runtime bytecode for a given code hash.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`codeHash`** Hash32 **REQUIRED**

Target runtime code hash.

## Result

**`result`** Data

Runtime bytecode; `0x` when no bytecode is stored for that hash.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`eth_getCodeByHash` is not part of the core Ethereum execution JSON-RPC API. It is an implementation-specific extension.

### MegaETH Node Behavior

MegaETH adds a direct code-hash lookup that returns the stored runtime bytecode. An unknown code hash produces empty bytecode rather than an account lookup.

### MegaETH Public Gateway

The public gateway exposes this MegaETH extension and caches successful immutable lookups for 30 minutes.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 43,
  "method": "eth_getCodeByHash",
  "params": [
    "0xfa8c9db6c6cab7108dea276f4cd09d575674eb0852c0fa3187e59e98ef977998"
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 43,
  "result": "0x6080604052\u2026"
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/eth/ext.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getHeaderByHash

eth\_getHeaderByHash JSON-RPC reference for MegaETH.

## Summary

Returns a block header by its hash.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`blockHash`** Hash32 **REQUIRED**

Target block hash.

## Result

`Header | null` — `null` when the hash does not match any known block.

* **`number`** Quantity

  Block number.
* **`hash`** Hash32

  Block hash.
* **`parentHash`** Hash32

  Parent block hash.
* **`timestamp`** Quantity

  Block timestamp.
* **`miner`** Address

  Fee recipient / coinbase.
* **`gasLimit`** Quantity

  Block gas limit.
* **`gasUsed`** Quantity

  Gas consumed.

Additional standard header fields (`stateRoot`, `logsBloom`, `transactionsRoot`, `receiptsRoot`, `baseFeePerGas`, …) are also included.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`eth_getHeaderByHash` is not part of the core Ethereum execution JSON-RPC API. It is an implementation-specific extension.

### MegaETH Node Behavior

MegaETH exposes a header-only lookup. It returns `null` when the hash is unknown and avoids serializing the block body.

### MegaETH Public Gateway

The gateway streams successful responses, caches them for 30 minutes, and records a hash-to-number mapping. A `null` result is deliberately not cached.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32602` | Request          | Invalid params      | Block hash is missing or malformed                          |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 26,
  "method": "eth_getHeaderByHash",
  "params": [
    "0x6f3fcff78eefe9591d2ad590b8a78738b8ad80d9646eccd302618cd9198b73e0"
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 26,
  "result": {
    "hash": "0x6f3fcff78eefe9591d2ad590b8a78738b8ad80d9646eccd302618cd9198b73e0",
    "parentHash": "0x6b6b52368c21dcdba7348fa37edae3e945013627a83a96b64d55217696899d30",
    "stateRoot": "0xf328fa2752aea1c211a73067d17c25d09a416b4b6a7785441f39bcc930028717",
    "number": "0xb10f64",
    "timestamp": "0x69c33537",
    "baseFeePerGas": "0xf4240"
  }
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/eth/ext.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/get-header-by-hash-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getHeaderByNumber

eth\_getHeaderByNumber JSON-RPC reference for MegaETH.

## Summary

Returns a header-only view of a block by number or block tag.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`block`** string **REQUIRED**

Hex block number or tag: `latest`, `safe`, `finalized`, `earliest`, `pending`.

## Result

`Header | null` — `null` when the block is not found.

* **`number`** Quantity

  Block number.
* **`hash`** Hash32

  Block hash.
* **`parentHash`** Hash32

  Parent block hash.
* **`timestamp`** Quantity

  Block timestamp.
* **`miner`** Address

  Fee recipient / coinbase.
* **`gasLimit`** Quantity

  Block gas limit.
* **`gasUsed`** Quantity

  Gas consumed.

Additional standard header fields (`stateRoot`, `logsBloom`, `transactionsRoot`, `receiptsRoot`, `baseFeePerGas`, …) are also included.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`eth_getHeaderByNumber` is not part of the core Ethereum execution JSON-RPC API. It is an implementation-specific extension.

### MegaETH Node Behavior

MegaETH exposes a header-only lookup by number or tag. It returns `null` when the block cannot be resolved.

### MegaETH Public Gateway

The gateway returns `null` immediately for `pending`; other header responses are streamed and cached, with fixed blocks treated as immutable.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                                |
| -------- | ---------------- | ------------------- | -------------------------------------------------------------- |
| `-32602` | Request          | Invalid params      | Malformed selector, decimal string, or unsupported object form |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget.    |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit.    |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 27,
  "method": "eth_getHeaderByNumber",
  "params": ["0xb11048"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 27,
  "result": {
    "hash": "0x235d80b5e91125a1a1d6da6776c6a9ee087d1818c494f71736b09bed61b1411e",
    "parentHash": "0x6fc0412abfba89bbfab17b2d8bd36cb1c214c1d53ed213fa8958439d0c4f9c18",
    "stateRoot": "0x301d7b77a74893451bd76e5d1672aaaa493cd78c06d59e885218d48917a35c03",
    "number": "0xb11048",
    "timestamp": "0x69c3361b",
    "baseFeePerGas": "0xf4240"
  }
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/eth/ext.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/simple-cache-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getLogs

eth\_getLogs JSON-RPC reference for MegaETH.

## Summary

Returns event logs emitted by smart contracts, filtered by block range, contract address, and/or topics.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`filter`** object **REQUIRED**

Log filter.

* **`fromBlock`** string

  Inclusive start as a hex block number or tag. The default is `latest`.
* **`toBlock`** string

  Inclusive end as a hex block number or tag. The default is `latest`.
* **`blockHash`** Hash32

  Single-block mode; mutually exclusive with `fromBlock`/`toBlock`.
* **`address`** Address | Address\[]

  Filter by emitting address(es).
* **`topics`** array

  Positional topic filter where positions are AND and values within a position are OR. Use `null` for wildcards.

## Result

`Log[]` — array of matching log entries.

* **`address`** Address

  Emitting contract.
* **`topics`** Hash32\[]

  Indexed topics.
* **`data`** Data

  Unindexed payload.
* **`blockNumber`** Quantity | null

  Containing block number.
* **`transactionHash`** Hash32 | null

  Containing transaction hash.
* **`transactionIndex`** Quantity | null

  Transaction position in block.
* **`logIndex`** Quantity | null

  Log position in block.
* **`removed`** boolean

  `true` if removed during reorg.
* **`blockTimestamp`** Quantity

  Block timestamp.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node applies the standard address/topic filter and enforces canonical block-selector encoding. Backend retention can still affect historical ranges.

### MegaETH Public Gateway

The gateway places the method in the IO-heavy tier, routes older explicit ranges to its ClickHouse-backed log service when configured, streams the response, and caches only cache-safe filters. There is no gateway block-range cap, but backend row, time, or memory limits can still make very large queries incomplete or fail.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                                        |
| -------- | ---------------- | ------------------- | ---------------------------------------------------------------------- |
| `-32602` | Request          | Invalid params      | Filter is malformed or combines `blockHash` with `fromBlock`/`toBlock` |
| `-32001` | Method           | Resource not found  | Provided `blockHash` cannot be resolved                                |
| `-32000` | Method           | Server error        | Query range is too large for the endpoint                              |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's IO-heavy read budget.          |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit.            |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 110,
  "method": "eth_getLogs",
  "params": [
    {
      "fromBlock": "0xb120c6",
      "toBlock": "0xb120c6",
      "address": "0xf818c8da51f9a712cfbcddd44d0c445fa1a104e6",
      "topics": [
        "0x994d1f10d7d73f3765b557bce9826b2fafd1bad3862fa6192211b39a12183815",
        "0x00000000000000000000000000000000000000000000000000000000000000d8"
      ]
    }
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 110,
  "result": [
    {
      "address": "0xf818c8da51f9a712cfbcddd44d0c445fa1a104e6",
      "topics": [
        "0x994d1f10d7d73f3765b557bce9826b2fafd1bad3862fa6192211b39a12183815",
        "0x00000000000000000000000000000000000000000000000000000000000000d8"
      ],
      "data": "0x0000000000000000000954150000002f000000000000d6d800000000006ec9a2",
      "blockNumber": "0xb120c6",
      "blockTimestamp": "0x69c34699",
      "transactionHash": "0xf3473347041eb4ccc045ee58e6c79c80d98ee4aa783d49e49c69d0a0e50d8ed6",
      "logIndex": "0x24",
      "removed": false
    }
  ]
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/filter.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/filter.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/eth-logs-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getStorageAt

eth\_getStorageAt JSON-RPC reference for MegaETH.

## Summary

Returns the 32-byte value stored at a given contract storage slot at a specified block.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`address`** Address **REQUIRED**

Contract address.

***

**`slot`** string **REQUIRED**

Hex storage slot; use a 32-byte zero-padded value for portability.

***

**`block`** string

Hex block number, block hash, or tag (`latest`, `safe`, `finalized`, …). The default is `"latest"`.

## Result

**`result`** Bytes32

Raw 32-byte storage word; a zero value can mean an empty slot, a non-existent account, or an explicitly stored zero.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node reads a 32-byte storage word from the selected state. A zero word does not distinguish absent storage from an explicitly stored zero.

### MegaETH Public Gateway

The gateway exposes the method in the instant read tier and does not cache the response. Historical-state retention errors from the selected backend remain visible to callers.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message                    | When it happens                                              |
| -------- | ---------------- | -------------------------- | ------------------------------------------------------------ |
| `-32602` | Request          | Invalid params             | Address, slot encoding, or block selector is malformed       |
| `-32001` | Method           | Resource not found         | Block selector cannot be resolved                            |
| `4444`   | Method           | Pruned history unavailable | Requested historical state is unavailable                    |
| `-32005` | Transport/policy | Rate limit exceeded        | The caller exceeds the public gateway's instant read budget. |
| `-32099` | Transport/policy | Payload too large          | The request body exceeds the 128 KiB public endpoint limit.  |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 63,
  "method": "eth_getStorageAt",
  "params": [
    "0x4200000000000000000000000000000000000011",
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0xb11048"
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 63,
  "result": "0x000000000000000000000000000000000000000000000001bce8287cf283cc16"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/state.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getTransactionByHash

eth\_getTransactionByHash JSON-RPC reference for MegaETH.

## Summary

Returns a transaction by its hash.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`transactionHash`** Hash32 **REQUIRED**

Target transaction hash.

## Result

`Transaction | null` — `null` when the transaction cannot be found.

* **`hash`** Hash32

  Transaction hash.
* **`type`** Quantity

  Transaction type identifier.
* **`from`** Address

  Sender.
* **`to`** Address | null

  Recipient; `null` for contract creation.
* **`value`** Quantity

  Transfer value in wei.
* **`nonce`** Quantity

  Sender nonce.
* **`gas`** Quantity

  Gas limit.
* **`input`** Data

  Calldata.
* **`blockHash`** Hash32 | null

  `null` for pending transactions.
* **`blockNumber`** Quantity | null

  `null` for pending transactions.
* **`transactionIndex`** Quantity | null

  `null` for pending transactions.

Additional fields vary by transaction type (`gasPrice`, `maxFeePerGas`, `accessList`, `chainId`, `v`, `r`, `s`, etc.).

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node returns a transaction known to canonical storage or the live transaction view; an unknown hash produces `null`.

### MegaETH Public Gateway

The gateway caches included transactions for 30 minutes. A `null` result is not cached, so a later request can observe a transaction that has since become available.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32602` | Request          | Invalid params      | Transaction hash is missing or malformed                    |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 79,
  "method": "eth_getTransactionByHash",
  "params": [
    "0x89f0ccba20d5bbbe1cb6b44fb8d1f9a9e14b620a0b947a3de81cff684462f60c"
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 79,
  "result": {
    "type": "0x0",
    "hash": "0x89f0ccba20d5bbbe1cb6b44fb8d1f9a9e14b620a0b947a3de81cff684462f60c",
    "from": "0xa887dcb9d5f39ef79272801d05abdf707cfbbd1d",
    "to": "0x6342000000000000000000000000000000000001",
    "nonce": "0x597ac57",
    "gas": "0x3d5720",
    "value": "0x0",
    "blockHash": "0xf773491fd24617452b30c3ed626bf440b5846b9c818ec7d8d7f71c9a02993c8b",
    "blockNumber": "0xb120c6",
    "transactionIndex": "0x1"
  }
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/transaction.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/get-tx-by-hash-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getTransactionCount

eth\_getTransactionCount JSON-RPC reference for MegaETH.

## Summary

Returns the number of transactions sent from an address at a given block.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`address`** Address **REQUIRED**

Target account address.

***

**`block`** string

Hex block number or tag (`latest`, `safe`, `finalized`, `earliest`, `pending`). The default is `"latest"`.

## Result

**`result`** Quantity

Transaction count at the requested block. The method returns a zero quantity for both unknown accounts and accounts with zero transactions.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node returns the account nonce at the selected state. Unknown accounts and accounts that have not sent transactions both produce a zero quantity.

### MegaETH Public Gateway

For `latest` or `pending`, the gateway rewrites to `mega_getAccountInfo`, treats `pending` as `latest`, and can return a fresh cached nonce immediately. Historical selectors bypass the account cache; a nonce read in the same outer batch as submissions need not include those submissions.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message                    | When it happens                                             |
| -------- | ---------------- | -------------------------- | ----------------------------------------------------------- |
| `-32602` | Request          | Invalid params             | Malformed address or block selector                         |
| `-32001` | Method           | Resource not found         | Block selector cannot be resolved                           |
| `4444`   | Method           | Pruned history unavailable | Requested historical state is unavailable                   |
| `-32005` | Transport/policy | Rate limit exceeded        | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large          | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 91,
  "method": "eth_getTransactionCount",
  "params": ["0xa344fb2d117501ee379d2ea9c0c016959ad94f1e", "0xb120c6"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 91,
  "result": "0xfa8c"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/state.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/account-query-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getTransactionReceipt

eth\_getTransactionReceipt JSON-RPC reference for MegaETH.

## Summary

Returns a transaction receipt by hash.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`transactionHash`** Hash32 **REQUIRED**

Hash of the target transaction.

## Result

`Receipt | null` — `null` when the transaction is unknown or not yet mined.

* **`transactionHash`** Hash32

  Transaction hash.
* **`status`** Quantity

  A nonzero status indicates success; zero indicates that execution reverted.
* **`blockHash`** Hash32

  Containing block hash.
* **`blockNumber`** Quantity

  Containing block number.
* **`from`** Address

  Sender.
* **`to`** Address | null

  Recipient; `null` for contract creation.
* **`gasUsed`** Quantity

  Gas consumed by this transaction.
* **`effectiveGasPrice`** Quantity

  Effective gas price.
* **`contractAddress`** Address | null

  Created contract address when applicable.
* **`logs`** Log\[]

  Emitted log entries.

Additional fields include `cumulativeGasUsed`, `logsBloom`, `type`, and L1 fee fields (`l1Fee`, `l1GasPrice`, `l1GasUsed`, etc.).

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node returns `null` until a receipt is visible. Receipts produced from a real-time mini-block may temporarily use the all-`ff` block-hash placeholder until the EVM block seals.

### MegaETH Public Gateway

The gateway first checks its receipt cache, forwards misses upstream, and caches non-null receipts for 30 minutes. A `null` result is not cached.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32602` | Request          | Invalid params      | Transaction hash is missing or malformed                    |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

The captured response below is abridged. Receipts also include the other fields documented in [Result](#result), including `transactionIndex`, `cumulativeGasUsed`, `logs`, and `logsBloom`.

```json
{
  "jsonrpc": "2.0",
  "id": 120,
  "method": "eth_getTransactionReceipt",
  "params": [
    "0xf3473347041eb4ccc045ee58e6c79c80d98ee4aa783d49e49c69d0a0e50d8ed6"
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 120,
  "result": {
    "type": "0x2",
    "status": "0x1",
    "transactionHash": "0xf3473347041eb4ccc045ee58e6c79c80d98ee4aa783d49e49c69d0a0e50d8ed6",
    "blockHash": "0xf773491fd24617452b30c3ed626bf440b5846b9c818ec7d8d7f71c9a02993c8b",
    "blockNumber": "0xb120c6",
    "gasUsed": "0x215ec",
    "effectiveGasPrice": "0xf4241",
    "from": "0xa344fb2d117501ee379d2ea9c0c016959ad94f1e",
    "to": "0x5e3ae52eba0f9740364bd5dd39738e1336086a8b",
    "contractAddress": null,
    "l1Fee": "0x4ab5901"
  }
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/transaction.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/tx-receipt-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getUncleByBlockHashAndIndex

Returns an uncle block by parent block hash and uncle index.

## Summary

Returns an uncle block selected by its parent block hash and index. MegaETH blocks do not contain proof-of-work uncles, so the method returns `null` for valid MegaETH blocks.

## Parameters

| Position | Name        | Type             | Required | Description                                      |
| -------- | ----------- | ---------------- | -------- | ------------------------------------------------ |
| `0`      | `blockHash` | `DATA`, 32 bytes | Yes      | Hash of the block whose uncle list is inspected. |
| `1`      | `index`     | `QUANTITY`       | Yes      | Zero-based uncle index.                          |

## Result

The result is a block object or `null` when no uncle exists at the selected index. On MegaETH, `null` is expected and does not mean that the parent block itself is missing.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The method returns the uncle header at the selected index as a block object without transactions.

### MegaETH Node Behavior

MegaETH inherits the compatibility method, but its proof-of-stake L2 blocks do not contain proof-of-work uncles.

### MegaETH Public Gateway

The gateway may cache immutable hash selections. A lookup at index zero for a valid Mainnet block returned `null` on July 24, 2026.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                     |
| -------- | ---------------- | ----------------- | --------------------------------------------------- |
| `-32602` | Method           | Invalid params    | The block hash or index is missing or malformed.    |
| `-32099` | Transport/policy | Payload too large | The request exceeds the public endpoint body limit. |

No method-specific errors were observed for a canonical lookup.

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: null

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_getUncleByBlockHashAndIndex",
  "params": [
    "0x57804c21b747137075b29ce153b4f559345a3624273660c87e81bd57e7cbbc3d",
    "0x0"
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": null
}
```

## Sources

* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getUncleByBlockNumberAndIndex

Returns an uncle block by parent block number and uncle index.

## Summary

Returns an uncle block selected by its parent block number or tag and index. MegaETH blocks do not contain proof-of-work uncles, so the method returns `null` for valid MegaETH blocks.

## Parameters

| Position | Name    | Type                    | Required | Description                                                              |
| -------- | ------- | ----------------------- | -------- | ------------------------------------------------------------------------ |
| `0`      | `block` | `QUANTITY` or block tag | Yes      | Block number or `latest`, `safe`, `finalized`, `earliest`, or `pending`. |
| `1`      | `index` | `QUANTITY`              | Yes      | Zero-based uncle index.                                                  |

## Result

The result is a block object or `null` when no uncle exists at the selected index. On MegaETH, `null` is expected and does not mean that the parent block itself is missing.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The method returns the uncle header at the selected index as a block object without transactions.

### MegaETH Node Behavior

MegaETH inherits the compatibility method, but its proof-of-stake L2 blocks do not contain proof-of-work uncles.

### MegaETH Public Gateway

The gateway may cache immutable selections and treats head tags as dynamic. A lookup at index zero for the `latest` block returned `null` on July 24, 2026.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                      |
| -------- | ---------------- | ----------------- | ---------------------------------------------------- |
| `-32602` | Method           | Invalid params    | The block selector or index is missing or malformed. |
| `-32099` | Transport/policy | Payload too large | The request exceeds the public endpoint body limit.  |

No method-specific errors were observed for a canonical lookup.

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: null

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_getUncleByBlockNumberAndIndex",
  "params": ["latest", "0x0"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": null
}
```

## Sources

* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getUncleCountByBlockHash

Returns the number of uncle blocks referenced by a MegaETH block selected by hash.

## Summary

Returns the number of uncle blocks referenced by a block selected by hash. MegaETH does not produce proof-of-work uncles, so valid MegaETH blocks return zero.

## Parameters

| Position | Name        | Type             | Required | Description                   |
| -------- | ----------- | ---------------- | -------- | ----------------------------- |
| `0`      | `blockHash` | `DATA`, 32 bytes | Yes      | Hash of the block to inspect. |

## Result

The result is a hexadecimal `QUANTITY` containing the uncle count. For a valid MegaETH block this is zero.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The method returns the number of uncles referenced by the selected block.

### MegaETH Node Behavior

MegaETH inherits the compatibility method, but its proof-of-stake L2 blocks do not contain proof-of-work uncles.

### MegaETH Public Gateway

The gateway may cache the count for a block hash. A valid Mainnet block returned an uncle count of zero on July 24, 2026.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                     |
| -------- | ---------------- | ----------------- | --------------------------------------------------- |
| `-32602` | Method           | Invalid params    | The block hash is missing or malformed.             |
| `-32099` | Transport/policy | Payload too large | The request exceeds the public endpoint body limit. |

No method-specific errors were observed for a valid block.

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_getUncleCountByBlockHash",
  "params": [
    "0x57804c21b747137075b29ce153b4f559345a3624273660c87e81bd57e7cbbc3d"
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x0"
}
```

## Sources

* Spec: [Ethereum Execution APIs method reference](https://github.com/ethereum/execution-apis/blob/50d1e5e0b6f5a5046e45421e5c84497ab6e55e6c/docs-api/api/methods/eth_getUncleCountByBlockHash.mdx)
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getUncleCountByBlockNumber

Returns the number of uncle blocks referenced by a MegaETH block selected by number.

## Summary

Returns the number of uncle blocks referenced by a block selected by number or tag. MegaETH does not produce proof-of-work uncles, so valid MegaETH blocks return zero.

## Parameters

| Position | Name    | Type                    | Required | Description                                                              |
| -------- | ------- | ----------------------- | -------- | ------------------------------------------------------------------------ |
| `0`      | `block` | `QUANTITY` or block tag | Yes      | Block number or `latest`, `safe`, `finalized`, `earliest`, or `pending`. |

## Result

The result is a hexadecimal `QUANTITY` containing the uncle count. For a valid MegaETH block this is zero.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The method returns the number of uncles referenced by the selected block.

### MegaETH Node Behavior

MegaETH inherits the compatibility method, but its proof-of-stake L2 blocks do not contain proof-of-work uncles.

### MegaETH Public Gateway

The gateway may cache immutable selections and treats head tags as dynamic. The `latest` block returned an uncle count of zero on July 24, 2026.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                     |
| -------- | ---------------- | ----------------- | --------------------------------------------------- |
| `-32602` | Method           | Invalid params    | The block selector is missing or malformed.         |
| `-32099` | Transport/policy | Payload too large | The request exceeds the public endpoint body limit. |

No method-specific errors were observed for a valid block.

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_getUncleCountByBlockNumber",
  "params": ["latest"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x0"
}
```

## Sources

* Spec: [Ethereum Execution APIs method reference](https://github.com/ethereum/execution-apis/blob/50d1e5e0b6f5a5046e45421e5c84497ab6e55e6c/docs-api/api/methods/eth_getUncleCountByBlockNumber.mdx)
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_getWithdrawalProof

Returns a withdrawal-storage proof for MegaETH's L2-to-L1 message passer contract.

## Summary

Returns the same proof as [`mega_getWithdrawalProof`](/developer-docs/rpc/reference/mega_getwithdrawalproof). The gateway routes both method names to the same node implementation.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

| Position | Name          | Type                | Required | Description                                                                                              |
| -------- | ------------- | ------------------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `0`      | `address`     | `Address`           | Yes      | Contract address to prove; use `0x4200000000000000000000000000000000000016` for withdrawal verification. |
| `1`      | `storageKeys` | `Bytes32[]`         | Yes      | Withdrawal-message storage keys to prove; an empty array is valid.                                       |
| `2`      | `block`       | block number or tag | Yes      | State against which to build the proof.                                                                  |

## Result

An EIP-1186-style account proof containing `accountProof`, `balance`, `codeHash`, `nonce`, `storageHash`, and one `storageProof` entry per requested key.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`eth_getWithdrawalProof` is not part of the core Ethereum execution JSON-RPC API. It is a MegaETH compatibility extension for the withdrawal-proof API.

### MegaETH Node Behavior

MegaETH implements this OP Stack withdrawal-proof extension for the L2-to-L1 message passer. It returns an EIP-1186-style account and storage proof.

### MegaETH Public Gateway

The public gateway exposes this method and caches successful proofs for 30 minutes. All three positional parameters are required at the gateway.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 27, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_getWithdrawalProof",
  "params": ["0x4200000000000000000000000000000000000016", [], "latest"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "address": "0x4200000000000000000000000000000000000016",
    "accountProof": [],
    "balance": "0x0",
    "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
    "nonce": "0x0",
    "storageHash": "0x891f4462376be7ecac17a67a0ee5be7bc0c35979c182e5f7f19ebb2b1e320cc3",
    "storageProof": []
  }
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/eth/ext.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 27, 2026


# eth\_maxPriorityFeePerGas

eth\_maxPriorityFeePerGas JSON-RPC reference for MegaETH.

## Summary

Returns the recommended priority fee per gas in wei. MegaETH returns a zero-wei priority fee because priority fees are not needed under the current fee policy.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

None.

## Result

**`result`** Quantity

Always a zero-wei quantity.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node fee policy does not require a priority fee, but the public result is synthesized by the gateway rather than used as evidence of a node query.

### MegaETH Public Gateway

The gateway synthesizes a zero-wei priority fee without calling a node. This is a current MegaETH fee-policy response, not a market estimate.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 27, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_maxPriorityFeePerGas",
  "params": []
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x0"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/fee_market.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc-eth-api/src/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/hardcoded-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 27, 2026


# eth\_protocolVersion

Returns the Ethereum protocol version reported by the MegaETH RPC node.

## Summary

Returns the Ethereum protocol version reported by the connected node. The public MegaETH endpoint supports this legacy compatibility method.

## Parameters

None.

## Result

The result is a hexadecimal `QUANTITY`. Do not confuse this compatibility value with the MegaETH chain ID or network ID.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The legacy method reports an Ethereum wire-protocol version and takes no parameters.

### MegaETH Node Behavior

MegaETH exposes the inherited compatibility method through the `eth` namespace.

### MegaETH Public Gateway

The gateway treats this response as immutable and may cache it. Callers should not use this value for chain selection; use [`eth_chainId`](/developer-docs/rpc/reference/eth_chainid) instead.

## Errors

The `| Scope |` column distinguishes request failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                     |
| -------- | ---------------- | ----------------- | --------------------------------------------------- |
| `-32602` | Request          | Invalid params    | Unexpected parameters are supplied.                 |
| `-32099` | Transport/policy | Payload too large | The request exceeds the public endpoint body limit. |

No method-specific errors were observed.

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_protocolVersion",
  "params": []
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x5"
}
```

## Sources

* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_sendRawTransaction

eth\_sendRawTransaction JSON-RPC reference for MegaETH.

## Summary

Submits a signed transaction to the network and returns its transaction hash.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`rawTx`** Data **REQUIRED**

Signed, RLP-encoded transaction bytes. Supported envelope types are legacy, EIP-2930, EIP-1559, EIP-4844, and EIP-7702.

## Result

**`result`** Data

32-byte transaction hash.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node decodes and validates the signed transaction before admitting it to the transaction pool. Successful submission returns the transaction hash, not an inclusion receipt.

### MegaETH Public Gateway

The gateway validates chain ID, signature, intrinsic gas, fee floor, nonce, balance, and policy checks before forwarding. The method is exempt from read-rate limits and accepts request bodies up to 2.5 MiB.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message              | When it happens                                                                      |
| -------- | ---------------- | -------------------- | ------------------------------------------------------------------------------------ |
| `-32602` | Request          | Invalid params       | Parameter missing, hex malformed, or bytes cannot be decoded as a signed transaction |
| `-32000` | Method           | Server error         | Pool or gateway rule violation                                                       |
| `-32003` | Method           | Transaction rejected | Insufficient sender funds, pool at capacity, or unsupported transaction type         |
| `-32099` | Transport/policy | Payload too large    | The request body exceeds the 2.5 MiB public endpoint limit.                          |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_sendRawTransaction",
  "params": [
    "0xf86c808405763d658261a894aa000000000000000000000000000000000000000a8255448718e5bb3abd109fa0c8e3b4a0087357bd49d80a0ac24daf0c91191e71086c1e355fc62cfab2218873a074f4636f740fa4d1697b6e736e5982b700be2c8b63031a24fa531ae4814b3af8"
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x66734e85ef096167acb887cf445946a1ed57b90b66ffe38af87e11294febbfa9"
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/submit.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/eth/api.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/sequencer-guard/single-tx.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_sendRawTransactionSync

eth\_sendRawTransactionSync JSON-RPC reference for MegaETH.

## Summary

Submits a signed transaction and returns a receipt once the transaction is included in a block. The public gateway routes this method and [`realtime_sendRawTransaction`](/developer-docs/rpc/reference/realtime_sendrawtransaction) through the same synchronous submission handler, with the same parameters and receipt result.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`data`** Data **REQUIRED**

Signed raw transaction bytes.

***

**`timeoutMs`** number

Client wait budget in milliseconds. When omitted, the node uses its 5-second default; the public gateway caps explicit values at `3000` (3 s).

## Result

* **`transactionHash`** Hash32

  Transaction hash.
* **`status`** Quantity

  A nonzero status indicates success; zero means the transaction reverted but was included on-chain.
* **`blockHash`** Hash32

  Containing block hash. A receipt produced from a streaming mini-block can temporarily contain the all-`ff` placeholder hash until the enclosing EVM block is committed. Refetch the receipt with `eth_getTransactionReceipt` after block sealing when a canonical block hash is required.
* **`blockNumber`** Quantity

  Containing block number.
* **`from`** Address

  Sender.
* **`to`** Address | null

  Recipient; `null` for contract creation.
* **`gasUsed`** Quantity

  Gas consumed by this transaction.
* **`effectiveGasPrice`** Quantity

  Effective gas price.
* **`contractAddress`** Address | null

  Created contract address when applicable.
* **`logs`** Log\[]

  Emitted log entries.

Additional fields include `cumulativeGasUsed`, `logsBloom`, `type`, and L1 fee fields (`l1Fee`, `l1GasPrice`, `l1GasUsed`, etc.).

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`eth_sendRawTransactionSync` is not part of the core Ethereum execution JSON-RPC API. It is a compatibility extension exposed by the MegaETH public gateway.

### MegaETH Node Behavior

The current MegaETH node does not register this `eth_*` alias. Its native synchronous submission method is `realtime_sendRawTransaction`; the node waits up to 5 seconds by default for a real-time receipt.

### MegaETH Public Gateway

The gateway exposes this compatibility name and routes it and `realtime_sendRawTransaction` through the same handler. Both are rewritten to the node's `realtime_sendRawTransactionWithSender` method after gateway-side validation. The gateway caps explicit waits at 3,000 milliseconds and accepts request bodies up to 2.5 MiB. An expiry is inconclusive: the transaction may still land.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                                                            |
| -------- | ---------------- | ----------------- | ------------------------------------------------------------------------------------------ |
| `-32602` | Request          | Invalid params    | Raw transaction is malformed, undecodable, or `timeoutMs` is invalid                       |
| `-32000` | Method           | Server error      | Receipt not available before the wait window expired, or the node rejected the transaction |
| `-32099` | Transport/policy | Payload too large | The request body exceeds the 2.5 MiB public endpoint limit.                                |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 91,
  "method": "eth_sendRawTransactionSync",
  "params": [
    "0xf86480830f424082ea6094cc4b43ab7230cc5913801a746c1834aa06c4e7e780808231b2a0b8126d2c41a6c7dbd0a9e219233497057bb391e7ee1d628370f9c1456f82b054a06663fde9daa2fae784c3dac1c9a5a973d538e3a12ec9c0e4d3cee9c70ba2b239",
    3000
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 91,
  "result": {
    "type": "0x0",
    "status": "0x1",
    "transactionHash": "0x8d3b1e22e7a9026c8658b5d922293d59e4de7c3382bb832d6890e6ab23ad7ec7",
    "transactionIndex": "0x5",
    "blockHash": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
    "blockNumber": "0xe7133c",
    "from": "0xcc4b43ab7230cc5913801a746c1834aa06c4e7e7",
    "to": "0xcc4b43ab7230cc5913801a746c1834aa06c4e7e7",
    "gasUsed": "0xea60",
    "effectiveGasPrice": "0xf4240",
    "cumulativeGasUsed": "0x143043",
    "contractAddress": null,
    "logs": [],
    "l1GasPrice": "0x3216",
    "l1GasUsed": "0x640",
    "l1Fee": "0x6da0",
    "l1BaseFeeScalar": "0x558",
    "l1BlobBaseFee": "0x1",
    "l1BlobBaseFeeScalar": "0x0"
  }
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/realtime.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/sequencer-guard/single-tx.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_subscribe

eth\_subscribe — WebSocket subscriptions for block headers, logs, pending transactions, sync status, mini-blocks, and state changes.

## Summary

Creates a WebSocket subscription and returns a connection-scoped subscription ID. MegaETH supports four common Ethereum subscription types and adds `miniBlocks` and `stateChanges`.

Use [`eth_unsubscribe`](/developer-docs/rpc/reference/eth_unsubscribe) on the same connection when the subscription is no longer needed. Notifications are not replayed after a connection closes, so reconnecting clients must recreate subscriptions and reconcile missed data.

## Parameters

| Position | Name           | Type                            | Required | Description                                                                                      |
| -------- | -------------- | ------------------------------- | -------- | ------------------------------------------------------------------------------------------------ |
| `0`      | `subscription` | string                          | Yes      | One of `newHeads`, `logs`, `newPendingTransactions`, `syncing`, `miniBlocks`, or `stateChanges`. |
| `1`      | `options`      | object, boolean, or `Address[]` | No       | Shape depends on the subscription type.                                                          |

### `newHeads`

No options are accepted. Notifications are emitted for sealed EVM block headers.

### `logs`

The optional filter object accepts:

| Field       | Type                     | Required | Description                                                             |
| ----------- | ------------------------ | -------- | ----------------------------------------------------------------------- |
| `fromBlock` | block number or tag      | No       | Set to `pending` or `latest` to receive mini-block log updates.         |
| `toBlock`   | block number or tag      | No       | Upper bound for the filter.                                             |
| `blockHash` | `Hash32`                 | No       | Selects one block and cannot be combined with `fromBlock` or `toBlock`. |
| `address`   | `Address` or `Address[]` | No       | Matches emitting contracts.                                             |
| `topics`    | array                    | No       | Position-sensitive topic filter with OR arrays at individual positions. |

The public gateway accepts at most 20 addresses and four topic positions in one log subscription. For real-time mini-block logs, set both `fromBlock` and `toBlock` to `pending`.

### `newPendingTransactions`

The optional second parameter is a boolean. Omit it or pass `false` to receive transaction hashes, or pass `true` to receive full transaction objects.

### `syncing`

No options are accepted. Notifications report changes in node synchronization status.

### `miniBlocks`

No options are accepted. Notifications contain transactions and receipts as each mini-block is produced.

### `stateChanges`

The optional second parameter is an array of account addresses. Omitting the array or passing an empty array subscribes to all changed accounts. The node defaults to a maximum of 256 addresses in one subscription.

## Result

The initial response returns a subscription ID as `Data`. Later messages use the `eth_subscription` notification envelope:

```json
{
  "jsonrpc": "2.0",
  "method": "eth_subscription",
  "params": {
    "subscription": "0x...",
    "result": {}
  }
}
```

The `result` shape depends on the subscription type.

### `newHeads` result

The result contains the standard Ethereum block-header fields documented by [`eth_getBlockByNumber`](/developer-docs/rpc/reference/eth_getblockbynumber). When block metadata is available, MegaETH also includes:

| Field             | Type       | Description                                    |
| ----------------- | ---------- | ---------------------------------------------- |
| `txOffset`        | `Quantity` | Transaction offset recorded for the block.     |
| `miniBlockOffset` | `Quantity` | Global offset of the block's first mini-block. |
| `miniBlockCount`  | `Quantity` | Number of mini-blocks in the EVM block.        |
| `signature`       | `Data`     | Sequencer signature recorded for the block.    |

### `logs` result

The result uses the log object documented by [`eth_getLogs`](/developer-docs/rpc/reference/eth_getlogs). Mini-block log notifications can contain streaming placeholders until the enclosing EVM block is sealed.

### `newPendingTransactions` result

The result is a transaction `Hash32` by default. When the second parameter is `true`, the result is the full transaction object documented by [`eth_getTransactionByHash`](/developer-docs/rpc/reference/eth_gettransactionbyhash).

### `syncing` result

The result is `false` when the node is not syncing. While syncing, it is the progress object documented by [`eth_syncing`](/developer-docs/rpc/reference/eth_syncing).

### `miniBlocks` result

Mini-block payloads use `snake_case` field names.

| Field                  | Type       | Description                                                                        |
| ---------------------- | ---------- | ---------------------------------------------------------------------------------- |
| `block_number`         | `Quantity` | Number of the enclosing EVM block.                                                 |
| `block_timestamp`      | `Quantity` | Unix timestamp of the enclosing EVM block in seconds.                              |
| `index`                | `Quantity` | Mini-block index within the EVM block.                                             |
| `mini_block_number`    | `Quantity` | Global mini-block number.                                                          |
| `mini_block_timestamp` | `Quantity` | Mini-block Unix timestamp in microseconds.                                         |
| `gas_used`             | `Quantity` | Gas consumed by the mini-block.                                                    |
| `transactions`         | object\[]  | Included transaction objects.                                                      |
| `receipts`             | object\[]  | Corresponding transaction receipts.                                                |
| `transaction_root`     | `Hash32`   | Transaction trie root for the mini-block.                                          |
| `receipt_root`         | `Hash32`   | Receipt trie root for the mini-block.                                              |
| `signature`            | `Data`     | Sequencer signature, omitted for mini-blocks produced before the signing hardfork. |

### `stateChanges` result

Each notification describes one changed account.

| Field     | Type       | Description                                      |
| --------- | ---------- | ------------------------------------------------ |
| `address` | `Address`  | Changed account.                                 |
| `nonce`   | `Quantity` | Current account nonce.                           |
| `balance` | `Quantity` | Current account balance.                         |
| `storage` | object     | Changed storage slots as `{ key: value }` pairs. |

`storage` contains only slots changed in that mini-block. An empty object means that the account's nonce or balance changed without a storage change.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`eth_subscribe` is a WebSocket transport extension rather than an HTTP Execution API method. Ethereum clients commonly support `newHeads`, `logs`, `newPendingTransactions`, and `syncing`, with subscription IDs scoped to one connection.

### MegaETH Node Behavior

MegaETH adds `miniBlocks` and `stateChanges` for updates at mini-block granularity. It enriches `newHeads` with transaction-offset, mini-block, and sequencer-signature metadata. Setting a log subscription's `fromBlock` to `pending` or `latest` selects the mini-block event stream.

### MegaETH Public Gateway

Use `wss://mainnet.megaeth.com/ws` for Mainnet or `wss://carrot.megaeth.com/ws` for Testnet. The public gateway allows all six subscription types and limits each connection to five active subscriptions. Send `eth_chainId` at least every 30 seconds to keep an otherwise idle connection active. See [Operations and limits](/developer-docs/rpc/operations-and-limits#websocket-limits) for the remaining WebSocket limits.

## Errors

| Code     | Scope             | When it happens                                                                                        | Action                                                                 |
| -------- | ----------------- | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- |
| `-32602` | Method            | The subscription type or options are invalid, or a `stateChanges` address list exceeds the node limit. | Correct the type, option shape, filter, or address count.              |
| `-32005` | Gateway or server | The connection subscription cap or server capacity is exhausted.                                       | Unsubscribe from unused streams or reconnect with fewer subscriptions. |

Calling `eth_subscribe` over HTTP does not create a subscription. Use a WebSocket connection and inspect the returned JSON-RPC error if a client sends the method to the wrong transport.

See also [Error reference](/developer-docs/rpc/error-codes).

## Examples

Connect to the Mainnet WebSocket endpoint and subscribe to block headers:

```bash
wscat -c wss://mainnet.megaeth.com/ws
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_subscribe",
  "params": ["newHeads"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0xaec58cfc2dc41f873fc37d6c871230c1"
}
```

Subscribe to pending transaction hashes:

```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "eth_subscribe",
  "params": ["newPendingTransactions"]
}
```

Subscribe to all state changes:

```json
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "eth_subscribe",
  "params": ["stateChanges"]
}
```

Filter state changes by account:

```json
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "eth_subscribe",
  "params": ["stateChanges", ["0xaa000000000000000000000000000000000000aa"]]
}
```

## Sources

* Spec: [EIP-1474](https://eips.ethereum.org/EIPS/eip-1474) for JSON-RPC framing.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/pubsub.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/rpc-gateway/websocket/constants.ts`
* Probe: MegaETH Mainnet public WebSocket endpoint, July 27, 2026.


# eth\_syncing

eth\_syncing JSON-RPC reference for MegaETH.

## Summary

Returns whether the node is currently syncing.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

None.

## Result

`false` when the node is fully synced. When syncing, a `SyncProgress` object:

* **`startingBlock`** Quantity

  Sync start point.
* **`currentBlock`** Quantity

  Current progress.
* **`highestBlock`** Quantity

  Target block.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

The canonical Ethereum method uses the parameter and result contract documented above, including the stated `null`, `false`, or zero-value semantics where applicable.

### MegaETH Node Behavior

The node returns `false` when caught up and a progress object while synchronizing. This reports node synchronization, not L1 finality.

### MegaETH Public Gateway

The gateway forwards this dynamic status without response caching in the simple read tier.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_syncing",
  "params": []
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": false
}
```

## Sources

* Spec: `git@github.com:ethereum/execution-apis.git @ d24f58b56dcd16ab0f0c70ec609bcc1c42750b51: src/eth/client.yaml`
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc/src/eth/core.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_uninstallFilter

Removes an Ethereum log or block filter by ID.

## Summary

Removes a filter and releases the node resources associated with it. The public MegaETH endpoint accepts this standard method even though filter-creation and filter-polling methods are not publicly supported.

## Parameters

| Position | Name       | Type       | Required | Description                                      |
| -------- | ---------- | ---------- | -------- | ------------------------------------------------ |
| `0`      | `filterId` | `QUANTITY` | Yes      | Identifier returned by a filter-creation method. |

## Result

Returns `true` when the filter existed and was removed. Returns `false` when the filter ID was unknown or had already expired. `false` does not mean that `eth_uninstallFilter` itself is unavailable.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

Clients should uninstall a filter when it is no longer needed so the node can release its resources.

### MegaETH Node Behavior

MegaETH inherits the standard filter-removal handler and returns a boolean indicating whether a filter was removed.

### MegaETH Public Gateway

The method returned `false` for an unknown filter ID on July 24, 2026. The public endpoint returned method-not-found errors for `eth_newFilter`, `eth_newBlockFilter`, `eth_newPendingTransactionFilter`, `eth_getFilterChanges`, and `eth_getFilterLogs` on the same date, so public clients normally use [`eth_subscribe`](/developer-docs/rpc/reference/eth_subscribe) instead of filter polling.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                     |
| -------- | ---------------- | ----------------- | --------------------------------------------------- |
| `-32602` | Method           | Invalid params    | The filter ID is missing or malformed.              |
| `-32099` | Transport/policy | Payload too large | The request exceeds the public endpoint body limit. |

No method-specific error was observed for a canonical request.

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: false

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_uninstallFilter",
  "params": ["0x1"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": false
}
```

## Sources

* Spec: [Ethereum Execution APIs, `src/eth/filter.yaml`](https://github.com/ethereum/execution-apis/blob/50d1e5e0b6f5a5046e45421e5c84497ab6e55e6c/src/eth/filter.yaml)
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# eth\_unsubscribe

eth\_unsubscribe JSON-RPC reference for MegaETH.

## Summary

Cancels an existing subscription so that no further events are sent.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`subscriptionId`** Data **REQUIRED**

Subscription ID returned by `eth_subscribe`.

## Result

**`result`** boolean

`true` if the subscription was found and cancelled; `false` if the ID was not active.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`eth_unsubscribe` is part of the commonly implemented Ethereum WebSocket subscription API, but it is not specified by the core execution JSON-RPC API.

### MegaETH Node Behavior

The node cancels a subscription in the WebSocket session that created it. Subscription IDs are connection-scoped.

### MegaETH Public Gateway

The public method is WebSocket-only. The gateway keeps subscription ownership per connection and rejects attempts to cancel a subscription from another session.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope   | Message         | When it happens                                    |
| -------- | ------- | --------------- | -------------------------------------------------- |
| `-32602` | Request | Invalid params  | Subscription ID parameter is missing               |
| `-32600` | Request | Invalid request | Subscription was created by a different connection |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `wss://mainnet.megaeth.com/ws` (WebSocket)

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_unsubscribe",
  "params": ["0xaec58cfc2dc41f873fc37d6c871230c1"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": true
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/eth/api.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/rpc-gateway/websocket-session.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# mega\_getBlockWitness

mega\_getBlockWitness JSON-RPC reference for MegaETH.

## Summary

Returns the execution witness for a block.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`keys`** object **REQUIRED**

Block lookup key.

* **`blockNumber`** Quantity **REQUIRED**

  Target block number.
* **`blockHash`** Hash32

  Block hash for the same block number. Always include it when available so the lookup is pinned to a specific fork.
* **`parentHash`** Hash32

  Parent block hash for an OP payload lookup. Must be supplied together with `attributesHash` and cannot be combined with `blockHash`.
* **`attributesHash`** Hash32

  Payload-attributes hash for an OP payload lookup. Must be supplied together with `parentHash` and cannot be combined with `blockHash`.

{% hint style="warning" %}
A `blockNumber`-only lookup returns the first stored witness at that height and is not reorg-safe. Use `blockNumber` together with `blockHash`, or the paired `parentHash` and `attributesHash`, for production verification.
{% endhint %}

## Result

**`result`** string

`v0:` followed by a base64-encoded zstd-compressed witness blob.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`mega_getBlockWitness` is not part of the core Ethereum execution JSON-RPC API. It is a MegaETH extension.

### MegaETH Node Behavior

MegaETH returns a `v0:`-prefixed, base64-encoded zstd witness. Requests can select by block hash, or by the paired parent and payload-attributes hashes.

### MegaETH Public Gateway

The gateway does not cache witness responses. In an outer batch, if any witness request uses a block number below 7,385,897, at most four `mega_getBlockWitness` requests are allowed.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                                             |
| -------- | ---------------- | ------------------- | --------------------------------------------------------------------------- |
| `-32602` | Request          | Invalid params      | `blockNumber` missing, invalid hex value, or invalid hash field combination |
| `-32603` | Method           | Internal error      | No witness exists for the requested keys, or the witness service failed     |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget.                 |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit.                 |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "mega_getBlockWitness",
  "params": [
    {
      "blockNumber": "0x7fd",
      "blockHash": "0x262206173864c1e597ab9fcf2f718f95f942907207f4fed97dda66d272c5d4a6"
    }
  ]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "v0:KLUv/QBgzVUAZJwh\u2026"
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/witness.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/services/batch/batch-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# mega\_getWithdrawalProof

mega\_getWithdrawalProof JSON-RPC reference for MegaETH.

## Summary

Returns a Merkle proof for the L2ToL1MessagePasser contract at a given block.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`address`** Address **REQUIRED**

The contract address to prove. For withdrawal verification, use the L2-to-L1 message passer address `0x4200000000000000000000000000000000000016`.

***

**`storageKeys`** Bytes32\[] **REQUIRED**

Storage keys to prove; empty array is valid.

***

**`block`** string **REQUIRED ON THE PUBLIC GATEWAY**

Hex block number or tag (`latest`, `safe`, `finalized`, `earliest`, `pending`). The node defaults an omitted value to `latest`, but the public endpoint requires all three positional parameters.

## Result

* **`address`** Address

  Proved address.
* **`accountProof`** Data\[]

  Account trie proof nodes.
* **`balance`** Quantity

  Account balance.
* **`codeHash`** Hash32

  Account code hash.
* **`nonce`** Quantity

  Account nonce.
* **`storageHash`** Hash32

  Storage trie root.
* **`storageProof`** object\[]

  Per-key storage proofs; each entry has `key` (`Bytes32`), `value` (`Bytes32`), `proof` (`Data[]`).

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`mega_getWithdrawalProof` is not part of the core Ethereum execution JSON-RPC API. It is a MegaETH extension for OP Stack withdrawal proofs.

### MegaETH Node Behavior

The current MegaETH node registers the withdrawal-proof implementation as `eth_getWithdrawalProof`; it does not register this `mega_*` alias.

### MegaETH Public Gateway

The gateway rewrites this alias to `eth_getWithdrawalProof` and caches successful proofs for 30 minutes. Callers receive the same result shape under either name.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                                                     |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------------------------------- |
| `-32602` | Request          | Invalid params      | A storage key is not a valid 32-byte hex string, or required parameters are missing |
| `-32000` | Method           | Server error        | The requested block cannot be resolved                                              |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget.                         |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit.                         |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "mega_getWithdrawalProof",
  "params": ["0x4200000000000000000000000000000000000016", [], "latest"]
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "address": "0x4200000000000000000000000000000000000016",
    "balance": "0x0",
    "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
    "nonce": "0x0",
    "storageHash": "0xddd6dcaf75eeb81fb4701c2a39b3132bd60bf9602e2fcbe5852f5d07e14c8084",
    "accountProof": [],
    "storageProof": []
  }
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/eth/ext.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# mega\_outputAtBlock

mega\_outputAtBlock JSON-RPC reference for MegaETH.

## Summary

Returns the output root at a given block.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

**`blockNumber`** Quantity **REQUIRED**

Concrete hex block number; block tags such as `latest` are not accepted.

## Result

* **`version`** Hash32, optional

  Output version. Fresh upstream responses can include it, while the gateway's cached projection currently omits it.
* **`outputRoot`** Hash32

  Output commitment.
* **`blockRef`** object

  Block reference; see fields below.

  * **`hash`** Hash32

    Block hash.
  * **`number`** number

    Block number (JSON number).
  * **`parentHash`** Hash32

    Parent block hash.
  * **`timestamp`** number

    Block timestamp (JSON number).
  * **`l1origin`** object

    L1 origin with `hash` and `number`.
  * **`sequenceNumber`** number

    Sequence number.
* **`withdrawalStorageRoot`** Hash32

  Withdrawal storage root.
* **`stateRoot`** Hash32

  State root.
* **`syncStatus`** object

  Backend sync-status snapshot.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`mega_outputAtBlock` is not part of the core Ethereum execution JSON-RPC API. It is a MegaETH extension.

### MegaETH Node Behavior

The current MegaETH execution node's related native method is `mega_optimismOutputAtBlock`, which forwards a concrete block number to the OP node's `optimism_outputAtBlock` endpoint. The public `mega_outputAtBlock` spelling is a gateway-facing compatibility name.

### MegaETH Public Gateway

The gateway rewrites this method to `optimism_outputAtBlock` and routes it to the OP-node pool. It caches stable output data for 30 minutes but refreshes the embedded synchronization status on a 1-second cadence. Its cached projection omits the upstream `version` field, so callers must tolerate `version` being present on a fresh response and absent on a cache hit.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message             | When it happens                                                                       |
| -------- | ---------------- | ------------------- | ------------------------------------------------------------------------------------- |
| `-32602` | Request          | Invalid params      | Missing block number, wrong parameter count, or block tag instead of hex block number |
| `-32603` | Method           | Internal error      | Backend cannot produce output data for the requested block                            |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget.                           |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit.                           |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 27, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "mega_outputAtBlock",
  "params": ["0x154de48"]
}
```

The captured response below is abridged; `syncStatus` contains additional L1 and L2 progress fields.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "outputRoot": "0xf90851c88ec4adfe04b03f33beab99bbabbd73fc474ab7b3a8fa109a3913f047",
    "blockRef": {
      "hash": "0xce5344be15fecbe70574c97e57626f79a0816e8ebfc37a53ad535e82dd2def56",
      "number": 22339144,
      "parentHash": "0x85f2e75f7be8967a319af7de35275ad257150f80ae243b97f07b45332d3476a1",
      "timestamp": 1785136155,
      "l1origin": {
        "hash": "0xf79fbbd55e49baaff2f61e027b424b1b5b1ef7cd58bd7d664eb39947352b2f73",
        "number": 25622475
      },
      "sequenceNumber": 137
    },
    "syncStatus": {
      "head_l1": {
        "number": 25622556
      }
    },
    "withdrawalStorageRoot": "0x891f4462376be7ecac17a67a0ee5be7bc0c35979c182e5f7f19ebb2b1e320cc3",
    "stateRoot": "0x686f5150a2aec8f1b5ae15108288530860fa4157a9f39c71e55b0fa24783d506"
  }
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/mega.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/op-output-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 27, 2026; response abridged to stable top-level fields


# net\_listening

net\_listening JSON-RPC reference for MegaETH.

## Summary

Returns whether the node is listening for connections.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

None.

## Result

**`result`** boolean

Always `true`.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`net_listening` is a legacy Ethereum client/network compatibility method rather than a current execution-API method. Implementations commonly expose it with the result shape above.

### MegaETH Node Behavior

The inherited network method reports whether the node's peer-to-peer service is listening.

### MegaETH Public Gateway

The gateway forwards this dynamic value without response caching in the simple read tier.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "net_listening",
  "params": []
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": true
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc/src/net.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# net\_peerCount

net\_peerCount JSON-RPC reference for MegaETH.

## Summary

Returns the number of peers currently connected to the node.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

None.

## Result

**`result`** Quantity

Number of connected peers.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`net_peerCount` is a legacy Ethereum client/network compatibility method rather than a current execution-API method. Implementations commonly expose it with the result shape above.

### MegaETH Node Behavior

The inherited network method reports the node's current peer count; the value is inherently transient.

### MegaETH Public Gateway

The gateway forwards this dynamic value without response caching in the simple read tier.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "net_peerCount",
  "params": []
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x4"
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc/src/net.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# net\_version

net\_version JSON-RPC reference for MegaETH.

## Summary

Returns the current network ID.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

None.

## Result

**`result`** string

Network ID as a decimal integer string.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`net_version` is a legacy Ethereum client/network compatibility method rather than a current execution-API method. Implementations commonly expose it with the result shape above.

### MegaETH Node Behavior

The node reports its configured network identifier as a decimal string. On MegaETH this normally matches the chain ID, but callers should use `eth_chainId` for transaction signing.

### MegaETH Public Gateway

The gateway exposes the method in the instant read tier and caches the immutable network ID for 30 minutes.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                              |
| -------- | ---------------- | ------------------- | ------------------------------------------------------------ |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's instant read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit.  |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "net_version",
  "params": []
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "4326"
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc/src/net.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# optimism\_outputAtBlock

Returns the OP Stack output-root data for a MegaETH block.

## Summary

Returns the same output-root data as [`mega_outputAtBlock`](/developer-docs/rpc/reference/mega_outputatblock). The two names are aliases on MegaETH.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

| Position | Name          | Type       | Required | Description                                                     |
| -------- | ------------- | ---------- | -------- | --------------------------------------------------------------- |
| `0`      | `blockNumber` | `QUANTITY` | Yes      | Concrete hexadecimal block number; block tags are not accepted. |

## Result

An output object containing `outputRoot`, `blockRef`, `withdrawalStorageRoot`, `stateRoot`, and `syncStatus`. The upstream `version` field can be present on a fresh response but is omitted by the gateway's cached projection. See [`mega_outputAtBlock`](/developer-docs/rpc/reference/mega_outputatblock#result) for every field.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`optimism_outputAtBlock` is not part of the core Ethereum execution JSON-RPC API. It is an OP Stack extension.

### MegaETH Node Behavior

This is the OP node's native output-root method. The related MegaETH execution-node method is `mega_optimismOutputAtBlock`, which forwards to it.

### MegaETH Public Gateway

The gateway accepts this name and `mega_outputAtBlock`, routes both to the OP-node pool as `optimism_outputAtBlock`, and applies the same split cache policy for output data and synchronization status. Because the cached projection omits `version`, callers must not require that field even though it can appear on a fresh response.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                             |
| -------- | ---------------- | ------------------- | ----------------------------------------------------------- |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's simple read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit. |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 27, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "optimism_outputAtBlock",
  "params": ["0x154de48"]
}
```

The captured response below is abridged; `syncStatus` contains additional L1 and L2 progress fields.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "version": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "outputRoot": "0xf90851c88ec4adfe04b03f33beab99bbabbd73fc474ab7b3a8fa109a3913f047",
    "blockRef": {
      "hash": "0xce5344be15fecbe70574c97e57626f79a0816e8ebfc37a53ad535e82dd2def56",
      "number": 22339144
    },
    "withdrawalStorageRoot": "0x891f4462376be7ecac17a67a0ee5be7bc0c35979c182e5f7f19ebb2b1e320cc3",
    "stateRoot": "0x686f5150a2aec8f1b5ae15108288530860fa4157a9f39c71e55b0fa24783d506",
    "syncStatus": {
      "head_l1": {
        "number": 25622556
      }
    }
  }
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/mega.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/processors/op-output-processor.ts`
* Probe: MegaETH Mainnet public endpoint, July 27, 2026; response abridged to stable top-level fields


# realtime\_sendRawTransaction

realtime\_sendRawTransaction — submit a transaction and receive the receipt in a single call without polling.

## Summary

Submits a signed transaction and returns the receipt directly once the transaction is executed — no polling required. This is a drop-in replacement for `eth_sendRawTransaction` that eliminates the need to poll `eth_getTransactionReceipt`. When no timeout is supplied, the node uses its 5-second default wait. The public gateway accepts an optional timeout but caps it at 3,000 milliseconds. The gateway routes this method and [`eth_sendRawTransactionSync`](/developer-docs/rpc/reference/eth_sendrawtransactionsync) through the same synchronous submission handler, so their parameters and receipt behavior are equivalent.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

| Position | Type     | Required | Notes                                                         |
| -------- | -------- | -------- | ------------------------------------------------------------- |
| `0`      | `Data`   | Yes      | Hex-encoded signed transaction                                |
| `1`      | `number` | No       | Wait timeout in milliseconds; capped at `3000` by the gateway |

## Result

A transaction receipt object on success:

| Field             | Type              | Notes                                            |
| ----------------- | ----------------- | ------------------------------------------------ |
| `transactionHash` | `Data` (32 bytes) | Hash of the submitted transaction                |
| `blockHash`       | `Data` (32 bytes) | Block containing the transaction                 |
| `blockNumber`     | `Quantity`        | Block containing the transaction                 |
| `from`            | `Data` (20 bytes) | Sender address                                   |
| `to`              | `Data` (20 bytes) | Recipient address (`null` for contract creation) |
| `gasUsed`         | `Quantity`        | Gas consumed by the transaction                  |
| `status`          | `Quantity`        | Nonzero for success; zero for revert             |
| `logs`            | `Log[]`           | Event logs emitted during execution              |
| `contractAddress` | `Data` (20 bytes) | Deployed contract address, or `null`             |

For receipts produced from a streaming mini-block, `blockHash` can temporarily be the all-`ff` placeholder until the enclosing EVM block is committed. Refetch the receipt with `eth_getTransactionReceipt` after block sealing when a canonical block hash is required.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`realtime_sendRawTransaction` is not part of the core Ethereum execution JSON-RPC API. It is a MegaETH extension.

### MegaETH Node Behavior

MegaETH adds this synchronous submission method. It returns a real-time receipt and uses the same node implementation as `eth_sendRawTransactionSync`.

### MegaETH Public Gateway

The gateway routes this name and `eth_sendRawTransactionSync` through the same synchronous handler. After gateway-side validation, both names are rewritten to the node's `realtime_sendRawTransactionWithSender` method. The gateway caps explicit waits at 3,000 milliseconds and accepts request bodies up to 2.5 MiB.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

| Code     | Scope            | Message           | When it happens                                                                |
| -------- | ---------------- | ----------------- | ------------------------------------------------------------------------------ |
| `-32000` | Method           | Server error      | `realtime transaction expired` — receipt not available before the wait expired |
| `-32099` | Transport/policy | Payload too large | The request body exceeds the 2.5 MiB public endpoint limit.                    |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

The gateway routes this method and `eth_sendRawTransactionSync` through the same handler, so their successful receipt responses have the same structure:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "type": "0x0",
    "status": "0x1",
    "transactionHash": "0x8d3b1e22e7a9026c8658b5d922293d59e4de7c3382bb832d6890e6ab23ad7ec7",
    "transactionIndex": "0x5",
    "blockHash": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
    "blockNumber": "0xe7133c",
    "from": "0xcc4b43ab7230cc5913801a746c1834aa06c4e7e7",
    "to": "0xcc4b43ab7230cc5913801a746c1834aa06c4e7e7",
    "gasUsed": "0xea60",
    "effectiveGasPrice": "0xf4240",
    "cumulativeGasUsed": "0x143043",
    "contractAddress": null,
    "logs": [],
    "l1GasPrice": "0x3216",
    "l1GasUsed": "0x640",
    "l1Fee": "0x6da0",
    "l1BaseFeeScalar": "0x558",
    "l1BlobBaseFee": "0x1",
    "l1BlobBaseFeeScalar": "0x0"
  }
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32000,
    "message": "realtime transaction expired"
  }
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/megaeth/rpc/src/realtime.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/sequencer-guard/single-tx.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# web3\_clientVersion

web3\_clientVersion JSON-RPC reference for MegaETH.

## Summary

Returns the current client version string.

The public MegaETH endpoint supports this method. The standard, node, and gateway layers below identify behavior that differs from a generic Ethereum endpoint.

## Parameters

None.

## Result

**`result`** string

Client name, version, and build target.

## Comparison with Ethereum Standard JSON-RPC

### Ethereum Standard

`web3_clientVersion` is a legacy Ethereum client/network compatibility method rather than a current execution-API method. Implementations commonly expose it with the result shape above.

### MegaETH Node Behavior

The node constructs a client/build identifier. The exact string is operational metadata and can change between deployments.

### MegaETH Public Gateway

The gateway uses the instant read tier and caches the version string for 30 minutes. Callers must not parse the deployment suffix as a stable API.

## Errors

The `| Scope |` column distinguishes method failures from gateway policy errors.

No method-specific errors were observed.

| Code     | Scope            | Message             | When it happens                                              |
| -------- | ---------------- | ------------------- | ------------------------------------------------------------ |
| `-32005` | Transport/policy | Rate limit exceeded | The caller exceeds the public gateway's instant read budget. |
| `-32099` | Transport/policy | Payload too large   | The request body exceeds the 128 KiB public endpoint limit.  |

See also [Error Codes](/developer-docs/rpc/error-codes).

## Examples

Endpoint: `https://mainnet.megaeth.com/rpc`

Capture date: July 24, 2026

Outcome: success

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "web3_clientVersion",
  "params": []
}
```

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "mega-reth/v2.0.17-97ab2f0@mnet-sgp-rpc-2"
}
```

## Sources

* Spec: EIP-1474 for JSON-RPC framing and error conventions; this method is an extension or legacy compatibility method.
* Code: `git@github.com:megaeth-labs/mega-reth.git @ ab60376631228edab3a6df180f295280bad26e93: crates/rpc/rpc/src/web3.rs`
* Code: `git@github.com:megaeth-labs/mega-rpc.git @ 06aa35aa95d569c227cc25d2aa12834eb0458aa0: workers/src/spec/methods.ts`
* Probe: MegaETH Mainnet public endpoint, July 24, 2026


# Developer FAQ

Frequently asked questions for MegaETH developers — EVM compatibility, gas, transactions, mini-blocks, RPC, and tooling.

## Chain Behavior & EVM Compatibility

### Which EIPs are supported or enforced on MegaETH?

| EIP          | Title                                                     | Enforced / Supported | Notes                                                                                                                                                 |
| ------------ | --------------------------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| **EIP-55**   | Mixed-case checksum address encoding                      | Not enforced         | Addresses may appear in lowercase, especially in logs and WebSocket responses.                                                                        |
| **EIP-170**  | Contract code size limit                                  | Not enforced         | MegaETH raises the contract size limit to **512 KB** to support larger deployments.                                                                   |
| **EIP-1559** | Fee market change for ETH 1.0 chain                       | Supported            | MegaETH uses a dynamically adjusting base fee model with a different set of parameters.                                                               |
| **EIP-7702** | Account abstraction via temporary smart contract accounts | Supported            | EOAs can be delegated to smart contracts and behave like smart contract wallets. See compatible tools on the [tooling page](/developer-docs/tooling). |

### What versions of Solidity does MegaETH support?

As long as the output bytecode targets the Prague EVM or an older one, it will run on MegaETH. This means you can use any Solidity version that supports Prague or earlier as the compilation target.

### Does MegaETH support transient storage (`TSTORE`)?

Yes, MegaETH supports `TSTORE` as part of its compatibility with the Cancun upgrade.

### Should I expect race conditions to affect simulations?

Some applications simulate transactions before submitting them to the blockchain for actual execution. Race conditions occur if the chain state changes after a transaction is simulated and before it is executed on-chain — for example, because of a conflicting transaction sent in parallel. This may lead to disagreeing results between simulation and on-chain execution. Write proper error handling for this scenario, and only regard on-chain execution results as authoritative.

### Are there any edge cases that may cause an L2 preconfirmation to be reverted because of an L1 reorganization?

Given that each MegaETH block anchors to an L1 block, an L1 reorganization ("reorg") can invalidate the anchor and roll back any corresponding MegaETH blocks. The likelihood depends on how aggressively the sequencer chooses anchors, but should be overall very low. (Ethereum almost never experiences finality violation.)

Write error handling for rollbacks of preconfirmed blocks.

### What is the contract size limit?

512 KB, rather than Ethereum's 24 KB. See the [Contract Limits specification](https://docs.megaeth.com/spec/megaevm/contract-limits) for details.

## Transaction Lifecycle & Txpool

### What limits apply to `eth_call` and `eth_estimateGas`?

The public gateway adds a 60,000,000 compute-gas limit to `eth_call`. It preserves the caller's total `gas` field, so this is a compute limit rather than a replacement total-gas limit.

`eth_estimateGas` instead uses the node's CPU-limited estimator; the gateway's source default is 500,000,000 nanoseconds (0.5 seconds). It does not add the same 60M compute-gas override.

These RPC simulation limits are *different* from the protocol per-transaction gas limit of 10,000,000,000. Managed RPC providers may allow higher limits.

### What is the maximum number of transactions I can have in the txpool?

Each account can have up to **500 pending transactions** in the pool. If you exceed this limit, new transactions will be rejected with a `txpool is full` error. To free up space in the queue, try replacing existing pending transactions. To avoid leaving transactions stuck in the pool, send transactions with nonces that increase one by one, as required by the EVM.

### What is the maximum number of transactions I can send per second per account?

MegaETH does not exercise a per-account transaction rate limit, but there are two main constraints:

1. **Block gas limit.** Each EVM block has a maximum gas limit of 10 billion (10,000,000,000) gas. Given that the minimum gas cost per transaction is 60,000 gas (21,000 compute gas + 39,000 storage gas), the theoretical maximum number of transactions per block is 10,000,000,000 / 60,000 = 166,666.
2. **Execution throughput.** The practical limit also depends on the number of transactions the EVM can process per second. For native ETH transfers, this number is estimated to be around 100,000 transactions per second under ideal conditions.

### How do I check how many transactions are in the txpool?

There is currently no way to check the contents of the txpool.

### Is the txpool cleared when I reconnect or restart my sender?

No. The txpool is persistent and is not cleared when you reconnect to the RPC or restart your sender. If you are observing nonce-related issues after reconnecting, it is likely because your sender is re-initializing the nonce from the latest executed block (`latest`) instead of tracking the `pending` state.

To avoid creating gaps or collisions in nonces, use `eth_getTransactionCount(..., "pending")` or manage nonce state locally when sending multiple transactions concurrently.

### My transactions are stuck in the txpool. How can I clear the blockage?

This usually happens when there is a gap in your nonce sequence. For example, if your last executed transaction had nonce *x*, but the txpool contains transactions starting at *x+2*, those transactions will remain stuck until a transaction with nonce *x+1* is submitted and executed.

Previously, the txpool would reject this corrective *x+1* transaction if the per-account limit (500 transactions) had already been reached. After a recent update, transactions with the next sequential nonce (*x+1*) are always admissible, even when the account has hit the txpool cap. To recover:

{% stepper %}
{% step %}

## Identify the last executed nonce

Find the last nonce that was successfully executed and included in a block.
{% endstep %}

{% step %}

## Send a transaction with nonce x+1

Submit a transaction with the next sequential nonce.
{% endstep %}

{% step %}

## Wait for execution

Wait for it to be executed and included in a block.
{% endstep %}

{% step %}

## Repeat if necessary

If there are more gaps, repeat the process until the queue is unblocked.
{% endstep %}
{% endstepper %}

## Mini-Blocks & Realtime API

### Does `block.timestamp` return the timestamp of the EVM block or the mini-block?

It returns the timestamp of the EVM block.

### Can smart contracts access mini-block metadata?

Not currently. Mini-blocks are intentionally compact and do not include the same metadata fields as EVM blocks, so there is currently no way to access their metadata from within a smart contract.

### Do mini-blocks have the same guarantees as EVM blocks?

Yes. Preconfirmation of mini-blocks by the sequencer has the same level of guarantees as that of EVM blocks. Every mini-block header is [signed by the sequencer](/mini-block#sequencer-signatures), so the preconfirmation is cryptographically verifiable.

### Does the performance dashboard (uptime.megaeth.com) display the block height in mini-blocks or EVM blocks?

Mini-blocks.

### Why is `blockHash` `null` in a realtime transaction receipt even though `blockNumber` is valid?

In the realtime RPC, if a transaction receipt has a `null` `blockHash` but a valid `blockNumber`, it means the transaction was included in a mini-block and is preconfirmed by the sequencer, but not yet part of an EVM block.

The presence or absence of `blockHash` does not affect the level of finality, as the sequencer guarantees inclusion from the moment it is included in a mini-block.

Full finality still depends on the transaction being submitted and finalized on the L1.

### Why does `eth_subscribe` return an internal error?

`eth_subscribe` must be called over a WebSocket (`ws`) connection. You will receive the error when trying it over HTTP because HTTP transport does not support the persistent, bidirectional communication required for subscriptions.

## RPC and WebSocket Behavior

### Which methods are available over WebSocket?

The public WebSocket endpoint supports the following methods:

* `eth_subscribe`
* `eth_unsubscribe`
* `eth_sendRawTransaction`
* `eth_sendRawTransactionSync`
* `realtime_sendRawTransaction`
* `eth_chainId`

WebSocket connections are rate-limited to 5 messages per second per connection. Send `eth_chainId` at least once every 30 seconds to keep the connection alive — idle connections may be closed by the server. See [Operations and limits](/developer-docs/rpc/operations-and-limits#websocket-limits) for connection, subscription, filter, and message-size limits.

### Can I set up my own RPC node?

Not yet. Currently, all RPC endpoints are operated by the MegaETH team and support for externally hosted or self-run nodes is not available. Keep an eye on the [tooling page](/developer-docs/tooling) for updates.

### Where are the RPC endpoints located?

Miami, FL.

### I'm having trouble accessing the RPC without a VPN. Is this related to SSL support?

The issue is unlikely to be SSL-related unless your router is blocking TLS handshakes using deprecated protocol versions. MegaETH only disables outdated ciphers and protocol versions, so modern routers and firewalls should have no problem establishing a connection.

## Developer Tooling

### Where can I find standard token contract addresses?

See [Contracts & Tokens](/developer-docs/overview-1/contracts) for all token and contract addresses on MegaETH.

### How do I wrap the native (gas) token?

To wrap the native token (ETH), use the WETH contract at [`0x4200000000000000000000000000000000000006`](https://megaeth.blockscout.com/address/0x4200000000000000000000000000000000000006) (OP Stack predeploy).

Call `deposit()` and send ETH as `msg.value` — you'll receive an equivalent amount of WETH. See [Contracts & Tokens](/developer-docs/overview-1/contracts#core) for the full list of core contract addresses.

### How can I get my contract verified on the MegaExplorer?

Open a pull request with the contract address and ABI at <https://github.com/princesinha19/megaeth-abis/tree/main>. It should then automatically be reflected on the [MegaExplorer](https://www.megaexplorer.xyz).

Note that both this repo and the MegaExplorer are community-created and managed.

## Errors

### Why am I seeing `null` `blockHash` when calling `getTransactionReceipt`?

To avoid adding latency, MegaETH does not force global synchronization across all RPC servers. As a result, it is possible that the RPC server handling your request has not yet received the transaction receipt from the sequencer, even if the transaction has already been processed.

### Why am I getting a `403` error saying "Enable JavaScript and cookies to continue" when using Foundry?

This error typically comes from Cloudflare's protection layers. Consider retrying with a low-risk IP address.

### Why am I getting a TLS handshake failure when using Alloy.rs?

This error typically occurs because Alloy's WebSocket transport forces the use of `rustls` for TLS. To fix this:

{% stepper %}
{% step %}

## Install `reqwest` with the `rustls-tls` feature

Add to your `Cargo.toml`:

```toml
reqwest = { version = "...", features = ["rustls-tls"] }
```

{% endstep %}

{% step %}

## Use a custom transport to build your HTTP provider

```rust
let client = reqwest::Client::builder()
    .use_rustls_tls()
    .build()
    .unwrap();

let http_client = Http::with_client(client, Url::parse(&self.http_url).unwrap());
let is_local = http_client.guess_local();
let http_client = ClientBuilder::default().transport(http_client, is_local);
let http_provider = ProviderBuilder::new().on_client(http_client);
```

{% endstep %}

{% step %}

## Install the default TLS provider early in `main.rs`

```rust
let _ = rustls::crypto::ring::default_provider().install_default();
```

{% endstep %}
{% endstepper %}

### What does `Rate limit exceeded` mean?

It means you are hitting a rate limit. Older clients or outdated docs may still refer to `rabbit hole is full. Please try again later`, but the public gateway now returns `Rate limit exceeded` with RPC error `-32005`.

### What does "rpc method is not whitelisted" mean?

It means you are calling a method that is currently restricted. If this is a blocker, please reach out to the team to come up with a solution.

### Why do I get a `502 Bad Gateway` error?

A `502` usually indicates a temporary upstream issue or stale DNS resolution. The latter case is especially common in long-running processes (e.g., bots, indexers, or backends) that reuse DNS lookups for too long. Restarting your process typically resolves it. If the issue persists, reach out to the team.


# Stateless Validation

Run a stateless validator to independently verify every MegaETH block on commodity hardware using SALT witnesses.

The **stateless validator** is a Rust client that independently verifies every MegaETH block without maintaining full chain state. Instead of replaying blocks against a locally-stored state trie, it re-executes each block against a compact cryptographic witness supplied by the network, then checks that the resulting post-state matches the commitments in the block header.

This design enables independent verification of sequencer execution on commodity hardware — a laptop-class machine can verify MegaETH Mainnet in real time. For how validators fit into the broader network, see [Architecture](/architecture).

## Why run a stateless validator

* **Independent verification** — you re-execute the state transition function (STF) of every block yourself, rather than trusting an RPC provider to tell you the truth.
* **Low hardware cost** — thanks to [SALT (Small Authentication Large Trie)](https://github.com/megaeth-labs/salt) witnesses, proof data per block is significantly smaller than Merkle Patricia Trie witnesses, so validators do not need sequencer-class hardware.
* **Parallel-friendly** — validation workers are embarrassingly parallel; throughput scales linearly with CPU cores.
* **Auditable trusted computing base (TCB)** — the validator is built on the upstream Rust EVM interpreter [revm](https://github.com/bluealloy/revm) with an in-memory backend, keeping the TCB small and reviewable.

## Installation

The validator is distributed as source only — there are no prebuilt binaries today. Install the Rust toolchain and build the release binary:

```bash
# Install rustup (if you don't already have it)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Clone and build
git clone https://github.com/megaeth-labs/stateless-validator.git
cd stateless-validator
cargo build --release --bin stateless-validator
```

The project pins a specific nightly Rust toolchain via `rust-toolchain.toml`, so `cargo build` downloads it automatically on first run.

The compiled binary lives at `./target/release/stateless-validator`. Copy it onto your `PATH` if you plan to invoke it directly.

## Quick start

### First run

On the first launch, the validator needs two pieces of bootstrap information:

1. **`--genesis-file`** — the MegaETH genesis JSON, which encodes the chain ID and hardfork activation schedule. Use [`test_data/mainnet/genesis.json`](https://github.com/megaeth-labs/stateless-validator/blob/main/test_data/mainnet/genesis.json) from the stateless-validator repo. The `alloc` list is stripped from this file — the validator never reads initial balances, so only the chain config is needed.
2. **`--start-block`** — a **trusted block hash** that anchors your local chain. The validator fetches this block's header and stores its `block_number`, `block_hash`, `state_root`, and `withdrawals_root` as the anchor. The anchor itself is **not** re-executed; its values are taken on faith. Verification starts from the **next** block, which must satisfy both invariants below or the pipeline halts:

   * `parent_hash` equals the anchor's `block_hash`.
   * witness `pre_state_root` / `pre_withdrawals_root` match the anchor's `state_root` / `withdrawals_root`.

   The simplest way to get a usable anchor is to fetch the latest **finalized** header from the same RPC you'll point the validator at, then cross-check the returned hash against an independent source (a block explorer, a second RPC provider):

   ```bash
   curl -sX POST https://mainnet.megaeth.com/rpc \
     -H 'Content-Type: application/json' \
     -d '{"jsonrpc":"2.0","method":"eth_getHeaderByNumber","params":["finalized"],"id":1}' \
     | jq -r '.result.hash'
   # Output: a 0x-prefixed 64-hex-char string.
   ```

   Pass that hash to `--start-block`. An older anchor is also valid, but the validator must then re-check every block between the anchor and the tip before going live.

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p><code>--start-block</code> takes a block <strong>hash</strong> (<code>0x</code> + 64 hex chars), not a block number. Always verify the hash against at least one independent source before passing it — the anchor is the single point of trust the rest of the chain hangs from.</p></div>

Replace `<ANCHOR_HASH_FROM_CURL_ABOVE>` below with the hash returned by the `curl` command above, then launch from the cloned `stateless-validator` directory (so `./target/release/...` and `./test_data/...` resolve):

```bash
./target/release/stateless-validator \
  --data-dir ./validator-data \
  --rpc-endpoint https://mainnet.megaeth.com/rpc \
  --witness-endpoint https://mainnet.megaeth.com/rpc \
  --genesis-file ./test_data/mainnet/genesis.json \
  --start-block <ANCHOR_HASH_FROM_CURL_ABOVE> \
  --log.file-directory ./validator-data/logs \
  --data-max-concurrent-requests 4 \
  --witness-max-concurrent-requests 4
```

{% hint style="info" %}
`--data-max-concurrent-requests` and `--witness-max-concurrent-requests` are independent semaphores guarding the data path (`eth_get*`) and the witness path (`mega_getBlockWitness`) respectively — keeping them separate prevents a burst on one path from starving the other. The values shown (`4` / `4`) are tuned for the public mainnet RPC at `mainnet.megaeth.com/rpc`: unbounded concurrency may trigger HTTP 429 rate-limiting and stall the validator's forward progress.
{% endhint %}

On start, the validator:

1. Persists the genesis config to its database.
2. Fetches the header for `--start-block` and installs it as the trusted anchor.
3. Begins the fetch → process → advance pipeline, verifying every new block.

`--log.file-directory` writes a rotated `stateless-validator.log` into the directory you pass it (`./validator-data/logs` in the example above). Tail it from another terminal to watch the pipeline make progress:

```bash
tail -f ./validator-data/logs/stateless-validator.log
```

Healthy output looks like this — `Replay block`, `Successfully validated block`, and `Chain advanced` lines marching forward:

```
DEBUG stateless_core::executor: Replay block: block_number=14471126, block_hash=0xfda1cc..., hardfork=Some(Rex4)
DEBUG stateless_validator::chain_sync: Successfully validated block block_number=14471126
DEBUG stateless_core::pipeline::advancer: Chain advanced tip=14471126 advanced=1 buffered=0
```

File logs are at `debug` level by default; console output stays at `info`. See [Logging flags](#logging-flags) to tune levels, formats, and rotation.

### Subsequent runs

Once the database is initialized, omit `--genesis-file` and `--start-block` — the validator resumes from the last validated block. All other operational flags (logging, concurrency caps) are **not** persisted to the database, so re-supply them on every run:

```bash
./target/release/stateless-validator \
  --data-dir ./validator-data \
  --rpc-endpoint https://mainnet.megaeth.com/rpc \
  --witness-endpoint https://mainnet.megaeth.com/rpc \
  --log.file-directory ./validator-data/logs \
  --data-max-concurrent-requests 4 \
  --witness-max-concurrent-requests 4
```

### Multiple RPC endpoints

Both `--rpc-endpoint` and `--witness-endpoint` accept multiple endpoints as repeated flags or a comma-separated list. Both share the same retry primitive: each "round" attempts every provider once in order (no inter-provider sleep), and only when an entire round has failed does the client sleep for **round-level** exponential backoff (initial → 2× → 4× …, capped at `--rpc-max-backoff-ms`, with up to 50% jitter) before starting the next round. There is no global retry cap — rounds repeat indefinitely until a request succeeds. The two paths only differ in which provider each round starts at:

* **`--rpc-endpoint` (data: blocks / headers / code / tx)** — round-robin load balancing. The starting provider rotates per call via an atomic counter, so healthy endpoints share traffic evenly; within a round the order is fixed (`start → start+1 → …`).
* **`--witness-endpoint`** — primary-failover. Every round starts from provider 0, so the first endpoint takes all traffic while healthy and later endpoints only see traffic when the primary is failing. This keeps the primary cache-hot.

The two paths have independent concurrency caps (`--data-max-concurrent-requests`, `--witness-max-concurrent-requests`) so a burst on one cannot starve the other.

```bash
# Repeated flags
--rpc-endpoint https://a.example/rpc --rpc-endpoint https://b.example/rpc

# Comma-separated (the env var also accepts this form)
--rpc-endpoint https://a.example/rpc,https://b.example/rpc
```

## Command-line options

Every flag has an equivalent environment variable, convenient for service managers and containerized deployments. Command-line flags take precedence over environment variables. Boolean flags (e.g., `--metrics-enabled`) accept `true` or `false` via their env var — set `STATELESS_VALIDATOR_METRICS_ENABLED=true` to turn the endpoint on without command-line arguments.

### Core flags

| Flag                           | Env variable                                     | Required? | Description                                                                                                                             |
| ------------------------------ | ------------------------------------------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `--data-dir`                   | `STATELESS_VALIDATOR_DATA_DIR`                   | Yes       | Directory holding the validator database and any cached data.                                                                           |
| `--rpc-endpoint`               | `STATELESS_VALIDATOR_RPC_ENDPOINT`               | Yes       | JSON-RPC endpoint(s) for block headers and bodies. Repeat the flag or pass a comma-separated list.                                      |
| `--witness-endpoint`           | `STATELESS_VALIDATOR_WITNESS_ENDPOINT`           | Yes       | MegaETH JSON-RPC endpoint(s) for SALT witnesses (`mega_getBlockWitness`). Multiple endpoints accepted.                                  |
| `--genesis-file`               | `STATELESS_VALIDATOR_GENESIS_FILE`               | First run | Path to the genesis JSON. Stored in the database after the first run.                                                                   |
| `--start-block`                | `STATELESS_VALIDATOR_START_BLOCK`                | First run | Trusted block hash used as the validation anchor.                                                                                       |
| `--report-validation-endpoint` | `STATELESS_VALIDATOR_REPORT_VALIDATION_ENDPOINT` | No        | RPC endpoint that receives `mega_setValidatedBlocks` callbacks for validated blocks. If not provided, validation reporting is disabled. |
| `--metrics-enabled`            | `STATELESS_VALIDATOR_METRICS_ENABLED`            | No        | Expose a Prometheus `/metrics` endpoint. Default: `false` (endpoint not bound).                                                         |
| `--metrics-port`               | `STATELESS_VALIDATOR_METRICS_PORT`               | No        | Port for the metrics endpoint. Default: `9090`.                                                                                         |

### Advanced tuning

These flags override pipeline and RPC retry defaults — most operators can leave them unset.

| Flag                                | Env variable                                          | Default   | Description                                                                                                                                   |
| ----------------------------------- | ----------------------------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `--data-max-concurrent-requests`    | `STATELESS_VALIDATOR_DATA_MAX_CONCURRENT_REQUESTS`    | unlimited | Cap on concurrent in-flight data requests (blocks, headers, code, tx). Omit for unlimited.                                                    |
| `--witness-max-concurrent-requests` | `STATELESS_VALIDATOR_WITNESS_MAX_CONCURRENT_REQUESTS` | unlimited | Cap on concurrent in-flight witness fetches, independent of the data cap. Omit for unlimited.                                                 |
| `--poll-interval-ms`                | `STATELESS_VALIDATOR_POLL_INTERVAL_MS`                | `100`     | Fetcher caught-up poll interval (ms). Also rate-limits `eth_blockNumber`. Lower values reduce tip-following lag.                              |
| `--error-restart-delay-ms`          | `STATELESS_VALIDATOR_ERROR_RESTART_DELAY_MS`          | `1000`    | Pipeline restart delay (ms) after a transient cycle error.                                                                                    |
| `--rpc-initial-backoff-ms`          | `STATELESS_VALIDATOR_RPC_INITIAL_BACKOFF_MS`          | `500`     | Initial round-level RPC retry backoff (ms). Applied after every provider in a round has failed; doubles each round.                           |
| `--rpc-max-backoff-ms`              | `STATELESS_VALIDATOR_RPC_MAX_BACKOFF_MS`              | `30000`   | Cap on round-level RPC retry backoff (ms).                                                                                                    |
| `--canonical-chain-max-length`      | `STATELESS_VALIDATOR_CANONICAL_CHAIN_MAX_LENGTH`      | `1000`    | Soft cap on canonical-chain rows retained locally. Larger values widen the reorg-lookup window; smaller values reduce db growth. Must be ≥ 1. |

### Logging flags

Logging is configured via `--log.*` flags, mirrored by `STATELESS_LOG_*` environment variables.

| Flag                   | Env variable                   | Default                   | Description                                                        |
| ---------------------- | ------------------------------ | ------------------------- | ------------------------------------------------------------------ |
| `--log.stdout-filter`  | `STATELESS_LOG_STDOUT`         | `info`                    | Console log level (`trace` / `debug` / `info` / `warn` / `error`). |
| `--log.stdout-format`  | `STATELESS_LOG_STDOUT_FORMAT`  | `terminal`                | Console format: `terminal` or `json`.                              |
| `--log.color`          | `STATELESS_LOG_COLOR`          | `auto`                    | ANSI color: `auto`, `always`, or `never`.                          |
| `--log.file-directory` | `STATELESS_LOG_FILE_DIRECTORY` | (unset)                   | Directory for rotated log files. File logging is off when unset.   |
| `--log.file-name`      | `STATELESS_LOG_FILE_NAME`      | `stateless-validator.log` | Base name of the active log file.                                  |
| `--log.file-filter`    | `STATELESS_LOG_FILE`           | `debug`                   | Log level for file output.                                         |
| `--log.file-format`    | `STATELESS_LOG_FILE_FORMAT`    | `terminal`                | File format: `terminal` or `json`.                                 |
| `--log.file-max-size`  | `STATELESS_LOG_FILE_MAX_SIZE`  | `200`                     | Max log file size (MB) before rotation.                            |
| `--log.file-max-files` | `STATELESS_LOG_FILE_MAX_FILES` | `5`                       | Number of rotated log files to keep.                               |

## Monitoring

### Checking validation progress

With metrics enabled, the validator binds a Prometheus endpoint on `0.0.0.0:9090` (reachable as `http://<host>:9090/metrics`, or `http://localhost:9090/metrics` from the same machine). Three gauges tell you whether the validator is keeping up:

```bash
curl -s http://localhost:9090/metrics | grep -v '^#' | grep -E 'chain_height|validation_lag'
```

```
stateless_validator_remote_chain_height 14479507
stateless_validator_local_chain_height  14479502
stateless_validator_validation_lag      5
```

`validation_lag` is the number of blocks the validator is behind the remote tip (`remote_chain_height − local_chain_height`). Interpret it in two phases:

* **During initial catch-up** (only if you anchored at an older block), `validation_lag` starts large and shrinks as the validator replays history to reach the tip. A large lag here is expected, not a symptom.
* **Once caught up**, the gauge sits around `3–5` and briefly spikes during bursty periods. This floor is intentional: the validator currently buffers 3 blocks below the remote tip, refusing to fetch any block within that window so the upstream witness generator has headroom to finish. Factor in the 100 ms poll cadence and one RPC round-trip, and a steady-state lag of a few blocks is expected — not a symptom. Persistent lag much above that range means the validator can't keep pace with the sequencer — investigate per the [Troubleshooting](#troubleshooting) section.

The [`scripts/validator-status.sh`](https://github.com/megaeth-labs/stateless-validator/blob/main/scripts/validator-status.sh) helper in the repo renders these metrics as a formatted dashboard.

### Useful metrics

| Metric                                                     | Type      | What it tells you                                                  |
| ---------------------------------------------------------- | --------- | ------------------------------------------------------------------ |
| `stateless_validator_local_chain_height`                   | Gauge     | Local chain tip.                                                   |
| `stateless_validator_remote_chain_height`                  | Gauge     | Remote chain tip reported by the RPC endpoint.                     |
| `stateless_validator_validation_lag`                       | Gauge     | Blocks behind the remote tip (steady-state floor ≈ 3–5).           |
| `stateless_validator_block_validation_time_seconds`        | Histogram | End-to-end time to validate a block.                               |
| `stateless_validator_witness_verification_time_seconds`    | Histogram | Time spent verifying SALT witnesses.                               |
| `stateless_validator_block_replay_time_seconds`            | Histogram | EVM execution time per block.                                      |
| `stateless_validator_salt_update_time_seconds`             | Histogram | Time to apply post-state deltas to the SALT trie.                  |
| `stateless_validator_block_state_reads`                    | Histogram | KV reads per block (diagnoses I/O-bound slowdown).                 |
| `stateless_validator_block_state_writes`                   | Histogram | KV writes per block.                                               |
| `stateless_validator_transactions_total`                   | Counter   | Total transactions validated.                                      |
| `stateless_validator_gas_used_total`                       | Counter   | Total gas used in validated blocks.                                |
| `stateless_validator_reorgs_detected_total`                | Counter   | Number of reorgs handled.                                          |
| `stateless_validator_reorg_depth`                          | Histogram | Depth of chain reorganizations.                                    |
| `stateless_validator_rpc_requests_total{method=...}`       | Counter   | RPC requests made (one per logical call), labelled by method.      |
| `stateless_validator_rpc_errors_total{method=...}`         | Counter   | RPC final failures (not retried attempts), labelled by method.     |
| `stateless_validator_rpc_retry_attempts_total{method=...}` | Counter   | Transient retry attempts before final outcome, labelled by method. |
| `stateless_validator_block_fetch_time_seconds`             | Histogram | Per-call `eth_getBlockByNumber` / `eth_getBlockByHash` latency.    |
| `stateless_validator_code_fetch_time_seconds`              | Histogram | Per-call `eth_getCodeByHash` latency.                              |
| `stateless_validator_witness_fetch_rpc_time_seconds`       | Histogram | Per-call `mega_getBlockWitness` latency.                           |
| `stateless_validator_contract_cache_hits_total`            | Counter   | Bytecode served from the local cache.                              |
| `stateless_validator_contract_cache_misses_total`          | Counter   | Bytecode fetched from RPC on miss.                                 |
| `stateless_validator_salt_witness_size_bytes`              | Histogram | Serialized SALT witness size per block.                            |
| `stateless_validator_salt_witness_keys`                    | Histogram | Key count in each SALT witness.                                    |
| `stateless_validator_salt_witness_kvs_size_bytes`          | Histogram | KV payload size inside each SALT witness.                          |
| `stateless_validator_mpt_witness_size_bytes`               | Histogram | Serialized MPT withdrawals-witness size per block.                 |
| `stateless_validator_worker_tasks_completed_total`         | Counter   | Tasks completed per worker (label: `worker_id`).                   |
| `stateless_validator_worker_tasks_failed_total`            | Counter   | Tasks failed per worker (label: `worker_id`).                      |

For the complete list, see [`metrics.rs`](https://github.com/megaeth-labs/stateless-validator/blob/main/bin/stateless-validator/src/metrics.rs) in the upstream repo.

### Logs

When `--log.file-directory` is set, the validator writes rotated log files to that directory. Rotation is size-based (`--log.file-max-size`, default 200 MB), keeping `--log.file-max-files` rotated files (default 5). Console output honors `--log.stdout-filter`.

```bash
tail -f ./validator-data/logs/stateless-validator.log
```

## Trust model

The stateless validator is an **execution client**: it verifies that every block's state transition was applied correctly and that commitments in the block header match the resulting post-state. It does **not** decide which chain is canonical — it validates whatever sequence of blocks you feed it.

If you trust the data endpoint (`--rpc-endpoint`) to serve the canonical block sequence the sequencer produced, the validator detects any block whose post-state does not match the header commitments — including any execution mistake by the sequencer. The witness endpoint (`--witness-endpoint`) does not need to be trusted for correctness: witness contents are cryptographically verified against the previous block's state root, so a faulty or malicious witness endpoint can only stall progress, not produce a false validation.

{% hint style="warning" %}
The stateless validator currently does **not** check that the blocks it validates are consistent with the L2 rollup batch posted to L1. A sequencer that posts a different sequence of blocks to L1 than it serves over RPC would not be detected by the validator alone. End-to-end batch-consistency checking is work in progress.
{% endhint %}

For a fully trust-minimized setup, pair the stateless validator with:

* **`op-node`** to derive the canonical L2 chain from L1 and the data availability layer.
* **A MegaETH replica node** that follows the derived chain and serves blocks locally.

In that configuration, you rely only on L1's security and your own software — no external RPC is in the trusted path.

{% hint style="info" %}
The MegaETH replica node is currently permissioned — the binary is not generally available. If you want to run a replica alongside the stateless validator, [contact the MegaETH team](https://megaeth.com) to request access.
{% endhint %}

## Troubleshooting

**The validator can't find the start block.** You will see warnings like `WARN ...: failed to fetch start block ...` repeating in the log. Check that `--rpc-endpoint` is reachable and that the block hash in `--start-block` exists on that endpoint. The validator retries fetch failures automatically, so the warnings clear once the RPC starts responding.

**`validation_lag` keeps growing.** Either the remote RPC is throttling witness fetches (look for `mega_getBlockWitness` errors in `stateless_validator_rpc_errors_total`) or the machine is under-provisioned. Compare `stateless_validator_block_validation_time_seconds` p99 against the chain's block period — if validation time exceeds the period, the validator cannot keep pace at all and you need either faster hardware or fewer worker tasks. Histograms like `block_validation_time_seconds`, `witness_verification_time_seconds`, and `block_replay_time_seconds` break down where time is being spent.

## Related pages

* [Get Block Witness](/node-operation/stateless-validation/witness) — `mega_getBlockWitness` RPC reference and witness data layout
* [Architecture](/architecture) — how transactions flow through MegaETH and where validators fit in
* [stateless-validator source](https://github.com/megaeth-labs/stateless-validator) — Rust client source code
* [SALT](https://github.com/megaeth-labs/salt) — MegaETH's state trie and witness format


# Validator Architecture

Architecture and implementation guide for building a MegaETH-compatible stateless validator.

This page describes the reference architecture of MegaETH's stateless validator and the per-block validation pipeline it runs. It is written for engineers building a compatible validator from scratch — in another language or against a different EVM stack.

The reference implementation lives at [`megaeth-labs/stateless-validator`](https://github.com/megaeth-labs/stateless-validator) and is used throughout this page as the source of truth. For day-to-day operation of that client, see [Stateless Validation](/node-operation/stateless-validation). For the wire format of the witness, see [Get Block Witness](/node-operation/stateless-validation/witness).

## What a stateless validator does

A stateless validator independently re-executes every MegaETH block against a compact cryptographic witness, then checks that every commitment in the block header matches the resulting post-state. It holds **no chain state of its own** — a fresh witness arrives with each block and supplies just the slice of state that block touches.

| Aspect | Detail                                                                                                                                               |
| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| Input  | A `(block, witness)` pair fetched per height. The witness is the response of [`mega_getBlockWitness`](/node-operation/stateless-validation/witness). |
| Output | A locally-persisted record that the block validates.                                                                                                 |

The validator's only startup trust input is a **genesis JSON** (chain ID + hardfork schedule) and an **anchor block hash** that the next validated block must extend. Both are detailed in [Genesis configuration](#genesis-configuration) below.

**Non-goal:** picking the canonical fork. The validator validates whatever block sequence it is fed; pair it with a consensus client (e.g. `op-node`) to derive canonicality.

## Genesis configuration

The genesis JSON is the validator's primary configuration anchor. Misconfigure it and every subsequent fork-conditional check silently runs against the wrong rules — the validator will produce mismatched state roots with no "wrong chain" error to point you at the cause. Treat it like a chain-identity contract: load it once, persist it, and never edit it by hand. **Pull a fresh copy of the canonical mainnet genesis whenever a new hardfork is scheduled.** For the file layout (not a runtime artifact), see the schema-shaped sample at [`test_data/mainnet/genesis.json`](https://github.com/megaeth-labs/stateless-validator/blob/main/test_data/mainnet/genesis.json) — `alloc` is stripped to keep the repo small.

{% hint style="info" %}
**Reference impl.** Loads genesis via `--genesis-file` on first run, stores it in the local database with [`store_genesis`](https://github.com/megaeth-labs/stateless-validator/blob/main/bin/stateless-validator/src/validator_db.rs#L88), and re-reads the stored copy on every subsequent boot.
{% endhint %}

Despite the file carrying the full Genesis schema (allocations, gas limit, timestamp, base fee, ...), the validator consumes only two pieces of state from it:

| Derived value     | Source in `config`                    | Use during validation                                                                                                                                                                                                            |
| ----------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Chain ID          | `chainId`                             | Drives the EVM `CHAINID` opcode and EIP-155 transaction-signature checks.                                                                                                                                                        |
| Hardfork schedule | `<fork>Block` and `<fork>Time` fields | Activates Ethereum (Cancun, Shanghai, ...), OP-Stack (Ecotone, Granite, Holocene, Isthmus, ...), and MegaETH (MiniRex, MiniRex1, MiniRex2, Rex, Rex1, Rex2, Rex3, Rex4, Rex5) at their pre-declared block numbers or timestamps. |

The genesis `alloc`, `gasLimit`, `baseFeePerGas`, and other initial-state fields are **not** consumed — once the chain has produced a single block, initial state is served by the witness, not by the genesis file.

{% hint style="info" %}
**Reference impl.** [`ChainSpec::from_genesis`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/chain_spec.rs#L59) reads `genesis.config.chain_id` directly, hands the full `Genesis` to `OpChainSpec::from_genesis` to extract Ethereum and OP-Stack fork conditions, and pulls MegaETH-specific forks via [`MegaethGenesisHardforks::extract_from`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/chain_spec.rs#L123). The three sets are merged into a single ordered hardfork schedule that drives every fork-conditional code path: opcode availability, gas-cost tables, system-contract pre/post-block hooks, and resource limits.
{% endhint %}

{% hint style="warning" %}
All replicas of the chain MUST use byte-identical genesis JSON. A divergence in any single hardfork timestamp produces a fork that the rest of the network will reject — and because the divergence only manifests as a `state_root` mismatch on the first affected block, it is hard to attribute after the fact.
{% endhint %}

## Reference architecture

The current implementation of the stateless validator is a three-stage async pipeline. Each `(block, witness)` pair flows through the same stages; only the validator workers run in parallel.

```
                ┌─────────────────┐
  RPC ────────► │  Block fetcher  │
                └────────┬────────┘
                         │  (block, witness)
                  ┌──────┴──────┐
                  ▼             ▼
              ┌──────────┐ ┌──────────┐ ... N workers
              │ Worker 1 │ │ Worker 2 │
              └─────┬────┘ └─────┬────┘
                    └─────┬──────┘
                          │  ValidatedBlock
                ┌─────────▼─────────┐
                │  Chain advancer   │ ────► local chain store
                └───────────────────┘
```

| Component        | Role                                                                                                | Reference                                                                                                                                                                      |
| ---------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Block fetcher    | Streams `(block, witness)` pairs from RPC. Independent semaphores cap data and witness concurrency. | [`crates/stateless-common/src/rpc_client.rs`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-common/src/rpc_client.rs)                         |
| Validator worker | Verifies the witness, replays the block, computes post-state, compares against the header.          | [`crates/stateless-core/src/executor.rs:411`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/executor.rs#L411) (`validate_block`)     |
| Chain advancer   | Reorders out-of-order results, detects reorgs by parent-hash mismatch, persists in height order.    | [`crates/stateless-core/src/pipeline/mod.rs:44`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/pipeline/mod.rs#L44) (`run_pipeline`) |
| Contract cache   | Resolves contract bytecode by code hash with three tiers: in-memory → disk (redb) → RPC.            | [`crates/stateless-db/`](https://github.com/megaeth-labs/stateless-validator/tree/main/crates/stateless-db)                                                                    |

Workers do not coordinate. A custom implementation can collapse the pipeline into a single sequential loop without changing correctness — parallelism is purely a throughput choice.

## Validation pipeline

The per-block sequence below is what `validate_block` performs. A different implementation MUST run every numbered step. Reorderings are allowed only when they preserve the data dependencies between steps — most importantly, the SALT proof MUST verify (step 3) before any state is read (steps 4+), bytecode MUST be hash-verified before being installed in the cache, and each header recompute MUST include all the state changes it commits to.

{% stepper %}
{% step %}

### Fetch the block and witness

Call `eth_getBlockByHash` (or `eth_getBlockByNumber`) for the block, and [`mega_getBlockWitness`](/node-operation/stateless-validation/witness) for the witness. Pin the witness call to `(blockNumber, blockHash)`; a `blockNumber`-only call is non-deterministic across forks.

{% hint style="info" %}
**Reference impl.** Fetches both in parallel from independent RPC pools — see [`get_block`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-common/src/rpc_client.rs#L430) and [`get_witness`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-common/src/rpc_client.rs#L558).
{% endhint %}
{% endstep %}

{% step %}

### Decode the witness payload

Strip the `v0:` prefix, base64-decode, Zstd-decompress, and bincode-deserialize (legacy config) into `(SaltWitness, MptWitness)`. The exact pipeline and a Rust reference snippet live on [Get Block Witness](/node-operation/stateless-validation/witness#decoding-pipeline).
{% endstep %}

{% step %}

### Verify the SALT proof against the previous state root

The `SaltProof` inside `SaltWitness` is a multi-point IPA opening on the Banderwagon curve. Run the verifier against the **previous block's** `state_root` (taken from the parent header, or from the trusted anchor on the very first block).

If the proof does not verify, **reject the block immediately** — every subsequent step assumes the witnessed key-value pairs are authenticated.

For the proof's mathematical structure, see the [SALT repository](https://github.com/megaeth-labs/salt).
{% endstep %}

{% step %}

### Build a state-read backend over the witness

Treat `SaltWitness.kvs` as the only source of state for the duration of replay. Every account or storage read during execution falls through to a lookup in this map and resolves to one of three outcomes:

| Witness entry               | Verifier behavior                                                                 |
| --------------------------- | --------------------------------------------------------------------------------- |
| `Some(value)` — present     | Return the decoded account or slot.                                               |
| `Some(None)` — proven empty | Return the EVM "empty" sentinel (zero balance / nonce, no code; `0` for storage). |
| Key absent from `kvs`       | **Error.** Halt validation immediately.                                           |

{% hint style="warning" %}
The third case is what blocks witness omission attacks. A malicious witness producer that left a key out (rather than proving it empty) would otherwise let the verifier silently treat real state as zero. The verifier MUST treat "absent from `kvs`" as a fatal error, not as "empty".
{% endhint %}

A custom implementation needs the equivalent surface for whatever EVM it embeds.

{% hint style="info" %}
**Reference impl.** This backend is [`WitnessDatabase`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/evm_database.rs#L64), which implements [`revm::DatabaseRef`](https://docs.rs/revm/latest/revm/trait.DatabaseRef.html).
{% endhint %}
{% endstep %}

{% step %}

### Resolve contract bytecode by hash

Account entries in the witness carry the `codehash`, not the bytecode itself. This is intentional — bytecode is large, changes infrequently, and is content-addressed, so the witness only references it.

Maintain a local cache keyed by `codehash`. On a miss, fetch via [`eth_getCodeByHash`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-common/src/rpc_client.rs#L398) — a MegaETH RPC extension that takes a code hash and returns the bytecode whose `keccak256` equals that hash — and **verify** that `keccak256(code) == codehash` before using it. If the endpoint does not support `eth_getCodeByHash`, fall back to `eth_getCode` against a known holder address, and **always pin the call to the exact block at which the witness anchors** (the parent block's number). Apply the same `keccak256(code) == codehash` verification to the result. A miss that cannot be resolved is a fatal error for the block being validated.
{% endstep %}

{% step %}

### Apply pre-execution system updates

Before the first transaction, apply hardfork-conditional system calls. Two layers run in order:

1. **OP-Stack base hooks** (always active on MegaETH, since Isthmus is the floor):
   * EIP-2935 history-storage contract update.
   * EIP-4788 beacon root contract update.
2. **MegaEVM system-contract deployments / updates**, gated by the active MegaETH hardfork:
   * **MiniRex** — deploy the oracle contract and the high-precision timestamp oracle contract.
   * **Rex2** — deploy the keyless-deploy contract.
   * **Rex4** — deploy the access-control contract and the `MegaLimitControl` contract.
   * **Rex5** — deploy the `SequencerRegistry` contract (`0x6342000000000000000000000000000000000006`) and upgrade the oracle to its dynamic-authority version. When a scheduled system-address or sequencer change is due, an additional pre-block system call to `applyPendingChanges()` is executed.
   * **MiniRex1, MiniRex2, Rex, Rex1, Rex3** — no new system-contract deployments. The fork still gates EVM behavior changes; the pre-execution hook list is just empty.

The L1-attributes deposit is **not** a pre-block hook: it is the block's first transaction and runs in the regular tx loop in step 7.

The exact hook set is fixed by the active hardfork — see [System Contracts](https://docs.megaeth.com/spec/system-contracts/overview) for the canonical addresses and behaviors.

{% hint style="info" %}
**Reference impl.** [`apply_pre_execution_changes`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/executor.rs#L364) inside [`replay_block`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/executor.rs#L252) delegates to mega-evm's [`pre_execution_changes`](https://github.com/megaeth-labs/mega-evm/blob/main/crates/mega-evm/src/block/executor.rs#L172), which runs the OP-Stack base hooks followed by the MegaEVM-specific system-contract deployments listed above.
{% endhint %}
{% endstep %}

{% step %}

### Replay the block's transactions

Execute every transaction with the chain's hardfork rules and accumulate state changes, receipts, and the cumulative gas counter.

A custom EVM must match MegaEVM's semantics exactly — see [Re-execution requirements](#re-execution-requirements).

Re-implementers can either link `mega-evm` directly or build a compatible EVM from the [MegaEVM specification — Dual Gas Model](https://docs.megaeth.com/spec/megaevm/dual-gas-model) and the related spec pages linked under [Re-execution requirements](#re-execution-requirements).

{% hint style="info" %}
**Reference impl.** Wires this through [`MegaBlockExecutorFactory` and `MegaEvmFactory`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/executor.rs#L273) from the [`mega-evm`](https://github.com/megaeth-labs/mega-evm) crate, which extends `revm` rather than forking it.
{% endhint %}

The `BLOCKHASH` opcode is served from the witnessed [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935) history-storage contract entries — see [`evm_database.rs:149`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/evm_database.rs#L149). There is no separate "ancestor headers" field in the witness.
{% endstep %}

{% step %}

### Apply post-execution system updates

After the last transaction, apply hardfork-conditional post-block system calls — including primarily EIP-7002 withdrawal-request and EIP-7251 consolidation-request processing on Isthmus+. The `withdrawals_root` is **not** computed here: it is recomputed separately in step 9 against the L1 message-passer storage trie. As with pre-execution, the exact hook set is fixed by the active hardfork.

{% hint style="info" %}
**Reference impl.** [`apply_post_execution_changes`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/executor.rs#L373) inside [`replay_block`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/executor.rs#L252) delegates to op-reth's `BlockExecutor` for the canonical hook list.
{% endhint %}
{% endstep %}

{% step %}

### Update the withdrawals MPT and recompute `withdrawals_root`

`MptWitness` carries the storage trie of the L2-to-L1 message-passer contract (`0x4200000000000000000000000000000000000016`) as RLP-encoded MPT nodes plus its pre-state root.

Apply the block's withdrawal-message writes against this trie, then recompute the root. This must match `block.withdrawals_root`.

{% hint style="info" %}
**Reference impl.** [`MptWitness::verify`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/withdrawals.rs#L80).
{% endhint %}
{% endstep %}

{% step %}

### Apply state changes to SALT and recompute `state_root`

Flatten the EVM's collected state changes into `(SaltKey, SaltValue)` pairs.

{% hint style="info" %}
**Reference impl.** Uses two intermediate types — `PlainKey` (account address or `address ++ slot`) and `PlainValue` (encoded account or 32-byte slot) — defined in [`crates/stateless-core/src/data_types.rs`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/data_types.rs).
{% endhint %}

Encoding rules (mirrored on [Get Block Witness](/node-operation/stateless-validation/witness#saltvalue) for the reverse direction):

| Update           | `key_len` | `value_len` | Layout                                                                              |
| ---------------- | --------- | ----------- | ----------------------------------------------------------------------------------- |
| EOA account      | 20        | 40          | 8-byte big-endian nonce ‖ 32-byte big-endian balance.                               |
| Contract account | 20        | 72          | 8-byte big-endian nonce ‖ 32-byte big-endian balance ‖ 32-byte keccak256 code hash. |
| Storage slot     | 52        | 32          | Key is `address(20) ‖ slot(32)`; value is the 32-byte big-endian U256.              |

Apply these updates to the SALT trie in canonical (sorted) key order and recompute the root. This must match `block.state_root`.
{% endstep %}

{% step %}

### Compare every header commitment

The block validates only if **every** check below passes:

| Field              | Source                                                             |
| ------------------ | ------------------------------------------------------------------ |
| `state_root`       | Recomputed SALT root from the previous step.                       |
| `withdrawals_root` | Recomputed MPT root from step 9.                                   |
| `receipts_root`    | Merkle root of the transactions' receipts collected during replay. |
| `logs_bloom`       | Aggregated 256-byte bloom filter over emitted logs.                |
| `gas_used`         | Cumulative gas counter from replay.                                |

A single mismatch is a fatal error for the block — do **not** advance the local chain.

{% hint style="info" %}
**Reference impl.** Comparisons are at [`executor.rs:534-559`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/executor.rs#L534).
{% endhint %}
{% endstep %}

{% step %}

### Advance the local chain

If all checks pass, persist the block as the new tip.

If the validated block's `parent_hash` does not match the previous tip, treat it as a reorg: walk back to the divergence and re-validate forward along the new branch.
{% endstep %}
{% endstepper %}

## Re-execution requirements

A custom EVM must implement [OP-Stack Isthmus](https://docs.megaeth.com/spec/overview) semantics — MegaETH's baseline, inherited unless explicitly overridden — **plus** the MegaEVM-specific extensions below. Each link points to the normative specification.

| Topic             | Reference                                                                                                                                                                                          |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Dual gas model    | [Dual Gas Model](https://docs.megaeth.com/spec/megaevm/dual-gas-model) — compute gas vs. storage gas accounting per opcode.                                                                        |
| Resource limits   | [Resource Limits](https://docs.megaeth.com/spec/megaevm/resource-limits) — per-block and per-transaction caps.                                                                                     |
| System contracts  | [System Contracts](https://docs.megaeth.com/spec/system-contracts/overview) — addresses and behaviors that MUST be replicated.                                                                     |
| Precompiles       | OP-Stack Isthmus set, with MegaETH gas-cost overrides at a few standard addresses. See [Precompiles](https://docs.megaeth.com/spec/megaevm/precompiles) for the full list and per-address details. |
| Volatile data     | [Volatile Data Access](/developer-docs/overview-3/volatile-data) — non-deterministic reads and how they are handled at re-execution.                                                               |
| Hardfork schedule | The genesis JSON the validator is started with. Mirror the same schedule in your own client.                                                                                                       |

{% hint style="info" %}
**Reference impl.** If `block_replay_time_seconds` exceeds the chain's block period, you are not real-time — diagnose with the per-stage histograms in [Stateless Validation](/node-operation/stateless-validation#useful-metrics).
{% endhint %}

## Trust model and reorgs

The validator has two trust inputs, both supplied at startup:

* The **genesis JSON** — supplies the chain ID and hardfork schedule (see [Genesis configuration](#genesis-configuration)). Persisted on first run; reused thereafter.
* The **anchor block hash** — pins the chain head. The next validated block's `parent_hash` must equal this value.

Everything downstream is verified:

* The witness is verified cryptographically against the parent's state root before replay.
* Bytecode is verified by recomputing `keccak256(code)` on every cache miss.
* The post-state is verified by recomputing every header commitment.

The validator does **not** verify:

* **Block canonicity.** The validator validates whatever block sequence is fed to it; it does not decide which fork is canonical. To derive canonicality from L1 instead of trusting the upstream RPC, pair the validator with `op-node`, which derives the canonical block sequence directly from L1, and the replica feeds those blocks to the validator.

Reorgs are detected when a freshly validated block's `parent_hash` does not match the local tip. The chain advancer truncates back to the divergence height and re-validates the new branch from there; the canonical-chain row cap (`canonical-chain-max-length`) bounds how far back this can reach.

## Reference implementation

The reference client is a Cargo workspace. The crates below are the entry points a re-implementation will most often want to mirror:

| Crate                 | Path                                                                                                                | Role                                                                           |
| --------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `stateless-core`      | [`crates/stateless-core/`](https://github.com/megaeth-labs/stateless-validator/tree/main/crates/stateless-core)     | Validation pipeline, witness-backed `revm` database, SALT update path.         |
| `stateless-common`    | [`crates/stateless-common/`](https://github.com/megaeth-labs/stateless-validator/tree/main/crates/stateless-common) | Multi-endpoint RPC client with retry/backoff and independent concurrency caps. |
| `stateless-db`        | [`crates/stateless-db/`](https://github.com/megaeth-labs/stateless-validator/tree/main/crates/stateless-db)         | redb-backed chain store, contract cache, table layout.                         |
| `stateless-validator` | [`bin/stateless-validator/`](https://github.com/megaeth-labs/stateless-validator/tree/main/bin/stateless-validator) | CLI, configuration, metrics endpoint, signal handling.                         |

Companion repositories:

* [`megaeth-labs/salt`](https://github.com/megaeth-labs/salt) — the authenticated key-value store and IPA proof system. Defines [`SaltWitness`](https://github.com/megaeth-labs/salt/blob/main/salt/src/proof/salt_witness.rs#L46), [`SaltKey`](https://github.com/megaeth-labs/salt/blob/main/salt/src/types.rs#L198), [`SaltValue`](https://github.com/megaeth-labs/salt/blob/main/salt/src/types.rs#L274), and [`SaltProof`](https://github.com/megaeth-labs/salt/blob/main/salt/src/proof/prover.rs#L103).
* [`megaeth-labs/mega-evm`](https://github.com/megaeth-labs/mega-evm) — the MegaEVM execution layer, layered on top of `revm`.

## Related pages

* [Get Block Witness](/node-operation/stateless-validation/witness) — wire format, decoding pipeline, and field-by-field type definitions for the witness payload.
* [Stateless Validation](/node-operation/stateless-validation) — operator guide for running the reference client (CLI, metrics, anchoring, troubleshooting).
* [Architecture](/architecture) — how transactions move through MegaETH and where validators fit in.
* [MegaEVM specification — Dual Gas Model](https://docs.megaeth.com/spec/megaevm/dual-gas-model) — normative MegaEVM behavior; entry point into the spec space.


# Get Block Witness

mega\_getBlockWitness — fetch the SALT + MPT witness needed to stateless-verify a MegaETH block.

MegaETH defines a `mega_getBlockWitness` RPC method to return the cryptographic witness for a single MegaETH block. The witness contains the subset of state the block reads or writes, packaged with proofs against the previous block's state root, so that a stateless verifier can re-execute the block without holding any chain state locally.

The RPC method is served at the public MegaETH RPC endpoint:

```
https://mainnet.megaeth.com/rpc
```

The witness JSON-RPC method is the same logical service that powers the [stateless validator](/node-operation/stateless-validation)'s `--witness-endpoint`. Any client — an operator running [`stateless-validator`](https://github.com/megaeth-labs/stateless-validator) or a custom verifier — can call it directly.

## Request

|        | Value                             |
| ------ | --------------------------------- |
| Method | `mega_getBlockWitness`            |
| Params | `[<keys>]` — single-element array |

`<keys>` is a JSON object that identifies the block. `blockNumber` is always required; pair it with `blockHash` to pin the witness to a specific block.

| Field         | Type              | Required | Description                                                                                             |
| ------------- | ----------------- | -------- | ------------------------------------------------------------------------------------------------------- |
| `blockNumber` | `Quantity` (hex)  | Yes      | Block number, 0x-prefixed lowercase hex (e.g. `"0x7fd"`).                                               |
| `blockHash`   | `Data` (32 bytes) | No       | 0x-prefixed lowercase hash of the block to fetch the witness for. Pins the result, so it is reorg-safe. |

### Lookup modes

The combination of fields chosen determines the lookup mode. **Always pass `blockHash` when one is available.** The `blockNumber`-only mode does not pin the result to a specific block and can return a witness for the wrong fork.

| Mode                        | Recommendation | When to use                                                                                                                                                                                                                                                   |
| --------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `blockNumber` + `blockHash` | **Preferred**  | The caller already knows the canonical block hash (e.g. fetched from `eth_getBlockByNumber` first). The witness is pinned to that exact block, so the result is reorg-safe.                                                                                   |
| `blockNumber`               | **Avoid**      | Last-resort convenience. The backend returns the first stored witness it finds at that height — there is **no guarantee** the returned witness is for the block you expect. Only use when you cannot obtain a hash and can independently verify the response. |

{% hint style="warning" %}
Calling `mega_getBlockWitness` with `blockNumber` only is unsafe for any caller that needs a specific block. The server returns the first witness it finds at that height, which is non-deterministic, may correspond to a non-canonical fork, and may change between calls. Always pair `blockNumber` with `blockHash` unless you are willing to validate the response yourself (e.g. by re-deriving the block hash from the returned witness against an independently-trusted header).
{% endhint %}

### Examples

{% tabs %}
{% tab title="Preferred — by block number and hash" %}

```json
[
  {
    "blockNumber": "0x7fd",
    "blockHash": "0x262206173864c1e597ab9fcf2f718f95f942907207f4fed97dda66d272c5d4a6"
  }
]
```

{% endtab %}

{% tab title="By block number only (unsafe)" %}

```json
[{ "blockNumber": "0x7fd" }]
```

{% endtab %}
{% endtabs %}

## Response

The response `result` is a single string of the form `<version>:<base64-payload>`.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "v0:<base64 payload>"
}
```

| Field     | Description                                                                                                                                                                                     |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `version` | Encoding version. Currently `v0`. Bumped if the witness payload format ever changes — clients must check the prefix.                                                                            |
| `payload` | Base64-encoded, Zstd-compressed [bincode](https://docs.rs/bincode/2.0.1/bincode) tuple ([`SaltWitness`](#saltwitness--main-state-trie), [`MptWitness`](#mptwitness--withdrawals-storage-trie)). |

### Errors

| Code     | Cause                                                                                                         |
| -------- | ------------------------------------------------------------------------------------------------------------- |
| `-32602` | Invalid params — malformed JSON, missing `blockNumber`, unparseable hex, or an invalid parameter combination. |
| `-32603` | Witness not found for the requested keys, or a server-side failure while fetching it.                         |

A missing witness and a server-side fetch failure both surface as `-32603`; the error `message` distinguishes them. To treat a missing witness as an expected outcome, match both `code == -32603` and an error `message` containing `Witness not found`. Treating `-32603` alone as a hard failure produces false alerts for testnet blocks outside the covered range — see [Historical coverage](#historical-coverage) below. The RPC layer in front of the witness service may also return standard JSON-RPC transport codes: `-32700` (parse error), `-32600` (invalid request).

### Historical coverage

Witness availability on the public RPC depends on the network:

| Network | Coverage                                                                                                                                                 |
| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Mainnet | All blocks.                                                                                                                                              |
| Testnet | As of 2026-07-24: block `1000` (a permanent test fixture) and blocks `>= 10325789`. Older testnet witnesses are not guaranteed and cannot be backfilled. |

Requesting a testnet block outside this range typically returns `Witness not found`.

### Decoding pipeline

To turn the response string back into a witness, apply these steps in order:

1. Verify the string starts with the literal prefix `v0:` and strip it.
2. Base64-decode the payload (standard alphabet, padded).
3. Zstd-decompress the result.
4. Bincode-deserialize using the **legacy** config (fixed-int encoding, little-endian) into `(SaltWitness, MptWitness)`.

A reference Rust implementation lives in the upstream stateless validator at [`fetch_witness_raw`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-common/src/rpc_client.rs#L978):

```rust
use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _};
use bincode::{config, serde::decode_from_slice};
use salt::SaltWitness;
use stateless_core::withdrawals::MptWitness;
use zstd;

let b64 = encoded.strip_prefix("v0:").ok_or("missing v0 prefix")?;
let compressed = BASE64.decode(b64)?;
let decompressed = zstd::decode_all(compressed.as_slice())?;
let (salt_witness, mpt_witness): (SaltWitness, MptWitness) =
    decode_from_slice(&decompressed, config::legacy())?.0;
```

{% hint style="info" %}
`SaltWitness` is defined in the [`salt`](https://github.com/megaeth-labs/salt) crate; `MptWitness` is defined in the `stateless-core` crate of the [`stateless-validator`](https://github.com/megaeth-labs/stateless-validator) repository. Add both as Cargo dependencies (via a git or path source) before compiling this snippet.
{% endhint %}

## Witness data structure

The decoded payload is a 2-tuple — one component per state surface the validator must check. Every type below is given as the upstream Rust definition with its source location, so a third-party decoder in another language can reproduce the byte layout exactly.

### `SaltWitness` — main state trie

Carries the subset of [SALT](https://github.com/megaeth-labs/salt) key-value pairs the block touches, plus a single multi-point IPA proof binding them to the previous block's state root.

Defined at [`salt/src/proof/salt_witness.rs:46`](https://github.com/megaeth-labs/salt/blob/main/salt/src/proof/salt_witness.rs#L46):

```rust
pub struct SaltWitness {
    pub kvs:   BTreeMap<SaltKey, Option<SaltValue>>,
    pub proof: SaltProof,
}
```

| Field   | Description                                                                                                                                                      |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kvs`   | Witnessed slots. `Some(v)` means the slot is occupied with value `v`; `None` means the slot is proven empty; an absent key is **unknown** (verifier must error). |
| `proof` | IPA multi-point proof + the path commitments needed to authenticate every entry in `kvs` against the state root.                                                 |

A verifier uses the witness as a `StateReader` / `TrieReader`: every state read during block re-execution falls through to `kvs` (existence-proven) or errors (unknown). The three-state distinction (existing / proven-empty / unknown) is what blocks a malicious witness server from hiding state by omission — see the security model in the upstream `SaltWitness` doc-comment. For the trie design this witness proves against, see the [SALT README](https://github.com/megaeth-labs/salt#design).

#### `SaltKey`

Defined at [`salt/src/types.rs:198`](https://github.com/megaeth-labs/salt/blob/main/salt/src/types.rs#L198):

```rust
pub struct SaltKey(pub u64);
```

The `u64` packs the SALT trie address into two fields:

| Bits      | Field       | Range           | Meaning                                                                                       |
| --------- | ----------- | --------------- | --------------------------------------------------------------------------------------------- |
| `63..=40` | `bucket_id` | 24 bits (\~16M) | Index into the static main trie. The first `NUM_META_BUCKETS = 65_536` buckets hold metadata. |
| `39..=0`  | `slot_id`   | 40 bits (\~1T)  | Slot offset inside the bucket's SHI hash table.                                               |

Use `bucket_id = key >> 40` and `slot_id = key & ((1<<40) - 1)` to unpack. Bincode-legacy serializes `SaltKey` as a fixed 8-byte little-endian `u64`.

#### `SaltValue`

Defined at [`salt/src/types.rs:274`](https://github.com/megaeth-labs/salt/blob/main/salt/src/types.rs#L274):

```rust
pub const MAX_SALT_VALUE_BYTES: usize = 94;

pub struct SaltValue {
    pub data: [u8; MAX_SALT_VALUE_BYTES],  // serialized as a fixed 94-byte array
}
```

`data` holds a length-prefixed key-value blob:

| Offset                           | Size        | Field       |
| -------------------------------- | ----------- | ----------- |
| `0`                              | 1 byte      | `key_len`   |
| `1`                              | 1 byte      | `value_len` |
| `2..2+key_len`                   | `key_len`   | `key`       |
| `2+key_len..2+key_len+value_len` | `value_len` | `value`     |
| `2+key_len+value_len..94`        | remainder   | zero-padded |

Three `SaltValue` flavors share this encoding:

| Kind         | `key_len` | `value_len`              | Used bytes | Notes                                                                                                   |
| ------------ | --------- | ------------------------ | ---------- | ------------------------------------------------------------------------------------------------------- |
| `Account`    | 20        | 40 (EOA) / 72 (contract) | 62 / 94    | Key is the 20-byte address; value is the encoded account body.                                          |
| `Storage`    | 52        | 32                       | 86         | Key is `address(20) ++ storage_slot(32)`; value is the 32-byte slot value.                              |
| `BucketMeta` | 12        | 0                        | 14         | Reserved for the metadata buckets — `BucketMeta` is fully encoded into the 12-byte key, value is empty. |

#### `SaltProof`

Defined at [`salt/src/proof/prover.rs:103`](https://github.com/megaeth-labs/salt/blob/main/salt/src/proof/prover.rs#L103):

```rust
pub struct SaltProof {
    pub parents_commitments: BTreeMap<NodeId, SerdeCommitment>,
    pub proof:               SerdeMultiPointProof,
    pub levels:              FxHashMap<BucketId, u8>,
}
```

| Field                 | Type                                | Description                                                                                                                                                                                                                                                                     |
| --------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parents_commitments` | `BTreeMap<NodeId, SerdeCommitment>` | Commitment for every trie node on the path from a witnessed bucket up to the root. Lookups by `NodeId = u64` (a flat trie-node index) — the verifier walks these to the root.                                                                                                   |
| `proof`               | `SerdeMultiPointProof`              | The IPA multi-point opening proof over the Banderwagon scalar field. Serialized via `MultiPointProof::to_bytes`; deserialize with `MultiPointProof::from_bytes(&buf, DOMAIN_SIZE)` where `DOMAIN_SIZE = 256` (the IPA polynomial degree, matching SALT's 256-ary trie fan-out). |
| `levels`              | `FxHashMap<BucketId, u8>`           | Number of subtree levels for each bucket present in the proof. Required because the verifier doesn't always know a bucket's capacity from the witness alone.                                                                                                                    |

`SerdeCommitment` wraps a Banderwagon group `Element`; `SerdeMultiPointProof` wraps an `ipa_multipoint::MultiPointProof`. Both serialize to opaque byte vectors via the IPA crate's encoding.

{% hint style="info" %}
**Map encoding order.** `kvs` and `parents_commitments` are `BTreeMap`, so bincode emits their entries in canonical (sorted) key order — wire output is byte-stable for re-implementors that want to round-trip-compare. `levels` is an `FxHashMap`, whose iteration order depends on the hasher; do not assume a fixed order when re-encoding.
{% endhint %}

### `MptWitness` — withdrawals storage trie

A small Merkle Patricia Trie witness covering the storage trie of the L2-to-L1 message-passer contract (`0x4200000000000000000000000000000000000016`), so the validator can recompute `withdrawals_root` after applying the block's withdrawal-message writes.

Defined at [`stateless-core/src/withdrawals.rs:49`](https://github.com/megaeth-labs/stateless-validator/blob/main/crates/stateless-core/src/withdrawals.rs#L49):

```rust
pub struct MptWitness {
    pub storage_root: B256,         // 32-byte fixed array
    pub state:        Vec<Bytes>,   // length-prefixed list of RLP-encoded trie nodes
}
```

| Field          | Type         | Description                                                                                                                                             |
| -------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `storage_root` | `B256`       | Pre-state storage root of the L2ToL1MessagePasser contract. Serialized as 32 raw bytes.                                                                 |
| `state`        | `Vec<Bytes>` | RLP-encoded MPT trie nodes that authenticate the storage slots the block's withdrawal writes will touch. Each `Bytes` is a length-prefixed byte string. |

This is intentionally an MPT (not SALT) witness: withdrawals are committed to the standard Ethereum withdrawals MPT root for L1 compatibility, so the slice of state needed to maintain it is proved separately from the SALT-backed account/storage state.

## Example

Fetch the witness for a known block and pipe it through the decode pipeline. Replace `<BLOCK_NUMBER>` (0x-prefixed lowercase hex) and `<BLOCK_HASH>` with values from `eth_getBlockByNumber`. The pipeline below assumes `jq` and `zstd` are on `PATH` — install them via `brew install jq zstd` on macOS or `apt install jq zstd` on Debian/Ubuntu.

```bash
curl -sS https://mainnet.megaeth.com/rpc \
  -X POST -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "mega_getBlockWitness",
    "params": [{
      "blockNumber": "<BLOCK_NUMBER>",
      "blockHash": "<BLOCK_HASH>"
    }]
  }' \
  | jq -r '.result' \
  | sed 's/^v0://' \
  | base64 --decode \
  | zstd -d \
  > witness.bincode
```

`witness.bincode` is a Zstd-decompressed bincode tuple — feed it into a Rust deserializer (using the snippet under [Decoding pipeline](#decoding-pipeline)) to obtain `(SaltWitness, MptWitness)`.

## Related pages

* [Stateless Validation](/node-operation/stateless-validation) — the operator guide for the reference client that consumes this RPC.
* [stateless-validator source](https://github.com/megaeth-labs/stateless-validator) — Rust implementation of the witness fetcher and verifier.
* [SALT](https://github.com/megaeth-labs/salt) — the authenticated key-value store that produces `SaltWitness`.


# Debug Trace Server

Self-host debug\_\* and trace\_\* RPC methods for MegaETH by replaying blocks with SALT witnesses — no archive node required.

The **debug-trace-server** provides `debug_*` and `trace_*` JSON-RPC methods for MegaETH. It re-executes blocks against [SALT](https://github.com/megaeth-labs/salt) witness data instead of a full state database, so it needs no archive node and runs on commodity hardware.

Point it at any MegaETH RPC endpoint, and it can trace any block or transaction that endpoint serves.

## When to use this

Run your own debug-trace-server when you need a **self-hosted** trace endpoint — for example, to power a block explorer backend, an indexer, or high-volume trace queries that would exceed public RPC rate limits.

If you only need occasional traces, the public MegaETH RPC already serves `debug_traceTransaction` and related methods directly — see [Debugging Transactions](/developer-docs/overview-1/debugging).

## Installation

The server is built from source alongside the [stateless validator](/node-operation/stateless-validation).

```bash
git clone https://github.com/megaeth-labs/stateless-validator.git
cd stateless-validator
cargo build --release --bin debug-trace-server
```

The binary is at `./target/release/debug-trace-server`. The project pins a nightly Rust toolchain via `rust-toolchain.toml`; `cargo build` downloads it automatically on first run.

## Quick start

The server needs two upstream endpoints to operate:

| Flag                 | What it connects to                                               | Methods called                                                         |
| -------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------------- |
| `--rpc-endpoint`     | A MegaETH JSON-RPC node that serves standard Ethereum block data. | `eth_getBlockByNumber`, `eth_getHeaderByHash`, `eth_getCodeByHash`     |
| `--witness-endpoint` | A MegaETH endpoint that serves SALT block witnesses.              | [`mega_getBlockWitness`](/node-operation/stateless-validation/witness) |

{% hint style="info" %}
Most external teams do not run their own witness generator. Point `--witness-endpoint` at the MegaETH public RPC — it serves `mega_getBlockWitness` for all historical blocks on mainnet. On testnet, witnesses are only available for block `1000` and blocks `>= 10325789` — see [Historical coverage](/node-operation/stateless-validation/witness#historical-coverage). In the common case both flags point to the same URL.
{% endhint %}

{% tabs %}
{% tab title="Mainnet" %}

```bash
./target/release/debug-trace-server \
  --rpc-endpoint https://mainnet.megaeth.com/rpc \
  --witness-endpoint https://mainnet.megaeth.com/rpc
```

{% endtab %}

{% tab title="Testnet" %}

```bash
./target/release/debug-trace-server \
  --rpc-endpoint https://carrot.megaeth.com/rpc \
  --witness-endpoint https://carrot.megaeth.com/rpc
```

{% endtab %}
{% endtabs %}

The server listens on `0.0.0.0:8545` by default. Verify it is running:

```bash
curl -s http://localhost:8545 \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","method":"debug_traceBlockByNumber","params":["latest",{"tracer":"callTracer"}],"id":1}' \
  | head -c 200
```

### Production setup

For production traffic, add `--data-dir` to enable **local cache mode**. The server starts a background pipeline that pre-fetches blocks and witnesses into a local database, so trace requests read locally instead of hitting upstream RPC on every call.

```bash
./target/release/debug-trace-server \
  --rpc-endpoint https://mainnet.megaeth.com/rpc \
  --witness-endpoint https://mainnet.megaeth.com/rpc \
  --data-dir ./dts-data \
  --blocks-to-keep 5000 \
  --response-cache-max-size 2GB \
  --metrics-enabled
```

| Flag                            | Effect                                                                                            |
| ------------------------------- | ------------------------------------------------------------------------------------------------- |
| `--data-dir ./dts-data`         | Enable local cache mode. Creates a `trace_server.redb` database and starts background block sync. |
| `--blocks-to-keep 5000`         | Retain the most recent 5 000 blocks; older blocks are pruned automatically.                       |
| `--response-cache-max-size 2GB` | Cache serialized trace responses in memory so repeated requests return instantly.                 |
| `--metrics-enabled`             | Expose a Prometheus `/metrics` endpoint on port 9090.                                             |

{% hint style="warning" %}
On the first start with `--data-dir`, the server fetches the latest block from upstream as an anchor and begins syncing forward. To anchor at a specific block, pass `--start-block <BLOCK_HASH>` — this accepts a block **hash**, not a number.
{% endhint %}

## Supported RPC methods

### Geth-style (`debug_*`)

| Method                     | Description                                   |
| -------------------------- | --------------------------------------------- |
| `debug_traceBlockByNumber` | Trace all transactions in a block, by number. |
| `debug_traceBlockByHash`   | Trace all transactions in a block, by hash.   |
| `debug_traceTransaction`   | Trace a single transaction by hash.           |
| `debug_getCacheStatus`     | Query current response cache statistics.      |

The trace methods accept an optional second parameter with [Geth debug tracing options](https://geth.ethereum.org/docs/developers/evm-tracing/built-in-tracers):

```json
{
  "method": "debug_traceBlockByNumber",
  "params": ["latest", { "tracer": "callTracer" }]
}
```

Supported tracers:

| Tracer                  | `tracer` value     | Output                                                                        |
| ----------------------- | ------------------ | ----------------------------------------------------------------------------- |
| Default (struct logger) | *(omit)*           | Opcode-level trace with gas, stack, memory, storage at each step.             |
| Call tracer             | `"callTracer"`     | Nested call tree with inputs, outputs, gas per frame.                         |
| Prestate tracer         | `"prestateTracer"` | Account state before execution; add `"diffMode": true` for before/after diff. |
| 4-byte tracer           | `"4byteTracer"`    | Function selector frequency statistics.                                       |
| Flat call tracer        | `"flatCallTracer"` | Parity-style flat list of all internal calls.                                 |
| Noop tracer             | `"noopTracer"`     | No output — useful for benchmarking execution time.                           |
| Mux tracer              | `"muxTracer"`      | Run multiple tracers in a single pass.                                        |

Custom JavaScript tracers are also supported.

### Parity-style (`trace_*`)

| Method              | Description                                                                                                                                |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `trace_block`       | Flat call traces for all transactions in a block.                                                                                          |
| `trace_transaction` | Flat call traces for a single transaction. Returns `null` (not an error) when the transaction is not found, matching `mega-reth` behavior. |

Every method also has a `timed_`-prefixed alias (e.g. `timed_debug_traceBlockByNumber`) with identical behavior, letting callers tag client-side metrics separately.

## Command-line reference

Every flag has an equivalent environment variable. Command-line flags take precedence.

### Core flags

| Flag                 | Env variable                          | Required? | Description                                                                                                                                                                                                      |
| -------------------- | ------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--addr`             | `DEBUG_TRACE_SERVER_ADDR`             | No        | Listen address. Default: `0.0.0.0:8545`.                                                                                                                                                                         |
| `--rpc-endpoint`     | `DEBUG_TRACE_SERVER_RPC_ENDPOINT`     | Yes       | MegaETH JSON-RPC endpoint(s) for block data. Comma-separated or repeated for failover (round-robin).                                                                                                             |
| `--witness-endpoint` | `DEBUG_TRACE_SERVER_WITNESS_ENDPOINT` | Yes       | MegaETH endpoint(s) serving [`mega_getBlockWitness`](/node-operation/stateless-validation/witness). Comma-separated or repeated for failover (primary-failover: first endpoint takes all traffic while healthy). |
| `--genesis-file`     | `DEBUG_TRACE_SERVER_GENESIS_FILE`     | No        | Path to genesis JSON. Uses the built-in chain spec when unset.                                                                                                                                                   |

### Local cache

Omit `--data-dir` to run in stateless mode (no local storage).

| Flag                     | Env variable                              | Default   | Description                                                                                                       |
| ------------------------ | ----------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------- |
| `--data-dir`             | `DEBUG_TRACE_SERVER_DATA_DIR`             | *(unset)* | Directory for the local database. Enables local cache mode when set.                                              |
| `--start-block`          | `DEBUG_TRACE_SERVER_START_BLOCK`          | *(unset)* | Block **hash** for the initial anchor. When unset, the server fetches the latest block. Only used on first start. |
| `--blocks-to-keep`       | `DEBUG_TRACE_SERVER_BLOCKS_TO_KEEP`       | `1000`    | Recent blocks to retain. Older blocks are pruned.                                                                 |
| `--db-max-size`          | `DEBUG_TRACE_SERVER_DB_MAX_SIZE`          | `0` (off) | Max database file size (e.g. `10GB`). Triggers extra pruning (100-block batches) when exceeded.                   |
| `--pruner-interval-secs` | `DEBUG_TRACE_SERVER_PRUNER_INTERVAL_SECS` | `300`     | Seconds between pruning cycles.                                                                                   |

### Timeout and concurrency

| Flag                                | Env variable                                         | Default   | Description                                                                                       |
| ----------------------------------- | ---------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------- |
| `--witness-timeout`                 | `DEBUG_TRACE_SERVER_WITNESS_TIMEOUT`                 | `8`       | Witness fetch timeout in seconds.                                                                 |
| `--block-fetch-timeout`             | `DEBUG_TRACE_SERVER_BLOCK_FETCH_TIMEOUT_SECS`        | `13`      | Total timeout in seconds for all data needed for one block (header + witness + body + contracts). |
| `--rpc-per-attempt-timeout-ms`      | `DEBUG_TRACE_SERVER_RPC_PER_ATTEMPT_TIMEOUT_MS`      | *(unset)* | Per-attempt RPC timeout in milliseconds. Must be ≥ 100.                                           |
| `--data-max-concurrent-requests`    | `DEBUG_TRACE_SERVER_DATA_MAX_CONCURRENT_REQUESTS`    | unlimited | Cap on concurrent in-flight data requests (blocks, headers, code).                                |
| `--witness-max-concurrent-requests` | `DEBUG_TRACE_SERVER_WITNESS_MAX_CONCURRENT_REQUESTS` | unlimited | Cap on concurrent in-flight witness fetches, independent of the data cap.                         |

{% hint style="info" %}
The data and witness concurrency caps are independent semaphores — a burst on one path cannot starve the other. When using the public RPC, setting both to `4` prevents HTTP 429 rate-limiting.
{% endhint %}

### Response cache

| Flag                               | Env variable                                        | Default | Description                                                             |
| ---------------------------------- | --------------------------------------------------- | ------- | ----------------------------------------------------------------------- |
| `--response-cache-max-size`        | `DEBUG_TRACE_SERVER_RESPONSE_CACHE_MAX_SIZE`        | `1GB`   | Maximum memory for cached responses. Accepts `KB`, `MB`, `GB` suffixes. |
| `--response-cache-estimated-items` | `DEBUG_TRACE_SERVER_RESPONSE_CACHE_ESTIMATED_ITEMS` | `1000`  | Initial capacity hint. Set to `0` to disable the cache entirely.        |

The cache stores pre-serialized JSON responses keyed by `(block_number, tracer_type)`. Different tracers on the same block are cached independently. Entries are invalidated automatically on chain reorganization.

### Monitoring

| Flag                | Env variable                         | Default | Description                             |
| ------------------- | ------------------------------------ | ------- | --------------------------------------- |
| `--metrics-enabled` | `DEBUG_TRACE_SERVER_METRICS_ENABLED` | `false` | Enable the Prometheus metrics endpoint. |
| `--metrics-port`    | `DEBUG_TRACE_SERVER_METRICS_PORT`    | `9090`  | Port for the metrics HTTP endpoint.     |

When enabled, scrape `http://<HOST>:9090/metrics`.

| Metric                                                            | Type      | What it tells you                                |
| ----------------------------------------------------------------- | --------- | ------------------------------------------------ |
| `debug_trace_rpc_requests_total`                                  | Counter   | Total RPC requests, labelled by method.          |
| `debug_trace_rpc_errors_total`                                    | Counter   | Total RPC errors, labelled by method.            |
| `debug_trace_request_duration_seconds`                            | Histogram | End-to-end request latency.                      |
| `debug_trace_inflight_requests`                                   | Gauge     | Currently in-flight requests.                    |
| `debug_trace_cache_hits_total` / `debug_trace_cache_misses_total` | Counter   | Response cache hit/miss.                         |
| `debug_trace_evm_execution_seconds`                               | Histogram | EVM trace execution time per request.            |
| `debug_trace_upstream_duration_seconds`                           | Histogram | Upstream RPC latency, labelled by method.        |
| `debug_trace_witness_bytes`                                       | Histogram | Witness payload size.                            |
| `debug_trace_local_chain_height`                                  | Gauge     | Latest block in the local database.              |
| `debug_trace_db_size_bytes`                                       | Gauge     | Database file size on disk.                      |
| `debug_trace_reorg_depth`                                         | Histogram | Chain reorg depth detected by the sync pipeline. |

### Logging

Logging shares the same `--log.*` flags and `STATELESS_LOG_*` environment variables as the [stateless validator](/node-operation/stateless-validation#logging-flags). See that page for the full flag table.

Recommended production settings:

```bash
--log.stdout-format json \
--log.stdout-filter info \
--log.file-directory /var/log/dts \
--log.file-filter debug \
--log.file-max-size 500 \
--log.file-max-files 10
```

## Environment variables

All flags can be set via environment variables — convenient for container or orchestrator-based deployments:

```bash
DEBUG_TRACE_SERVER_ADDR=0.0.0.0:8545
DEBUG_TRACE_SERVER_RPC_ENDPOINT=https://mainnet.megaeth.com/rpc
DEBUG_TRACE_SERVER_WITNESS_ENDPOINT=https://mainnet.megaeth.com/rpc
DEBUG_TRACE_SERVER_DATA_DIR=/data/dts
DEBUG_TRACE_SERVER_BLOCKS_TO_KEEP=5000
DEBUG_TRACE_SERVER_RESPONSE_CACHE_MAX_SIZE=2GB
DEBUG_TRACE_SERVER_METRICS_ENABLED=true
STATELESS_LOG_STDOUT=info
STATELESS_LOG_STDOUT_FORMAT=json
```

## Troubleshooting

**Database needs a reset.** Stop the service, delete `trace_server.redb` from the data directory, and restart. The server re-syncs from the latest block automatically.

```bash
rm /data/dts/trace_server.redb
systemctl restart dts
```

**Upstream RPC is unreachable.** The server retries with round-robin failover and exponential backoff. While all endpoints are down, the sync pipeline stalls (it does not crash) and trace requests return error `-32001` after `--block-fetch-timeout` expires. Service resumes automatically once any endpoint recovers.

**High memory usage.** Lower `--response-cache-max-size` if the response cache is consuming too much memory. The contract bytecode cache is process-lifetime — chains with many deployed contracts accumulate bytecode in memory over time.

**Slow trace requests.** Use Prometheus metrics to isolate the bottleneck:

* `debug_trace_upstream_duration_seconds` high — upstream RPC is slow.
* `debug_trace_evm_execution_seconds` high — the block has many or complex transactions.
* `debug_trace_witness_bytes` large — witness payloads are large, causing slow fetches.

The server logs a warning (`slow stages detected`) for any request stage exceeding 1 second.

## Related pages

* [Debugging Transactions](/developer-docs/overview-1/debugging) — trace via the public RPC or `mega-evme` without running your own server
* [Stateless Validation](/node-operation/stateless-validation) — the stateless validator that cryptographically verifies every block
* [Get Block Witness](/node-operation/stateless-validation/witness) — `mega_getBlockWitness` RPC reference and witness data layout
* [debug-trace-server source](https://github.com/megaeth-labs/stateless-validator/tree/main/bin/debug-trace-server) — upstream Rust implementation


# MegaETH Specification

MegaETH formal specification — normative behavioral definitions for EVM execution, system contracts, oracle services, and protocol upgrades.

This is the formal specification of MegaETH's verifiable behavior — the complete, normative definition of how MegaETH processes transactions, enforces resource limits, and manages protocol state. It covers every behavioral difference from standard Ethereum and Optimism: the EVM modifications, system contracts, oracle services, resource metering, and the upgrade history that defines how these features evolved.

Any node implementation that produces the same outputs given the same inputs for every case defined in this specification is a correct MegaETH node.

The reference implementation is [MegaEVM](https://github.com/megaeth-labs/mega-evm), built on [revm](https://github.com/bluealloy/revm) and [op-revm](https://github.com/bluealloy/op-revm). All standard EVM semantics are inherited from Optimism Isthmus (Ethereum Prague) unless explicitly overridden. Transactions that don't touch MegaETH-specific features behave identically to Optimism.

## Why MegaETH Differs from Standard Ethereum

MegaETH is designed for real-time performance: sub-millisecond block times, extremely low base fees, and transaction gas limits far higher than Ethereum's. These properties break assumptions that standard EVM gas pricing relies on.

Under standard EVM rules, MegaETH's low fees and high gas limits would make storage operations — state writes, logs, calldata — dramatically underpriced relative to their cost to node operators. A single transaction could bloat on-chain state or history data for nearly free. At the same time, MegaETH's parallel transaction execution requires mechanisms to detect and limit conflicts between concurrently executing transactions that read shared data.

MegaETH addresses these problems with a targeted set of protocol-level modifications:

* [**Dual Gas Model**](/spec/megaevm/dual-gas-model) — Adds a [storage gas](/spec/reference/glossary#storage-gas) dimension on top of standard [compute gas](/spec/reference/glossary#compute-gas), so state-heavy operations pay their true cost even when base fees are low.
* [**Multidimensional Resource Limits**](/spec/megaevm/resource-limits) — Enforces four independent per-transaction limits (compute gas, data size, KV updates, state growth) beyond the standard gas limit, preventing any single resource from being exhausted by a single transaction.
* [**Gas Detention**](/spec/megaevm/gas-detention) — Caps remaining compute gas after a transaction reads [volatile data](/spec/reference/glossary#volatile-data) (block environment, oracle storage), forcing such transactions to terminate quickly and reducing parallel execution conflicts.
* [**Dynamic Gas Costs**](/spec/megaevm/dual-gas-model#dynamic-salt-multiplier) — Scales storage gas based on [SALT bucket](/spec/reference/glossary#salt-bucket) capacity, making writes to crowded state regions progressively more expensive while keeping fresh storage free.
* [**System Contracts**](/spec/system-contracts/overview) — Pre-deployed protocol contracts providing oracle storage, high-precision timestamps, keyless deployment, and runtime access/limit control.

## How to Use This Documentation

This specification targets teams implementing MegaETH-compatible execution clients, auditors verifying protocol correctness, and anyone who needs the exact behavioral semantics of MegaEVM.

Start with [Hardforks and Specs](/spec/hardfork-spec) to understand how behavior is versioned, then read each [Network Upgrade](/spec/network-upgrades/overview) page for the exact behavioral deltas introduced at each spec. For the current stable behavior as a single reference, see the [MegaEVM Overview](/spec/megaevm/overview).

## Reference Implementation

| Component        | Version                                                    |
| ---------------- | ---------------------------------------------------------- |
| **MegaEVM**      | [mega-evm](https://github.com/megaeth-labs/mega-evm)       |
| **Base EVM**     | [revm v27.1.0](https://github.com/bluealloy/revm)          |
| **Optimism EVM** | [op-revm v8.1.0](https://github.com/bluealloy/op-revm)     |
| **Alloy EVM**    | [alloy-evm v0.15.0](https://github.com/alloy-rs/alloy-evm) |

## Spec Progression

MegaETH uses a spec system to version its verifiable behavior at each stage of the protocol's evolution. Each newer spec includes all previous behaviors:

```
EQUIVALENCE → MINI_REX → REX → REX1 → REX2 → REX3 → REX4 → REX5 → REX6 → REX7
```

{% hint style="info" %}
**Backward Compatibility** — EVM semantics for frozen specs are fixed. A new spec may add behavior, but it never changes what an existing frozen spec does. Contracts deployed under a given spec will continue to behave identically, regardless of future upgrades.
{% endhint %}

* **EQUIVALENCE** — Baseline. Full Optimism Isthmus compatibility with block environment access tracking for parallel execution.
* **MINI\_REX** — Dual gas model, multidimensional resource limits, gas detention, 98/100 gas forwarding, SELFDESTRUCT disabled, Oracle and Timestamp system contracts.
* **REX** — Revised storage gas economics (`base × (multiplier − 1)`), transaction intrinsic storage gas, state growth tracking, consistent CALL-like opcode behavior.
* **REX1** — Fix: compute gas limit reset between transactions.
* **REX2** — SELFDESTRUCT re-enabled (EIP-6780), KeylessDeploy system contract.
* **REX3** — Oracle gas cap raised to 20M, SLOAD-based oracle detention, keyless deploy compute gas tracking.
* **REX4** — Per-call-frame resource budgets, relative gas detention, [storage gas stipend](/spec/reference/glossary#storage-gas-stipend), MegaAccessControl and MegaLimitControl system contracts.
* **REX5** — SequencerRegistry system contract, Oracle v2.0.0 with dynamic system address, caller-account update deduplication, storage-gas-stipend separated-allowance model, value-transfer CALL/CALLCODE parent compute-gas attribution, CREATE code-deposit compute-gas atomicity, EIP-2935/EIP-4788 pre-block gas floor with fail-closed block rejection, CREATE2 empty-initcode short-circuit, KeylessDeploy trailing-bytes rejection and empty-code log forwarding.
* **REX6** — Unified per-opcode gas metering order, consolidated EIP-7702 authorization accounting, CREATE-frame accounting corrections, KeylessDeploy sandbox hardening, post-execution fee-reward accounting, system-originated transaction metering exemption, extended beneficiary detention coverage, and SequencerRegistry v2.0.0 rotation hardening.
* **REX7** — The **unstable** spec, currently open for development. No behavioral change over REX6 yet.

See [Hardforks and Specs](/spec/hardfork-spec) for full details.

***

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this specification are to be interpreted as described in [BCP 14](https://www.rfc-editor.org/info/bcp14) ([RFC 2119](https://www.rfc-editor.org/rfc/rfc2119), [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174)) when, and only when, they appear in all capitals, as shown here.


# Hardforks and Specs

MegaETH hardfork and spec versioning — how behavioral changes are versioned, activated, and tracked across network upgrades.

MegaETH versions its verifiable behavior through **hardforks** and **specs**. This page defines both concepts and summarizes what each spec introduces.

## Hardfork vs Spec

The protocol distinguishes between two related concepts:

* [**Hardfork**](/spec/reference/glossary#hardfork-megahardfork) — A network upgrade event: *when* changes are activated on the chain. A hardfork may include protocol-level changes beyond MegaEVM (e.g., networking, state sync, RPC behavior).
* [**Spec**](/spec/reference/glossary#spec-megaspecid) — A set of MegaETH verifiable behaviors: *what* a correct node does. A spec captures the execution-layer semantics that determine node correctness.

Multiple hardforks can map to the same spec. A hardfork can also map to an older spec. For example: `MiniRex` → `MINI_REX`, `MiniRex1` → `EQUIVALENCE` (rollback), `MiniRex2` → `MINI_REX` (restoration).

This documentation covers specs — the verifiable behavioral definitions that determine correctness of a MegaETH node. Protocol-level changes outside the verifiable execution layer (e.g., networking, peer discovery) that are part of a hardfork are not covered here.

## Spec Progression

```
EQUIVALENCE → MINI_REX → REX → REX1 → REX2 → REX3 → REX4 → REX5 → REX6 → REX7
```

Each newer spec includes all previous behaviors. All specs build on Optimism Isthmus (Ethereum Prague) as the base layer. All specs through REX6 are frozen; REX7 is **unstable** and under active development.

Frozen and activated are separate properties. A frozen spec's semantics no longer change, but it takes effect on a network only once that network schedules the corresponding hardfork. REX7 is unstable and has no activation timestamp on either mainnet or testnet.

### Backward Compatibility

A frozen spec's EVM semantics never change again. Freezing is what confers that guarantee — not activation: a frozen spec no network has scheduled is as immutable as one running on mainnet, because a future schedule would replay history against it. A new spec may add behavior, but it never alters what an existing frozen spec does.

This means:

* Contracts deployed under a given spec continue to behave identically after future upgrades.
* Adding or modifying a system contract requires introducing a new spec.
* Changing gas costs, opcode behavior, or resource limits requires a new spec.
* Implementations gate spec-specific behavior on the active spec.

## Spec Summary

### EQUIVALENCE

The baseline spec. Maintains full compatibility with Optimism Isthmus EVM. Adds block environment access tracking for parallel execution support.

### MINI\_REX

The first spec to introduce MegaETH-specific modifications:

* [**Dual gas model**](/spec/megaevm/dual-gas-model) — [Compute gas](/spec/reference/glossary#compute-gas) + [storage gas](/spec/reference/glossary#storage-gas)
* [**Multidimensional resource limits**](/spec/megaevm/resource-limits) — Compute gas (1B), data size (3.125 MB), KV updates (125K)
* [**Dynamic gas costs**](/spec/megaevm/dual-gas-model#dynamic-salt-multiplier) — [SALT bucket](/spec/reference/glossary#salt-bucket)-based scaling
* [**Gas detention**](/spec/megaevm/gas-detention) — [Volatile data](/spec/reference/glossary#volatile-data) access triggers gas limiting
* **SELFDESTRUCT disabled**
* **Large contract support** — 512 KB contracts (21x increase from 24 KB)

*See* [*MiniRex Network Upgrade*](/spec/network-upgrades/minirex) *for full details.*

### REX

Refines the [storage gas](/spec/reference/glossary#storage-gas) economics introduced in MINI\_REX:

* **Refined storage gas formulas** — Gradual scaling (20K–32K base costs vs MiniRex's 2M)
* **Transaction intrinsic storage gas** — 39,000 flat fee for all transactions
* **Zero cost fresh storage** — Minimum-sized [SALT buckets](/spec/reference/glossary#salt-bucket) charge 0 storage gas
* **Security fixes** — DELEGATECALL, STATICCALL, CALLCODE properly enforce gas forwarding and oracle access detection
* [**State growth**](/spec/megaevm/resource-accounting#state-growth) **tracking** — New [resource limit](/spec/megaevm/resource-limits) dimension

*See* [*Rex Network Upgrade*](/spec/network-upgrades/rex) *for full details.*

### REX1

* **Limit reset fix** — Resets compute gas limits at the start of each transaction
* Inherits Rex semantics fully

*See* [*Rex1 Network Upgrade*](/spec/network-upgrades/rex1) *for full details.*

### REX2

* **SELFDESTRUCT restored** — Re-enabled with [EIP-6780](https://eips.ethereum.org/EIPS/eip-6780) semantics
* [**KeylessDeploy**](/spec/system-contracts/keyless-deploy) **system contract** — Enables deterministic cross-chain deployment (Nick's Method)

*See* [*Rex2 Network Upgrade*](/spec/network-upgrades/rex2) *for full details.*

### REX3

* **Increased oracle access gas limit** — Raised from 1M to 20M
* **SLOAD-based** [**oracle**](/spec/system-contracts/oracle) **detention** — Triggers on SLOAD from oracle storage instead of CALL to oracle contract
* [**Keyless deploy**](/spec/system-contracts/keyless-deploy) [**compute gas**](/spec/reference/glossary#compute-gas) **tracking** — Records the 100K overhead as compute gas

*See* [*Rex3 Network Upgrade*](/spec/network-upgrades/rex3) *for full details.*

### REX4

* **Per-**[**call-frame**](/spec/reference/glossary#call-frame) **resource budgets** — All four [resource dimensions](/spec/reference/glossary#resource-dimension) (compute gas, data size, KV updates, state growth) are bounded per call frame with 98/100 forwarding
* **Relative** [**gas detention**](/spec/megaevm/gas-detention) **cap** — Effective [detained limit](/spec/reference/glossary#detained-limit) is `current_usage + cap` instead of an absolute cap
* [**Storage gas stipend**](/spec/reference/glossary#storage-gas-stipend) — Value-transferring CALL/CALLCODE receives an additional 23,000 gas for [storage gas](/spec/reference/glossary#storage-gas) operations, fixing LOG events in `receive()` under the [dual gas model](/spec/megaevm/dual-gas-model)
* **MegaAccessControl system contract** — Allows contracts to proactively disable [volatile data](/spec/reference/glossary#volatile-data) access for a call subtree
* **MegaLimitControl system contract** — Allows querying effective remaining compute gas under detention and call frame limits
* [**Keyless deploy**](/spec/system-contracts/keyless-deploy) **sandbox environment inheritance** — Sandbox inherits parent transaction's external environment for dynamic pricing and oracle behavior

*See* [*Rex4 Network Upgrade*](/spec/network-upgrades/rex4) *for full details.*

### REX5

* [**SequencerRegistry**](/spec/system-contracts/sequencer-registry) **system contract** — Tracks the system address and sequencer roles independently with on-chain change scheduling and history.
* **Dynamic system address** — `MEGA_SYSTEM_ADDRESS` is resolved per block from `SequencerRegistry.currentSystemAddress()` instead of a hardcoded constant.
* **Oracle v2.0.0** — `onlySystemAddress` reads the authority from `SequencerRegistry`. In-place Oracle bytecode upgrades preserve existing storage instead of clearing it.
* **Caller-account update deduplication** — Fixes overcounting of caller-account data-size and KV updates across multiple value-transferring sub-calls or creates from the same parent frame.
* [**KeylessDeploy**](/spec/system-contracts/keyless-deploy) **trailing-bytes rejection** — RLP encodings with trailing bytes after the signed payload are rejected with `MalformedEncoding()`.
* **CALLCODE new-account storage gas fix** — New-account storage gas is now charged against the caller's storage context rather than the code-source address.
* **Storage-gas-stipend separated allowance** — The `STORAGE_CALL_STIPEND` no longer inflates the callee's gas limit; it is a per-frame allowance drawn only at storage-gas surcharge sites and is neither burned nor rescued.
* **Value-transfer CALL/CALLCODE compute attribution** — Compute gas recorded into the parent excludes the `CALL_STIPEND` granted to the callee.
* **CREATE code-deposit compute-gas atomicity** — Contract-creation code-deposit compute gas is charged atomically with the deployment commit and not double-counted in post-execution accounting.
* **EIP-2935 / EIP-4788 pre-block gas floor** — The history-storage and beacon-roots pre-block system calls use `max(block_gas_limit, 30,000,000)` and are fail-closed: a non-successful call rejects the block.
* **CREATE2 empty-initcode short-circuit** — A `CREATE2` with zero-length init code short-circuits after the salt check using the empty-code hash, without offset conversion, memory expansion, or hashing.
* **KeylessDeploy empty-code log forwarding** — An empty-runtime-code deployment success forwards the constructor's logs before returning.

*See* [*Rex5 Network Upgrade*](/spec/network-upgrades/rex5) *for full details.*

### REX6

REX6 is frozen and scheduled on both networks; see the [upgrade overview](/spec/network-upgrades/overview) for activation timestamps.

* **Unified per-opcode gas metering order** — Every storage-affecting opcode charges storage gas before its body and records compute gas exactly once after the body completes; the `CREATE2` memory-expansion gas is folded into that single recording.
* **Consolidated EIP-7702 authorization accounting** — Per-authorization data-size and KV-update charges are narrowed to applied authorizations, authority state growth resolves during validation, net-new authorities pay dynamic SALT account-creation gas, and an applied authority equal to the block beneficiary triggers beneficiary gas detention.
* **CREATE-frame resource accounting** — The creator nonce-bump write is booked to the parent frame's discardable lane, and `CREATE` records state growth only for net-new addresses.
* [**KeylessDeploy**](/spec/system-contracts/keyless-deploy) **sandbox hardening** — Unused gas is rescued on a transaction-level compute-gas halt, and a self-destructing constructor is classified as an empty-code deployment.
* **Post-execution fee-reward accounting** — Account writes performed by the post-execution fee-reward step count toward resource accounting.
* **System-originated transaction metering exemption** — Pre-block system calls and [Mega System Transactions](/spec/system-contracts/system-tx) charge storage gas at minimum bucket capacity and are not halted by resource limits or gas detention.
* **Beneficiary detention / volatile-access coverage** — A `SELFDESTRUCT` executed by the beneficiary comes under `disableVolatileDataAccess`, and CALL-family targets whose EIP-7702 delegate resolves to the beneficiary come under both detention and `disableVolatileDataAccess`; a `SELFDESTRUCT` balance credit to an existing beneficiary counts toward resource accounting.
* **Additional resource-accounting corrections** — A per-log data-size base is charged for the log address, and forwarded gas returns to the parent when a `CALL` / `CREATE` halts on the compute-gas limit.
* **Value self-transfer dedup** — A value transfer whose target equals the caller is counted as a single account-info write.

*See* [*Rex6 Network Upgrade*](/spec/network-upgrades/rex6) *for full details.*

### REX7

REX7 is the current **unstable** spec under active development. It introduces no behavioral change over REX6 yet; its semantics may change at any time before it is frozen.

*See* [*Rex7 Network Upgrade*](/spec/network-upgrades/rex7) *for the current state.*


# Overview

MegaEVM specification index — dual gas model, resource limits, gas detention, system contracts, and per-spec behavioral history.

This page summarizes the current MegaEVM behavior. The linked concept pages are the authoritative specification for each behavior.

## Stable Scope

This page describes the current MegaEVM behavior. For full per-upgrade behavioral deltas, see [Network Upgrades](/spec/network-upgrades/overview).

## Specifications

### Inheritance Boundary

MegaEVM builds on Optimism Isthmus (Ethereum Prague). Unless explicitly overridden by the MegaETH specification, standard EVM behavior is inherited from that baseline.

### Gas and Resource Model

MegaETH replaces the single-dimensional intuition of standard EVM gas with a two-dimensional model. Every transaction is charged for both compute gas and storage gas, and the transaction's total gas usage is the sum of those two components.

Storage-heavy operations such as state writes, code deposit, logs, and calldata therefore carry additional cost beyond inherited EVM compute gas. For the complete formulas, constants, SALT multiplier rules, and charging lifecycle, see [Dual Gas Model](/spec/megaevm/dual-gas-model).

Compute gas is not an independent gas schedule but a derived measurement of the inherited EVM gas. For the measurement window, the per-opcode metering classes, the non-opcode recording sites, and the exceed behavior, see [Compute Gas Accounting](/spec/megaevm/compute-gas).

### Runtime Resource Limits and Accounting

In addition to the transaction's gas limit, MegaETH enforces separate runtime ceilings on compute gas, data size, KV updates, and state growth. These dimensions are tracked independently and limit execution even when the transaction still has remaining total gas.

The protocol distinguishes between:

* **resource limits**, which define ceilings and enforcement outcomes, and
* **resource accounting**, which defines how each dimension is counted during execution and across reverted call frames.

For limits, see [Resource Limits](/spec/megaevm/resource-limits). For counting rules, revert behavior, and deduplication rules, see [Resource Accounting](/spec/megaevm/resource-accounting).

### Gas Detention

MegaETH restricts post-access computation after a transaction reads [volatile data](/spec/reference/glossary#volatile-data). This includes block-environment data, beneficiary-related access, and oracle-backed data.

The purpose of gas detention is to bound the amount of compute gas that may follow access to shared, conflict-prone inputs. For the detention categories, cap semantics, and halt conditions, see [Gas Detention](/spec/megaevm/gas-detention).

### Execution Semantics Overrides

MegaEVM inherits the baseline semantics of Optimism Isthmus / Ethereum Prague, but overrides selected execution behaviors. The current stable differences include gas forwarding, contract size limits, precompile pricing overrides, and `SELFDESTRUCT` semantics.

### Gas Forwarding

CALL-like opcodes and `CREATE`/`CREATE2` use the 98/100 forwarding rule in current stable behavior. This differs from the standard EVM's 63/64 forwarding rule. The 98/100 rule was introduced in [Rex](/spec/network-upgrades/rex) for stable behavior. For the exact forwarding rule, stipend interaction, and opcode scope, see [Gas Forwarding](/spec/megaevm/gas-forwarding).

### SELFDESTRUCT

`SELFDESTRUCT` follows [EIP-6780](https://eips.ethereum.org/EIPS/eip-6780) semantics. If the contract was created in the same transaction, `SELFDESTRUCT` removes code and storage and transfers the balance. Otherwise it transfers the balance only and preserves code and storage. This behavior became part of MegaETH in [Rex2](/spec/network-upgrades/rex2). For the full stable semantics and earlier MiniRex disablement, see [SELFDESTRUCT](/spec/megaevm/selfdestruct).

### Contract Limits

| Limit             | Value                          |
| ----------------- | ------------------------------ |
| Max contract size | 524,288 bytes (512 KB)         |
| Max initcode size | 548,864 bytes (512 KB + 24 KB) |

These enlarged limits were introduced in [MiniRex](/spec/network-upgrades/minirex). For the exact limits and rejection rules, see [Contract Limits](/spec/megaevm/contract-limits).

### Precompiles

| Precompile           | Address | Stable MegaETH-Specific Behavior                                 |
| -------------------- | ------- | ---------------------------------------------------------------- |
| KZG Point Evaluation | `0x0A`  | 100,000 gas                                                      |
| ModExp               | `0x05`  | [EIP-7883](https://eips.ethereum.org/EIPS/eip-7883) gas schedule |

These stable overrides are part of the current behavior. For the full precompile specification, including the inherited baseline and MegaETH-specific differences, see [Precompiles](/spec/megaevm/precompiles).

### Built-In Protocol Interfaces

MegaETH predeploys the following stable system contracts:

| Contract                                                                    | Address                                      | Since                                     | Purpose                                                  |
| --------------------------------------------------------------------------- | -------------------------------------------- | ----------------------------------------- | -------------------------------------------------------- |
| [Oracle](/spec/system-contracts/oracle)                                     | `0x6342000000000000000000000000000000000001` | [MiniRex](/spec/network-upgrades/minirex) | Off-chain data key-value storage                         |
| [High-Precision Timestamp](/spec/system-contracts/high-precision-timestamp) | `0x6342000000000000000000000000000000000002` | [MiniRex](/spec/network-upgrades/minirex) | Sub-second timestamp oracle service                      |
| [KeylessDeploy](/spec/system-contracts/keyless-deploy)                      | `0x6342000000000000000000000000000000000003` | [Rex2](/spec/network-upgrades/rex2)       | Deterministic cross-chain deployment                     |
| [MegaAccessControl](/spec/system-contracts/mega-access-control)             | `0x6342000000000000000000000000000000000004` | [Rex4](/spec/network-upgrades/rex4)       | Volatile-data access control                             |
| [MegaLimitControl](/spec/system-contracts/mega-limit-control)               | `0x6342000000000000000000000000000000000005` | [Rex4](/spec/network-upgrades/rex4)       | Query remaining compute-gas budget                       |
| [SequencerRegistry](/spec/system-contracts/sequencer-registry)              | `0x6342000000000000000000000000000000000006` | [Rex5](/spec/network-upgrades/rex5)       | Dual-role registry for system address and sequencer keys |

For the full registry and behavioral semantics, see [System Contracts Overview](/spec/system-contracts/overview).


# Dual Gas Model

MegaETH dual gas model specification — compute gas, storage gas, SALT bucket multiplier, and per-operation storage gas schedule.

MegaETH's dual gas model separates transaction gas costs into two independent dimensions: [compute gas](/spec/reference/glossary#compute-gas) (the gas charged for EVM computation, derived from standard EVM gas semantics) and [storage gas](/spec/reference/glossary#storage-gas) (an additional charge for operations that impose persistent storage burden on nodes). A transaction's total gas is the sum of both.

## Motivation

Standard EVM gas pricing assumes a base fee high enough that storage-heavy operations (state writes, logs, calldata) are adequately priced by compute gas alone. MegaETH breaks this assumption in two ways:

1. **Extremely low base fees** — MegaETH's base fee is 0.001 gwei (10⁶ wei), orders of magnitude lower than Ethereum mainnet. At this fee level, the compute gas cost of an SSTORE (22,100 gas) is negligible relative to the actual cost of persisting the state change.
2. **High transaction gas limits** — MegaETH allows up to 10 billion gas per block. A single transaction could write thousands of storage slots, deploy megabytes of bytecode, or emit massive logs for near-zero cost under standard gas pricing.

Without a separate storage gas dimension, a single transaction could bloat on-chain state or history data to unsustainable levels. The dual gas model addresses this by pricing storage burden independently of computation, ensuring that state-heavy operations pay their true cost to node operators regardless of the base fee level.

## Specification

The named constants referenced in this section are defined later in [Constants](#constants).

### Total Gas

A node MUST compute total gas for every transaction as:

```
total_gas_used = compute_gas_used + storage_gas_used
```

Both compute gas and storage gas MUST be deducted from the transaction's `gas_limit` budget. When that budget is exhausted, the transaction MUST halt with `OutOfGas`; the halt is decided by the EVM gas meter's budget, not by summing the two counters.

Total gas is the sum of the two metered dimensions. It is not the receipt, and a node MUST NOT derive the receipt by summing the two counters.

#### Gas Charged to the Transaction

The two counters are metering state. The gas charged to a transaction is the EVM gas meter's own accounting, maintained alongside them.

A node MUST charge the transaction from the gas meter, and MUST NOT compute the charge from the two counters. No equation relates them: the counters can total more than the transaction is charged, or less, and both happen in ordinary transactions.

They total **less** than the charge when the transaction pays for gas neither counter records:

* Gas an operation consumed before halting partway through, which is deliberately never recorded as compute gas (see [Single-Record Rule](/spec/megaevm/compute-gas#single-record-rule)).
* The difference between the gas limit a caller forwards into a failing precompile and the compute gas recorded for it, which is capped at the remaining compute budget (see [Precompiles](/spec/megaevm/compute-gas#precompiles)).

Gas forwarded to a child frame that a compute-gas exceed discarded, and the envelope a transaction has left when the [KeylessDeploy](/spec/megaevm/compute-gas#keyless-deploy-exceed) dispatch overhead crosses the transaction-level compute limit, are both returned rather than spent, so neither contributes to this gap (see [Exceed Behavior](/spec/megaevm/compute-gas#exceed-behavior)).

They total **more** than the charge when compute gas records gas the transaction never paid. This happens on every value-transferring `CALL` or `CALLCODE`: the inherited EVM hands the callee `CALL_STIPEND` without deducting it from the caller, and the parent's compute gas records it regardless, so the counters run `CALL_STIPEND` ahead of the charge for each such call (see [Forwarded Gas Exclusion](/spec/megaevm/compute-gas#forwarded-gas-exclusion)).

#### Receipt Gas

The `gas_used` field in the transaction receipt MUST be the gas charged to the transaction, less any standard EVM gas refund settled at the end of the transaction, and then raised to the [calldata floor cost](#calldata-floor-cost) if that floor is higher.

Refunds and the calldata floor apply to the charge, not to either counter: a node MUST NOT subtract a refund from tracked compute gas, and MUST NOT raise it to a floor.

### Compute Gas

[Compute gas](/spec/reference/glossary#compute-gas) is based on standard EVM gas semantics inherited from Optimism Isthmus / Ethereum Prague. Unless explicitly overridden elsewhere in this specification, each opcode MUST use the same compute gas cost as in the inherited EVM semantics. The dual gas model itself does not redefine opcode compute gas costs; it adds the storage gas dimension on top of them.

How much of an operation's inherited EVM gas a node records as compute gas — the measurement window, its exclusions, and the recording sites — is specified in [Compute Gas Accounting](/spec/megaevm/compute-gas).

### Gas Metering Order

Each opcode consumes [compute gas](/spec/reference/glossary#compute-gas) and may additionally charge [storage gas](/spec/reference/glossary#storage-gas). Because the compute gas a transaction has consumed is itself a metered resource bounded by the [compute gas limit](/spec/megaevm/resource-limits), the order in which an opcode charges storage gas relative to recording compute gas is consensus-visible: it determines, when an opcode halts partway through, how much compute gas has been recorded and which limit is reached first.

A node MUST meter every storage-affecting opcode — `SSTORE`, `LOG0` through `LOG4`, `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`, `CREATE`, `CREATE2`, and `SELFDESTRUCT` — in the following fixed order:

1. Validate the operands the storage-gas charge itself reads. A validation failure (for example, stack underflow) MUST halt before any gas is charged or recorded. Operands the charge does not read are validated by the opcode body in step 3: `LOG1` through `LOG4` read only the data length here, so a short stack missing their topic operands reaches step 2 first.
2. Charge the opcode's storage gas against the transaction's gas budget. If the budget is insufficient, the node MUST halt with `OutOfGas` before executing the opcode body.
3. Execute the opcode body, including every standard EVM dynamic cost such as memory expansion, account access, and child-frame gas forwarding. `CREATE2` is the exception to the order of steps 2 and 3: its target address is derived from the initcode, so the memory expansion and hash that derive it necessarily precede the charge for that address, and an insufficient budget surfaces after the expansion has already been paid for.
4. Record the opcode's compute gas as a single amount, measured over a window spanning steps 2 and 3 — or over the equivalent window that opens after step 2 with `storage_gas_charged` treated as zero (see [Storage Gas Exclusion](/spec/megaevm/compute-gas#storage-gas-exclusion)). The recorded amount and its exclusions are defined in [Compute Gas Accounting](/spec/megaevm/compute-gas#measurement-window). The node MUST then enforce the compute gas limit, halting if it is exceeded.
5. Surface the opcode's other resource-limit dimensions (data size, key-value updates, state growth). This step fixes when an exceed on those dimensions is acted on, not when their usage is recorded. An opcode MAY record such usage earlier — before its body runs — provided the resulting exceed is not acted on until this step, so that a body that fails still discards the usage it would have added.

`SELFDESTRUCT` is the exception to the split between steps 4 and 5. It records its beneficiary's data-size, key-value-update, and state-growth usage before its body runs, so it MUST evaluate all four dimensions together once the body completes, rather than deciding compute gas first. When more than one dimension is over its limit on that opcode, the reported dimension follows the fixed priority specified in [Multidimensional Resource Limits](/spec/megaevm/resource-limits#runtime-transaction-level-limits). `SELFDESTRUCT` can record all three non-compute dimensions for a newly materialized beneficiary, so that order decides the reported dimension in both directions — data size or key-value updates outrank compute gas, while compute gas outranks state growth.

A node MUST record an opcode's compute gas in exactly one step, after the opcode body has fully executed — with no `CREATE2` exception. The no-record rule when the body does not run to completion is specified in [Single-Record Rule](/spec/megaevm/compute-gas#single-record-rule).

### Storage Gas

[Storage gas](/spec/reference/glossary#storage-gas) is an additional charge for operations that impose persistent storage burden on nodes. A node MUST charge storage gas according to the following schedule:

| Operation                          | Storage Gas Formula                                       | Charging Trigger                                                                                                       |
| ---------------------------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| **Transaction Intrinsic**          | `INTRINSIC_STORAGE_GAS` (39,000 flat)                     | Charged before execution begins, alongside compute intrinsic gas                                                       |
| **SSTORE (0 → non-0)**             | `SSTORE_STORAGE_GAS_BASE × (multiplier − 1)`              | Charged at the time of the SSTORE opcode when writing a non-zero value to a slot that was zero before this transaction |
| **Account Creation**               | `ACCOUNT_CREATION_STORAGE_GAS_BASE × (multiplier − 1)`    | Charged when a value transfer targets an empty account                                                                 |
| **Contract Creation**              | `CONTRACT_CREATION_STORAGE_GAS_BASE × (multiplier − 1)`   | Charged at CREATE/CREATE2 execution or creation transaction, regardless of whether initcode succeeds or fails          |
| **Code Deposit**                   | `CODE_DEPOSIT_STORAGE_GAS × code_length`                  | Charged per byte when contract creation succeeds and bytecode is stored                                                |
| **LOG Topic**                      | `LOG_TOPIC_STORAGE_GAS × topic_count`                     | Charged at the LOG opcode                                                                                              |
| **LOG Data**                       | `LOG_DATA_STORAGE_GAS × data_length`                      | Charged at the LOG opcode                                                                                              |
| **Calldata (zero byte)**           | `CALLDATA_ZERO_STORAGE_GAS × zero_byte_count`             | Charged before execution begins, alongside intrinsic gas                                                               |
| **Calldata (non-zero byte)**       | `CALLDATA_NONZERO_STORAGE_GAS × nonzero_byte_count`       | Charged before execution begins, alongside intrinsic gas                                                               |
| **Calldata floor (zero byte)**     | `CALLDATA_FLOOR_ZERO_STORAGE_GAS × zero_byte_count`       | Post-execution floor check (see below)                                                                                 |
| **Calldata floor (non-zero byte)** | `CALLDATA_FLOOR_NONZERO_STORAGE_GAS × nonzero_byte_count` | Post-execution floor check (see below)                                                                                 |

Contract creation MUST charge only `CONTRACT_CREATION_STORAGE_GAS_BASE × (multiplier − 1)`. The account creation storage gas (`ACCOUNT_CREATION_STORAGE_GAS_BASE`) MUST NOT be charged on top of the contract creation cost.

#### Top-Level Contract Creation Address

For a top-level contract-creation transaction, the contract-creation storage gas and its [SALT bucket](/spec/reference/glossary#salt-bucket) multiplier MUST be computed from the address that the transaction will actually create. A node MUST derive that address from the sender account's current state nonce — the same nonce used to create the contract — and MUST NOT derive it from the transaction's nonce field. These two values differ when prior in-block activity or EIP-7702 authorizations have advanced the sender account's nonce ahead of the value carried in the transaction's nonce field.

#### Calldata Floor Cost

Per [EIP-7623](https://eips.ethereum.org/EIPS/eip-7623), after execution completes, if the total gas consumed is less than the calldata floor cost, the transaction MUST be charged the floor cost instead. The floor cost storage gas component uses the `CALLDATA_FLOOR_*_STORAGE_GAS` constants, which are `STORAGE_GAS_MULTIPLIER` (10×) of the standard EVM floor costs defined in EIP-7623.

#### SSTORE Storage Gas Refund

Setting a storage slot back to its original value within the same transaction MUST NOT refund the storage gas that was charged when the slot was first written to a non-zero value. Storage gas for SSTORE is non-refundable: every zero-to-non-zero SSTORE transition accumulates storage gas even if the slot is later reset.

Standard EVM gas refunds for SSTORE (e.g., the `SSTORE_CLEARS_SCHEDULE` refund) apply only to the compute gas component and MUST NOT affect storage gas.

#### Revert Behavior

Storage gas charged within a reverted [call frame](/spec/reference/glossary#call-frame) MUST be consumed and not refunded, consistent with standard EVM gas semantics. The [data size](/spec/megaevm/resource-accounting) tracked for LOG operations within a reverted call frame MUST be rolled back, since the logs themselves are discarded.

### Storage Gas Stipend for Value Transfers

The 10× storage gas on LOG opcodes causes a simple `LOG1` to cost 4,500 gas (750 compute + 3,750 storage), exceeding the EVM's `CALL_STIPEND` of 2,300.

A [**storage gas stipend**](/spec/reference/glossary#storage-gas-stipend) allowance of 23,000 gas is reserved for internal (`depth > 0`) value-transferring `CALL` and `CALLCODE` opcodes. `DELEGATECALL`, `STATICCALL`, top-level transaction calls, and [system contract](/spec/system-contracts/overview) interceptions MUST NOT receive the stipend. The allowance MUST NOT inflate the callee's gas limit: the callee runs with the standard `forwarded_gas + CALL_STIPEND (2,300)`, and the stipend is a separate per-frame budget drawn only at the storage-gas surcharge sites MegaETH adds on top of standard EVM opcode costs (LOG topic/data, new-account materialization, first-time-write SSTORE, contract-creation storage, SELFDESTRUCT beneficiary creation). Because the allowance never enters the callee's gas limit, it MUST NOT be spendable on compute (standard EVM opcode) gas, and any undrawn portion is neither returned to the caller nor rescued for the sender on early termination. See the [gas forwarding](/spec/megaevm/gas-forwarding) page for the full mechanism.

### Dynamic SALT Multiplier

Storage gas costs for SSTORE, account creation, and contract creation scale dynamically based on [SALT bucket](/spec/reference/glossary#salt-bucket) capacity.

A node MUST compute the multiplier for each operation as:

```
multiplier = bucket_capacity / MIN_BUCKET_SIZE
```

Where `bucket_capacity` is the capacity of the SALT bucket that the target account or storage slot maps to in the parent block's state.

The following rules MUST apply:

* When `multiplier = 1` (bucket at minimum size): storage gas for the operation MUST be zero, since `base × (1 − 1) = 0`.
* When `multiplier > 1`: storage gas MUST scale linearly as `base × (multiplier − 1)`.
* The multiplier MUST be determined from the SALT bucket state of the **parent block**, not the current transaction's intermediate state.

A [system-originated transaction](/spec/system-contracts/system-tx#system-originated-transaction-metering-exemption) MUST be charged dynamic storage gas as if every target bucket were at minimum capacity (`multiplier = 1`), regardless of the bucket's actual capacity. Under the `base × (multiplier − 1)` formula this makes the dynamic storage gas zero, so a protocol-mandated storage write costs only its standard EVM gas and cannot run out of gas as SALT buckets grow. User transactions are unaffected and continue to pay capacity-scaled storage gas.

#### Bucket ID Calculation

For storage gas calculation, a node MUST determine the SALT bucket from the target key, regardless of whether the account or storage slot already exists.

The bucket ID formula is:

```
bucket_id(key) = (ahash(key) mod NUM_KV_BUCKETS) + NUM_META_BUCKETS
```

Where `ahash` is the fixed-seed deterministic hash function defined by SALT. The canonical bucket-mapping implementation is in the [SALT repository](https://github.com/megaeth-labs/salt/blob/main/salt/src/state/hasher.rs).

* For account creation, the bucket ID MUST be computed from the target account address.
* For an `SSTORE`-triggered new storage write, the bucket ID MUST be computed from the concatenation of the contract address and storage slot key.

Equivalently:

```
account_bucket_id = bucket_id(address_bytes)
slot_bucket_id = bucket_id(address_bytes || slot_key_bytes)
```

The multiplier MUST be computed from the capacity of that bucket in the parent-block state, before the new account or storage slot is created.

#### Bucket Capacity Determination

Bucket capacity is determined by SALT bucket metadata. Each data bucket has a minimum capacity of `MIN_BUCKET_SIZE` (256 slots).

SALT determines capacity using the following rule:

1. A bucket starts at `MIN_BUCKET_SIZE`.
2. Let `used` be the number of occupied slots in the bucket.
3. If `used > capacity × 80%`, the bucket MUST expand.
4. Expansion doubles the bucket capacity.
5. Expansion repeats until `used / capacity ≤ 80%`.

Equivalently:

```
new_capacity = capacity
while used * 100 > new_capacity * 80:
    new_capacity = new_capacity * 2
```

The resulting capacity is a power-of-two multiple of `MIN_BUCKET_SIZE` under normal operation. The maximum bucket capacity is `2^40` slots.

Buckets larger than `MIN_BUCKET_SIZE` are represented as multiple 256-slot segments under a local SALT bucket subtree. As capacity grows, the bucket subtree root moves upward to cover the larger slot range.

For storage gas calculation, a node MUST use the capacity recorded for the target bucket in the parent-block state. It MUST NOT derive capacity from the transaction's intermediate writes.

The canonical design references are:

* [SALT README — Dynamic Bucket Sizing and Bucket Management](https://github.com/megaeth-labs/salt/blob/main/salt/README.md)
* [`salt/src/constant.rs`](https://github.com/megaeth-labs/salt/blob/main/salt/src/constant.rs) for `MIN_BUCKET_SIZE`, resize threshold, and resize multiplier

### Transaction Intrinsic Costs

All transactions MUST pay both compute gas and storage gas as intrinsic costs before execution begins:

| Component   | Cost                             |
| ----------- | -------------------------------- |
| Compute gas | `INTRINSIC_COMPUTE_GAS` (21,000) |
| Storage gas | `INTRINSIC_STORAGE_GAS` (39,000) |
| **Total**   | **60,000**                       |

These costs are in addition to standard calldata gas (both compute and storage components). A transaction with `gas_limit < 60,000 + calldata_gas` MUST be rejected as invalid.

## Constants

| Constant                                                      | Value      | Description                                                           |
| ------------------------------------------------------------- | ---------- | --------------------------------------------------------------------- |
| `INTRINSIC_COMPUTE_GAS`                                       | 21,000     | Standard EVM intrinsic gas for all transactions                       |
| `CALL_STIPEND`                                                | 2,300      | Standard EVM value-transfer call stipend, inherited unchanged         |
| `INTRINSIC_STORAGE_GAS`                                       | 39,000     | Storage gas intrinsic for all transactions                            |
| `SSTORE_STORAGE_GAS_BASE`                                     | 20,000     | Base storage gas for SSTORE (0 → non-0)                               |
| `ACCOUNT_CREATION_STORAGE_GAS_BASE`                           | 25,000     | Base storage gas for account creation                                 |
| `CONTRACT_CREATION_STORAGE_GAS_BASE`                          | 32,000     | Base storage gas for contract creation                                |
| `CODE_DEPOSIT_STORAGE_GAS`                                    | 10,000     | Storage gas per byte of deployed bytecode                             |
| `LOG_TOPIC_STORAGE_GAS`                                       | 3,750      | Storage gas per LOG topic                                             |
| `LOG_DATA_STORAGE_GAS`                                        | 80         | Storage gas per byte of LOG data                                      |
| `CALLDATA_ZERO_STORAGE_GAS`                                   | 40         | Storage gas per zero byte of calldata                                 |
| `CALLDATA_NONZERO_STORAGE_GAS`                                | 160        | Storage gas per non-zero byte of calldata                             |
| `CALLDATA_FLOOR_ZERO_STORAGE_GAS`                             | 100        | Storage gas floor per zero byte of calldata                           |
| `CALLDATA_FLOOR_NONZERO_STORAGE_GAS`                          | 400        | Storage gas floor per non-zero byte of calldata                       |
| `STORAGE_GAS_MULTIPLIER`                                      | 10         | Ratio of calldata/LOG storage gas to standard EVM costs               |
| [`MIN_BUCKET_SIZE`](/spec/reference/glossary#min_bucket_size) | 256        | Smallest [SALT bucket](/spec/reference/glossary#salt-bucket) capacity |
| `NUM_META_BUCKETS`                                            | 65,536     | Number of SALT buckets reserved for metadata                          |
| `NUM_KV_BUCKETS`                                              | 16,711,680 | Number of SALT buckets available for key-value state                  |

## Rationale

**Why `base × (multiplier − 1)` instead of `base × multiplier`?** The MiniRex spec originally used `base × multiplier`, which charged storage gas even in uncrowded state regions (multiplier = 1). The Rex spec changed to `base × (multiplier − 1)` so that operations in minimum-sized SALT buckets incur zero storage gas, removing the penalty for writing to fresh state. See the [MiniRex](/spec/network-upgrades/minirex) and [Rex](/spec/network-upgrades/rex) upgrade pages for the historical evolution.

**Why no storage gas refund for SSTORE resets?** Allowing refunds would enable a pattern where contracts repeatedly write and clear the same slot to generate refund credits, undermining the storage gas pricing model. The non-refundable design ensures that every state-expanding operation pays its full cost regardless of subsequent reversals within the same transaction.

**Why 10× multiplier for calldata and LOG?** The `STORAGE_GAS_MULTIPLIER` of 10 was chosen to reflect the long-term storage and data availability costs that calldata and log operations impose on nodes, relative to their standard EVM gas costs which were designed for Ethereum's higher base fee regime.

**Why a flat intrinsic storage gas?** Every transaction imposes a baseline storage cost on nodes regardless of its execution: the transaction itself must be stored, the receipt must be persisted, and account state (nonce, balance) must be updated. The 39,000 flat intrinsic storage gas covers this per-transaction overhead.

## Security Considerations

**If storage gas is omitted or undercharged**, MegaETH's 0.001 gwei base fee makes every SSTORE, contract deployment, and LOG call negligible in cost. A single transaction could write thousands of storage slots or emit megabytes of log data for nearly zero fee — the exact attack the dual gas model exists to prevent.

**If the `STORAGE_CALL_STIPEND` allowance is allowed to enter the callee's gas limit or be returned to the caller**, system-granted gas leaks to the caller, who can redirect it to non-storage operations — defeating the allowance's purpose of covering only MegaETH's storage-gas surcharges.

## Spec History

For the historical evolution of storage gas formulas and constants across specs:

* [MiniRex](/spec/network-upgrades/minirex) — original `base × multiplier` formula with 2,000,000 base cost
* [Rex](/spec/network-upgrades/rex) — revised to `base × (multiplier − 1)` with current base costs, added transaction intrinsic storage gas
* [Rex4](/spec/network-upgrades/rex4) — storage gas stipend for value transfers
* [Rex5](/spec/network-upgrades/rex5) — reworked the storage gas stipend into a separated-allowance model, derived the top-level contract-creation storage-gas address from the sender's current state nonce, and made contract-creation code-deposit compute gas atomic with the deployment commit
* [Rex6](/spec/network-upgrades/rex6) — unified per-opcode gas metering order (compute gas recorded once, after the opcode body, with no `CREATE2` exception); system-originated transactions charge dynamic storage gas at minimum bucket capacity; forwarded gas and the KeylessDeploy envelope are returned on a compute-gas exceed rather than spent


# Compute Gas Accounting

MegaETH compute gas accounting specification — the measurement window that derives compute gas from inherited EVM gas, per-opcode metering classes, non-opcode recording sites, transaction and per-call

[Compute gas](/spec/reference/glossary#compute-gas) is one of the two dimensions of MegaETH's [dual gas model](/spec/megaevm/dual-gas-model), and is independently bounded by a per-transaction limit. This page specifies how a node derives compute gas from inherited EVM gas: where each measurement window opens and closes, what is excluded from it, which sites record compute gas, and what happens when a limit is exceeded.

## Motivation

MegaETH does not define its own opcode gas schedule. Compute gas is a *derived measurement* of the EVM gas inherited from Optimism Isthmus / Ethereum Prague: a node observes how much EVM gas an operation consumed, removes the components that are not computation, and records the remainder.

That derivation is consensus-critical for two reasons.

First, compute gas is itself a metered resource with its own limit. When a transaction halts on that limit, the exact amount recorded determines *which* limit was reached first and *at which opcode* the halt lands. Two implementations that agree on every opcode's EVM gas cost can still disagree on the transaction outcome if they open their measurement windows at different points.

Second, MegaETH charges [storage gas](/spec/reference/glossary#storage-gas) out of the same EVM gas budget as computation, and forwards gas into child frames that perform their own accounting. Without a precise rule for what is removed from the measurement, a node would double-count storage surcharges as computation, or count a child frame's budget twice.

Stating only that "each opcode costs the same compute gas as it does on Ethereum" is insufficient: it fixes the gas *schedule* but leaves the *measurement* undefined. This page defines the measurement.

## Specification

The named constants referenced in this section are defined later in [Constants](#constants).

### Overview

A node MUST track compute gas as a per-transaction resource across the whole of transaction execution. Compute gas usage is the sum of the amounts recorded at every recording site defined on this page.

Compute gas metering begins at [MiniRex](/spec/network-upgrades/minirex). Under the Equivalence spec, a node MUST NOT track compute gas and MUST NOT enforce any compute gas limit; execution is bounded only by the standard EVM gas limit.

Compute gas is not an independent gas schedule. Unless explicitly overridden elsewhere in this specification, the EVM gas cost of every operation is inherited unchanged from Optimism Isthmus / Ethereum Prague. What this page defines is how much of that inherited cost is *recorded* as compute gas. The one departure from inherited pricing that this page itself defines is specified next.

### Inherited-Cost Exception: Preload-Warm Addresses

The inherited EVM treats some addresses as warm from the start of every transaction without loading them: precompile addresses, access-list addresses listed without storage keys, and the block [beneficiary](/spec/reference/glossary#beneficiary). MegaETH departs from the inherited account-access pricing on the first touch of such an address.

When the first access to such an address in a transaction is made by one of the opcodes below, the opcode MUST charge the cold account access cost in place of the warm cost:

| Opcode                       | Charged cold since                                                                                                                                             |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CALL`                       | MiniRex                                                                                                                                                        |
| `DELEGATECALL`, `STATICCALL` | [Rex](/spec/network-upgrades/rex)                                                                                                                              |
| `CALLCODE`                   | Rex through [Rex4](/spec/network-upgrades/rex4); not charged under [Rex5](/spec/network-upgrades/rex5); charged again from [Rex6](/spec/network-upgrades/rex6) |
| `SELFDESTRUCT` (beneficiary) | Rex5                                                                                                                                                           |

The rule covers the inspected address only. A preload-warm *delegate* keeps its inherited warmth for the delegate-access charge: where the pre-execution inspection resolves an EIP-7702 delegation, it reads the delegate's address, not the delegate's account. Under MiniRex through Rex4 the inspection loaded the delegate's account instead, and the delegate address was charged cold on first touch as well.

`CALLCODE`'s two boundaries in the table both follow from which address that inspection materializes. Under Rex5 the inspection targets the executing account, which is already warm, so the inherited pricing is restored. From Rex6 the beneficiary detection for `CALL`-family targets is delegation-aware, and resolving the delegation materializes the call target — without its preloaded warmth — ahead of the inherited load, which reintroduces the cold first-touch charge. The other three call opcodes already materialize their call targets, so their pricing is unaffected by that change.

The rule does not extend beyond that first touch or those opcodes:

* the same address is warm for every subsequent access in the transaction, as inherited;
* a first touch by any other opcode (`BALANCE`, `EXTCODESIZE`, `EXTCODECOPY`, `EXTCODEHASH`) observes the inherited warmth;
* addresses loaded rather than merely preloaded — the transaction sender and recipient, access-list addresses listed with storage keys, and addresses created by `CREATE` / `CREATE2` — are unaffected.

The extra charge is ordinary EVM gas: it is debited from the transaction's gas budget, recorded as compute gas by the opcode's measurement window, and visible in the receipt's `gas_used`.

### Measurement Window

#### Recording Rule

A node MUST record an operation's compute gas as a single amount computed over a measurement window:

```
recorded = (gas_before − gas_after) − storage_gas_charged − forwarded_child_gas
```

Where:

* `gas_before` is the EVM gas remaining at the point the window opens,
* `gas_after` is the EVM gas remaining at the point the window closes,
* `storage_gas_charged` is the storage gas debited from the EVM gas budget inside the window, and
* `forwarded_child_gas` is the gas transferred into a child call frame inside the window.

Each subtraction is saturating: the recorded amount MUST NOT underflow below zero.

#### Window Boundaries

The window MUST cover all of the opcode's compute work: it MUST open before any EVM gas movement that will be recorded as compute gas, and MUST close after the inner opcode body has fully executed.

A storage-gas charge is the one movement that MAY fall on either side of the opening point, because it is excluded from the recorded amount either way — see [Storage Gas Exclusion](#storage-gas-exclusion). A forwarding-cap adjustment applied after the inner body completes changes the remaining gas and the pending child's gas limit by the same amount, so a window closed before that adjustment records the same amount as one closed after it; both placements satisfy this rule.

The window for every storage-affecting opcode — `SSTORE`, `LOG0` through `LOG4`, `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`, `CREATE`, `CREATE2`, and `SELFDESTRUCT` — MUST open before the opcode's storage-gas charge and before any wrapper-side EVM gas work, and MUST close after the inner opcode body completes. An opcode MAY realize this canonical window through the equivalent charge-outside-window form of the [storage gas exclusion](#storage-gas-exclusion), opening after its storage-gas charge with `storage_gas_charged` treated as zero; the recorded amount is identical by construction.

The full canonical metering order is specified in [Dual Gas Model](/spec/megaevm/dual-gas-model#gas-metering-order).

#### Single-Record Rule

A node MUST record an operation's compute gas exactly once per measurement window.

If the window does not close — because operand validation fails, a storage-gas charge exhausts the budget, or the operation halts partway through — the node MUST NOT record compute gas for that operation, even when EVM gas was already consumed by work performed before the halt. The EVM gas consumed by such work remains deducted from the transaction's gas budget.

There is no per-opcode exception: every opcode, `CREATE2` included, records in exactly one window.

#### Storage Gas Exclusion

A node MUST NOT record [storage gas](/spec/reference/glossary#storage-gas) as compute gas. The two dimensions are charged from the same EVM gas budget but accounted separately.

A node MAY implement the exclusion in either of two equivalent forms:

* by subtracting `storage_gas_charged` from a window that spans the storage-gas charge, or
* by opening the window after the storage-gas charge, so that the charge falls outside it.

Both forms MUST produce identical recorded amounts. When the window is placed so that a storage-gas charge falls outside it, `storage_gas_charged` MUST be treated as zero for that window; subtracting it again would under-count compute gas.

#### Forwarded Gas Exclusion

A node MUST NOT record gas forwarded into a child call frame as the parent's compute gas. The child frame records its own compute gas as it executes.

A node MUST compute `forwarded_child_gas` as:

```
if the opcode produced no pending child call:
    forwarded_child_gas = 0
else if spec >= Rex5 and scheme in (CALL, CALLCODE) and child.value != 0:
    forwarded_child_gas = child.gas_limit - CALL_STIPEND
else:
    forwarded_child_gas = child.gas_limit
```

The condition is on what the opcode produced, not on what frame initialization later did with it. A pending child call may still resolve without any child EVM frame executing — as a precompile invocation, a [system contract interception](#system-contract-interception), or a too-deep call result. The parent has already parted with the gas in every one of those cases, so it MUST be excluded from the parent's compute gas all the same; whatever runs in the child's place accounts for its own consumption.

`child.gas_limit` is the gas limit the opcode itself assigns to the pending child frame. It is not the limit the child ultimately runs with: under Rex4 the [storage gas stipend](/spec/reference/glossary#storage-gas-stipend) is granted by inflating that limit after the parent's measurement window has already closed. A node MUST use the pre-inflation value here on every spec; subtracting the inflated one would under-record the parent by the stipend amount.

All three conditions in the `CALL_STIPEND` branch MUST hold together. A `DELEGATECALL` or `STATICCALL` never satisfies it (wrong scheme), a zero-value `CALL` never satisfies it (no stipend is granted), and no spec before Rex5 satisfies it. `CREATE` and `CREATE2` always fall through to the final branch: contract creation carries no stipend.

The `CALL_STIPEND` adjustment exists because the stipend is added to the child's gas limit without being deducted from the parent's remaining gas. Treating it as forwarded would under-count the parent's compute gas by the stipend amount.

`CALLCODE`, `DELEGATECALL`, and `STATICCALL` are subject to the same [98/100 forwarding cap](/spec/megaevm/gas-forwarding) as `CALL`. Under MiniRex only, these three opcodes do not apply the cap, and therefore deduct the child's uncapped gas limit from the parent's recorded compute gas; Rex brought them under the cap.

#### Refund Exclusion

A node MUST NOT subtract EVM gas refunds from compute gas usage. Refunds affect final gas settlement but do not reduce the compute gas recorded during execution.

### Opcode Metering Classes

Every opcode belongs to exactly one metering class. The class determines which exclusions apply to its measurement window and which resource dimensions are checked after it records.

| Class            | Storage gas exclusion | Forwarded gas exclusion | Dimensions checked after recording |
| ---------------- | --------------------- | ----------------------- | ---------------------------------- |
| **Plain**        | Not applicable        | Not applicable          | Compute gas only                   |
| **Volatile**     | Not applicable        | Not applicable          | Compute gas only                   |
| **Storage**      | Applies               | Not applicable          | Compute gas only                   |
| **Call**         | Applies               | Applies                 | Compute gas only                   |
| **Create**       | Applies               | Applies                 | Compute gas only                   |
| **SelfDestruct** | Applies               | Not applicable          | All four dimensions                |
| **Untracked**    | Not applicable        | Not applicable          | None — no compute gas recorded     |

A **Volatile** opcode is a Plain opcode that additionally applies a [gas detention](/spec/megaevm/gas-detention) cap after it executes. Its measurement window is identical to a Plain opcode's.

A **SelfDestruct** opcode checks all four resource dimensions after recording, rather than compute gas alone. This is required because `SELFDESTRUCT` records its data-size, KV-update, and state-growth contributions *before* its inner instruction runs, without latching an exceed; those dimensions must be latched only once the inner instruction has succeeded. Every other opcode records its non-compute dimensions after its inner instruction and latches at the recording site, so a compute-gas-only check suffices. When that check finds more than one dimension over its limit, the reported dimension follows the fixed priority specified in [Multidimensional Resource Limits](/spec/megaevm/resource-limits#runtime-transaction-level-limits).

#### Class Assignment

The current assignment is:

| Class            | Opcodes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Plain**        | `STOP`; `ADD`–`SIGNEXTEND`; `LT`–`SAR`; `KECCAK256`; `ADDRESS`, `ORIGIN`, `CALLER`, `CALLVALUE`, `CALLDATALOAD`, `CALLDATASIZE`, `CALLDATACOPY`, `CODESIZE`, `CODECOPY`, `GASPRICE`, `RETURNDATASIZE`, `RETURNDATACOPY`, `CHAINID`; `POP`, `MLOAD`, `MSTORE`, `MSTORE8`, `JUMP`, `JUMPI`, `PC`, `MSIZE`, `GAS`, `JUMPDEST`, `TLOAD`, `TSTORE`, `MCOPY`; `PUSH0`–`PUSH32`; `DUP1`–`DUP16`; `SWAP1`–`SWAP16`; `RETURN`, `REVERT`, `INVALID`                                                                                                                                                                                                                                                                                                                                         |
| **Volatile**     | <p>Unconditional: <code>BLOCKHASH</code>, <code>COINBASE</code>, <code>TIMESTAMP</code>, <code>NUMBER</code>, <code>DIFFICULTY</code>, <code>GASLIMIT</code>, <code>BASEFEE</code>, <code>BLOBBASEFEE</code>, <code>BLOBHASH</code>.<br>Volatile when the stack target is the <a href="/pages/WBFT0tJW7nAjo1X6ZSnk#beneficiary">beneficiary</a>: <code>BALANCE</code>, <code>EXTCODESIZE</code>, <code>EXTCODECOPY</code>, <code>EXTCODEHASH</code>.<br>Volatile when the executing contract is the beneficiary: <code>SELFBALANCE</code>.<br>Volatile when the executing contract is the <a href="/pages/qTBHlC9xUIWDcAtVMNUc">oracle</a>: <code>SLOAD</code>, subject to the system-address exemption specified in <a href="/pages/2wfcxlmmbQ0Z2PMuG8JU">Gas Detention</a>.</p> |
| **Storage**      | `SSTORE`, `LOG0`–`LOG4`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| **Call**         | `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| **Create**       | `CREATE`, `CREATE2`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| **SelfDestruct** | `SELFDESTRUCT`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| **Untracked**    | Every opcode not available in the inherited EVM, including `CLZ`. `CLZ` requires a base revision later than the one MegaETH inherits, so it always fails before its measurement window closes and records nothing; if the inherited base revision is ever raised, its class MUST be re-declared rather than inherited silently                                                                                                                                                                                                                                                                                                                                                                                                                                                    |

Under Equivalence every opcode is Untracked, because compute gas is not tracked at all.

Class membership is not the only volatility-related property an opcode can carry. `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`, and `SELFDESTRUCT` remain in their own classes but additionally apply a beneficiary volatile-access guard before executing. Their measurement windows follow their class; the guard decides whether the opcode runs, and when the call touches the beneficiary it also applies the detention cap after the opcode executes (see [Gas Detention](/spec/megaevm/gas-detention)).

**How the assignment evolved.** Class assignment is defined by inheritance: each spec inherits the previous spec's assignment and overrides only the opcodes listed. A node implementing replay for historical blocks needs every spec's assignment, so the base and each delta are given below.

**MiniRex** (base assignment):

| Class         | Opcodes                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Plain**     | `STOP`; `ADD`–`SIGNEXTEND`; `LT`–`SAR`; `KECCAK256`; `ADDRESS`, `ORIGIN`, `CALLER`, `CALLVALUE`, `CALLDATALOAD`, `CALLDATASIZE`, `CALLDATACOPY`, `CODESIZE`, `CODECOPY`, `GASPRICE`, `RETURNDATASIZE`, `RETURNDATACOPY`, `CHAINID`, `SELFBALANCE`; `POP`, `MLOAD`, `MSTORE`, `MSTORE8`, `SLOAD`, `JUMP`, `JUMPI`, `PC`, `MSIZE`, `GAS`, `JUMPDEST`, `TLOAD`, `TSTORE`, `MCOPY`; `PUSH0`–`PUSH32`; `DUP1`–`DUP16`; `SWAP1`–`SWAP16`; `RETURN`, `REVERT`, `INVALID` |
| **Volatile**  | `BLOCKHASH`, `COINBASE`, `TIMESTAMP`, `NUMBER`, `DIFFICULTY`, `GASLIMIT`, `BASEFEE`, `BLOBBASEFEE`, `BLOBHASH` (unconditional); `BALANCE`, `EXTCODESIZE`, `EXTCODECOPY`, `EXTCODEHASH` (conditional on the [beneficiary](/spec/reference/glossary#beneficiary))                                                                                                                                                                                                   |
| **Storage**   | `SSTORE`, `LOG0`–`LOG4`                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| **Call**      | `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`                                                                                                                                                                                                                                                                                                                                                                                                                  |
| **Create**    | `CREATE`, `CREATE2`                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| **Untracked** | `SELFDESTRUCT` (disabled — halts with an invalid-opcode result); every opcode undefined in the inherited EVM, including `CLZ`                                                                                                                                                                                                                                                                                                                                     |

Per-spec overrides, applied in order on top of the MiniRex base to reach the current assignment above:

| Spec                                    | Override                                                                                                                                                                                                                                                                       |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Rex**                                 | `CALLCODE`, `DELEGATECALL`, `STATICCALL` become subject to the 98/100 forwarding cap (class unchanged; the forwarded-gas exclusion changes accordingly, and `CALLCODE`'s storage gas exclusion becomes non-vacuous — it gains the empty-account value-transfer storage charge) |
| [**Rex1**](/spec/network-upgrades/rex1) | No change                                                                                                                                                                                                                                                                      |
| [**Rex2**](/spec/network-upgrades/rex2) | `SELFDESTRUCT`: Untracked → SelfDestruct (re-enabled with EIP-6780 semantics)                                                                                                                                                                                                  |
| [**Rex3**](/spec/network-upgrades/rex3) | `SLOAD`: Plain → Volatile (conditional on the [oracle](/spec/system-contracts/oracle) contract)                                                                                                                                                                                |
| **Rex4**                                | `SELFBALANCE`: Plain → Volatile (conditional on the beneficiary). `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`, and `SELFDESTRUCT` gain a beneficiary volatile-access guard that runs before the opcode executes                                                           |
| **Rex5**                                | `SELFDESTRUCT` gains a storage-gas charge for empty-beneficiary creation (class unchanged; the storage gas exclusion becomes applicable)                                                                                                                                       |
| **Rex6**                                | No change                                                                                                                                                                                                                                                                      |

#### Contract Creation Memory Expansion

`CREATE2` expands memory to hash its initcode before the inner opcode runs. The EVM gas consumed by that expansion is compute gas, and a node MUST record it inside the opcode's single measurement window, which opens before the memory expansion and closes after the inner opcode completes. A halt between the two therefore records no compute gas for the opcode, per the [single-record rule](#single-record-rule); the EVM gas consumed by the expansion is still debited from the transaction's budget.

Earlier specs split the expansion into a window of its own, making `CREATE2` the one opcode that recorded twice. Under Rex5 that expansion window records first, before the contract-creation storage gas is charged and ahead of the opcode's main window. Under MiniRex through Rex4 it instead records last — after the inner opcode completes and after the main window records — and is skipped if the inner opcode fails, or if the main window's recording fails the opcode on a compute-gas exceed.

### Non-Opcode Recording Sites

Compute gas is recorded outside opcode execution at the following sites.

Taken together with the per-opcode windows, they close the transaction's compute-gas accounting:

```
compute_gas_used = intrinsic_recorded
                 + sum(recorded(opcode window))
                 + sum(recorded(precompile invocation))
                 + sum(code_deposit_recorded(contract creation))
                 + sum(keyless_deploy_recorded)
```

`sum(recorded(opcode window))` sums the per-opcode windows defined in [Measurement Window](#measurement-window); every other term is one of the subsections below. A node MUST NOT record compute gas at any site not listed here. `sum(recorded(opcode window))` sums over every window closed during execution — including windows in call frames that later reverted, since compute gas is not reverted. The `keyless_deploy_recorded` term is zero before Rex3.

#### Transaction Intrinsic Gas

Before the first call frame begins, a node MUST record the transaction's standard EVM intrinsic gas as compute gas.

This amount MUST be the whole of the intrinsic gas the inherited EVM defines for the transaction, and nothing beyond it. For every transaction that means the base transaction cost, the calldata token cost, the access-list cost, and the EIP-7702 authorization-list cost. A contract-creation transaction additionally carries the inherited creation surcharge and the EIP-3860 per-initcode-word charge, and both are part of this amount. A node MUST NOT include MegaETH's intrinsic storage gas additions in the recorded compute gas, even though they are added to the same intrinsic gas total charged against the transaction's gas limit. Those additions comprise every storage gas component folded into the intrinsic total: the calldata storage gas and the flat transaction intrinsic storage gas defined in [Dual Gas Model](/spec/megaevm/dual-gas-model), and the recipient account-creation or contract-creation storage gas charged when the transaction materializes its target.

This recording is made outside any call frame. It therefore reduces the budget available to the top-level call frame, as specified in [Per-Call-Frame Budget](#per-call-frame-budget).

#### Precompiles

The gas limit a node forwards into a precompile is capped at the remaining compute gas budget, as specified in [Precompile Compute-Gas Bound](/spec/megaevm/resource-limits#precompile-compute-gas-bound). Call that capped value the **effective gas limit**:

```
effective_gas_limit   = min(call_gas_limit, remaining_compute_gas)
remaining_compute_gas = min(current frame's remaining budget,
                            effective_limit − compute_gas_used)
```

A precompile is therefore bounded by whichever of the [per-call-frame budget](#per-call-frame-budget) and the detained [transaction budget](#effective-limit) binds first.

For a transaction whose recipient is a precompile, the invocation runs before any call-frame budget exists. The frame term of `remaining_compute_gas` is then the transaction-level remaining budget itself — the effective limit minus the compute gas already recorded, including the [transaction intrinsic gas](#transaction-intrinsic-gas) — so the cap reduces to `effective_limit − compute_gas_used`.

A node MUST record a precompile invocation's compute gas as:

```
if the precompile returned or reverted:
    recorded = gas_spent
else if target is the KZG point-evaluation precompile
        and effective_gas_limit >= KZG_POINT_EVALUATION_GAS_COST:
    recorded = KZG_POINT_EVALUATION_GAS_COST
else:
    recorded = effective_gas_limit
```

The KZG branch covers that precompile reaching its verification step and returning a non-out-of-gas error. Its condition is expressed structurally — on the effective gas limit rather than on the specific error returned — so that it remains correct if the inherited EVM adds further non-out-of-gas error variants. No other precompile takes that branch. `KZG_POINT_EVALUATION_GAS_COST` is a MegaETH override, not an inherited value; see [Precompiles](/spec/megaevm/precompiles).

Both non-`gas_spent` branches exist because the precompile recorded no cost on those paths, so recording the spent amount — zero — would under-count the work performed.

On a halting precompile the recorded compute gas is deliberately distinct from the EVM gas the parent frame burns: the parent burns the caller-supplied call gas limit, while the compute gas recorded is the effective gas limit. When the compute-gas cap is the binding constraint the two amounts differ, and a node MUST NOT reconcile them.

Earlier specs record less:

| Spec         | Recorded amount              |
| ------------ | ---------------------------- |
| MiniRex–Rex4 | The gas the precompile spent |
| Equivalence  | Not recorded                 |

Under MiniRex through Rex4, no compute-gas cap bounds the forwarded gas, and "the gas the precompile spent" is the amount the precompile itself recorded as consumed. On a failing invocation no cost is recorded, so the compute gas recorded is zero — even though the parent frame still burns the forwarded gas limit. Rex5 introduced the cap and the three-branch recording above.

#### Contract Creation Code Deposit

For any contract creation (`CREATE`, `CREATE2`, or a contract-creation transaction), a node MUST record the code-deposit compute gas — `code_length × CODEDEPOSIT` — exactly once, and only when the deposit's success conditions hold at the recording point.

The deposit does not occur, and a node MUST therefore record nothing, when the returned runtime code exceeds the maximum contract size, when it begins with the `0xEF` byte reserved by EIP-3541, or when the frame's remaining gas cannot cover the code-deposit charge. These conditions apply on every spec; only the point at which the recording happens differs.

| Spec         | Recording point                                                                                                                                                                                    |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Rex5+        | Atomically with the deployment commit: recorded when the deployment's pre-commit success conditions hold, at the same point the EVM charges the code-deposit gas and commits the created contract. |
| MiniRex–Rex4 | During frame-return processing, in the window covering the EVM's code-deposit charge.                                                                                                              |

A node MUST NOT record this amount twice.

The recording itself can latch a compute-gas exceed, and the two recording points then produce different deployment outcomes:

* From Rex5, the recording precedes the commit: the frame fails as specified in [Exceed Behavior](#exceed-behavior) and the deployment commits nothing, but the recorded amount stands — recording precedes exceed evaluation, and compute gas is never reverted.
* Under Rex4, the only earlier spec with a per-frame budget, the recording happens after the EVM has already charged the deposit and committed the created contract. A frame-budget exceed latched by this recording therefore produces a split outcome: the frame's result is the frame-local revert, while the deployed code remains committed. A node MUST NOT roll the deployment back on this path.

The code-deposit *storage* gas is charged before this window opens and therefore falls outside it, consistent with the [storage gas exclusion](#storage-gas-exclusion).

#### Keyless Deploy Sandbox

From Rex3 onward, a node MUST record the [KeylessDeploy](/spec/system-contracts/keyless-deploy) fixed dispatch overhead (`KEYLESS_DEPLOY_OVERHEAD_GAS`) as compute gas when that overhead is charged.

From Rex5 onward, a node MUST additionally merge the compute gas consumed inside the keyless-deploy sandbox into the enclosing transaction's compute gas usage.

#### System Contract Interception

An intercepted [system contract](/spec/system-contracts/interception) call produces a synthetic frame result without executing a child EVM frame.

Where an interceptor performs no metering of its own, a node MUST NOT record compute gas for the interception: the forwarded gas is returned to the caller in full, so the interception consumes nothing beyond the `CALL`-family opcode that initiated it.

An interceptor that records compute gas of its own is the exception, and its charges are specified with that operation rather than here. [KeylessDeploy](#keyless-deploy-sandbox) is the only interceptor that records compute gas: it records a fixed dispatch overhead from Rex3, and merges its sandbox's compute gas from Rex5. A node MUST record those amounts even though the call reaches KeylessDeploy through the same interception framework, and even though such a call is necessarily top-level — KeylessDeploy intercepts only top-level transactions (see [Keyless Deployment](/spec/system-contracts/keyless-deploy)) — and therefore has no initiating opcode.

An interception MUST NOT perturb per-call-frame budgets: the budgets observed by frames that run after it MUST be the same as if a real child frame had been entered and returned without recording compute gas.

### Limits

#### Transaction-Level Limit

A node MUST enforce a per-transaction compute gas limit of `TX_COMPUTE_GAS_LIMIT`.

#### Effective Limit

The effective transaction-level limit is the minimum of `TX_COMPUTE_GAS_LIMIT` and the current detained limit produced by [gas detention](/spec/megaevm/gas-detention):

```
effective_limit = min(TX_COMPUTE_GAS_LIMIT, detained_limit)
```

How `detained_limit` is lowered by volatile-data access, how competing caps combine, and when it resets between transactions are specified in [Gas Detention](/spec/megaevm/gas-detention). This page only defines how the resulting limit is applied.

A node MUST evaluate the transaction-level check with strict greater-than:

```
tx_exceeded = compute_gas_used > effective_limit
```

Usage exactly equal to the effective limit is within limit.

#### Per-Call-Frame Budget

From Rex4 onward, a node MUST additionally enforce a per-call-frame compute gas budget. Before Rex4, compute gas is enforced at the transaction level only, and no per-frame budget exists.

How a frame's budget is derived — the top-level frame's budget net of pre-frame usage, and the `FRAME_LIMIT_NUMERATOR` / `FRAME_LIMIT_DENOMINATOR` share forwarded to each nested frame — is specified for all four resource dimensions in [Per-Call-Frame Runtime Budgets](/spec/megaevm/resource-limits#per-call-frame-runtime-budgets). For compute gas, the pre-frame usage deducted from the top-level budget is the [transaction intrinsic gas](#transaction-intrinsic-gas).

Under Rex4 only, an internal value-transferring `CALL` or `CALLCODE` carries one further constraint. Rex4 grants the [storage gas stipend](/spec/reference/glossary#storage-gas-stipend) by inflating the child's gas limit, so the child's compute gas budget MUST additionally be capped at the pre-inflation gas limit — otherwise the system-granted stipend becomes spendable on computation. The child's budget is therefore the minimum of the forwarded share and that pre-inflation limit. Rex5 replaced the inflation with a separated allowance that never enters the child's gas limit, so no such cap applies from Rex5 onward.

The per-frame check uses the same strict comparison as the transaction-level one, and a node MUST evaluate it before the transaction-level check. A node MUST NOT skip the transaction-level check when the per-frame check is within limit: the intrinsic recording lies outside every frame budget, and the detained limit may be lowered at any point during execution.

{% hint style="info" %}
**Design intent.** The per-frame budget is a termination guardrail, not a budget guarantee. Because compute gas is never reverted (see [Revert Behavior](#revert-behavior)), a child frame that exceeds its budget and reverts still contributes its full recorded usage to the transaction total. The budget bounds how far a single frame may run; it does not protect the transaction's remaining budget from that frame's consumption.
{% endhint %}

### Exceed Behavior

A compute gas exceed is either *frame-local* or *transaction-level*, and the two produce different outcomes.

| Condition                                 | Scope             | Result                                                                                                         | Gas                                                 |
| ----------------------------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| Per-frame budget exceeded                 | Frame-local       | The frame MUST revert with `MegaLimitExceeded(uint8 kind, uint64 limit)`                                       | Returns to the parent frame normally                |
| Transaction limit exceeded                | Transaction-level | The transaction MUST halt with `OutOfGas`                                                                      | Remaining gas is rescued and refunded to the sender |
| Detained limit exceeded                   | Transaction-level | The transaction MUST halt with `VolatileDataAccessOutOfGas` (see [Gas Detention](/spec/megaevm/gas-detention)) | Remaining gas is rescued and refunded to the sender |
| Keyless-deploy dispatch overhead exceeded | See below         | The frame MUST revert, or the transaction MUST halt with `OutOfGas`                                            | As for the matching scope above                     |

A frame-local exceed in a nested frame does not fail the transaction: the parent frame MAY continue execution. The top-level frame also carries a budget, and a frame-local exceed there has no parent to return to — the transaction's own result becomes the revert, and the receipt reports failure.

On a transaction-level exceed, a node MUST preserve the frame's remaining gas for refund to the sender. The rescued amount MUST exclude any portion contributed by the [storage gas stipend](/spec/reference/glossary#storage-gas-stipend), so that system-granted gas is not recovered by the sender. The rule admits no exception: the keyless-deploy dispatch path rescues on the same terms as opcode dispatch.

Rescue is specific to a transaction-level exceed. A frame-local exceed needs none: the frame reverts and its unspent gas returns to the parent through ordinary frame accounting.

When a `CALL`-family or `CREATE` / `CREATE2` opcode fails on a compute-gas exceed — the frame-local revert and the transaction-level halt alike — its pending child frame is discarded before the child runs. A node MUST return the gas already forwarded to that discarded child to the frame before it terminates, so that gas is not charged as consumed: on a frame-local revert it returns to the parent frame, and on a transaction-level halt it is excluded from the transaction's `gas_used`.

A node MUST NOT halt a [system-originated transaction](/spec/system-contracts/system-tx#system-originated-transaction-metering-exemption) on the compute gas limit or on gas detention. The node MUST still record its compute gas usage; only the halt decision is suppressed. The transaction's standard EVM `gas_limit` remains the only bound that can halt it.

A node MUST record compute gas before evaluating any exceed, including an exceed already latched on another resource dimension. The compute work was performed, and the recorded total feeds the transaction outcome and the block-level compute accounting even for a transaction halted on a different dimension.

#### Keyless Deploy Exceed

When recording the [KeylessDeploy](/spec/system-contracts/keyless-deploy) dispatch overhead exceeds a compute gas limit, the outcome follows the frame-local / transaction-level split above, but the two branches are not observably the same:

* A frame-local exceed MUST revert with an ABI-encoded `InsufficientComputeGas` error carrying the limit and the usage.
* A transaction-level exceed MUST halt with `OutOfGas` and empty output. A node MUST NOT attach `InsufficientComputeGas` to this branch; the caller cannot distinguish it from any other out-of-gas halt.

Each branch handles gas as its scope does above: the frame-local revert returns unspent gas to the parent through ordinary frame accounting, and the transaction-level halt rescues the outer transaction's remaining gas for the sender. Specs through Rex5 do not rescue on this path: on those specs a transaction-level exceed here records a full spend and the sender loses the entire unused envelope. See [Keyless Deployment](/spec/system-contracts/keyless-deploy) for the full dispatch semantics.

### Revert Behavior

Compute gas MUST accumulate globally and MUST NOT be reverted. Usage recorded within a call frame contributes to the transaction total whether that frame succeeds or reverts.

This makes compute gas the sole exception among the four runtime resource dimensions; the other three are call-frame-aware and discard a reverted frame's usage. See [Resource Accounting](/spec/megaevm/resource-accounting#revert-behavior).

## Constants

| Constant                        | Value         | Spec           | Description                                                                                                                 |
| ------------------------------- | ------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `TX_COMPUTE_GAS_LIMIT`          | 200,000,000   | Rex onward     | Maximum compute gas per transaction from Rex onward                                                                         |
| `TX_COMPUTE_GAS_LIMIT`          | 1,000,000,000 | MiniRex        | Maximum compute gas per transaction under MiniRex                                                                           |
| `FRAME_LIMIT_NUMERATOR`         | 98            | Rex4 onward    | Numerator of the per-call-frame budget forwarding fraction                                                                  |
| `FRAME_LIMIT_DENOMINATOR`       | 100           | Rex4 onward    | Denominator of the per-call-frame budget forwarding fraction                                                                |
| `CALL_STIPEND`                  | 2,300         | All            | Standard EVM value-transfer call stipend, inherited unchanged                                                               |
| `CODEDEPOSIT`                   | 200           | All            | Standard EVM per-byte code-deposit gas, inherited unchanged                                                                 |
| `KEYLESS_DEPLOY_OVERHEAD_GAS`   | 100,000       | Rex2 onward    | Fixed dispatch overhead for a keyless deploy                                                                                |
| `KZG_POINT_EVALUATION_GAS_COST` | 100,000       | MiniRex onward | MegaETH's fixed-cost override for the KZG point-evaluation precompile (defined in [Precompiles](/spec/megaevm/precompiles)) |

The gas detention caps that lower the effective compute gas limit are defined in [Gas Detention](/spec/megaevm/gas-detention).

## Rationale

**Why define a measurement window instead of a per-opcode gas table?**

MegaETH inherits its opcode gas schedule unchanged from Optimism Isthmus / Ethereum Prague. Restating 256 absolute gas costs would duplicate the inherited specification, would need re-verification on every upstream EVM revision, and would still leave the consensus-critical question unanswered — namely, how much of an opcode's inherited cost counts as compute gas and when it is recorded. The measurement window is the part MegaETH actually defines, so it is the part this page specifies.

**Why is the window's opening point normative rather than an implementation detail?**

Compute gas is bounded by a limit, so the amount recorded at the moment of a halt is consensus-visible. Moving the opening point changes how much has been recorded when an opcode halts partway through, which changes which limit is reached first and at which opcode the transaction fails. Two nodes with identical gas schedules but different window placement will disagree on transaction outcomes.

**Why are two forms of storage gas exclusion permitted?**

Subtracting the charge from a spanning window and placing the window after the charge produce identical results. Permitting both lets an implementation choose whichever is cheaper at a given site without a spec change, and makes explicit that they must not be combined — a window placed after the charge must treat `storage_gas_charged` as zero.

**Why does the Rex5+ forwarded-gas exclusion subtract the `CALL_STIPEND`?**

For a value-transferring `CALL` or `CALLCODE`, the inherited EVM adds `CALL_STIPEND` to the child's gas limit without deducting it from the parent's remaining gas. Treating the child's full gas limit as forwarded would therefore subtract gas the parent never contributed, under-counting the parent's compute gas by the stipend.

**Why is the first `CALL`-family touch of a preload-warm address charged cold?**

MegaETH's storage-gas pricing inspects the callee account before the opcode's own access, and that inspection materializes the account without inheriting its preloaded warmth, so the opcode's subsequent access observes a cold account. The pricing has been charged gas on every spec since MiniRex and is therefore frozen; later specs changed which opcodes perform the inspection, which is why the affected opcode set varies by spec while the pricing of a performed inspection never changed.

**Why does MiniRex exclude three call opcodes from the forwarding cap?**

The MiniRex instruction table omitted the forwarding wrapper for `CALLCODE`, `DELEGATECALL`, and `STATICCALL`. Rex corrected the omission. MiniRex behavior remains frozen for replay compatibility.

**Why does this page carry per-spec behavior in the main specification?**

Concept pages normally describe only the latest stable spec and leave earlier behavior to the Spec History and upgrade pages. This page departs from that. Compute gas is not a fixed rule that happened to change; it is a measurement whose definition differs at MiniRex, Rex, Rex3, Rex4, Rex5, and Rex6, and a node replaying historical blocks must implement every one of those definitions simultaneously. Splitting them across pages would force an implementer to reassemble the measurement from a changelog before they could execute a single historical block. The current assignment is therefore stated first and directly, with the earlier definitions kept alongside it rather than relocated.

**Why is compute gas the only non-revertible dimension?**

CPU cycles cannot be undone. If compute gas were scoped to call frames like the other dimensions, an attacker could execute and revert expensive subcalls repeatedly within a single transaction, consuming negligible apparent compute gas while imposing real execution cost on nodes.

**Why is the per-frame budget a guardrail rather than a guarantee?**

Making per-frame budgets protective would require reverting a failed child's compute gas, which reintroduces the attack above. Keeping compute gas persistent while still bounding each frame gives early termination of runaway frames without creating a revert-based escape from transaction-level accounting.

**Why does intrinsic compute gas exclude MegaETH's intrinsic storage gas?**

Both are added to the same intrinsic total charged against the transaction's gas limit, but the storage components price persistent storage burden, not computation. Recording them as compute gas would consume the compute budget for work that performs no computation, and would make the compute limit sensitive to calldata length.

## Security Considerations

**If the measurement window is opened after work that consumes EVM gas**

That gas escapes compute-gas accounting entirely. An attacker could then construct a transaction whose real execution cost far exceeds its recorded compute gas, defeating the compute gas limit as a bound on node CPU time.

**If storage gas is recorded as compute gas**

Storage-heavy transactions exhaust the compute limit prematurely and halt while still holding gas, and the compute limit stops measuring computation.

**If forwarded child gas is not excluded**

It is counted twice — once by the parent's window and again by the child's own recording — so deep call chains exhaust the compute limit at a fraction of their true computational cost.

**If a recording is skipped when another dimension has already latched an exceed**

Block-level compute accounting under-reports the work the node actually performed, and a transaction can impose uncounted CPU cost by first tripping a cheaper dimension.

**If rescued gas includes the storage gas stipend**

System-granted gas leaks to the sender, who recovers gas that was never theirs to spend.

## Spec History

* [MiniRex](/spec/network-upgrades/minirex) — introduced compute gas metering, the per-opcode measurement window, and `TX_COMPUTE_GAS_LIMIT` at 1,000,000,000. `CALLCODE`, `DELEGATECALL`, and `STATICCALL` are not subject to the 98/100 forwarding cap. The first `CALL` touch of a preload-warm address is charged cold.
* [Rex](/spec/network-upgrades/rex) — brought `CALLCODE`, `DELEGATECALL`, and `STATICCALL` under the forwarding cap, changing their forwarded-gas exclusion; extended the cold first-touch charge to those three opcodes; lowered `TX_COMPUTE_GAS_LIMIT` to 200,000,000.
* [Rex1](/spec/network-upgrades/rex1) — reset the detained compute gas limit between transactions in the same block.
* [Rex2](/spec/network-upgrades/rex2) — re-enabled `SELFDESTRUCT`, adding the SelfDestruct metering class; introduced the keyless-deploy dispatch overhead.
* [Rex3](/spec/network-upgrades/rex3) — moved `SLOAD` into the Volatile class for oracle access; began recording the keyless-deploy dispatch overhead as compute gas.
* [Rex4](/spec/network-upgrades/rex4) — introduced the per-call-frame compute gas budget; made gas detention caps relative to usage at the access point; added beneficiary volatile-access guards to the `CALL` family, `SELFDESTRUCT`, and `SELFBALANCE`.
* [Rex5](/spec/network-upgrades/rex5) — excluded the `CALL_STIPEND` from the forwarded-gas deduction; moved `CREATE2` memory-expansion recording ahead of the storage-gas charge; made contract-creation code-deposit compute gas atomic with the deployment commit; refined precompile compute-gas recording and bounded it by the remaining compute budget; added the `SELFDESTRUCT` empty-beneficiary storage-gas charge; removed `CALLCODE` from the cold first-touch charge and added `SELFDESTRUCT`'s beneficiary to it; stopped following EIP-7702 delegation in the pre-execution inspection, restoring inherited warmth for delegates.
* [Rex6](/spec/network-upgrades/rex6) — unified the measurement window across all storage-affecting opcodes and folded `CREATE2` memory expansion into it, ending the two-window exception; returned forwarded gas to the failing frame on a compute-gas exceed; rescued the unused envelope on a keyless-deploy dispatch exceed; made beneficiary detection delegation-aware, returning `CALLCODE` call targets to the cold first-touch charge; exempted system-originated transactions from the compute gas limit and gas detention.


# Resource Limits

MegaETH per-transaction and per-block resource limits — compute gas, data size, KV updates, and state growth ceilings with enforcement semantics.

This page specifies the limits MegaETH enforces on transaction execution and block construction. It defines the limit set, the split between pre-execution and runtime enforcement, and the outcomes of transaction-level and block-level violations.

## Motivation

The transaction `gas_limit` alone is insufficient to protect MegaETH from resource-heavy transactions. A transaction may remain within its total gas budget while still producing excessive state growth, too many key-value updates, or too much execution data.

MegaETH therefore enforces independent resource ceilings in addition to the standard gas limit. Without those ceilings, a transaction could remain valid under gas accounting while still imposing disproportionate execution, storage, or networking costs on nodes.

Resource limits also need deterministic block-building semantics. Implementations must agree on which transactions are rejected permanently, which are skipped for the current block, which are included as failed, and when the last transaction that exceeds a block-level runtime limit is still allowed.

## Specification

The named constants referenced in this section are defined later in [Constants](#constants).

### Overview

MegaETH enforces seven distinct resource limits:

1. standard gas limit,
2. transaction encoded size,
3. data-availability size,
4. [compute gas](/spec/reference/glossary#compute-gas),
5. data size,
6. KV updates,
7. state growth.

Limits 1–3 are checked before execution. Limits 4–7 are enforced during execution and accumulated at block level after execution.

For exact counting rules of data size, KV updates, and state growth, see [Resource Accounting](/spec/megaevm/resource-accounting). For compute gas — the measurement window, metering classes, recording sites, and exceed behavior — see [Compute Gas Accounting](/spec/megaevm/compute-gas). For the relationship between total gas, compute gas, and storage gas, see [Dual Gas Model](/spec/megaevm/dual-gas-model).

### Limit Set

A node MUST enforce the following limits:

| Resource                                                                                | Phase         | Transaction Limit       | Block Limit                        |
| --------------------------------------------------------------------------------------- | ------------- | ----------------------- | ---------------------------------- |
| [Gas Limit](https://ethereum.org/en/developers/docs/gas/#block-size)                    | Pre-execution | Sequencer-configured    | `block.gasLimit` from block header |
| Transaction Size                                                                        | Pre-execution | Sequencer-configured    | Sequencer-configured               |
| [DA Size](https://docs.optimism.io/stack/transactions/transaction-fees#the-l1-data-fee) | Pre-execution | Sequencer-configured    | Sequencer-configured               |
| [Compute Gas](/spec/reference/glossary#compute-gas)                                     | Runtime       | `TX_COMPUTE_GAS_LIMIT`  | No separate limit                  |
| Data Size                                                                               | Runtime       | `TX_DATA_LIMIT`         | `BLOCK_DATA_LIMIT`                 |
| KV Updates                                                                              | Runtime       | `TX_KV_UPDATE_LIMIT`    | `BLOCK_KV_UPDATE_LIMIT`            |
| State Growth                                                                            | Runtime       | `TX_STATE_GROWTH_LIMIT` | `BLOCK_STATE_GROWTH_LIMIT`         |

The absence of a separate block-level compute gas limit means that cumulative block compute gas is bounded only indirectly by the block gas limit.

### Pre-Execution Limits

#### Standard Gas Limit

A node MUST apply standard Ethereum gas-limit semantics. The transaction's `gas_limit` field MUST fit within both the sequencer-configured per-transaction gas cap and the remaining block gas budget from the block header.

#### Transaction Size

A node MUST check the EIP-2718 encoded transaction size before execution. Transactions that exceed the configured transaction-size limit MUST be rejected permanently. Transactions that fit the transaction-level size limit but would cause the block's cumulative encoded transaction size to exceed the configured block-level size limit MUST be skipped for the current block.

#### DA Size

A node MUST check the compressed data-availability size of each non-deposit transaction before execution. Transactions that exceed the configured transaction-level DA size limit MUST be rejected permanently. Transactions that fit the transaction-level DA size limit but would cause the block's cumulative DA size to exceed the configured block-level DA size limit MUST be skipped for the current block.

Deposit transactions MUST be exempt from DA size limit checks. Their DA size MAY still be tracked for monitoring purposes.

### Runtime Transaction-Level Limits

A node MUST enforce the following runtime transaction-level limits during execution:

* `TX_COMPUTE_GAS_LIMIT`
* `TX_DATA_LIMIT`
* `TX_KV_UPDATE_LIMIT`
* `TX_STATE_GROWTH_LIMIT`

If any runtime transaction-level limit is exceeded during execution, the transaction MUST:

1. halt,
2. preserve its remaining gas,
3. produce a failed receipt (`status = 0`),
4. and still be included in the block.

The failed transaction's actual resource usage MUST still count toward the block's cumulative resource counters.

When a single limit check finds more than one dimension over its limit, the reported dimension MUST be the first in the fixed order: data size, key-value updates, compute gas, state growth.

Step 2 applies to every transaction-level exceed, including the one crossed while recording the [KeylessDeploy](/spec/system-contracts/keyless-deploy) dispatch overhead. The rescued amount is excluded from the receipt's `gas_used` and refunded to the sender. See [Keyless Deploy Exceed](/spec/megaevm/compute-gas#keyless-deploy-exceed).

The four runtime transaction-level limits MUST NOT be enforced against a [system-originated transaction](/spec/system-contracts/system-tx#system-originated-transaction-metering-exemption). The node MUST still record such a transaction's resource usage; only the per-transaction halt decision is suppressed. The transaction's standard EVM `gas_limit` — for the pre-block system calls, floored at 30,000,000 — remains the only bound that can halt it.

#### Precompile Compute-Gas Bound

A precompile invocation's compute-gas consumption MUST be bounded by the compute gas remaining in the current call frame. A node MUST cap the gas forwarded into a precompile at the minimum of the caller-supplied call gas limit and the remaining compute-gas budget, so a precompile cannot consume more compute gas than remains. A precompile whose minimum cost exceeds that cap MUST fail without performing its computation, halting with `PrecompileOOG`. On successful or reverting precompile returns, the caller's gas-refund accounting MUST reflect the originally forwarded gas limit minus the precompile's actual spent gas, so the cap does not alter the caller's observed refund on non-halting returns.

### Runtime Block-Level Limits

A node MUST maintain cumulative block counters for:

* data size,
* KV updates,
* state growth,
* and compute gas.

The node MUST update those cumulative counters after transaction execution.

For data size, KV updates, and state growth, the first transaction that causes the cumulative block usage to meet or exceed the block-level limit MUST still be included in the block. Subsequent candidate transactions MUST be skipped before execution once the block is already at or above the corresponding block-level runtime limit.

Although block compute gas usage MAY be tracked, the protocol does not impose a separate block-level compute gas cap.

### Two-Phase Block Building Workflow

When constructing a block, a node or sequencer MUST process candidate transactions in the following order:

1. Perform pre-execution validation.
2. If a transaction violates a transaction-level pre-execution limit, reject it permanently.
3. If a transaction would exceed a block-level pre-execution limit, skip it for the current block.
4. If any stable block-level runtime limit is already reached or exceeded from prior included transactions, skip later candidate transactions that depend on that resource category.
5. Execute the transaction.
6. If a runtime transaction-level limit is exceeded, include the transaction as failed.
7. Update cumulative block counters with the transaction's actual resource usage.
8. Include the transaction in the block.

### Outcomes

| Outcome  | Cause                                                                            | Receipt      | Block Impact                                                 |
| -------- | -------------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------ |
| Success  | Transaction completes within all applicable limits                               | `status = 1` | Counts toward all relevant block counters                    |
| Failed   | Runtime transaction-level limit exceeded                                         | `status = 0` | Still included and counts toward all relevant block counters |
| Skipped  | Current block cannot admit the transaction without violating a block-level limit | No receipt   | Not included; may be reconsidered in a later block           |
| Rejected | Transaction-level pre-execution limit exceeded                                   | No receipt   | Permanently invalid                                          |

### Per-Call-Frame Runtime Budgets

Each [call frame](/spec/reference/glossary#call-frame) receives a bounded share of the remaining budget for compute gas, data size, KV updates, and state growth. Each inner call frame receives `remaining × FRAME_LIMIT_NUMERATOR / FRAME_LIMIT_DENOMINATOR` of its parent call frame's remaining budget. These budgets are system-enforced — the calling contract cannot directly control them. Only total gas (the standard EVM gas parameter in CALL-like opcodes) remains under direct contract control. If a child call frame exceeds its local budget, it MUST revert with `MegaLimitExceeded(uint8 kind, uint64 limit)`. The parent call frame MAY continue execution.

The top-level call frame's budget MUST equal the transaction limit minus any resource usage already recorded before the first frame begins. These deductions include transaction-only intrinsic usage and any DB-dependent pre-execution usage that is resolved before the first frame starts. Each resource dimension deducts only the pre-frame items relevant to it:

* **Data size** — base transaction data (110 bytes), calldata byte length, access-list entry sizes, EIP-7702 authorization records, applied EIP-7702 authority account updates, and the caller account update.
* **KV updates** — applied EIP-7702 authority account updates and the caller account update.
* **State growth** — applied EIP-7702 authorizations that create previously non-existent authority accounts.
* **Compute gas** — standard EVM transaction intrinsic gas, enumerated normatively in [Transaction Intrinsic Gas](/spec/megaevm/compute-gas#transaction-intrinsic-gas).

These deductions ensure that pre-frame costs reduce the budget available to the first call frame, preventing transactions from front-loading pre-frame usage to escape per-frame limits.

#### Authority State Growth Resolution

A node MUST resolve the state-growth contribution of EIP-7702 authorizations during transaction validation, after the inherited intrinsic-gas validation and before the final gas-limit and fee-affordability checks — the ones that see the dynamic SALT account-creation gas this scan folds in. A transaction whose standard intrinsic gas already exceeds its own gas limit is therefore rejected by the inherited validation without the authority accounts being read at all. The set of authorities and the per-authority effects are derived from the same applied-authorization scan that drives the data-size and KV-update narrowing in [Resource Accounting](/spec/megaevm/resource-accounting).

#### Dynamic Authority Account-Creation Gas

For each *applied* EIP-7702 authorization that materializes a previously non-existent authority account, a node MUST charge dynamic new-account storage gas for that authority using the same SALT bucket pricing as other new-account materialization paths. This charge MUST be folded into the transaction's intrinsic gas so that it is deducted before the first call frame and enforced against the gas limit and fee affordability. A node MUST NOT charge this new-account gas twice when a value-transferring call materializes the same account that an applied authorization materializes.

#### Authorization List Skip on Pre-Frame Limit Exceed

A type-4 transaction's authorization list is applied — each applied authority's account written — during pre-execution, before the transaction's first call frame begins. A per-transaction limit that pre-frame accounting has already exceeded still halts the transaction at the first frame boundary, but a frame-boundary halt does not roll back writes performed before that frame began. Without a guard, a transaction halting on the state-growth limit could commit more net-new authority accounts than the per-transaction state-growth cap allows.

For a type-4 transaction, if any per-transaction resource limit has already been exceeded at the point where the authorization list would be applied, a node MUST NOT apply any authorization in the list. The skip is all-or-nothing: once any per-transaction limit is exceeded — whether by the authorizations themselves or by the transaction's other pre-frame usage, such as calldata — no authorization in the list is applied, including ones that would fit under the limit. The transaction MUST still halt at the same frame boundary with the same limit-exceeded halt reason it would have reached without the skip. Because no authorization is applied, an already-existing authority forgoes the per-authorization refund it would otherwise earn.

## Constants

| Constant                   | Value       | Description                                     |
| -------------------------- | ----------- | ----------------------------------------------- |
| `TX_COMPUTE_GAS_LIMIT`     | 200,000,000 | Maximum compute gas per transaction             |
| `TX_DATA_LIMIT`            | 13,107,200  | Maximum data size per transaction               |
| `BLOCK_DATA_LIMIT`         | 13,107,200  | Maximum cumulative block data size              |
| `TX_KV_UPDATE_LIMIT`       | 500,000     | Maximum KV updates per transaction              |
| `BLOCK_KV_UPDATE_LIMIT`    | 500,000     | Maximum cumulative block KV updates             |
| `TX_STATE_GROWTH_LIMIT`    | 1,000       | Maximum state growth per transaction            |
| `BLOCK_STATE_GROWTH_LIMIT` | 1,000       | Maximum cumulative block state growth           |
| `FRAME_LIMIT_NUMERATOR`    | 98          | Numerator of per-call-frame budget forwarding   |
| `FRAME_LIMIT_DENOMINATOR`  | 100         | Denominator of per-call-frame budget forwarding |

## Rationale

**Why split limits into pre-execution and runtime phases?** Gas limit, encoded transaction size, and DA size are known before execution and can be checked cheaply. Compute gas, data size, KV updates, and state growth depend on actual execution and therefore cannot be known precisely in advance.

**Why include failed runtime-limited transactions?** The node must execute a transaction to know whether it exceeds a runtime limit. If such transactions were excluded from the block, an attacker could force repeated expensive executions at no cost. Including failed transactions ensures that the sender pays for the resources consumed.

**Why allow the first transaction to push a block over a runtime block limit?** Runtime block limits are known only after execution. Allowing the first over-limit transaction to be included maximizes block utilization while preserving deterministic block-building behavior for later transactions.

**Why no separate stable block-level compute gas limit?** Cumulative block compute gas is already indirectly constrained by the block gas limit. The stable protocol therefore does not need a second independent block-level compute gas ceiling.

**Why cap precompile gas at the remaining compute-gas budget?** A precompile whose natural cost exceeds the remaining compute-gas budget would otherwise execute fully and overshoot the budget, with the overshoot detected only after the work was already performed. Capping the forwarded gas at the remaining compute-gas budget converts that overshoot into a fail-fast `PrecompileOOG` before the computation runs, keeping the compute-gas limit enforceable for precompile work as well as ordinary opcodes.

## Security Considerations

**If a transaction that exceeds a runtime limit is excluded from the block rather than included as failed**, an attacker can force the sequencer to execute expensive but failing transactions at no cost — the sender never pays because the transaction is dropped. Including failed transactions ensures the sender always pays for consumed resources.

## Spec History

* [MiniRex](/spec/network-upgrades/minirex) introduced compute gas, data size, and KV update limits, with transaction-level data and KV limits set to 25% of the corresponding block limits.
* [Rex](/spec/network-upgrades/rex) changed the stable runtime transaction-level limits to `TX_COMPUTE_GAS_LIMIT = 200,000,000`, `TX_DATA_LIMIT = 13,107,200`, `TX_KV_UPDATE_LIMIT = 500,000`, and introduced state-growth limits.
* [Rex3](/spec/network-upgrades/rex3) retained the stable resource-limit set.
* [Rex4](/spec/network-upgrades/rex4) — added per-call-frame runtime budgets; intrinsic resource costs (always deducted before execution) are now reflected in the top-level frame budget before it is forwarded to child frames.
* [Rex5](/spec/network-upgrades/rex5) — bounded a precompile invocation's compute-gas consumption by the remaining compute-gas budget, failing the precompile with `PrecompileOOG` rather than letting it overshoot the budget.
* [Rex6](/spec/network-upgrades/rex6) — moved EIP-7702 authority state-growth resolution from pre-execution (after the caller nonce bump) to validation, and added dynamic SALT account-creation gas for each net-new applied authority to the pre-frame intrinsic gas deduction; removed the keyless-deploy exception to gas preservation, so remaining gas is now rescued on every transaction-level exceed; and stopped enforcing the four runtime transaction-level limits against system-originated transactions, whose usage is still recorded.


# Resource Accounting

MegaETH resource accounting specification — counter semantics, revert behavior, and per-opcode metering for compute gas, data size, KV updates, and state growth.

This page specifies how MegaETH accounts for usage across the four runtime resource dimensions: [compute gas](/spec/reference/glossary#compute-gas), data size, KV updates, and state growth. It defines what each dimension tracks, when counters are updated, and how revert behavior affects the counters.

## Motivation

MegaETH enforces multiple runtime resource limits in addition to the transaction gas limit. Those limits are meaningful only if every node computes the same resource usage for the same transaction.

Without a precise accounting specification, different implementations could disagree on questions such as:

* whether reverted subcalls still count toward a resource dimension,
* whether repeated account updates should be counted once or multiple times,
* whether new storage writes and later resets within the same transaction cancel out,
* and whether logs or deployed bytecode should count before or after success is known.

Resource accounting exists to make runtime-limit enforcement deterministic across implementations.

## Specification

The named constants referenced in this section are defined later in [Constants](#constants).

### Overview

MegaETH defines four runtime resource dimensions:

1. [Compute gas](/spec/reference/glossary#compute-gas)
2. Data size
3. KV updates
4. State growth

A node MUST track each dimension independently. Runtime limit enforcement for these dimensions is defined in [Multidimensional Resource Limits](/spec/megaevm/resource-limits). This page defines only how usage is counted.

### Revert Behavior

Unless explicitly stated otherwise on this page, resource trackers MUST be [call-frame](/spec/reference/glossary#call-frame)-aware:

* usage created within a child call frame MUST be discarded if that child frame reverts,
* and usage created within a child call frame MUST be merged into the parent call frame if that child call frame succeeds.

The sole exception is [compute gas](/spec/reference/glossary#compute-gas), which MUST accumulate globally and MUST NOT be reverted.

#### Creator Nonce-Bump Frame Attribution

A `CREATE` / `CREATE2` bumps the creator's nonce, and that account-info write is charged to the data-size and KV-update dimensions. The creator's nonce bump survives a revert of the created frame under EVM semantics, so its accounting MUST follow the same scope.

A node MUST record the creator nonce-bump account-info write (`ACCOUNT_UPDATE_DATA_SIZE` bytes of data size and one KV update) in the **parent** frame's discardable lane, so that it is discarded only when the parent itself reverts.

A node MUST record the charge even for a creation rejected for exceeding the call-depth limit or for insufficient creator balance, where no nonce bump follows.

### Compute Gas

Compute gas accounting is specified in full on its own page: see [Compute Gas Accounting](/spec/megaevm/compute-gas).

That page defines the measurement window that derives compute gas from inherited EVM gas, the per-opcode metering classes, the non-opcode recording sites, and the exceed behavior.

Two properties matter for this page's purposes:

* A node MUST track compute gas as the sum of the amounts recorded at the sites [Compute Gas Accounting](/spec/megaevm/compute-gas) defines, independent of [storage gas](/spec/megaevm/dual-gas-model). It is not simply all EVM gas consumed: gas consumed by an operation whose measurement window never closes is deliberately not recorded.
* Compute gas MUST accumulate globally and MUST NOT be reverted — the sole exception to the [revert behavior](#revert-behavior) that governs the other three dimensions.

### Data Size

#### Definition

A node MUST track data size as the total number of bytes of execution-related data attributable to the transaction.

#### Non-Discardable Data Size

The following contributions MUST be counted at transaction start and MUST NOT be reverted:

| Data Type                 | Size                                                |
| ------------------------- | --------------------------------------------------- |
| Base transaction data     | `BASE_TRANSACTION_DATA_SIZE`                        |
| Calldata                  | `tx.input().len()`                                  |
| Access list               | Sum of encoded entry sizes                          |
| EIP-7702 authorizations   | `AUTHORIZATION_DATA_SIZE × authorization_count`     |
| Caller account update     | `ACCOUNT_UPDATE_DATA_SIZE`                          |
| Authority account updates | `ACCOUNT_UPDATE_DATA_SIZE × authority_update_count` |

#### Discardable Data Size

The following contributions MUST be tracked within call frames and MUST be discarded if the call frame reverts:

| Data Type                        | Size                                | Trigger                                  |
| -------------------------------- | ----------------------------------- | ---------------------------------------- |
| Log base                         | `LOG_BASE_DATA_SIZE`                | `LOG0`–`LOG4`                            |
| Log topics                       | `LOG_TOPIC_DATA_SIZE × topic_count` | `LOG0`–`LOG4`                            |
| Log data                         | `log_data.len()`                    | `LOG0`–`LOG4`                            |
| SSTORE new write                 | `ACCOUNT_UPDATE_DATA_SIZE`          | `original == present && original != new` |
| SSTORE reset                     | `-ACCOUNT_UPDATE_DATA_SIZE`         | `original != present && original == new` |
| Account update (CALL with value) | `ACCOUNT_UPDATE_DATA_SIZE`          | Balance change on CALL-like operation    |
| Account update (CREATE/CREATE2)  | `ACCOUNT_UPDATE_DATA_SIZE`          | Successful account creation path         |
| Deployed bytecode                | `code.len()`                        | Successful `CREATE` or `CREATE2`         |

#### Account Update Deduplication

Within a single call frame, a node MUST count a given account update at most once for data-size tracking. If the same account is updated multiple times within the same call frame — including the caller account across multiple value-transferring sub-calls or creates — subsequent updates in that call frame MUST NOT add additional `ACCOUNT_UPDATE_DATA_SIZE` bytes.

#### Value Self-Transfer Deduplication for Data Size

A value-transferring call whose target equals its caller touches a single account, but the per-call accounting otherwise records a caller-side and a target-side account update.

When a value-transferring call's target equals its caller, a node MUST count the account update once: the target-side `ACCOUNT_UPDATE_DATA_SIZE` charge MUST be suppressed, leaving the caller-side charge (or, at the top level, the transaction-start caller record) as the single charge for the account. Calls with distinct caller and target, and zero-value calls, are unchanged.

#### Applied-Authorization Narrowing for Data Size

A node MUST count the `ACCOUNT_UPDATE_DATA_SIZE` authority account update only for an *applied* authorization — one that passes all application gates and therefore writes the authority account. A node MUST NOT count a skipped authorization toward `authority_update_count`. The per-record `AUTHORIZATION_DATA_SIZE × authorization_count` contribution counts every authorization in the list, applied or not.

When multiple authorizations target the same authority, a node MUST evaluate them sequentially against the authority nonce and MUST count each applied authorization independently.

#### SELFDESTRUCT Existing-Beneficiary Data Size

A node MUST record `ACCOUNT_UPDATE_DATA_SIZE` bytes of data size for a `SELFDESTRUCT` that transfers a **non-zero** balance to an existing account **distinct** from the executing contract. A `SELFDESTRUCT` of a zero-balance contract performs no balance credit and MUST record nothing. A `SELFDESTRUCT` whose target is the executing contract itself credits no other account and MUST record nothing — under [EIP-6780](https://eips.ethereum.org/EIPS/eip-6780) it is a balance no-op for a contract not created in the current transaction and burns the balance for one that was, and neither writes a distinct target account.

### KV Updates

#### Definition

A node MUST track KV updates as the number of state-modifying key-value updates attributable to the transaction.

#### Non-Discardable KV Updates

The following contributions MUST be counted at transaction scope and MUST NOT be reverted:

| Operation                  | Count                         |
| -------------------------- | ----------------------------- |
| Transaction caller update  | `1`                           |
| EIP-7702 authority updates | `applied_authorization_count` |

#### Discardable KV Updates

The following contributions MUST be tracked within call frames and MUST be discarded if the call frame reverts:

| Operation        | Count      | Trigger                                                                                |
| ---------------- | ---------- | -------------------------------------------------------------------------------------- |
| SSTORE new write | `+1`       | `original == present && original != new`                                               |
| SSTORE reset     | `-1`       | `original != present && original == new`                                               |
| CREATE/CREATE2   | `1` or `2` | Created account plus caller update if caller not yet counted in the current call frame |
| CALL with value  | `1` or `2` | Callee update plus caller update if caller not yet counted in the current call frame   |

#### Account Update Deduplication

Within a single call frame, a node MUST deduplicate caller account updates for KV-update tracking in the same way it does for data-size tracking. When a CALL with value or CREATE occurs, the caller's update MUST be counted only if it has not already been counted in the current call frame.

#### Value Self-Transfer Deduplication for KV Updates

When a value-transferring call's target equals its caller, a node MUST count one KV update for the account instead of two, mirroring the data-size deduplication above. Calls with distinct caller and target, and zero-value calls, are unchanged.

#### Applied-Authorization Narrowing for KV Updates

A node MUST count one authority KV update only for each *applied* authorization — one that passes the chain-id, nonce, and code gates and writes the authority account — mirroring the data-size narrowing above. A node MUST NOT count a skipped authorization. When multiple authorizations target the same authority, each applied authorization MUST be counted independently.

#### SELFDESTRUCT Existing-Beneficiary KV Update

A node MUST record one KV update for a `SELFDESTRUCT` that transfers a **non-zero** balance to an existing account **distinct** from the executing contract, mirroring the data-size rule above. No state growth is recorded — the account already exists. A `SELFDESTRUCT` of a zero-balance contract, or to the executing contract itself, MUST record nothing.

### State Growth

#### Definition

A node MUST track state growth as the net increase in on-chain state caused by new accounts and new storage slots.

#### Storage Slot Growth Rules

For `SSTORE`, a node MUST apply the following state-growth accounting rules:

| Original | Present | New     | Growth |
| -------- | ------- | ------- | ------ |
| `0`      | `0`     | non-`0` | `+1`   |
| `0`      | non-`0` | `0`     | `-1`   |
| `0`      | non-`0` | non-`0` | `0`    |
| non-`0`  | any     | any     | `0`    |

The table above means:

* the first write to a slot that was empty at transaction start MUST increase state growth by `1`,
* clearing such a slot later in the same transaction MUST decrease state growth by `1`,
* rewriting a slot already counted within the transaction MUST NOT change state growth further,
* and slots that were already non-zero at transaction start MUST NOT contribute to state growth.

#### Conditional CREATE State Growth

A node MUST record the `+1` state growth for a `CREATE` / `CREATE2` only when the created address is net-new — that is, the account at the derived address is empty under the state-clear rule when the frame starts. Deploying to an address that already exists (for example, an address previously funded with a balance) MUST NOT record state growth, mirroring the value-transfer rule that counts only newly materialized accounts.

#### SELFDESTRUCT Refund

When a same-transaction-created contract is destroyed by `SELFDESTRUCT`, the node MUST apply a state-growth refund. See [SELFDESTRUCT — State Growth Refund](/spec/megaevm/selfdestruct#state-growth-refund) for the full specification.

#### Negative Intermediate Values

The state-growth counter MAY become negative during execution. The reported final state growth for limit enforcement MUST be clamped to a minimum of `0`.

### Post-Execution Fee-Reward Accounting

After execution, the protocol credits transaction fees to the block beneficiary and the protocol fee vaults (the L1-fee, base-fee, and operator-fee recipients). These writes happen after the per-transaction resource trackers have been finalized.

For each **distinct** fee-recipient account whose balance the fee-reward step changes, a node MUST record one account-info write — `ACCOUNT_UPDATE_DATA_SIZE` bytes of data size and one KV update — in the transaction-persistent lane. If the write materializes a previously non-existent account (empty before the credit, non-empty after), the node MUST additionally record `+1` state growth.

A fee recipient that coincides with another (for example, a block beneficiary that is also a fee vault) MUST be counted once. This usage is recorded after the transaction's execution result is final: it feeds the transaction's reported usage and the block-level cumulative counters, and it MUST NOT retroactively change the transaction's outcome — a transaction-level limit crossed only by the fee-reward writes does not fail the transaction. Transactions that credit no fees (deposit transactions and sandboxed executions) record nothing in this step.

## Constants

| Constant                     | Value | Description                                                                       |
| ---------------------------- | ----- | --------------------------------------------------------------------------------- |
| `BASE_TRANSACTION_DATA_SIZE` | 110   | Fixed estimate of the RLP-encoded transaction envelope excluding calldata         |
| `AUTHORIZATION_DATA_SIZE`    | 101   | Bytes counted per EIP-7702 authorization                                          |
| `ACCOUNT_UPDATE_DATA_SIZE`   | 40    | Bytes counted for an account update or storage-write record in data-size tracking |
| `LOG_TOPIC_DATA_SIZE`        | 32    | Bytes counted per log topic in data-size tracking                                 |
| `LOG_BASE_DATA_SIZE`         | 32    | Bytes counted per emitted log for the log address in data-size tracking           |

## Rationale

**Why make most resource dimensions call-frame-aware?** Data size, KV updates, and state growth represent effects that should match the surviving transaction outcome. If a child call frame reverts, its discarded logs, writes, and transient growth should not count toward the final resource totals.

**Why is compute gas the exception?** Compute gas measures work already performed by the node. That work cannot be undone merely because a child call frame reverted. Making compute gas non-revertible prevents implementations from undercounting resource consumption in transactions that repeatedly attempt and revert expensive subcalls.

**Why deduplicate account updates within a call frame?** Repeated writes to the same account within one call frame do not represent distinct independent account objects in state. Deduplication prevents artificial inflation of data-size and KV-update counts from repeated modifications to the same account within a single call frame.

**Why allow negative intermediate state growth?** During execution, a transaction may first create new state and later remove it. Allowing the counter to go negative during intermediate steps keeps the accounting locally composable across nested call frames, while clamping the final reported value prevents negative net state growth from being treated as a meaningful resource credit.

## Security Considerations

**If compute gas were made revertible** (scoped to call frames like data size and KV updates), an attacker could execute and revert expensive subcalls repeatedly within a single transaction, consuming negligible apparent compute gas while imposing real execution cost on nodes.

## Spec History

This page describes the current accounting behavior.

* [Rex4](/spec/network-upgrades/rex4) — introduced per-call-frame runtime budgets for all four resource dimensions.
* [Rex5](/spec/network-upgrades/rex5) — corrected caller-account update deduplication: pre-Rex5, the caller's `ACCOUNT_UPDATE_DATA_SIZE` (data size) and KV-update count were re-charged on every value-transferring sub-call or create from the same parent frame because the caller was never marked as already counted after the first charge; Rex5 marks the caller after the first charge so subsequent operations from the same parent frame do not re-count the caller account. Rex5 also records contract-creation code-deposit compute gas atomically with the deployment commit instead of during post-execution accounting.
* [Rex6](/spec/network-upgrades/rex6) — narrowed the EIP-7702 authority data-size and KV-update charges from every recoverable authorization to only *applied* authorizations: through Rex5, the `ACCOUNT_UPDATE_DATA_SIZE` and KV update were charged for every authorization with a recoverable authority, including ones later skipped by the chain-id, nonce, or code application gates.
* [Rex6](/spec/network-upgrades/rex6) — corrected two `CREATE`-frame accounting errors: the creator nonce-bump account-info write is booked to the parent frame's discardable lane instead of the child's, so it survives a child-`CREATE` revert correctly, and a creation rejected for call depth or creator balance now keeps the charge where through Rex5 it was discarded with the child's lane; and `CREATE` records `+1` state growth only when the created address is net-new instead of unconditionally.
* [Rex6](/spec/network-upgrades/rex6) — counted the account writes performed by the post-execution fee-reward step toward resource accounting: through Rex5, fee-recipient writes performed after the resource trackers were finalized escaped accounting entirely. The deposit-mint half was already closed in Rex5; Rex6 covers the remaining non-deposit fee-credit paths.
* [Rex6](/spec/network-upgrades/rex6) — counted the account-info write of a `SELFDESTRUCT` balance credit to an already-existing beneficiary: through Rex5 only a `SELFDESTRUCT` that created a new beneficiary was metered, so a balance credit to an existing beneficiary (which does not flow through the frame-initialization or caller-dedup path) recorded nothing.
* [Rex6](/spec/network-upgrades/rex6) — added a per-log data-size base: through Rex5, an empty `LOG0` contributed zero data size because the log address was not counted.
* [Rex6](/spec/network-upgrades/rex6) — deduplicated the value self-transfer account-info write: when a value-transferring call's target equals its caller, the caller-side and target-side writes refer to the same account, but through Rex5 the data-size and KV-update charges were recorded for both, over-counting the one account (it never under-charges). This extends the Rex5 caller-account deduplication above to the self-transfer case.


# Gas Detention

MegaETH gas detention specification — compute gas caps triggered by volatile data access (block environment, oracle SLOAD).

This page specifies the current gas-detention behavior. Gas detention limits post-access [compute gas](/spec/reference/glossary#compute-gas) after a transaction reads [volatile data](/spec/reference/glossary#volatile-data), bounding the amount of computation that may occur after access to shared, conflict-prone inputs.

## Motivation

MegaETH executes transactions with aggressive parallelism. Certain inputs are shared across many transactions and therefore create conflict hotspots: block-environment fields, the [beneficiary](/spec/reference/glossary#beneficiary) account, and oracle-backed data.

Without an additional constraint, a transaction could read one of these shared inputs and then continue executing an arbitrarily large amount of computation. That pattern increases contention, reduces parallel execution efficiency, and makes worst-case execution time depend on transactions that touch conflict-prone state.

Gas detention addresses this by limiting the remaining compute budget after volatile data access. The transaction is still permitted to read the data, but the amount of computation that can follow the access is bounded.

## Specification

The named constants referenced in this section are defined later in [Constants](#constants).

### Overview

A node MUST apply gas detention when a transaction accesses volatile data as defined on this page. Gas detention affects only [compute gas](/spec/reference/glossary#compute-gas). It MUST NOT directly change storage gas accounting, [data size](/spec/megaevm/resource-accounting#data-size), [KV updates](/spec/megaevm/resource-accounting#kv-updates), or [state growth](/spec/megaevm/resource-accounting#state-growth).

Detention applies a **relative cap** on compute gas. When a volatile access applies a detention cap `cap`, the effective detained limit becomes:

```
effective_detained_limit = current_compute_gas_used + cap
effective_compute_gas_limit = min(tx_compute_gas_limit, effective_detained_limit)
```

This means a transaction MAY always consume up to `cap` more compute gas after the volatile access, regardless of how much compute gas was consumed before the access.

### Volatile Data Categories

The following volatile data categories trigger detention.

#### Block Environment Access

A node MUST apply block-environment gas detention with cap `BLOCK_ENV_DETENTION_CAP` when a transaction executes any of the following opcodes:

* `NUMBER`
* `TIMESTAMP`
* `COINBASE`
* `DIFFICULTY` / `PREVRANDAO`
* `GASLIMIT`
* `BASEFEE`
* `BLOCKHASH`
* `BLOBBASEFEE`
* `BLOBHASH`

#### Beneficiary Access

A node MUST apply beneficiary gas detention with cap `BENEFICIARY_DETENTION_CAP` when a transaction accesses the [beneficiary](/spec/reference/glossary#beneficiary) account through any of the following behaviors:

* `BALANCE` on the beneficiary address
* `SELFBALANCE` when the current contract is the beneficiary
* `EXTCODECOPY` on the beneficiary address
* `EXTCODESIZE` on the beneficiary address
* `EXTCODEHASH` on the beneficiary address
* a transaction whose sender is the beneficiary
* a transaction or call frame whose recipient is the beneficiary
* beneficiary access performed through `DELEGATECALL`

`SELFDESTRUCT` targeting the beneficiary MUST also trigger beneficiary gas detention.

When a `CALL`, `CALLCODE`, `DELEGATECALL`, or `STATICCALL` loads a target account whose code is an [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) delegation designation, the node MUST resolve the delegation one hop and mark beneficiary access when either the raw target or the resolved delegate equals the beneficiary.

A node MUST also apply beneficiary gas detention when an *applied* EIP-7702 authorization — one that passes the chain-id, nonce, and code application gates and therefore writes the authority account — has an authority address equal to the block beneficiary. Applying such an authorization mutates beneficiary state (nonce and delegation code), so the node MUST mark beneficiary access and re-derive the effective compute-gas detention cap during transaction validation, even though no opcode in the list above was executed. A skipped authorization whose authority equals the beneficiary MUST NOT trigger detention.

#### Oracle Access

A node MUST apply oracle gas detention with cap `ORACLE_DETENTION_CAP` when a transaction performs `SLOAD` against the storage of the [oracle contract](/spec/system-contracts/oracle).

The following rules MUST apply:

* `CALL` to the oracle contract address alone MUST NOT trigger oracle detention.
* `STATICCALL` to the oracle contract address alone MUST NOT trigger oracle detention.
* Oracle detention is triggered by storage reads, not by message-call targeting alone.
* `DELEGATECALL` to the oracle contract MUST NOT trigger oracle detention solely by virtue of targeting the oracle address, because `SLOAD` in a `DELEGATECALL` context reads the caller's storage, not the oracle contract's storage.
* If the transaction sender is [`MEGA_SYSTEM_ADDRESS`](/spec/system-contracts/system-tx), oracle gas detention MUST NOT be applied.

### Cap Selection

If multiple volatile-data categories are accessed during the same transaction, the node MUST apply the most restrictive effective cap. Each volatile access produces its own effective detained limit (`current_compute_gas_used + cap` at the time of that access). The node MUST keep the minimum across all such limits:

```
effective_compute_gas_limit = min(tx_compute_gas_limit, all effective_detained_limits)
```

Applying a later volatile access MUST NOT increase the effective detained limit.

### Execution Semantics

When a volatile-data trigger occurs, the node MUST perform the following steps in order:

1. Identify the detention category and its cap.
2. Compute the effective detained limit as `current_compute_gas_used + cap`.
3. Update the transaction's effective compute gas limit to the minimum of the current effective limit and the newly computed effective detained limit.
4. Continue execution subject to the updated limit.

After detention has been applied, any subsequent execution step that would cause `compute_gas_used` to exceed the effective detained limit MUST halt the transaction with `VolatileDataAccessOutOfGas`.

The detained compute-gas limit MUST NOT halt a [system-originated transaction](/spec/system-contracts/system-tx#system-originated-transaction-metering-exemption). Volatile-data accesses by such a transaction are still tracked, but the detention cap is not enforced against it; its standard EVM `gas_limit` remains the only halting bound.

### Refund Semantics

Gas detention does not consume the detained portion of the transaction's gas budget. If a transaction halts because the detained compute gas limit would be exceeded, the unused gas beyond actual execution MUST remain refundable under the same rules as other unused transaction gas.

Detention therefore limits execution but MUST NOT itself create an additional gas charge beyond the compute gas actually consumed.

### Transaction Boundary

The detained compute gas limit MUST be reset at the start of each transaction. Gas detention state from one transaction MUST NOT carry over to subsequent transactions in the same block.

### Corner Cases

#### Repeated Access to Same Category

Repeated access to the same volatile-data category within the same transaction MUST NOT relax the effective detained limit. Reapplying the same cap is idempotent.

#### Access Across Multiple Call Frames

Detention is transaction-scoped, not call-frame-scoped. If a child call frame triggers detention, the reduced effective compute gas limit MUST apply to the remainder of the transaction, including parent and sibling call frames.

#### Reverted Call Frames

If volatile access occurs inside a call frame that later reverts, the compute gas already consumed remains consumed. The detained compute gas limit MUST remain in effect for the rest of the transaction.

## Constants

| Constant                       | Value      | Description                                                          |
| ------------------------------ | ---------- | -------------------------------------------------------------------- |
| `BLOCK_ENV_DETENTION_CAP`      | 20,000,000 | Relative compute gas cap after block-environment access              |
| `BENEFICIARY_DETENTION_CAP`    | 20,000,000 | Relative compute gas cap after beneficiary access                    |
| `ORACLE_DETENTION_CAP`         | 20,000,000 | Relative compute gas cap after oracle storage access                 |
| `ORACLE_DETENTION_CAP_MINIREX` | 1,000,000  | Historical absolute compute gas cap after oracle access (superseded) |

`BLOCK_ENV_DETENTION_CAP` and `BENEFICIARY_DETENTION_CAP` have the same value: block-environment and beneficiary access are detained at the same level.

## Rationale

**Why detention instead of outright prohibition?** MegaETH must permit contracts to read shared inputs such as time, block metadata, and oracle-fed values. Outright banning such reads would make large classes of contracts non-viable. Detention preserves expressiveness while bounding the computation that may follow a conflict-prone read.

**Why a relative cap instead of an absolute cap?** The original MiniRex design used an absolute cap, which guaranteed a hard upper bound on total compute gas after volatile access. Its drawback was that late volatile access could cause immediate failure if substantial compute gas was already consumed — penalizing transactions for work done *before* touching volatile data. The relative model avoids this by guaranteeing a fixed budget of additional compute gas *after* the access, regardless of prior consumption.

**Why make the most restrictive cap win?** A transaction that touches multiple volatile sources should be governed by the strongest applicable constraint. Allowing a less restrictive later trigger to relax an earlier cap would make detention order-dependent and harder to reason about.

**Why make detention transaction-scoped?** The purpose of detention is to bound the remainder of execution after volatile access. If the cap were scoped only to the triggering call frame, contracts could evade the limit by returning to a parent frame and continuing computation there.

## Security Considerations

**If detention is call-frame-scoped rather than transaction-scoped**, a contract can trigger volatile access inside a child call frame, revert the frame, and resume unbounded execution in the parent — entirely bypassing detention. Transaction-level scoping is essential to preserve the invariant that compute gas after any volatile access is bounded.

**If detention applied in a call frame that later reverts is reversed**, an attacker can trigger volatile access inside a frame it then reverts to escape the detention cap for the rest of the transaction.

## Spec History

Gas detention semantics evolved across specs:

* [MiniRex](/spec/network-upgrades/minirex) — introduced gas detention; block-environment cap 20M, oracle cap 1M, oracle triggering based on message-call access
* [Rex](/spec/network-upgrades/rex) — made CALL-like opcode behavior consistent
* [Rex1](/spec/network-upgrades/rex1) — reset detained compute gas limit between transactions in the same block
* [Rex3](/spec/network-upgrades/rex3) — raised oracle cap to 20M and changed oracle detection from CALL-based to SLOAD-based
* [Rex4](/spec/network-upgrades/rex4) — changes absolute detention to relative detention and adds additional beneficiary-triggered behavior
* [Rex6](/spec/network-upgrades/rex6) — adds a beneficiary-detention trigger for an applied EIP-7702 authorization whose authority equals the block beneficiary; resolves a CALL-family target's EIP-7702 delegation one hop before the beneficiary comparison, so a call through a delegator whose delegate is the beneficiary triggers detention (through Rex5 only the raw target is compared); and stops enforcing the detention cap against system-originated transactions, whose volatile accesses are still tracked


# Gas Forwarding

MegaETH 98/100 gas forwarding rule — CALL, DELEGATECALL, STATICCALL, CALLCODE, and CREATE/CREATE2 forwarding semantics.

This page specifies how MegaETH forwards gas into child call frames and contract-creation call frames. It defines the stable 98/100 forwarding rule and its relation to value-transfer stipends.

## Motivation

The standard 63/64 forwarding rule was introduced to mitigate call-depth attacks by ensuring that each nested call retains less gas than its parent. MegaETH is designed to support block gas limits up to 10 billion gas. At that scale, the inherited 63/64 rule again leaves enough gas available at deep call depth to reintroduce the attack it was meant to mitigate.

MegaETH therefore replaces the inherited forwarding fraction with a stricter rule.

## Specification

### Stable Forwarding Rule

A node MUST cap gas forwarded by CALL-like opcodes and contract-creation opcodes to 98/100 of the parent's remaining gas.

The stable forwarding rule applies to:

* `CALL`,
* `CALLCODE`,
* `DELEGATECALL`,
* `STATICCALL`,
* `CREATE`,
* `CREATE2`.

The forwarding cap is:

`forwarded_gas_cap = parent_remaining_gas - parent_remaining_gas × 2 / 100`

The child call frame gas limit MUST be the minimum of:

* the gas requested by the caller, and
* `forwarded_gas_cap`.

When a `CALL`-family or `CREATE` / `CREATE2` opcode records its compute gas after its body and the recording exceeds the [compute gas limit](/spec/megaevm/resource-limits), the opcode fails — with the frame-local revert or the transaction-level halt alike — and its pending child frame is discarded before the child runs (see [Exceed Behavior](/spec/megaevm/compute-gas#exceed-behavior)). A node MUST return the forwarded gas to the failing frame before it terminates, so the discarded child's gas is not charged as consumed.

### Value Transfer Stipend

For `CALL` and `CALLCODE` with non-zero value transfer, the standard EVM `CALL_STIPEND` MUST be preserved. The forwarding cap applies to the forwarded gas portion, not to the stipend itself.

The child call frame gas for value-transferring `CALL` and `CALLCODE` MUST be:

`child_gas = min(requested_forwarded_gas, forwarded_gas_cap) + CALL_STIPEND`

For `DELEGATECALL`, `STATICCALL`, `CREATE`, and `CREATE2`, no call stipend applies.

### [Storage Gas Stipend](/spec/reference/glossary#storage-gas-stipend) Interaction

For internal (call depth greater than zero) value-transferring `CALL` and `CALLCODE`, the callee frame receives a `STORAGE_CALL_STIPEND` allowance. This allowance MUST NOT inflate the callee's `gas_limit`: the child-frame gas limit is exactly `min(requested_forwarded_gas, forwarded_gas_cap) + CALL_STIPEND`, with no `STORAGE_CALL_STIPEND` term.

The allowance is a per-frame budget reserved exclusively for the storage-gas surcharges that MegaETH adds on top of standard EVM opcode costs. A node MUST apply the allowance only to the following storage-gas surcharge sites incurred within the callee frame:

* empty-account creation via value-transferring `CALL` / `CALLCODE`,
* contract creation via `CREATE` / `CREATE2`,
* the first-time zero-to-non-zero `SSTORE` write,
* `LOG` topic and data storage gas, and
* empty-beneficiary creation via `SELFDESTRUCT`.

At each such site, a node MUST draw up to `STORAGE_CALL_STIPEND` from the frame's remaining allowance and charge only the residual surcharge (the surcharge minus the amount drawn) against the frame's gas.

Because the allowance never enters the frame's gas limit, it MUST NOT be spendable on compute (standard EVM opcode) gas. The allowance does not apply to standard EVM opcode costs: a callee whose forwarded gas plus `CALL_STIPEND` does not cover the standard EVM cost of an opcode MUST run out of gas normally regardless of the remaining allowance. Any portion of the allowance not drawn by a surcharge site is not returned to the caller; the allowance never contributes to the gas a frame returns to its parent.

The allowance applies to internal value-transferring `CALL` and `CALLCODE` only. Top-level transactions, `DELEGATECALL`, `STATICCALL`, `CREATE`, `CREATE2`, and any value-zero call MUST NOT receive the allowance.

## Constants

| Constant                  | Value  | Description                                                                           |
| ------------------------- | ------ | ------------------------------------------------------------------------------------- |
| `GAS_FORWARD_NUMERATOR`   | 98     | Numerator of the stable forwarding fraction                                           |
| `GAS_FORWARD_DENOMINATOR` | 100    | Denominator of the stable forwarding fraction                                         |
| `CALL_STIPEND`            | 2,300  | Standard EVM stipend preserved for value-transferring `CALL` and `CALLCODE`           |
| `STORAGE_CALL_STIPEND`    | 23,000 | Per-frame storage-gas allowance for internal value-transferring `CALL` and `CALLCODE` |

## Rationale

**Why 98/100 instead of 63/64?** The inherited 63/64 rule was designed to mitigate call-depth attacks by ensuring that each nested call retains less gas than its parent. MegaETH is intended to support block gas limits up to 10 billion gas, which makes the inherited 63/64 reduction insufficient to suppress that attack pattern at deep call depth. Retaining 2% instead of approximately 1.56% reduces residual gas more aggressively and restores the protective intent of gas-based call-depth mitigation under MegaETH's higher gas regime.

**Why make the storage gas stipend a per-frame allowance instead of inflating the child gas limit?** The stipend exists so a value-transferring internal call can pay MegaETH's storage-gas surcharges even when the caller forwards little or no gas. Adding the stipend to the child's gas limit, Rex4 left it spendable on compute opcodes; the per-frame compute-gas cap that fenced it off was enforced only after each opcode completed, so a single expensive opcode could record its full compute cost into the parent's compute-gas counter before the cap triggered, and repeated value-transferring calls could amplify recorded compute gas beyond the transaction's compute-gas limit. Keeping the stipend as an allowance that never enters the child's gas limit makes it structurally unspendable on compute, removing the amplification path without changing the grant amount or which calls qualify.

## Security Considerations

**If more than 98/100 of gas is forwarded**, MegaETH's high block gas limits (up to 10 billion) mean enough residual gas survives at deep call depth to sustain a call-depth denial-of-service attack. The 63/64 rule inherited from Ethereum was designed for much lower gas budgets; at 10B gas, 98/100 is needed to achieve the same protective effect.

## Spec History

* [MiniRex](/spec/network-upgrades/minirex) introduced the 98/100 rule for `CALL`, `CREATE`, and `CREATE2` only.
* [Rex](/spec/network-upgrades/rex) extended the rule to all CALL-like opcodes.
* [Rex4](/spec/network-upgrades/rex4) — added storage-gas stipend for value-transferring `CALL` and `CALLCODE`.
* [Rex5](/spec/network-upgrades/rex5) — recast the storage-gas stipend as a per-frame allowance that no longer inflates the child's gas limit (so it cannot be spent on compute), and corrected the parent's compute-gas attribution to exclude the `CALL_STIPEND` for value-transferring `CALL` / `CALLCODE`; the 23,000 grant amount and admission conditions are unchanged.
* [Rex6](/spec/network-upgrades/rex6) — returns forwarded gas to the parent when a `CALL` or `CREATE` halts on the compute-gas limit: through Rex5, the pending child frame was discarded but the gas already forwarded to it was not returned, inflating `gas_used`.


# Contract Limits

MegaETH contract size limits — 512 KB max bytecode, 536 KB max initcode, inherited from MiniRex.

This page specifies MegaETH's limits on deployed contract bytecode size and initcode size. It defines the contract-size limits inherited from [MiniRex](/spec/network-upgrades/minirex).

## Motivation

Contract size and initcode size directly affect execution cost, state footprint, and validation overhead. MegaETH raises these limits to accommodate larger deployments, but the protocol must still define explicit maximum values so all nodes reject oversized contracts consistently.

## Specification

A node MUST enforce the following limits:

| Limit                          | Value               |
| ------------------------------ | ------------------- |
| Maximum deployed contract size | `MAX_CONTRACT_SIZE` |
| Maximum initcode size          | `MAX_INITCODE_SIZE` |

If deployed runtime bytecode exceeds `MAX_CONTRACT_SIZE`, the node MUST reject the deployment. If initcode exceeds `MAX_INITCODE_SIZE`, the node MUST reject the creation transaction or creation opcode execution.

The initcode limit is defined as:

`MAX_INITCODE_SIZE = MAX_CONTRACT_SIZE + ADDITIONAL_INITCODE_SIZE`

### Creation-Opcode Halt Ordering

The rules in this section apply from [MiniRex](/spec/network-upgrades/minirex) onward. Under the Equivalence spec a node runs the creation opcodes unchanged, with no prework and no contract-creation storage gas, so canonical ordering applies throughout.

`CREATE2` computes its target address by expanding memory, copying the initcode, and hashing it before the inner opcode body runs, and both `CREATE` and `CREATE2` charge the contract-creation [storage gas](/spec/reference/glossary#storage-gas) for the derived address before that body runs. Two rejections MUST fire ahead of that prework.

When a `CREATE2`'s initcode length exceeds `MAX_INITCODE_SIZE`, a node MUST halt with `CreateInitCodeSizeLimit` before the memory expansion, the initcode copy, the `keccak256` hash, and the address derivation. The check follows canonical operand ordering: the length operand is converted first, then the size check runs, then the offset operand is converted.

This rule is specific to `CREATE2`. A `CREATE` derives its address from the creator's nonce without reading the initcode, so it has no such prework to precede: its size check stays inside the opcode body, after the contract-creation storage gas for the derived address is charged. An oversized `CREATE` therefore surfaces whichever halt that charge reaches first — a storage-gas out-of-gas, or a fatal external error from the storage-pricing lookup — rather than `CreateInitCodeSizeLimit`, on every spec from MiniRex onward.

Inside a static call frame, any `CREATE` or `CREATE2` MUST halt with the static-call rejection before its operands are read, before the size check runs, before the deployment address is derived, and before the contract-creation storage gas is charged. This matches canonical ordering, in which the static-context check precedes every other check.

Where both orderings end in a halt, they change only the halt reason and its timing, not the outcome: every such halt consumes all gas regardless of when it fires, so committed gas and committed state are identical either way. The exception is the fatal external error, which abandons the transaction instead of halting the frame: rejecting before the storage-pricing lookup avoids it entirely, so the outcomes there are not equivalent.

MiniRex through Rex5 run the prework first. There, an oversized `CREATE2` surfaces whichever halt the prework reaches first — a memory out-of-gas, for instance — rather than the size-limit halt, and a creation opcode in a static frame surfaces a stack underflow, a memory out-of-gas, a storage-gas out-of-gas, or a fatal external error from the storage-pricing lookup instead of the static-call rejection.

### Zero-Length Init Code in CREATE2

When a `CREATE2` opcode is executed with an init-code length of zero, a node MUST short-circuit after validating the salt operand: it MUST use the keccak-256 hash of the empty byte string as the resulting init-code hash, and MUST NOT perform any offset conversion, memory expansion, or hashing of memory. Because the init-code length is zero, the init-code offset operand MUST be ignored entirely, even when it is a very large value. This ensures that a zero-length `CREATE2` charges no memory-expansion gas (and no associated compute gas) for the unused offset operand and never halts with a spurious out-of-gas error caused by an out-of-range offset whose length is zero.

## Constants

| Constant                   | Value         | Description                                                         |
| -------------------------- | ------------- | ------------------------------------------------------------------- |
| `MAX_CONTRACT_SIZE`        | 524,288 bytes | Maximum size of deployed contract bytecode                          |
| `ADDITIONAL_INITCODE_SIZE` | 24,576 bytes  | Additional bytes allowed above the contract-size limit for initcode |
| `MAX_INITCODE_SIZE`        | 548,864 bytes | Maximum initcode size                                               |

## Rationale

**Why raise the contract limits?** MegaETH allows substantially larger contracts than standard Ethereum. The enlarged limits support deployment patterns that would otherwise exceed Ethereum's contract-size constraints.

## Security Considerations

This page has no security considerations.

## Spec History

* [MiniRex](/spec/network-upgrades/minirex) introduced the enlarged contract and initcode limits.
* [Rex](/spec/network-upgrades/rex), [Rex1](/spec/network-upgrades/rex1), [Rex2](/spec/network-upgrades/rex2), [Rex3](/spec/network-upgrades/rex3), and [Rex4](/spec/network-upgrades/rex4) retain the same stable limits.
* [Rex5](/spec/network-upgrades/rex5) short-circuits zero-length `CREATE2` after salt validation, using the empty-init-code hash without observing the init-code offset operand.
* [Rex6](/spec/network-upgrades/rex6) moved the oversized-`CREATE2` initcode halt and the static-frame rejection ahead of the creation opcode's address-computation prework; MiniRex through Rex5 run the prework first, so those cases surface whichever halt it reaches first instead. The halt reason and its timing change; the outcome changes only where the prework would have raised a fatal external error.




---

[Next Page](/llms-full.txt/1)

