test: give the open-salt entry points an oracle independent of the library - #45
Conversation
…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>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. WalkthroughThe PR adds tests for ChangesOpen-salt clone validation
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~10 minutes Change: Other 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
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 givingcloneDeterministicOpenSalt/predictDeterministicAddressOpenSaltan oraclethat is not the library they delegate to.
Why
The open-salt pair's only coverage was
CloneFactoryLibEquivalence.t.sol, whichbuilds 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 reorderedabi.encodeoperands would all stay green.The namespaced pair has never had this problem.
testCloneDeterministicSaltIsDomainTaggedHashpins the effective salt againstthe interface constant and OpenZeppelin
Clones, and its NatSpec says why: "sothe test does not restate the library's arithmetic back to itself." This PR
applies the repo's own existing standard to the other derivation.
ICloneableFactoryV4states the derivation as a MUST and spells the preimageout 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
Clonesinitialized with the data
and the one thing the namespaced derivation cannot have
data— distinct data, distinct addressRevert paths and the
NewCloneevent are deliberately not restated; theequivalence suite already holds them field for field.
QA
(
testCloneDeterministicOpenSaltIsDomainTaggedHash,testCloneDeterministicOpenSaltMatchesPredict,testCloneDeterministicOpenSaltIsSenderIndependent,testCloneDeterministicOpenSaltCommitsToData,testCloneDeterministicOpenSaltManyClonesPerImpl) pass on base, verified byrunning them against unmutated
main. This PR is additive oracleindependence, not gap closure; claiming a discriminating test here would be
false.
5c165a8scanmutated 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 therain-factorydependency and istherefore outside this repo's mutable surface — the existing equivalence
assertions restate it and cannot see such a change; these do not and can.
ICloneableFactoryV4interface 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 itis stated as a MUST — cross-checked against OpenZeppelin
Clonesas a foreignEIP-1167 implementation.
LibICloneableFactoryV4is deliberately not importedby this file.
LibICloneableFactoryV4, built the way the namespaced test is built. Covered:the spec-derived salt through OZ
Clones, deploy-matches-predict, senderindependence, and the commitment to
data— exactly the four itemsthe 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-shellon this branch off currentmain: 33 non-chain tests pass, 0 failed —main's 28 plus exactly the 5added here.
forge buildandforge fmt --checkleave the tree clean. Thechain suite needs RPC credentials, is excluded from the local run, and is
untouched by this diff.
Closes #43
🤖 Generated with Claude Code