Ask
Add a standard check to rainix (so all consuming rain repos inherit it via the reusable rainix-sol-static workflow / rainix-sol-static task) that fails when a Solidity .sol file declares more than one contract.
Rain's convention is one contract per file (named after the file), but it's only enforced by review and drifts — e.g. helper/mocks get declared inline in .t.sol test files, and some source/helper files accumulate multiple contracts. A mechanical check keeps it consistent without reviewer effort.
Suggested scope
- Count top-level
contract and abstract contract declarations per .sol; fail if > 1.
- Open question for maintainers: should
library and interface count too (stricter "one top-level definition per file"), or only deployable/abstract contracts? Recommend starting with contract + abstract contract and deciding on libraries/interfaces separately.
- File-scope
error/struct/enum/constant declarations alongside a single contract should remain allowed (they're not contracts).
Implementation options
- A small shell/awk check added to the
rainix-sol-static task body (greps each tracked .sol for ^(abstract )?contract count), or
- A
forge lint / slither custom check if one fits cleanly, or
- A pre-commit hook in the rainix hook bundle.
Rollout caveat
This will fail CI in consumers that currently have multi-contract files (including some test helpers, e.g. files bundling a mock asset + a manager). Land it behind a cleanup pass, or stage it as a warning first, so it doesn't break downstream main on merge. Track the rain.vats cleanup at rainlanguage/rain.vats#314.
Context
Surfaced while extracting inline .t.sol test helpers into dedicated test/concrete/ files for the rain.vats #309 fix; a repo-wide audit there found several pre-existing inline-helper violations (rainlanguage/rain.vats#314). A rainix-level check would prevent this class of drift everywhere.
🤖 Generated with Claude Code
Ask
Add a standard check to rainix (so all consuming rain repos inherit it via the reusable
rainix-sol-staticworkflow /rainix-sol-statictask) that fails when a Solidity.solfile declares more than one contract.Rain's convention is one contract per file (named after the file), but it's only enforced by review and drifts — e.g. helper/mocks get declared inline in
.t.soltest files, and some source/helper files accumulate multiple contracts. A mechanical check keeps it consistent without reviewer effort.Suggested scope
contractandabstract contractdeclarations per.sol; fail if> 1.libraryandinterfacecount too (stricter "one top-level definition per file"), or only deployable/abstractcontracts? Recommend starting withcontract+abstract contractand deciding on libraries/interfaces separately.error/struct/enum/constantdeclarations alongside a single contract should remain allowed (they're not contracts).Implementation options
rainix-sol-statictask body (greps each tracked.solfor^(abstract )?contractcount), orforge lint/ slither custom check if one fits cleanly, orRollout caveat
This will fail CI in consumers that currently have multi-contract files (including some test helpers, e.g. files bundling a mock asset + a manager). Land it behind a cleanup pass, or stage it as a warning first, so it doesn't break downstream
mainon merge. Track the rain.vats cleanup at rainlanguage/rain.vats#314.Context
Surfaced while extracting inline
.t.soltest helpers into dedicatedtest/concrete/files for the rain.vats #309 fix; a repo-wide audit there found several pre-existing inline-helper violations (rainlanguage/rain.vats#314). A rainix-level check would prevent this class of drift everywhere.🤖 Generated with Claude Code