# Vaults can be bricked by `selfdestruct()`ing implementations, using forged immutable args

Forged immutable args in clone-with-immutable-args let attacker fake factory/recipient and delegatecall a selfdestructing adaptor, bricking all escrows.

- Payout: Contest reward
- Severity: high
- Program: Rio Vesting Escrow
- Credited: 0xLogos
- Disclosed: 2024-01-05
- Write-up quality: 8/10
- Original: https://github.com/sherlock-audit/2024-01-rio-vesting-escrow-judging/issues/60
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-01-rio-vesting-escrow%3AH-1
- Tags: domain:web3 impact:dos kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:access-control vuln:misconfiguration

**Target:** VestingEscrow clone implementation (Solidity)
**Root cause:** Clone-with-immutable-args stores args as calldata, so calling the implementation directly lets an attacker forge factory()/recipient()/votingAdaptor() values; the forged adaptor is delegatecall()ed and selfdestructs the implementation.
**Steps:**
1. Craft calldata for `vote(bytes)` with forged immutable args: factory=attacker, recipient=attacker, votingAdaptor=attacker (Bomb contract)
2. Call the VestingEscrow implementation directly with that calldata
3. Implementation's `_votingAdaptor()` returns attacker contract; `functionDelegateCall` delegatecalls it
4. Attacker's `vote()` runs in implementation context and calls `selfdestruct(payable(0))`
5. Implementation is destroyed; all clones/escrows become non-functional, blocking withdrawals
**How found:** Recognized the clone-with-immutable-args pattern is unsafe when an immutable arg controls a delegatecall target, analogous to the Astaria beacon proxy issue; traced factory()/votingAdaptor() to delegatecall sites and realized args are forgeable calldata.
**Exploitation:** Attacker forges immutable args in direct calldata to the implementation, bypassing onlyRecipient by setting recipient to self, fakes factory to return a malicious votingAdaptor, and triggers delegatecall to a selfdestruct bomb, destroying the shared implementation and bricking every escrow.
**Escalation:** Single implementation shared by all factory clones means one selfdestruct bricks all escrows and freezes token withdrawals.
**Insight:** When auditing clone-with-immutable-args (SSTORE2/Solady), check whether any `_getArgAddress()` result feeds a `delegatecall`/`call`; since args are calldata, calling the implementation directly forges them—test by invoking implementation functions with hand-crafted calldata.
