FoundrySolidityLayer 2
7.25 ETH
Submission Details
Impact: low
Likelihood: low

Missing minStake validation in ConfidencePoolFactory.createPool leads to wasted clone deployment

Author Revealed upon completion

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 in the codebase with @> marks to highlight the relevant section

Root Cause Code:

// src/ConfidencePoolFactory.sol createPool function
// No minStake > 0 check before:
pool = Clones.cloneDeterministic(poolImplementation, salt);
// @> The clone is deployed here, then initialize fails below:
IConfidencePool(pool).initialize(..., minStake, ...);
// @> Reverts with InvalidAmount() if minStake == 0

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);

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!