# On-Chain Size Limits & the Glamsterdam Upgrade

ChainRender stores your app *as bytecode on-chain*, so Ethereum's contract-size limit is a real constraint the
architecture is built around — and an upcoming upgrade may relax it. This page explains the current limit, how
ChainRender already handles it, and what Glamsterdam could change.

> **A note on forward-looking content.** Ethereum's roadmap evolves. The specifics below are accurate as of this
> writing but may change — always check the current status of any EIP before relying on it. ChainRender is
> designed so that *none* of these outcomes require it to change; that design is the durable part.

## The current constraint: EIP-170's 24 KiB limit

Since EIP-170, a single contract's deployed bytecode is capped at **24,576 bytes (24 KiB)**. ChainRender stores app
components as bytecode (via **SSTORE2** — cheap, immutable code-backed storage), so this cap bounds how much a
single stored chunk can hold.

This is why ChainRender was architected with two mechanisms from day one:

- **SSTORE2 chunked storage** — large apps are split across multiple code chunks, each within the limit, and
  reassembled at render time.
- **Paginated reads (`IChunkedRender`)** — large *outputs* (a world atlas, a long table) are read in chunks that
  concatenate byte-identically to the whole, so an app can exceed any single-call bound.

The result: **the 24 KiB limit constrains a chunk, not an app.** ChainRender apps are already effectively unbounded
in size through chunking — today, on every chain, unchanged.

## The design that makes upgrades a non-event: the ChainProfile seam

Critically, **no ChainRender contract hardcodes `24576`.** The size ceiling lives in exactly one place — a
`ChainProfile` — and every component reads the ceiling from it (`maxChunkPayload()`, etc.). This is a deliberate
forward-compatibility seam: a chain with a *different* limit just uses a different profile.

Profiles already exist for both today's chains and a larger-limit future:
- `evm-legacy-24k` — the 24,576-byte ceiling (pre-Glamsterdam Ethereum + L2s).
- `evm-glamsterdam-64k` — the 65,536-byte ceiling for a Glamsterdam-enabled chain (EIP-7954).

So when the limit changes, ChainRender doesn't need new code — it needs a different profile at deployment. **The
upgrade is a config choice, not a rewrite.** This is the "no layer hardcodes a current EVM constant" discipline in
action.

## What Glamsterdam could change

**Glamsterdam** is Ethereum's next major upgrade. It is live on Sepolia (since 2026-10-06); its Hoodi activation was
postponed on 2026-10-22 and mainnet has no date. Its
headliner changes are structural (enshrined Proposer-Builder Separation, Block-Level Access Lists for parallel
execution), but two threads matter directly for on-chain apps like ChainRender:

### 1. A larger contract-size limit (EIP-7954)
Scheduled for Glamsterdam is **EIP-7954**, which raises the maximum contract **code** size from **24 KiB to 64 KiB**
(24,576 → 65,536 bytes) and the **initcode** limit from 48 KiB to **128 KiB** (49,152 → 131,072). If it ships, each
SSTORE2 chunk can hold roughly **2.7× as much**, meaning markedly fewer chunks per app and simpler large components.

> **Status (updated 2026-10-23):** Glamsterdam has been **live on Sepolia since 2026-10-06**. On 2026-10-21 a
> 65,535-byte chunk was deployed and byte-checked there, so ChainRender's Sepolia profile is now 64 KiB. Hoodi's
> activation was **postponed on 2026-10-22** (to study EIP-8037's effect on mainnet contracts) and **mainnet is
> unscheduled**. Confirm the live status on [Forkcast](https://forkcast.org/upgrade/glamsterdam) before trusting any date.
>
> **The number, verified against EIP-7954:** the *code* limit rises 24,576 → **65,536 bytes (64 KiB, 0x10000)**, and
> the *initcode* limit 49,152 → **131,072 bytes (128 KiB, 0x20000)**. A stored DataChunk is deployed *code*, so the
> chunk ceiling becomes **64 KiB**. (Earlier drafts and some client work used 0x8000 = 32 KiB; the EIP of record now
> specifies 0x10000. Confirm on the live chain with a near-64 KiB test chunk before relying on it — the doc-101
> runbook does exactly this before raising the chain profile.)

### 2. State-creation repricing (EIP-8037) — this makes deploys ~7× pricier (measured)
Glamsterdam reprices **state creation** (EIP-8037): the cost of *deployed code* rises from ~200 gas/byte to
**~1,530 gas/byte** (the client's `cost_per_state_byte` is fixed at 1530 for Glamsterdam). Measured on Sepolia (October 2026), one stored chunk costs **~208,723 gas plus ~1,558.9 gas per byte**, against
~52,518 + 216.4 before the fork: **about 7.2× per byte.** Because ChainRender stores apps *as code* (SSTORE2), this
hits deploys directly — it is **not** modest, and earlier drafts of this page understated it.

The two size EIPs therefore pull in opposite directions:
- **EIP-7954** (64 KiB code) → *markedly fewer* chunks per app.
- **EIP-8037** (~7.2× per byte, measured) → each byte you deploy is *much* more expensive.

The **net** effect on a given app's deploy cost depends on its size and is a real tradeoff — do not assume the bigger
limit means cheaper deploys. **Benchmark it** with `scripts/compare-deploy-cost.mjs` against the post-fork schedule
before relying on any savings. (Related repricings EIP-7976/EIP-7981 raise calldata-floor and access-list costs,
which also touch deploy transactions; EIP-7778 removes refunds from block-gas accounting.)

### 3. The transaction gas limit now sets the chunk size, not the code-size limit
One chunk is one transaction, and under EIP-8037 a full 64 KiB chunk costs ~101.6M gas (measured). That is more than a
wallet will usually send: a **45,000,000-gas MetaMask transaction is proven on Sepolia**, and Hardhat's local signer
refuses anything above 30,000,000. So each chain's entry in `chains.json` carries a `txGasCap` (Sepolia: 45,000,000)
and its measured `storageGas`, and the visual builder sizes every chunk to fit both: the smaller of the code-size
ceiling and what the gas cap can pay for, after a 20% estimate margin and a 500,000-gas registration reserve. On
Sepolia that is **about 23.6 KB per chunk** — below the 64 KiB code ceiling — and the builder refuses to send a
transaction whose estimate exceeds the cap rather than letting the wallet warn "likely to fail". Raising the cap is a
manifest change, made only after a larger transaction is proven on that chain.

What does **not** change: ChainRender's **render path is a free `view` call** — reads are unaffected by any of
these write/create repricings. The cost story is entirely about *deploying*, never *viewing*.

## What this means for you as a developer

- **Today:** build without worrying about size — chunking handles it, transparently. The limit constrains a chunk,
  not your app.
- **When Glamsterdam ships EIP-7954:** your existing apps keep working unchanged (backward-compatible); new deploys
  on updated chains can use the larger profile for fewer chunks — but each stored byte costs ~7× more (EIP-8037), and
  the per-transaction gas cap limits how big a chunk can be in practice. You change a deployment profile, not your
  code.
- **Rendering stays free forever** — a `view` call — no matter how gas schedules or size limits change. The
  repricings touch deploy/write costs, not reads.

## Cross-chain & cost roadmap — what actually helps (and what doesn't)

It's tempting to look at the flashy "cross-chain" EIPs for cost relief, but for ChainRender's *specific* constraint
— the cost of storing app bytecode on-chain — most of them are irrelevant. Here's the honest ranking, grounded in
what touches ChainRender's storage/deploy cost versus what's generically hyped.

> **Verify status + timing.** The roadmap shifts monthly and dates slip. Treat everything below as "on the radar,"
> and confirm live status on [Forkcast](https://forkcast.org) / the EF roadmap before relying on any of it.

### Tailwinds (genuinely help ChainRender)
- **Blobs + PeerDAS + blob-count increases (EIP-4844, EIP-7691, EIP-7742, PeerDAS).** The biggest lever. Blobs
  already made L2 data 90–99% cheaper; PeerDAS (expected late 2026/early 2027) and higher blob counts keep pushing
  L2 storage cost *down*. **This is why deploying on an L2 is the real cost answer** — see
  [L2 Deployment Strategy](./l2-deployment-strategy.md). The ecosystem is optimizing exactly the cost that dominates
  ChainRender.
- **Larger code limits (EIP-7954, Glamsterdam).** 24→64 KiB (~2.7×) = markedly fewer chunks per app. A real win,
  though (see above) partly offset by EIP-8037's ~10x code-deposit cost.
- **Block-space capacity (BALs, EIP-7928).** Parallel execution + higher future gas limits mean more block-space
  headroom for chunked deploys ecosystem-wide.

### Headwinds (make on-chain storage *more* expensive — watch these)
- **EIP-8037 (state-creation repricing, Glamsterdam).** ~10x on code deposit. Already covered above — the single
  biggest near-term cost change for ChainRender deploys.
- **EIP-8032 (Size-Based Storage Gas Pricing).** Proposed: make `SSTORE` cost scale with a contract's storage size
  to discourage state bloat. Because ChainRender stores apps *as state/code*, this cuts *against* the model if it
  ships. Not scheduled as of writing — but the one to watch, because it's philosophically aimed at exactly what
  ChainRender does (put durable data on-chain). Monitor its status.

### Not relevant to storage cost (don't be misled)
- **ERC-7683 (cross-chain intents), EIP-7702 (smart EOAs / account abstraction), chain abstraction.** These improve
  *user UX across chains* (one signature, gas sponsorship, cross-chain orders). They matter for the **action layer**
  of apps a developer builds *with* ChainRender — but they do **nothing** for ChainRender's storage/deploy cost.
  Useful to know; not a cost fix.

### The strategic conclusion
The highest-leverage cost decision isn't waiting for an EIP — it's **where you deploy today**. L1 storage is 10–1000x
pricier than an L2, and the L2 cost curve is bending down (blobs → PeerDAS). So: **deploy real apps on an L2**, keep
L1 for flagships, watch EIP-8032 as the headwind, and treat Glamsterdam's bigger 64 KiB limit as a real but
EIP-8037-offset help.
The full decision framework is in **[L2 Deployment Strategy](./l2-deployment-strategy.md)**.

## The durable takeaway

The specific numbers and timelines will keep moving — that's the nature of a live protocol roadmap. What's durable
is that **ChainRender abstracts the limit behind a single seam**, so whatever Ethereum settles on, adopting it is a
profile change, not an architectural one. The system was designed to *inherit* protocol improvements without
rework — bigger contracts, cheaper storage, new execution models — as they arrive.

## Related
- **[L2 Deployment Strategy](./l2-deployment-strategy.md)** — where to deploy for lowest cost, the decision framework.
- **[No Hosting: How It Works](./no-hosting.md)** — why on-chain storage, and SSTORE2.
- **[What's Fully On-Chain](./fully-on-chain.md)** — the storage + robustness layer.
- **[Contracts → Architecture](../contracts/architecture.md)** — SSTORE2 + chunked storage in the stack.
