ConfidencePoolFactory::setPoolImplementation() only checks that the new implementation address is not the zero address. It does not verify that the address contains contract code.
As a result, the factory owner can accidentally configure poolImplementation to an EOA or another address with no code. Future calls to createPool() may then create and register pool clones that depend on an invalid implementation address.
This does not affect existing pools. The issue is limited to future pools created after the misconfiguration.
In ConfidencePoolFactory.sol, the implementation setter only validates against the zero address:
The function does not check whether newPoolImplementation contains contract code.
createPool() later uses the configured implementation directly:
The created pool is then recorded in the factory registry:
Therefore, if poolImplementation is misconfigured to a non-contract address, future pool entries may be recorded by the factory even though the implementation address they depend on does not contain valid ConfidencePool logic.
This is primarily an admin misconfiguration risk.
If poolImplementation is set to a non-contract address:
Future pool deployments may be registered with invalid clone logic.
The factory can record pool addresses that do not behave like ConfidencePool.
Indexers, frontends, and users relying on getPoolsByAgreement() may see unusable pool entries.
Agreement owners may believe they successfully created a pool while the deployed clone is not backed by valid pool logic.
Existing pools are not affected because pool clones are non-upgradeable and keep using the implementation address they were created with.
This requires factory owner action and does not directly allow an untrusted actor to steal funds. The issue is best classified as Low / QA due to misconfiguration risk and reduced deployment safety.
Manual review
The test below demonstrates the issue step by step:
poolImplementation is set to an address with no contract code.
createPool() is called with a valid agreement and token.
The factory returns a clone address and registers it in _poolsByAgreement.
The clone has bytecode (minimal proxy), but its underlying implementation is not a valid ConfidencePool.
Add a code length validation when setting a new pool implementation:
The same validation can also be added in initialize() for poolImplementation_ to prevent the factory from being initialized with an invalid implementation address.
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.