Description
The ConfidencePoolFactory.createPool function deploys a clone contract via CREATE2 before validating all inputs. The minStake parameter is only checked inside ConfidencePool.initialize, which executes after the clone is already deployed. If minStake is zero, the clone is deployed but initialization reverts, wasting gas and leaving an unused contract on-chain.
## Root + Impact
The `createPool` function does not validate `minStake > 0` before deploying a clone contract. The check exists in `ConfidencePool.initialize` but runs after the clone is already deployed via CREATE2. This wastes gas and leaves an unused clone on-chain.
## Risk
Likelihood: Low — requires user to pass minStake=0, which is unlikely in normal operation.
Impact: Low — only gas waste and blockchain state bloat, no fund loss.
## Proof of Concept
Calling `createPool` with `minStake = 0` deploys a clone at the deterministic address, then reverts during `initialize` with `InvalidAmount()`. The clone contract remains deployed but permanently unusable because `initialize` uses the `initializer` modifier and the second attempt will succeed (after gas waste on first attempt).
## Recommended Mitigation
Add input validation in `createPool` before `cloneDeterministic`:
```diff
function createPool(...) external whenNotPaused returns (address pool) {
...
+ if (minStake == 0) revert InvalidAmount();
...
pool = Clones.cloneDeterministic(poolImplementation, salt);
Root Cause Code:
pool = Clones.cloneDeterministic(poolImplementation, salt);
IConfidencePool(pool).initialize(..., minStake, ...);
Recommended Mitigation
Add input validation in `createPool` before `cloneDeterministic`:
```diff
function createPool(...) external whenNotPaused returns (address pool) {
...
+ if (minStake == 0) revert InvalidAmount();
...
pool = Clones.cloneDeterministic(poolImplementation, salt);