Methodology
Every number on /mips is produced by one of four methods. This page describes how each signal is measured, what it captures, and what it does not. The same prose is available next to each signal on the main page via the "How we measure" disclosure; here it's laid out top-to-bottom for reference.
MONAD_NINE activated on mainnet at 2026-03-19T14:30:00Z, block 62,466,234. Every metric below uses that block as its lower bound.
Direct measurement; every event in the range captured.
Statistical estimate; sample size + coverage are quoted alongside.
No on-chain measurement; an interactive tool to compute spec-implied behavior.
The spec change is real but receipts/traces don't expose it. Documented; no number.
MIP-2 - Contract Code & Initcode Size
MIP-2 raised two limits at MONAD_NINE: deployed MAX_CODE_SIZE from 24,576 bytes (EIP-170) to 131,072, and MAX_INITCODE_SIZE from 49,152 (EIP-3860) to 262,144. Both changes are backwards-compatible and apply prospectively. Adoption shows up as two distinct signals - contracts whose deployed bytecode would have been rejected by EIP-170, and contracts whose deployment payload would have been rejected by EIP-3860.
Deployed bytecode size
Exhaustive· Top-level CREATEFor every contract creation since MONAD_NINE activation (block 62,466,234), the scanner records the deployed bytecode length. Creations are discovered via an Envio HyperSync transactions query over each block range, collecting every transaction whose receipt carries a `contract_address` (top-level CREATE; factory/internal CREATE2 spawns are not exposed as receipt creations on Monad). The bytecode itself is fetched via `eth_getCode`. Contracts whose deployed bytecode exceeds 24,576 bytes (EIP-170, the pre-MIP-2 ceiling) use MIP-2's `MAX_CODE_SIZE` raise.
source · Envio HyperSync (contract-creation discovery) + eth_getCode on the Monad RPC pool
Initcode size
Exhaustive· Direct-CREATE onlyFor each successful deployment, the deployment transaction's `input` field equals the initcode length when the transaction is a top-level CREATE (`to == null`). Contracts whose initcode exceeded 49,152 bytes (EIP-3860, the pre-MIP-2 initcode ceiling) use MIP-2's `MAX_INITCODE_SIZE` raise.
Limitations. Contracts deployed by factories (`CREATE`/`CREATE2` inside another transaction) have their deployed bytecode captured but not their initcode - `tx.input` is the factory's calldata, not the spawned contract's initcode. Recovering the latter requires call traces, which are not currently indexed at scale for Monad. In practice all 200 sampled jumbo (>24KB) contracts were direct-CREATE, so jumbo-initcode coverage is effectively complete; the small-contract initcode dimension is partial.
source · eth_getTransactionByHash on the deployment tx; `input.length` measured client-side
MIP-3 - Linear Memory
MIP-3 replaces Ethereum's quadratic memory-expansion cost (words² / 512 + 3·words) with linear pricing (words / 2) and imposes an 8 MB cap per transaction. The change is a pure gas-pricing recompute: receipts show only final gasUsed, with no indication of which cost regime applied or how much memory was expanded.
Memory regime
CalculatorMIP-3 changes the gas-cost formula for memory expansion from quadratic (`words² / 512 + 3·words`) to linear (`words / 2`), with an 8 MB hard cap per transaction. The change is a server-side pricing recompute - transaction receipts show only the final `gasUsed`, with no indication of which regime applied or how much memory was expanded. Detecting MIP-3 usage directly would require step-level execution traces (e.g. `debug_traceTransaction` with the `structLogger`) to recover peak memory per transaction and recompute the Ethereum-equivalent cost.
Limitations. Step-level tracing across every Monad transaction is currently infeasible (no trace-indexed source for Monad on Envio HyperSync; rpc.monad.xyz's `debug_traceBlockByNumber` is rate-limited below the chain's own block-production rate). Instead the page exposes a calculator so developers can compute the savings for their own use cases.
source · interactive calculator - no on-chain measurement
MIP-4 - Reserve Balance Introspection
MIP-4 introduced a precompile at 0x0000000000000000000000000000000000001001 implementing dippedIntoReserve() (selector 0x3a61584e). The precompile returns a bool indicating whether the executing transaction has dipped into reserve balance. It is designed for mid-execution use by other contracts - never a top-level transaction target - which means "adoption" has to be measured at two layers: whether contracts CAN invoke it (static), and whether they actually DO (runtime).
Static - contracts that could invoke MIP-4
Exhaustive· Bytecode address + selectorFor every contract deployed since MONAD_NINE, the scanner walks the deployed bytecode as opcodes (skipping `PUSH1..PUSH32` immediate data) and looks for two patterns: the literal precompile address `0x…1001` (which Solidity emits for hardcoded `address(0x…1001)`), and the 4-byte function selector `0x3a61584e` (which catches contracts that load the address dynamically - from storage, calldata, or computation - but still invoke `dippedIntoReserve()`). Either signal counts a contract as statically MIP-4-aware.
Limitations. This counts contracts that *could* invoke the precompile, not the count of actual invocations. A contract with the bytes baked in might never take the MIP-4 branch in practice. For actual on-chain usage see the runtime sample below.
source · deployed bytecode of every scanned contract, opcode-aware walk
Runtime - actual on-chain invocations
Sampled· Sparse daily trace sampleOnce per day a sparse trace sample runs: 25 windows of 60 blocks each, evenly distributed across the post-MONAD_NINE range. Each block goes through `debug_traceBlockByNumber` (`callTracer`) on `rpc.monad.xyz` - the only Monad endpoint we have access to that exposes trace methods. The call tree of every transaction is walked, counting CALL frames where the destination is the MIP-4 precompile. (Per the MIP-4 spec, `dippedIntoReserve()` must be invoked via `CALL`; `STATICCALL`/`DELEGATECALL`/`CALLCODE` are forbidden and would revert. Non-CALL frames are reported separately as anomalies.) Each run covers ~1,500 blocks (~7 minutes of chain time) spread across 50+ days of history; the cumulative result is preserved.
Limitations. A true exhaustive runtime backfill is currently infeasible on the available infrastructure. `rpc.monad.xyz` sustains roughly 3 blocks/second of sequential tracing while the chain produces ~3.5 blocks/second, so brute-force scanning can't even keep pace, let alone backfill 14M+ blocks of history. The other Monad pool endpoints (`rpc1/2/3`) reject trace methods (403). Envio HyperSync does not currently index Monad trace data - confirmed empirically. Until either of those changes, runtime usage is reported as a sampled estimate, not a complete count.
source · debug_traceBlockByNumber + callTracer on rpc.monad.xyz
MIP-5 - Fusaka EIP Activation
MIP-5 activates three EIPs from Ethereum's Fusaka upgrade on Monad. They have very different shapes - one adds a new opcode (positive adoption signal), one tightens a precompile's input bounds (a restriction), and one increases a precompile's gas cost (not detectable from RPC). We report each separately because rolling them into a single "MIP-5 adoption" number would be misleading.
EIP-7939 · CLZ opcode in bytecode
Exhaustive· Opcode walk for 0x1eFor every contract deployed since MONAD_NINE the scanner walks the deployed bytecode as opcodes (skipping `PUSH1..PUSH32` immediate data) and counts contracts that contain the new CLZ opcode (byte 0x1e). A naive substring check would false-positive on `0x1e` bytes appearing inside `PUSH32` payloads; the disassembly walk avoids that.
source · deployed bytecode of every scanned contract, opcode-aware walk
EIP-7823 · MODEXP usage vs new bound
Not measurable· Not observable on MonadEIP-7823 caps each MODEXP (`0x…0005`) input-length parameter at 1024 bytes; calls exceeding it now revert. Measuring real exposure would mean counting MODEXP invocations and their input sizes — but MODEXP is a precompile invoked *internally* via CALL from other contracts, essentially never as a top-level transaction (an exhaustive HyperSync scan of the post-MONAD_NINE range found zero top-level calls to `0x…0005`). Internal precompile calls are only visible in execution traces, which Monad does not expose via HyperSync, and `debug_traceBlockByNumber` is rate-limited below the chain's block-production rate. So real usage is not measurable from available data. Context: the EIP author's historical-Ethereum analysis found the largest observed MODEXP input was 513 bytes — well under the 1024-byte cap — so real-world impact is expected to be nil.
source · not measurable — internal precompile calls require traces unavailable on Monad
EIP-7883 · MODEXP gas-cost increase
Not measurableEIP-7883 raises the gas cost for the MODEXP precompile (from `max(200, mc·ic/3)` to `max(500, mc·ic)`, with the multiplier for oversized exponents doubled). The change is a server-side pricing recompute: the same inputs and outputs occur, only the gas debit differs. Transaction receipts cannot distinguish the old regime from the new - they only show the final `gasUsed`. We document the change but do not publish a number.
source · documented only - no measurement
MIP-6 - MONAD_NINE Network Upgrade
MIP-6 is a meta proposal that coordinated the simultaneous activation of MIPs 3, 4, and 5 on Monad mainnet. It introduces no standalone protocol changes; it is the umbrella activation event the substantive MIPs anchor to, and the lower-bound block of every metric on this page.
Activated: 2026-03-19T14:30:00Z, block 62,466,234. No per-MIP measurement.
Data pipeline
Daily snapshots are produced by src/agent/snapshot-mips.ts: it walks new mainnet blocks since the last run via eth_getBlockReceipts, fetches each new contract's bytecode via eth_getCode, fetches the deployment transaction via eth_getTransactionByHash for the initcode dimension, and folds the results into the persistent state at data/snapshots/mip-adoption/state.json. A dated snapshot and latest.json are written for the page and API.
The MIP-4 runtime sampler src/agent/sample-mip4-runtime.ts runs separately (daily, after the snapshot scanner): it traces 25 evenly-spaced windows of 60 blocks each via debug_traceBlockByNumber on the only Monad endpoint exposing trace methods, walks each transaction's call tree, counts CALL frames to the MIP-4 precompile, and updates mip4.runtime.
Every snapshot is exposed via /api/v1/mips as monscope.mip-adoption.v2. The methodology prose ships embedded in the JSON so downstream consumers know what each number means without consulting this page.