# Re-balancing the vault allocation may always revert when distributing profits: resulting of a massive system DOS  

StabilityPool.updateRewardSum with zero debt offset underflows lastLUSDLossError_Offset, making ActivePool._rebalance revert and bricking most Trove operations.

- Payout: Contest reward
- Severity: high
- Program: Ethos Reserve
- Credited: 0xBeirao
- Disclosed: 2023-05-02
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-02-ethos-findings/issues/481
- Library page: https://bugbountylibrary.com/r/c4%3A2023-02-ethos%3AH-01
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** StabilityPool / ActivePool Solidity contracts
**Root cause:** updateRewardSum calls _computeRewardsPerUnitStaked with _debtToOffset=0; the loss-error assignment at L531 computes a negative value into an uint when lastLUSDLossError_Offset != 0, reverting.
**Steps:**
1. Vault accrues profit above yieldClaimThreshold so vars.profit != 0 in _rebalance.
2. Trigger a trove liquidation so StabilityPool.offset() runs and floor division leaves lastLUSDLossError_Offset != 0.
3. Call any function invoking ActivePool._rebalance() (openTrove, closeTrove, adjustTrove, withdrawLUSD, repayLUSD, liquidations).
4. updateRewardSum -> _computeRewardsPerUnitStaked with _debtToOffset=0 underflows at L531 and reverts.
**How found:** Code reading of updateRewardSum/_computeRewardsPerUnitStaked noting _debtToOffset=0 path and the uint assignment of a negative loss-error value.
**Exploitation:** No attacker capital needed; once a liquidation sets a nonzero loss error and the vault has withdrawable profit, every _rebalance call reverts, permanently blocking borrower operations and most liquidations.
**Escalation:** Single underflow cascades into system-wide DOS across BorrowerOperations and TroveManager.
**Insight:** In rebasing/accounting pools, audit the zero-amount branch of reward-per-unit math: floor-division error accumulators assigned to unsigned ints underflow when the offset is zero, and any later call path that reuses that state bricks the pool.
