# AstridProtocol: fake staked-token address drains collateral via withdraw/claim

AstridProtocol withdraw/claim trusted attacker-supplied fake ERC20 staked-token address, letting attacker drain stETH/rETH/cbETH collateral (~$228k).

- Payout: Real-world hack
- Severity: high
- Program: AstridProtocol
- Analysis by: DeFiHackLabs
- Disclosed: 2023-10-28
- Write-up quality: 6/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2023-10/Astrid_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20231028-astrid
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** Restaking protocol withdraw/claim functions
**Root cause:** withdraw() accepted an arbitrary _restakedTokenAddress and read scaledBalanceOf/scaledBalanceToBalance from it, so a fake token returning attacker-chosen values let claim() release real staked collateral.
**Steps:**
1. Fork mainnet at block 18448167.
2. For each staked token (stETH, rETH, cbETH): read vulnerable contract's balance.
3. Deploy fake MyERC20 with stakedTokenAddr=real token and scaledBalanceToBal=real balance; mint and approve max to vulnerable.
4. Call `vulnerable.withdraw(address(fake_token), staked_bal)` then `vulnerable.claim(i)`.
5. Swap drained stETH via Curve Lido pool, rETH/cbETH via Uniswap V3 pools to WETH, unwrap to ETH.
**Exploitation:** Attacker deployed a fake ERC20 whose scaledBalanceOf returns 0 and scaledBalanceToBalance returns the victim contract's real token balance, passed it to withdraw(), then claim() released the real stETH/rETH/cbETH held by the protocol; converted all to ETH.
**Insight:** When a withdraw/claim function takes a token address as a parameter, check whether it trusts that address's balance/scale getters instead of the protocol's own accounting — a fake token returning arbitrary values can unlock real collateral.

