Skip to content

Nothing in the suite can make the foundry.toml config assertions fail #194

Description

@thedavidmeister

Unit and file

testSupportedNetworksAreFullyConfigured in src/abstract/RainDeployVerifySnapshot.sol -- the whole config group, which is inline in a test body that takes no arguments and reads the real foundry.toml. Its only subject anywhere in the repo is test/src/abstract/RegistryDeployVerify.t.sol, a one-line binder over this repo's real declaration.

Verified against a fresh read-only clone of main at e9a922a845056c95a9fd38bdf8fbe674db1ece6e with the oracle dependencies/ copied in.

The intent oracle

The NatSpec on the test makes an enforcement claim:

This is what makes the [etherscan] half enforced at all. The RPC half is enforced only incidentally, by the fork tests, and only forwards.

and states the group's job as failing on the PR that drifts:

so this needs no RPC and fails on the PR that drifts rather than at dispatch time.

The sibling record group is deliberately shaped the other way: checkFrozenSnapshotsReleased(string[] memory paths, DeploySuite[] memory released) in src/abstract/RainDeployVerifySnapshotBase.sol takes its subject as arguments, and RainDeployVerifySnapshotBaseTest drives it at every position and every shape of declaration. The repo already ships the pattern that would close this.

The property violated

An enforcement claim with no demonstration behind it. Seven behaviours in this unit are assertions that nothing in the suite has ever driven to a failure, so none of them is known to be capable of failing. The two reverse loops (LibStringSet.holds over vm.parseTomlKeys) in particular have never been driven to false by anything: if vm.parseTomlKeys began returning an empty array for a missing section instead of reverting, both loops would go inert, every run would stay green with no subject, and nothing would notice. That is the exact inert-check failure shape the record group's own NatSpec spends two paragraphs guarding against.

The verified repro, and what it does now

Neuter the [etherscan] key-existence assertion -- replace its vm.keyExistsToml(config, string.concat(.etherscan., networks[i])) argument with the literal true -- and run the suite:

nix develop -c forge test

Result now: byte-identical to the unmutated baseline in this environment (Encountered a total of 61 failing tests, 398 tests succeeded, the 61 being fork tests that need RPC env vars absent locally). The mutant SURVIVES. The original campaign reports the same against its own green 397-test probe baseline, along with M07 through M13 all SURVIVED.

The structural claim was independently confirmed: grep over test/ finds no occurrence of etherscan in any .sol test file, and the only contract that reaches this test is the real binder, so no assertion in this test has ever been observed to fail.

Also unasserted, and folded in here rather than filed separately:

  • A position-versus-membership mutation on the [rpc_endpoints] reverse loop cannot be discriminated today at all, because [rpc_endpoints] happens to list the nine aliases in supportedNetworks() order, so the two agree element for element.
  • A supported network whose name contained a dot would make string.concat(.rpc_endpoints., name) query a nested key rather than the alias. No current network is affected and nothing asserts it stays that way.

The file was restored; the clone tree is clean and nothing was committed or pushed.

Triage

For it being a defect: the group's whole value is that it fails on the PR that drifts, and nothing demonstrates that it fails on anything. Nothing in the NatSpec or README defends the group's undrivability. What the NatSpec defends is that the FILE READ must be the binder's own (vm.readFile resolves against the project root of whatever runs it), which is true of the test but says nothing about an internal check(config, networks) that the test would call with its own read -- precisely the sibling shape. The record group's anti-seam argument is aimed narrowly at the ROOT, not at parameterisation as such, so it does not transfer here.

For it being intended: the check must read the binder's own foundry.toml, which is why it is bound where the binder is, and factoring the body into an internal function adds surface to a contract whose NatSpec argues hard that every optional-looking seam is a way to make a check inert. The one thing it buys is testability rather than a new guarantee.

Note -- independent verdict: bug, in the coverage sense this campaign is for, at moderate rather than high severity: on the real binder the assertions do execute against the real file every run, so they are unproven rather than dead. The sharpest version of the complaint is the NatSpec's own enforcement claim, which has no demonstration behind it anywhere in the suite. The proposed fix is the sibling's shape -- an internal checker over (config, networks) plus synthetic TOML fixtures -- which is the pattern the repo already ships.

🤖 Generated with Claude Code

https://claude.ai/code/session_01V8ViHcKLVk2YoS2joH4HdN

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    adversarialAdversarial mutation-test findingauditAudit findingseverity:mediumAudit severity: MEDIUM

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions