Skip to content

feat(solidity-test): add --gas-profile to test solidity - #8738

Open
aelmanaa wants to merge 1 commit into
NomicFoundation:mainfrom
aelmanaa:feat/solidity-test-gas-profile
Open

aelmanaa wants to merge 1 commit into
NomicFoundation:mainfrom
aelmanaa:feat/solidity-test-gas-profile

Conversation

@aelmanaa

Copy link
Copy Markdown
Contributor

Part of #8737. A follow-up PR adds the HTML report.

Summary

hardhat test solidity --gas-profile shows where each test's gas goes. After the test results, it prints a summary: tests by gas, functions by self gas, and each test's hottest call path. It also writes one folded-stack file per test to <cache>/gas-profile/folded/. speedscope, inferno, and flamegraph.pl can open these files.

The profile is built from the call traces EDR already returns (TestResult.callTraces()). It needs no EDR change and no new dependency.

Changes

  • New gasProfile flag on test solidity. When it is on, the run sets includeTraces to All through a new optional includeTraces parameter in helpers.ts. The test output is the same as without the flag.

  • gas-profile/model.ts builds each test's call tree from its last trace root, so setUp is left out. It:

    • drops cheatcode and console.log frames, which report 0 gas;
    • computes self gas;
    • merges calls to the same function, keeping their per-call gas;
    • builds the folded lines in execution order, weighted by self gas.

    It also computes refund, minCall/maxCall, kinds, and tags, which the HTML report in the follow-up PR uses.

  • gas-profile/summary.ts prints the terminal summary, with formatTable.

  • gas-profile/index.ts writes the folded files and replaces <cache>/gas-profile/ on each run. File names are sanitized, capped at 200 bytes with a hash, and deduplicated case-insensitively.

  • --coverage with --gas-profile is refused before the build (HHE823), because coverage instruments the bytecode.

  • When isolation is on (--gas-stats, --gas-stats-json, or the isolate setting), a warning says that each top-level call then includes its own transaction cost.

  • Writing the profile never changes the exit code. A failure prints a warning.

  • Fuzz, invariant, and skipped tests are listed as not profiled.

  • Changeset: hardhat minor, @nomicfoundation/hardhat-errors patch.

Gas accounting

A frame's gas is its gasUsed, which includes its calls. Self gas is that value minus its calls' gasUsed. The self gas of all frames adds up to the root's gasUsed. The root's gasUsed minus consumedGas is the refund applied at the end of the test. Recursive calls count once in a function's total.

Testing

  • Unit tests for the model, the summary, and the file writing. The model tests use numbers measured on EDR 0.23.0: a deposit test with a 2,800 refund, and five swaps where the first costs 80,634 and the next four 17,934. The file tests cover long names, case collisions, and replacing an old profile.
  • Integration tests in solidity-test/task-action.ts on the solidity-test fixture:
    • files and summary are written when a test fails;
    • nothing is written when no test runs;
    • --coverage is refused;
    • the isolation warning is printed;
    • a write failure leaves the result unchanged.
  • Edge cases run by hand: 200,000 calls in one test, recursion 200 deep, a 245-character test name, testCase and testcase, vm.skip, the P256 and BLS precompiles, and labels with <, ;, and %.
  • solidity-test, gas-analytics, and coverage tests: 574 pass. pnpm lint and pnpm build pass in hardhat and hardhat-errors.

Docs: NomicFoundation/hardhat-website#317.

🤖 Generated with Claude Code

Prints a gas summary after the test results (tests by gas, functions by self gas, hottest call paths) and writes a folded-stack file per test to <cache>/gas-profile/folded/, for speedscope, inferno and flamegraph.pl. Builds the profile from the call traces EDR already returns. Refuses --coverage (HHE823) and warns when isolation is on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Oct 19, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 646bd00

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
hardhat Minor
@nomicfoundation/hardhat-errors Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants