Skip to content

Repository files navigation

ChainImpact

Know what your smart-contract PR breaks before you merge.

ChainImpact compares two Git revisions of a Foundry project and reports what the diff breaks for everything downstream: contract ABIs, events your indexers consume, proxy storage layouts, function permissions, and the TypeScript frontend and backend that call them.

ChainImpact performs change-impact analysis. It is not a security audit. It does not prove the absence of vulnerabilities and does not replace review by a security professional.


Quick start

Requires Node 20+, pnpm, and Foundry.

ChainImpact is not published to npm yet, so build it from source:

git clone https://github.com/mayanksharma-eth/chainimpact
cd chainimpact
pnpm install
pnpm build

Then run it against any Foundry repository:

node packages/cli/dist/index.js analyze \
  --cwd /path/to/your-repo \
  --base origin/main \
  --head HEAD
 MERGE BLOCKED   11 blocker(s)  2 warning(s)  3 info

 BLOCKER  Vault.redeem(uint256,address) was removed
  abi · deterministic
  This externally callable function no longer exists. Any caller still targeting it will revert.
  - function redeem(uint256,address) returns (uint256)
  Affected consumers:
    apps/web/hooks/useRedeem.ts:13
      functionName: "redeem",
    api/indexer/redemptions.ts:20
      functionName: "redeem",

Try it on the bundled fixture without touching your own code:

pnpm test:integration   # compares fixtures/risky-upgrade and fixtures/safe-upgrade

Use it in pull requests

Copy examples/github-action/chainimpact.yml into .github/workflows/:

name: ChainImpact
on: pull_request
permissions:
  contents: read
  pull-requests: write
jobs:
  impact:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0            # two revisions are compared
      - uses: foundry-rs/foundry-toolchain@v1
      - uses: mayanksharma-eth/chainimpact@v0
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          fail-on: blocker

The action writes the report to the job summary and maintains exactly one PR comment, updating it in place on every push. It never uses pull_request_target.

What it checks

Check Detects Source
ABI Removed functions, changed parameters, changed return types, mutability and payability flips, custom errors, added/removed contracts Compiler ABI
Events Removed and renamed events, parameter type and order changes, indexed/non-indexed moves Compiler ABI
Storage Slot and offset moves, type changes, insertions, deletions, reorders, safe appends Compiler storage layout
Permissions Modifier additions and removals, visibility escalation, changed onlyRole arguments, new role/ownership operations Compiler AST
Consumers References to changed symbols in TypeScript/JavaScript, with file and line Text search (heuristic)

Two behaviors worth knowing:

  • Return-type changes are blockers. Return types are not part of the four-byte selector, so calls still resolve — but every consumer decoding the result breaks.
  • Indexed/non-indexed changes are blockers. topic0 is unchanged, so an indexer keeps matching the event while silently mis-decoding it.

Reports

Three formats, same analysis:

chainimpact analyze --base origin/main --head HEAD                    # terminal
chainimpact analyze --base origin/main --head HEAD --format markdown  # PR-ready
chainimpact analyze --base origin/main --head HEAD --format json      # machine-readable
chainimpact analyze --base origin/main --head HEAD -o report.md

Exit codes

Code Meaning
0 Analysis completed; nothing met the failure threshold
1 Analysis completed; the configured threshold was met
2 Operational or configuration failure

A skipped or unavailable check is never rendered as a pass, and the verdict is never clear while an enabled check could not run.

Configuration

Optional. Copy chainimpact.example.yml to .chainimpact.yml to override the defaults:

version: 1
framework: foundry
contracts:
  include: ["src/**/*.sol"]
  exclude: ["test/**", "script/**", "lib/**"]
consumers:
  include: ["apps/**/*.ts", "apps/**/*.tsx", "api/**/*.ts"]
  exclude: ["**/node_modules/**", "**/dist/**", "**/generated/**"]
checks:
  abi: true
  events: true
  storage: true
  permissions: true
  consumers: true
failOn: blocker

Globs are relative to the repository root. Unknown keys are rejected with a readable error.

Privacy

  • The analyzer runs entirely on your machine or CI runner. There is no ChainImpact server.
  • No source code, artifact, or report leaves the runner. The action's only network calls are to the GitHub API to post its comment.
  • No telemetry, no account, no API key, and no AI or LLM at runtime.
  • Analysis is deterministic: the same two revisions always produce the same findings and the same finding IDs.

Repository layout

packages/core      analysis engine — checks, renderers, git and Foundry integration
packages/cli       chainimpact command-line interface
packages/action    GitHub Action source (bundled to dist/ at the repository root)
apps/web           website, docs, and browser playground
fixtures/          risky-upgrade and safe-upgrade Foundry projects used by the tests
examples/          example GitHub Actions workflow

Development

pnpm install
pnpm dev               # website at http://localhost:3000
pnpm build             # build every package
pnpm lint
pnpm typecheck
pnpm test              # unit tests (no Foundry required)
pnpm test:integration  # fixture tests (requires Foundry; skips with a visible reason otherwise)
pnpm action:build      # rebundle the GitHub Action into dist/

dist/ at the repository root is the committed, bundled Action — GitHub Actions requires it. CI fails if it is out of date, so run pnpm action:build after changing anything under packages/action or packages/core.

Deploying the website

The site is a static Next.js App Router build with no environment variables and no backend, so there is nothing to configure beyond the monorepo paths. There is no .env.example because the site does not read any environment variable.

npm i -g vercel
vercel login
vercel link                      # run from the repository root
vercel --cwd apps/web            # preview deployment
vercel --cwd apps/web --prod     # production deployment

If you configure the project through the Vercel dashboard instead, use:

Setting Value
Framework preset Next.js
Root directory apps/web
Build command pnpm build
Install command pnpm install
Node version 20.x

Enable "Include files outside the root directory" so the workspace dependency on packages/core resolves.

After deploying, set url in apps/web/lib/site.ts to the real domain — it is only used for Open Graph metadata, and every outbound link comes from that same file.

Limitations

  • Foundry only. Hardhat and Vyper are not supported.
  • Both revisions must compile; a build failure is reported as an operational failure, not partial results.
  • Consumer detection is text-based and therefore heuristic. It can miss dynamically constructed names and match unrelated identifiers. Every match shows its file and line so you can verify it.
  • Storage gaps and namespaced (ERC-7201) storage cannot be validated confidently by layout diffing. ChainImpact flags them for manual review rather than calling them safe.
  • Permission analysis compares declared modifiers and visibility. It does not evaluate authorization logic written inside a function body.
  • Not published to npm and not published to the GitHub Marketplace. Install by building from source.

License

MIT. Security policy: SECURITY.md.

About

Know what your smart-contract PR breaks before you merge. Change-impact analysis for Foundry projects: ABI, events, storage layout, permissions, and TypeScript consumers — in the pull request.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages