# It shouldn’t be possible to create a vault with Cally’ own token

Cally allows creating a vault using Cally's own address as token, locking ETH premiums forever since withdraw always reverts.

- Payout: Contest reward
- Severity: medium
- Program: Cally
- Credited: p4st13r4
- Disclosed: 2022-07-01
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-05-cally-findings/issues/224
- Library page: https://bugbountylibrary.com/r/c4%3A2022-05-cally%3AM-02
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:chained technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Cally.sol createVault ERC-721 vault creation
**Root cause:** createVault() does not reject token == address(this); since the vault NFT is minted during the call, a user can reference the freshly minted vault id as tokenIdOrAmount, making Cally the vault owner/beneficiary.
**Steps:**
1. Call `createVault` with `token = address(Cally)` and `tokenIdOrAmount = <future vault id>`
2. Vault is created with Cally contract as owner/beneficiary
3. Users call `buyOption` depositing ETH premiums into the vault
4. User calls `exercise` receiving the vault NFT as underlying
5. Call `initiateWithdraw` — reverts because vault id is burned then transferred back (Cally.sol L335/L344)
6. ETH premiums remain locked in Cally contract forever
**How found:** Code review of createVault() noting the vault NFT is minted during the call, so tokenIdOrAmount can reference an id not yet owned at call time; no check against token == address(this).
**Exploitation:** Attacker creates a vault whose underlying is Cally's own vault NFT; buyers deposit premiums via buyOption; exercise transfers the vault NFT but withdraw always reverts, permanently locking all ETH in the Cally contract.
**Escalation:** Judge cited GimelSec's chained attack: vault a 100 ETH NFT with 1 ETH strike, buy the option, re-vault the vault NFT at 89 ETH strike, victim buys and exercises paying 89 ETH, attacker exercises original option paying 1 ETH to reclaim NFT and keeps 89 ETH.
**Insight:** When a contract mints an NFT during the same call that accepts an arbitrary token address, check whether the freshly minted id can be passed as the underlying — self-referential vaults break burn/withdraw invariants.
