if (recoveryAddress_ == address(0)) revert InvalidRecoveryAddress();
if (expiry_ < block.timestamp + _MIN_EXPIRY_LEAD) revert ExpiryTooSoon();
@> if (expiry_ > type(uint32).max) revert ExpiryTooFar();
function setExpiry(uint256 newExpiry) external onlyOwner {
if (expiryLocked) revert ExpiryLocked();
if (newExpiry < block.timestamp + _MIN_EXPIRY_LEAD) revert ExpiryTooSoon();
@> if (newExpiry > type(uint32).max) revert ExpiryTooFar();
if (
@> riskWindowStart != 0
|| (state != IAttackRegistry.ContractState.NOT_DEPLOYED
&& state != IAttackRegistry.ContractState.NEW_DEPLOYMENT
&& state != IAttackRegistry.ContractState.ATTACK_REQUESTED)
) {
revert WithdrawsDisabled();
}
function testExpiryHasNoCeilingTrappingPrincipalForDecades() external {
uint256 farExpiry = type(uint32).max - 1;
MockSafeHarborRegistry factoryRegistry = new MockSafeHarborRegistry();
factoryRegistry.setAttackRegistry(address(attackRegistry));
address agreementOwner = makeAddr("agreementOwner");
MockAgreement mockAgreement = new MockAgreement(agreementOwner);
factoryRegistry.setAgreementValid(address(mockAgreement), true);
ConfidencePool implementation = new ConfidencePool();
ConfidencePoolFactory factoryImpl = new ConfidencePoolFactory();
ERC1967Proxy proxy = new ERC1967Proxy(
address(factoryImpl),
abi.encodeCall(
ConfidencePoolFactory.initialize, (address(factoryRegistry), address(implementation), moderator)
)
);
ConfidencePoolFactory factory = ConfidencePoolFactory(address(proxy));
factory.setStakeTokenAllowed(address(token), true);
address farPoolAddr = factory.createPool(
address(mockAgreement), address(token), farExpiry, ONE, recovery, _defaultScope()
);
ConfidencePool farPool = ConfidencePool(farPoolAddr);
token.mint(alice, 100 * ONE);
vm.startPrank(alice);
token.approve(address(farPool), 100 * ONE);
farPool.stake(100 * ONE);
vm.stopPrank();
attackRegistry.setAgreementState(IAttackRegistry.ContractState.UNDER_ATTACK);
farPool.pokeRiskWindow();
vm.prank(alice);
vm.expectRevert(IConfidencePool.WithdrawsDisabled.selector);
farPool.withdraw();
vm.prank(alice);
vm.expectRevert(IConfidencePool.PoolNotExpired.selector);
farPool.claimExpired();
vm.prank(moderator);
vm.expectRevert(IConfidencePool.InvalidOutcome.selector);
farPool.flagOutcome(PoolStates.Outcome.SURVIVED, false, address(0));
vm.prank(moderator);
vm.expectRevert(IConfidencePool.InvalidOutcome.selector);
farPool.flagOutcome(PoolStates.Outcome.CORRUPTED, false, address(0));
assertEq(token.balanceOf(address(farPool)), 100 * ONE, "principal stuck in pool");
assertGt(farExpiry - block.timestamp, 365 days * 50, "no exit for at least 50 years");
}