ByAUJay
EIP-7623 Migration Guide: Refactoring Contracts to Reduce Calldata Footprint
Understanding EIP-7623: Navigating Calldata Costs Post-Pectra Upgrade
EIP-7623 rolled out with Ethereum's Pectra upgrade on May 7, 2025, and it's definitely making waves when it comes to how we handle transaction pricing, especially for those transactions that come with a lot of calldata. In this guide, we're diving into what’s changed, how to measure your exposure under this new system, and some handy tips to tweak your code for reducing calldata or shifting it over to blobs. Plus, we’ve packed in some code snippets and sizing math to help you out! For more details, check out the official documentation: (eips.ethereum.org).
1) What exactly changed with EIP‑7623?
At a quick look, transactions are now going to be charged based on whichever is higher between two options: (a) the standard gas formula or (b) a new calldata floor that changes depending on how many "tokens" are in your calldata. This proposal is officially live on the mainnet as part of Pectra. Feel free to dive into the details here: (eips.ethereum.org)
- Check out these key constants pulled right from the EIP spec:
- STANDARD_TOKEN_COST = 4
- TOTAL_COST_FLOOR_PER_TOKEN = 10
- tokens_in_calldata = zero_bytes + 4 × nonzero_bytes
- Oh, and there's a fresh rule you should remember:
tx.gasUsed = 21,000 + max( 4 × tokens_in_calldata + execution_gas_used + create_costs, 10 × tokens_in_calldata )
Take a look at this: eips.ethereum.org
- Intuition and threshold:
- The floor kicks in when
execution_gas_usedis less than ( (10^{-4}) \times tokens_in_calldata = 6 \times tokens_in_calldata ). - If your transaction involves a lot of computing compared to the actual data being sent, you’ll stay to the left side (no changes). But, if you’re mostly just sending data (like DA payloads), you’ll bump into that 10/40 gas-per-byte floor--10 for zeros and 40 for non-zeros. You can check out more details here: (eips.ethereum.org)
- The floor kicks in when
- Here's why Ethereum decided to make these updates:
- The main aim was to cap the largest block sizes, open up room for more blobs, and keep things consistent. This connects nicely with EIP‑7691, which increased blob throughput (targeting 6 blobs, with a maximum of 9 per block) during the same Pectra upgrade. (blog.ethereum.org)
- Status and timing:
- Pectra (Prague/Electra) officially launched on the mainnet on May 7, 2025 (epoch 364,032). It comes packed with EIP‑7623 as well as a bunch of other important EIPs. You can explore more about it here: (eips.ethereum.org)
2) Should you act? A quick decision matrix
- Most likely unaffected:
- Everyday user activities such as ERC‑20 transfers, swaps, and NFT mints are pretty safe. In these cases, the execution gas usually ranges from 60k to over 200k, while the calldata is only about 100 bytes. When you think about the 6 × tokens_in_calldata, it’s really minor compared to the execution gas involved, so the floor doesn’t really apply here. (eips.ethereum.org)
- Must act:
- When you're working with workflows that involve sending out big arrays, attachments, batched proofs, or any kind of bulk state via calldata--like airdrop allocations, batched claims, off-chain data anchoring, index updates, content storage, and the like--just remember that these often end up hitting the calldata floor. A smart move is to switch this data over to blobs or, if that's not possible, consider compressing and committing it. You can find more info here: (eips.ethereum.org)
- Strategic context:
- The blob capacity really increased with Pectra (EIP‑7691). Since we haven't seen demand meet that new target just yet, blob fees have been practically zero since Pectra rolled out. This is a great opportunity to transition your DA from calldata to blobs. (eips.ethereum.org)
3) Measure your exposure with one number
The additional gas your transaction needs to set aside because of 7623 is:
floor_gas = 10 × tokens_in_calldata- in this case,
tokens_in_calldata = (#zero_bytes) + 4 × (#nonzero_bytes)
You can definitely figure this out on the client side by checking out the hex payload:
// Node/Browser utility: estimate EIP-7623 floor contribution
export function calldataFloor(hexData: string) {
const bytes = Buffer.from(hexData.replace(/^0x/, ''), 'hex');
let zeros = 0, nonzeros = 0;
for (const b of bytes) (b === 0) ? zeros++ : nonzeros++;
const tokens = zeros + 4 * nonzeros;
return { zeros, nonzeros, tokens, floorGas: 10 * tokens, thresholdExecGas: 6 * tokens };
}
// Example: 68B ERC-20 transfer input (mostly non-zeros)
const ex = calldataFloor("0xa9059cbb000000000000000000000000..."); // truncated
// Compare your measured executionGasUsed vs ex.thresholdExecGas to see if floor applies.
Transactions won't be seen as valid if the gas limit comes in under 21,000 plus the higher value between the intrinsic gas or the floored gas amount. So, don't forget to refresh your off-chain gas estimators with this info. (eips.ethereum.org)
4) Refactor patterns that work now
Pattern A -- Shift data availability to blobs (EIP‑4844)
Best for: L2 sequencers or any setup that needs data to be available for verifiers, but doesn’t have to be accessed in real-time by a contract.
- How it works:
- You can send large payloads as blobs in a type-3 “blob-carrying” transaction. Even though contracts can't peek into the actual contents of the blobs, they can still get the versioned blob hashes with the BLOBHASH opcode and verify KZG proofs through the point-evaluation precompile (0x0A). If you're curious to learn more, take a look here.
- Why now:
- With Pectra’s EIP‑7691 in play, blob throughput has skyrocketed--now targeting 6, with a peak at 9. On top of that, blob fees have dropped to nearly nothing since the upgrade, making blobs a much more budget-friendly option compared to calldata. Check it out here.
- Durability and Ops Notes:
- A quick heads-up: blobs usually hang out for around 18 days on the consensus layer. If you want to keep them for a bit longer, you'll need to set up mirroring to your archival infrastructure. For instance, Blockscout does a great job of indexing blobs, and there are several providers that offer blob APIs. You can check out more info here.
Minimal integration example (on-chain reference):
Understanding On-Chain References: A Simple Guide
Here's a straightforward guide to help you get the hang of on-chain references. We'll take it step by step, so it's easy to follow along.
Prerequisites
Before we jump in, just double-check that you have:
- A good grasp of the basics of blockchain
- A wallet, such as MetaMask
- A bit of test ETH or the cryptocurrency that matches your network
Smart Contract Example
Here’s a simple smart contract you can check out for guidance:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleStorage {
uint256 public storedData;
function set(uint256 x) public {
storedData = x;
}
function get() public view returns (uint256) {
return storedData;
}
}
Deployment Steps
- Set Up Your Environment: For an easy experience, try using Remix IDE. Just head over to Remix.
- Compile the Contract: Grab the code and paste it into a new file. Then, go ahead and compile it to see if there are any errors that pop up.
- Deploy the Contract:
- Go to the "Deploy & Run Transactions" tab.
- Pick "Injected Web3" as your environment (this links up with your wallet).
- Just click the "Deploy" button and confirm the transaction in your wallet.
- Interact with the Contract:
- After you've deployed it, you'll notice some handy options:
setandget. - Go ahead and use the
setfunction to store a value. Then, givegeta try to check out what you just saved!
- After you've deployed it, you'll notice some handy options:
Testing the Contract
Double-check that everything's running smoothly. Feel free to engage with the contract on your selected network to confirm it’s doing what it’s supposed to do.
Here’s a quick overview of some handy commands you might want to use in your go-to JavaScript framework:
const contract = new web3.eth.Contract(abi, contractAddress);
await contract.methods.set(42).send({ from: userAddress });
const value = await contract.methods.get().call();
console.log(value); // Should print 42
Conclusion
And that's it! You've just created a basic integration with an on-chain reference. From here, you can expand and add more sophisticated features as you progress. Enjoy coding!
// Read blob versioned hash at index i and record it
uint256 i = 0;
bytes32 vh;
assembly {
// BLOBHASH opcode (0x49) pushes versioned hash for tx blob at index i
// solidity doesn't expose it yet; inline-asm or prebuilt lib
mstore(0x00, i)
// pseudo: vh = blobhash(i)
}
// store vh; later verify a field element with the KZG point-eval precompile
Design pattern:
When you're dealing with your contract, think about sending versioned hash(es) along with it. Instead of going through the entire payload, just focus on checking the specific field(s) that really matter to you by using the KZG point-evaluation precompile. Trust me, this method is way more efficient! If you want to dive deeper, take a look at the official EIP documentation here: eips.ethereum.org.
Pattern B -- Replace arrays with commitments + per‑user proofs
Best for: airdrops, allowlists, and all sorts of batch distributions.
- Old: send N addresses/amounts in calldata.
- New: instead of that, we just store a Merkle (or KZG) commitment on-chain once. After that, users can send in short proofs one at a time.
- Benefit: this change drops the calldata from O(N) to O(1) for each claim. This is a big win because it helps us avoid that pesky 10/40 floor for batch updates. And if a verifier needs some temporary data availability, you can combine this with blobs too! (eips.ethereum.org)
Pattern C -- Pack calldata tightly and decode in Yul
Best for: scenarios where you can fully manage both the client and the contract, plus the contract really needs to access those values.
- The standard ABI tends to squeeze a bunch of scalars into those 32-byte slots, which can seem pretty inefficient. So, let’s try a smarter approach:
- We can work with a
bytespayload that has fields neatly packed together at the bit level. - After that, we’ll decode it using Yul to keep our computing costs low and save some bytes.
- We can work with a
Take a look at this: if you manage to fit 3 addresses (that’s 20B each) and 2 uint128s (16B each) into just 92B instead of the typical 5×32=160B, you’re saving a significant 68B. Since a lot of those bytes are nonzero, that translates to a drop of about ~4×68=272 tokens. Plus, this also lowers the floor and thresholdExecGas by 2720 and 1632 gas, respectively. Usually, that's enough to slip past the floor on those tricky borderline calls.
function execPacked(bytes calldata p) external {
// Layout: [addrA(20)|addrB(20)|addrC(20)|u128x(16)|u128y(16)]
address a; address b; address c; uint128 x; uint128 y;
assembly {
let ptr := p.offset
a := shr(96, calldataload(ptr)) // first 20B
b := shr(96, calldataload(add(ptr, 20))) // next 20B
c := shr(96, calldataload(add(ptr, 40))) // next 20B
x := shr(128, calldataload(add(ptr, 60))) // next 16B
y := shr(128, calldataload(add(ptr, 76))) // last 16B
}
// ...use a,b,c,x,y...
}
Trade-off: extra compute for decoding vs bytes saved. With EIP 7623, it seems that there are times when spending a bit more on compute can actually save you money in the long run, rather than just sticking with that 10/40 floor. Check it out here: (eips.ethereum.org).
Pattern D -- Aggregate signatures with BLS (EIP‑2537)
Best for: multi-sig attestations, allowlists, or oracle reports that need a bunch of signers to support the same message.
- Ditch those bulky N×65-byte ECDSA signatures and replace them with one sleek 96-byte BLS aggregated signature. Plus, use the shiny new BLS12-381 precompiles (pairing/multi-scalar-mult) to verify it! This switch can really trim down your calldata, making it easier to keep an eye on gas costs (think pairing base cost of 37,700 + 32,600×k). For more details, check it out here: (eips.ethereum.org)
Design note: After Pectra, it’s totally feasible to use BLS at the application layer thanks to batch verification patterns and MSM precompiles.
Pattern E -- On‑chain catalogs and ID indirection
Best for: reusing parameters that pop up in various calls.
- Publish your static configurations just once--think of things like an address list, IPFS CID, or price table--and then simply reference them by their ID in any future calls. This approach swaps a one-time storage cost for lower expenses on repeated calldata. Plus, you can get creative by combining this with CREATE2 deterministic addresses, pulling the addresses from salts instead of sending them out directly.
Pattern F -- Skip base64 and human‑readable encodings
- Base64 bumps up the size of your data by roughly 33%, which means you end up with more nonzero bytes. It’s often a good move to go for compact binary layouts and compression methods tailored to your specific needs, like varints or bit-slicing. According to EIP-7623, when the floor is in play, nonzero bytes actually cost you 4 times more in tokens than zeros.
Pattern G -- Batch/sponsor calls to amortize fixed costs
- Each transaction still requires about 21,000 intrinsic gas. To make the process easier, why not look into smart-account flows like ERC‑4337 or check out EIP‑7702-enabled delegation? These approaches let you batch intent execution, which not only reduces the overhead for each action but also trims down on inputs. And don't forget, the 7623 spec clearly mentions that bundling won’t interfere with block-size goals. (eips.ethereum.org)
5) When blobs are the right answer (and how to wire them)
If your contract doesn’t need to process all that bulk data in one go, using blobs is definitely the way to go:
- When you're ready to post the payload in a blob, just keep these things in mind:
- You'll need one or more blob versioned hashes (you can use BLOBHASH for that),
- Plus, a handful of minimal witnesses or indices that can support that one field you're focusing on (the point-evaluation precompile at 0x0A works great for checking KZG openings). For more info, you can check out the details here.
- Economics:
- With the introduction of Pectra (EIP‑7691), we’re seeing blob capacity ramp up to about 6, and potentially up to 9 blobs per block. When Pectra first launched, blob prices took a nosedive for a while, since the demand didn't quite keep pace with the new capacity targets. This gave blobs a solid advantage over calldata. You can dive deeper into it here.
- Ops:
- Just a quick reminder that blobs stick around in consensus for roughly 18 days. If you need to hang onto them longer, think about mirroring them to your indexers or checking out services that can archive blobs, like Blockscout. You can find more details here.
6) Gas‑limit, estimation, and failure‑proofing under 7623
Wallets and RPCs really need to pay attention to the calldata floor when they’re using eth_estimateGas. If they overlook this, users could run into “out of gas” errors, even if they have plenty of ETH. This change is detailed in the EIP, so make sure your setup--be it your wallet, bundler, or relayer--is in the loop. You can read all about it here: (eips.ethereum.org).
- Minimal safe gasLimit:
- Your gasLimit should be at least 21,000 plus the higher value between intrinsic_gas or 10 times the tokens in calldata.
- Programmatic guardrail (pseudo):
- if (estimatedExecGas + 4×tokens + createCost) is less than (10×tokens), then bump up the gasLimit to meet the minimum requirement.
Just a quick tip: some bundlers used to reject transactions if the gasLimit didn’t meet the minimum amount needed. To avoid any extra mempool action, it’s smart to add a pre-send check using that utility we discussed earlier. You can find more info here: (eips.ethereum.org).
7) Worked examples with numbers
- Example 1: ERC‑20 transfer
- The calldata comes in at about 68 bytes (with most of it being non-zero), which means tokens ≈ 4×68 = 272
- That gives us a thresholdExecGas of 6×272 = 1,632
- Typically, the exec gas hovers around 50k+, so when we look at it, the left side (standard compute pricing) has the upper hand here; no tweaks necessary. (eips.ethereum.org)
- Example 2: Sending a 10 kB nonzero payload to a contract
- tokens ≈ 4×10,240 = 40,960; minimum gas cost = 409,600 gas
- As long as your execution gas stays below 245,760 (which is 6 times the token count), you’ll be stuck paying that minimum. This is precisely what EIP-7623 is all about--it’s a push to either switch to blobs or pack as much as you can into it. Dive deeper here: (eips.ethereum.org)
- Example 3: BLS Aggregate vs ECDSA Bunch
- Alright, let’s break this down. If you’ve got 100 ECDSA signatures crammed into calldata, you’re looking at 100×65 = 6,500 bytes. That’s about 26,000 tokens if you’ve got a lot of non-zero values in there, which is definitely on the tighter side.
- Now, compare that with just one BLS aggregate signature, which only takes up 96 bytes. When it comes to verification, you’ll need to do 2-3 pairings, with precompile costs hitting around 37,700 + 32,600×k, plus a few MSM operations thrown in. Basically, you're swapping out thousands of calldata bytes for just a few hundred thousand compute gas--usually a better deal after the post-7623 updates. Want to dive deeper? Check it out here: (eips.ethereum.org)
8) L2s and rollups: the new default is “blob‑first”
If you’re operating an L2 or a service focused on data delivery, there are a few things you’ll want to keep in mind:
- Let’s really hone in on those type-3 blob transactions for batch data while keeping calldata around for those smaller control parameters.
- After the Pectra update, rollups started grabbing about 20.8% more blobs each day, but they still weren’t maxing out the new target. This led to blob prices plummeting to nearly zero, which is definitely a win for rollup economics (just look at Base for instance). So, moving blobs around isn't just essential after 7623; it’s also the savvy and budget-friendly move. (galaxy.com)
9) Future‑proofing: plan for stricter floors
There's a new draft floating around (EIP-7976) that’s proposing we raise the calldata floor even higher, aiming for 15/60. Sure, things might change before it gets officially rolled out, but it's clear where we're headed: as blob capacity grows, larger data availability (DA) in calldata is going to attract more penalties. It makes sense to start designing now so we can manage a higher floor without having to go through a big, complicated redesign later. You can check it out for more details at (eips.ethereum.org).
10) Implementation checklist (30/60/90 days)
- Week 1-2: Measure and Gate
- Get the instrumentation ready for calldata tokens and set those floor thresholds in CI and pre-send tools.
- Ensure that builds fail if any functions exceed the specified token budget. (eips.ethereum.org)
- Week 3-6: Refactor
- Move DA payloads to blobs and add in BLOBHASH along with point-evaluation proofs.
- Replace those big arrays with commitments; switch to packed calldata and implement Yul decoders on the key paths.
- Integrate BLS aggregation for multi-signature processes wherever it makes sense. (eips.ethereum.org)
- Week 7-12: Toughen up and polish things
- Shake up the gas estimation to account for the calldata floor ahead of time; add some mempool policy checks for good measure.
- Get things rolling on testnets (Holesky/Sepolia) with those blob flows; work on mirroring data for that 18-day blob expiry. (eips.ethereum.org)
11) Executive talking points (for decision‑makers)
- Risk: If you're making data-heavy calls, watch out--there's a new floor cost kicking in (10/40 gas per zero/nonzero byte). This means that transactions not accounting for this cost could end up being invalid. If your team is using DA in calldata, be prepared for increased costs and the possibility of some transactions failing. (eips.ethereum.org)
- Opportunity: Pectra has successfully doubled blob throughput, and blob fees are pretty much negligible at this point. If you shift DA to blobs, you'll not only save on costs but also reduce bandwidth risks, and it keeps you in line with Ethereum’s roadmap. (eips.ethereum.org)
- Action: Let's dive into a quick migration sprint centered around those “blob‑first” and “packed‑calldata” patterns. And, let’s go ahead and approve BLS aggregation where it can seriously cut down on calldata.
12) Reference summary
- EIP‑7623 (Increase calldata cost) -- It's officially live in Pectra! This update establishes a calldata floor of 10/40 for tokens, meaning wallets and RPCs will need to tweak their gas estimation. You can take a look at the details here: (eips.ethereum.org).
- Pectra meta and activation -- Don’t forget to circle May 7, 2025, on your calendars! That’s when the Prague/Electra mainnet is set to go live, and EIP‑7623 will be included alongside other important EIPs. You can check out more details here: (eips.ethereum.org).
- EIP‑7691 (Blob throughput increase) -- We're shooting for 6 blobs, with a cap of 9; this should really amp up our blob market headroom. Check it out: (eips.ethereum.org).
- EIP‑4844 (Blobs, BLOBHASH opcode, point‑evaluation precompile) -- This proposal focuses on leveraging blobs for data availability. Instead of dealing with raw data, contracts will read commitments. If you want to explore the nitty-gritty, check it out here: (eips.ethereum.org).
- EIP‑2537 (BLS12‑381 precompiles) -- This EIP makes it easier to do BLS aggregation in a practical way, which can really help in reducing the size of signature calldata. Want to dive deeper? Check it out here: (eips.ethereum.org).
- Post‑Pectra Blob Market -- Blob prices have plummeted to almost nothing, and we've noticed a solid 20.8% bump in daily blob purchases! This has some interesting effects on node storage, particularly with that 18-day retention period. Check out the details here: (galaxy.com).
- Draft EIP‑7976 -- There’s some buzz about a potential increase in the calldata floor down the line, so it’s worth keeping an eye on this. Stay updated here: (eips.ethereum.org).
13) Brief in‑depth takeaways
- The practical threshold: The floor comes into play when
execution_gas_usedis less than6 × tokens_in_calldata. If your setup usually sends kilobytes of nonzero data through calldata, you’re likely to hit that limit. So, you've got a couple of choices: (a) pack those bytes into blobs, or (b) streamline your inputs and put in a little extra computational work. (eips.ethereum.org) - The architecture shift: Blobs are the new go-to for making canonical data available; calldata should really just focus on the parameters. If your contracts need to pull certain data elements every now and then, they can use KZG openings to verify those without having to load everything all at once. (eips.ethereum.org)
- The crypto assist: Thanks to Pectra’s BLS precompiles, you can now swap out thousands of signature bytes for a single aggregated signature. This means you can really cut down on your calldata usage while keeping your security intact. Check it out here: (eips.ethereum.org)
If you want 7Block Labs to dive into your calldata footprint and whip up a solid refactor plan--like packed ABI, blob wiring, BLS integration, and tightening up those gas limits--we’re here to help! In just two weeks, we can deliver a clear blueprint that outlines specific byte and gas targets for each key path.
Like what you're reading? Let's build together.
Get a free 30-minute consultation with our engineering team.
Related Posts
ByAUJay
EIP 7702, EIP-7691, and EIP-402: The Impact of Pectra and Others on Rollup Design
Ethereum’s Pectra upgrade on May 7, 2025, really turned the tables for rollups and wallets in some exciting and practical ways. To kick things off, EIP‑7691 doubled the target blob throughput and revamped the blob fee dynamics, which is a huge deal. Plus, EIP‑7702 introduced “smart EOAs,” adding even more functionality. And we can’t ignore the emerging x40--it's all pretty mind-blowing!
ByAUJay
Getting to Know EIP-7691: How Pectra Boosts Ethereum's Blob Throughput
EIP-7691, which rolled out with Ethereum’s Pectra hard fork on May 7, 2025, significantly increases the network's blob throughput from a target/max of 3/6 to 6/9. It also adjusts the way blob fees work, allowing prices to fall more rapidly when demand drops below the target. Let’s take a closer look at what this all means!
ByAUJay
Getting EIP-7623 in Action: Upgrading Calldata Pricing and Revamping L2 Data Pipelines
### Description EIP-7623 made its debut with Ethereum’s Prague/Electra (“Pectra”) mainnet upgrade on May 7, 2025, and it's shaking things up by changing how calldata is priced. This upgrade also leads to some significant changes in L2 batch posting and data engineering. In this guide, we’ll unpack the new rules and what they mean for you.

