Skip to content

Standard check: fail when a .sol file declares more than one contract #214

@thedavidmeister

Description

@thedavidmeister

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

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions