> ## Documentation Index
> Fetch the complete documentation index at: https://monadfoundation-40611fb6-devops-1498-direct-udp-implementat.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Opcode Pricing

## Summary

Monad is a highly optimized system that introduces efficiencies across all dimensions -
compute, state access, and bandwidth utilization. However, the multiplier relative to legacy
EVM systems is not equal across all dimensions. As a result, some opcode gas price
changes are needed so that applications can unlock the full potential of the chain.

To minimize the number of gas price changes, rather than adjusting the gas pricing of almost
all opcodes down, Monad instead adjusts a few opcode prices up. This has the same relative
effect as discounting almost all opcodes.

The following costs are changed:

* [Cold access to state](#cold-access-cost)
* [Storage pages](#storage-pages)
* [A few precompiles](#precompiles)
* [Memory expansion](#memory-expansion)

All other costs are as on Ethereum; [evm.codes](https://www.evm.codes/) is a helpful reference.

<Note>
  These changes are covered formally in the
  [Monad Initial Spec Proposal](https://category-labs.github.io/category-research/monad-initial-spec-proposal.pdf)
</Note>

## Why are changes needed?

The EVM's current pricing model needs adaptation to support a high-performance, low-fee regime.
The pricing model assigns a weight (gas amount) to each opcode based on perceived costliness to
the system, then charges the user only based on the calculated sum of weights. As resource
scarcity changes - and especially in the event of a completely new system - those weightings
must be revised.

The changes described in this page make the minimal set of adjustments to allow Monad to
deliver high performance and low fees, while minimizing disruption to users and protecting
the system against DOS attacks.

## Cold access cost

To account for the relatively higher cost of state reads from disk when compared to computation in the Monad execution client,
the cost for "cold" account and storage access costs changes:

| Access Type | Ethereum      | Monad                  |
| ----------- | ------------- | ---------------------- |
| Account     | 2600          | 10100                  |
| Storage     | 2100 per slot | 8100 per 128-slot page |

The following opcodes are impacted because of the differed gas costs:

* Account access: `BALANCE`, `EXTCODESIZE`, `EXTCODECOPY`, `EXTCODEHASH`, `CALL`, `CALLCODE`,
  `DELEGATECALL`, `STATICCALL`, `SELFDESTRUCT`
* Storage access: `SLOAD`, `SSTORE`

Storage is warmed one page of 128 consecutive slots at a time rather than one slot at a time, so
the cold cost is paid once per page. See [Storage pages](#storage-pages).

<Note>
  Gas costs for warm account access (100 gas) and storage access (100 gas) are the same on Monad as on Ethereum.
</Note>

## Storage pages

Storage slots are grouped into pages of 128 consecutive slots. A slot's page is the slot index
with its lowest 7 bits stripped:

```
page_index = slot >> 7
```

Warmth is tracked per (account, page) for the duration of a transaction: once any slot of a page
has been accessed, every other slot of that page is warm. Warmth propagates into child calls and
back to the caller, and is rolled back when a frame reverts, matching how Ethereum tracks account
and slot access.

Sequentially declared state variables, the fields of a struct, and the elements of an array occupy
consecutive slots and therefore share pages. Each key of a `mapping` still resolves to its own
page, but the struct fields stored under that key share it.

### `SLOAD`

| Case                     | Gas  |
| ------------------------ | ---- |
| First access to the page | 8100 |
| Page already accessed    | 100  |

### `SSTORE`

`SSTORE` charges for page I/O and for state growth. The applicable components are summed:

| Component    | Gas    | Charged                                                    |
| ------------ | ------ | ---------------------------------------------------------- |
| Base         | 100    | On every `SSTORE`                                          |
| Page load    | 8000   | On the first access to the page, whether a read or a write |
| Page write   | 2800   | On the first `SSTORE` to the page that changes a value     |
| State growth | 17,000 | Each time the page's net slot count reaches a new high     |

State growth is counted per page as a high-water mark over the transaction, so creating a slot to
replace one cleared earlier in the same page is not charged for growth. Ethereum's 20,000 gas for
writing a fresh slot and 2900 gas for overwriting an existing one do not apply.

### Cost examples

Costs for consecutive operations on one account within a single transaction:

| Sequence                                                | Before MIP-8 | With MIP-8 |
| ------------------------------------------------------- | ------------ | ---------- |
| `SLOAD` a slot, first access to its page                | 8100         | 8100       |
| `SLOAD` another slot in the same page                   | 8100         | 100        |
| `SSTORE` a fresh slot, first access to its page         | 28,100       | 27,900     |
| `SSTORE` a fresh slot in a page already written         | 28,100       | 17,100     |
| `SSTORE` over a non-zero slot, first access to its page | 11,000       | 10,900     |
| `SSTORE` over a non-zero slot in a page already written | 11,000       | 100        |

An [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930) access list entry warms the whole page
containing the listed key, and `eth_createAccessList` deduplicates storage keys by page.

<Note>
  These changes are activated in the [`MONAD_TEN`](/developer-essentials/changelog#revisions)
  revision, defined in [MIP-8](https://mips.monad.xyz/MIPs/MIP-8). See
  [Releases](/developer-essentials/changelog/releases) for per-network activation timestamps.
</Note>

## Precompiles

A few [precompiles](/developer-essentials/precompiles) have been repriced to accurately reflect their relative costs in execution.

| Precompile   | Address | Ethereum                  | Monad                       | Multiplier |
| ------------ | ------- | ------------------------- | --------------------------- | ---------- |
| `ecRecover`  | `0x01`  | 3000                      | 6000                        | 2          |
| `ecAdd`      | `0x06`  | 150                       | 300                         | 2          |
| `ecMul`      | `0x07`  | 6000                      | 30,000                      | 5          |
| `ecPairing`  | `0x08`  | 45,000 + 34,000 per point | 225,000 + 170,000 per point | 5          |
| `blake2f`    | `0x09`  | $\text{rounds} * 1$       | $\text{rounds} * 2$         | 2          |
| `point eval` | `0x0a`  | 50,000                    | 200,000                     | 4          |

A point is a 192-byte pair of `G1` and `G2` elements, as in
[EIP-1108](https://eips.ethereum.org/EIPS/eip-1108).

## Memory expansion

Memory expansion is priced linearly, and the memory a transaction can use is capped at 8 MB
(8,388,608 bytes).

| Item           | Ethereum                 | Monad                |
| -------------- | ------------------------ | -------------------- |
| Expansion cost | $3w + w^2 / 512$         | $w / 2$              |
| Memory limit   | Bounded by the gas limit | 8 MB per transaction |

where $w$ is the memory size in 32-byte words. Expanding all the way to the 8 MB cap costs 131,072 gas.

Memory is counted cumulatively across call frames: the memory available to a child call is 8 MB
minus the memory already used by the current call and its parents. Memory returns to the pool
once a call returns.

Exceeding the limit halts the call frame exceptionally, consuming all the gas that frame
was given and reverting its state changes. From the caller's perspective this is
indistinguishable from an ordinary out-of-gas.

<Note>
  These changes are activated in the [`MONAD_NINE`](/developer-essentials/changelog/releases#v0-13-0-monad_nine) revision.
</Note>
