Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 12 additions & 22 deletions src/interface/ICloneableFactoryV4.sol
Original file line number Diff line number Diff line change
Expand Up @@ -109,28 +109,18 @@ interface ICloneableFactoryV4 is ICloneableFactoryV3 {
/// # Why hashing `data` into the salt is the whole point
///
/// Without the `msg.sender` namespacing, anybody can deploy at this address
/// before the party that intended to, and since clone-and-initialize is
/// atomic and `initialize` runs exactly once, whoever gets there first sets
/// the clone's state permanently. There is no recovery: the address is
/// occupied and nobody can redeploy over it.
///
/// That is only dangerous if the first deployer has anything to vary.
/// Because `data` is inside the derivation, they do not:
/// before the party that intended to, and whoever gets there first sets the
/// clone's state permanently. That is only dangerous if the first deployer
/// has anything to vary. Because `data` is inside the derivation, they
/// cannot vary it:
///
/// - A front-runner passing DIFFERENT `data` derives a DIFFERENT address.
/// The address anyone pinned is untouched; the front-runner has deployed
/// their own contract at their own address, at their own expense.
/// - A front-runner passing the SAME `data` produces the contract that was
/// intended, initialized with the bytes that were intended, and has done
/// nothing but pay the gas.
/// intended, initialized with the bytes that were intended.
///
/// This is the same position that makes permissionless deterministic
/// (Zoltu-style) deployment harmless — a Zoltu deploy has no arguments, so
/// front-running it produces byte-for-byte the intended contract — reached
/// WITH arguments, by putting the arguments in the address rather than by
/// having none. It is a property of this signature, not a condition on the
/// implementation being cloned, so there is no per-implementation audit of
/// "could a squatter pass something worse" to get wrong.
/// This commits what a squatter can PASS. It does not commit what the
/// implementation runs — the derivation fixes its ADDRESS, not its code —
/// nor anything else `initialize` reads. Those are below.
///
/// # What the address does NOT fix, which implementations MUST respect
///
Expand All @@ -151,10 +141,10 @@ interface ICloneableFactoryV4 is ICloneableFactoryV3 {
/// resolves the admin by NAME from the registry rather than taking an
/// admin address, and the name, being part of `data`, is committed to by
/// the address.
/// - Registry-resolved authority is the ordinary case: it is simply `data`
/// that names things instead of naming addresses. `data` MAY be empty, and
/// an implementation that resolves everything from the registry will pass
/// empty `data`.
/// - The implementation MUST NOT delegate onward to a target anyone can
/// change. The derivation fixes the implementation's ADDRESS, not its
/// code, so a beacon proxy as implementation leaves the clone's behaviour
/// with whoever retargets the beacon.
///
/// # Obligation on the factory, not on the consumer
///
Expand Down
3 changes: 2 additions & 1 deletion src/lib/LibICloneableFactoryV4.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
error ZeroImplementationCodeSize();

/// Thrown when an implementation's code begins with `0xef`: an EIP-7702
/// delegated account.
/// delegated account. The only mutable-code shape detectable here; an
/// implementation that delegates onward to a mutable target is not.
error DelegatedImplementation();

/// Thrown when the clone address already has code. On the open-salt path the
Expand Down
Loading