Skip to content

Bump rain-sol-codegen 0.1.6 -> 0.1.36 and forge-std 1.16.1 -> 1.16.2 - #134

Merged
thedavidmeister merged 6 commits into
mainfrom
2026-08-17-codegen-0.1.35
Aug 18, 2026
Merged

Bump rain-sol-codegen 0.1.6 -> 0.1.36 and forge-std 1.16.1 -> 1.16.2#134
thedavidmeister merged 6 commits into
mainfrom
2026-08-17-codegen-0.1.35

Conversation

@thedavidmeister

@thedavidmeisterthedavidmeister commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Bumps rain-sol-codegen from 0.1.6 to 0.1.35, the latest published release.

forge-std goes 1.16.1 -> 1.16.2 in the same change, and that is forced rather than scope creep: codegen 0.1.35's own LibFs.sol and LibCodeGen.sol import forge-std-1.16.2/src/Vm.sol, and a Vm from 1.16.1 is a different type — nothing compiles otherwise.

Why this is more than a prefix rewrite

Decisions

Licence and copyright are parameters of LibRainDeploySnapshot, not constants inside it. Declared in script/Build.sol and threaded down. rain-deploy is itself published and rain.factory.deploy consumes it, so hardcoding Rain's header in the library would recreate one layer up the precise defect codegen #135 fixed.

snapshotName is deleted — it existed only to build the smuggled name.

LIB_FS_ROOT = GENERATED_DIR imported from LibFs rather than a second "src/generated" literal.

The root-aware dirForSnapshot/pathForSnapshot overloads carry the writer's guards (requireTag then requireIdentifier, in pathForTaggedContract's order), so both path spellings share one validity rule.

Fixture dirs renamed to the tag alphabet (write-snapshot-not-a-tag -> writeSnapshotNotATag); they must stay non-isTag while being alphabet-legal. Record roots and raw string.concat fixtures are untouched.

The regeneration is byte-identical, and that is now measured

forge script script/Build.sol on this head, then git status: empty. Not just src/generated/candidate/ — nothing anywhere in the tree moved. Both rolling snapshots, both alias libs and both released-suites libs regenerate to the bytes already committed under codegen 0.1.6.

That claim was previously reasoning about the two versions' emitters. It is now the measurement, which matters because rainix runs frozen-snapshots-append-only and because the deploy pins consumers hold are exactly these bytes: a bump that moved them would move DEPLOYED_ADDRESS.

QA

Discriminating tests.testRootAwareSnapshotPathIsTheWritersAtTheRealRoot, rewritten as a staticcall outcome-parity fuzz — both path spellings accept/refuse the same names and return the same bytes, through new externalPathForSnapshotAt / externalPathForSnapshot wrappers. Writer-test expected headers are built from script/Build.sol's licence/copyright constants, so those constants are anchored to the committed artifacts rather than restated. Each fails on base by construction: snapshotName no longer exists on this head and the writers take two more arguments, so the base spelling does not compile.

Added here: testWriteSnapshotDeclaresTheLicenceItWasHanded. Making the header a parameter is only worth doing if what is handed in is what comes out, and the snapshot writer had no assertion on that — the alias and released emitters each have a byte-for-byte one, and every other test that reads a snapshot header reads the committed file, which is evidence about a generation that already happened. The two values are strings of the same type in adjacent positions, so a call that swapped them compiles and writes a file carrying both, in the wrong tags, into a consumer's append-only record. The test asserts the header entire — everything before pragma — against text spelled out rather than taken from LibCodeGen.filePrefix, so the oracle is not the code that wrote the file.

Mutations. The pass over the changed lines recorded 11 mutants, 11/11 killed, 0 survived — the deleted snapshotName path, the guard placement in the root-aware overloads, and the licence/copyright threading. That pass is not re-run here.

Run here, for the test added here: swapping spdxLicenseIdentifier and copyrightText at the buildFileForTaggedContract call in writeSnapshot. KilledLibRainDeploySnapshot.t.sol goes 43 passed to 42 passed / 1 failed, and the single failure is the new test, on // SPDX-License-Identifier: Copyright (c) 2020 Rain Open Source Software Ltd. Nothing else in the file notices, which is the gap it was written for.

Oracle. The committed artifacts under src/generated/candidate/, and now the empty regeneration diff against them rather than an argument about emitters.

Category check. The ask is one thing — bump to the latest codegen release. Covered: the pin, soldeer.lock, remappings.txt, all 19 .sol import prefixes (zero rain-sol-codegen-0.1.6 or forge-std-1.16.1 survive), both API changes above, and the README versions.

Checks run locally

  • forge script script/Build.sol — successful, zero diff.
  • reuse lint — compliant, 82/82 files.
  • forge fmt --check — clean.
  • slither . — 49 contracts, 100 detectors, 0 results.
  • forge test206 passed, 51 failed, 0 skipped, 257 total across 18 suites. All 51 failures are vm.createSelectFork: environment variable ARBITRUM_RPC_URL / BASE_RPC_URL / POLYGON_RPC_URL not found — fork tests wanting RPC secrets CI has and a local shell does not. Counted, not sampled: zero of the 51 is anything else, and none is related to this change.

The symlink/ffi risk is closed

codegen 0.1.35 reaches removeSymlink, and its vm.tryFfi, only inside if (vm.exists(path) && isSymlinkIn(vm, dir, path)) — an actual symlink sitting at a generated path. This repo does not set ffi = true, so that branch would revert.

It is unreachable here: find src test script -type l is empty, there is no ln -s or symlink-creating call anywhere outside dependencies/, and both the regeneration and the full suite write generated files with ffi unset without hitting it.

About the earlier red on db4e887

All three checks on db4e887 failed at step 1, "Set up job", 48-88 seconds after starting at 14:51:18Z — before checkout, before dependencies, before anything in this diff ran. That is inside the critical-impact GitHub incident opened at 13:40:03Z with Actions in major outage. The runner never started, so those reds are not a verdict on this code and nothing about them was fixed, because there was nothing there to fix.

Actions has since recovered. rainix / static, rainix / legal and rainix / test are all completed/success on dc3204f, started 15:42:03Z.

Summary by CodeRabbit

  • Documentation

    • Updated documented dependency versions and configuration examples.
  • Refactor

    • Improved snapshot path handling and generation reliability.
    • Added configurable SPDX license and copyright metadata to generated files.
  • Tests

    • Expanded snapshot path and metadata validation.
    • Updated test coverage for generated headers and snapshot writers.
  • Chores

    • Updated Forge and code-generation tooling versions across the project.

`rain-sol-codegen` 0.1.35 replaces the API this repo generated through, so the
bump is a rewrite of the calls rather than a version string.
forge-std goes with it, forced rather than chosen: 0.1.35's own `LibFs.sol` and
`LibCodeGen.sol` import `forge-std-1.16.2/src/Vm.sol`, and a `Vm` from 1.16.1 is
a different type at every seam the two libraries share.
The licence and the copyright holder are now PARAMETERS of
`LibRainDeploySnapshot`, declared in `script/Build.sol` as
`GENERATED_SPDX_LICENSE_IDENTIFIER` / `GENERATED_COPYRIGHT_TEXT` and threaded
down to `LibCodeGen.filePrefix`. `rain-deploy` is itself published and
`rain.factory.deploy` consumes it, so a header chosen inside this library would
stamp Rain's licence permanently into another org's append-only
`src/generated/<tag>/` — the defect one layer down that codegen made
unrepresentable.
`LIB_FS_ROOT` is now `LibFs`'s exported `GENERATED_DIR` rather than a second
`"src/generated"` literal held equal to it by an assertion. One constant is what
the assertion was standing in for.
`snapshotName` is deleted. It existed only to smuggle `dir + "/" + name` through
an argument documented to be a Solidity identifier, which codegen now refuses;
`LibFs.pathForTaggedContract` takes the directory as a directory. The root-aware
`dirForSnapshot`/`pathForSnapshot` overloads carry the writer's own guards in
`pathForTaggedContract`'s order, so the reader and the writer agree on which
paths EXIST as well as on how they are spelled —
`testRootAwareSnapshotPathIsTheWritersAtTheRealRoot` now compares the two as
OUTCOMES across the whole fuzz domain, revert data included, rather than only
over the names both accept.
`writeSnapshot` no longer creates the snapshot directory: the writer creates it
from the same tag the path is derived from, so there is no second `createDir` to
disagree with it.
Fixture directories are renamed to the tag alphabet
(`write-snapshot-not-a-tag` -> `writeSnapshotNotATag`, same for the dependencies
fixture). They must stay non-`isTag` — a tag-shaped scratch directory under the
real `src/generated/` is a release every parallel test suite has to fail on —
while being alphabet-legal, because the writer places files only in directories
whose names are.
Regenerating `src/generated/` and both alias libs with 0.1.35 produces output
byte-identical to what is committed: `forge script ./script/Build.sol` followed
by `forge fmt` leaves the tree clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@thedavidmeisterthedavidmeister self-assigned this Aug 17, 2026
The licence and the copyright holder are parameters of
`LibRainDeploySnapshot` rather than constants inside it, so that deploy
repos in other orgs get their own header in their own append-only
`src/generated/<tag>/`. That freedom is only worth having if what is
handed in is what comes out.
The alias and released emitters each already assert their output byte for
byte. The snapshot writer had no such assertion: the two values are
strings of the same type in adjacent positions, so a call that swapped
them compiles and writes a file carrying both, in the wrong tags. Every
other test that reads a snapshot header reads the COMMITTED file, which
is evidence about a generation that already happened rather than about
what the writer emits now.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Aug 17, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in:39 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: 7d49fdd6-c6e1-4e9c-9c84-b04320107972

📥 Commits

Reviewing files that changed from the base of the PR and between 47e58b1 and 0514369.

📒 Files selected for processing (3)
  • script/Build.sol
  • src/lib/LibRainDeploySnapshot.sol
  • test/src/lib/LibRainDeploySnapshot.t.sol

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b4c335c7-0929-45cd-92a0-f169d67cdd4d

📥 Commits

Reviewing files that changed from the base of the PR and between 52c0ef6 and 47e58b1.

⛔ Files ignored due to path filters (1)
  • soldeer.lock is excluded by !**/*.lock
📒 Files selected for processing (22)
  • README.md
  • foundry.toml
  • remappings.txt
  • script/Build.sol
  • src/abstract/RainDeployBroadcast.sol
  • src/abstract/RainDeployVerifyBase.sol
  • src/lib/LibRainDeploy.sol
  • src/lib/LibRainDeploySnapshot.sol
  • test/lib/LibMigrationFuzz.sol
  • test/script/Build.t.sol
  • test/src/abstract/RainDeployBroadcast.t.sol
  • test/src/abstract/RainDeploySuitesBase.t.sol
  • test/src/concrete/AddressRegistryGet.t.sol
  • test/src/concrete/AddressRegistryRegister.t.sol
  • test/src/concrete/MigrationRegistryApplied.t.sol
  • test/src/concrete/MigrationRegistryApplyMigration.t.sol
  • test/src/concrete/MigrationRegistryHead.t.sol
  • test/src/lib/GeneratedSnapshotShape.t.sol
  • test/src/lib/LibAddressRegistry.t.sol
  • test/src/lib/LibMigrationRegistry.t.sol
  • test/src/lib/LibRainDeploy.t.sol
  • test/src/lib/LibRainDeploySnapshot.t.sol

Included review availability: Your plan includes up to 1 review per rolling hour; 0 remain after this review.


Walkthrough

The pull request updates Forge Std and Rain Sol Codegen versions. It changes snapshot path handling to use validated tagged-contract paths and adds caller-provided SPDX license and copyright metadata to generated files. Build wiring and snapshot tests were updated.

Changes

Snapshot generation

Layer / File(s)Summary
Dependency and import alignment
README.md, foundry.toml, remappings.txt, src/abstract/*, src/lib/LibRainDeploy.sol, test/lib/LibMigrationFuzz.sol, test/script/Build.t.sol, test/src/abstract/*, test/src/concrete/*, test/src/lib/GeneratedSnapshotShape.t.sol, test/src/lib/LibAddressRegistry.t.sol, test/src/lib/LibMigrationRegistry.t.sol, test/src/lib/LibRainDeploy.t.sol
Forge Std is updated to 1.16.2. Rain Sol Codegen is updated to 0.1.36. Documentation, remappings, source imports, and test imports use the new versions.
Snapshot paths and generated metadata
src/lib/LibRainDeploySnapshot.sol, script/Build.sol
Snapshot path helpers validate directory and contract names through LibFs. Writers use buildFileForTaggedContract and caller-provided SPDX license and copyright values. Build generation passes the new metadata values.
Snapshot path and header validation
test/src/lib/LibRainDeploySnapshot.t.sol
Tests compare path return and revert outcomes. Snapshot, alias, dependency, and released-library tests pass and verify generated license and copyright metadata.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk:⚪ Minimal · up to 47e58

This dependency and snapshot-path update is merge-ready after normal checks; no actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly and concisely identifies the two dependency upgrades that form the main changes in the pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 2026-08-17-codegen-0.1.35

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
ContributorAuthor

@coderabbitai review

The earlier review failed during the GitHub outage, and the head has moved to dc3204f.

@coderabbitai

coderabbitaiBot commented Aug 17, 2026

Copy link
Copy Markdown

@thedavidmeister I will review the current pull request head, dc3204f.

❌ Action failed

Review failed.

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.

0.1.35 predates the licence defaults. 0.1.36 is the release that carries
`RAIN_SPDX_LICENSE_IDENTIFIER` and `RAIN_COPYRIGHT_TEXT` and the arities of
`filePrefix` and the `LibFs` writers that resolve to them.
`soldeer update` adds the new remapping but leaves the superseded one in place,
so `rain-sol-codegen-0.1.35/` is deleted here rather than left to resolve
against a directory that no longer exists.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@thedavidmeisterthedavidmeister changed the title Bump rain-sol-codegen 0.1.6 -> 0.1.35 and forge-std 1.16.1 -> 1.16.2Bump rain-sol-codegen 0.1.6 -> 0.1.36 and forge-std 1.16.1 -> 1.16.2Aug 18, 2026
@thedavidmeister

Copy link
Copy Markdown
ContributorAuthor

Re-pointed 0.1.35 -> 0.1.36. 0.1.35 predates the licence defaults; 0.1.36 is the release cut from rainlanguage/rain.sol.codegen#144, which restores RAIN_SPDX_LICENSE_IDENTIFIER and RAIN_COPYRIGHT_TEXT as constants and adds the arities of filePrefix and the three LibFs writers that resolve to them.

Also deleted the rain-sol-codegen-0.1.35/ remapping. forge soldeer update appends the new remapping and leaves the superseded one behind, pointing at a dependencies/ directory that no longer exists.

Local: forge fmt --check exit 0, 206 passed. The 51 failures are all vm.createSelectFork: environment variable \*_RPC_URL` not found— 102 of 102[FAIL` lines match that, none of any other kind — which is this machine having no RPC secrets, not the bump.

`script/Build.sol` declared `GENERATED_SPDX_LICENSE_IDENTIFIER` and
`GENERATED_COPYRIGHT_TEXT` as its own string literals, holding the same two
values `rain-sol-codegen` 0.1.36 exports as `RAIN_SPDX_LICENSE_IDENTIFIER` and
`RAIN_COPYRIGHT_TEXT`. Two definitions of one invariant, free to drift, with
nothing comparing them.
Both are deleted and the call sites — three in `Build.sol`, twelve in
`LibRainDeploySnapshot.t.sol` — name codegen's. `LibRainDeploySnapshot` and
`LibFs` still take the header as parameters, because both are dependencies of
deploy repos in other orgs whose generated trees are append-only; what changes
is only which repo the values are written down in.
`testWriteAliasLibWritesTheLibAtItsPath` emits with these constants and asserts
the result is the committed generated file byte for byte. It passes, and no
file under `src/generated/` moves, so the emitted header is unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@thedavidmeister

Copy link
Copy Markdown
ContributorAuthor

Removed rain.deploy's own licence constants.

script/Build.sol declared GENERATED_SPDX_LICENSE_IDENTIFIER and GENERATED_COPYRIGHT_TEXT as its own string literals, holding the same two values 0.1.36 exports as RAIN_SPDX_LICENSE_IDENTIFIER and RAIN_COPYRIGHT_TEXT. Two definitions of one invariant with nothing comparing them. Both deleted; the 3 call sites in Build.sol and 12 in LibRainDeploySnapshot.t.sol name codegen's, which the exported constants' own NatSpec anticipates — Exported rather than inlined into the defaulting overload, so a consumer that threads the header through its own build can name the value instead of restating the string.

LibRainDeploySnapshot and LibFs still take the header as parameters. Both are dependencies of deploy repos in other orgs whose src/generated/<tag>/ is append-only, so neither may choose one; what changed is only which repo the values are written down in.

The emitted header is unchanged.testWriteAliasLibWritesTheLibAtItsPath emits with these constants and asserts the result is the committed generated file byte for byte — it passes, and nothing under src/generated/ moved.

Local, before and after, identical: 206 passed; 51 failures, all vm.createSelectFork: environment variable \*_RPC_URL` not found(102 of 102[FAILlines), confined toRainDeployVerifyChain, RainDeployVerifyChainCandidateandLibRainDeploy`. This machine has no RPC secrets.

thedavidmeisterand others added 2 commits August 18, 2026 09:44
192 lines of which 111 were comment. The doc block argued for the design —
why one list rather than two, why candidates are reached by name, what would
go wrong under alternatives nobody wrote — rather than saying what the script
does. Same in the alias-lib test's NatSpec.
Now 115 lines, 34 comment: what each entry point rewrites, what the struct
fields place and name, what the test asserts.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codegen 0.1.36 defaults the header at its own writers, but every caller reaches
them through this library, whose three writers each had one arity requiring the
licence and copyright. So a repo in this org still had to name the values, and
`script/Build.sol` did — which is the same either/or the codegen change
already removed one layer down: taking the values as parameters is what a repo
outside this org needs, and it never ruled out an arity that defaults.
`writeSnapshot`, `writeAliasLib` and `writeReleasedSuitesLib` each gain the
defaulting overload. Build.sol drops the arguments and the import; nothing in
this repo now names a licence in the build path.
Covered three ways: the two tests that emit over the committed generated files
and assert byte equality now go through the defaulting arity, and one test per
writer asserts the defaulting arity writes exactly what the parameterised one
writes when handed the org values — which a swapped or wrong constant breaks.
`testWriteSnapshotDefaultsToTheOrgHeader` reverts EVM state between its two
writes: the Zoltu deploy is CREATE2, so writing one creation code twice lands
on an address that already has code.
209 passed, up from 206.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@thedavidmeister

Copy link
Copy Markdown
ContributorAuthor

Pushed the defaults one layer up, which is where the question actually was.

Codegen 0.1.36 defaults the header at its own writers, but nothing in this repo calls those directly — every caller goes through LibRainDeploySnapshot, whose writeSnapshot, writeAliasLib and writeReleasedSuitesLib each had exactly one arity, all three requiring the licence and copyright. So a repo in this org still had to name the values and script/Build.sol did. That is the same either/or the codegen change already removed one layer down: taking the values as parameters is what a repo outside this org needs, and it never ruled out an arity that defaults.

Each of the three writers now has the defaulting overload. Build.sol drops the arguments and the import — nothing in this repo names a licence in the build path any more.

Covered three ways:

  • The two tests that emit over the committed generated files and assert byte equality now go through the defaulting arity, so the defaults are pinned to the headers the committed files actually carry.
  • One test per writer asserts the defaulting arity writes exactly what the parameterised one writes when handed the org values.

Mutations, applied to the branch and reverted:

MutationResult
writeAliasLib defaulting overload passes the two constants swapped[FAIL: assertion failed: // SPDX-License-Identifier: Copyright (c) 2020 Rain Open Source Software Ltd]testWriteAliasLibDefaultsToTheOrgHeader, testWriteAliasLibWritesTheLibAtItsPath
writeSnapshot defaulting overload passes "MIT"[FAIL: assertion failed: // SPDX-License-Identifier: MIT]testWriteSnapshotDefaultsToTheOrgHeader

testWriteSnapshotDefaultsToTheOrgHeader reverts EVM state between its two writes: the Zoltu deploy is CREATE2, so writing one creation code twice lands on an address that already has code. Caught by the first run of it, which failed DeployFailed(false, 0x0).

209 passed, up from 206. Same 51 RPC-env failures. forge fmt --check exit 0.

Sign up for freeto 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.

1 participant

@thedavidmeister