7Block Labs
Blockchain Development

ByAUJay

web3 contract development service: Writing Specs That Prevent Audit Ping-Pong


Why audit ping‑pong happens (and how to kill it)

Ending the Audit "Ping-Pong"

Audit “ping-pong” is that frustrating back-and-forth where you spend weeks going over unclear requirements, misunderstanding threat models, and trying to keep things consistent. The best way to put a stop to this cycle is to give auditors a clear spec that:

  • encodes intent in a way that’s testable (no lengthy prose here),
  • aligns with the current chain semantics and toolchain, and
  • comes equipped with tests you can reproduce and simple upgrade procedures.

Here’s a solid spec blueprint that’s been tried and tested, perfectly lined up with the changes for 2024-2025 that teams usually overlook.


What changed in 2024-2025 that your spec must reflect

  • Blobs and blob fees are here and bigger than ever! We’ve got EIP‑4844 rolling out blob transactions, and Dencun officially hit the mainnet on March 13, 2024. Plus, Pectra (May 7, 2025) boosted blob throughput (aiming for 6, with a max of 9 blobs) and improved how fees respond to demand. Oh, and let’s not forget, calldata now has a floor price for those data-heavy transactions thanks to EIP‑7623. Make sure your gas/DA assumptions, fee formulas, and rollup settlement specs reflect all these changes. (blog.ethereum.org)
  • Solidity is getting some new defaults and features. With Solidity 0.8.30, the default EVM version is now “prague” (thanks, Pectra!). This comes right after 0.8.29, which introduced the experimental EOF support and custom storage layouts. It’s important to specify which compiler/EVM versions you’re using and to clearly state how you’re handling EOF in your specs. (soliditylang.org)
  • When it comes to upgradeability and storage layout, we’re seeing some safer patterns emerging. With namespaced storage (ERC‑7201) and compiler support from version 0.8.20, we can avoid those pesky collisions across facets and modules. Be sure to reference the annotation in both your code and specs. (eips.ethereum.org)
  • Account abstraction (AA) keeps getting better. ERC‑4337 has gone mainstream, and with it, validation rules and proposals for native AA (like RIP‑7560 and EIP‑7702 “set code for EOAs”) are shaping how we think about wallets and signatures. Make it clear in your specs which path you're backing. (docs.erc4337.io)
  • There have been some updates to opcode semantics. The behavior of SELFDESTRUCT has changed (thanks to EIP‑6780), and we now have transient storage with EIP‑1153’s TLOAD/TSTORE. This means some of those “old patterns” you used to rely on may no longer work. Be sure your specs disallow relying on legacy destruct semantics and set some limits on transient-storage usage. (eips.ethereum.org)
  • And finally, BLS12‑381 precompiles (EIP‑2537) are now part of Pectra. If you're verifying BLS signatures on L1, make sure your specs consider these precompiles and their gas costs. (eips.ethereum.org)

The 7Block Labs audit‑ready spec template

Copy these sections into your internal PRD. Each line helps avoid a usual audit stall.

1) Problem Statement and Non-Goals

  • Let’s nail down the basic business objective while also clarifying what’s off the table. For example, we’re not looking at “cross-chain minting v1” right now.

2) Canonical External References

  • Here’s a rundown of the exact standards we’re implementing: ERC‑20, ERC‑721, ERC‑6909, ERC‑4337, ERC‑2612, and so on. You can find further details and any differences from the originals through the links below. Check it out! (eips.ethereum.org)

3) Chain, EVM, Compiler Matrix

  • For instance: “Mainnet, EVM=prague, Solidity 0.8.30; no EOF bytecode in v1.” Don’t forget to mention any Layer 2 solutions and any differences! Check out the details here: (soliditylang.org)

4) Threat Model (SCSVS + EthTrust Mapping)

  • Take the time to map out risks to your requirements using SCSVS v2 and EthTrust v3 IDs. If you're okay with some residual risks, don’t forget to keep an exceptions register handy! Check it out here: github.com

5) Roles, Auth, and Upgrade Governance

  • We’re all about that owner/admin/signer setup, complete with timelocks, Safe multisig thresholds, and a plan for emergencies. Let’s break down the upgrade flow too--whether we're going UUPS, Transparent, or Beacon; and we’ll clarify who’s signing what, which Safe is involved, and what kind of delay we’re talking about. Don’t forget to check out the Defender/Upgrades plugin for more insights! You can find all the details here.

6) Storage Layout and Upgrade Rules

  • Clearly state the ERC‑7201 namespaces you’re using, along with the base slots, and make sure to include the “no reordering/no shrinking” rules. Also, it's essential to commit to validating your storage layout in CI for every PR. Check out more details at (eips.ethereum.org).

7) Invariants (machine‑checkable)

  • Set these up as properties you’ll run tests on using Foundry invariants or Echidna. Think about including math assertions (like supply conservation) and safety rules (for example, “no external call before state write” except for X). Check out more details at learnblockchain.cn.

8) Economic and Fee Assumptions

  • If you're using calldata, take a look at how the EIP‑7623 floors can impact your expenses. If blobs are more your thing, outline your blob budget and any failover strategies you've got in place. And if you're tapping into blobbasefee on-chain, be sure to clarify how you're planning to use it. (eips.ethereum.org)

9) Event Model and Off-Chain Integration

  • Every time a state changes, it kicks off an event. Make sure to define the names and arguments for these events, and keep in mind that they should handle idempotent replays.

10) Testing and CI Hooks

  • Make sure to incorporate Foundry commands, tweak those fuzz parameters, replay any counterexamples you find, and don’t forget about static analysis using Slither. Also, keep an eye on your coverage targets! You can find more details over at getfoundry.sh.

11) Deployment and Migration Plan

  • Make sure to have scripts ready, run some dry‑run networks, and outline your rollback criteria. If the system is upgradeable, don’t forget to add oz‑upgrades validation steps. Check out the details here.

12) Observability and On-Call

  • Key metrics and events to keep an eye on
  • Alert thresholds you should set
  • How to pause and unpause runbooks

Make your spec machine‑checkable: examples you can copy

Here are some handy spec snippets along with code/test scaffolds that auditors can easily run without needing to interpret them.

A. Upgradeable contract with namespaced storage (UUPS + ERC‑7201)

Spec Fragment

  • Pattern: We're using UUPS through the ERC1967Proxy. Upgrades can only be done by the UpgradeAdmin multisig via _authorizeUpgrade.
  • Storage: It's namespaced thanks to ERC‑7201. We’re keeping things tidy with no variable reordering, and new fields will get added at the end while we reserve gaps.
  • CI: Every PR will trigger OpenZeppelin's storage layout validation, and any incompatible ones will be rejected.
  • Rollback: For rollbacks, let's go with Defender's proposeUpgrade; we’ll need 2/3 of the multisig and a 48-hour timelock. (docs.openzeppelin.com)

Code Stub

A code stub is basically a placeholder in your code that represents a piece of functionality that you haven’t fully implemented yet. It’s super useful during the development phase when you want to test parts of your application without having everything in place.

Why Use Code Stubs?

Here are a few reasons why code stubs can be handy:

  • Facilitates Testing: You can test individual components even if other parts of the system aren’t ready.
  • Improves Collaboration: Team members can work on different parts of a project simultaneously.
  • Simplifies Debugging: You can narrow down issues without having to wade through the entire application.

How to Create a Code Stub

Creating a code stub is pretty straightforward. Here’s a quick example in Python:

def my_function():
    pass  # This is a stub for future implementation

In this example, my_function doesn’t do anything yet, but it’s set up for when you’re ready to add functionality.

Best Practices

  • Keep It Simple: Don’t overcomplicate your stubs. They should be easy to understand.
  • Document Your Intentions: Add comments to explain what you plan to do with the stub later on.
  • Stay Organized: Keep all your stubs documented in your project so you don’t lose track of them.

Conclusion

Using code stubs can make your development process smoother and more efficient. They allow you to focus on building your application piece by piece while keeping everything neatly organized. So, next time you hit a roadblock, consider throwing in a stub and keep moving forward!

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

// @custom:storage-location erc7201:MyApp.Storage.V1
struct MyStorageV1 {
    uint128 feeBps;
    address treasury;
    uint256[46] __gap;
}

// Minimal UUPS pattern (OpenZeppelin Contracts Upgradeable recommended for prod)
abstract contract UUPSLike {
    function _authorizeUpgrade(address) internal virtual;
}

contract MyModule is UUPSLike {
    // keccak256(keccak256("MyApp.Storage.V1") - 1) & ~bytes32(uint256(0xff))
    bytes32 private constant SLOT = 0x...; // compute per EIP‑7201

    function _s() internal pure returns (MyStorageV1 storage $) {
        assembly { $.slot := SLOT }
    }

    function setFee(uint128 bps) external {
        require(bps <= 1000, "fee too high");
        _s().feeBps = bps;
    }

    function _authorizeUpgrade(address) internal override {
        require(msg.sender == 0xMultiSig..., "not admin");
    }
}

CI Snippet (Foundry + oz-upgrades)

Here's a quick breakdown of using Foundry with OpenZeppelin upgrades. This should get you started with setting up your continuous integration for smart contracts.

Getting Started

Make sure you have the necessary packages installed. You'll need Foundry and OpenZeppelin upgrades. If you haven't set them up yet, here's what you should do:

forge install OpenZeppelin/openzeppelin-contracts-upgradeable

Configuration

Once you've installed the necessary packages, the next step is to configure your project. Just create or update your foundry.toml file with the following settings:

[profile.default]
compiler = "remix"

[profile.default.build]
libraries = { 'openzeppelin-solidity': '0.8.0' }

Writing Your Contracts

Now, let’s write a simple contract that utilizes OpenZeppelin’s upgradeable contracts. Here’s an example of a basic contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

contract MyContract is Initializable {
    uint256 public myValue;

    function initialize(uint256 value) public initializer {
        myValue = value;
    }

    function updateValue(uint256 newValue) public {
        myValue = newValue;
    }
}

Running Tests

To ensure everything is working smoothly, you can run your tests with the following command:

forge test

If you need to specify a specific file for testing, you can use:

forge test --file path/to/your/test_file.sol

Continuous Integration Setup

For a seamless CI experience, consider setting up GitHub Actions. Here’s a basic example of a workflow file that you can use:

name: CI

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up Foundry
        run: curl -L https://foundry.paradigm.xyz | bash

      - name: Install dependencies
        run: forge install

      - name: Run tests
        run: forge test

Additional Resources

That’s it! You’re all set to integrate Foundry with OpenZeppelin upgrades in your CI pipeline. Happy coding!

# foundry.toml
[profile.default]
ffi = true
ast = true
build_info = true
extra_output = ["storageLayout"]
# Validate storage layout compatibility on PR
npx oz-upgrades validate --build-info ./out/build-info --contracts src/**/*.sol

Why auditors dig this: it lays down the storage rules (7201) and shows that you’re doing the same validation they will be doing. Check it out here: (eips.ethereum.org)


B. ERC‑6909 “minimal multi‑token” instead of ERC‑1155

Spec Fragment

  • Standard: ERC‑6909. We’re using a hybrid operator/approval model without callbacks.
  • Invariants:
    • For every id, the total of balances[id] should equal totalSupply[id].
    • Operators can’t transfer more than what’s allowed for (owner,id).
    • Minting and burning can only be done through the MINTER_ROLE.
  • Events: We’ll track Transfer and Approval for each id.

Rationale

ERC‑6909 simplifies things, reducing the complexity that can lead to audit headaches with 1155 callbacks. It’s a great idea to incorporate these invariants as Foundry tests. Check out more about it here: eips.ethereum.org.


C. Permits in 2025: pick ERC‑2612 vs. Permit2 and document risks

Spec Fragment

  • For tokens you control: Implement ERC‑2612 exactly as specified; don’t forget to include the EIP‑712 domain separator details and nonces.
  • When dealing with arbitrary tokens: Go with Uniswap’s Permit2 (address 0x000000000022D473030F116dDEE9F6B43aC78BA3) for a smoother user experience. Just make sure to outline the risks of signature phishing and approval scopes in both the spec and UI copy.
  • Tests: Ensure that both EOA secp256k1 signatures and ERC‑1271 contract signatures can pass when they apply. (eips.ethereum.org)

Why auditors appreciate this: it links your authorization surface to a standard, making you clearly define signature formats and implement replay protections.


D. Account Abstraction (4337) with future‑proofing

Spec Fragment

  • Current Path: We're currently on ERC‑4337 with EntryPoint v0.x, which means we can validate UserOperations according to the ERC‑7562 rules. The state acceptance criteria we’re looking at are simulation determinism, maximum verification gas, and some anti-grief constraints.
  • Future Path: Keep an eye on the implications of EIP‑7702 and RIP‑7560. If we're planning to upgrade to native Account Abstraction (AA), we’ll need a migration doc and a plan to deprecate the entry point. For more details, check out the official docs.

E. Dencun/Pectra fee semantics baked into acceptance criteria

Spec Fragment

  • When estimating contracts for blob versus calldata path on-chain, make sure to:

    • utilize block.blobbasefee wherever it's relevant,
    • consider the calldata floor through EIP‑7623,
    • deny operations if the DA cost goes over a governance cap (be sure to specify the cap and its unit).
  • Include a post-upgrade playbook to tweak DA caps after EIP‑7691 changes the fee dynamics. (eips.ethereum.org)

Turn invariants into code the auditor can run

Foundry turns your specifications into something you can actually run. Each property below is clearly marked as either “green or red,” so there's no room for negotiation here--just straightforward details.

Core Foundry Config

Configuring Core Foundry can feel a bit daunting, but don't worry! We’re here to simplify things for you. Below are the essential steps and necessary information to get your Core Foundry environment up and running smoothly.

1. Installation

First things first, you need to install Core Foundry. You can grab the latest version from the official Core Foundry GitHub repository. Just clone the repo like this:

git clone https://github.com/core-foundry/core-foundry.git

2. Configuration File

Once you have Core Foundry installed, the next step is to tweak the configuration file. This file is key for setting up preferences and defining specific parameters for your project.

Example Config

Here's a sample configuration to get you started:

{
  "projectName": "YourProjectName",
  "version": "1.0.0",
  "settings": {
    "theme": "default",
    "enableAnalytics": true
  }
}

Make sure to replace "YourProjectName" with the actual name of your project!

Configuration Options

There are a few other options you might want to customize in your config file:

  • theme: Change the theme to suit your taste. Choose from options like default, dark, or any custom themes you've added.
  • enableAnalytics: Set this to true if you want to track user behavior.
  • maxItems: Set a limit for the number of items in your lists or databases.

3. Environment Variables

Don't forget about environment variables! They're crucial for configuring your application without hardcoding values into your configuration files. Here’s how you can set them up:

export API_KEY="your_api_key_here"
export DATABASE_URL="your_database_url_here"

Remember to replace the placeholders with your actual API key and database URL.

4. Running the Application

After you've got everything set up, it’s time to run the application. You can do this using:

npm start

This will boot up Core Foundry, and you should see everything coming together.

5. Troubleshooting

If you bump into any issues, here are a few tips:

  • Double-check your configuration file for any typos.
  • Review the console for any error messages that can give you a clue about what’s going wrong.
  • Check the documentation for more detailed help.

Conclusion

And that’s a wrap! You've now got the basics of configuring Core Foundry down. Remember, the more you play around with it, the more comfortable you’ll become. Happy coding!

# foundry.toml
[profile.default]
fuzz = { runs = 1000 }
invariant = { runs = 128, depth = 128 }
ffi = true
ast = true
build_info = true
extra_output = ["storageLayout"]

Property Examples

When thinking about property, it's all about the types and how they can fit into your life or investment goals. Here are some classic categories to consider:

Residential Property

This is where people live, and it includes:

  • Single-Family Homes: Perfect for families looking for their own space.
  • Condos: Great for those who want a low-maintenance lifestyle, often with shared amenities.
  • Multi-Family Units: Ideal for investors looking to rent out apartments or duplexes.

Commercial Property

These places are all about business. Think of:

  • Office Buildings: Where the 9-to-5 magic happens.
  • Retail Spaces: Stores and shops, perfect for brick-and-mortar sales.
  • Industrial Properties: Warehouses and factories that support production and logistics.

Land

Sometimes, it's all about the ground beneath your feet. You can find:

  • Undeveloped Land: Raw land that’s just waiting for the right idea.
  • Agricultural Land: Perfect for farming or ranching ventures.
  • Recreational Land: Great for camping, fishing, or just getting away from it all.

Investment Property

For those looking to cash in, check out:

  • Rental Properties: Buy a home or apartment to rent out for steady income.
  • Real Estate Investment Trusts (REITs): A way to invest in real estate without actually buying property.
  • Fix-and-Flip: Buy properties, make improvements, and sell them for a profit.

Vacation Property

Who doesn’t love a getaway? Think about:

  • Beach Houses: A perfect spot for summer fun or rental income.
  • Cabins: Ideal for cozy retreats in nature.
  • Timeshares: Share a vacation property with others and enjoy it part of the year.

Special Purpose Property

These properties have unique uses, like:

  • Churches: Spaces for worship and community gatherings.
  • Schools: Educational buildings that serve various ages.
  • Storage Units: Renting out space for people to store their stuff.

No matter which type of property you’re into, doing your research and knowing what you're getting into is key!

// Supply conservation for ERC-6909
function invariant_totalSupplyMatchesBalances(uint256 id) public {
    uint256 sum;
    address[] memory holders = registry.holders(id);
    for (uint256 i; i < holders.length; i++) sum += token.balanceOf(holders[i], id);
    assertEq(sum, token.totalSupply(id));
}

// No-external-call-before-state-write (simple CEI guard sample)
function invariant_noExternalBeforeState() public {
    vm.recordLogs();
    hevm.prank(attacker);
    try system.doSomething() {} catch {}
    Vm.Log[] memory logs = vm.getRecordedLogs();
    assertTrue(orderingChecker.logsShowStateWriteBeforeExternal(logs));
}

Helpful Foundry Features for Reproducibility:

When it comes to making sure your experiments and analyses can be easily repeated, Foundry has some awesome features that really help out. Here’s a rundown of what you should check out:

1. Version Control

Foundry keeps track of all the changes you make to your code and data, so you can go back to any version whenever you need. This is super handy for figuring out what worked and what didn’t.

2. Environment Management

You can create specific environments for each of your projects. This means you can ensure that all the right dependencies and versions are in place, so everything runs smoothly every time. No more “it worked on my machine” problems!

3. Reproducible Pipelines

With Foundry, you can set up pipelines that automate your data processes. This way, every time you run your analysis, you can be sure it’s done exactly the same way as before.

4. Data Provenance

Foundry captures the entire history of your data. You can track where it came from, how it’s been processed, and any changes made along the way. This transparency is key for any reproducible work.

5. Experiment Tracking

Documenting your experiments is a breeze. Foundry allows you to log all your parameters, configurations, and outcomes. So, when you want to revisit an old experiment, everything you need is right there.

6. Collaboration Tools

Working with a team? No problem! Foundry provides features that make it easy for multiple people to work together without losing track of who did what. This collaborative spirit makes reproducibility a whole lot easier.

7. Built-in Documentation

Foundry encourages good documentation practices. You can easily create guides and notes right in the platform. This ensures that anyone, including your future self, can understand what was done and why.

Conclusion

All in all, Foundry packs some powerful features that make reproducibility a lot simpler. Whether you're a solo researcher or part of a larger team, these tools can help make your life easier and your work more reliable. Happy experimenting!

  • Rerun failures only: forge test --rerun
  • Keep fuzz/invariant counterexamples around and automatically replay them in the next runs
  • Add inline configs for each test (like increasing runs/depth for those heavy invariants) (foundry-book.zksync.io)

Static + Fuzzing:

When it comes to ensuring your code is secure and bug-free, combining static analysis with fuzzing is a pretty solid approach. Let’s break it down a bit.

What is Static Analysis?

Static analysis is all about examining your code without actually running it. Think of it as an early warning system that can help you spot potential issues before they turn into headaches down the line. Here are some key points about it:

  • Early Detection: Finds vulnerabilities and bugs during the development phase.
  • Code Quality: Helps enforce coding standards and best practices.
  • Automation: Can be integrated into CI/CD pipelines for continuous feedback.

What is Fuzzing?

On the flip side, fuzzing is the wild child of testing. It involves sending a ton of random or unexpected inputs to your application to see how it holds up. Here’s what fuzzing brings to the table:

  • Real-World Testing: Mimics user behavior with unpredictable inputs.
  • Uncovering Crashes: Helps identify bugs that might not show up during normal testing.
  • Security Focus: Effective in finding security flaws and vulnerabilities.

Why Combine Static Analysis and Fuzzing?

Using both static analysis and fuzzing together gives you the best of both worlds. Here’s why this combo rocks:

  1. Comprehensive Coverage: Static analysis catches issues in the code, while fuzzing tests how the application reacts to unexpected inputs.
  2. Reduced Risk: By identifying vulnerabilities early and testing them in real scenarios, you reduce the chances of security breaches.
  3. Better Reliability: You’re more likely to end up with a robust application that can handle whatever users throw at it.

Tools to Consider

Here are some tools that can help you get started with static analysis and fuzzing:

Static Analysis Tools:

  • SonarQube: A popular choice for analyzing code quality.
  • ESLint: Great for JavaScript code linting and ensuring best practices.
  • FindBugs: Focused on Java applications, it helps identify potential bugs.

Fuzzing Tools:

  • AFL (American Fuzzy Lop): A well-known fuzzer that’s easy to set up and use.
  • libFuzzer: Integrated with Clang, it’s perfect for testing C/C++ code.
  • OSS-Fuzz: Google’s initiative that combines fuzzing with open-source projects.

By leveraging both static analysis and fuzzing, you'll create a safer, more stable application. Embrace the power of these techniques and watch your software quality soar!

  • Launch Slither to check for detectors and prints in your CI.
  • Leverage Echidna for property fuzzing, especially for those tricky invariants that need multi-step sequences. Don’t forget to bring any crashes back into Foundry using fuzz-utils. (github.com)

Storage and upgrade acceptance tests (the #1 audit stall)

Make sure to include these checks in your “Definition of Done”:

  • We’ve got storage layout diff passes lined up (no reorders or shrinks happening here), and each module has namespaced slots declared (thanks to ERC‑7201).
  • The oz-upgrades “validate” checks are running in CI; any PRs that mess with the layout will hit a wall and fail.
  • The choice between UUPS and Transparent proxy is all laid out for you; _authorizeUpgrade makes sure we stick to using multisig and a delay, and we’re using Defender’s proposeUpgrade for all the approvals. (docs.openzeppelin.com)

Tip: Don’t forget to add a “storage map appendix” that shows slot addresses for each namespace and outlines your growth strategy. Auditors love to reference it, so it’s a good idea to have it handy!


Security baselines auditors expect now

  • SWC coverage: Check out the SWC registry categories and run some tools to catch any false positives. Make sure to put together a mapping table in your spec appendix. (github.com)
  • EthTrust v3 and SCSVS v2: Set your certification level targets (S/M/Q) and don’t forget to list any exceptions along with your reasons for them. (entethalliance.org)
  • Opcode semantics: It’s important to avoid depending on SELFDESTRUCT cleanup (we’ve documented this), and let’s keep an eye on transient storage usage by capping it; remember to include tests as well. (eips.ethereum.org)

Deliver an “audit packet” instead of just code

Hand over a zip file (or a repo tag) that includes:

  • Spec PDF/MD that includes all the sections mentioned above.
  • A thorough threat model that’s got SCSVS/EthTrust mapping and an exceptions register. Check it out here.
  • Test artifacts like the output from forge test, gas snapshots, coverage reports, invariant and fuzz configurations, plus replayed counterexamples. More details can be found here.
  • Static analysis reports in Slither JSON format and any custom detectors you created. You can find Slither here.
  • Upgrade packet that includes the storage layout JSON, oz-upgrades validation logs, and the Defender proposal URLs (or IDs) for staging. Get more info here.

This shifts the focus of the review from trying to “interpret intent” to actually “verifying properties.”


Common spec anti‑patterns that guarantee ping‑pong (and how to fix)

  • When you say “Implements ERC‑20 with permits” but don’t share signature details, it needs a little work. Make sure to reference ERC‑2612, include your EIP‑712 domain, and add some test vectors while you're at it. If you’re using Permit2, don’t forget to lock down the address and clearly define the approval scopes and signature expiry rules. (eips.ethereum.org)
  • The term “Upgradeable proxy” is being thrown around without any governance flow. You should specify which proxy pattern you’re using, lay out the admin roles, and clarify the exact steps for using Defender/Safe. (docs.openzeppelin.com)
  • Saying “Will optimize calldata costs” is nice, but it’s lacking the Pectra math. Be sure to show how EIP‑7623 floors interact with your payload sizes. If there’s a chance you'll switch from blobs to calldata, specify what the thresholds are and discuss the fail-closed behavior. (eips.ethereum.org)
  • When you mention “Uses AA” but skip the validation rules, it just doesn’t cut it. You need to specify ERC‑4337 conformance, the EntryPoint version, and what guarantees you offer during the ERC‑7562 validation phase. Also, don’t forget to mention any plans for future EIP‑7702 migration. (docs.erc4337.io)
  • If you’re claiming “Deletes contracts to reclaim gas,” make it clear that you can’t rely on SELFDESTRUCT for state cleanup. Instead, show the actual cleanup function that you use. (eips.ethereum.org)

Brief, in‑depth example: Rollup settlement contract spec hooks post‑Pectra

  • Blob DA budgeting: "The contract makes sure that blob posting happens only when blobbasefee * blobsNeeded <= maxBlobSpend. If it doesn’t, it’ll revert and you’ll have to try again off-chain. Also, v1 doesn’t support calldata fallback."
  • Fee monitoring: "There’s an on-chain view that shows the effective ceiling based on the current block.blobbasefee for frontends. Plus, ops can tweak maxBlobSpend using timelocked governance."
  • Tests: "We’re testing for fuzziness in blob fee volatility. If calldata ends up being cheaper than blobs based on EIP-7623 thresholds, it’ll fail (and is protected by a revert). Check it out here: (eips.ethereum.org)."

Your next steps (copy/paste)

  • Make sure to include the twelve sections mentioned above in your PRD.
  • Set up the CI hooks (Foundry + oz‑upgrades + Slither).
  • Before handing things off, encode your invariants as Foundry/Echidna tests.
  • Create the audit packet and tag the commit that you plan to send.

If you're looking for some assistance, 7Block Labs offers “Spec‑to‑Audit” engagements. We’ll help you by writing or adjusting your spec to fit our template, connecting the tests, and ensuring the oz-upgrades validation is all set. Plus, we package the audit kit so that the initial findings are meaningful and not just clarifications.


References for the 2025 spec landscape

  • Dencun/Pectra timelines and EIPs: Check out the EF blog for details on EIP‑4844 (blobs), EIP‑7691 (blob throughput), and EIP‑7623 (calldata cost). You can find it here: (blog.ethereum.org).
  • Solid updates with Solidity 0.8.29 and 0.8.30 releases! Get the scoop on EOF experiments and the Prague default. Dive into the announcement at (soliditylang.org).
  • New standards are here with ERC‑7201 Namespaced Storage and ERC‑6909 Minimal Multi‑Token. Check them out at (eips.ethereum.org).
  • Explore the core docs for ERC‑4337 AA, along with some cool native AA proposals (RIP‑7560) and EIP‑7702 (EOA code). You'll find all the info you need at (docs.erc4337.io).
  • Don't miss EIP‑1153 about Transient storage and EIP‑6780 which brings some changes to SELFDESTRUCT. More details at (eips.ethereum.org).
  • Get familiar with the BLOBBASEFEE opcode from EIP‑7516. More info is available at (eips.ethereum.org).
  • Upgrades alert! OpenZeppelin has released new plugins, featuring storage-layout validation and Defender workflows. Check the details at (docs.openzeppelin.com).
  • Security baselines have received updates too! Explore the SWC registry, SCSVS v2, and EthTrust v3 at (github.com).
  • For testing, look into Foundry fuzz/invariant docs and the Echidna fuzzer. You'll find great resources at (learnblockchain.cn).
  • Lastly, Permits were updated with ERC‑2612, EIP‑712, ERC‑1271, and Uniswap Permit2 docs and address. Check it out at (eips.ethereum.org).

Like what you're reading? Let's build together.

Get a free 30-minute consultation with our engineering team.

7BlockLabs

Full-stack blockchain product studio: DeFi, dApps, audits, integrations.

7Block Labs is a trading name of JAYANTH TECHNOLOGIES LIMITED.

Registered in England and Wales (Company No. 16589283).

Registered Office address: Office 13536, 182-184 High Street North, East Ham, London, E6 2JA.

© 2026 7BlockLabs. All rights reserved.