# Giant pools can be drained due to weak vault authenticity check

Giant pools trusted any caller-supplied vault whose liquidStakingManager() returned a valid manager, letting an attacker pass a fake vault and drain pooled ETH.

- Payout: Contest reward
- Severity: high
- Program: Stakehouse Protocol
- Credited: Jeiwan
- Disclosed: 2023-01-20
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-11-stakehouse-findings/issues/251
- Library page: https://bugbountylibrary.com/r/c4%3A2022-11-stakehouse%3AH-17
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** GiantSavETHVaultPool / GiantMevAndFeesPool batchDepositETHForStaking
**Root cause:** Vault authenticity was checked by calling liquidStakingManager() on the untrusted vault address and only validating the returned manager, so an attacker-controlled contract could return a valid manager address and receive the ETH.
**Steps:**
1. Deploy exploit contract implementing liquidStakingManager() returning a registered valid manager address and batchDepositETHForStaking() forwarding received ETH to owner.
2. Call `giantSavETHPool.batchDepositETHForStaking([exploit], [amount], [blsKeys], [stakeAmounts])` with the exploit as the vault address.
3. Pool passes the isLiquidStakingManager check and sends ETH to the exploit contract, which transfers it to the attacker.
**How found:** Code review of the vault authenticity check: noticed the check calls a method on the untrusted vault argument rather than validating the vault address itself, making the check spoofable by any contract.
**Exploitation:** Attacker needs no capital beyond gas: they pass their own contract as the vault in batchDepositETHForStaking; the pool's authenticity check calls liquidStakingManager() on the attacker contract which returns a legitimate manager, so the pool forwards idle ETH to the attacker contract which sweeps it to the attacker.
**Insight:** When validating an untrusted address, never call a method on that address to derive the trusted reference; instead take the trusted entity (manager) as input and derive the dependent contract (vault) from it.
