# Users can fail to unstake and lose their deserved ETH because malfunctioning or untrusted derivative cannot be removed

SafEth has no way to remove a derivative; if one derivative's external pool is killed or hacked, unstake reverts for all users, locking their ETH.

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

**Target:** SafEth staking contract and WstEth derivative
**Root cause:** adjustWeight can zero a derivative's weight but no removal function exists, so unstake's loop still calls every derivative's withdraw; a reverting derivative (e.g. killed Curve stETH-ETH pool) reverts the whole unstake.
**Steps:**
1. WstEth is a registered derivative; its withdraw calls IStEthEthPool(LIDO_CRV_POOL).exchange(1,0,stEthBal,minOut).
2. Curve pool's self.is_killed becomes true (hack/compromise), so exchange always reverts.
3. Alice calls SafEth.unstake(_safEthAmount); loop reaches WstEth.withdraw which reverts.
4. Entire unstake reverts despite other derivatives being healthy; Alice cannot withdraw her ETH.
**How found:** Code reading of unstake's loop over all derivatives and WstEth.withdraw's dependency on the Curve pool's is_killed assertion; noted absence of any derivative-removal path.
**Insight:** When a contract loops over a registry of external dependencies, check whether entries can be removed/disabled; a single reverting or killed dependency can DoS the whole loop and lock user funds.
