ConfidencePoolFactory.createPool() deploys a deterministic clone and invokes initialize() exactly once. The expected lifecycle is that initialization completes before the pool becomes externally usable.
However, initialize() performs an external call through _replaceScope() before initialization has completed. The function is protected by OpenZeppelin's initializer modifier but not nonReentrant. These two mechanisms are independent: initializer only prevents re-entering another initializer/reinitializer function, while it does not engage ReentrancyGuard's lock.
Before _replaceScope() executes, the pool has already initialized state required by user-facing entrypoints, including stakeToken, minStake, expiry, and outcome. A malicious agreement implementation can therefore reenter the pool during _replaceScope() and successfully invoke externally callable functions such as stake() or contributeBonus() while initialization is still in progress.
Likelihood:
initialize() performs an external call before initialization completes.
Because agreement is supplied by the pool creator, a malicious implementation can execute arbitrary logic during isContractInScope(), including reentering the pool.
Impact:
Reentrant execution into stake() and contributeBonus() is possible while the pool is still initializing.
exposing externally callable state-changing functions before initialization completes unnecessarily expands the contract's attack surface and deviates from the otherwise consistent defensive pattern (nonReentrant) used across the contract's value-moving functions.
The following call sequence demonstrates successful reentrant execution during initialization:
An illustrative Foundry test:
Prevent external execution while initialization is still in progress. One straightforward approach is to apply the same ReentrancyGuard protection already used by the contract's other state-changing functions.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
View preliminary resultsAppeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.