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

Pool Created on Already-Terminal Agreement Allows No Staking

Author Revealed upon completion

Summary

When creating a pool, initialize() only checks if the agreement is registered (isAgreementValid), but does not check the agreement's current state. A pool can be successfully deployed on an agreement already in CORRUPTED, PRODUCTION, or PROMOTION_REQUESTED state. Where staking is permanently blocked, resulting in a pool that is born dead.

Root Cause

//initialize()
// Only checks existence, NOT current state
if (!IBattleChainSafeHarborRegistry(safeHarborRegistry_).isAgreementValid(agreement_)) {
revert InvalidAgreement();
}

While staking correctly blocks terminal states:

//stake()
function _assertDepositsAllowed(IAttackRegistry.ContractState state) private pure {
if (
state == IAttackRegistry.ContractState.PROMOTION_REQUESTED
|| state == IAttackRegistry.ContractState.PRODUCTION
|| state == IAttackRegistry.ContractState.CORRUPTED
) {
revert StakingClosed();
}
}

There is no matching guard at pool creation time.

Code Snippet-
https://github.com/CodeHawks-Contests/2026-07-bc-confidence-pools/blob/58e8ba4ce3f3277866e4926f3140e597f9554a1e/src/ConfidencePool.sol#L200

Impact

Pool deploys successfully but no one can ever stake on it.

Mitigation

Add agreement state check inside initialize() after the isAgreementValid check:

// After existing isAgreementValid check, add:
address attackRegistry = IBattleChainSafeHarborRegistry(safeHarborRegistry_)
.getAttackRegistry();
if (attackRegistry != address(0)) {
IAttackRegistry.ContractState state = IAttackRegistry(attackRegistry)
.getAgreementState(agreement_);
if (
state == IAttackRegistry.ContractState.PROMOTION_REQUESTED ||
state == IAttackRegistry.ContractState.PRODUCTION ||
state == IAttackRegistry.ContractState.CORRUPTED
) {
revert AgreementNotEligibleForPool();
}
}

This ensures pools are only created on agreements where staking is still possible.

Support

FAQs

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

Give us feedback!