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

`PoolStates.isTerminal` is unused dead code

Author Revealed upon completion

Description

PoolStates defines a helper for checking whether an Outcome is terminal:

library PoolStates {
enum Outcome {
UNRESOLVED,
SURVIVED,
CORRUPTED,
EXPIRED
}
/// @notice Returns true when an outcome is terminal.
function isTerminal(Outcome outcome) internal pure returns (bool) {
return outcome != Outcome.UNRESOLVED;
}
}

isTerminal is never called anywhere in the codebase. Every terminality check in
ConfidencePool.sol is instead written as a direct comparison against PoolStates.Outcome
members, e.g.:

if (outcome != PoolStates.Outcome.UNRESOLVED) revert OutcomeAlreadySet(); // stake()
if (outcome != PoolStates.Outcome.UNRESOLVED) revert OutcomeAlreadySet(); // contributeBonus()
if (outcome != PoolStates.Outcome.UNRESOLVED) revert OutcomeAlreadySet(); // withdraw()
if (outcome != PoolStates.Outcome.UNRESOLVED && claimsStarted) revert OutcomeAlreadySet(); // flagOutcome()
if (outcome != PoolStates.Outcome.UNRESOLVED && outcome != PoolStates.Outcome.EXPIRED) { ... } // claimExpired()
if (outcome != PoolStates.Outcome.UNRESOLVED) return; // pokeRiskWindow()

Confirmed via repo-wide search — isTerminal has zero call sites in src/:

$ grep -rn "isTerminal" src/
src/libraries/PoolStates.sol:14: function isTerminal(Outcome outcome) internal pure returns (bool) {

Impact

None functionally — it's internal pure and costs nothing at runtime if unused (the compiler
strips unreferenced internal functions from deployed bytecode). It is purely a maintainability /
code-hygiene issue: an unused helper that duplicates logic already inlined everywhere else is a
latent inconsistency risk. If a future change ever introduces a fifth Outcome value, or if a
future call site starts using isTerminal instead of the inline pattern, the two representations
of "terminal" could silently drift apart from the direct-comparison sites that would need the same
update.

Recommended Mitigation

Either:

  1. Remove isTerminal if it's not intended to be used, or

  2. Replace the repeated outcome != PoolStates.Outcome.UNRESOLVED checks throughout
    ConfidencePool.sol with PoolStates.isTerminal(outcome) so there is a single source of truth
    for terminality.

Support

FAQs

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

Give us feedback!