You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Replace prettier, eslint, and solhint with Biome and forge lint, installed without npm - #1429
Stacked on #1428. It retargets to main once the earlier PRs merge.
Moves linting off the Node toolchain and off npm entirely: every tool is a pinned binary checked against a recorded SHA-256.
Solidity uses forge fmt and forge lint --deny warnings (configured in foundry.toml) instead of prettier-plugin-solidity and solhint. The deployed contracts (Seaport.sol, conduit/, helpers/, interfaces/, zones/) are excluded, so their source still matches what was verified onchain. Lint also skips contracts/test/, whose mocks are deliberately unsafe.
TypeScript, JavaScript, JSON, Markdown, and YAML use Biome 2.6.3 instead of prettier and eslint. Biome's linter is off for test/, which holds the legacy Hardhat suite that later PRs port to Foundry. Formatting is still enforced there.
foundry.toml is formatted with taplo. Shell scripts get shellcheck and shfmt, and workflows get actionlint. .editorconfig records each language's indent.
lefthook replaces husky and lint-staged for the optional pre-commit hook.
scripts/install-tools.sh installs Biome, taplo, lefthook, shellcheck, shfmt, and actionlint into .tools/bin from each tool's GitHub release. Every file is checked against a pinned SHA-256, so a replaced asset fails the install, and nothing comes from a package registry. Every release is at least two weeks old. scripts/lint.sh check|fix runs what CI runs, and warns when the local Foundry differs from CI's. The CI lint job no longer installs Node.
The CI lint job runs each check as its own step.
Commits
forge fmt over tests, scripts, mocks, and reference/. Whitespace and line wrapping only, so review it with whitespace hidden. The bytecode check still passes, and reference/ isn't deployed.
23 forge lint findings in four test files: block.timestamp reads in functions that call vm.warp, which via_ir can cache across the warp. They now use vm.getBlockTimestamp().
The tooling swap itself, plus Biome's formatting and safe fixes on the TypeScript.
Removal of the readme.io front matter, the stub pages, and prepare-docs.js. They only fed the docs sync, whose destination repo is archived, and Biome's Markdown formatter mangles front matter. This commit also carries Biome's Markdown reformatting of docs/.
Biome for Markdown and YAML, plus taplo, shellcheck, shfmt, and actionlint. Inline FOUNDRY_PROFILE=... prefixes in workflows move into env: blocks.
Small follow-ups: Biome pinned to 2.6.3, and the pre-commit hook covers Markdown and YAML.
The pinned-binary install script and scripts/lint.sh, replacing the npm packages for Biome, taplo, and lefthook.
forge fmt over reference/, which the first commit missed (plain forge fmt skips it), and explicit fmt paths in lint.sh and CI so it stays checked.
Verification
scripts/lint.sh check (forge fmt, forge lint, Biome, taplo, shellcheck, shfmt, actionlint) is clean locally with Foundry 1.9.0.
scripts/install-tools.sh installs all six tools on macOS arm64, skips them on a second run, and refuses to install a tool when its hash doesn't match.
The Forge suites touched by the timestamp change pass: FulfillAdvancedOrder, FulfillOrderTest, MatchAdvancedOrder, and FuzzMain.
After the Biome rewrite, the Hardhat suites pass: yarn test with 402 passing and yarn test:ref with 376 passing. One local test:ref run had two flaky failures under load; the rerun was clean.
AGENTS.md states the one rule for this repo (the deployed 1.6 bytecode
must not change), the layout, the pinned toolchain, and the build and
test commands. CLAUDE.md imports it.
docs/Seaport-1.7-candidates.md collects ideas from past PRs and issues
that would change the deployed bytecode, each linked to its source.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude Code reads AGENTS.md directly, so the CLAUDE.md import is not
needed. The root file now covers only the bytecode rule, layout, and
commands; test/foundry/AGENTS.md covers precompiled artifacts, profiles,
and fuzz-test pitfalls. The 1.7 list drops the optimizer runs note,
since max runs reproduces the deployed bytecode.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Configure forge fmt and forge lint in foundry.toml and apply forge fmt.
The deployed contracts (Seaport.sol, conduit, helpers, interfaces,
zones) are excluded so their source keeps matching what was verified
onchain. This commit only changes whitespace and line wrapping.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
forge lint flags block.timestamp reads in test functions that also call
vm.warp, since via_ir can cache the value across the warp. These four
files now use vm.getBlockTimestamp(), and forge lint reports no
findings outside the excluded deployed contracts and mocks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Solidity: forge fmt and forge lint --deny warnings, configured in
foundry.toml, replace prettier-plugin-solidity and solhint.
- TypeScript, JavaScript, and JSON: Biome 2.6.6 replaces prettier and
eslint, with SeaDrop's config. Markdown is excluded (Biome's formatter
breaks the docs front matter), and Biome's linter is off for test/,
which holds the legacy Hardhat suite being ported to Foundry.
- lefthook replaces husky and lint-staged for the pre-commit hook.
- The CI lint job checks out submodules, installs Foundry, and runs the
three checks as separate steps.
Biome's formatter and safe fixes rewrote the TypeScript; both Hardhat
suites still pass (402 and 376).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The front matter and the AuditLink, SeaportDiagramLink, and Overview
stubs only fed the readme.io sync, whose workflow published to the
now-archived developer-docs repo. prepare-docs.js belonged to the same
pipeline. The remaining docs keep their content.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Biome now also formats Markdown and YAML, so every non-Solidity text
file follows one formatter.
- taplo formats foundry.toml (4-space indent via .taplo.toml).
- shellcheck and shfmt check the shell scripts in CI, and actionlint
checks the workflows. Inline FOUNDRY_PROFILE=... prefixes move into
env blocks, which actionlint's shellcheck pass prefers.
- .editorconfig records the indent for each language.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Socket blocks packages published in the last few days, and 2.6.6 is
three days old. 2.6.3 is over two weeks old and produces identical
results on this repo.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This PR migrates Seaport’s formatting and linting to Forge, Biome, and supporting tools while preserving deployed contract sources and compiler settings.
Changes:
Replaces Prettier, ESLint, Solhint, and Husky with Forge checks, Biome, taplo, and lefthook; adds separate CI checks.
Applies formatter output and targeted TypeScript cleanups across tests, mocks, and scripts.
Removes obsolete documentation-sync assets and updates contributor instructions.
File
Description
tsconfig.json
Removes the deleted docs script from compilation inputs.
test/zone.spec.ts
Applies Biome import ordering and callback cleanup.
assertPass raises it for any run that didn't end in the expected passing
status, including failures both implementations share, so it doesn't by
itself mean the optimized and reference builds disagree.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Biome, taplo, and lefthook came from npm, which puts a registry and its
dependency tree in the path of every lint run. scripts/install-tools.sh
now downloads them, plus shellcheck, shfmt, and actionlint, from each
tool's GitHub release into .tools/bin and checks every file against a
pinned SHA-256, so a replaced asset fails the install. All six releases
are at least two weeks old.
scripts/lint.sh runs the same checks as CI and warns when the local
Foundry differs from CI's. The CI lint job no longer installs Node.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ryanio
changed the title
Replace prettier, eslint, and solhint with Biome and forge lint
Replace prettier, eslint, and solhint with Biome and forge lint, installed without npm
Nov 10, 2026
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Formatting checks skip reference/, allowing reference-only regressions to pass locally and in CI; both lint branches and the CI workflow need explicit formatting paths that include it.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Include reference files in forge fmt checks and fixes
scripts/lint.sh:20
With the default profile, forge fmt checks contracts/, test/foundry/, and script/, but skips reference/, so reference-only formatting regressions pass both local checks and CI. Pass contracts test/foundry script reference explicitly to forge fmt in both the check and fix branches. Apply the same change to .github/workflows/test.yml:64.
forge fmt with no arguments covers only the profile's src, test, and
script dirs, so reference/ was never formatted or checked. lint.sh and
CI now pass contracts, test, script, and reference explicitly; the
deployed contracts stay excluded by the fmt ignore list.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot's body-only finding was right, and it's fixed in f0f6bc8. With no arguments, forge fmt covers only the profile's contracts, test/foundry and script dirs, so reference/ was never formatted. That also means the first commit's message overstates what it did. reference/ is now formatted (20 files, whitespace only; it still compiles), and scripts/lint.sh and the CI step pass contracts test script reference explicitly. The deployed contracts stay excluded through the [fmt] ignore list, which still applies with explicit paths.
Review: 7/10. Safe to merge once the two P1s are fixed.
What checks out:
No contract changes. I compared all 176 changed .sol files token by token, ignoring whitespace, comments and quote style. The only real difference is the braces added in FuzzEngineLib.sol, and those don't change behaviour.
Only test mocks touched under contracts/. The edits are all in contracts/test/.
Tool installs look safe.install-tools.sh downloads pinned release URLs and checks each SHA-256 before extracting. There's no curl | sh.
CI looks right. CI has contents: read, third-party actions are SHA-pinned, and I found nothing left that still references prettier, eslint or solhint.
P0: none
P1:
test/utils/seeded-rng.js:66,89: Biome turned the Mash and uheprng constructors into arrow functions, but lines 102 and 267 still call them with new.
Failure: With REPORT_GAS set, test/utils/encoding.ts calls SeededRNG.create("gas-report") when it's imported. So yarn profile and yarn profile:nospec throw TypeError: uheprng is not a constructor before any test runs. I reproduced this in Node.
Fix: Revert the file to the version before this PR, and add it to Biome's ignore list, since it's vendored code.
lefthook.yml:5-10: the forge fmt {staged_files} pre-commit hook skips most of the [fmt] ignore list.
Cause: When a file path is passed explicitly, Forge 1.9.0 honours only the exact-path entry (contracts/Seaport.sol), not the ** globs.
Repro:forge fmt --check contracts/conduit/ConduitController.sol and contracts/zones/PausableZone.sol both exit 1. forge fmt --check contracts exits 0.
Failure: Edit a comment in ConduitController.sol and commit. The hook reformats the whole deployed file and re-stages it (stage_fixed: true). CI won't catch this either: the directory-level fmt check skips the file, and DeployedBytecode.t.sol only covers Seaport. This also contradicts the README's statement that deployed contracts are excluded from forge fmt.
Fix: Add the same globs to that job's exclude list in lefthook.yml. Ideally, also add a CI guard that fails when contracts/{Seaport.sol,conduit,helpers,interfaces,zones} change.
P2 / optional:
Bytecode check coverage: extend DeployedBytecode.t.sol to cover ConduitController and Conduit as well, to back up the claim that the deployed contracts are frozen.
Dead lint comments: the eslint-disable comments left in test/ (e.g. seeded-rng.js:1-2, fixtures/index.ts:766) no longer do anything. Drop them or convert them to biome-ignore.
Commit message: commit 1 says it formatted reference/, but that formatting happened in f0f6bc8a.
Windows:install-tools.sh supports only macOS and Linux, so Windows contributors lose yarn lint:check. Worth noting in the README.
Name the settings the optimized profile inherits from the default
profile, note that tests need both builds, add the single bytecode check
command, and correct who closed seaport-core#10.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Biome rewrote the vendored Mash and uheprng constructors as arrow
functions, so `new uheprng()` threw when REPORT_GAS was set. Restore
the original file and exclude it from Biome.
forge fmt applies only exact-path ignores when given files, so the
pre-commit hook would reformat deployed contracts. Exclude them in
lefthook too, and pin their sources in scripts/frozen-contracts.sha256,
which CI and scripts/lint.sh check.
Drop the eslint-disable comments Biome doesn't read, and note that the
tool installer needs WSL on Windows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
seeded-rng.js: I reproduced TypeError: uheprng is not a constructor with the old file. The file is now byte-identical to main and excluded from Biome as vendored code, and SeededRNG.create("gas-report") works again. I also checked every other function-to-arrow rewrite in the diff. The rest are Mocha describe callbacks whose bodies never use this or arguments, so they behave the same.
lefthook.yml: confirmed with Forge 1.9.0. With explicit paths, forge fmt --check exits 1 on ConduitController.sol, PausableZone.sol, and SeaportRouter.sol, and only Seaport.sol is skipped. The forge fmt job now excludes the same globs, and lefthook run pre-commit on those files now skips them while still formatting contracts/test/. For the CI guard, scripts/frozen-contracts.sha256 pins all 48 deployed sources. CI and scripts/lint.sh check run shasum -a 256 --check against it, so any edit fails, whitespace included. A deliberate change regenerates it with scripts/lint.sh freeze, and that shows up in review.
P2s:
I didn't extend DeployedBytecode.t.sol to ConduitController. Etherscan shows the deployed controller was compiled with solc 0.8.14 at 1,000,000 runs, so this repo's 0.8.24 build can't reproduce it, and Conduit's code comes from the controller. The source manifest covers both instead.
The dead eslint-disable comments are gone. Biome's linter is off for test/, so they needed no biome-ignore replacement.
The commit message overstated it, as I noted above. I'm leaving history as is instead of force-pushing.
The README now says the installer supports macOS and Linux, and to use WSL on Windows.
SeaDrop's only npm dependencies were two dev tools, Biome and lefthook.
This replaces them with the same pinned tooling seaport now uses
([seaport#1429](ProjectOpenSea/seaport#1429)),
so the repo has no Node or npm dependencies at all.
- `scripts/install-tools.sh` downloads Biome, taplo, lefthook,
shellcheck, shfmt and actionlint from their GitHub releases into
`.tools/bin`, and checks each file against a pinned SHA-256. It's the
same script as seaport's.
- `scripts/lint.sh check` runs what CI runs: `forge fmt --check`, the
Seaport pragma patch, `forge lint --deny warnings`, Biome, taplo,
shellcheck, shfmt and actionlint. `scripts/lint.sh fix` applies the
formatters.
- CI's lint job installs the tools (cached by the install script's hash)
instead of setting up Node and running `npm ci`.
- `package.json`, `package-lock.json` and `.nvmrc` are gone.
`.gitignore` ignores `.tools/` instead of `node_modules`.
- Biome is pinned at 2.6.3, the version seaport uses. 2.6.6, which
`package.json` had, was released on November 6, which is under the two
weeks we wait before pinning a release. Its output on this repo is
unchanged.
- `lefthook.yml` runs the binaries from `.tools/bin` and also formats
TOML and shell scripts.
- The shell scripts are reindented to four spaces for shfmt, and seven
unquoted variables that shellcheck flagged in `check_deployments.sh`,
`find_optimizer_runs.sh` and `forge_script_multichain.sh` are now
quoted.
- AGENTS.md and the docs replace the `npm run` commands with the scripts
and the plain build command.
No Solidity changes. The same change for `main` is
[seadrop#229](#229).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
ryanio
added a commit
to ProjectOpenSea/seadrop
that referenced
this pull request
Nov 10, 2026
SeaDrop's only npm dependencies were two dev tools, Biome and lefthook.
This replaces them with the same pinned tooling seaport now uses
([seaport#1429](ProjectOpenSea/seaport#1429)),
so the repo has no Node or npm dependencies at all.
- `scripts/install-tools.sh` downloads Biome, taplo, lefthook,
shellcheck, shfmt and actionlint from their GitHub releases into
`.tools/bin`, and checks each file against a pinned SHA-256. It's the
same script as seaport's.
- `scripts/lint.sh check` runs what CI runs: `forge fmt --check`, `forge
lint --deny warnings`, Biome, taplo, shellcheck, shfmt and actionlint.
`scripts/lint.sh fix` applies the formatters.
- CI's lint job installs the tools (cached by the install script's hash)
instead of setting up Node and running `npm ci`.
- `package.json`, `package-lock.json` and `.nvmrc` are gone.
`.gitignore` ignores `.tools/` instead of `node_modules`.
- Biome is pinned at 2.6.3, the version seaport uses. 2.6.6, which
`package.json` had, was released on November 6, which is under the two
weeks we wait before pinning a release. Its output on this repo is
unchanged.
- `lefthook.yml` runs the binaries from `.tools/bin` and also formats
TOML and shell scripts.
- `scripts/check_sizes.sh` is reindented to four spaces for shfmt.
That's whitespace only.
- AGENTS.md and the docs replace the `npm run` commands with the scripts
and the plain `forge coverage` command.
No Solidity changes. A matching PR for the `v2` branch follows.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #1428. It retargets to
mainonce the earlier PRs merge.Moves linting off the Node toolchain and off npm entirely: every tool is a pinned binary checked against a recorded SHA-256.
forge fmtandforge lint --deny warnings(configured infoundry.toml) instead of prettier-plugin-solidity and solhint. The deployed contracts (Seaport.sol,conduit/,helpers/,interfaces/,zones/) are excluded, so their source still matches what was verified onchain. Lint also skipscontracts/test/, whose mocks are deliberately unsafe.test/, which holds the legacy Hardhat suite that later PRs port to Foundry. Formatting is still enforced there.foundry.tomlis formatted with taplo. Shell scripts get shellcheck and shfmt, and workflows get actionlint..editorconfigrecords each language's indent.scripts/install-tools.shinstalls Biome, taplo, lefthook, shellcheck, shfmt, and actionlint into.tools/binfrom each tool's GitHub release. Every file is checked against a pinned SHA-256, so a replaced asset fails the install, and nothing comes from a package registry. Every release is at least two weeks old.scripts/lint.sh check|fixruns what CI runs, and warns when the local Foundry differs from CI's. The CI lint job no longer installs Node.Commits
forge fmtover tests, scripts, mocks, andreference/. Whitespace and line wrapping only, so review it with whitespace hidden. The bytecode check still passes, andreference/isn't deployed.forge lintfindings in four test files:block.timestampreads in functions that callvm.warp, whichvia_ircan cache across the warp. They now usevm.getBlockTimestamp().prepare-docs.js. They only fed the docs sync, whose destination repo is archived, and Biome's Markdown formatter mangles front matter. This commit also carries Biome's Markdown reformatting ofdocs/.FOUNDRY_PROFILE=...prefixes in workflows move intoenv:blocks.scripts/lint.sh, replacing the npm packages for Biome, taplo, and lefthook.forge fmtoverreference/, which the first commit missed (plainforge fmtskips it), and explicit fmt paths inlint.shand CI so it stays checked.Verification
scripts/lint.sh check(forge fmt, forge lint, Biome, taplo, shellcheck, shfmt, actionlint) is clean locally with Foundry 1.9.0.scripts/install-tools.shinstalls all six tools on macOS arm64, skips them on a second run, and refuses to install a tool when its hash doesn't match.yarn testwith 402 passing andyarn test:refwith 376 passing. One localtest:refrun had two flaky failures under load; the rerun was clean.🤖 Generated with Claude Code