# Delegate call in Vault#_execute can alter Vault's ownership

Vault.execute delegatecalls a permissioned target that can reset the nonce storage slot, making init() callable again to seize Vault ownership.

- Payout: Contest reward
- Severity: medium
- Program: Fractional
- Credited: byterocket
- Disclosed: 2022-09-27
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-07-fractional-findings/issues/487
- Library page: https://bugbountylibrary.com/r/c4%3A2022-07-fractional%3AM-01
- Tags: domain:web3 impact:funds-loss impact:privesc kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** Vault.sol execute/_execute delegatecall and init()
**Root cause:** _execute delegatecalls an owner-permissioned target using the Vault's own storage; it only guards the owner slot, not nonce, so a callee can zero nonce and re-enable init().
**Steps:**
1. Deploy Vault proxy and call `init()` so address(this) is owner.
2. Deploy malicious target whose storage layout places a `nonce` slot matching Vault's nonce.
3. Owner calls `vaultProxy.execute(address(targetContract), abi.encodeCall(target.changeNonce,()), proof)`; delegatecall sets Vault nonce=0 and does not revert.
4. Attacker calls `vaultProxy.init()`; nonce==0 passes check, owner is set to msg.sender.
5. Assert `vaultProxy.owner() == attacker`.
**How found:** Noticed the developers cached and re-checked `owner` around the delegatecall, implying awareness of storage-takeover risk, then reasoned that other storage slots (nonce) also gate ownership via init() and are unchecked.
**Exploitation:** Requires the Vault owner to permission a malicious/faulty target in the merkle tree (or call it directly). The target's delegatecall zeroes the Vault's nonce storage slot; any address then calls init() to become owner, gaining control of Vault funds.
**Insight:** When a contract guards one storage slot (owner) around a delegatecall, enumerate every other slot that gates privileged state transitions (init nonce, merkleRoot, methods) and check whether resetting them re-opens a privileged function.
