# A user can steal from the shrine by forcing redistribution of their trove; due to incorrect logic trove debt will be reset but yangs kept

In Opus Shrine, redistribute_helper skips updating new_yang_totals for zero-balance yangs, leaving trove debt reset while collateral is retained, letting a user withdraw stolen yang.

- Payout: Contest reward
- Severity: high
- Program: Opus
- Credited: kfx
- Disclosed: 2024-03-08
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2024-01-opus-findings/issues/143
- Library page: https://bugbountylibrary.com/r/c4%3A2024-01-opus%3AH-03
- Tags: domain:web3 impact:funds-loss impact:integrity kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Shrine redistribute_helper loop (Cairo/StarkNet lending protocol)
**Root cause:** In redistribute_helper, when a yang's trove amount is zero the code updates updated_trove_yang_balances then `continue`s before updating new_yang_totals, so the final write loop misaligns indices and never zeroes the trove's actual yang balance while debt is fully redistributed.
**Steps:**
1. Set up trove1 and trove2 each depositing the same yang with equal debt.
2. Trigger `shrine.redistribute(trove1, debt, RAY_ONE)` for 100% redistribution.
3. Observe trove1 retains its yang deposit but debt becomes 0, while trove2 absorbs the debt.
4. Withdraw the retained yang from trove1 to steal collateral.
**How found:** Code-reading of redistribute_helper loop: noticed `continue` after updating updated_trove_yang_balances but before new_yang_totals, causing array misalignment; validated with a PoC test and invariant check.
**Exploitation:** Attacker forces redistribution of their own trove (e.g. by draining the absorber via forced absorptions, then borrowing max and letting small price moves push ltv over threshold). After redistribution their debt is zeroed but yangs remain, which they withdraw, extracting value from the shrine at other users' expense.
**Insight:** When auditing loops that build parallel arrays with early `continue`, check that every array is advanced in lockstep; a skipped index silently misaligns later writes.
