This repo is the library half of the library/deploy split: the ICloneable*
interface surface and the LibICloneableFactoryV4 library that implements it.
It publishes to Soldeer as rain-factory.
Soldeer rain-factory 0.1.5 and earlier are the pre-split package, carrying the
concrete CloneFactory and its deploy pins; 0.1.6 dropped them. The v0.1.0,
v0.1.1, sol-v0.1.2, sol-v0.1.3 and sol-v0.1.5 tags here are those
pre-split releases, and the reports under audit/protofire/ audit them, not the
current tree.
CloneFactory — the concrete that implements these interfaces — lives in
rain.factory.deploy,
together with its deployed address + codehash pins, its frozen per-release
deploy-pin snapshots and its deploy script. That repo publishes as
rain-factory-deploy.
Depend on rain-factory for the interfaces and the library; on
rain-factory-deploy for a live CloneFactory's address or codehash. A live
CloneFactory embeds the rain-factory revision that repo pins.
src/lib/LibICloneableFactoryV4.sol is the executable form of
ICloneableFactoryV4 as internal library logic. The two CREATE2 salt
derivations the interface pins to exact bytes — the msg.sender-namespaced one
and the open-salt one — are pure functions that import the domain tags from the
interface, so the tags have a single source of truth and a factory, an indexer
or a consumer predicting a clone address computes the salt from one place. On
top of them sit the implementation-code guard, the EIP1167 creation code and its
CREATE2 address prediction (constructed from the standard's own bytes, so the
published src/ depends on no external cloning code), and the atomic
clone-initialize-verify flow with its typed errors and the NewClone event.
msg.sender and address(this) are read inside the library, so a concrete
factory is one delegation per entry point. The tests live here under
test/src/lib/: they recompute both salt formulas independently to pin them to
the interface's spec byte for byte, and pin the EIP1167 construction against
OpenZeppelin Clones as a foreign implementation of the same standard.
Contains interfaces for working with Rain factories.
Rain tooling/ecosystem generally tries to be as agnostic and low friction as possible on the implementation side.
The ideal would be that "any" contract can call an interpreter and magically be supported but there's a lot that can go wrong, for example:
- Contracts can self-destruct or even be redeployed with new bytecode
- Proxies can point to new implementations and "upgrade"
- Discoverability of ABIs and other metadata subject to indexer limitations
Falling short of the ideal, we want to support:
- Ability to (dis)trust contracts at the bytecode level NOT the human/key level
- Support existing patterns such as EIP1167 for clones, etc.
- Avoid introducing Rain-isms as much as possible
The onchain tooling for analysis is found at https://github.com/rainprotocol/rain.extrospection
The current interfaces in this repository are for
ICloneableFactoryV4, the current factory interface. ExtendsICloneableFactoryV3— nothing was dropped this time, so it inherits rather than restates — and adds a second deterministic derivation,cloneDeterministicOpenSalt+predictDeterministicAddressOpenSalt, whoseCREATE2salt hashes the caller-supplied salt together with the initialization data and nothing about the caller. The two derivations differ in what the clone's address commits to, and neither dominates: the V3 pair namespaces the salt bymsg.sender, so the address commits to WHO deployed and not to WHAT — nobody else can reach the caller's address, but the deploying account is baked into it forever and the deployer alone decides the initial state. The open-salt pair commits to WHAT and not to WHO — every account reaches the same address, and so can anyone, but everyone who reaches it deploys the same contract initialized with the same bytes, because varying either input lands somewhere else. Its cost is that the address is not knowable until the data is final. The residual the address cannot fix — implementations MUST NOT readtx.origin— and the address-registry pairing it is intended for are spelled out in the NatSpec onICloneableFactoryV4.cloneDeterministicOpenSalt- A small interface
ICloneableV2designed for cloneable proxy contracts to expose aninitializefunction that the factory can call to act like a constructor
Every interface that is not the newest version of itself is deprecated and lives
in src/interface/deprecated/. They are still published for consumers pinned to
them. New work uses the current interfaces above.
Deterministic-only (cloneDeterministic + predictDeterministicAddress,
CREATE2 with the salt namespaced by msg.sender). Superseded by
ICloneableFactoryV4, which extends it, so the namespaced pair and NewClone
are still declared in ICloneableFactoryV3 and inherited from there. Standalone
rather than extending ICloneableFactoryV2, because the non-deterministic
clone() was intentionally dropped.
Clones proxies from a reference implementation with a non-deterministic
clone(). Superseded by ICloneableFactoryV4.
This version of ICloneable did not have any explicit return value on success
of initialize. It is possible for contracts that do not implement ICloneableV1
to silently fail to initialize when cloned by an ICloneableFactoryV1.
Newer versions of the interface include an explicit success value and check.
The legacy factory model was much more restricted in that each factory implementation was 1:1 with the thing it was deploying. If you needed a new contract you also needed to implement a new factory.
This was suboptimal for several reasons:
- Increased surface area for things to go wrong
- More Rain-isms creeping in
- Redundant work to maintain a growing list of factories
The legacy interface is available as IFactory but it is NOT RECOMMENDED for
new contracts.