Skip to content

solc warning 2018: candidateContractName declared view when it can be pure #78

Description

@thedavidmeister

Audit finding Q4-03 — dimension 4, severity LOW. Whole-repo audit pass 1 at 440e90b5.

test/src/lib/GeneratedSnapshotShape.t.sol:126

Problem

nix develop -c forge build reports:

Warning (2018): Function state mutability can be restricted to pure
   --> test/src/lib/GeneratedSnapshotShape.t.sol:126:5

The body only calls vm.split (declared pure on Vm) on a memory argument; vm itself is a constant on Test, so nothing is read from state. This is the only solc warning the whole tree emits, which means the build is one warning away from clean — and a build that already prints a warning is one where the next, real warning is not noticed.

Proposed fix

test/src/lib/GeneratedSnapshotShape.t.sol line 126:

-    function candidateContractName(DeployCandidate memory candidate) internal view returns (string memory) {
+    function candidateContractName(DeployCandidate memory candidate) internal pure returns (string memory) {

No caller changes: pure is accepted everywhere view was.


Verification — this finding survived an adversarial refutation pass

Verified against source at 440e90b, could not refute.

  1. The warning is real and at the cited location. nix develop -c forge build --force on a clean tree prints exactly:
    Warning (2018): Function state mutability can be restricted to pure --> test/src/lib/GeneratedSnapshotShape.t.sol:126:5
    Line 126 of /home/gildlab/code/rain-deploy-audit/test/src/lib/GeneratedSnapshotShape.t.sol is function candidateContractName(DeployCandidate memory candidate) internal view returns (string memory) {, matching the finding verbatim.

  2. The mechanism is as described. The body calls only vm.split(...) on a memory argument; split is declared external pure at dependencies/forge-std-1.16.1/src/Vm.sol:1301, and vm is a constant on Test. Nothing is read from state.

  3. The proposed fix was applied and built: with line 126 changed to internal pure, solc reports Compiler run successful! with no warnings. The sole caller is line 164 in the same file (declared[i] = candidateContractName(candidates[i]);), inside a view test function — pure is accepted there, no caller change needed. Grep confirms those are the only two occurrences of the symbol in the tree. Working tree restored afterwards.

  4. No convention refutes it. CLAUDE.md documents no mutability exemption, and the file's sibling helpers already follow the compiler: holdsName and artifactPath are pure, while snapshotContractNames/nodeTypes/constantDeclarations are view because they genuinely call vm.readDir/vm.readFile. candidateContractName is the odd one out, not a deliberate pattern.

One factual overreach in the rationale, not enough to refute: the finding says fixing this leaves the build "clean", but forge build also emits a forge-lint warning (warning[unsafe-typecast] at src/lib/LibRainDeploy.sol:304). The narrow claim — it is the only solc warning — is true; the broader "one warning away from a clean build" is not, since lint output remains after the fix.

Severity corrected LOW -> INFO: this is a compiler style hint on an internal helper in test code. Nothing deployed, no test semantics, no on-chain value at risk; the mutability keyword affects no generated behaviour. The stated harm (a standing warning masks the next one) is also weakened by the lint warning that survives the fix, so the build is noisy either way until that is addressed too.

Activity

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

Metadata

Metadata

Labels

auditAudit findingpass1Audit pass 1 (whole-repo, 2026-08-15)severity:lowAudit severity: LOW

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions