# DAO admin in LiquidStakingManager.sol can rug the registered node operator by stealing their fund in the smart wallet via arbitrary execution.

DAO admin's executeAsSmartWallet lets it make arbitrary calls from a node runner's smart wallet, draining the 4 ETH deposit and any ERC20s held there.

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

**Target:** LiquidStakingManager.executeAsSmartWallet / OwnableSmartWallet
**Root cause:** executeAsSmartWallet is onlyDAO and forwards arbitrary _to/_data/_value to the node runner's smart wallet, which the manager owns, so the DAO can direct the wallet to transfer its ETH or tokens anywhere.
**Steps:**
1. Register a node runner via `manager.registerBLSPublicKeys{value: 4 ether}(publicKeys, signature, user)`; wallet holds 4 ETH.
2. As admin call `manager.executeAsSmartWallet(user, rugContract, abi.encodeWithSelector(RugContract.receiveFund.selector), 4 ether)` to move ETH out.
3. For ERC20: `manager.executeAsSmartWallet(user, token, abi.encodeWithSelector(IERC20.transfer.selector, rug, 100 ether), 0)` drains tokens.
4. Run `forge test -vv --match testDaoRugFund_Pull_ETH_POC`; wallet balance goes 4e18 -> 0.
**How found:** Code review of the onlyDAO executeAsSmartWallet proxy and the smart wallet ownership model; noticed the manager owns the wallet and can forward arbitrary calls, then wrote Foundry PoCs for ETH and ERC20 theft.
**Exploitation:** DAO admin (privileged) calls executeAsSmartWallet targeting an attacker contract with value equal to the wallet's ETH balance, or targeting a token with transfer calldata, emptying the node runner's smart wallet.
**Insight:** When a contract owns user smart wallets, any privileged function that proxies arbitrary calls through those wallets is effectively a drain primitive — check every onlyDAO/onlyOwner path that reaches wallet.execute.
