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

# Up-to-180-day fund lock with no partial-principal escape during the moderator grace window

Author Revealed upon completion

Summary

When the registry is CORRUPTED with an observed risk window, claimExpired reverts for the entire 180-day grace period and every other staker exit is also blocked, freezing all principal — even in the case where stakers are eventually owed a full refund.

Description

src/ConfidencePool.sol:532-542:

if (state == IAttackRegistry.ContractState.CORRUPTED && riskWindowStart != 0) {
if (block.timestamp < expiry + MODERATOR_CORRUPTED_GRACE) { // 180 days
revert AgreementCorruptedAwaitingModerator(); // L541
}
...
}

During expiry ≤ now < expiry + 180 days every staker path reverts:

  • withdraw()WithdrawsDisabled (disabled once riskWindowStart != 0)

  • claimExpired()AgreementCorruptedAwaitingModerator

  • claimSurvived() / claimCorrupted()OutcomeNotSet (outcome still UNRESOLVED)

Risk

Likelihood: Medium — occurs whenever the registry is CORRUPTED with an observed risk window and the moderator is slow.

Impact: Medium — all staker principal is frozen for up to 180 days with no partial or emergency exit, including the eventual full-refund (out-of-scope) case.

Proof of Concept

test/poc/ManualReviewPoC.t.sol::testPoC_graceWindowLocksPrincipal:

function testPoC_graceWindowLocksPrincipal() external {
_stake(alice, 1000 * ONE);
_passThroughUnderAttack();
attackRegistry.setAgreementState(IAttackRegistry.ContractState.CORRUPTED);
vm.warp(uint256(pool.expiry()) + 1); // inside the grace window
vm.prank(alice);
vm.expectRevert(IConfidencePool.WithdrawsDisabled.selector);
pool.withdraw();
vm.prank(alice);
vm.expectRevert(IConfidencePool.AgreementCorruptedAwaitingModerator.selector);
pool.claimExpired();
vm.prank(alice);
vm.expectRevert(IConfidencePool.OutcomeNotSet.selector);
pool.claimSurvived();
assertEq(token.balanceOf(alice), 0); // principal frozen
}

Result: [PASS] — all three exits revert, Alice's balance stays 0.

Recommended Mitigation

Document the maximum lock for stakers, and shorten the grace period (the backstop only needs to defend against a permanently absent moderator) or add an outcome-neutral partial-principal escape.

- uint256 public constant override MODERATOR_CORRUPTED_GRACE = 180 days;
+ uint256 public constant override MODERATOR_CORRUPTED_GRACE = 30 days;

Support

FAQs

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

Give us feedback!