# Some protection buyers might not be able to renew their protections due to delayed expiration processing.

Carapace's verifyAndAccruePremium skips expiration check when no payment was made after protection start, so expired protections never get processed and buyers can't renew.

- Payout: Contest reward
- Severity: medium
- Program: Carapace
- Credited: chaduke
- Disclosed: 2023-02-01
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-02-carapace-judging/issues/27
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-02-carapace%3AM-9
- Tags: domain:web3 impact:dos kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** ProtectionPool / ProtectionPoolHelper premium accrual and expiration logic
**Root cause:** verifyAndAccruePremium returns early (0,false) when _latestPaymentTimestamp < _startTimestamp or _startTimestamp > block.timestamp, before computing _protectionExpired, so protections with no post-start payment are never marked expired.
**Steps:**
1. Buy a protection P with startTimestamp in the future or with no premium payment made after start.
2. Wait past P's expiration (startTimestamp + protectionDurationInSeconds).
3. Call _accruePremiumAndExpireProtections: verifyAndAccruePremium hits the early return at L215-220 and returns _protectionExpired=false.
4. expireProtection() is never invoked, so expiredProtectionIndexByLendingPool[lendingPool][nftLpTokenId] is never populated.
5. Call renewProtection: verifyBuyerCanRenewProtection fails to find an expired protection and reverts; after grace period renewal is permanently blocked.
**How found:** Code reading of the expiration flow: traced verifyBuyerCanRenewProtection -> expireProtection -> verifyAndAccruePremium and noticed the early-return branch precedes the expiration computation, so the expired flag can never be set in the no-payment case.
**Insight:** When auditing state-machine expiry logic, check that early-return guards don't bypass the expiration/flag computation; a guard meant to skip premium accrual can also skip the state transition that downstream renewal/lookup logic depends on.
