ByAUJay
Building a Testing Strategy for Blockchain: Unit, Integration, and Fuzzing
A Practical Blueprint for Decision-Makers
Are you all set to launch a modern blockchain testing program in just a few weeks instead of dragging it out for ages? Well, you're in the right place! This guide is here to help you every step of the way. We'll explore the essential aspects you should be testing, check out the best tools for EVM and permissioned stacks, and I'll show you how to smoothly integrate unit, integration, and fuzz/invariant testing into your CI pipeline with some clear, measurable checkpoints. Let’s get started!
What to Test
When you're diving into blockchain testing, don’t forget to hit the key points.
- Smart contracts: This is where you want to kick things off! Think of them as the foundation of your dApp.
- Transaction flows: Check out how users are navigating through your app.
- Network Security: Make sure your blockchain is protected from any possible threats or weaknesses.
Tools for EVM and Permissioned Stacks
Make sure you pick the right tools for what you need to do. I've got a few suggestions for you:
- Truffle: It's a great tool when you're diving into developing, testing, or even rolling out smart contracts.
- Hardhat: This is a super handy Ethereum development environment that makes testing and debugging a breeze. Seriously, it's flexible and really helps streamline the whole process!
- Ganache: Think of this as your go-to tool for whipping up a personal Ethereum blockchain. It’s perfect for testing out your contracts right on your own machine.
- Hyperledger Fabric: This is a fantastic choice for permissioned blockchain applications, making it perfect for enterprise solutions!
Wiring Testing into CI
Incorporating testing into your Continuous Integration (CI) process is super important. Alright, let’s break it down step by step:
1. Unit Testing: First things first, kick things off by writing some unit tests for your smart contracts. It's a great way to ensure everything works as it should! You might want to check out frameworks like Mocha or Chai. They're pretty handy!
const { expect } = require("chai");
describe("Smart Contract", function() {
it("should return the correct value", async function() {
const value = await contract.value();
expect(value).to.equal(42);
});
});
2. Integration Testing: This is where you check out how all the different parts of your app play nice together. You can totally do this using tools like Postman or Insomnia. They're pretty handy for that!
3. Fuzz/Invariant Testing: It's super important to ensure your application can take on unexpected inputs without breaking a sweat. You never know what might come its way! You might want to check out libraries like Echidna or MythX for some help with this. They're pretty handy!
4. Measurable Gates: Make sure you've got some solid metrics in place to assess your testing. It really helps to have clear benchmarks to know how things are going! This way, you can keep an eye on how things are going and make sure everything's running smoothly.
If you stick to this blueprint, you’ll be able to set up a solid blockchain testing program in no time. It'll help ensure your applications stay both secure and efficient! Happy testing!.
By 2025, with the new protocol upgrades like Prague, Pectra, and Osaka coming into play, along with some fresh compiler behaviors and advancements in fuzzing frameworks, it’s pretty clear that the old test plans just aren’t doing the job anymore. In this guide, I’m excited to share some of the latest strategies we've been using over here at 7Block Labs to keep our teams on the cutting edge. (soliditylang.org).
Why blockchain testing is different in 2025
- Protocol churn is causing some excitement: With the release of Solidity 0.
8. So, around October 2023, the default EVM changed to "prague," following along with Pectra. After that, it switched to version 0. 8. 31 made their way over to Osaka. This change affects gas accounting and the availability of opcodes, such as CLZ, thanks to EIP-7939. Don't forget to test it out with the exact EVM version you're aiming for. It's super important! (soliditylang.org).
- Cost models are shifting: With Pectra’s EIP‑7623 increasing calldata costs, it’s smart to make sure you're testing those calldata-heavy paths in your regression tests. Also, don’t forget to keep an eye on those budget alerts! (soliditylang.org).
- Local devnets are leveling up: Hardhat and Anvil have both introduced some cool features that let you fork the mainnet in a deterministic way. How awesome is that? Locking in a specific block can definitely help make your tests more stable and can even boost the speed of repeated runs by up to 20 times! (hardhat.org).
- Invariants trump examples: It turns out that testing properties and invariants, especially when combined with coverage-guided fuzzing, is really effective at uncovering a ton of bugs that regular unit tests frequently overlook. Just a heads up--it's a good idea to plan for both options to make sure you've got all your bases covered! (learnblockchain.cn).
The test strategy blueprint
Think in Layers
When you’re trying to figure things out, it really helps to think of it like peeling back layers. Alright, let’s break it down! When it comes to each part--like smart contracts or chaincode, off-chain services, and client gateways--here are a few things you might want to keep in mind:
Smart Contracts/Chaincode
- Purpose: So, what's the main job of this smart contract or chaincode?
- Logic: What kind of logic are you using here? Take a moment to consider the rules and conditions that make everything tick.
- Interactivity: How does it connect and work with other contracts or outside systems?
- Security: What steps have been taken to keep it secure and trustworthy?
Off-Chain Services
- Functionality: So, what exactly are these services stepping in to do that smart contracts can't manage by themselves?
- Data Handling: So, how's the data actually being processed and stored?
- Scalability: Can these services keep up as more transactions or users come on board?
- Integration: So, how do they link up with the blockchain and other services?
Client Gateways
- User Interaction: So, how do people actually engage with this layer?
- APIs: So, what kind of APIs can developers dive into?
- Authentication: What kinds of measures do we have to keep access secure?
- Performance: So, how do these gateways manage their speed and efficiency?
When you break it down into these layers, it really helps you see how all the pieces come together. Plus, it makes sure that every part is clearly defined and actually works like it's supposed to.
- Unit tests: Think of these as your trusty little helpers. They’re fast, super targeted, and always deliver the same results, no matter how many times you run them.
- Integration tests: In this part, we're diving into real-world situations. It’s a good idea to consider using forked or test networks, and don't forget about any external dependencies or permissions that might come into play.
- Fuzzing and invariants: So, this is all about property-based testing. We dive into stateful simulations that really put your code to the test, especially in tricky or hostile scenarios. It's a great way to see how your code holds up under pressure!
I've got some awesome playbooks designed just for various stacks.
Unit testing that actually catches blockchain bugs
EVM (Solidity) with Foundry
Foundry lets you run tests with Solidity, which is pretty awesome because it means you can create really detailed test harnesses without having to constantly jump between different tools or environments.
- Property-based fuzz tests: These tests mix in a variety of parameters to see what works and what doesn’t. It’s kind of like experimenting and finding out what sticks! If you focus on just a few types and make some thoughtful assumptions, you'll really be able to grasp the input space better. Check it out here!.
- Invariant tests: In this step, you're establishing some rules that need to stay consistent, kind of like ensuring that certain values are always kept in check.
You can easily adjust your settings for global use or for specific tests by messing around with the
foundry.tomlfile. Plus, you can even do it on-the-fly with in-line pragmas if that’s more your style! Dive deeper here. - Gas Budgets: Want to keep your gas expenses under control? Just use
forge snapshotwithFORGE_SNAPSHOT_CHECK=trueto help you out! Hey, remember to grab those section-level snapshots so you can track the hot paths! If you need more details, check it out here.
Example (fuzz + invariant + gas gate):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import "forge-std/Test.sol";
import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
contract Token is ERC20("T","T"){ function mint(address to,uint256 a) external { _mint(to,a);} }
contract TokenTest is Test {
/// forge-config: default.fuzz.runs = 512
Token t;
function setUp() public { t = new Token(); }
// Property: totalSupply equals sum of balances across holders we track.
function testFuzz_MintConservation(address who, uint96 amt) public {
vm.assume(who != address(0));
uint256 pre = t.totalSupply();
t.mint(who, amt);
// section-level gas snapshot for the mint path
vm.startSnapshotGas("mint");
t.mint(who, 1);
vm.stopSnapshotGas();
assertEq(t.totalSupply(), pre + amt + 1);
assertEq(t.balanceOf(who), amt + 1);
}
// Invariant: balances never exceed totalSupply (holds across sequences)
function invariant_BalancesNotExceedSupply() public {
assertGe(t.totalSupply(), 0);
}
}
Don’t forget to pin your EVM version in foundry.toml so it matches what you’re deploying. You can go with something like evm_version = "prague" or "osaka". It’s a small step that makes a big difference!
If you don’t keep an eye on this, you might notice that the default settings in the compiler start shifting unexpectedly.
(soliditylang.org).
Static Analysis in Unit Loops:
When we chat about static analysis in unit loops, we're really looking at a method for checking out code without having to run it. It’s like peeking under the hood to see how things work without starting the engine. This approach really helps us spot any potential problems, boost the overall quality of our code, and make sure our loops are working just the way they should.
Why Static Analysis?
Static analysis is really about nipping issues in the bud before they escalate. Let me tell you why this is really useful:
- Catch Bugs Early: Spot problems before you even hit that run button!
- Code Quality: Make sure your code is neat and easy to manage.
- Conformance: Just a friendly reminder to keep an eye on those coding standards! It's super important to stay on track.
- Documentation: Get automatic insights that make sense of your code.
Common Tools for Static Analysis
Check out these popular tools that can really assist you with static analysis in unit loops:
1. SonarQube is a popular tool that lets you check out the quality and security of your code. It’s super handy for developers who want to ensure their projects are in top shape! 2. ESLint: This tool is awesome for JavaScript developers! It scans your code to catch any stylistic mistakes and potential bugs, helping you write cleaner, more reliable code. 3. Pylint: If you're working with Python, you definitely want to have this tool in your toolkit. It's great for spotting errors and keeping your code neat and in line with coding standards! 4. Checkstyle: If you're working with Java, this tool is super handy! It helps you make sure your code sticks to coding guidelines, keeping everything neat and tidy.
Key Areas to Focus On
When you're diving into static analysis, especially when it comes to unit loops, make sure you pay attention to a few key things:
- Loop Bounds: Just a quick reminder to keep an eye on those loop limits! You don’t want to accidentally get stuck in an infinite loop.
- Variable Scopes: Just a heads up - be careful with variable shadowing. It can lead to some unexpected hiccups!
- Performance: Take a moment to check if your loops are running smoothly.
- Complexity: When you're writing loops, aim to keep them straightforward. It really helps make your code easier to read and understand.
Conclusion
Static analysis is a really effective way to boost your code quality, especially when you're dealing with those unit loops. If you spot potential problems early on and use the right tools, you can really clean up your code. It’ll not only run smoother but also be way easier to maintain in the long run.
- Integrate Slither into your CI pipeline to quickly catch upgradeability problems, dead code, and common vulnerabilities--think of it as a super-fast linter! Oh, and it works really well with both Foundry and Hardhat projects! If you’re curious, take a look over on GitHub. You won’t regret it!
Hyperledger Fabric chaincode
So, the official Fabric test network, which you can find in fabric-samples/test-network, is designed to create a setup with two organizations and a single orderer using Docker Compose.
This setup is great for running your chaincode unit and integration tests! Just keep in mind that it’s not really designed for production use.
Check it out here.
Hey there! So, when we talk about those scripted flows, it’s pretty cool how they work. They sort of guide the conversation and help keep things on track. It's like having a roadmap for a journey, making sure you hit all the right spots!
By running the command /network.sh deployCC, you can easily install and set up the chaincode for testing purposes. It's a straightforward way to get everything up and running!
Feel free to mix around the channel names and CA settings to explore all sorts of different identity paths!
If you're looking for more info, you can check it out here.
Cosmos SDK modules (Golang)
Imagine module keepers as separate units that come with their own mock-ups.
Next up, check out the SDK "integration tests" that you can find in the /tests/integrations folder.
Before we launch the mainnet, the Simulator is going to throw in some random messages to really put those state transitions to the test. It's going to be a great way to make sure everything's working smoothly!
Hey, take a look at this link: docs.cosmos.network! It’s got some great info for you.
Integration tests that reflect real networks
Mainnet‑fork tests (EVM)
- Hardhat: You can easily spin up a node that's forked from the mainnet or pretty much any EVM chain. It's super handy! Pinning a block is really helpful for keeping things quick and consistent! Oh, and with Network Helpers, it's super easy to impersonate accounts and adjust timestamps or balances on the fly! Take a look at this link: v2.hardhat.org. You'll find some great info there!
- Anvil (Foundry): Simply run
anvil --fork-urlto quickly set up a lightning-fast forked devnet that comes with predictable accounts. It's that easy! It’s great for testing out your Solidity code! Learn more at (getfoundry.sh).
Example (Hardhat Config):
Let me show you a straightforward example of setting up your Hardhat configuration. It’s pretty easy!
require('@nomiclabs/hardhat-waffle');
module.exports = {
solidity: "0.8.4",
networks: {
hardhat: {
chainId: 1337
},
ropsten: {
url: "https://ropsten.infura.io/v3/YOUR_INFURA_PROJECT_ID",
accounts: [`0x${YOUR_PRIVATE_KEY}`]
}
}
};
Breakdown of the Config:
- solidity: This tells you which version of the Solidity compiler you're working with.
Alright, we're starting off with a
0.
8. Sure, you can totally change it to whatever version works best for you!
- Networks: Here’s where you’ll outline the different networks your project will connect with.
- hardhat: Think of this as the local Ethereum network that Hardhat sets up for you to run tests. It's super handy for testing out your smart contracts without any hassle! It’s super convenient for whipping things up quickly.
- Ropsten: So, if you’re ready to roll out your contracts on Ropsten (which is a well-liked test network), don’t forget to grab your Infura link and set up your account’s private key right here.
Don’t forget to swap out
YOUR_INFURA_PROJECT_IDandYOUR_PRIVATE_KEYwith your real info! It's an easy step, but super important.
Tips:
Make sure to keep your private keys safe and never share them in public places. You definitely don’t want anyone snooping around your info! Hey there! If you’re looking to level up your setup, definitely give the Hardhat documentation a look. It’s packed with tons of great tips and tricks! Happy coding!
import { HardhatUserConfig } from "hardhat/config";
const config: HardhatUserConfig = {
networks: {
hardhat: {
forking: {
url: process.env.MAINNET_RPC!,
blockNumber: 20400000 // pin for deterministic caches
}
}
},
// Align local EVM to target hardfork
hardhat: { hardfork: "prague" }
};
export default config;
Hey there! If you're diving into Hedera's EVM, don't forget to use the Hardhat forking plugin. It's super handy for simulating HTS system contract reads while you're running your fork tests. Happy coding! Take a look at it here: github.com. You'll find some interesting stuff!
Permissioned networks
- Fabric: First things first, go ahead and kick off the test network. Once that’s up and running, you can start running client flows. You can use either FireFly or the SDK, just make sure you have your organization's connection profiles handy! Don't forget to take a look at the cert material mapping and the channel ACLs! If you're looking for more info, just check this out here. It's got all the details you need!
- Cross-DLT: If you’re curious about diving into some interoperability proofs-of-concept, you should definitely take a look at the Hyperledger Weaver test setups. They're pretty cool! They’ve got these dual networks and contracts that really help you out when it comes to validating data sharing and handling asset exchanges. Want to get into the nitty-gritty? Check it out here!
Cross‑client/spec conformance (EVM teams)
Hey, just a quick reminder to use the Ethereum Execution Spec Tests (EEST/EELS) when you're working on this. They’re super important! So, in late 2025, they rolled out the "Weld" project, which brought together all the tests and the Python spec into one handy repository. Pretty cool, right? This change really simplified the process of creating fixtures and test vectors that aren’t tied to any specific client. It’s super useful for checking out custom precompiles or digging into those low-level libraries. Check it out here!.
Fuzzing and invariant testing: what to run and where
Foundry fuzzing and invariants (EVM)
- You can easily fuzz any parameterized test by setting the global
FOUNDRY_FUZZ_RUNSvariable. If you want to get a bit more specific, you can also adjust it just for certain tests by adding some in-line config comments. When you're running CI, it's a smart move to use deterministic seeds alongside it. (learnblockchain.cn).
Invariant testing has a lot to offer! You’ve got various choices to play around with, like direct checks and differential checks. Plus, there are some cool “targeted” handlers that really come in handy for managing those stateful sequences.
You might find it handy to use it as a pre-merge gate for your DeFi protocols.
(learnblockchain.cn).
So, when you're diving into differential fuzzing, one cool thing you can do is check out the Solidity output and compare it against a reference implementation written in TypeScript or Rust.
Whenever you're working with your crypto or math libraries, just go ahead and use vm.ffi() to catch any semantic mismatches. It's a handy way to ensure everything's lined up correctly!
(foundry-book.zksync.io).
Echidna (coverage‑guided ABI fuzzer)
This tool is awesome for dealing with black-box ABI sequences and letting you use your own invariants. It meshes really well with Slither for pre-analysis, and it even spits out streamlined counterexamples to make triage a breeze! We really enjoy using it with Foundry; that's where grammar-focused campaigns truly shine! (github.com).
Certora & symbolic tools
Hey there! If you want to level up your Foundry fuzz tests, you should definitely check out Certora’s Foundry integration (it's still in alpha, but really cool!). It can actually verify your tests more thoroughly by diving deep into all the different inputs, rather than just taking a few samples here and there. This is great for transforming those high-value fuzz specs into reliable proofs over time. (docs.certora.com).
Halmos has come up with a pretty awesome method for symbolic testing, and it’s even better now with a Foundry frontend. Plus, they’ve added some neat support for stateful invariants.
You can totally use it to quickly transform your current tests into solver-driven checks. It’s super straightforward!
You should definitely check this out--it's a cool addition to your testing toolkit! You can find it here.
Client and off‑chain fuzzing
- Go clients/middleware: Don't miss out on Go's awesome built-in fuzzing feature, which has been around since version 1. It's a great tool to help you catch those pesky bugs!
- Let’s get creative with some crazy invalid RPCs, throw together some messed-up blocks and receipts, and really test the limits with those tricky ABI edge cases. Hey, just a reminder to link this up with your CI so you can catch any panics or resource leaks right from the start! If you want to dive into more details, you can find them here.
- OSS-Fuzz: So, if you're working on an open-source project--like clients, SDKs, or precompiles--make sure to set up those wire sanitizers. And keep the fuzzing vibe alive by using libFuzzer, AFL++, or Honggfuzz on a pretty big scale! If you're looking for more info, just check it out here. It's all laid out for you!
Non‑EVM smart contracts
- Cosmos SDK: Take a look at the Simulation framework--it’s a great way to play around with message sequences and module parameters. This is definitely the best approach to catch any state transitions that might lead to a hiccup before you go live. (docs.cosmos.network).
- Stellar Soroban: Jump into
cargo-fuzzwith nightly Rust to really explore contract interfaces. You'll notice that we've got property tests hanging out with the regular tests too! (developers.stellar.org).
Measuring what matters (and failing the build on regressions)
Adopt Objective Gates That Match Risk:
When you're looking to manage risk, it’s super important to create some clear checkpoints that match the different levels of risk you’re facing. By doing it this way, you’ll be able to make the smartest choices and keep everything running smoothly. Alright, here's the scoop on how to get it done:
1. Define Risk Levels: First things first, take a moment to nail down what "risk" actually means for your project or initiative. It’s important to have a clear picture! Let's break down what we mean by low, medium, and high risk.
Low risk is usually when the chances of something going wrong are pretty slim. Think of it like investing in a well-established company--odds are in your favor.
Then there's medium risk. This is where things start to get a bit trickier. You might have a decent chance of getting a good return, but there’s also some uncertainty--like putting your money into a newer startup that shows promise but could also stumble.
Now, high risk is when the stakes are really elevated. This could involve investing in something volatile, like cryptocurrencies or stocks in emerging markets. Sure, you might hit it big, but the possibility of losing your investment is also much higher.
So, to sum it up: low risk is safe and steady, medium risk has some potential but with a twist of uncertainty, and high risk is all about taking big swings.
2. Create Gate Criteria: Nail down specific criteria for each gate that match the risk levels you've outlined. This helps you get a solid grasp of what you need to do to make it through each stage.
3. Keep Track of Progress: Make sure to check in on how everything's moving along. Make sure you check in on your milestones pretty regularly and tweak your risk assessment whenever you need to. It's all about staying flexible and adapting as you go along!
4. Keep It Clear: It's important that everyone on the team knows the criteria and why the gates matter. Make sure to communicate that well! Being open and transparent really helps set clear expectations and keeps everyone on the same page.
5. Take a Moment to Review and Tweak: You know, sometimes things don’t go as planned, and that’s totally normal! It’s a good idea to keep an open mind and check back on your gates and criteria when you get new info or if the project situation shifts a bit.
By using these targeted checkpoints based on your unique risk levels, you’ll find it easier to tackle challenges and keep your projects running smoothly.
- Security lint: Run Slither and make sure it doesn't throw any "High" warnings. Also, double-check that everything's set for upgradeability. If you’re looking for more details, just check it out here.
- Gas budget: Go ahead and run the command
forge snapshot --check --tolerance 1, and fingers crossed, it should pass without any issues! And hey, make sure to include those section-level snapshot gates for those key areas! If you're looking for the details, just click here. It’ll take you right where you need to go! - Fuzzing: It's a good idea to shoot for a minimum number of runs per suite--try to hit at least 2,000 when you're testing locally and aim for about 10,000 during those nightly runs. And don't forget, you should be seeing “no failures after shrinking.”
You can easily get this going by using in-line
forge-configalong with CI profiles. More info here. - Invariants: Make sure everything stays squeaky clean--aim for zero violations, either after running for at least a minute for each suite or after hitting a set number of sequences. Just remember, this number should be tailored to fit the specific risks of the protocol you’re working with! If you want to dive deeper into the topic, just click on this link. It’s got all the details you’ll need!
- Fork tests: Don’t forget to check that the pinned-block fork CI is all good to go! When it’s unpinned, things can get a little dicey during the nightly runs, but don’t worry--it’s rock solid when it comes to pull requests. Oh, and by the way, using Hardhat pinning can seriously boost your caching speeds! If you want to dive deeper into this topic, just click here to get all the details!
- Spec conformance: When it comes to the client and those low-level libraries, let’s kick off a quick round of EELS tests in CI. It’s a good idea to run a full suite of tests overnight, too, just to keep everything in check. If you want to dive deeper into this topic, check out the details here.
A reference CI pipeline you can copy
Minimal GitHub Actions Fragments to Establish Gates Quickly:
Setting up gates in your GitHub Actions doesn't need to be a headache! Here are some cool little tips to help you kick things off.
Basic Workflow Example
name: CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
Adding a Gate for Code Quality
Before you dive into the next steps, it might be a good idea to add a little check to make sure your code hits the quality marks you’re aiming for.
jobs:
build:
steps:
...
- name: Run linters
run: npm run lint
Conditional Gates Based on Branch
So, if you're looking to set up a job that only runs for certain branches, here's a simple way to go about it:
jobs:
build:
if: github.ref == 'refs/heads/main'
steps:
...
Manual Gates with workflow_dispatch
You might find it helpful to decide when a workflow should kick off. You can totally set it up to go off whenever you want!
on:
workflow_dispatch:
Summary
Setting up gates in your workflows can be super easy with just a few simple GitHub Action snippets. Feel free to mix and match these snippets however you like to fit your project! It's super easy to customize them to make them work for you. Happy coding!.
# .github/workflows/ci.yml
name: smart-contract-ci
on: [pull_request, push]
jobs:
solidity-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: foundry-rs/foundry-toolchain@v1
with: { version: nightly }
- name: Unit + fuzz (quick)
run: |
FOUNDRY_FUZZ_RUNS=512 forge test --gas-report
- name: Gas snapshot gate
env:
FORGE_SNAPSHOT_CHECK: "true"
run: forge snapshot --check --tolerance 1
- name: Slither
run: |
pipx install slither-analyzer
slither .
hardhat-fork:
runs-on: ubuntu-latest
env:
MAINNET_RPC: ${{ secrets.MAINNET_RPC }}
steps:
- uses: actions/checkout@v4
- run: npx hardhat test --network hardhat
Hey there! When it comes to your Fabric/Weaver repos, you’re going to want to set up a job that starts with a simple ..
First, run /network.sh up createChannel, and then you can go ahead and launch your chaincode test harness.
Just a quick reminder to make sure you finish everything off with a period!
Just run the command network.sh down to reset everything. It's that simple!
Hey, if you want to dive into the specifics, take a look at the details here. It's all laid out for you!
Tool choices by stack (what we deploy most)
- EVM Smart Contracts: If you're diving into EVM smart contracts, you’ve got some awesome tools to work with! Foundry is super useful for running unit tests, doing some fuzz testing, generating gas reports, and checking for invariants. It really makes those tasks a lot easier! Hardhat makes it super easy to integrate forks, plus it comes with some handy JavaScript helpers that can really boost your workflow. If you're diving into static analysis, definitely check out Slither. And if fuzz testing with a grammar-based approach is more your vibe, I’d recommend giving Echidna a try! Certora and Halmos focus on symbolic testing, which is a cool way to analyze software. On the other hand, EELS gets the job done by making sure everything meets the required standards. Hey, if you’re getting into forked devnets, make sure to check out Anvil! If you want to dive deeper into this topic, check it out here. You'll find some great info waiting for you!
- Fabric: Looking to run some tests on Fabric? You can easily create a Fabric test network that works alongside FireFly and Weaver. This setup is perfect for tackling those integration scenarios you might be facing. Feel free to dive into the details here when you get a chance!
- Cosmos SDK: When it comes to Cosmos SDK, I’ve found that using a combination of Go tests, integration tests, and a handy simulator really does the trick. If you're looking to dive in, you can find a ton of helpful info to kick things off right here. Happy exploring!
- Soroban/Rust: If you're diving into Soroban with Rust, definitely check out cargo-fuzz. It works with libFuzzer and can be a great addition to your property tests. Happy coding! Want to dive deeper? Check out more insights here. It's got a ton of useful info!
- Clients/SDKs (Go/Rust/C++): If you’re working with clients and SDKs in Go, Rust, or C++, definitely take advantage of Go fuzzing - it’s super helpful! And don’t forget about OSS-Fuzz for that continuous sanitization. It’s a great way to keep everything in check! If you want to dive deeper into that topic, you can check it out here.
Emerging practices we recommend adopting now
Hey, just a heads up! When you're running your tests, make sure they align with the latest deployment hardfork. It's a good idea to set the EVM to either “prague” or “osaka” in your compiler or tools. This will help you avoid any unexpected opcode or gas changes that might catch you off guard. Happy coding! Just a quick reminder to update it whenever you upgrade Solidity to version 0. 8. 30→0. 8. 31+). (soliditylang.org). Think of calldata as a cost surface: after EIP-7623, make sure to create regression tests that push out large calldata, like when you're doing batched mints or proofs. It’s important to check those against gas limits so we can keep the user experience nice and smooth. (soliditylang.org). Hey there! Just a quick tip: when you're getting ready to merge, make sure to keep an eye on invariants--they're super important. We tend to spot those tricky class-breakers, like fee drifts and liquidity leaks, which usually pop up during stateful fuzz sequences. Trust me, it’s worth it to double-check! (learnblockchain.cn). Hey there! Just a quick tip for when you’re working with those low-level primitives like RLP, Merkle, or arithmetic. It’s a good idea to take some hints from the spec tests. If you’re rolling them out, try running EELS fixtures as differential tests along with your own testing suite. It’ll really help you ensure everything's working smoothly! (steel.ethereum.foundation).
Research to Watch:
LLM-guided fuzzers and automated invariant synthesis are finally moving beyond just the pages of academic journals and making their way into real-world use. It's exciting to see these ideas come to life! They’re super helpful for sorting out fuzz campaigns and getting the ball rolling on property generation. That being said, it's really crucial to have a human take a look at everything before it goes live in production. You know, just to make sure everything's spot on! Take a look at it here: (arxiv.org).
Pitfalls we still see--and fixes
Simply saying that "It passed unit tests on a dev chain" doesn't cut it. Hey, just a heads up--you definitely want to run some mainnet-fork tests and try out impersonation. It’s super important for getting a clear picture of the real allowance and permit states, as well as how fees on transfers and proxies are behaving. Trust me, it’ll make a big difference! Just a quick tip: don’t forget to grab a fork and a pin! (hardhat.org).
Hey there! Just a quick tip for your fuzzing adventures: try not to jump to conclusions. If you're dealing with unconstrained domains, you could run into some sneaky false negatives. For example, when you’re using Foundry’s default settings, you might accidentally send over 2^96 wei and not even realize it. Keep an eye out for that!
It's a good idea to narrow down your types and make use of vm.assume.
(learnblockchain.cn).
Watch out for those sneaky gas regressions! They can catch you off guard if you’re not careful--make sure to lock your settings.
Hey team, just a quick reminder to set up the gas-snapshot in CI with a 1% tolerance. Also, don't forget to include section snapshots for those key processes like swap and settle. These details really matter!
(learnblockchain.cn).
- Just a heads up, the Fabric test network is strictly for testing purposes. So let’s make sure we use it the right way! When you take your project to production, steer clear of just copying its single-node ordering and the TLS shortcuts. It's best to approach it thoughtfully! (hyperledger-fabric.readthedocs.io).
Bringing it together: a 30‑day rollout plan
- Week 1: Alright, let’s get started! We can either dive into Foundry or mix it up with a combo of Hardhat and Foundry for our EVM setup. What do you think? Don't forget to set your compiler EVM to match the hardfork you're using for your deployment. It’s a little detail, but it can save you from a lot of headaches down the road! Oh, and make sure to throw in Slither and those quick fuzz runs into the CI process too! Can't leave those out! If you're looking to set up local networks, definitely get those Fabric or Cosmos configurations up and running! (soliditylang.org).
Week 2: Alright, it's time to dive in and brainstorm about 5 to 10 invariants that highlight the key financial or access properties we really value. Let's make sure we're focusing on what's important!
Don't forget to turn on those forge snapshot gates and set up a pinned-block fork suite for our main integration paths. Thanks!
(learnblockchain.cn).
- Week 3: We're diving into using Echidna for our ABI-level campaigns this week! Let's start a nightly routine for long-run fuzzing. Oh, and make sure you set up OSS-Fuzz or Go fuzzing for the clients and SDKs. It's super important! (github.com).
- Week 4: Alright, let’s dive into those EELS/EEST conformance tests! It's the perfect moment to tackle them where they really fit in. Let’s dive a bit deeper into Certora and Halmos. We really need to pay attention to our key invariants--those are our real assets. If we can nail those down, we can turn those fuzz specs into some strong, formal guarantees. (steel.ethereum.foundation).
Final word
When it comes to testing blockchain software in 2025, it’s really about staying on top of those speedy protocol changes and proving how the software holds up in real-world situations, especially when facing tough challenges. If you stick to the strategies we talked about--like doing solid unit tests, using forked integration, and throwing in some property-driven fuzz testing along with strict CI checks--you’ll find that you can launch faster and dodge a lot of the surprises that usually pop up in those final stages. Trust me, it makes a big difference!
At 7Block Labs, we’ve established these practices as a standard for both EVM and permissioned stacks. If you’d like us to tweak the blueprint to match your unique architecture and risk profile, just give us a shout! We’re more than happy to help you out!
References
Hey there! Make sure to take a look at the release notes for Solidity 0. They’ve got some pretty interesting updates!
8.
30/0.
8.
31, which goes over hardfork defaults and EIPs.
You can check them out here.
Hey, if you're a fan of Hardhat, you've gotta check out the fork documentation and the performance tips. They’ve got some super useful tools for impersonation and taking snapshots, too!
Dive in here.
Foundry really stands out with its awesome documentation on fuzzing and invariants. Plus, it offers handy in-line configuration guides and tools for gas snapshots, making it super user-friendly!
Check it out here.
- Curious about Anvil? Check out this overview on forking here for all the details! Hey, if you're into ABI fuzzing, you should definitely check out Echidna on GitHub! You can find it here. It's pretty cool! If you're into static analysis, you've got to check out Slither! It's a great tool, and you can easily find it on GitHub right here. Trust me, it’s worth a look! Hey there, if you're diving into Hyperledger Fabric, you might want to take a look at the test network and FireFly connection profiles. You can find all the info you need right here. Happy exploring! Hey there! If you're diving into Cosmos SDK, you might want to check out their docs where you can play around with testing and a cool simulator. You can find all that info right here. Happy exploring! If you're a Go developer, definitely check out fuzzing and OSS-Fuzz! You can find more info about it here. It's worth a look!
- And hey, don't forget to check out the latest on the EELS/EEST "The Weld" merge and those spec tests! You can dive into all the details here. Happy reading!
Like what you're reading? Let's build together.
Get a free 30-minute consultation with our engineering team.
Related Posts
ByAUJay
Building a Donation-Based Crowdfunding Platform That Gives Tax Receipts
**Summary:** Donation-based crowdfunding that includes tax receipts has become quite the complex puzzle across different regions. You've got to navigate IRS Pub 1771/526 rules, UK Gift Aid declarations, Canada’s CRA receipting, and the new eIDAS/OpenID4VCI wallets--all while keeping everything running smoothly.
ByAUJay
Why 'Full-Lifecycle Advisory' Beats Just Coding
**Summary:** Engineering teams that focus solely on “writing Solidity” often find themselves caught off guard by shifts in protocols, the need for composable security, and the procurement hurdles that are now impacting real ROI. Our full-lifecycle advisory service bridges the gap by connecting EIP-7702 smart accounts, modular decentralized applications (DA), and ZK-based compliance solutions.
ByAUJay
Why Your Project Could Really Use a 'Protocol Economist
Summary: A lot of Web3 teams are missing a crucial player: the “protocol economist.” And you can really see the impact--value slips away through MEV routing, token incentives that are all out of whack, and those sneaky changes to wallets after Pectra that end up messing with the unit economics. In this playbook, we’ll explore what a protocol economist can do to tackle these issues head-on.

