Skip to content

chore: bump forge-std 1.16.1 -> 1.16.2, including the prefix rewrite the pin forces - #126

Merged
thedavidmeister merged 8 commits into
mainfrom
2026-08-16-issue-90
Aug 17, 2026
Merged

chore: bump forge-std 1.16.1 -> 1.16.2, including the prefix rewrite the pin forces#126
thedavidmeister merged 8 commits into
mainfrom
2026-08-16-issue-90

Conversation

@thedavidmeister

@thedavidmeister thedavidmeister commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Closes #90

forge-std is the repo's only dependency and it was pinned a version behind:
1.16.1 (published 2026-05-08) against 1.16.2 (published 2026-07-03, still
the newest revision on the Soldeer registry as of this PR).

The version is baked into the import prefix, so this is a coordinated rewrite
rather than a lockfile bump. Moved together:

  • foundry.toml [dependencies] forge-std
  • soldeer.lock (version, url, checksum, integrity)
  • remappings.txt
  • 31 import statements across 29 files in src/ and test/
  • two prose references to the pinned version, in foundry.toml:22 and
    test/src/lib/LibFs.isPresent.t.sol:14, both stating that no forge-std
    cheatcode creates a symlink

That is the whole diff. git diff origin/main on the merge commit is 32 files,
+39/-39, and 39 is exactly 31 imports + 1 pin + 1 remapping + 4 lockfile fields + 2 prose lines. Nothing else moves.

Note

Re-resolved against post-#56, post-#138 main. #138 deleted
script/Build.sol, src/generated/CodeGennable.sol and
.github/workflows/build-pointers.yaml; #56 then moved every .t.sol into
the test/src/** mirror tree. This branch's prefix rewrite of
script/Build.sol is dropped — the file is gone — and every hunk it had
against test/lib/*.t.sol is re-sited onto its test/src/lib/ destination.
Five files that landed on main after this branch was cut carry the old
prefix and are rewritten here too: #119's four test/src/interface/*.t.sol
suites and #107's test/src/lib/LibCodeGen.commentPrefix.t.sol. That set is
derived from a grep over the merged tree, not from a list, and the grep is
re-run to zero afterwards — any other post-base addition would be caught the
same way. The bump itself is untouched. See "What the merges removed from this
PR" below.

Downstream consequence: this is a republish cascade

src/lib/*.sol ships in the published soldeer package carrying its import
prefixes
. src/lib/LibCodeGen.sol, src/lib/LibFs.sol and
src/lib/LibHexString.sol each open with
import {Vm} from "forge-std-1.16.2/src/Vm.sol";, and that literal string is
what a consumer compiles. So once this lands and rain-sol-codegen republishes,
every consumer must have forge-std 1.16.2 installed under exactly that
prefix
— a consumer still on 1.16.1 gets Source "forge-std-1.16.2/src/Vm.sol" not found the moment it takes the new revision.
Consumers move their own pin in lockstep with taking this package's bump; they
do not get to take one without the other. This is a fact about the change, not a
reason not to make it.

Where the issue's proposed fix was wrong

The issue proposed forge soldeer update as the step that moves the version.
Measured here, it does not:

$ nix develop -c forge soldeer update   # foundry.toml still says 1.16.1
└  Done updating!
$ grep forge-std foundry.toml soldeer.lock remappings.txt
foundry.toml:forge-std = "1.16.1"
soldeer.lock:version = "1.16.1"
remappings.txt:forge-std-1.16.1/=dependencies/forge-std-1.16.1/

forge-std = "1.16.1" is an exact requirement, so update re-resolves to the
same revision and is a no-op. The version has to be raised in foundry.toml
first; update then re-resolves, refreshes the lockfile and downloads the new
tree.

Two further things the proposed fix would have left behind, both measured:

  1. soldeer does not prune. After bumping the pin and running update,
    dependencies/forge-std-1.16.1/ is still on disk and remappings.txt holds
    both lines:

    forge-std-1.16.1/=dependencies/forge-std-1.16.1/
    forge-std-1.16.2/=dependencies/forge-std-1.16.2/
    

    Deleting the stale directory and re-running update does not remove its
    remapping line either — soldeer merges into remappings.txt and never drops
    entries. Left in place, that line maps a prefix to a path that does not exist
    on a clean checkout, and locally (where the old directory survives) it hides
    an incomplete prefix rewrite behind a green build. The remappings.txt here
    is the single line that rm -rf dependencies && forge soldeer update
    produces, re-verified on this merge commit against that exact command:
    git diff --exit-code -- remappings.txt soldeer.lock returned 0 afterwards,
    so both files came back byte-identical to what is committed, with
    dependencies/ holding forge-std-1.16.2 and nothing else.

  2. The issue's grep -rl 'forge-std-1\.16\.1/' misses the prose, and it only
    reaches src script test remappings.txt.
    The two mentions of
    forge-std 1.16.1 are written with a space, not the forge-std-1.16.1/
    prefix, so the issue's pattern does not reach them; foundry.toml's own pin
    is outside the paths it searches. All three are corrected here, and the claim
    the prose makes still holds at 1.16.2: grep -rniE 'function [a-z]*link'
    over dependencies/forge-std-1.16.2/src returns exactly one line,
    Vm.sol:1020: function readLink(...), so there is still no cheatcode that
    creates a symlink. Re-run on this merge commit.

What the merges removed from this PR

QA

  • Discriminating tests: no new Solidity test ships, deliberately — see
    "Why no new test". The discriminating check for this change is
    nix develop -c forge build, which fails whenever any one of the version
    surfaces disagrees with the others and passes only when all agree; it was run
    against a broken tree before the fix (evidence below) and against this merge
    commit after, and the four mutations below each break it (or
    forge soldeer install) individually. The regression oracle is the
    pre-existing suite: 155 tests in 23 suites, 0 failed on the merge commit,
    the same count main (c816251) runs.

  • Whole-tree check on the merge commit:
    grep -rn 'forge-std-1\.16\.1\|forge-std 1\.16\.1\|forge-std~1\.16\.1\|1_16_1'
    excluding dependencies/, out/ and cache/ returns zero hits. No
    prefix is left behind.

  • Mutations applied: four, one per surface the diff moves, run from this
    merge commit and restored after. Baseline (unmutated) forge build --force
    exits 0 in the same script, so the harness is proved to run rather than
    silently no-op:

    # mutation killed by observed
    M1 src/lib/LibCodeGen.sol:5 prefix → forge-std-1.16.1/ forge build exit 1, Error (6275): Source "forge-std-1.16.1/src/Vm.sol" not found at src/lib/LibCodeGen.sol
    M2 remappings.txt → the 1.16.1 line forge build exit 1, 31 unresolved-source errors — one per import statement in the tree
    M3 foundry.toml pin → 1.16.1, then a clean forge soldeer install as CI does forge soldeer install exit 1, Failed to run soldeer: error during remappings operation: dependency not found: forge-std~1.16.1
    M4 soldeer.lock → the 1.16.1 revision, then a clean forge soldeer install forge soldeer install and forge build install exit 1, dependency not found: forge-std~1.16.2; build exit 1, 31 unresolved-source errors

    Restored state: git status clean, forge build --force exit 0.

  • Oracle: the existing suite's expected strings, which are hard-coded from
    the definition of vm.toString rather than read back off
    LibCodeGen/LibHexString. The artifact-regeneration oracle the original
    version of this PR used is gone with the artifact; see above.

  • Category check: Stale soldeer pin: foundry.toml pins forge-std 1.16.1 with 1.16.2 published, and the version is baked into every import prefix #90 asks for the pin, the lockfile, the remappings and
    every import prefix to move together, and for build-pointers to prove the
    generated artifact is unchanged. All version surfaces covered plus the two
    prose references the issue's grep pattern could not reach; the
    build-pointers half is void, per "What the merges removed" above.

  • README.md is untouched and needs nothing. The published rain-sol-codegen package ships no dependency metadata, and the README never names the forge-std version its imports require #82 and its PR docs: name the forge-std prerequisite in the README Install section #117 are both
    closed; grep -in 'forge-std\|1\.16' README.md on the merge commit returns
    zero hits, so there is no version named in the README for this bump to
    contradict.

Failing before the fix

With the pin, lockfile and remappings at 1.16.2 and the import prefixes not yet
rewritten, nix develop -c forge build --force exits 1 with 31
unresolved-source errors — one per import statement across all 29 importing
files:

Error (6275): Source "forge-std-1.16.1/src/Vm.sol" not found: File not found.
ParserError: Source "forge-std-1.16.1/src/Vm.sol" not found: File not found.
 --> test/src/lib/LibHexString.bytesToHex.t.sol:6:1:
  |
6 | import {Vm} from "forge-std-1.16.1/src/Vm.sol";
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Passing after the fix

On the merge commit, nix develop -c forge test:

Ran 23 test suites in 1.98s (20.15s CPU time): 155 tests passed, 0 failed, 0 skipped (155 total tests)

nix develop -c forge fmt --check exits 0. forge coverage over src/lib is
100% lines / statements / branches / funcs (83/83, 95/95, 10/10, 20/20).
cache/fuzz/failures was deleted before the run so no result is a replay of an
earlier counterexample.

Why no new test

The issue flags that vm.toString is on the critical path of every constant
this library emits, so a forge-std change could move the generated text. It
cannot here: toString is a cheatcode implemented in the forge binary, which
the nix flake pins independently of forge-std; forge-std only declares the
interface, and diff -u forge-std-1.16.{1,2}/src/Vm.sol changes no toString
or parseBytes declaration (124 changed lines: new cheatcode declarations, a
lastCallGaslastFrameGas rename that keeps the old name, and doc
comments). 1.16.2 is otherwise a documentation and private-member-underscore
rename release across StdAssertions, StdChains, StdCheats, StdConfig,
StdJson, StdMath, StdStorage, StdStyle, StdToml and StdUtils.

A test asserting the pin is the newest published revision would need the network
and would red the day 1.16.3 ships, so it is not written. A test asserting the
version surfaces agree is not written either: the compiler already holds that
invariant, as M1, M2 and M4 above show, and reaching remappings.txt from
Solidity would mean widening fs_permissions for no coverage the build does not
already give.

thedavidmeister and others added 3 commits August 16, 2026 18:46
forge-std is the only dependency and the version is baked into every import
prefix, so the pin, the lockfile, the remappings and all 23 import statements
move together.

Closes #90

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@thedavidmeister thedavidmeister self-assigned this Aug 16, 2026
@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@thedavidmeister, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 13 minutes

Limit details: You’ve used all 1 included review currently available under your plan.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 70f01fc9-0ccf-4920-9ba2-3664ecd405e8

📥 Commits

Reviewing files that changed from the base of the PR and between 37a8dcf and c375942.

⛔ Files ignored due to path filters (1)
  • soldeer.lock is excluded by !**/*.lock
📒 Files selected for processing (31)
  • foundry.toml
  • remappings.txt
  • src/lib/LibCodeGen.sol
  • src/lib/LibFs.sol
  • src/lib/LibHexString.sol
  • test/concrete/LibFsExternal.sol
  • test/concrete/LibHexStringExternal.sol
  • test/lib/LibCodeGenSlow.sol
  • test/src/interface/IIntegrityToolingV1.t.sol
  • test/src/interface/IOpcodeToolingV1.t.sol
  • test/src/interface/IParserToolingV1.t.sol
  • test/src/interface/ISubParserToolingV1.t.sol
  • test/src/lib/LibCodeGen.addressConstantString.t.sol
  • test/src/lib/LibCodeGen.bytecodeHashConstantString.t.sol
  • test/src/lib/LibCodeGen.bytes32ConstantString.t.sol
  • test/src/lib/LibCodeGen.bytesConstantString.t.sol
  • test/src/lib/LibCodeGen.commentPrefix.t.sol
  • test/src/lib/LibCodeGen.describedByMetaHashConstantString.t.sol
  • test/src/lib/LibCodeGen.filePrefix.t.sol
  • test/src/lib/LibCodeGen.integrityFunctionPointersConstantString.t.sol
  • test/src/lib/LibCodeGen.literalParserFunctionPointersConstantString.t.sol
  • test/src/lib/LibCodeGen.maxLineLength.t.sol
  • test/src/lib/LibCodeGen.opcodeFunctionPointersConstantString.t.sol
  • test/src/lib/LibCodeGen.operandHandlerFunctionPointersConstantString.t.sol
  • test/src/lib/LibCodeGen.requireContractName.t.sol
  • test/src/lib/LibCodeGen.subParserWordParsersConstantString.t.sol
  • test/src/lib/LibCodeGen.uint8ConstantString.t.sol
  • test/src/lib/LibFs.buildFileForContract.t.sol
  • test/src/lib/LibFs.isPresent.t.sol
  • test/src/lib/LibFs.t.sol
  • test/src/lib/LibHexString.bytesToHex.t.sol

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@thedavidmeister

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…ver it

`main` removed the worked example, so this branch's `script/Build.sol` prefix
rewrite has no target and the deletion is taken. `main`'s `setUp` additions and
its narrowed `LibCodeGen` import in
`test/lib/LibFs.buildFileForContract.t.sol` are kept, with only the forge-std
prefix rewritten over them.

`grep -rn 'forge-std-1\.16\.1\|forge-std 1\.16\.1'` over the merged tree
(excluding `dependencies/`, `out/`, `cache/`) returns nothing: all four version
surfaces — `foundry.toml`, `soldeer.lock`, `remappings.txt` and 26 import
statements across 24 files — read 1.16.2.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
#119's four `test/src/interface/*.t.sol` suites and
`test/src/lib/LibCodeGen.commentPrefix.t.sol` landed after this branch was cut,
each importing `forge-std-1.16.1/src/Test.sol`. The merge brought them in
untouched, which would have left the pin at 1.16.2 with five files still
resolving against a remapping that no longer exists.

`grep -rn 'forge-std-1\.16\.1' .` outside `dependencies/`, `out/` and `cache/`
now returns zero hits.
@thedavidmeister
thedavidmeister merged commit 3109352 into main Aug 17, 2026
4 checks passed
thedavidmeister added a commit that referenced this pull request Aug 17, 2026
Takes #126's forge-std 1.16.2 import prefixes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
thedavidmeister added a commit that referenced this pull request Aug 17, 2026
`test/src/lib/LibFs.requireTag.t.sol`, `LibFs.dirForTag.t.sol`,
`LibFs.pathForTaggedContract.t.sol` and `LibFs.buildFileForTaggedContract.t.sol`
do not exist on `main`, so #126's rewrite had nothing to rename in them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stale soldeer pin: foundry.toml pins forge-std 1.16.1 with 1.16.2 published, and the version is baked into every import prefix

1 participant