# rotateNodeRunnerOfSmartWallet is vulnerable to a frontrun attack

Malicious node runner frontruns DAO's rotateNodeRunnerOfSmartWallet call to rotate their EOA and evade the ban/slash.

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

**Target:** LiquidStakingManager smart contract (rotateNodeRunnerOfSmartWallet)
**Root cause:** rotateNodeRunnerOfSmartWallet is callable by the current node runner, not just the DAO, so a malicious runner can rotate their EOA before the DAO's banning transaction lands, deleting smartWalletOfNodeRunner[_current] and causing the DAO tx to revert.
**Steps:**
1. Malicious node runner is current owner of a smart wallet in the LSD network.
2. DAO submits rotateNodeRunnerOfSmartWallet(_current, _new, true) to ban the runner.
3. Runner monitors mempool and frontruns with rotateNodeRunnerOfSmartWallet(_current, attackerNew, false) from their own address.
4. Runner's tx passes the `_current == msg.sender` check, sets smartWalletOfNodeRunner[_new]=wallet and deletes smartWalletOfNodeRunner[_current].
5. DAO tx reverts at `require(wallet != address(0), "Wallet does not exist")`; runner is never banned.
**How found:** Code reading of rotateNodeRunnerOfSmartWallet: noticed the access check allows `_current == msg.sender` in addition to DAO, and that the ban branch only triggers when msg.sender==dao, enabling a race.
**Exploitation:** Attacker (malicious node runner) watches the mempool for the DAO's banning transaction and submits an identical rotate call from their own EOA with _wasPreviousNodeRunnerMalicious=false, moving the wallet to a fresh address and deleting the old mapping entry so the DAO's tx reverts.
**Insight:** When a privileged action (ban/slash) shares an entrypoint with a user-callable state-mutating path, check whether the user path can invalidate the precondition (here deleting the mapping) so the admin tx reverts — classic frontrun-to-evade-punishment pattern.
