The pool-level initialize omits the two curation gates that live only in Factory.createPool, enabling rogue clones over any valid agreement with any token — a phishing/impersonation surface.
Pools are meant to be created through Factory.createPool, which checks the stake token is allowlisted and that msg.sender owns the agreement.
The implementation is a public minimal-proxy target, and its initialize validates only zero-addresses / expiry / minStake / isAgreementValid — not the token allowlist and not agreement ownership. Anyone can Clones.clone(impl) and initialize over a real valid agreement they do not own, with a non-allowlisted or malicious token, naming themselves owner / moderator / recovery.
Likelihood:
Occurs whenever an attacker clones the public implementation directly and initializes it over a valid registered agreement.
Realized only when a victim is socially engineered into depositing into a pool that is absent from factory.getPoolsByAgreement.
Impact:
Rogue impersonation pool can route a victim's deposits to the attacker's recoveryAddress via a self-flagged CORRUPTED.
Bounded: rogue clones hold only voluntarily-deposited funds; they cannot collide with or touch factory-registered pools (different CREATE2 deployer) or protocol funds.
This shows an attacker cloning the public implementation and initializing a pool over a valid agreement they do not own, using a non-allowlisted token and naming themselves owner/moderator/recovery — none of which initialize rejects.
Restrict initialize to the factory, so the factory's allowlist + ownership gates cannot be bypassed:
(Alternative: re-check allowedStakeToken and IAgreement(agreement).owner() inside initialize itself.)
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.