testing

Guides writing Hardhat, Foundry, Halmos, and Certora tests for OpenZeppelin contracts.

Updated Aug 10, 2026
One-click install
npx skills add https://github.com/isreal916/pistis --skill testing-isreal916
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: testing
Source: https://github.com/isreal916/pistis/tree/main/contracts/lib/openzeppelin-contracts/.claude/skills/testing
Command: npx skills add https://github.com/isreal916/pistis --skill testing-isreal916

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Contributors to openzeppelin-contracts must choose between four testing approaches (Hardhat unit tests, Foundry fuzzing, Halmos symbolic execution, Certora formal verification) and follow strict conventions for mocks, fixtures, and changesets. This Skill encodes those conventions so tests are written correctly the first time. ## Core Features & Use Cases - Approach selection: A decision table maps contract complexity (state machines, math-heavy code, invariants) to the right testing tool, from baseline Hardhat edge cases up to Certora rule-based verification. - hardhat-exposed and mock conventions: Explains auto-generated $-prefixed wrappers for internal functions and the five cases where manual mocks in contracts/mocks/ are warranted. - Concrete patterns: Covers loadFixture with named functions, shouldBehaveLike* shared behaviors, multi-target test loops, Chai assertion styles, Foundry fuzz and Halmos symbolic test naming, Certora local workflow, and the changeset rule. - Use Case: When fixing a bug in an ERC20 extension, use this Skill to add a minimal regression test with the correct fixture pattern, decide whether a Halmos symbolic test is warranted, and generate the required changeset. ## Quick Start Write a Hardhat test for the ERC20 _mint function following the openzeppelin-contracts testing conventions, including a fixture and a changeset.

Frequently Asked Questions about testing

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I test internal functions in OpenZeppelin contracts?

Use the auto-generated $-prefixed wrappers from hardhat-exposed, which re-expose every internal _function as an external $_function in contracts-exposed/. Deploy with ethers.deployContract('$ERC20', ...) and call token.$_mint(...) directly instead of writing manual wrappers.

When should I use Certora vs Halmos vs Foundry fuzzing?

Use Foundry fuzzing for math-heavy code and invariants, Halmos symbolic execution when a property is expressible as a Foundry test with symbolic inputs, and Certora when state machines or access-control rules are too complex for fuzzing. Hardhat unit tests remain the baseline for all contracts.

When is a manual mock warranted in contracts/mocks/?

Write a manual mock only when hardhat-exposed cannot provide what you need: constructor-level setup, multi-extension composition, injected hook behavior like reentrancy, adversarial behavior with no base analogue, or a plain public wrapper where the auto-generated signature is unsuitable.

Why does loadFixture re-run my fixture on every test?

loadFixture caches by function reference, so an inline anonymous arrow function creates a new reference each call and re-runs instead of restoring the snapshot. Declare the fixture as a named function and pass that reference to loadFixture.

Does every PR to openzeppelin-contracts need a changeset?

Every PR that changes contract behavior needs a changeset created with npx changeset add. Skip it for NatSpec-only edits, internal refactors with no user-visible effect, or pure repository plumbing. Use patch for bug fixes and minor for new features.