Skip to content

test: give the open-salt entry points an oracle independent of the library - #45

Merged
thedavidmeister merged 1 commit into
mainfrom
43-open-salt-independent-oracle
Sep 21, 2026
Merged

thedavidmeister merged 1 commit into
mainfrom
43-open-salt-independent-oracle

Conversation

@thedavidmeister

@thedavidmeister thedavidmeister commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Split out of #37, which carried this alongside two unrelated concerns (the
declaration-metadata tests, which stay on #37, and the scan record, now #46).
Branched off main, depends on nothing, and is independently mergeable.

What

CloneFactoryCloneDeterministicOpenSaltTest — 5 tests giving
cloneDeterministicOpenSalt / predictDeterministicAddressOpenSalt an oracle
that is not the library they delegate to.

Why

The open-salt pair's only coverage was CloneFactoryLibEquivalence.t.sol, which
builds its expectations from LibICloneableFactoryV4.effectiveOpenSalt(salt, data)
— the code under test. Both sides of those assertions move together, so they
cannot detect a change to the derivation they exist to pin: a different domain
separator, keccak256(data) dropped from the preimage, or reordered
abi.encode operands would all stay green.

The namespaced pair has never had this problem.
testCloneDeterministicSaltIsDomainTaggedHash pins the effective salt against
the interface constant and OpenZeppelin Clones, and its NatSpec says why: "so
the test does not restate the library's arithmetic back to itself." This PR
applies the repo's own existing standard to the other derivation.

ICloneableFactoryV4 states the derivation as a MUST and spells the preimage
out twice in its NatSpec. Nothing in this repo checked the code against it.

What this is not

These tests close no mutation gap, and this PR does not claim one. Pass B of
the scan showed the concrete's 12 delegation mutants were already killed by the
behaviour-only suite. Every test here passes on base. The value is oracle
independence, and that is the whole claim.

Coverage

  • the effective salt is the spec's domain-tagged hash, predicted through OZ
    Clones
  • deploy matches predict, is an EIP-1167 proxy of the implementation, and is
    initialized with the data
  • the address is sender independent — the defining property of "open" salt,
    and the one thing the namespaced derivation cannot have
  • the address commits to data — distinct data, distinct address
  • distinct salts give distinct clones of one implementation

Revert paths and the NewClone event are deliberately not restated; the
equivalence suite already holds them field for field.

QA

  • Discriminating tests: none — and that is the point. All five tests
    (testCloneDeterministicOpenSaltIsDomainTaggedHash,
    testCloneDeterministicOpenSaltMatchesPredict,
    testCloneDeterministicOpenSaltIsSenderIndependent,
    testCloneDeterministicOpenSaltCommitsToData,
    testCloneDeterministicOpenSaltManyClonesPerImpl) pass on base, verified by
    running them against unmutated main. This PR is additive oracle
    independence, not gap closure; claiming a discriminating test here would be
    false.
  • Mutations applied: n/a for gap closure — Pass B of the 5c165a8 scan
    mutated all 12 of the concrete's delegation lines and the pre-existing
    behaviour-only suite (17 tests, pin and bytecode tests excluded) killed every
    one, so there was no surviving mutant to close. What these tests newly
    discriminate is a change to the derivation in LibICloneableFactoryV4
    (effectiveOpenSalt), which lives in the rain-factory dependency and is
    therefore outside this repo's mutable surface — the existing equivalence
    assertions restate it and cannot see such a change; these do not and can.
  • Oracle: the ICloneableFactoryV4 interface spec —
    keccak256(abi.encode(ICLONEABLE_FACTORY_V4_OPEN_SALT_DOMAIN, salt, keccak256(data))),
    read from rain-factory-0.1.9/src/interface/ICloneableFactoryV4.sol, where it
    is stated as a MUST — cross-checked against OpenZeppelin Clones as a foreign
    EIP-1167 implementation. LibICloneableFactoryV4 is deliberately not imported
    by this file.
  • Category check: The open-salt entry points have no test oracle independent of the library under test #43 asks for one thing — an open-salt oracle independent of
    LibICloneableFactoryV4, built the way the namespaced test is built. Covered:
    the spec-derived salt through OZ Clones, deploy-matches-predict, sender
    independence, and the commitment to data — exactly the four items
    the issue's "Proposed fix" lists. Nothing else is in scope here: the
    declaration-metadata tests stay on test: cover the deploy declaration's metadata #37 and the scan record is audit: record the adversarial mutation-test scan of 5c165a8 #46, each
    branched independently off main.

Checks

Verified locally in the pinned rainix sol-shell on this branch off current
main: 33 non-chain tests pass, 0 failedmain's 28 plus exactly the 5
added here. forge build and forge fmt --check leave the tree clean. The
chain suite needs RPC credentials, is excluded from the local run, and is
untouched by this diff.

Closes #43

🤖 Generated with Claude Code

…brary

`CloneFactory`'s open-salt pair was covered only by the equivalence suite, which
states its expectations in terms of `LibICloneableFactoryV4.effectiveOpenSalt` --
the code under test. Both sides of those assertions move together, so they
cannot detect a change to the derivation they are meant to pin.

The namespaced pair has had an independent oracle all along
(`testCloneDeterministicSaltIsDomainTaggedHash`, pinned against OpenZeppelin
`Clones`). This applies the same standard to the other derivation.

Every expectation here is built from the `ICloneableFactoryV4` spec --
`keccak256(abi.encode(ICLONEABLE_FACTORY_V4_OPEN_SALT_DOMAIN, salt, keccak256(data)))`,
which the interface states as a MUST -- and cross-checked against OZ `Clones` as
a foreign EIP-1167 implementation. `LibICloneableFactoryV4` is deliberately not
imported.

Also covers the derivation's two defining properties, which the namespaced pair
cannot have: the address is sender independent, and it commits to `data`.

Revert paths and the `NewClone` event are deliberately not restated; the
equivalence suite already holds them field for field.

These tests close no mutation gap -- every concrete delegation mutant was already
killed -- and the PR does not claim one. This is oracle independence.

Closes #43

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 79695f00-4b19-4855-b61b-8896c162d2d7

📥 Commits

Reviewing files that changed from the base of the PR and between 3c19a6a and a08088b.

📒 Files selected for processing (1)
  • test/src/concrete/CloneFactoryCloneDeterministicOpenSalt.t.sol

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


Walkthrough

The PR adds tests for CloneFactory open-salt deterministic cloning. The tests independently compute the effective salt, compare predicted and deployed addresses, verify proxy initialization, and check sender, data, and salt effects.

Changes

Open-salt clone validation

Layer / File(s) Summary
Independent address oracle and test setup
test/src/concrete/CloneFactoryCloneDeterministicOpenSalt.t.sol
The test deploys CloneFactory and compares its open-salt prediction with an OpenZeppelin Clones prediction using the domain-tagged salt specification.
Clone deployment and derivation properties
test/src/concrete/CloneFactoryCloneDeterministicOpenSalt.t.sol
The tests verify the ERC1167 implementation target, initialized data, sender-independent addresses, and distinct addresses for different data or salts.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Other

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The change satisfies issue #43. The new tests derive the effective salt with ICLONEABLE_FACTORY_V4_OPEN_SALT_DOMAIN and keccak256(abi.encode(..., salt, keccak256(data))). They compare predictions …
Out of Scope Changes check ✅ Passed The change adds only the test file for the open-salt entry points. The assertions directly support issue #43. No unrelated production changes or unrelated test scope are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding independent-oracle tests for the open-salt entry points.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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
thedavidmeister merged commit f49a79f into main Sep 21, 2026
5 checks passed
Sign up for free to 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.

The open-salt entry points have no test oracle independent of the library under test

1 participant