# Zero amount withdrawals of SafEth or Votium will brick the withdraw process

Zero-amount SafEth unstake or Votium CVX swap reverts, bricking AfEth withdraw() and trapping user's vAfEth tokens permanently.

- Payout: Contest reward
- Severity: high
- Program: Asymmetry Finance
- Credited: adriro
- Disclosed: 2024-02-06
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-09-asymmetry-findings/issues/36
- Library page: https://bugbountylibrary.com/r/c4%3A2023-09-asymmetry%3AH-02
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:dos

**Target:** AfEth.sol withdraw() / SafEth unstake / VotiumStrategy sellCvx
**Root cause:** withdraw() unconditionally calls SafEth.unstake() and VotiumStrategy.withdraw()->sellCvx(); both downstream contracts revert on zero input amount, so a zero split on either leg reverts the whole withdrawal.
**Steps:**
1. Set ratio such that safEthWithdrawAmount=0 (e.g. ratio=0) or votiumWithdrawAmount=0.
2. User calls `requestWithdraw()`; withdrawIdInfo stores safEthWithdrawAmount=0 with non-zero votiumWithdrawAmount (or vice versa).
3. After delay, user calls `withdraw()`; it invokes `ISafEth(SAF_ETH_ADDRESS).unstake(0,0)` which reverts `AmountTooLow()`.
4. Alternatively `sellCvx(0)` calls Curve `exchange_underlying(1,0,0,0)` which reverts `assert dx > 0`.
5. Stored withdrawIdInfo cannot be recomputed, so withdrawal is permanently bricked.
**How found:** Code-reading of AfEth.withdraw() call chain into SafEth.unstake() and VotiumStrategy.sellCvx(), noticing both downstream implementations revert on zero input while the split ratio can legitimately produce zero for one leg.
**Exploitation:** Any user whose withdrawal split rounds one leg to zero (ratio 0/1e18, small amounts, or last staker) permanently loses access to their queued vAfEth/SafEth position; no attacker capital needed, griefing/loss is self-inflicted by protocol logic.
**Insight:** When a contract batches multiple downstream calls, check each callee's zero/edge-input guards: a zero leg that 'shouldn't matter' can revert the whole batch and brick stored state that can't be recomputed.
