Problem
ICloneableFactoryV4 pins two CREATE2 salt derivations to exact bytes:
- namespaced:
keccak256(abi.encode(ICLONEABLE_FACTORY_V4_NAMESPACED_DOMAIN, msg.sender, salt))
- open-salt:
keccak256(abi.encode(ICLONEABLE_FACTORY_V4_OPEN_SALT_DOMAIN, salt, keccak256(data)))
Both exist only as (a) prose in the interface NatSpec and (b) inline internal functions (_effectiveSalt, _effectiveOpenSalt) in the concrete CloneFactory in rain.factory.deploy. There is no executable library implementing them.
Consequence: the derivation is deployment-independent, pure hashing math, but a consumer that wants to predict or verify a clone address off-chain or from another contract must depend on rain-factory-deploy — the whole concrete plus its deploy-address/codehash pins — to obtain it. The math is a library and belongs in this library repo, next to the interface it implements. It also has no single executable source of truth today: the interface states the bytes in prose and the concrete re-implements them, so the two can drift.
Deliverable (this repo)
src/lib/LibICloneableFactoryV4.sol — a pure library implementing exactly the two pinned derivations:
- functions are
internal pure (no state, no deployed bytecode, no deploy pin — stays compatible with this repo's no-pins nature), floating ^0.8.18 like the interfaces;
- import the two domain constants from
ICloneableFactoryV4.sol (do not re-declare them — one source of truth for the tags);
- output must be byte-identical to the interface's pinned NatSpec formulas above. This is the executable pin.
Tests: test/src/lib/LibICloneableFactoryV4.t.sol (this repo gains its first test tree; test files pin =0.8.25 per convention while the lib floats). Discriminating coverage:
- each formula reproduces its exact
keccak256(abi.encode(...)) value against an independent recomputation (not the library calling itself);
- the two derivations are disjoint by construction — the two domain constants are distinct fixed words, so no
(sender, salt) namespaced input can collide with any (salt, data) open-salt input.
Docs: update CLAUDE.md and README.md — this repo now holds the interface surface and the V4 derivation library, not interfaces-only; the "no tests" and "tests live in rain.factory.deploy" statements are now stale (the library's tests live here).
Consumer follow-on (not a merge gate for this issue — coupling to flag)
Once rain-factory republishes with the library, the concrete CloneFactory in rain.factory.deploy should import and call it instead of re-deriving inline, making the library the single source of truth and reconciling the concrete's namespaced derivation (currently the untagged 2-word keccak256(abi.encode(deployer, salt))) to the V4-pinned tagged 3-word form. That change lives in the deploy repo and rides the open-salt work in rain.factory.deploy#8 plus the republish cascade — do not attempt it from this issue.
Problem
ICloneableFactoryV4pins twoCREATE2salt derivations to exact bytes:keccak256(abi.encode(ICLONEABLE_FACTORY_V4_NAMESPACED_DOMAIN, msg.sender, salt))keccak256(abi.encode(ICLONEABLE_FACTORY_V4_OPEN_SALT_DOMAIN, salt, keccak256(data)))Both exist only as (a) prose in the interface NatSpec and (b) inline
internalfunctions (_effectiveSalt,_effectiveOpenSalt) in the concreteCloneFactoryin rain.factory.deploy. There is no executable library implementing them.Consequence: the derivation is deployment-independent, pure hashing math, but a consumer that wants to predict or verify a clone address off-chain or from another contract must depend on
rain-factory-deploy— the whole concrete plus its deploy-address/codehash pins — to obtain it. The math is a library and belongs in this library repo, next to the interface it implements. It also has no single executable source of truth today: the interface states the bytes in prose and the concrete re-implements them, so the two can drift.Deliverable (this repo)
src/lib/LibICloneableFactoryV4.sol— a pure library implementing exactly the two pinned derivations:internal pure(no state, no deployed bytecode, no deploy pin — stays compatible with this repo's no-pins nature), floating^0.8.18like the interfaces;ICloneableFactoryV4.sol(do not re-declare them — one source of truth for the tags);Tests:
test/src/lib/LibICloneableFactoryV4.t.sol(this repo gains its first test tree; test files pin=0.8.25per convention while the lib floats). Discriminating coverage:keccak256(abi.encode(...))value against an independent recomputation (not the library calling itself);(sender, salt)namespaced input can collide with any(salt, data)open-salt input.Docs: update
CLAUDE.mdandREADME.md— this repo now holds the interface surface and the V4 derivation library, not interfaces-only; the "no tests" and "tests live in rain.factory.deploy" statements are now stale (the library's tests live here).Consumer follow-on (not a merge gate for this issue — coupling to flag)
Once
rain-factoryrepublishes with the library, the concreteCloneFactoryin rain.factory.deploy should import and call it instead of re-deriving inline, making the library the single source of truth and reconciling the concrete's namespaced derivation (currently the untagged 2-wordkeccak256(abi.encode(deployer, salt))) to the V4-pinned tagged 3-word form. That change lives in the deploy repo and rides the open-salt work in rain.factory.deploy#8 plus the republish cascade — do not attempt it from this issue.