You write unchecked { total += amounts[i]; } in a hot loop and your gas bill drops 40%. You know it’s safe: the inputs are bounded, overflow is impossible here. You ship it.
What you may not know is why it works. Solidity 0.8 didn’t eliminate the cost of overflow protection. It made the compiler pay it for you, invisibly, on every single arithmetic operation in every function that handles balances, counters, or token amounts. The unchecked block doesn’t skip a safety check. It removes a 22-byte instruction sequence that the compiler generated whether you asked for it or not.
EIP-8219, proposed by Hubert Ritzdorf of Hegota in March 2026, wants to change the underlying contract. Move overflow detection from compiler output to a single EVM opcode. Compress 22 bytes into 1. Cut 79 gas to 5.1
How safe arithmetic actually works in compiled bytecode
Before Solidity 0.8, you called SafeMath.add(a, b) from OpenZeppelin’s library. The overhead was explicit: a library call, visible in the source, obviously expensive.
Solidity 0.8 changed this by building the check into the compiler. To a developer reading the source, a + b looks free. In the generated bytecode, it is not.
Here is what the Solidity 0.8.33 compiler actually emits for a single unsigned addition:2
DUP2 ; copy b onto stack
ADD ; compute a + b → result
SWAP1 ; rearrange stack: [b, result]
GT ; is b > result? (true means overflow)
PUSH4 <panic> ; push panic selector (error 0x11)
JUMPI ; conditional jump to panic handler
The panic path adds a few more instructions: PUSH1 0x11, PUSH4 Panic.selector, MSTORE, REVERT. Total across the whole pattern: 22 bytes of bytecode, roughly 79 gas, for an arithmetic operation whose actual computation costs 3 gas.
EIP-8219 states the ratio directly: a compiler-checked addition costs approximately 79 gas, a 25x multiplier purely for safety.1
Vyper is more efficient, at roughly 41 gas and 26 bytes for the same pattern. The principle is identical: the overflow check is compiler-generated bytecode, not a protocol primitive.
When you write unchecked { a + b; }, you’re telling the compiler to omit that 22-byte sequence and emit just the bare ADD. The arithmetic is the same. The bytecode surrounding it disappears.
What real EVM execution looks like
The 25x overhead isn’t a niche concern confined to performance-critical loops. It appears on every arithmetic operation in every contract that uses Solidity 0.8’s default mode.
A March 2026 analysis on ethresear.ch instrumented 1,297 Ethereum mainnet blocks (2,092,522 EVM calls, 255,696 transactions) and documented what those calls actually do:3
- 88.9% of calls operate on fewer than 32 stack items. Median stack depth: 8 items.
- 90.3% of calls use less than 1 KiB of memory. Median: 128 bytes.
- 45.5% of transactions have no internal calls.
- Average call depth per transaction: 8.2
The picture that emerges is that typical EVM execution is compact. Contracts doing token transfers, balance updates, and counter increments (bread-and-butter operations on small stacks, limited memory). These are exactly the contracts paying the 22-byte overhead on every arithmetic step.
Every transfer() call. Every _mint(). Every loop accumulating amounts. Each one carries the DUP-ADD-SWAP-GT-PUSH-JUMPI sequence for overflow protection, even when the developer has already reasoned that overflow cannot happen.
EIP-8219: four opcodes that belong in the protocol
EIP-8219 proposes four new EVM opcodes for checked arithmetic:1
| Opcode | Hex | Gas | Operation |
|---|---|---|---|
| SAFEADD | 0x0c | 5 | Unsigned addition; reverts on overflow |
| SAFESUB | 0x0d | 5 | Unsigned subtraction; reverts on underflow |
| SAFEMUL | 0x0e | 7 | Unsigned multiplication; reverts on overflow |
| SAFEDIV | 0x0f | 7 | Unsigned division; reverts on zero divisor |
The opcodes fill slots 0x0c–0x0f immediately after the existing arithmetic group (0x01 ADD through 0x0b SIGNEXTEND). These slots currently decode as INVALID and consume all remaining gas. Assigning them to the SAFE* opcodes is backwards compatible: no existing contract uses them, and the new behavior is strictly better than burning all gas.
On any error condition (overflow, underflow, zero divisor), the opcode executes REVERT(0, 0). The current call frame reverts with empty returndata and does not consume all remaining gas, matching the behavior of Solidity’s built-in panic on arithmetic errors.
The gas pricing follows a straightforward rationale: take the base cost of the existing opcode and add 2 for the comparison and conditional revert. SAFEADD and SAFESUB cost 5 gas (3 base + 2). SAFEMUL and SAFEDIV cost 7 gas (5 base + 2).
Two edge cases: SAFEDIV reverts when the divisor is zero, which differs from the bare DIV opcode that returns 0 for zero divisors, a known footgun. SAFEMUL short-circuits when the first operand is zero, returning 0 immediately without an overflow check, since no multiplication by zero can overflow.
The result:
| Metric | Current Solidity 0.8 | With SAFEADD |
|---|---|---|
| Gas per checked addition | approximately 79 | 5 |
| Bytecode per checked addition | 22 bytes | 1 byte |
| Reduction | , | 93.7% gas, 95.5% bytecode |
Compiler adoption follows the same path as prior opcode additions: compilers target an EVM version flag. When a contract targets the version that includes EIP-8219, the compiler emits SAFEADD instead of the DUP-ADD-SWAP-GT-PUSH-JUMPI sequence. Contracts targeting older EVM versions are unaffected. The existing ADD opcode is unchanged.
Why not flags? The EIP-1051 backstory
This is not the first attempt to move overflow detection into the protocol. EIP-1051, proposed in 2018, introduced CPU-style carry and overflow flags: OFV (0x0c) to check and clear an unsigned overflow flag, SOVF (0x0d) for the signed version.4 After an ADD or MUL exceeded 2^256, the flag would be set; the programmer would check it afterward.
EIP-1051 was never merged. EIP-8219’s analysis explains why the flag model fails:1
First, the flag approach still requires a multi-instruction pattern. You write the arithmetic opcode, then OFV to check the flag, then a conditional jump. Three instructions instead of one. The check is still in the programmer’s code, just in a different form.
Second, the flag is implicit persistent state. If you forget to read it, it carries forward into the next piece of code. This complicates formal verification significantly: the tool must track an additional boolean state machine alongside the stack.
Third, a later clean operation can silently overwrite an earlier error flag before it is read. An overflow in one calculation can become invisible if any subsequent arithmetic completes without issue.
The CPU analogy that motivated EIP-1051 breaks down in this context. x86 and ARM benefit from pipelining and branch prediction: the flag register is effectively free because it is computed in parallel with the arithmetic unit. The EVM has neither. The flag model imports CPU interface conventions without the hardware properties that make those conventions practical.
EIP-8219’s design avoids all of this. Each opcode is fully self-contained: it either returns a result or reverts. No external state. No pattern to write correctly. No way to miss the check.
The broader repricing moment
EIP-8219 lands in a particular context. Ethereum’s Glamsterdam fork, targeting Q3 2026, includes EIP-7904, which was expected to raise gas costs on compute operations that appeared underpriced.5
The final EIP-7904 contains zero changes to gas costs. The reason: EIP-7928’s Block-Level Access Lists changed the execution architecture in ways that affect performance measurement. Operations benchmarked at 100 Mgas/s now meet their target without repricing. As the Ethereum Magicians thread documents, many compute operations are already overpriced relative to their actual cost at that throughput:6
| Operation | Current gas | Measured need | Overpriced by |
|---|---|---|---|
| DIV/SDIV/MOD | 5 | 2 | 60% |
| ADDMOD | 8 | 3 | 62% |
| ECPAIRING_BASE | 45,000 | 8,247 | 82% |
When DIV costs 5 gas and that is already roughly 2.5x its actual computational cost, the 79 gas for a checked addition is especially incoherent. You pay 5 gas for a division and 79 gas for a safe addition. The overhead is not measuring anything real about the EVM’s work , it is a compiler-layer workaround priced at 25x the underlying opcode cost.
EIP-8219 fits the direction Glamsterdam is moving: calibrate costs to what operations actually do, encode safety invariants at the protocol layer, remove compiler-level workarounds that should never have been necessary.
What you see in a transaction trace
In Ethernal’s opcode trace for a Solidity 0.8 ERC-20 token transfer, the checked arithmetic pattern is visible. Around every arithmetic operation, you see a cluster of instructions that aren’t part of the token logic:
DUP2
ADD
SWAP1
GT
PUSH4 0x4e487b71 ; Panic(uint256) selector
JUMPI ; conditional jump to panic handler
These clusters exist around every +, -, and * in the contract. They aren’t business logic. They’re the overflow guard.
After EIP-8219, each cluster collapses to a single SAFEADD step. The trace becomes structurally leaner , the actual logic of the transfer stands out clearly because the boilerplate no longer surrounds it on all sides.
This is useful today without any protocol change. If you trace a contract and see unexpectedly high gas on arithmetic-heavy functions, the DUP-GT-JUMPI pattern shows exactly where the cost is. Understanding why unchecked{} works requires seeing what it removes. A transaction trace shows you precisely that.
Status and what to watch
EIP-8219 is an open PR (#11495) as of mid-2026. It is not scheduled for any hard fork. It needs EIPIP review and All-Core Devs discussion before it can move toward implementation.
Two things could accelerate it. First, EVM Object Format: if EOF lands in a future fork with a structured opcode container, the SAFE* opcodes are a natural addition to that infrastructure. Second, ZK rollups: as ZK proving costs become a meaningful operational expense, the combination of smaller bytecode (95.5% reduction per operation) and lower gas makes the opcode family attractive for high-throughput L2 use cases.
For now, the practical takeaway is simpler. The next time you reach for unchecked{}, you know exactly what you’re removing: a 22-byte, 79-gas sequence of opcodes that exists because the EVM has never had a native checked arithmetic primitive. EIP-8219 argues that it should. The case is hard to argue with.
FAQ
What is EIP-8219?
EIP-8219 is a proposal by Hubert Ritzdorf (Hegota) to add four checked arithmetic opcodes to the EVM: SAFEADD, SAFESUB, SAFEMUL, and SAFEDIV. Each opcode performs the arithmetic operation and reverts if the result would overflow, underflow, or divide by zero. This replaces the 22-byte compiler-generated check pattern that Solidity currently emits for every arithmetic operation.
Why does Solidity 0.8 safe arithmetic cost so much gas?
Solidity 0.8 introduced automatic overflow checking by inserting a multi-instruction sequence around every arithmetic opcode. For addition, the pattern is: DUP2, ADD, SWAP1, GT, PUSH4, JUMPI , six instructions totaling 22 bytes and approximately 79 gas. The underlying ADD opcode costs 3 gas. The other 76 gas is entirely the overhead of the overflow check, which exists as compiler output because the EVM has no native checked arithmetic instruction.
What does SAFEDIV do differently from DIV?
The bare DIV opcode returns 0 when the divisor is zero. SAFEDIV reverts instead. Division-by-zero returning zero is a known footgun in EVM arithmetic, because it silently produces a result that may be arithmetically wrong. SAFEDIV treats zero-division as an error, consistent with how Solidity handles arithmetic panics.
Will EIP-8219 break existing contracts?
No. Opcodes 0x0c–0x0f currently decode as INVALID in the EVM. Assigning new behavior to them does not affect any deployed contract, because no existing contract can legitimately reach those opcodes , doing so would already result in out-of-gas or invalid opcode errors. Contracts compiled for earlier EVM versions continue to use the existing ADD, SUB, MUL, and DIV opcodes unchanged.
Is EIP-8219 scheduled for a hard fork?
As of July 2026, EIP-8219 is an open PR (not yet a numbered EIP) and is not assigned to any hard fork. It has not yet entered the EIPIP review process or appeared on All-Core Devs agenda. Glamsterdam (Q3 2026) is the next scheduled hard fork, and EIP-8219 is not among its EIPs.
References
1. Ritzdorf, Hubert. “EIP-8219: Checked Arithmetic Opcodes.” Ethereum EIPs GitHub, March 2026. https://github.com/ethereum/EIPs/pull/11495/files
2. Trail of Bits / Crytic. “Arithmetic Checks in EVM Bytecode.” building-secure-contracts, 2024. https://github.com/crytic/building-secure-contracts/blob/master/learn_evm/arithmetic-checks.md
3. Zilkworm team. “EVM Stack and Memory Usage Statistics Report.” ethresear.ch, February 2026. https://ethresear.ch/t/evm-stack-and-memory-usage-statistics-report/24209
4. “EIP-1051: Overflow Checking for the EVM.” Ethereum Improvement Proposals, 2018. https://eips.ethereum.org/EIPS/eip-1051
5. “EIP-7904: Compute Gas Cost Increase.” Ethereum Improvement Proposals, 2025. https://eips.ethereum.org/EIPS/eip-7904
6. Various contributors. “Glamsterdam Repricings #3, Mar 4, 2026.” Ethereum Magicians, March 2026. https://ethereum-magicians.org/t/glamsterdam-repricings-3-mar-4-2026/27893
7. Ritzdorf, Hubert. “Hegota Proposal: Checked Arithmetic Opcodes.” Ethereum Magicians, March 2026. https://ethereum-magicians.org/t/hegota-proposal-checked-arithmetic-opcodes/27913