Repository navigation
chore: CI and tooling upgrades (actions, TypeScript 6, husky 9, solhint 6, oxfmt) - #2605
philippzentner wants to merge 18 commits into
Conversation
Node 22 reaches end-of-life on 2027-04-30. Pin CI and .nvmrc to Node 26, raise engines.node to >=24 so developers on the 24 LTS line keep working, and move @types/node to 24.19.2 to match the lowest supported runtime.
tj-actions/changed-files was compromised in March 2025. The Olympix job only needs the added/copied/modified/renamed src/**/*.sol list and a boolean, which dorny/paths-filter (already used elsewhere) provides with identical semantics.
The immutable-registry job used bun-version: latest; use bun-version-file: package.json like every other setup-bun step.
Bump the overrides still needed to the latest safe version within their current major (protobufjs 7.6.6, axios 1.21.0, smol-toml 1.9.1, lodash 4.18.1, katex 0.18.11, ws 8.22.1, ip-address 10.7.5, fast-uri 3.1.9; markdown-it is already at the latest 14.x) and move the direct axios and smol-toml pins with them. Drop socks, validator and handlebars: without the override the tree already resolves a non-vulnerable version. bun audit: 83 -> 60.
Node 24+ matches engines.node; .nvmrc now selects 26. Bun follows the packageManager pin, which CI also uses.
Unify actions/checkout on v7.0.1 (four different v4 SHAs were in use) and move every other external action to its latest release, SHA-pinned with a version comment.
Minor and patch bumps for bun.lock dependencies arrive as one grouped PR per month, with at most 5 open Dependabot PRs. The github-actions entry stays weekly and ungrouped.
Moves the submodule to the v1.17.0 tag commit (f3dae6e) and updates foundry.lock. src artifacts compile to identical bytecode, and forge test gives the same pass/fail set as before.
TypeScript 7 (the native Go port) only ships the tsc binary and an
unstable API under typescript/unstable/*; require('typescript') returns
just the version. The node-runtime and funnel fences, validate-scripts
and several placement tests use the classic compiler API, so 6.0.3 is the
newest release that works.
husky 9: prepare runs `husky` (no `husky install`), and hooks no longer source husky.sh. husky 9's wrapper still runs hooks under `sh -e`, so pre-commit and pre-push keep re-execing themselves under `bash -e`, now behind their own guard variable instead of husky v8's husky_skip_init. lint-staged 17: the pre-commit output filter also drops the new progress lines so failures still show only the tool output.
solhint 6 adds use-natspec, function-max-lines and seven gas-* rules to solhint:recommended, which would raise ~900 warnings on src/. They are turned off to keep the v5 rule set; the other new recommended rules (duplicated-imports, no-immutable-before-declaration, no-unchecked-calls) report nothing on src/ and stay on. no-unused-vars now also checks modifier parameters (solhint 6.0.1) and flags the unused _polymerData parameter of PolymerCCTPFacet's validatePolymerData modifier. Fixing it changes src bytecode, so the rule drops to warn and lint:sol reports 0 errors, 1 warning. .solhint.json is plain JSON and solhint rejects extra keys, so the reasons live here.
.oxfmtrc.json is generated by `oxfmt --migrate=prettier` from .prettierrc.cjs (same options, .prettierignore entries as ignorePatterns). Prettier stays on 2.8 + prettier-plugin-solidity 1.4 for *.sol only: Prettier 3 + plugin 2 would reformat 113 .sol files (49 under src/), and any src/*.sol change alters bytecode metadata. solhint-plugin-prettier stays on 0.0.5 because 0.1.0 needs Prettier 3. Updates the format scripts, lint-staged, the agent format hook, the factory format check, the docs that name the formatter and the VS Code settings template.
Mechanical output of `bun format:fix` after the switch to oxfmt. No .sol file changes. Listed in .git-blame-ignore-revs. Committed with --no-verify: lint-staged's typecheck-files step fails on script/demoScripts/demoChainflip.ts with the same 4 type errors it has on main. oxlint, both fences and typecheck of the other 89 files pass.
- node-gyp 10 -> 13 - plop 3 -> 4 (bun codegen --help and a non-interactive facet run work) - @typechain/ethers-v5 10 -> 11: same 369 files; inputs lose the PromiseOrValue<T> wrapper and overloaded event keys use full tuple signatures. No script uses either; tsc reports the same errors. - markdownlint-cli2 0.23.3 -> 0.24.0 (lint:md clean) - @types/bun 1.2 -> 1.4 - patch-package removed together with its postinstall step: the repo has no patches/ directory, so it never applied anything.
|
Important Review skippedToo many files! This PR contains 150 files, which is 50 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.
|
Its header says only humans edit the factory rules, so the switch of its format check to oxfmt is left to a maintainer.
The file has 4 type errors on main, including an undefined lifiDiamondAddress, so they can't be fixed with type-only changes. Reformatting it made validate-scripts type-check it and fail. It is restored byte-for-byte to main and listed in the oxfmt ignorePatterns. lint-staged's oxfmt entry gets --no-error-on-unmatched-pattern so staging an ignored file doesn't fail the commit. Committed with --no-verify: staging the file makes lint-staged's typecheck-files step report its 4 pre-existing errors, which happens for any commit that touches it on main too.
v11 drops PromiseOrValue<T> from common.ts and every input type and renames overloaded event keys. types.yaml publishes this output to lifinance/lifi-contract-types as a patch/minor release, so v11 would break downstream TS consumers. It needs a coordinated major release of lifi-contract-types plus a downstream migration. The typechain output is identical to the lifinance#2604 baseline again.
|
Thanks for this, @philippzentner! Fork PRs can't run our secret-backed CI, so we've moved your commits (merged in unchanged, still signed by you) to an internal PR, stacked on #2607 (the internal copy of #2604): #2609. Changes on top of yours:
Closing this one in favour of #2609. Review continues there. |
…nt 6, forge-std) (#2609) * ci: bump Node 22 to 26 ahead of Node 22 end-of-life Node 22 reaches end-of-life on 2027-04-30. Pin CI and .nvmrc to Node 26, raise engines.node to >=24 so developers on the 24 LTS line keep working, and move @types/node to 24.19.2 to match the lowest supported runtime. * ci: replace tj-actions/changed-files with dorny/paths-filter in Olympix tj-actions/changed-files was compromised in March 2025. The Olympix job only needs the added/copied/modified/renamed src/**/*.sol list and a boolean, which dorny/paths-filter (already used elsewhere) provides with identical semantics. * ci: pin bun in validateScripts to package.json packageManager The immutable-registry job used bun-version: latest; use bun-version-file: package.json like every other setup-bun step. * chore(deps): refresh security overrides Bump the overrides still needed to the latest safe version within their current major (protobufjs 7.6.6, axios 1.21.0, smol-toml 1.9.1, lodash 4.18.1, katex 0.18.11, ws 8.22.1, ip-address 10.7.5, fast-uri 3.1.9; markdown-it is already at the latest 14.x) and move the direct axios and smol-toml pins with them. Drop socks, validator and handlebars: without the override the tree already resolves a non-vulnerable version. bun audit: 83 -> 60. * docs: update Node and Bun prerequisites in Setup.md Node 24+ matches engines.node; .nvmrc now selects 26. Bun follows the packageManager pin, which CI also uses. * ci: bump GitHub Actions to their latest releases Unify actions/checkout on v7.0.1 (four different v4 SHAs were in use) and move every other external action to its latest release, SHA-pinned with a version comment. * ci(dependabot): add monthly grouped bun updates Minor and patch bumps for bun.lock dependencies arrive as one grouped PR per month, with at most 5 open Dependabot PRs. The github-actions entry stays weekly and ungrouped. * chore(deps): bump forge-std from v1.16.1 to v1.17.0 Moves the submodule to the v1.17.0 tag commit (f3dae6e) and updates foundry.lock. src artifacts compile to identical bytecode, and forge test gives the same pass/fail set as before. * chore(deps): bump typescript from 5.9 to 6.0 TypeScript 7 (the native Go port) only ships the tsc binary and an unstable API under typescript/unstable/*; require('typescript') returns just the version. The node-runtime and funnel fences, validate-scripts and several placement tests use the classic compiler API, so 6.0.3 is the newest release that works. * chore(deps): bump husky from 8 to 9 and lint-staged from 13 to 17 husky 9: prepare runs `husky` (no `husky install`), and hooks no longer source husky.sh. husky 9's wrapper still runs hooks under `sh -e`, so pre-commit and pre-push keep re-execing themselves under `bash -e`, now behind their own guard variable instead of husky v8's husky_skip_init. lint-staged 17: the pre-commit output filter also drops the new progress lines so failures still show only the tool output. * chore(deps): bump solhint from 5 to 6 solhint 6 adds use-natspec, function-max-lines and seven gas-* rules to solhint:recommended, which would raise ~900 warnings on src/. They are turned off to keep the v5 rule set; the other new recommended rules (duplicated-imports, no-immutable-before-declaration, no-unchecked-calls) report nothing on src/ and stay on. no-unused-vars now also checks modifier parameters (solhint 6.0.1) and flags the unused _polymerData parameter of PolymerCCTPFacet's validatePolymerData modifier. Fixing it changes src bytecode, so the rule drops to warn and lint:sol reports 0 errors, 1 warning. .solhint.json is plain JSON and solhint rejects extra keys, so the reasons live here. * chore(format): format TS/JS with oxfmt instead of Prettier .oxfmtrc.json is generated by `oxfmt --migrate=prettier` from .prettierrc.cjs (same options, .prettierignore entries as ignorePatterns). Prettier stays on 2.8 + prettier-plugin-solidity 1.4 for *.sol only: Prettier 3 + plugin 2 would reformat 113 .sol files (49 under src/), and any src/*.sol change alters bytecode metadata. solhint-plugin-prettier stays on 0.0.5 because 0.1.0 needs Prettier 3. Updates the format scripts, lint-staged, the agent format hook, the factory format check, the docs that name the formatter and the VS Code settings template. * style: reformat TS/JS with oxfmt Mechanical output of `bun format:fix` after the switch to oxfmt. No .sol file changes. Listed in .git-blame-ignore-revs. Committed with --no-verify: lint-staged's typecheck-files step fails on script/demoScripts/demoChainflip.ts with the same 4 type errors it has on main. oxlint, both fences and typecheck of the other 89 files pass. * chore: add .git-blame-ignore-revs for the oxfmt reformat * chore(deps): bump small dev dependencies and drop patch-package - node-gyp 10 -> 13 - plop 3 -> 4 (bun codegen --help and a non-interactive facet run work) - @typechain/ethers-v5 10 -> 11: same 369 files; inputs lose the PromiseOrValue<T> wrapper and overloaded event keys use full tuple signatures. No script uses either; tsc reports the same errors. - markdownlint-cli2 0.23.3 -> 0.24.0 (lint:md clean) - @types/bun 1.2 -> 1.4 - patch-package removed together with its postinstall step: the repo has no patches/ directory, so it never applied anything. * chore(agents): restore factory.yml to its base content Its header says only humans edit the factory rules, so the switch of its format check to oxfmt is left to a maintainer. * chore(format): keep demoChainflip.ts out of the oxfmt reformat The file has 4 type errors on main, including an undefined lifiDiamondAddress, so they can't be fixed with type-only changes. Reformatting it made validate-scripts type-check it and fail. It is restored byte-for-byte to main and listed in the oxfmt ignorePatterns. lint-staged's oxfmt entry gets --no-error-on-unmatched-pattern so staging an ignored file doesn't fail the commit. Committed with --no-verify: staging the file makes lint-staged's typecheck-files step report its 4 pre-existing errors, which happens for any commit that touches it on main too. * chore(deps): keep @typechain/ethers-v5 on 10.x v11 drops PromiseOrValue<T> from common.ts and every input type and renames overloaded event keys. types.yaml publishes this output to lifinance/lifi-contract-types as a patch/minor release, so v11 would break downstream TS consumers. It needs a coordinated major release of lifi-contract-types plus a downstream migration. The typechain output is identical to the #2604 baseline again. * fix: address review findings on fork PR #2604 - Restore the validator 13.15.26 override: tronweb pins 13.15.23, which still carries AIKIDO-2025-10980 (see #2257). - Pin dorny/paths-filter to v3.0.4: list-files: shell is affected by GHSA-7hc6-8hq5-9q2m below 3.0.4. - Raise the Node minimum to 26 (engines, @types/node 26.6.6, Setup.md) to match .nvmrc, CI and the factory doctor check. - Correct the setup-bun version comment (the SHA is v2.1.2) and quote $GITHUB_ENV in the Olympix args step. - Reword the node-runtime fence comment: the allowlist follows what a .ts entry gets under tsx, not a Node version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci(olympix): scope permissions to the job Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: pin Bun and Node in every Bun job, unify paths-filter - Pin the three remaining setup-bun@v2 steps to v2.1.2 with bun-version-file, and install with --frozen-lockfile in validate-scripts - Add setup-node (node-version-file: .nvmrc) after every setup-bun step, so scripts run by `bunx tsx` use the Node that engines requires; the two existing setup-node steps also read .nvmrc - Move every dorny/paths-filter call site to v3.0.4 - Olympix: read the changed-file list as JSON and fail on whitespace in a path instead of re-parsing shell output with xargs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: address review findings on fork PR #2605 - factory.yml: check TS/JS format with oxfmt, which now owns it. - Drop .git-blame-ignore-revs: it names a fork-branch SHA that a squash merge discards. Add the main-branch SHA after merge. - dependabot: 7-day cooldown on bun updates, and ignore the majors this PR holds back (@typechain/ethers-v5, prettier, prettier-plugin-solidity, solhint-plugin-prettier >=0.1, typescript). - solhint: keep no-unused-vars an error, with validateParameters off so the existing unused modifier parameter in PolymerCCTPFacet does not need a src change. - Drop the ip-address override: its only consumer (socks) is gone. - Pin the bumped dev dependencies to their resolved versions. - .oxfmtrc.json: drop the copy of .prettierignore, which oxfmt reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(format): keep Prettier for TS/JS, drop the oxfmt switch oxfmt follows Prettier 3's output, so switching from Prettier 2.8.8 rewrites ~90 TS/JS files (ternary indentation, trailing commas in type arguments, parentheses around ??) with no way to configure it back. That churn conflicts with every open script branch and pushes this PR past CodeRabbit's 100-file limit. Restore the formatter setup, the reformatted files and the docs/hooks to their pre-switch state, and leave a formatter change for its own PR. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(hooks): source ~/.huskyrc after the bash re-exec husky 9 runs hooks under sh -e, so sourcing ~/.huskyrc before the re-exec ran it under dash on Linux and dropped its unexported variables at exec. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Philipp Zentner <philipp@li.finance> Co-authored-by: Philipp Zentner <philipp.zentner@stomt.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…js 0.6) (#2630) * ci: bump Node 22 to 26 ahead of Node 22 end-of-life Node 22 reaches end-of-life on 2027-04-30. Pin CI and .nvmrc to Node 26, raise engines.node to >=24 so developers on the 24 LTS line keep working, and move @types/node to 24.19.2 to match the lowest supported runtime. * ci: replace tj-actions/changed-files with dorny/paths-filter in Olympix tj-actions/changed-files was compromised in March 2025. The Olympix job only needs the added/copied/modified/renamed src/**/*.sol list and a boolean, which dorny/paths-filter (already used elsewhere) provides with identical semantics. * ci: pin bun in validateScripts to package.json packageManager The immutable-registry job used bun-version: latest; use bun-version-file: package.json like every other setup-bun step. * chore(deps): refresh security overrides Bump the overrides still needed to the latest safe version within their current major (protobufjs 7.6.6, axios 1.21.0, smol-toml 1.9.1, lodash 4.18.1, katex 0.18.11, ws 8.22.1, ip-address 10.7.5, fast-uri 3.1.9; markdown-it is already at the latest 14.x) and move the direct axios and smol-toml pins with them. Drop socks, validator and handlebars: without the override the tree already resolves a non-vulnerable version. bun audit: 83 -> 60. * docs: update Node and Bun prerequisites in Setup.md Node 24+ matches engines.node; .nvmrc now selects 26. Bun follows the packageManager pin, which CI also uses. * ci: bump GitHub Actions to their latest releases Unify actions/checkout on v7.0.1 (four different v4 SHAs were in use) and move every other external action to its latest release, SHA-pinned with a version comment. * ci(dependabot): add monthly grouped bun updates Minor and patch bumps for bun.lock dependencies arrive as one grouped PR per month, with at most 5 open Dependabot PRs. The github-actions entry stays weekly and ungrouped. * chore(deps): bump forge-std from v1.16.1 to v1.17.0 Moves the submodule to the v1.17.0 tag commit (f3dae6e) and updates foundry.lock. src artifacts compile to identical bytecode, and forge test gives the same pass/fail set as before. * chore(deps): bump typescript from 5.9 to 6.0 TypeScript 7 (the native Go port) only ships the tsc binary and an unstable API under typescript/unstable/*; require('typescript') returns just the version. The node-runtime and funnel fences, validate-scripts and several placement tests use the classic compiler API, so 6.0.3 is the newest release that works. * chore(deps): bump husky from 8 to 9 and lint-staged from 13 to 17 husky 9: prepare runs `husky` (no `husky install`), and hooks no longer source husky.sh. husky 9's wrapper still runs hooks under `sh -e`, so pre-commit and pre-push keep re-execing themselves under `bash -e`, now behind their own guard variable instead of husky v8's husky_skip_init. lint-staged 17: the pre-commit output filter also drops the new progress lines so failures still show only the tool output. * chore(deps): bump solhint from 5 to 6 solhint 6 adds use-natspec, function-max-lines and seven gas-* rules to solhint:recommended, which would raise ~900 warnings on src/. They are turned off to keep the v5 rule set; the other new recommended rules (duplicated-imports, no-immutable-before-declaration, no-unchecked-calls) report nothing on src/ and stay on. no-unused-vars now also checks modifier parameters (solhint 6.0.1) and flags the unused _polymerData parameter of PolymerCCTPFacet's validatePolymerData modifier. Fixing it changes src bytecode, so the rule drops to warn and lint:sol reports 0 errors, 1 warning. .solhint.json is plain JSON and solhint rejects extra keys, so the reasons live here. * chore(format): format TS/JS with oxfmt instead of Prettier .oxfmtrc.json is generated by `oxfmt --migrate=prettier` from .prettierrc.cjs (same options, .prettierignore entries as ignorePatterns). Prettier stays on 2.8 + prettier-plugin-solidity 1.4 for *.sol only: Prettier 3 + plugin 2 would reformat 113 .sol files (49 under src/), and any src/*.sol change alters bytecode metadata. solhint-plugin-prettier stays on 0.0.5 because 0.1.0 needs Prettier 3. Updates the format scripts, lint-staged, the agent format hook, the factory format check, the docs that name the formatter and the VS Code settings template. * style: reformat TS/JS with oxfmt Mechanical output of `bun format:fix` after the switch to oxfmt. No .sol file changes. Listed in .git-blame-ignore-revs. Committed with --no-verify: lint-staged's typecheck-files step fails on script/demoScripts/demoChainflip.ts with the same 4 type errors it has on main. oxlint, both fences and typecheck of the other 89 files pass. * chore: add .git-blame-ignore-revs for the oxfmt reformat * chore(deps): bump small dev dependencies and drop patch-package - node-gyp 10 -> 13 - plop 3 -> 4 (bun codegen --help and a non-interactive facet run work) - @typechain/ethers-v5 10 -> 11: same 369 files; inputs lose the PromiseOrValue<T> wrapper and overloaded event keys use full tuple signatures. No script uses either; tsc reports the same errors. - markdownlint-cli2 0.23.3 -> 0.24.0 (lint:md clean) - @types/bun 1.2 -> 1.4 - patch-package removed together with its postinstall step: the repo has no patches/ directory, so it never applied anything. * chore(agents): restore factory.yml to its base content Its header says only humans edit the factory rules, so the switch of its format check to oxfmt is left to a maintainer. * chore(format): keep demoChainflip.ts out of the oxfmt reformat The file has 4 type errors on main, including an undefined lifiDiamondAddress, so they can't be fixed with type-only changes. Reformatting it made validate-scripts type-check it and fail. It is restored byte-for-byte to main and listed in the oxfmt ignorePatterns. lint-staged's oxfmt entry gets --no-error-on-unmatched-pattern so staging an ignored file doesn't fail the commit. Committed with --no-verify: staging the file makes lint-staged's typecheck-files step report its 4 pre-existing errors, which happens for any commit that touches it on main too. * chore(deps): keep @typechain/ethers-v5 on 10.x v11 drops PromiseOrValue<T> from common.ts and every input type and renames overloaded event keys. types.yaml publishes this output to lifinance/lifi-contract-types as a patch/minor release, so v11 would break downstream TS consumers. It needs a coordinated major release of lifi-contract-types plus a downstream migration. The typechain output is identical to the #2604 baseline again. * chore(deps): bump @arbitrum/sdk from 3.7 to 4.1 v4 renamed L1ToL2MessageGasEstimator to ParentToChildMessageGasEstimator and exports it from the package root. estimateAll keeps the same arguments and the l2CallValue field, so the demo script only needs the import and constructor rename. * chore(deps): bump bs58 from 4 to 6 bs58 6 ships its own types, so the @ts-expect-error on the default import is no longer needed. decode() now returns a Uint8Array instead of a Buffer; the only consumer passes it to viem's toHex, which accepts both. * chore(deps): bump merkletreejs from 0.3 to 0.6 Output is unchanged: demoGenerateMerkleTree.ts writes a byte-identical outputMerkleProofs.json under 0.3.11 and 0.6.0 (sha256 0ab8f479…), and a comparison over 72 trees (both gasRebates networks plus synthetic trees of 1-70 leaves, including odd counts and a duplicate leaf) gives the same roots and proofs. * chore(deps): bump chalk from 5.6.2 to 6.0.1 chalk 6 only raises the Node floor to 22 (the repo runs Node 26) and changes numeric FORCE_COLOR / ansi256 downsampling, neither of which the scripts use. Kept as an exact pin, like before. * chore(deps): bump dotenv from 16 to 18 and keep it quiet dotenv 17+ logs an "injected env" line on every config() call (to stderr since 18). Pass { quiet: true } at all 34 explicit config() call sites, including the facet demo template, so script output stays the same as on dotenv 16. The 'dotenv/config' side-effect import already defaults to quiet since 18.0.4. No script uses the removed .env.vault support or preloading. Touches signing-path files under script/deploy/safe/ (one-line config() -> config({ quiet: true }) each). * chore(deps): bump @cowprotocol/cow-sdk from 5.10 to 9.3 cow-sdk 7+ takes a provider adapter instead of an ethers signer. The demo now passes a ViemAdapter (@cowprotocol/sdk-viem-adapter) built from the same Arbitrum RPC and private key; the ethers v5 adapter was not used because it peers on @typechain/ethers-v5 11. postSwapOrder now returns an object, so the order id is read from .orderId. The CowShed constants moved to @cowprotocol/sdk-cow-shed and are keyed by version; the helper keeps the 1.0.0 factory and implementation, which are the same addresses cow-sdk 5 exported. * fix: address review findings on fork PR #2604 - Restore the validator 13.15.26 override: tronweb pins 13.15.23, which still carries AIKIDO-2025-10980 (see #2257). - Pin dorny/paths-filter to v3.0.4: list-files: shell is affected by GHSA-7hc6-8hq5-9q2m below 3.0.4. - Raise the Node minimum to 26 (engines, @types/node 26.6.6, Setup.md) to match .nvmrc, CI and the factory doctor check. - Correct the setup-bun version comment (the SHA is v2.1.2) and quote $GITHUB_ENV in the Olympix args step. - Reword the node-runtime fence comment: the allowlist follows what a .ts entry gets under tsx, not a Node version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci(olympix): scope permissions to the job Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: pin Bun and Node in every Bun job, unify paths-filter - Pin the three remaining setup-bun@v2 steps to v2.1.2 with bun-version-file, and install with --frozen-lockfile in validate-scripts - Add setup-node (node-version-file: .nvmrc) after every setup-bun step, so scripts run by `bunx tsx` use the Node that engines requires; the two existing setup-node steps also read .nvmrc - Move every dorny/paths-filter call site to v3.0.4 - Olympix: read the changed-file list as JSON and fail on whitespace in a path instead of re-parsing shell output with xargs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: address review findings on fork PR #2605 - factory.yml: check TS/JS format with oxfmt, which now owns it. - Drop .git-blame-ignore-revs: it names a fork-branch SHA that a squash merge discards. Add the main-branch SHA after merge. - dependabot: 7-day cooldown on bun updates, and ignore the majors this PR holds back (@typechain/ethers-v5, prettier, prettier-plugin-solidity, solhint-plugin-prettier >=0.1, typescript). - solhint: keep no-unused-vars an error, with validateParameters off so the existing unused modifier parameter in PolymerCCTPFacet does not need a src change. - Drop the ip-address override: its only consumer (socks) is gone. - Pin the bumped dev dependencies to their resolved versions. - .oxfmtrc.json: drop the copy of .prettierignore, which oxfmt reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(format): keep Prettier for TS/JS, drop the oxfmt switch oxfmt follows Prettier 3's output, so switching from Prettier 2.8.8 rewrites ~90 TS/JS files (ternary indentation, trailing commas in type arguments, parentheses around ??) with no way to configure it back. That churn conflicts with every open script branch and pushes this PR past CodeRabbit's 100-file limit. Restore the formatter setup, the reformatted files and the docs/hooks to their pre-switch state, and leave a formatter change for its own PR. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(hooks): source ~/.huskyrc after the bash re-exec husky 9 runs hooks under sh -e, so sourcing ~/.huskyrc before the re-exec ran it under dash on Linux and dropped its unexported variables at exec. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: address review findings on fork PR #2606 - pin the bumped SDKs to exact versions - drop the protobufjs override: the cow-sdk 9 tree no longer pulls it in - delete demoArbitrumBridge.ts and @arbitrum/sdk: the demo targets the shut down Goerli testnet and reads a config key that does not exist - leave five demo scripts as on main: their only change was dotenv's quiet flag, and touching them surfaces type errors that predate this PR Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(deps): remove CoW SDKs with the broken demoPatcher demo demoPatcher.ts was the only user of @cowprotocol/cow-sdk, sdk-cow-shed and sdk-viem-adapter. Its post-hook calls RelayFacet, which is no longer on the diamond. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(safe): pin dotenv override off in the Safe scripts dotenv 17+ merges DOTENV_OVERRIDE / DOTENV_CONFIG_OVERRIDE from the shell into every config() call, so an exported flag could let .env replace an exported PRIVATE_KEY or SC_MONGODB_URI. Passing override: false keeps exports ahead of the file. The signing runbook now also stops on any exported DOTENV_* setting, which still applies to propose-to-safe's import 'dotenv/config'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(scripts): load .env through one loader that pins override off The override: false pin in the Safe scripts did not hold: they import viemScriptHelpers.ts and utils.ts, which loaded .env earlier without it, so DOTENV_OVERRIDE still let the file replace an exported value. script/utils/loadEnv.ts now loads .env with override: false and every non-demo script imports it in place of dotenv/config or its own config() call. The signing runbook describes the loader. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(scripts): load .env through loadEnv in demoScriptHelpers demoScriptHelpers.ts called config() without override: false at module load. Thirteen non-demo scripts import it (deploy-safe, execute-pending-timelock-tx, the Tron deployers, checkOffboardingStatusPerNetwork), so DOTENV_OVERRIDE could still let .env replace an exported value after their own loadEnv import ran. The helper and the facet demo template now import loadEnv instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Philipp Zentner <philipp@li.finance> Co-authored-by: Philipp Zentner <philipp.zentner@stomt.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Builds on #2604. Review only the commits listed below; this PR will be rebased once the earlier one merges.
3f07356cf0fa637d95e2fc152a97eb8e1ac86e33a5259ddb8188467c96b6342020350655.git-blame-ignore-revs)80e996323f4e500b2833adcc27c60eda3c5e1f34498d3Which Linear task belongs to this PR?
None. This is CI and tooling maintenance proposed from a fork, so there is no Linear ticket.
Why did I implement it this way?
Nothing under
src/changes and no.solfile changes anywhere; the only Solidity-side change is thelib/forge-stdsubmodule pointer. Compiledsrcoutput is byte-identical (see Verification).1. GitHub Actions (
3f07356cf). Every external action is SHA-pinned with a# vX.Y.Zcomment. SHAs come fromgh api repos/<owner>/<action>/git/ref/tags/<tag>with annotated tags dereferenced.actions/checkoutactions/setup-nodeactions/cache,cache/restore,cache/saveactions/github-scriptactions/upload-artifactactions/download-artifactdorny/paths-filter(including #2604's Olympix step)slackapi/slack-github-actionoven-sh/setup-bunfoundry-rs/foundry-toolchain(in.github/actions/setup-foundry)actions/setup-pythonactions/create-github-app-tokenactions/attest-build-provenancejwalton/gh-find-current-prvoiceflow/draft-prtspascoal/get-user-teams-membershipactions-ecosystem/action-add-labels# v1)# v1.1.3(the latest tag; the GitHub "latest release" v1.1.0 is older)actions-ecosystem/action-remove-labels# v1)# v1.3.0github/codeql-action/upload-sarifolympix/integrated-securitystays at its pinnedmainSHA: the repo has no newer release than v0.1.0.The local composite actions under
.github/actions/*are updated too. I read the release notes for every major in between. No workflow needed a change; this is what I checked:pull_request_target/workflow_run: the onlypull_request_targetworkflow (convertForkedPRsToInternal.yml) checks out the base ref, so it is unaffected.packageManageris set, but v6 limited that to npm, and this repo declares bun, so there is no new implicit cache.require('@actions/github')fail and turnsgetOctokitinto an injected parameter. The four scripts onlyrequire('fs')/require('child_process')and never declaregetOctokit.archive: false.name, so nothing changes. v8 fails on a digest mismatch by default (it used to warn).webhook,webhook-type,payload,errors). v3 moves to Node 24 and v4 parsespayloadYAML with stricter multi-line indentation. All 10 payloads are either one-line YAML or JSON whose dynamic values go throughtoJSON()or contain literal\n, so nothing spans an unindented line.NODE_USE_ENV_PROXYfor proxies (we use none) and deprecatesapp-idin favour ofclient-id.qa-review-trigger.ymlkeepsapp-id, which still works, because switching needs a new secret holding the app's client ID."true"/"false", which is whatdiamondEmergencyPause.ymlcompares.2. Dependabot (
0fa637d95). Abunentry checks/monthly, groups minor and patch updates into one PR and allows at most 5 open PRs. I left thegithub-actionsentry weekly and ungrouped. The team does not work the Dependabot queue today: every github-actions Dependabot PR since 2024 was closed unmerged, the last one opened in July 2025, and action bumps arrive as hand-made PRs. Whether to group that ecosystem too is the maintainers' call.3. forge-std v1.16.1 → v1.17.0 (
e2fc152a9). The submodule moves to the v1.17.0 tag commitf3dae6e, andfoundry.lockfollows.srcartifacts are byte-identical (bytecodeanddeployedBytecode), with both Foundry 1.8.7 and the 1.7.1 pinned in.foundry-version.gasStateUsedfield toVm.Gasand recommends Foundry ≥ 1.8.3 when decoding it. Nothing insrc/,test/orscript/useslastCallGas/Vm.Gas, so the 1.7.1 pin does not hit this. Worth keeping in mind for the next.foundry-versionbump.4. TypeScript 5.9 → 6.0.3, not 7.x (
7eb8e1ac8). TypeScript 7 (the Go port) works as a type checker:tsc-filescallsnode_modules/.bin/tsc, and typechain's ethers-v5 target only readsrequire('typescript').version. But TS 7'stypescriptpackage no longer exposes the compiler API (require('typescript')returns only{ version }, and the API lives undertypescript/unstable/*). 13 repo files use the classic API, includingscript/utils/fence-runner.ts,node-runtime-fence.ts,validateScripts.ts,cittyArgDefaults.ts,rpc-url-log-scan.tsand six*-placement.test.tsfiles underscript/deploy/safe/. With TS 7,bun lint:node-runtimecrashes and a whole-projecttscgoes from 38 to 204 errors. Porting them to the unstable API would rewrite the fences and signing-path tests, which is out of scope here, so 6.0.3 is the newest version that works.tsc --noEmitreports the same 38 pre-existing errors as 5.9 (all inscript/demoScripts/).validate-scripts,tsc-files, typechain,bun testand plop all work. No workflow callstscdirectly.5. husky 8 → 9, lint-staged 13 → 17 (
6e33a5259).prepareis nowhusky(nohusky install, andprepare:huskyis gone). Hooks no longer sourcehusky.sh..husky/_/h) still runs hooks assh -e <hook>, so the problem the long comment describes still applies..husky/pre-commitand.husky/pre-pushkeep re-execing underbash -e, now behind their own guard variable (LIFI_HOOK_BASH) instead of husky 8'shusky_skip_init.HUSKY=0and~/.huskyrckeep working (husky 9 only warns about~/.huskyrcand no longer sources it).*.solbash -c '…' _task correctly. I checked by staging a test.solchange with ano-global-importviolation: solhint ran and blocked it.⋯/✔progress lines, so a failure still shows only the tool output.sh→ thebash -ere-exec. A staged TS file with a type error was rejected ("Lint-staged failed. Aborting commit.").6. solhint 5 → 6.2.5 (
ddb818846).bun lint:solgives 0 errors and 1 warning (it was 0/0).solhint:recommended. Eight of them would raise about 900 warnings onsrc/, so they are set tooffto keep the v5 rule set:use-natspec(710),gas-indexed-events(60),function-max-lines(50),gas-calldata-parameters(38),gas-small-strings(17),gas-increment-by-one(16),gas-struct-packing(10) andgas-strict-inequalities(7).duplicated-imports,no-immutable-before-declaration,no-unchecked-calls) report nothing onsrc/and stay on.no-unused-varschanged behaviour in 6.0.1: it now checks modifier parameters. It flags a real finding, the unused_polymerDataparameter ofPolymerCCTPFacet.validatePolymerData(src/Facets/PolymerCCTPFacet.sol:153). Fixing that changessrcbytecode, so the rule goes fromerrortowarn(parameter checking stays on) and the finding is left for maintainers. The alternative,validateParameters: false, would also drop the function-parameter checks v5 had..solhint.jsonis plain JSON and solhint rejects unknown keys (I tried a"//"key), so these reasons live in the commit message instead of inline comments.7. Formatting (
7c96b6342,020350655,80e996323)..sol: stays on Prettier 2.8.8 + prettier-plugin-solidity 1.4.3 (the ranges are tightened to what was already resolved). I tried Prettier 3.9.10 + plugin 2.4.1 with the same options: it would rewrite 113.solfiles (49 insrc/, 58 intest/, 6 inscript/), and anysrc/*.solchange alters bytecode metadata.solhint-plugin-prettierstays on 0.0.5 because 0.1.0 has a peer dependency on Prettier 3..oxfmtrc.jsoncomes fromoxfmt --migrate=prettieron.prettierrc.cjs: same options, and the.prettierignoreentries becomeignorePatterns. I dropped the*.soloverride and the*.tsparser association, since oxfmt doesn't format Solidity and defaults to TypeScript..prettierrc.cjsloses its now-dead*.tsoverride.format/format:fixscripts (oxfmt for**/*.{ts,js}, Prettier for**/*.sol), the lint-staged*.{ts,js}entry,.agents/hooks/post-edit-format.sh, the formatter mentions inAGENTS.md/.agents/context.md,CLAUDE.mdand.agents/rules/{099,402}, and.vscode/settings.json.default(oxc as the TS/JS formatter; both extensions were already recommended)..agents/factory/factory.ymlis unchanged in the end: its header says only humans edit it, so33adcc27crestores it exactly (see Human follow-up).script/demoScripts/demoChainflip.tsis kept out of the reformat (60eda3c5e). It has 4 type errors on main, and one is a reference to an undefinedlifiDiamondAddress, so they cannot be fixed with type-only changes. Reformatting it madevalidate-scripts(and thevalidateScriptsCI job) type-check it and fail. It is restored byte-for-byte to main and listed in.oxfmtrc.jsonignorePatternswith a comment saying why. The lint-staged oxfmt entry gets--no-error-on-unmatched-pattern, so staging an ignored file doesn't fail the commit.script/deploy/safe/propose-funnel-fence.test.tsasserts the lint-staged task order and expectedprettier --writefirst. It now expectsoxfmt, which the formatter change strictly requires.020350655) is purebun format:fixoutput: 90 TS/JS files, +333/−339, with no.solchanges. The changes are Prettier-3-style nested-ternary indentation, trailing commas in multi-line type arguments and parentheses around??inside ternaries. Its SHA is in.git-blame-ignore-revs, so it needs updating if the commit is rebased.8. Small bumps (
f4e500b28, plus the revert in1f34498d3).bun codegen --helpworks, and a non-interactiveplop facet PlopSmoke "smoke test"generated all 7 files (removed afterwards).^10.2.0, resolved to 10.2.1, the latest 10.x).f4e500b28had bumped it to 11.1.2, and1f34498d3reverts that.PromiseOrValue<T>fromcommon.tsand from every input type, and overloaded event keys switch from'Event(tuple)'to full tuple signatures..github/workflows/types.yamlpublishes this output tolifinance/lifi-contract-typesas a patch/minor release, so v11 would break downstream TS consumers (lifi-backend etc.) without a major version.diff -rshows no differences.bun lint:md: 0 issues in 267 files).postinstallstep: the repo has nopatches/directory, so it never applied anything.Security-relevant paths touched (please review):
.github/**(all workflows,dependabot.yml,.github/actions/setup-foundry) and.husky/pre-commitmatchprotectSecurityRelevantCode.yml, so that approval gate applies.diamondEmergencyPause.yml(break-glass) only gets new pins for checkout, setup-bun, tspascoal and slack.script/deploy/safe/**: 48 files change only through the mechanical oxfmt reformat, plus the one-line lint-staged-order assertion inpropose-funnel-fence.test.ts. No logic changes.bun test:tsgives the same result as base: its only failure, inpinned-target-state.test.ts, also fails on base.Verification (local, Node 26.13.0, bun 1.4.4, Foundry 1.8.7; forge-std/bytecode also checked with Foundry 1.7.1 from
.foundry-version). The base is #2604's head. I ran pass 1 after implementing and pass 2 aftergit clean -xfdplus removingnode_modules,out,cacheandtypechain.bun install --frozen-lockfilebun lint(oxlint + solhint)bun lint:mdbun formatbun test:ts60eda3c5e: samebun validate-scripts(afterbun typechain:incremental, as CI does)60eda3c5eforge buildbun attestations:checkforge build src(159srcartifacts)bun typechain1f34498d3(10.2.1): identical to base except path-dependent metadatabun test:ts: the one failure (createPinnedTargetStateReader > reads the remote-tracking ref…) also fails on base. It depends on the local git environment.ETH_NODE_URI_*. They fail identically on base.validate-scriptspasses after60eda3c5e. Before that commit, the reformat ofdemoChainflip.tsmade it report that file's 4 pre-existing errors.bun lint(0 errors, 1 warning),bun formatandbun test:tswere re-run after the follow-up commits with the results above.--no-verifyuses:020350655: lint-staged'stypecheck-filesstep fails ondemoChainflip.tswith its pre-existing errors. oxlint, both fences and the typecheck of the other 89 files passed.60eda3c5e: it stagesdemoChainflip.ts(restoring it), and the same step reports the same pre-existing errors, which any commit touching that file hits on main.demoChainflip.tsis in that range (reformatted, then restored). The PR-level diff no longer touches the file, andbun validate-scriptsagainst the base passes.1f34498d3went through the hooks (pre-push validation passed), as did all other commits.1f34498d3:bun lintpasses with 0 errors and 1 warning, andbun validate-scriptspasses (91 changed files type-checked).bun test:tsgives 7206 pass and 1 fail, the same failure as base.Human follow-up:
.agents/factory/factory.ymlstill hasformat: [bunx, prettier, --check]for TS/JS. Its header says only humans edit it, so a maintainer should switch it to[bunx, oxfmt, --check], because Prettier no longer formats TS/JS in this repo.Not runnable on a fork PR: the RPC-backed forge fork tests, coverage, Olympix and every other secret-backed job. None of the bumped actions could be exercised locally; the release-note review above is the evidence for them, and CI on this PR is the first real run.
Checklist before requesting a review
Checklist for reviewer (DO NOT DEPLOY and contracts BEFORE CHECKING THIS!!!)