# Neglect of exceptional redistribution amounts in withdraw_helper function

In Opus Shrine, withdraw_helper computes new trove balance before charge() applies exceptional redistribution, overwriting and losing redistributed collateral.

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

**Target:** Shrine contract withdraw_helper (Cairo, StarkNet)
**Root cause:** withdraw_helper reads trove balance and computes new_trove_balance before calling charge(); charge() writes redistribution-updated deposits, which withdraw_helper then overwrites with the stale pre-charge value.
**Steps:**
1. Read deposits(yang_id,trove_id)=1000
2. Call abbot.withdraw for amount=100
3. withdraw_helper computes new_trove_balance=1000-100=900
4. charge() applies exceptional redistribution writing deposits=1050
5. withdraw_helper writes deposits=900, discarding the +50 redistribution
**How found:** Code reading of withdraw_helper ordering: noticed charge() mutates deposits after new_trove_balance was already computed, so the subsequent write clobbers redistribution updates.
**Exploitation:** Any user withdrawing yang during/after an exceptional redistribution has their redistributed collateral silently overwritten and lost; no attacker capital needed, loss occurs on normal withdraw.
**Insight:** When a helper computes a new value from storage then calls a function that also mutates that same storage slot, check ordering: any write after the mutating call must re-read state, not reuse the pre-call snapshot.
