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-framegasUsed. - SSTORE write (change): Run bytecode. Existing-slot cold write is about 5,006 vs 12,106. Seed
accounts[].storageon0x00000000000000000000000000000000000000b1. - SSTORE create vs change (paid / state gas): Run transaction with
codeatto. On Amsterdam,txStateGasis 0 for an existing slot and about 97,920 for a new one. On bytecode, new-slot Amsterdam setsstateGasSpilled97,920 (gasUsedincludes 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
| Step | Action | Purpose |
|---|---|---|
| 1 | Discover support | Confirm 8038 catalog row; shapes include simulate and transaction |
| 2 | Run bytecode | SLOAD / EXTCODESIZE / SSTORE program gas on osaka then amsterdam; read gasUsed (and stateGasSpilled on a new slot) |
| 3 | Run transaction | Paid 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:
{
"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 twice — osaka (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 spec | EIP-8038 |
| Coverage index | Coverage |
Changelog
- 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.
- v0.22026-09-14Named catalog row — SLOAD/EXTCODESIZE via run_bytecode; SSTORE via run_transaction with optional accounts[].storage; txStateGas for create vs change.
- v0.12026-09-11Exploration twin — simulate gasUsed already shows the SSTORE write jump; named catalog row follows with the engine module.