From b000c2c6fcfac9e191bddff460ce7dcf95fb6f98 Mon Sep 17 00:00:00 2001 From: ygd58 Date: Wed, 23 Sep 2026 13:08:41 +0000 Subject: [PATCH] docs: document Bradbury's per-transaction gas ceiling Contracts above ~20KB of Python source are currently undeployable on TestnetBradbury via any gas value, with no documentation explaining why - eth_estimateGas doesn't warn about it, and the failure ("gas limit too high") gives no revert reason. Root cause, from the community investigation in genlayer-cli#419: Bradbury enforces a fixed 16,777,216 (2^24) gas limit per transaction - a zksync-os runtime chain config value (DEFAULT_MAX_TX_GAS_LIMIT), added for EIP-7825 alignment. eth_estimateGas skips this check (simulation only), so it can return a plausible-looking estimate for a deployment that will actually be rejected at eth_sendRawTransaction. A transaction signed close to the boundary can also be accepted by the RPC and still run out of gas during execution - same ceiling, hit from the other side (confirmed via debug_traceTransaction: an out-of-gas revert five frames deep, no reason string). Added a "Known Limitations" section to the main deploying.mdx overview page, right after the Networks Overview (where Bradbury is already introduced), covering: the exact ceiling, why eth_estimateGas doesn't catch it, the ~730 gas/byte practical size implication (~20KB), workarounds (split into multiple contracts; don't trust estimateGas alone near the boundary), and that this is a runtime config value the chain admin can raise without a fork - not something permanently baked in. Credited the investigation (genlayer-cli#419) rather than presenting this as newly discovered - the binary search, the block-explorer trace back to the exact upgrade transaction that introduced the cap, and the debug_traceTransaction confirmation were multi-person community work I only helped narrow down, not root-caused solo. Verified with the real @mdx-js/mdx compiler. --- .../intelligent-contracts/deploying.mdx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pages/developers/intelligent-contracts/deploying.mdx b/pages/developers/intelligent-contracts/deploying.mdx index b902414b..6e6d109a 100644 --- a/pages/developers/intelligent-contracts/deploying.mdx +++ b/pages/developers/intelligent-contracts/deploying.mdx @@ -73,6 +73,23 @@ Deploy to different networks based on your development stage: [Explore Network Configuration →](./deploying/network-configuration) +## Known Limitations + +### Bradbury: per-transaction gas ceiling (~20KB practical source-size limit) + +TestnetBradbury enforces a **fixed 16,777,216 (2^24) gas limit per transaction** — a `zksync-os` runtime chain config value (`DEFAULT_MAX_TX_GAS_LIMIT`, added for [EIP-7825](https://eips.ethereum.org/EIPS/eip-7825) alignment). This is a hard cap on the transaction itself, not on the block (Bradbury's block gas limit is unaffected). + +`eth_estimateGas` does **not** enforce this cap — simulation skips the check — so an estimate can return a plausible-looking number (e.g. 28–32M) for a deployment that will actually be rejected. The rejection only appears at `eth_sendRawTransaction`, as `gas limit too high`, with no revert reason. If you *do* manage to sign a transaction near the 2^24 boundary, it can be accepted by the RPC but still run out of gas during execution — same ceiling, hit from the other side. + +**Practical impact:** Python Intelligent Contracts need roughly **730 gas per byte of source** to deploy. At a fixed 16,777,216-gas ceiling, that puts source contracts above **roughly 20KB** at risk of being undeployable on Bradbury as currently configured, regardless of what gas limit you request. + +**Workarounds:** +- Split a large contract into multiple smaller contracts, keeping each deploy under the effective size ceiling. +- If you're near the boundary, don't trust `eth_estimateGas` alone — test the actual `eth_sendRawTransaction` at your target gas limit, since simulation won't warn you. +- This is a runtime config value, not something baked into the network by a fork — it can be raised by whoever administers Bradbury's chain config, without requiring a network upgrade. + +This was root-caused through a multi-person community investigation in [genlayer-cli#419](https://github.com/genlayerlabs/genlayer-cli/issues/419), including a full binary search of the boundary and a `debug_traceTransaction`-confirmed out-of-gas trace pinpointing the exact mechanism in `zksync-os`. + ## Development Workflow Follow this recommended progression: