Skip to content

EIP-8038 — State-access gas

Status: Ready for the public MCP (not launched). Use the website exploration today.

What became possible

When you SSTORE on Amsterdam, what are you paying for — touching the slot, changing it, or creating it? EIP-8038 splits state-touching costs into touch (load), change (write), and create (new leaf). Cold storage access stays 2,100. The write surcharge on an existing slot is STORAGE_WRITE 10,000 (was about 2,800). Creating a slot is still EIP-8037 state gas (about 97,920). EXTCODESIZE / EXTCODECOPY pay an extra warm read.

The MCP server runs your program. It does not ship demo bytecode.

  • Touch / EXTCODESIZE: Run bytecode — call-frame gasUsed.
  • SSTORE write (change): Run bytecode. Existing-slot cold write is about 5,006 vs 12,106. Seed accounts[].storage on 0x00000000000000000000000000000000000000b1.
  • SSTORE create vs change (paid / state gas): Run transaction with code at to. On Amsterdam, txStateGas is 0 for an existing slot and about 97,920 for a new one. On bytecode, new-slot Amsterdam sets stateGasSpilled 97,920 (gasUsed includes the spill).

What you can ask your agent

Once the public MCP is live (Connect), try prompts like:

  • “Did cold SLOAD get more expensive on Amsterdam?”
  • “Why is EXTCODESIZE more expensive than BALANCE after Amsterdam?”
  • “SSTORE into a slot that already holds a value — Osaka vs Amsterdam, and is there state gas?”
  • “First write to an empty slot on Amsterdam — how much is regular vs state gas?”
  • “If I SSTORE the same value twice, do I pay STORAGE_WRITE twice?”

These are inspiration prompts — curiosity, understanding, or builder checks.

What the server does

StepActionPurpose
1Discover supportConfirm 8038 catalog row; shapes include simulate and transaction
2Run bytecodeSLOAD / EXTCODESIZE / SSTORE program gas on osaka then amsterdam; read gasUsed (and stateGasSpilled on a new slot)
3Run transactionPaid SSTORE code at to when you need txStateGas; seed accounts[].storage for an existing slot

Seed storage (existing slot) on run_bytecode — put slots on the lab execution account:

json
{
  "bytecode": "<your SSTORE program>",
  "accounts": [
    {
      "address": "0x00000000000000000000000000000000000000b1",
      "storage": [{ "slot": "0x03", "value": "0x01" }]
    }
  ],
  "fork": { "baseHardfork": "amsterdam" }
}

For paid txStateGas, use run_transaction with code at to and accounts[].storage on that to. Omit storage for a new empty slot. Repeat with "baseHardfork": "osaka".

Fork caveat

Run the same program twiceosaka (baseline), then amsterdam (preview). Amsterdam already bundles EIP-8038 in EthereumJS v10. Passing eips: [8038] is accepted but is not a pre/post toggle.

Paid gasUsed on a transaction is not a clean 5,006 vs 12,106 — it includes 21,000 intrinsic and EIP-2780 recipient access. Lead with call-frame gasUsed on run_bytecode for the write jump, and txStateGas / stateGasSpilled for create vs change. Cold SLOAD stays 2,103. EXTCODESIZE is about 2,603 vs 3,103.

Twins and spec

Link
Website exploration (interactive textbook)EIP-8038 on feelyourprotocol.org
Canonical specEIP-8038
Coverage indexCoverage

Changelog

EIP-8038 MCP Catalogue Changelog
  1. v0.32026-09-14run_bytecode is a VM message-call — SSTORE program gas in-call; seed storage on the lab execution account; txStateGas still run_transaction.
  2. v0.22026-09-14Named catalog row — SLOAD/EXTCODESIZE via run_bytecode; SSTORE via run_transaction with optional accounts[].storage; txStateGas for create vs change.
  3. v0.12026-09-11Exploration twin — simulate gasUsed already shows the SSTORE write jump; named catalog row follows with the engine module.

Use = end-user reference. Internals = architecture and operations. Each section carries its own micro-changelog.