Skip to content

EIP-4844 — Proto-Danksharding and Blobs

The previous page landed on an uncomfortable truth: for a rollup, the binding cost is not computing the new state, it is publishing the data so anyone can reconstruct and check it. And before March 2024, rollups had only one place to publish that data — inside ordinary transaction calldata, which every full node stores forever and which competes for the very same gas as every swap, mint, and transfer on Ethereum. A rollup was paying permanent-storage prices for data it only needed to be available for a while.

This page is about the fix Ethereum shipped for exactly that mismatch: EIP-4844, also called proto-danksharding, delivered in the Dencun upgrade on 13 March 2024. It adds a new, purpose-built data resource — the blob — that is cheaper than calldata, priced by its own independent fee market, and, crucially, thrown away after about 18 days. That last property is the whole trick, and it is worth being able to explain from first principles: why is it safe to delete the data a rollup depends on? The short answer, which the rest of this page earns, is that data availability is a deadline, not a filing cabinet — you only need the data to be downloadable long enough for anyone to check it or force their way out, and then it can go.

The problem, stated as a resource mismatch

Section titled “The problem, stated as a resource mismatch”

Recall the two-part job the rollup pattern hands to L1: settlement (hold the state commitment and the rules) and data availability (guarantee the compressed batch was actually published). The DA half is the expensive half, and pre-Dencun it rode on calldata. That is a bad fit on two axes:

what a rollup's data actually needs what calldata actually provides
────────────────────────────────── ───────────────────────────────
available for a bounded window, stored PERMANENTLY by every full
long enough to verify/challenge node, forever (state bloat)
its own supply/demand, isolated from priced in the SAME gas as every
ordinary L1 congestion swap — a busy day taxes rollups
large, opaque byte blocks the EVM fully readable by the EVM at
never needs to execute on ~16 gas/byte, whether you use it or not

Every mismatch on the left is a cost the rollup pays for a guarantee it does not need. It pays for permanent storage when it needs temporary availability. It pays EVM-execution prices for bytes the EVM will never run. And it is exposed to L1 congestion it has nothing to do with. EIP-4844 attacks all three at once by introducing a data type designed around what DA actually requires.

A blob (“binary large object”) is a fixed-size chunk of data — about 128 KiB — that a transaction can carry alongside a block without ever entering the EVM’s readable calldata. Concretely a blob is 4096 field elements of 32 bytes each = 131072 bytes ≈ 128 KiB. A new transaction type, the blob-carrying transaction (type 0x03), references one or more blobs; at launch the protocol targeted 3 blobs per block and capped it at 6 (these targets were raised in later forks — more on that below).

The defining feature is what the EVM can and cannot see:

┌─────────────────────────── a block ───────────────────────────┐
│ │
│ EXECUTION PAYLOAD BLOB SIDECAR │
│ ┌────────────────────┐ ┌──────────────────┐ │
│ │ txs, calldata, │ │ blob 0 (~128 KiB)│ │
│ │ state changes │ │ blob 1 (~128 KiB)│ │
│ │ ← EVM executes │ │ blob 2 (~128 KiB)│ │
│ │ all of this │ │ ← EVM never │ │
│ └─────────┬──────────┘ │ reads the data │ │
│ │ can see only a └────────┬─────────┘ │
│ │ 32-byte KZG *commitment* │ │
│ │ to each blob, via the │ gossiped & │
│ │ BLOBHASH opcode ──────────────────┘ stored by │
│ consensus, │
│ then PRUNED │
└────────────────────────────────────────────────────────────────┘

The EVM gets a 32-byte commitment to each blob (a KZG commitment, exposed to contracts through the new BLOBHASH opcode and to callers as the versioned hash), but never the ~128 KiB of blob bytes themselves. That is deliberate: a rollup’s verifier contract on L1 does not need to read the batch to do its job — it needs to know the batch was published (so challengers or provers can fetch it) and it needs a commitment it can bind a proof to. The commitment gives it exactly that, for 32 bytes instead of 128 KiB of calldata.

Under the hood — the KZG commitment, and why it is not just a hash

Section titled “Under the hood — the KZG commitment, and why it is not just a hash”

Why a KZG commitment rather than a plain keccak256 hash of the blob? Two reasons, and only the second matters for this page.

  • Cheap on-chain binding, today. A rollup proving something about its blob (an optimistic rollup’s fraud proof, a ZK rollup’s validity proof) can open the KZG commitment at a point far more cheaply than re-hashing 128 KiB in the EVM. A precompile (point evaluation, address 0x0A) verifies “at point z, this blob evaluates to y, consistent with commitment C” in a fixed, small amount of gas.
  • It is the on-ramp to sampling, tomorrow. KZG commitments are the mathematical substrate for data-availability sampling — the technique that lets nodes verify a blob was published by downloading a few random pieces rather than the whole thing. Proto-danksharding stores whole blobs today; the commitment scheme is already the one full danksharding will need. That is why 4844 is called “proto”: the expensive scaffolding (the commitment format, the transaction type, the fee market) is in place; only the sampling layer is deferred.

You do not need the polynomial math to use this page’s throughline. Treat the KZG commitment as a 32-byte fingerprint the EVM can cheaply reason about, chosen because it also happens to be exactly what future sampling requires.

Blobs do not compete with ordinary transactions for gas. EIP-4844 gives them a completely separate resource, “blob gas,” with its own EIP-1559-style market. This is the part that most directly cut rollup fees, so it is worth seeing the mechanism, not just the outcome.

Ethereum’s regular fee market has a target block size and a base fee that rises when blocks run above target and falls when they run below, adjusting each block by up to 12.5%. Blob gas is an independent copy of that same machinery, running in parallel:

REGULAR GAS BLOB GAS (new, independent)
─────────── ────────────────────────────
target: ~15M gas/block target: 3 blobs/block (at launch)
max: ~30M gas/block max: 6 blobs/block (at launch)
base_fee ↑ when >target, ↓ below blob_base_fee ↑ when >target, ↓ below
pays for execution + calldata pays ONLY for blob data
─────────── ────────────────────────────
▲ ▲
└── a congested DeFi day spikes ─┐ └── stays cheap unless BLOBS
THIS market … │ themselves are in demand
└── … but no longer drags blob prices with it

Two consequences fall straight out of the diagram:

  1. Rollup data is insulated from L1 execution congestion. When a popular NFT mint spikes the regular base fee, that no longer drags rollup costs up with it, because rollup data now buys blob gas, a different resource with its own supply and demand curve.
  2. Blob supply is elastic and self-pricing. If few rollups are posting, blocks run below the blob target and blob_base_fee decays toward its floor (a minimum of 1 wei per blob gas). Under Dencun’s launch parameters, when demand was light a whole ~128 KiB blob cost a tiny fraction of what the equivalent calldata would have — the single biggest reason a typical rollup transaction got dramatically cheaper the week Dencun shipped.

The pricing update is exponential in the gap from target, exactly mirroring 1559’s design intent: a sustained overshoot makes blobs progressively more expensive (rationing the scarce resource), and a sustained undershoot lets the price fall back down (so quiet periods are cheap). No governance sets the price; supply and demand do, block by block.

The key trick: prune the data after ~18 days

Section titled “The key trick: prune the data after ~18 days”

Here is the property that makes blobs fundamentally cheaper than calldata, and the one worth being able to defend from first principles. Blob data is not stored forever. Consensus nodes keep blobs for a bounded window — about 18 days (a minimum of 4096 epochs, and an epoch is 32 slots × 12 s ≈ 6.4 minutes, so 4096 × 6.4 min ≈ 18.2 days) — and then prune them. After that window, the blob bytes are gone from the protocol; only the tiny 32-byte commitment remains in history.

day 0 ~day 18 forever
──────┬──────────────────────────────────┬──────────────────────────────►
blob posted blobs PRUNED (only the
~128 KiB fully available ~128 KiB discarded 32-byte
to everyone via gossip by consensus nodes commitment
& the beacon P2P network survives)
┌───────── the availability window ────────┐
│ anyone can DOWNLOAD the blob │
│ anyone can VERIFY / CHALLENGE with it │ ← the entire security
│ any user can FORCE-EXIT using it │ job happens in HERE
└──────────────────────────────────────────┘

Why is deleting it safe? Because data availability is a deadline, not a filing cabinet. The DA guarantee a rollup needs is: “for a bounded window, anyone in the world could download this data.” Everything the data is for happens inside that window:

  • Fraud proofs. An optimistic rollup allows a challenge period (on the order of a week) during which anyone can download the batch and prove the sequencer posted an invalid state. The 18-day blob window comfortably covers that period.
  • Reconstruction / self-verification. Any party can re-derive the L2 state by replaying the posted batches — but only while the batches are still downloadable. 18 days is plenty for indexers, watchers, and re-orgs to have pulled the data.
  • Forced exits / escape hatches. A user who fears a censoring sequencer can force a withdrawal directly on L1 using the published data. As long as the data was available long enough for that transaction to land, the escape hatch worked.

Once every one of those has had its chance, the raw bytes have no further job. Keeping them would be pure, permanent cost with zero remaining security value. So the protocol keeps the commitment (a permanent, cheap fingerprint that history can always point to) and discards the payload. That asymmetry — permanent 32-byte commitment, ephemeral 128 KiB body — is the entire economic move.

Note the division of labour this implies: it is not L1’s job to be a rollup’s permanent archive. Anyone who wants the historical blob bytes beyond 18 days (block explorers, the rollup’s own operators, archival services) can store them off-protocol. The protocol only promises the window — long enough that anyone who needed the data had a fair chance to get it. Persisting it beyond that is a service, not a consensus guarantee.

Under the hood — where the commitment lives, and what BLOBHASH sees

Section titled “Under the hood — where the commitment lives, and what BLOBHASH sees”

A blob transaction commits to its blobs in the consensus layer (the beacon block references the KZG commitments), while the execution layer sees only the versioned hashes of those commitments. A contract reads one with the BLOBHASH opcode:

// A rollup's L1 verifier binds its batch to a specific blob it expects.
// BLOBHASH(i) returns the versioned hash of the i-th blob carried by THIS tx,
// or 0 if there is no such blob. It never returns the blob's ~128 KiB body.
function recordBatch(uint256 blobIndex, bytes32 expectedHash) external {
bytes32 vh;
assembly { vh := blobhash(blobIndex) } // 32-byte versioned hash
require(vh != bytes32(0), "no blob at index");
require(vh == expectedHash, "blob mismatch");
// Later, a fraud/validity proof opens this commitment via the
// point-evaluation precompile (0x0A) to prove facts about the batch —
// all in a fixed, small amount of gas, and all WITHOUT reading 128 KiB.
_commitBatch(vh);
}

The contract’s whole relationship to the blob is through the commitment: it binds to it now, and a proof opens it later. Because the commitment is 32 bytes and permanent, none of that machinery breaks when the underlying blob bytes are pruned on day 18 — by then the proof has either been made or the challenge window has closed.

It is easy to over-read the win, so three precise limits:

  • It is not full danksharding. 4844 ships the format (blobs, the type-3 tx, KZG commitments, the blob fee market) but every node still downloads every blob in full. The endgame — danksharding — is to raise the blob count far higher and let nodes verify availability by sampling a few random fragments instead of downloading everything. 4844 is the on-ramp; the sampling layer comes later.
  • It does not make rollups free, or permanently cheap. Blob space is a scarce, market-priced resource. When rollup demand exceeds the blob target, blob fees rise. Cheapness at launch reflected under-subscription, not a subsidy.
  • It does not store rollup data forever. By design. If you build something that assumes L1 will serve you blob bytes after ~18 days, it will break; that assumption is the opposite of what makes blobs cheap.
  • Why does it exist? Because rollups were forced to buy permanent, EVM-readable storage (calldata) to satisfy a need for temporary, unread data availability — a resource mismatch that made L2 fees dominated by L1 storage costs.
  • What problem does it solve? It gives rollups a data type matched to their actual requirement: cheap bytes the EVM never executes, priced in their own market, and pruned after ~18 days — long enough to verify, challenge, or force-exit, then discarded. That double saving (cheaper unit and cheaper guarantee) is what cut typical rollup fees sharply after 13 March 2024.
  • What are the trade-offs? Blob space is scarce (3 target / 6 max at launch, raised later), so fees rise with demand; blobs are unreadable by the EVM (contracts see only a 32-byte commitment); and the data is gone after the window, so anyone needing older bytes must archive them off-protocol.
  • When should I avoid it? When your data must be permanently readable on-chain by contracts (that is still calldata’s job), or when you genuinely need permanent, protocol-guaranteed storage — blobs promise a window, not an archive.
  • What breaks if I remove it? Rollups fall back to paying permanent calldata prices for temporary availability; L2 fees jump back toward pre-Dencun levels; and the roadmap loses its staging ground — the commitment format and fee market that full danksharding’s sampling layer is built on top of.
  1. A blob and equivalent calldata can hold the same bytes. Name the two distinct ways a blob is cheaper, and explain why each one is a saving the rollup actually needs.
  2. The EVM never sees a blob’s ~128 KiB of data — only a 32-byte commitment via BLOBHASH. Why is that enough for an L1 rollup verifier to do its job, and what does the verifier use the commitment for?
  3. Blob data is pruned after ~18 days. Explain from first principles why that is safe — what is the full list of jobs the data must serve, and why do they all fit inside the window?
  4. Blob gas is a separate EIP-1559-style market from regular gas. Walk through what happens to blob_base_fee when (a) almost no rollups are posting and (b) many rollups post through a busy day, and use that to explain why “rollups are cheap now” is a statement about demand, not a permanent fact.
  5. Why is EIP-4844 called proto-danksharding? Identify one thing it ships now and one thing it deliberately defers, and explain how the KZG commitment connects the two.
Show answers
  1. First, a cheaper unit price: blob data buys blob gas, a separate resource whose 1559-style base fee is independent of (and usually far below) the regular gas price rollups paid for calldata. Second, a cheaper guarantee: blobs are pruned after ~18 days rather than stored forever, so the rollup pays for temporary availability instead of permanent storage. Both are savings it needs, because a rollup only requires its data to be downloadable for a window, not readable by the EVM and not kept forever.
  2. The verifier does not need to read the batch — it needs to know the batch was published (so challengers/provers can fetch it) and to have something it can bind a proof to. The 32-byte KZG commitment gives it exactly that: the contract binds its batch to a specific blob via BLOBHASH, and later a fraud or validity proof opens that commitment (via the point-evaluation precompile) to prove facts about the batch — all in a small, fixed amount of gas, without ever loading 128 KiB.
  3. Safe because data availability is a deadline, not a filing cabinet: the data only needs to be downloadable long enough for its jobs to happen. Those jobs are (a) fraud proofs during an optimistic rollup’s ~week-long challenge window; (b) reconstruction/self-verification by anyone replaying batches; and (c) forced exits / escape hatches for users fleeing a censoring sequencer. All fit inside ~18 days, after which the raw bytes have no remaining security value, so the protocol keeps only the permanent 32-byte commitment and discards the payload.
  4. (a) With few rollups posting, blocks run below the blob target, so blob_base_fee decays toward its 1-wei floor — blobs are nearly free. (b) With many rollups posting through a busy day, blocks run at or above the target, so blob_base_fee climbs off the floor and blobs get expensive. Because the price is set by a real supply/demand market against scarce blob space (3 target / 6 max at launch), “rollups are cheap now” describes a moment of low demand, not a permanent subsidy — add more demand and the fee rises.
  5. It ships the full scaffolding now — the blob data type, the type-3 blob-carrying transaction, KZG commitments, and the blob-gas fee market — while every node still downloads every blob. It defers the part that actually scales blob count: data-availability sampling, where nodes verify a blob was published by checking a few random fragments instead of downloading the whole thing. The KZG commitment is the bridge: it is the same commitment scheme that sampling requires, so the format deployed by 4844 is already the one full danksharding builds on — hence “proto.”