# IndexTemplate.sol#compensate() will most certainly fail

Precision loss in IndexTemplate.compensate() share-to-underlying conversion makes CDS compensation always short, reverting offsetDebt and freezing pool funds.

- Payout: Audit contest
- Severity: high
- Program: InsureDAO
- Found by: WatchPug
- Disclosed: 2022-03-15
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-01-insure-findings/issues/269
- Library page: https://bugbountylibrary.com/r/c4%3A2022-01-insure%3AH-08
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:precision-loss

**Target:** IndexTemplate.sol compensate() / CDSTemplate.sol share conversion
**Root cause:** CDSTemplate.compensate() takes an underlying-token amount but transfers shares via vault.transferValue(); floor rounding of _attributions yields less underlying value than the shortage, so _compensated understates actual value and offsetDebt's require(underlyingValue >= _amount) reverts.
**Steps:**
1. Call PoolTemplate.resume() after pending period ends, triggering IndexTemplate.compensate()
2. Index pool insolvent: _shortage = _amount - _value
3. CDS.compensate(_shortage) computes _attributions = (_amount * totalAttributions) / valueAll and transfers shares
4. actualValueTransferred = (valueAll * _attributions) / totalAttributions < _shortage due to floor rounding
5. _compensated = _value + _cds understates; vault.offsetDebt(_compensated, msg.sender) reverts at require(underlyingValue(msg.sender) >= _amount)
6. resume() fails, debt unrepaid, LP funds frozen
**How found:** Code review of compensate() flow noting unit mismatch: CDS.compensate() parameter is underlying tokens but implementation transfers shares, then tracing rounding through the share/value conversion to the offsetDebt require.
**Exploitation:** Not attacker-driven; any resume() call after insolvency deterministically reverts, locking LP and index pool funds and unfairly distributing prior compensations among vault stakeholders.
**Insight:** When a function's parameter unit (underlying tokens) differs from what it actually transfers (shares), trace the round-trip conversion and check whether floor rounding can make a downstream require() fail deterministically rather than only on edge numbers.
