For the complete documentation index, see llms.txt. This page is also available as Markdown.

88712 sc high mutable period start snapshot lets lps remove collateral after it has been committed to cover

Submitted on Aug 14th 2026 at 17:02:00 UTC by @Jolyon for Audit Comp | Firelight

  • Report ID: #88712

  • Report Type: Smart Contract

  • Report severity: High

  • Target: https://github.com/immunefi-team/audit-comp-firelight/blob/v1_audit_ready/contracts/core/FirelightVault.sol

  • Impacts:

    • Protocol insolvency

Description

Brief/Intro

Capacity commitment and claim payout do not use an immutable shared collateral snapshot. At period start T, the allocator commits cover against totalAssetsAt(T). An LP can then withdraw at the same timestamp and reduce that historical value. Settlement still uses the original commitment, while payout uses the reduced snapshot, allowing collateral backing already-sold cover to escape slashing.

Vulnerability Details

The allocator reads period-start assets and stores the resulting capacity in CoverOrderAllocator.sol and commitAllocation.

A later same-timestamp withdraw/redeem writes the reduced active-assets value through _logTrace. Checkpoints.push appends or replaces the checkpoint at T, and the inclusive lookup makes it authoritative.

Settlement continues using the stored commitment, but FirelightVault.payout re-reads the now-lower totalAssetsAt(T) as its payout cap.

The exploit requires an exact-T block, allocator-first ordering, and the attacker’s reduced checkpoint to remain the final relevant write at T.

Impact Details

If the allocator commits against A vault assets and the attacker subsequently withdraws X at the same timestamp, the vault payout cap can be reduced from A to A-X.

For a full exit where X=A, the vault payout becomes zero. The incident is nevertheless finalized by IncidentManager, while the attacker later claims the un-slashed collateral.

This creates an unfunded liability against already-sold cover and therefore maps to Protocol insolvency.

Proof of Concept

The attached Hardhat test reproduces the issue using the unmodified FirelightVault, CoverOrderAllocator, CoverNFT, and IncidentManager. Only the ERC20 asset and price feed are mocked; the test is fully local and does not use a fork or contact a live network.

The test performs the following sequence:

1

Deposit and create cover

An LP deposits 100 asset units into the vault, while the funded and approved first-loss buffer provides another 20 units.

A 120-unit cover order is created for period P.

2

Commit and redeem at the exact period start

At the exact start T of P, commitAllocation executes first and the LP's full redeem executes second in the same block.

The commitment retains 120 capacity, but the redemption changes totalAssetsAt(T) to zero while the vault still physically holds the 100 units as a delayed withdrawal.

3

Settle cover and process the incident

The cover is settled before a valid incident occurs. For the resulting 120-unit loss, the first-loss buffer pays 20, while the vault is requested to pay 100 but pays zero.

4

Claim escaped collateral

The incident closes, and at P+2 the LP claims the entire 100 units that should have remained slashable.

A negative-control test changes only the redemption timestamp from T to T+1. In that case, the period-start snapshot remains 100, the vault pays the complete 100-unit request, and the LP's later withdrawal claim reverts with NoWithdrawalAmount.

This demonstrates that mutating the already-consumed period-start checkpoint is the direct cause of the payout shortfall.

test/poc/F001.exact-period-boundary.js

Was this helpful?