Rex4

Rex4 network upgrade (unstable) — per-call-frame resource budgets, relative gas detention, and new system contracts.

This page is an informative summary of the Rex4 specification. For the full normative definition, see the Rex4 spec in the mega-evm repository.

Rex4 is the current unstable specification and is subject to change before activation.

Summary

Rex4 introduces per-call-frame resource budgets across all four resource dimensions (compute gas, data size, KV updates, and state growth). Before Rex4, resource limits only applied at the transaction level, which meant a single inner call could consume nearly the entire budget and leave parent or sibling calls unable to execute predictably. Per-call-frame budgets give each call frame a bounded share of remaining resources, making nested execution more predictable for contract authors.

Rex4 also shifts gas detention from absolute caps to relative caps, so transactions that access volatile data late in execution are no longer penalized for compute work done before the access. Two new system contractsMegaAccessControl and MegaLimitControl — give contracts runtime control over volatile data access and the ability to query their effective remaining compute gas budget.

Rex4 also introduces a storage gas stipend for value-transferring calls, so that contracts receiving ETH via transfer() or send() can emit events without running out of gas.

Finally, the keyless deploy sandbox now inherits the parent transaction's external environment for dynamic gas pricing and oracle behavior, improving accuracy for contracts deployed via Nick's Method.

What Changed

Per-Call-Frame Resource Budgets

Previous behavior

  • Data size, KV updates, compute gas, and state growth were constrained only by transaction-level limits.

  • An inner call could consume nearly the entire remaining budget.

New behavior

  • The top-level call frame starts with the full transaction budget for each resource dimension.

  • Each inner call frame receives remaining × 98 / 100 of its parent's remaining budget.

  • These per-call-frame budgets are system-enforced and derived automatically from the parent frame's remaining budget. The calling contract cannot directly control them.

  • Only total gas (the standard EVM gas parameter in CALL-like opcodes) remains under direct contract control. The 98/100 forwarding ratio does not apply to total gas, which follows standard EVM semantics.

  • When a call frame exceeds its local budget, it reverts with MegaLimitExceeded(uint8 kind, uint64 limit) (does not halt the transaction).

  • The parent call frame can continue executing after a child call frame reverts due to a call-frame-local limit.

  • Transaction-level exceeds still halt the entire transaction with OutOfGas.

  • Compute gas consumed by reverted child frames still counts toward the transaction's total compute gas usage.

The kind discriminator identifies which resource was exceeded:

kind
Resource

0

Data size

1

KV updates

2

Compute gas

3

State growth

MegaAccessControl System Contract

Address: 0x6342000000000000000000000000000000000004

Previous behavior

  • No runtime mechanism existed to proactively disable volatile data access within a call subtree.

  • Gas detention was purely reactive — it only applied after volatile data was accessed.

New behavior

  • You can disable volatile data access for your call frame and all descendant calls.

  • While disabled, any volatile access (block environment reads, beneficiary-targeted account access including SELFDESTRUCT to the beneficiary, oracle storage reads) reverts immediately with VolatileDataAccessDisabled(uint8 accessType).

  • Blocked volatile access does not update volatile-access tracking and does not tighten gas detention.

  • A descendant call frame cannot re-enable access disabled by an ancestor — attempting to do so reverts with DisabledByParent().

  • The restriction automatically ends when the disabling call frame returns.

  • Calls with non-zero value transfer revert with NonZeroTransfer().

MegaLimitControl System Contract

Address: 0x6342000000000000000000000000000000000005

Previous behavior

  • No dedicated system query returned the effective remaining compute gas.

  • Contracts had no way to determine their actual compute budget under detention and call frame limits.

New behavior

  • You can query your effective remaining compute gas at any point during execution.

  • The returned value equals min(frame_remaining, tx_detained_remaining) at call time.

  • This is a snapshot — the value decreases as execution proceeds.

  • Calls with non-zero value transfer revert with NonZeroTransfer().

Storage Gas Stipend for Value Transfers

Previous behavior

  • The EVM's CALL_STIPEND (2,300 gas) was the only gas available to the callee when receiving ETH via transfer() or send().

  • On standard Ethereum, 2,300 gas is sufficient for a simple LOG event (e.g., LOG1 costs 750 gas).

  • On MegaETH, the 10× storage gas multiplier on LOG opcodes causes even LOG1 to cost 4,500 gas (750 compute + 3,750 storage), exceeding the stipend.

  • Any contract that emits an event in its receive() or fallback() function would revert when called via transfer() or send().

  • Affected contracts include WETH9 (whose withdraw() uses transfer()), Gnosis Safe, and smart contract wallets that emit events on ETH receipt.

New behavior

  • When an internal CALL or CALLCODE transfers value (value > 0), the callee receives an additional storage gas stipend of 23,000 gas on top of the standard CALL_STIPEND (2,300).

  • The callee's total gas becomes: forwarded_gas + CALL_STIPEND (2,300) + STORAGE_CALL_STIPEND (23,000).

  • The callee's compute gas limit remains at the original level (forwarded_gas + CALL_STIPEND), so the extra gas can only be consumed by storage gas operations (the 10× LOG topic/data costs).

  • On return, unused storage gas stipend is burned — it is never returned to the caller. The burn-on-return rule extends to all frame termination paths, including early termination from resource limit violations. When a transaction-level resource limit is exceeded during a stipend-bearing frame, the rescued gas (refunded to the sender) excludes the stipend amount.

  • Top-level transaction calls, DELEGATECALL, STATICCALL, and system contract interceptions do not receive the stipend.

  • The compute gas cap ensures the callee cannot perform state-modifying operations (SSTORE, CALL with value, CREATE) with the extra gas, preserving the reentrancy protection properties of the original CALL_STIPEND.

Event type
Compute gas
Storage gas
Total gas
Fits in 25,300?

LOG1 (1 topic, 0 bytes)

750

3,750

4,500

LOG2 (SafeReceived)

1,125

7,500

8,625

LOG3 (Transfer)

1,500

11,250

12,750

LOG4 + 32 bytes data

~2,075

17,560

~19,635

LOG4 + 64 bytes data

~2,387

20,120

~22,507

Relative Gas Detention Cap

Previous behavior

  • Gas detention applied an absolute cap per volatile-access category.

  • If a transaction had already consumed more compute gas than the cap before accessing volatile data, execution halted immediately.

New behavior

  • The effective detained limit is current_usage + cap at the time of volatile access.

  • Execution continues up to min(tx_compute_limit, effective_detained_limit).

  • Across multiple volatile accesses, the most restrictive effective limit applies.

  • Transactions that access volatile data late in execution can still use the full cap amount of compute gas after the access.

Keyless Deploy Sandbox Environment Inheritance

Previous behavior

  • The keyless deploy sandbox used fixed 1× pricing for all storage-related operations.

  • Oracle hints emitted during sandbox execution were not forwarded to the parent context.

New behavior

  • The sandbox inherits the parent transaction's external environment for dynamic gas pricing (SALT bucket multipliers) and oracle behavior.

  • Oracle hints emitted during sandbox execution are forwarded to the parent context.

  • The sandbox maintains its own isolated cache to prevent pollution of the parent's state.

  • Pre-Rex4 specs retain the prior sandbox behavior.

Developer Impact

Contract authors writing nested call patterns should be aware that each inner call frame now receives at most 98% of the parent's remaining budget for compute gas, data size, KV updates, and state growth. These budgets are system-enforced and cannot be overridden by the calling contract — only total gas (via the gas parameter in CALL-like opcodes) remains under direct contract control. If your contract makes deeply nested calls, the innermost call frames will have progressively smaller resource budgets. Design your call depth and resource usage accordingly.

Contracts that catch reverts from inner calls can now decode MegaLimitExceeded(uint8 kind, uint64 limit) from the revert data to determine whether a child call failed due to a call-frame-local resource limit. You can use this to implement fallback logic or graceful degradation.

Contracts that want to avoid gas detention can use MegaAccessControl.disableVolatileDataAccess() at the start of a call to guarantee that no descendant will trigger detention. Any accidental volatile access in the subtree will revert immediately rather than silently tightening your gas budget. This is useful for library contracts or aggregators that call untrusted code.

Contracts that need to know their effective compute budget can call MegaLimitControl.remainingComputeGas() to get a runtime snapshot. This accounts for both call-frame-level budgets and detention, giving you a single reliable number for gas-aware logic.

Contracts receiving ETH via transfer() or send() can now safely emit events in their receive() or fallback() functions. The storage gas stipend provides enough gas for LOG operations with the 10× storage gas multiplier. No changes are needed to existing contracts — this fix is transparent to both senders and receivers.

Deployers using keyless deployment will see more accurate gas costs in Rex4 because the sandbox now uses the same dynamic pricing as the parent transaction. If you previously needed extra gas headroom for keyless deploys, you may be able to reduce your gasLimitOverride.

Safety and Compatibility

All pre-Rex4 behavior is unchanged. Contracts deployed and running on Rex3 or earlier specs continue to execute with the same semantics.

Call-frame-local resource exceeds revert the call frame — they do not halt the transaction. Gas is returned to the parent, and the parent can continue. This is different from transaction-level exceeds, which halt the entire transaction with OutOfGas.

Compute gas consumed by reverted child frames still counts toward the transaction's total. This is consistent with how compute gas has always worked (CPU cycles cannot be undone).

The detained compute gas limit is monotonically non-increasing across a transaction. Once volatile data is accessed, no subsequent operation can raise the detained limit.

MegaAccessControl and MegaLimitControl intercept CALL and STATICCALL only. DELEGATECALL and CALLCODE to these addresses are not intercepted and fall through to on-chain bytecode, which reverts with NotIntercepted().

The storage gas stipend is burned on return — the caller never recovers the unused portion. This prevents contracts from exploiting value-transferring calls to generate free gas.

References

Last updated