# Lien count per epoch is not updated ultimately locking the collateralized NFT

After a lien buyout resets its epoch, decreaseEpochLienCount reverts because liensOpenForEpoch was never incremented, blocking payments and liquidation and locking the collateral NFT.

- Payout: Contest reward
- Severity: high
- Program: Astaria
- Credited: 0xRajeev
- Disclosed: 2022-11-07
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2022-10-astaria-judging/issues/194
- Library page: https://bugbountylibrary.com/r/sherlock%3A2022-10-astaria%3AH-11
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:sherlock sev:high tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** PublicVault/LienToken epoch lien accounting
**Root cause:** liensOpenForEpoch is only incremented in commitToLien paths; a lien buyout resets lien start/duration to a new epoch without incrementing that epoch's count, so decreaseEpochLienCount underflows/reverts.
**Steps:**
1. Create a lien via commitToLien so liensOpenForEpoch[currentEpoch] is incremented.
2. Buy out the lien with a new duration so lien.start = block.timestamp and duration spills into a later epoch.
3. Borrower calls _payment: LienToken computes the lien's new epoch and calls IPublicVault(lienOwner).decreaseEpochLienCount for that epoch.
4. decreaseEpochLienCount reverts because liensOpenForEpoch[newEpoch] was never incremented.
5. Same revert occurs on liquidation; if PublicVault(owner).timeToEpochEnd() <= COLLATERAL_TOKEN.auctionWindow(), auctioning reverts and the collateral NFT is locked.
**How found:** Code reading of epoch lien accounting: noticed liensOpenForEpoch is only incremented in _increaseOpenLiens/_afterCommitToLien, then traced the buyout path that resets lien start/duration to a new epoch without updating the count.
**Exploitation:** Borrower or liquidator cannot pay or liquidate the bought-out lien; the revert in decreaseEpochLienCount blocks auction, permanently locking the collateralized NFT in the protocol.
**Escalation:** Conditional on epoch timing: when timeToEpochEnd() <= auctionWindow(), liquidation itself reverts, converting a payment DoS into permanent collateral lock.
**Insight:** When a state counter is incremented only on creation paths, audit every mutation that changes the key (epoch/start/duration) the counter is indexed by — buyouts, refinances, and duration extensions can silently desync accounting and turn decrements into reverts.
