# sFrxEth may revert on redeeming non-zero amount

SfrxEth.withdraw reverts when redeeming a tiny share amount that rounds to zero assets, blocking SafEth unstaking entirely.

- Payout: Contest reward
- Severity: medium
- Program: Asymmetry Finance
- Credited: d3e4
- Disclosed: 2023-07-28
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-03-asymmetry-findings/issues/1049
- Library page: https://bugbountylibrary.com/r/c4%3A2023-03-asymmetry%3AM-02
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:dos

**Target:** SafEth derivative SfrxEth.withdraw / unstake flow
**Root cause:** SfrxEth.withdraw calls frxEth.redeem(_amount) which requires previewRedeem(shares)!=0; when shares are tiny and totalAssets<totalSupply, mulDivDown rounds assets to 0 and reverts, propagating up through SafEth.unstake.
**Steps:**
1. Set sFrxEth derivative weight to 0 so its balance is only drained proportionally.
2. Repeatedly unstake ~50% of SafEth supply; each withdrawal removes a percentage of remaining sFrxEth balance.
3. Balance shrinks toward 1 wei; when _amount==1 and totalAssets<totalSupply, previewRedeem returns 0.
4. redeem reverts with ZERO_ASSETS, causing SfrxEth.withdraw and SafEth.unstake to revert, blocking all unstaking.
**How found:** Read SfrxEth.withdraw's call into frxEth.redeem and traced the ZERO_ASSETS require through previewRedeem/convertToAssets mulDivDown rounding; realized proportional percentage withdrawals can drive the derivative balance to 1 wei.
**Insight:** When a wrapper forwards a proportional share of its balance to an ERC4626-style redeem, rounding-to-zero reverts can permanently brick the whole withdrawal path; check whether tiny residual balances are reachable via percentage-based drains.
