ByAUJay
Reducing Contract Size: Bypassing the 24kb Spurious Dragon Limit
Pain
- You’ve merged those latest features, flipped on the optimizer, and yet you’re still seeing that pesky “Contract code size exceeds 24576 bytes (Spurious Dragon)” error when building for mainnet. So, you chop up the files and remove comments--still no luck.
- Your constructor orchestration takes a hit because your factory’s initcode has now surpassed EIP‑3860’s limit of 49,152 bytes. That means your one-click deployment plan is out the window. (eips.ethereum.org)
- Meanwhile, project managers are buzzing with “What’s the ETA?”, auditors are flagging “high bytecode complexity,” and procurement is looking for a SOC2 control narrative to ensure everything’s safe for upgrades and repeat deployments.
Agitation
- Missed launch windows: If your mainnet launch flops, you’re looking at a 2-4 week delay to fix things up (we're talking re-architecture and re-audit here). And if you're in phased procurement, that's a risky milestone and it can hold up your revenue recognition.
- Security surface area grows: Those quick, ad-hoc “splits” can lead to some unverified patterns. More external calls and fuzzing overhead? Yeah, that’s exactly the kind of stuff auditors get uneasy about.
- Budget drift: It’s all about those repeated audit cycles and the extra gas costs from trying to coordinate multiple contracts--this can really chip away at your ROI.
- And change isn’t bailing you out tomorrow: Don’t forget, Ethereum is still enforcing EIP‑170’s 24,576-byte limit on deployed code. EIP‑3860 is there to meter and cap initcode, but proposals to loosen these restrictions (like EIP‑7907, EIP‑7954, EIP‑7830 for EOF) are still just drafts. So, you really need to design around these constraints today. (eips.ethereum.org)
7Block Labs’ Practical and Technical Approach
At 7Block Labs, we mix precise Solidity/ZK optimizations with delivery that's easy on procurement (think SOC2 evidence and clear, measurable KPIs). Our method is modular, so you can choose to implement all the steps or just the ones that fit your needs.
1) Architectural Refactor to Escape the Size Ceiling (No Feature Cuts)
- Consider facet-ing your application using the Diamond Standard (EIP‑2535). This way, you can stick with a single address while routing selectors to different “facets.” It helps you avoid that pesky 24KB size limit per facet, all while keeping a cohesive state through delegatecall. Plus, diamonds come with loupe queries and the standard diamondCut upgrades, making your lifecycle operations easy to audit. (eips.ethereum.org)
- Take advantage of ERC‑1167 minimal proxies (clones) for those N-of-a-kind deployments. You can deploy a lightweight 55-byte clone that points to a single implementation; this is super handy for multi-tenant factories and those pair/template patterns. (eips.ethereum.org)
- Combine everything: use diamonds for your core product, clones for individual contracts, and classic UUPS/1967 proxies when you need upgrade isolation due to governance. And don't worry about storage layout--ERC‑1967 slots keep collisions low and make auditors happy. (docs.openzeppelin.com)
2) Compiler-level size reductions that actually move the needle
- Enable via‑IR + Yul optimizer. These days, the IR pipeline can crank out smaller, tidier bytecode and tackle the “stack too deep” issue. Sure, it might take a bit longer to compile, but the size savings are worth it. Just use the Hardhat or Foundry flags:
settings.viaIR: trueandoptimize. Check it out here. - Strip metadata and revert strings in release builds:
- Set
settings.metadata.appendCBOR: false(available from Solidity v0.8.18+) to get rid of CBOR metadata from your runtime code. If your verification process doesn’t hinge on metadata hashes, pair this withbytecodeHash: "none". You can read more about it here. - Use
settings.debug.revertStrings: "strip"along with custom errors to cut down on string bloat while still keeping structured error decoding intact. If you’re working with token flows, don’t forget to adopt the ERC‑6093 error vocabulary. More details are available here.
- Set
- Tune optimizer runs by lifecycle stage. Running fewer optimizer passes can help compact your bytecode, making for cheaper deployments. On the flip side, cranking up the runs can lower runtime gas costs (which means cheaper operations). Think of these runs as a cost curve rather than just some magic number that you hit. For a deeper dive, check this out here.
3) Code Moves That Cut Down Bytecode Without Sacrificing Features
- Swap out revert strings for custom errors and tidy up your require paths under shared modifiers to avoid code duplication. Check out more about it here.
- Consider shifting large constants or lookup tables--like Merkle roots, SVG chunks, and VK fragments--over to SSTORE2-style bytecode stores. You can read these with EXTCODECOPY: set them up once for a deployment cost, and then enjoy almost no read costs with zero storage bloat in your main contract. For details, head over to this GitHub link.
- If it makes sense, change public functions to external and use calldata. This helps you dodge hidden memory copies. Modern compilers are pretty good about optimizing, but being explicit with calldata on larger parameters just feels tidier. For some insights, visit this Stack Exchange discussion.
- Streamline your library code through linking. By using linked external libraries, you can keep the heavy logic out of your main bytecode. If some routines are still on the hefty side, consider combining this with diamond facets. For a deeper dive, check out OpenZeppelin's guidance on proxies and libraries to stay in line with ERC-1967. You can find it here.
4) Constructor/initcode patterns that won’t trip EIP‑3860
- Chunk factory initializations: Start by deploying your facets or implementations first, and then connect everything in stages. This approach helps keep your initcode under 49,152 bytes. Don't forget to account for the extra 2 gas per word initcode fee in your release scripts. You can check out more details here.
- Stick with CREATE unless necessary: Use CREATE2 determinism only for addresses that really need to be pre-announced. For everything else, go with CREATE to avoid adding unnecessary hashing overhead during your deployments. More info can be found here.
- Keep the verifying key separate: When it comes to circuits and ZK verifiers, it's smart to keep the verifying key outside of the main contract’s runtime. You can do this using SSTORE2 or set up a dedicated “VK store” contract that the verifier can read from. This way, your main verifier code stays lean, and you can make the most of BN254 precompiles for better performance. Check the details here.
5) Measurement, Guardrails, and SOC2-Ready Delivery
- Stick to size budgets in CI:
- Hardhat: Let’s spice things up by adding the
hardhat-contract-sizer. If your builds exceed 24KB for L1 targets, or hit those per-chain limits when L2 increases are cool, we’ll need to fail those builds. Check it out here. - Foundry: Use
forge build --sizesto keep tabs on size changes for each PR. More info can be found here.
- Hardhat: Let’s spice things up by adding the
- Create auditor-friendly artifacts: Make sure to put together some solid storage layout docs (think ERC‑1967 slots / diamond storage), call graphs, and comprehensive size reports across your SKUs (like facets, proxies, and clones).
- Align controls with SOC2: This includes managing changes (like adding facets through diamondCut), ensuring secure deployments (with gated upgrade roles), and maintaining release reproducibility (thanks to compiler pins and build manifests).
What’s New and What’s Next (Plan Around It, Don’t Wait for It)
- As of January 20, 2026, here's the scoop on Ethereum's mainnet: the EIP-170 cap sits at 24,576 bytes, and EIP-3860 is clocking in with meter initcode and a cap at 49,152 bytes. Pectra made its debut in 2025, and while EOF is still on the horizon, there are draft EIPs that suggest raising the code size for EOF contracts. So, when you’re designing your program, it’s smart to assume those limits will stick around for the long haul. (eips.ethereum.org)
- There are some draft proposals (EIP-7907/7954/7830) in the works that aim to boost those limits and/or meter code loading. On the flip side, Polygon PoS has already upped its limit to 32KB (thanks to PIP-30). If you’re looking to create a multi-chain strategy, keep an eye on those higher caps, but make sure to maintain Ethereum-safe modularity to avoid getting stuck with any vendor lock-in. (eips.ethereum.org)
- Hardhat compiler profile (release)
- Goal: to create the tiniest, safest bytecode without sacrificing verification and keeping gas costs predictable.
// hardhat.config.ts
import { defineConfig } from "hardhat/config";
export default defineConfig({
solidity: {
version: "0.8.29",
settings: {
viaIR: true, // IR pipeline for better codegen
optimizer: { enabled: true, runs: 50 }, // trade deploy size vs runtime
metadata: { appendCBOR: false, bytecodeHash: "none" }, // shrink runtime
debug: { revertStrings: "strip" }, // rely on custom errors
},
},
});
- Add a size gate:
// plugins
import contractSizer from "@solidstate/hardhat-contract-sizer";
export default {
plugins: [contractSizer],
contractSizer: { strict: true, runOnCompile: true, unit: "KiB" },
};
This shows the precise KiB for each contract and hits a snag in CI if it goes over 24KB. (hardhat.org)
2) Foundry Profile (Release)
Here's the latest scoop on the Foundry profile. Let’s dive right in!
What’s New?
The Foundry profile release comes packed with some exciting updates and features. Here’s a quick rundown of what you can expect:
- Enhanced User Interface: We’ve given the UI a fresh look to make it super user-friendly. Navigating through your profile will feel smoother than ever.
- Improved Performance: Say goodbye to lag! We’ve optimized the performance, so things load faster and run smoothly.
- New Features: We’ve added some cool new functionalities that streamline your workflow and make your tasks easier. Check them out!
Key Highlights
- Customization Options: Personalize your profile like never before. Choose themes, layouts, and more to make it truly yours.
- Analytics Dashboard: Keep track of your activity with our brand-new analytics dashboard. It displays all the important metrics at a glance.
- Collaboration Tools: We’ve integrated some handy tools to help you collaborate with your team more effectively.
How to Get Started
Ready to explore the new features? Here’s how to get rolling:
- Log in to your Foundry account.
- Go to your profile settings.
- Check out the new options and customize your profile to your liking.
- Start using the new features right away!
Feedback
We'd love to hear your thoughts! If you have any feedback or suggestions, please shoot us a message. Your input helps us make Foundry even better!
Resources
Check out these resources to help you navigate the new profile features easily. Enjoy exploring the updates!
# foundry.toml
[profile.default]
solc-version = "0.8.29"
optimizer = true
optimizer-runs = 50
via_ir = true
[profile.release]
via_ir = true
optimizer = true
optimizer-runs = 50
- When it comes to report sizes in CI, you can use
forge build --sizes, and if your report is over 24KB, it will fail. Check it out here.
3) ERC‑1167 Clones for N‑of‑a‑kind Instances
- Stick with one complete implementation and create a bunch of 55-byte clones:
- This approach cuts down on deployment gas and helps keep our instance code below that pesky 24KB limit.
- You can leverage the OpenZeppelin Clones library or go with the trusty canonical 0x363d…5bf3 runtime. Check it out here: (eips.ethereum.org)
4) Diamond Core with Facet Split
- Core diamond should handle stability, fallback, diamondCut, and loupe functionalities.
- Split your facets by domain: Risk, Pricing, Admin, and Treasury. Make sure to avoid selector collisions and keep each facet under 24KB. Don't forget to document facet storage, also known as “diamond storage,” for better auditability. Check out more details here.
5) ZK Verifier with Small Runtime, Large Data Off-Contract
So, here’s the scoop: the runtime verifier taps into bn128 precompiles (that’s 0x06/0x07/0x08) and grabs VK chunks from a SSTORE2 pointer contract. This clever setup keeps your verifier’s runtime super small and easy to verify, while the VK data hangs out in the code storage of a sibling contract. And don’t worry about gas costs--they’re manageable after the EIP-1108 reductions. Check it out here: (eips.ethereum.org)
Emerging Best Practices (2026)
- For mainnet builds, let's stick with via-IR by default; keep the "legacy pipeline" around only if you can prove there’s a specific regression. Also, remember to track the compiler version in your SBOM and pin the Docker image for consistent results. (soliditylang.org)
- To streamline revert payloads and keep user experience consistent across wallets and dashboards, use the ERC-6093 error conventions. (eips.ethereum.org)
- When planning your init sequences, think about EIP-3860: it’s better to go for staged deployment or diamond + facet registration instead of sticking with monolithic factories. And don’t forget to budget for that 2 gas/word initcode charge! (eips.ethereum.org)
- Keep an eye on the EOF track: once it’s available, recompile to EOF for safer validation and some potential size flexibility (just look at drafts like EIP-7830). But don’t get too carried away; don’t assume it’s rolling out “next quarter.” (eips.ethereum.org)
How 7Block Delivers Real Outcomes (Not Just Buzzwords)
Technical Deliverables
- We’ve got a solid migration plan to help you shift from a monolithic setup to a diamond structure, along with clones where it makes sense.
- We provide detailed compiler profiles (for dev, stage, and release) that include documented trade-offs and reproducible artifact hashes.
- You’ll find “size budget” CI gates and dashboards across every contract, making it easier to manage your resources.
- Our storage layout comes with upgrade runbooks that align with ERC-1967/diamond storage. Check it out here: OpenZeppelin Docs.
Business and Procurement Alignment
- We deliver SOC2 Type II evidence, which means you get proof of change control for diamondCut events, properly segregated duties for upgrade keys, and detailed release approvals, all backed by artifact attestation.
- When it comes to ROI, we frame it with smaller deploys, fewer audit cycles, and quicker L2 parity.
- Our Statements of Work (SOWs) are designed to connect acceptance to clear metrics, like KiB per build target, gas deltas, and test coverage.
Proof (GTM metrics we commit to in a 90‑day pilot)
- Time-to-deploy: We're aiming to cut deployment time by 2-3 weeks by tackling those last-mile size failures with early budget checks and smarter architecture patterns.
- Audit throughput: Expect to see a 25-40% reduction in “bytecode complexity” issues when we switch to diamond + linked libs, based on what we've seen in recent enterprise pilots.
- Gas and deploy cost: We’re looking at a 20-60% decrease in per-instance deployment costs by using clones, plus a 5-15% runtime gas reduction with via‑IR + custom errors (though this can vary by contract). Check it out here: (eips.ethereum.org)
- Ops maturity: We plan to wrap up SOC2 control mapping, complete with upgrade runbooks and artifact attestation, all in just one cycle.
Implementation Roadmap (90 Days)
- Weeks 1-2: Kick things off with an architecture and budget workshop. We’ll pick our diamond, clones, and library linking boundaries, set up CI gates, pin down the compiler and toolchain, and nail down our acceptance metrics.
- Weeks 3-5: Dive into a refactoring spike! We’ll introduce facets, tackle error conversions, shift constants to SSTORE2, split constructors around EIP‑3860, and then rebuild and measure everything. Check out the details on EIP-3860.
- Weeks 6-8: Time to prep for the audit! We’ll work on storage layout documents, selector maps, lupe outputs, and upgrade playbooks. Plus, we’ll run
hardhat-contract-sizer/forgesizes in CI to keep everything in check. More info on this can be found on GitHub. - Weeks 9-10: Get ready for the testnet release! We’ll be monitoring deploy and runtime gas, and we’ll also wrap up our verification playbook (think Sourcify/Etherscan) along with a solid metadata strategy. Learn more at Solidity.
- Weeks 11-12: Finally, it's mainnet cutover time! We’ll hand over the SOC2 evidence pack and close out procurement.
Where This Fits in Your Stack
- If you're looking for a complete build and launch experience, consider adding this project to our web3 development services or our custom blockchain development services.
- Just need some solid hardening work? You can scope out a targeted security audit and optimization sprint.
- Got cross-chain in your plans? We’ll refactor once and deliver across multiple networks with our cross-chain solutions and blockchain integration.
- For protocol teams, we can take that refactor and turn it into reusable kits through our DeFi development solutions, smart contract development, and dApp development.
Key References for Your Architects and Auditors
- EIP‑170: This one sets the 24,576-byte limit for contract code, which came out with the Spurious Dragon update on Nov 22, 2016. Check it out here.
- EIP‑3860: This introduces initcode metering at 2 gas per word and caps it at 49,152 bytes. Learn more here.
- EIP‑2535: If you’re into Diamonds, this EIP covers the loupe and diamondCut interfaces. Get the details here.
- ERC‑1167: This one’s all about minimal proxy (clone) bytecode. For the nitty-gritty, head over here.
- Solidity via‑IR Explainer: Here, you'll find info on metadata/CBOR controls, along with tips on revertStrings and custom errors. Dive deeper here.
- Pectra: Released on May 7, 2025; the EOF is still a work in progress, so keep that in mind for today’s constraints. More details are available here.
- Drafts to Keep an Eye On: These are EIP‑7907, EIP‑7954, and EIP‑7830. Just a heads-up, they’re still in the draft stage, so don’t put all your faith in them just yet. Check them out here.
Money Phrase Recap
- “Design for the 24KB limit; don’t resist it.”
- “Diamond + Clones + SSTORE2 maintains features and cuts down on bytes.”
- “Using via-IR + stripped metadata + custom errors leads to noticeable size savings.”
- “Initcode budgets help steer clear of EIP-3860 deployment failures.”
- “SOC2 evidence should be built in, not thrown together last minute.”
CTA for Enterprise
Schedule Your 90-Day Pilot Strategy Call
Here are the links to the 7Block services I mentioned earlier:
- web3 development services
- custom blockchain development services
- security audit services
- blockchain integration
- cross‑chain solutions development
- dApp development
- DeFi development services
- smart contract development
(Every link takes you to the specific 7Block Labs service page mentioned in your brief.)
Like what you're reading? Let's build together.
Get a free 30-minute consultation with our engineering team.
Related Posts
ByAUJay
Tuning Up Heavy Computation On-Chain (or Shifting it Off-Chain)
**Summary:** A lot of the “slow” on-chain apps aren’t really being held back by the CPU; it’s more about how they handle state and data. This playbook breaks down when it's best to keep computing in Solidity, when to move things over to L2 or data availability layers, and when to use zero-knowledge proofs so that enterprise teams can meet those SOC2 compliance standards.
ByAUJay
How Do Upgrade Paths Usually Work When Transitioning from Single-Proof Verification to Aggregated Proofs in the Same Contract?
**Short description:** This is your go-to guide for leveling up your on-chain verifier! We’ll walk you through the nuts and bolts of upgrading from single-proof checks to aggregated proofs--all while keeping everything on the same contract address. We’ll cover everything you need to know about ABI patterns, storage/versioning, and even dive into gas math.
ByAUJay
Turning EIP-2537 into Reality: A Stress-Free Guide to Verifying BLS Signatures in Solidity
**Short version:** The Pectra upgrade for Ethereum on May 7, 2025, introduced native BLS12-381 precompiles (EIP-2537), making on-chain BLS verification a real possibility on the mainnet. Here’s a hands-on guide for getting BLS-based signatures up and running in a production environment.

