# ArrakisMetaVault::setModule Malicious executor can drain the vault by calling withdraw after initializePosition

Malicious executor calls setModule with crafted payloads to withdraw vault funds to an arbitrary address after re-initializing position, draining the vault.

- Payout: Contest reward
- Severity: high
- Program: Arrakis
- Credited: cergyk
- Disclosed: 2024-03-02
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2024-03-arrakis-judging/issues/50
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-03-arrakis%3AH-4
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:accounting-error vuln:business-logic

**Target:** ArrakisStandardManager / ArrakisMetaVault module management
**Root cause:** setModule executes arbitrary executor-supplied payloads after moving vault funds into the new module, without validating reserves or restricting payload targets, so a payload can call withdraw to an attacker address.
**Steps:**
1. Owner whitelists a legitimate new module via `ArrakisMetaVault::whitelistModules`.
2. Malicious executor calls `ArrakisStandardManager::setModule` with crafted `payloads_`.
3. setModule calls `ArrakisMetaVault::setModule`, which calls `ValantisModulePublic::withdraw` to move all vault funds from old module to new module.
4. First payload calls `ValantisModule::initializePosition` to deposit liquidity into the new pool.
5. Second payload calls `ValantisModule::withdraw` with attacker as receiver, extracting all funds.
**How found:** Code review of setModule flow: noticed executor-controlled payloads execute after funds are transferred into the new module, and that withdraw is reachable from those payloads without reserve validation.
**Exploitation:** Executor supplies two payloads: first re-initializes position to satisfy state, second calls withdraw with attacker as receiver, moving all vault funds to attacker. Alternatively withdrawManagerBalance or empty payloads leave funds in module.
**Insight:** When a privileged function executes arbitrary caller-supplied payloads after moving funds, check whether any reachable function in the payload can move those funds out; the trust boundary is the payload, not the caller role.
